diff --git a/pkg/index/indextest/tests.go b/pkg/index/indextest/tests.go index 7a8ae8d64..1b87011c6 100644 --- a/pkg/index/indextest/tests.go +++ b/pkg/index/indextest/tests.go @@ -404,6 +404,8 @@ func Index(t *testing.T, initIdx func() *index.Index) { {"genre", "(20)Alternative"}, {"year", "1992"}, {"track", "1"}, + {"disc", "2"}, + {"mediaref", "sha1-fefac74a1d5928316d7131747107c8a61b71ffe4"}, } for _, tt := range mediaTests { key = fmt.Sprintf("mediatag|%s|%s", mediaWholeRef.String(), tt.prop) diff --git a/pkg/index/receive.go b/pkg/index/receive.go index 3326845eb..493da2048 100644 --- a/pkg/index/receive.go +++ b/pkg/index/receive.go @@ -42,7 +42,7 @@ import ( "camlistore.org/third_party/github.com/camlistore/goexif/exif" "camlistore.org/third_party/github.com/camlistore/goexif/tiff" - "camlistore.org/third_party/taglib" + "camlistore.org/third_party/github.com/hjfreyer/taglib-go/taglib" ) func (ix *Index) reindex(br blob.Ref) error { @@ -313,12 +313,7 @@ func (ix *Index) populateFile(b *schema.Blob, mm *mutationMap) (err error) { mm.Set(keyFileTimes.Key(blobRef), keyFileTimes.Val(time3339s)) if strings.HasPrefix(mime, "audio/") { - tag, err := taglib.Decode(fr, fr.Size()) - if err == nil { - indexMusic(tag, wholeRef, mm) - } else { - log.Print("index: error parsing tag: ", err) - } + indexMusic(io.NewSectionReader(fr, 0, fr.Size()), wholeRef, mm) } return nil @@ -434,28 +429,62 @@ func tagDegrees(tag *tiff.Tag) float64 { return ratFloat(tag.Rat2(0)) + ratFloat(tag.Rat2(1))/60 + ratFloat(tag.Rat2(2))/3600 } -// indexMusic adds mutations to index the wholeRef by most of the -// fields in gotaglib.GenericTag. -func indexMusic(tag taglib.GenericTag, wholeRef blob.Ref, mm *mutationMap) { - const justYearLayout = "2006" +// indexMusic adds mutations to index the wholeRef by attached metadata and other properties. +func indexMusic(sr *io.SectionReader, wholeRef blob.Ref, mm *mutationMap) { + tag, err := taglib.Decode(sr, sr.Size()) + if err != nil { + log.Print("index: error parsing tag: ", err) + return + } - var yearStr, trackStr string + // Determine if an ID3v1 tag is present at the end of the file. + const v1Length = 128 + const v1Magic = "TAG" + buf := make([]byte, len(v1Magic), len(v1Magic)) + if _, err := sr.ReadAt(buf, sr.Size()-v1Length); err != nil { + log.Printf("index: error reading ID3v1 tag: ", err) + return + } + var footerLength int64 = 0 + if string(buf) == v1Magic { + footerLength = v1Length + } + + // Generate a hash of the audio portion of the file (i.e. excluding ID3v1 and v2 tags). + if _, err := sr.Seek(int64(tag.TagSize()), 0); err != nil { + log.Printf("index: error seeking past ID3v2 tag: ", err) + return + } + hash := sha1.New() + if _, err := io.CopyN(hash, sr, sr.Size()-int64(tag.TagSize())-footerLength); err != nil { + log.Printf("index: error generating SHA1 from audio data: ", err) + return + } + mediaRef := blob.RefFromHash(hash) + + var yearStr, trackStr, discStr string if !tag.Year().IsZero() { + const justYearLayout = "2006" yearStr = tag.Year().Format(justYearLayout) } if tag.Track() != 0 { trackStr = fmt.Sprintf("%d", tag.Track()) } + if tag.Disc() != 0 { + discStr = fmt.Sprintf("%d", tag.Disc()) + } // Note: if you add to this map, please update // pkg/search/query.go's MediaTagConstraint Tag docs. tags := map[string]string{ - "title": tag.Title(), - "artist": tag.Artist(), - "album": tag.Album(), - "genre": tag.Genre(), - "year": yearStr, - "track": trackStr, + "title": tag.Title(), + "artist": tag.Artist(), + "album": tag.Album(), + "genre": tag.Genre(), + "year": yearStr, + "track": trackStr, + "disc": discStr, + "mediaref": mediaRef.String(), } for tag, value := range tags { diff --git a/pkg/search/query.go b/pkg/search/query.go index 4489d3262..d69481e54 100644 --- a/pkg/search/query.go +++ b/pkg/search/query.go @@ -336,7 +336,7 @@ type FileConstraint struct { type MediaTagConstraint struct { // Tag is the tag to match. - // For ID3, this includes: title, artist, album, genre, year, track. + // For ID3, this includes: title, artist, album, genre, year, track, disc, mediaref. Tag string `json:"tag"` String *StringConstraint `json:"string,omitempty"` diff --git a/third_party/taglib/.gitignore b/third_party/github.com/hjfreyer/taglib-go/taglib/.gitignore similarity index 100% rename from third_party/taglib/.gitignore rename to third_party/github.com/hjfreyer/taglib-go/taglib/.gitignore diff --git a/third_party/taglib/LICENSE b/third_party/github.com/hjfreyer/taglib-go/taglib/LICENSE similarity index 100% rename from third_party/taglib/LICENSE rename to third_party/github.com/hjfreyer/taglib-go/taglib/LICENSE diff --git a/third_party/taglib/README.md b/third_party/github.com/hjfreyer/taglib-go/taglib/README.md similarity index 100% rename from third_party/taglib/README.md rename to third_party/github.com/hjfreyer/taglib-go/taglib/README.md diff --git a/third_party/taglib/id3/id3v23.go b/third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v23.go similarity index 100% rename from third_party/taglib/id3/id3v23.go rename to third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v23.go diff --git a/third_party/taglib/id3/id3v23frames.go b/third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v23frames.go similarity index 100% rename from third_party/taglib/id3/id3v23frames.go rename to third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v23frames.go diff --git a/third_party/taglib/id3/id3v24.go b/third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v24.go similarity index 100% rename from third_party/taglib/id3/id3v24.go rename to third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v24.go diff --git a/third_party/taglib/id3/id3v24_test.go b/third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v24_test.go similarity index 100% rename from third_party/taglib/id3/id3v24_test.go rename to third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v24_test.go diff --git a/third_party/taglib/id3/id3v24frames.go b/third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v24frames.go similarity index 100% rename from third_party/taglib/id3/id3v24frames.go rename to third_party/github.com/hjfreyer/taglib-go/taglib/id3/id3v24frames.go diff --git a/third_party/taglib/id3/util.go b/third_party/github.com/hjfreyer/taglib-go/taglib/id3/util.go similarity index 100% rename from third_party/taglib/id3/util.go rename to third_party/github.com/hjfreyer/taglib-go/taglib/id3/util.go diff --git a/third_party/taglib/taglib.go b/third_party/github.com/hjfreyer/taglib-go/taglib/taglib.go similarity index 96% rename from third_party/taglib/taglib.go rename to third_party/github.com/hjfreyer/taglib-go/taglib/taglib.go index d0d61cfcb..d02aed873 100644 --- a/third_party/taglib/taglib.go +++ b/third_party/github.com/hjfreyer/taglib-go/taglib/taglib.go @@ -22,7 +22,7 @@ import ( "io" "time" - "camlistore.org/third_party/taglib/id3" + "camlistore.org/third_party/github.com/hjfreyer/taglib-go/taglib/id3" ) var ( diff --git a/third_party/taglib/taglib_test.go b/third_party/github.com/hjfreyer/taglib-go/taglib/taglib_test.go similarity index 100% rename from third_party/taglib/taglib_test.go rename to third_party/github.com/hjfreyer/taglib-go/taglib/taglib_test.go diff --git a/third_party/taglib/testdata/test24.mp3 b/third_party/github.com/hjfreyer/taglib-go/taglib/testdata/test24.mp3 similarity index 100% rename from third_party/taglib/testdata/test24.mp3 rename to third_party/github.com/hjfreyer/taglib-go/taglib/testdata/test24.mp3