I use the following index func (please ignore the naive error handling for now):
import (
"fmt"
"os"
"path"
"path/filepath"
"io"
"bufio"
"crypto/sha1"
"encoding/hex"
"sort"
"flag"
"gob"
"
github.com/ascherkus/go-id3/src"
"http"
)
func indexMusicLib(dir string) (res MusicLib) {
res.Root = dir
res.Hash = make(map[string]*MP3File)
res.Tracks = make(map[string][]*MP3File)
res.Albums = make(map[string][]string)
walkFn := func(path string, info *os.FileInfo, err os.Error) os.Error {
var (
fullpath string
f *os.File
)
if err != nil {
debug("walkFn path %v, err %v\n", path, err)
return err
}
// continue to walk all directories
if info.IsDirectory() {
return nil
}
fullpath, err = filepath.Abs(path)
if err != nil {
panic(err.String())
}
f, err = os.Open(fullpath)
if err != nil {
panic(err.String())
}
defer f.Close()
mp3 := id3.Read(f)
if mp3 == nil {
// ignore non-mp3 files
return nil
}
//debug("id3.File = %#v\n", mp3)
_, err = f.Seek(0, 0)
if err != nil {
panic(err.String())
}
reader := bufio.NewReader(f)
sha1 := sha1.New()
_, err = io.Copy(sha1, reader)
if err != nil {
panic(err.String())
}
res.Files = append(res.Files, MP3File{FileName: f.Name(), SHA1Hash:hex.EncodeToString(sha1.Sum()), ID3Info: *mp3})
n := &res.Files[len(res.Files)-1]
debug("n = %#v\n", n)
res.Hash[n.SHA1Hash] = n
res.Tracks[n.ID3Info.Album] = append(res.Tracks[n.ID3Info.Album], n)
if !containsString(res.Albums[n.ID3Info.Artist], n.ID3Info.Album) {
res.Albums[n.ID3Info.Artist] = append(res.Albums[n.ID3Info.Artist], n.ID3Info.Album)
}
if !containsString(res.Artists, n.ID3Info.Artist) {
res.Artists = append(res.Artists, n.ID3Info.Artist)
}
return nil
}
err := filepath.Walk(dir, walkFn)
if err != nil {
debug("walk err %v\n", err)
}
sort.Strings(res.Artists)
for _, v := range res.Albums {
sort.Strings(v)
}
return
}