mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-14 19:20:37 +03:00
Use wchar_t for TagLib filenames on Windows (#1310)
* Use wchar_t for tagLib filenames on Windows * Make TagLib default extractor for all platforms. * Organize imports Co-authored-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
c55e65902b
commit
54f98497c2
@ -214,7 +214,7 @@ func init() {
|
|||||||
viper.SetDefault("reverseproxyuserheader", "Remote-User")
|
viper.SetDefault("reverseproxyuserheader", "Remote-User")
|
||||||
viper.SetDefault("reverseproxywhitelist", "")
|
viper.SetDefault("reverseproxywhitelist", "")
|
||||||
|
|
||||||
viper.SetDefault("scanner.extractor", DefaultScannerExtractor)
|
viper.SetDefault("scanner.extractor", consts.DefaultScannerExtractor)
|
||||||
viper.SetDefault("scanner.genreseparators", ";/,")
|
viper.SetDefault("scanner.genreseparators", ";/,")
|
||||||
|
|
||||||
viper.SetDefault("agents", "lastfm,spotify")
|
viper.SetDefault("agents", "lastfm,spotify")
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
package conf
|
|
||||||
|
|
||||||
const DefaultScannerExtractor = "taglib"
|
|
@ -1,5 +0,0 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
package conf
|
|
||||||
|
|
||||||
const DefaultScannerExtractor = "ffmpeg"
|
|
@ -47,6 +47,8 @@ const (
|
|||||||
PlaceholderAvatar = "logo-192x192.png"
|
PlaceholderAvatar = "logo-192x192.png"
|
||||||
|
|
||||||
DefaultHttpClientTimeOut = 10 * time.Second
|
DefaultHttpClientTimeOut = 10 * time.Second
|
||||||
|
|
||||||
|
DefaultScannerExtractor = "taglib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cache options
|
// Cache options
|
||||||
|
@ -10,13 +10,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/navidrome/navidrome/scanner/metadata/ffmpeg"
|
|
||||||
|
|
||||||
"github.com/navidrome/navidrome/scanner/metadata/taglib"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/navidrome/navidrome/conf"
|
"github.com/navidrome/navidrome/conf"
|
||||||
|
"github.com/navidrome/navidrome/consts"
|
||||||
"github.com/navidrome/navidrome/log"
|
"github.com/navidrome/navidrome/log"
|
||||||
|
"github.com/navidrome/navidrome/scanner/metadata/ffmpeg"
|
||||||
|
"github.com/navidrome/navidrome/scanner/metadata/taglib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Parser interface {
|
type Parser interface {
|
||||||
@ -32,8 +31,8 @@ func Extract(files ...string) (map[string]Tags, error) {
|
|||||||
p, ok := parsers[conf.Server.Scanner.Extractor]
|
p, ok := parsers[conf.Server.Scanner.Extractor]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Warn("Invalid 'Scanner.Extractor' option. Using default", "requested", conf.Server.Scanner.Extractor,
|
log.Warn("Invalid 'Scanner.Extractor' option. Using default", "requested", conf.Server.Scanner.Extractor,
|
||||||
"validOptions", "ffmpeg,taglib", "default", conf.DefaultScannerExtractor)
|
"validOptions", "ffmpeg,taglib", "default", consts.DefaultScannerExtractor)
|
||||||
p = parsers[conf.DefaultScannerExtractor]
|
p = parsers[consts.DefaultScannerExtractor]
|
||||||
}
|
}
|
||||||
|
|
||||||
extractedTags, err := p.Parse(files...)
|
extractedTags, err := p.Parse(files...)
|
||||||
|
9
scanner/metadata/taglib/get_filename.go
Normal file
9
scanner/metadata/taglib/get_filename.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package taglib
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func getFilename(s string) *C.char {
|
||||||
|
return C.CString(s)
|
||||||
|
}
|
96
scanner/metadata/taglib/get_filename_win.go
Normal file
96
scanner/metadata/taglib/get_filename_win.go
Normal file
@ -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)
|
||||||
|
}
|
@ -17,7 +17,11 @@
|
|||||||
|
|
||||||
char has_cover(const TagLib::FileRef f);
|
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) {
|
int taglib_read(const char *filename, unsigned long id) {
|
||||||
|
#endif
|
||||||
TagLib::FileRef f(filename, true, TagLib::AudioProperties::Fast);
|
TagLib::FileRef f(filename, true, TagLib::AudioProperties::Fast);
|
||||||
|
|
||||||
if (f.isNull()) {
|
if (f.isNull()) {
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Read(filename string) (map[string][]string, error) {
|
func Read(filename string) (map[string][]string, error) {
|
||||||
fp := C.CString(filename)
|
fp := getFilename(filename)
|
||||||
defer C.free(unsafe.Pointer(fp))
|
defer C.free(unsafe.Pointer(fp))
|
||||||
id, m := newMap()
|
id, m := newMap()
|
||||||
defer deleteMap(id)
|
defer deleteMap(id)
|
||||||
|
@ -8,7 +8,11 @@ extern "C" {
|
|||||||
extern void go_map_put_str(unsigned long id, char *key, char *val);
|
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);
|
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);
|
int taglib_read(const char *filename, unsigned long id);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user