Skip to content

Commit

Permalink
Include support to parse tags
Browse files Browse the repository at this point in the history
* Ignore tags to calculate length

* Parse tags

* Added trim to strings and removing double quotes in some values

* Added test case to read tag name and tag value
  • Loading branch information
soukron authored and jamesnetherton committed Mar 26, 2018
1 parent 78acbcb commit 8fa048d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 10 deletions.
25 changes: 20 additions & 5 deletions m3u.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"errors"
"os"
"regexp"
"strconv"
"strings"
)
Expand All @@ -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
Expand All @@ -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") {
Expand All @@ -48,20 +57,26 @@ 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
} else if len(playlist.Tracks) == 0 {
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, " ")
}
}

Expand Down
8 changes: 8 additions & 0 deletions m3u_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}

Expand Down
10 changes: 5 additions & 5 deletions testdata/playlist.m3u
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 8fa048d

Please sign in to comment.