diff --git a/audioc.go b/audioc.go index 295b6a1..8de324d 100644 --- a/audioc.go +++ b/audioc.go @@ -5,7 +5,6 @@ import ( "fmt" "runtime" "strings" - "path/filepath" "github.com/jamlib/libaudio/ffmpeg" "github.com/jamlib/libaudio/ffprobe" @@ -13,14 +12,12 @@ import ( ) type Config struct { - DirEntry string - Flags flags + Dir, Artist, Album, Bitrate string + Collection, Fix, Force, Write bool } type audioc struct { - DirEntry string - Flags flags - + Config *Config Ffmpeg ffmpeg.Ffmpeger Ffprobe ffprobe.Ffprober Image string @@ -29,36 +26,31 @@ type audioc struct { Workdir string } -type flags struct { - Artist, Album, Bitrate string - Collection, Fix, Force, Version, Write bool -} - func New(c *Config, ffm ffmpeg.Ffmpeger, ffp ffprobe.Ffprober) *audioc { - return &audioc{ DirEntry: filepath.Clean(c.DirEntry), Flags: c.Flags, - Ffmpeg: ffm, Ffprobe: ffp, Workers: runtime.NumCPU() } + return &audioc{ Config: c, Ffmpeg: ffm, Ffprobe: ffp, + Workers: runtime.NumCPU() } } func (a *audioc) Process() error { - if !a.Flags.Write { + if !a.Config.Write { fmt.Printf("\n* To write changes to disk, please provide flag: --write\n") } // ensure path is is valid directory - fi, err := os.Stat(a.DirEntry) + fi, err := os.Stat(a.Config.Dir) if err != nil || !fi.IsDir() { - return fmt.Errorf("Invalid directory: %s", a.DirEntry) + return fmt.Errorf("Invalid directory: %s", a.Config.Dir) } // obtain audio file list - a.Files = fsutil.FilesAudio(a.DirEntry) + a.Files = fsutil.FilesAudio(a.Config.Dir) - // if --artist mode, move innermost dir from a.DirEntry and add to each - // file path within a.Files since this folder could be the album name. + // if --artist mode, move innermost dir from a.Config.Dir and add to + // each file path within a.Files since this folder could be the album name. // if it is only the artist name, then will mimic --collection - if a.Flags.Artist != "" { - bpa := strings.Split(a.DirEntry, fsutil.PathSep) - a.DirEntry = strings.Join(bpa[:len(bpa)-1], fsutil.PathSep) + if a.Config.Artist != "" { + bpa := strings.Split(a.Config.Dir, fsutil.PathSep) + a.Config.Dir = strings.Join(bpa[:len(bpa)-1], fsutil.PathSep) for i := range a.Files { a.Files[i] = bpa[len(bpa)-1] + fsutil.PathSep + a.Files[i] @@ -67,7 +59,7 @@ func (a *audioc) Process() error { // group files by parent directory; call a.processBundle // a.processBundle found within bundle.go - err = fsutil.BundleFiles(a.DirEntry, a.Files, a.processBundle) + err = fsutil.BundleFiles(a.Config.Dir, a.Files, a.processBundle) if err != nil { return err } diff --git a/audioc_test.go b/audioc_test.go index 19e9f4a..5e38e42 100644 --- a/audioc_test.go +++ b/audioc_test.go @@ -25,7 +25,7 @@ func TestSkipFolderOnCollection(t *testing.T) { } for i := range tests { - a := &audioc{ Flags: flags{ Collection: tests[i].col } } + a := &audioc{ Config: &Config{ Collection: tests[i].col } } r := a.skipFolder(tests[i].path) if r != tests[i].skip { @@ -45,7 +45,7 @@ func TestSkipFolderOnArtist(t *testing.T) { } for i := range tests { - a := &audioc{ Flags: flags{ Artist: tests[i].artist } } + a := &audioc{ Config: &Config{ Artist: tests[i].artist } } r := a.skipFolder(tests[i].path) if r != tests[i].skip { @@ -66,7 +66,7 @@ func TestSkipFolderOnAlbum(t *testing.T) { } for i := range tests { - a := &audioc{ Flags: flags{ Artist: "Whoever", Album: tests[i].album } } + a := &audioc{ Config: &Config{ Artist: "Whoever", Album: tests[i].album } } r := a.skipFolder(tests[i].path) if r != tests[i].skip { @@ -76,7 +76,7 @@ func TestSkipFolderOnAlbum(t *testing.T) { } func TestProcessDirDNE(t *testing.T) { - a := &audioc{ DirEntry: "audioc-dir-def-dne" } + a := &audioc{ Config: &Config{ Dir: "audioc-dir-def-dne" } } err := a.Process() if err == nil { t.Errorf("Expected error, got none.") @@ -96,8 +96,8 @@ func createTestProcessFiles(t *testing.T, entryDir string, t.Errorf("Expected entryDir") } - a := &audioc{ Ffmpeg: &ffmpeg.MockFfmpeg{}, Ffprobe: &ffprobe.MockFfprobe{}, - Files: []string{}, Workers: 1 } + a := &audioc{ Config: &Config{}, Ffmpeg: &ffmpeg.MockFfmpeg{}, + Ffprobe: &ffprobe.MockFfprobe{}, Files: []string{}, Workers: 1 } indexes := []int{} createFiles := []*fsutil.TestFile{} @@ -113,8 +113,8 @@ func createTestProcessFiles(t *testing.T, entryDir string, createFiles = append(createFiles, &fsutil.TestFile{nestedPath, string(b)}) } - a.DirEntry, _ = fsutil.CreateTestFiles(t, createFiles) - a.DirEntry += fsutil.PathSep + entryDir + a.Config.Dir, _ = fsutil.CreateTestFiles(t, createFiles) + a.Config.Dir += fsutil.PathSep + entryDir return a, indexes } @@ -132,11 +132,11 @@ func TestProcessMain(t *testing.T) { }, }, }) - defer os.RemoveAll(filepath.Dir(a.DirEntry)) + defer os.RemoveAll(filepath.Dir(a.Config.Dir)) - a.Flags.Artist = "Phish" - a.Flags.Write = true - a.Flags.Force = true + a.Config.Artist = "Phish" + a.Config.Write = true + a.Config.Force = true err := a.Process() @@ -151,7 +151,7 @@ func TestProcessMain(t *testing.T) { "Phish/2003/2003.07.17 Bonner Springs, KS/01-01 Chalk Dust Torture.mp3", } - files := fsutil.FilesAudio(a.DirEntry) + files := fsutil.FilesAudio(a.Config.Dir) if len(files) == 0 { t.Errorf("No resulting files found.") } diff --git a/bundle.go b/bundle.go index 21a1625..e1ec17c 100644 --- a/bundle.go +++ b/bundle.go @@ -18,16 +18,16 @@ import ( // process each bundle or folder of audio files func (a *audioc) processBundle(indexes []int) error { var err error - fullDir := filepath.Dir(filepath.Join(a.DirEntry, a.Files[indexes[0]])) + fullDir := filepath.Dir(filepath.Join(a.Config.Dir, a.Files[indexes[0]])) // skip folder if possible (unless --force) - if !a.Flags.Force && a.skipFolder(a.Files[indexes[0]]) { + if !a.Config.Force && a.skipFolder(a.Files[indexes[0]]) { return nil } fmt.Printf("\nProcessing: %v ...\n", fullDir) - if a.Flags.Write { + if a.Config.Write { // create new random workdir within current path a.Workdir, err = ioutil.TempDir(fullDir, "") if err != nil { @@ -48,13 +48,13 @@ func (a *audioc) processBundle(indexes []int) error { return err } - if a.Flags.Write { + if a.Config.Write { // explicitly remove workdir (before folder is possibly renamed) os.RemoveAll(a.Workdir) // TODO: iterate through mdSlice moving each file individually instead of // assuming all belong to same resulting directory - fullResultD := filepath.Dir(filepath.Join(a.DirEntry, mdSlice[0].Resultpath)) + fullResultD := filepath.Dir(filepath.Join(a.Config.Dir, mdSlice[0].Resultpath)) // if not same dir, rename directory to target dir if fullDir != fullResultD { @@ -87,7 +87,7 @@ func (a *audioc) skipFolder(path string) bool { // determine which folder in path is the album name var alb string - if a.Flags.Collection { + if a.Config.Collection { // true if --collection & artist path contains " - " if strings.Index(pa[0], " - ") != -1 { return true @@ -105,9 +105,9 @@ func (a *audioc) skipFolder(path string) bool { // true if album folder matches metadata.ToAlbum if len(alb) > 0 { - if a.Flags.Album != "" { + if a.Config.Album != "" { // if --album matches album folder - if a.Flags.Album == alb { + if a.Config.Album == alb { return true } } else { @@ -126,12 +126,12 @@ func (a *audioc) skipFolder(path string) bool { func (a *audioc) processArtwork(file string) error { art := &albumart.AlbumArt{ Ffmpeg: a.Ffmpeg, Ffprobe: a.Ffprobe, ImgDecode: image.DecodeConfig, WithParentDir: true, - Fullpath: filepath.Join(a.DirEntry, file) } + Fullpath: filepath.Join(a.Config.Dir, file) } var err error a.Image = "" - if a.Flags.Write { + if a.Config.Write { a.Image, err = albumart.Process(art) } diff --git a/cmd/flag.go b/cmd/flag.go index 33cec03..9a2a319 100644 --- a/cmd/flag.go +++ b/cmd/flag.go @@ -61,18 +61,19 @@ func configFromFlags() (*audioc.Config, bool) { flags := flag.NewFlagSet(os.Args[0], flag.ExitOnError) // set mode - flags.StringVar(&c.Flags.Album, "album", "", "") - flags.StringVar(&c.Flags.Artist, "artist", "", "") - flags.BoolVar(&c.Flags.Collection, "collection", false, "") + flags.StringVar(&c.Album, "album", "", "") + flags.StringVar(&c.Artist, "artist", "", "") + flags.BoolVar(&c.Collection, "collection", false, "") // set options - flags.StringVar(&c.Flags.Bitrate, "bitrate", "V0", "") - flags.BoolVar(&c.Flags.Fix, "fix", false, "") - flags.BoolVar(&c.Flags.Force, "force", false, "") - flags.BoolVar(&c.Flags.Write, "write", false, "") + flags.StringVar(&c.Bitrate, "bitrate", "V0", "") + flags.BoolVar(&c.Fix, "fix", false, "") + flags.BoolVar(&c.Force, "force", false, "") + flags.BoolVar(&c.Write, "write", false, "") // set debug options - flags.BoolVar(&c.Flags.Version, "version", false, "") + var printVersion bool + flags.BoolVar(&printVersion, "version", false, "") // create --help closure flags.Usage = func() { @@ -85,7 +86,7 @@ func configFromFlags() (*audioc.Config, bool) { a := flags.Args() // --version - if c.Flags.Version { + if printVersion { fmt.Printf("%s\n", version) return &c, false } @@ -97,17 +98,17 @@ func configFromFlags() (*audioc.Config, bool) { } // must specify proper MODE - if !c.Flags.Collection && c.Flags.Artist == "" { + if !c.Collection && c.Artist == "" { fmt.Printf("\nError: Must provide a valid MODE\n") flags.Usage() return &c, false } // default to V0 unless 320 specified - if c.Flags.Bitrate != "320" { - c.Flags.Bitrate = "V0" + if c.Bitrate != "320" { + c.Bitrate = "V0" } - c.DirEntry = filepath.Clean(a[0]) + c.Dir = filepath.Clean(a[0]) return &c, true } diff --git a/cmd/flag_test.go b/cmd/flag_test.go index c0ba402..d93f401 100644 --- a/cmd/flag_test.go +++ b/cmd/flag_test.go @@ -36,8 +36,8 @@ func TestProcessFlagsArtist(t *testing.T) { if cont == false { t.Errorf("Expected %v, got %v", true, cont) } - if c.Flags.Artist != os.Args[2] { - t.Errorf("Expected %v, got %v", os.Args[2], c.Flags.Artist) + if c.Artist != os.Args[2] { + t.Errorf("Expected %v, got %v", os.Args[2], c.Artist) } } diff --git a/file.go b/file.go index 4ba0450..1391130 100644 --- a/file.go +++ b/file.go @@ -16,30 +16,30 @@ func (a *audioc) processFile(index int) (*metadata.Metadata, error) { i := &metadata.Info{} // if --artist mode, artist is set from flag - if a.Flags.Artist != "" { - i.Artist = a.Flags.Artist + if a.Config.Artist != "" { + i.Artist = a.Config.Artist } // if --collection mode, artist set from parent folder name - if a.Flags.Collection { + if a.Config.Collection { i.Artist = strings.Split(a.Files[index], fsutil.PathSep)[0] } // if --album mode, album is set from flag - if a.Flags.Album != "" { - i.Album = i.MatchCleanAlbum(a.Flags.Album) + if a.Config.Album != "" { + i.Album = i.MatchCleanAlbum(a.Config.Album) } m := metadata.New(a.Files[index], i) // call Probe after setting m.Info.Artist - err := m.Probe(a.Ffprobe, filepath.Join(a.DirEntry, a.Files[index])) + err := m.Probe(a.Ffprobe, filepath.Join(a.Config.Dir, a.Files[index])) if err != nil { return m, err } // skip if sources match (unless --force) - if m.Match && !a.Flags.Force { + if m.Match && !a.Config.Force { m.Resultpath = a.Files[index] return m, nil } @@ -48,7 +48,7 @@ func (a *audioc) processFile(index int) (*metadata.Metadata, error) { fpa := strings.Split(a.Files[index], fsutil.PathSep) // if --collection or artist/year folder in expected place - if a.Flags.Collection || + if a.Config.Collection || (len(fpa) > 2 && fpa[0] == m.Info.Artist && fpa[1] == m.Info.Year) { m.Resultpath = filepath.Join(m.Info.Artist, m.Info.Year) @@ -69,7 +69,7 @@ func (a *audioc) processFile(index int) (*metadata.Metadata, error) { // append album name as directory m.Resultpath = filepath.Join(m.Resultpath, m.Info.ToAlbum(), m.Info.ToFile()) - fp := filepath.Join(a.DirEntry, a.Files[index]) + fp := filepath.Join(a.Config.Dir, a.Files[index]) // print changes to be made p := fmt.Sprintf("\n%v\n", fp) @@ -82,7 +82,7 @@ func (a *audioc) processFile(index int) (*metadata.Metadata, error) { if ext != ".flac" || !skipConvert(a.Files[index]) { // convert to mp3 m.Resultpath += ".mp3" - p += fmt.Sprintf(" * convert to MP3 (%s)\n", a.Flags.Bitrate) + p += fmt.Sprintf(" * convert to MP3 (%s)\n", a.Config.Bitrate) _, err := a.processMp3(fp, m.Info) if err != nil { @@ -96,7 +96,7 @@ func (a *audioc) processFile(index int) (*metadata.Metadata, error) { // compare processed to current path if a.Files[index] != m.Resultpath { - p += fmt.Sprintf(" * rename to: %v\n", filepath.Join(a.DirEntry, m.Resultpath)) + p += fmt.Sprintf(" * rename to: %v\n", filepath.Join(a.Config.Dir, m.Resultpath)) } // print to console all at once @@ -116,12 +116,12 @@ func skipConvert(file string) bool { func (a *audioc) processMp3(f string, i *metadata.Info) (string, error) { // skip if not writing - if !a.Flags.Write { + if !a.Config.Write { return "", nil } // if already mp3, copy stream; do not convert - quality := a.Flags.Bitrate + quality := a.Config.Bitrate if strings.ToLower(filepath.Ext(f)) == ".mp3" { quality = "copy" } @@ -136,7 +136,7 @@ func (a *audioc) processMp3(f string, i *metadata.Info) (string, error) { newFile := filepath.Join(a.Workdir, i.ToFile() + ".mp3") // process or convert to mp3 - c := &ffmpeg.Mp3Config{ f, quality, newFile, ffmeta, a.Flags.Fix } + c := &ffmpeg.Mp3Config{ f, quality, newFile, ffmeta, a.Config.Fix } _, err := a.Ffmpeg.ToMp3(c) if err != nil { return newFile, err