diff --git a/m3u.go b/m3u.go index 9faff09..9aac8c0 100644 --- a/m3u.go +++ b/m3u.go @@ -4,6 +4,7 @@ import ( "bufio" "errors" "os" + "regexp" "strconv" "strings" ) @@ -13,11 +14,18 @@ type Playlist struct { Tracks []Track } -// Track represents an m3u track +// A Tag is a simple key/value pair +type Tag struct { + Name string + Value string +} + +// Track represents an m3u track with a Name, Lengh, URI and a set of tags type Track struct { Name string Length int URI string + Tags []Tag } // Parse parses an m3u playlist with the given file name and returns a Playlist @@ -31,7 +39,8 @@ func Parse(fileName string) (playlist Playlist, err error) { onFirstLine := true scanner := bufio.NewScanner(f) - + tagsRegExp, _ := regexp.Compile("([a-zA-Z0-9-]+?)=\"([^\"]+)\"") + for scanner.Scan() { line := scanner.Text() if onFirstLine && !strings.HasPrefix(line, "#EXTM3U") { @@ -48,12 +57,18 @@ func Parse(fileName string) (playlist Playlist, err error) { err = errors.New("Invalid m3u file format. Expected EXTINF metadata to contain track length and name data") return } - length, parseErr := strconv.Atoi(trackInfo[0]) + length, parseErr := strconv.Atoi(strings.Split(trackInfo[0], " ")[0]) if parseErr != nil { err = errors.New("Unable to parse length") return } - track := &Track{trackInfo[1], length, ""} + track := &Track{strings.Trim(trackInfo[1], " "), length, "", nil} + tagList := tagsRegExp.FindAllString(line, -1) + for i := range tagList { + tagInfo := strings.Split(tagList[i], "=") + tag := &Tag{tagInfo[0], strings.Replace(tagInfo[1], "\"", "", -1)} + track.Tags = append(track.Tags, *tag) + } playlist.Tracks = append(playlist.Tracks, *track) } else if strings.HasPrefix(line, "#") || line == "" { continue @@ -61,7 +76,7 @@ func Parse(fileName string) (playlist Playlist, err error) { err = errors.New("URI provided for playlist with no tracks") return } else { - playlist.Tracks[len(playlist.Tracks)-1].URI = line + playlist.Tracks[len(playlist.Tracks)-1].URI = strings.Trim(line, " ") } } diff --git a/m3u_test.go b/m3u_test.go index 66057d3..36d8ef8 100644 --- a/m3u_test.go +++ b/m3u_test.go @@ -24,6 +24,14 @@ func TestPlaylist(t *testing.T) { if playlist.Tracks[i].URI != fmt.Sprintf("Track%d.mp4", i+1) { t.Fatalf("Expected track URI to be Track%d.mp4 but was '%s'", i+1, playlist.Tracks[i].URI) } + + if playlist.Tracks[i].Tags[0].Name != "group-title" { + t.Fatalf("Expected tag to be group-title but was '%s'", playlist.Tracks[i].Tags[0].Name) + } + + if playlist.Tracks[i].Tags[0].Value != "Album1" { + t.Fatalf("Expected group-title tag value to be Album1 but was '%s'", playlist.Tracks[i].Tags[0].Value) + } } } diff --git a/testdata/playlist.m3u b/testdata/playlist.m3u index 936c18c..7323f41 100644 --- a/testdata/playlist.m3u +++ b/testdata/playlist.m3u @@ -1,11 +1,11 @@ #EXTM3U -#EXTINF:1,Track 1 +#EXTINF:1 group-title="Album1", Track 1 Track1.mp4 -#EXTINF:2,Track 2 +#EXTINF:2 group-title="Album1", Track 2 Track2.mp4 -#EXTINF:3,Track 3 +#EXTINF:3 group-title="Album1", Track 3 Track3.mp4 -#EXTINF:4,Track 4 +#EXTINF:4 group-title="Album1", Track 4 Track4.mp4 -#EXTINF:5,Track 5 +#EXTINF:5 group-title="Album1", Track 5 Track5.mp4