refactor: allow multi-part extensions (#102)

This commit is contained in:
鲁树人 2024-10-21 03:57:56 +09:00
parent b9e2a38f82
commit 19bc6c466e
2 changed files with 48 additions and 30 deletions

View File

@ -18,25 +18,32 @@ type DecoderParams struct {
} }
type NewDecoderFunc func(p *DecoderParams) Decoder type NewDecoderFunc func(p *DecoderParams) Decoder
type decoderItem struct { type DecoderFactory struct {
noop bool noop bool
decoder NewDecoderFunc Suffix string
Create NewDecoderFunc
} }
var DecoderRegistry = make(map[string][]decoderItem) var DecoderRegistry []DecoderFactory
func RegisterDecoder(ext string, noop bool, dispatchFunc NewDecoderFunc) { func RegisterDecoder(ext string, noop bool, dispatchFunc NewDecoderFunc) {
DecoderRegistry[ext] = append(DecoderRegistry[ext], DecoderRegistry = append(DecoderRegistry,
decoderItem{noop: noop, decoder: dispatchFunc}) DecoderFactory{noop: noop, Create: dispatchFunc, Suffix: "." + strings.TrimPrefix(ext, ".")})
} }
func GetDecoder(filename string, skipNoop bool) (rs []NewDecoderFunc) { func GetDecoder(filename string, skipNoop bool) []DecoderFactory {
ext := strings.ToLower(strings.TrimLeft(filepath.Ext(filename), ".")) var result []DecoderFactory
for _, dec := range DecoderRegistry[ext] { // Some extensions contains multiple dots, e.g. ".kgm.flac", hence iterate
// all decoders for each extension.
name := strings.ToLower(filepath.Base(filename))
for _, dec := range DecoderRegistry {
if !strings.HasSuffix(name, dec.Suffix) {
continue
}
if skipNoop && dec.noop { if skipNoop && dec.noop {
continue continue
} }
rs = append(rs, dec.decoder) result = append(result, dec)
} }
return return result
} }

View File

@ -75,12 +75,21 @@ func main() {
func printSupportedExtensions() { func printSupportedExtensions() {
var exts []string var exts []string
for ext := range common.DecoderRegistry { extSet := make(map[string]int)
for _, factory := range common.DecoderRegistry {
ext := strings.TrimPrefix(factory.Suffix, ".")
if n, ok := extSet[ext]; ok {
extSet[ext] = n + 1
} else {
extSet[ext] = 1
}
}
for ext := range extSet {
exts = append(exts, ext) exts = append(exts, ext)
} }
sort.Strings(exts) sort.Strings(exts)
for _, ext := range exts { for _, ext := range exts {
fmt.Printf("%s: %d\n", ext, len(common.DecoderRegistry[ext])) fmt.Printf("%s: %d\n", ext, extSet[ext])
} }
} }
@ -276,7 +285,19 @@ func (p *processor) processFile(filePath string) error {
return nil return nil
} }
func (p *processor) process(inputFile string, allDec []common.NewDecoderFunc) error { func (p *processor) findDecoder(decoders []common.DecoderFactory, params *common.DecoderParams) (*common.Decoder, *common.DecoderFactory, error) {
for _, factory := range decoders {
dec := factory.Create(params)
err := dec.Validate()
if err == nil {
return &dec, &factory, nil
}
logger.Warn("try decode failed", zap.Error(err))
}
return nil, nil, errors.New("no any decoder can resolve the file")
}
func (p *processor) process(inputFile string, allDec []common.DecoderFactory) error {
file, err := os.Open(inputFile) file, err := os.Open(inputFile)
if err != nil { if err != nil {
return err return err
@ -284,26 +305,16 @@ func (p *processor) process(inputFile string, allDec []common.NewDecoderFunc) er
defer file.Close() defer file.Close()
logger := logger.With(zap.String("source", inputFile)) logger := logger.With(zap.String("source", inputFile))
decParams := &common.DecoderParams{ pDec, decoderFactory, err := p.findDecoder(allDec, &common.DecoderParams{
Reader: file, Reader: file,
Extension: filepath.Ext(inputFile), Extension: filepath.Ext(inputFile),
FilePath: inputFile, FilePath: inputFile,
Logger: logger, Logger: logger,
})
if err != nil {
return err
} }
dec := *pDec
var dec common.Decoder
for _, decFunc := range allDec {
dec = decFunc(decParams)
if err := dec.Validate(); err == nil {
break
} else {
logger.Warn("try decode failed", zap.Error(err))
dec = nil
}
}
if dec == nil {
return errors.New("no any decoder can resolve the file")
}
params := &ffmpeg.UpdateMetadataParams{} params := &ffmpeg.UpdateMetadataParams{}
@ -365,7 +376,7 @@ func (p *processor) process(inputFile string, allDec []common.NewDecoderFunc) er
return fmt.Errorf("get relative dir failed: %w", err) return fmt.Errorf("get relative dir failed: %w", err)
} }
inFilename := strings.TrimSuffix(filepath.Base(inputFile), filepath.Ext(inputFile)) inFilename := strings.TrimSuffix(filepath.Base(inputFile), decoderFactory.Suffix)
outPath := filepath.Join(p.outputDir, inputRelDir, inFilename+params.AudioExt) outPath := filepath.Join(p.outputDir, inputRelDir, inFilename+params.AudioExt)
if !p.overwriteOutput { if !p.overwriteOutput {