Skip to content

Commit

Permalink
Use wchar_t for TagLib filenames on Windows (navidrome#1310)
Browse files Browse the repository at this point in the history
* Use wchar_t for tagLib filenames on Windows

* Make TagLib default extractor for all platforms.

* Organize imports

Co-authored-by: Deluan <[email protected]>
  • Loading branch information
caiocotts and deluan authored Aug 28, 2021
1 parent c55e659 commit 54f9849
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 18 deletions.
2 changes: 1 addition & 1 deletion conf/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ func init() {
viper.SetDefault("reverseproxyuserheader", "Remote-User")
viper.SetDefault("reverseproxywhitelist", "")

viper.SetDefault("scanner.extractor", DefaultScannerExtractor)
viper.SetDefault("scanner.extractor", consts.DefaultScannerExtractor)
viper.SetDefault("scanner.genreseparators", ";/,")

viper.SetDefault("agents", "lastfm,spotify")
Expand Down
5 changes: 0 additions & 5 deletions conf/defaults.go

This file was deleted.

5 changes: 0 additions & 5 deletions conf/defaults_win.go

This file was deleted.

2 changes: 2 additions & 0 deletions consts/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const (
PlaceholderAvatar = "logo-192x192.png"

DefaultHttpClientTimeOut = 10 * time.Second

DefaultScannerExtractor = "taglib"
)

// Cache options
Expand Down
11 changes: 5 additions & 6 deletions scanner/metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import (
"strings"
"time"

"github.com/navidrome/navidrome/scanner/metadata/ffmpeg"

"github.com/navidrome/navidrome/scanner/metadata/taglib"

"github.com/google/uuid"
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/consts"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/scanner/metadata/ffmpeg"
"github.com/navidrome/navidrome/scanner/metadata/taglib"
)

type Parser interface {
Expand All @@ -32,8 +31,8 @@ func Extract(files ...string) (map[string]Tags, error) {
p, ok := parsers[conf.Server.Scanner.Extractor]
if !ok {
log.Warn("Invalid 'Scanner.Extractor' option. Using default", "requested", conf.Server.Scanner.Extractor,
"validOptions", "ffmpeg,taglib", "default", conf.DefaultScannerExtractor)
p = parsers[conf.DefaultScannerExtractor]
"validOptions", "ffmpeg,taglib", "default", consts.DefaultScannerExtractor)
p = parsers[consts.DefaultScannerExtractor]
}

extractedTags, err := p.Parse(files...)
Expand Down
9 changes: 9 additions & 0 deletions scanner/metadata/taglib/get_filename.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build !windows

package taglib

import "C"

func getFilename(s string) *C.char {
return C.CString(s)
}
96 changes: 96 additions & 0 deletions scanner/metadata/taglib/get_filename_win.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// +build windows

package taglib

// From https://github.com/orofarne/gowchar

/*
#include <wchar.h>
const size_t SIZEOF_WCHAR_T = sizeof(wchar_t);
void gowchar_set (wchar_t *arr, int pos, wchar_t val)
{
arr[pos] = val;
}
wchar_t gowchar_get (wchar_t *arr, int pos)
{
return arr[pos];
}
*/
import "C"

import (
"fmt"
"unicode/utf16"
"unicode/utf8"
)

var SIZEOF_WCHAR_T C.size_t = C.size_t(C.SIZEOF_WCHAR_T)

func getFilename(s string) *C.wchar_t {
wstr, _ := StringToWcharT(s)
return wstr
}

func StringToWcharT(s string) (*C.wchar_t, C.size_t) {
switch SIZEOF_WCHAR_T {
case 2:
return stringToWchar2(s) // Windows
case 4:
return stringToWchar4(s) // Unix
default:
panic(fmt.Sprintf("Invalid sizeof(wchar_t) = %v", SIZEOF_WCHAR_T))
}
panic("?!!")
}

// Windows
func stringToWchar2(s string) (*C.wchar_t, C.size_t) {
var slen int
s1 := s
for len(s1) > 0 {
r, size := utf8.DecodeRuneInString(s1)
if er, _ := utf16.EncodeRune(r); er == '\uFFFD' {
slen += 1
} else {
slen += 2
}
s1 = s1[size:]
}
slen++ // \0
res := C.malloc(C.size_t(slen) * SIZEOF_WCHAR_T)
var i int
for len(s) > 0 {
r, size := utf8.DecodeRuneInString(s)
if r1, r2 := utf16.EncodeRune(r); r1 != '\uFFFD' {
C.gowchar_set((*C.wchar_t)(res), C.int(i), C.wchar_t(r1))
i++
C.gowchar_set((*C.wchar_t)(res), C.int(i), C.wchar_t(r2))
i++
} else {
C.gowchar_set((*C.wchar_t)(res), C.int(i), C.wchar_t(r))
i++
}
s = s[size:]
}
C.gowchar_set((*C.wchar_t)(res), C.int(slen-1), C.wchar_t(0)) // \0
return (*C.wchar_t)(res), C.size_t(slen)
}

// Unix
func stringToWchar4(s string) (*C.wchar_t, C.size_t) {
slen := utf8.RuneCountInString(s)
slen++ // \0
res := C.malloc(C.size_t(slen) * SIZEOF_WCHAR_T)
var i int
for len(s) > 0 {
r, size := utf8.DecodeRuneInString(s)
C.gowchar_set((*C.wchar_t)(res), C.int(i), C.wchar_t(r))
s = s[size:]
i++
}
C.gowchar_set((*C.wchar_t)(res), C.int(slen-1), C.wchar_t(0)) // \0
return (*C.wchar_t)(res), C.size_t(slen)
}
4 changes: 4 additions & 0 deletions scanner/metadata/taglib/taglib_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

char has_cover(const TagLib::FileRef f);

#ifdef WIN32
int taglib_read(const wchar_t *filename, unsigned long id) {
#else
int taglib_read(const char *filename, unsigned long id) {
#endif
TagLib::FileRef f(filename, true, TagLib::AudioProperties::Fast);

if (f.isNull()) {
Expand Down
2 changes: 1 addition & 1 deletion scanner/metadata/taglib/taglib_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
)

func Read(filename string) (map[string][]string, error) {
fp := C.CString(filename)
fp := getFilename(filename)
defer C.free(unsafe.Pointer(fp))
id, m := newMap()
defer deleteMap(id)
Expand Down
4 changes: 4 additions & 0 deletions scanner/metadata/taglib/taglib_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ extern "C" {
extern void go_map_put_str(unsigned long id, char *key, char *val);
extern void go_map_put_int(unsigned long id, char *key, int val);

#ifdef WIN32
int taglib_read(const wchar_t *filename, unsigned long id);
#else
int taglib_read(const char *filename, unsigned long id);
#endif

#ifdef __cplusplus
}
Expand Down

0 comments on commit 54f9849

Please sign in to comment.