From a464a14deb7c3c70bf465c713bf4bc9951ae27f7 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Jacquier <15922119+pierre-emmanuelJ@users.noreply.github.com> Date: Fri, 13 Dec 2019 09:59:12 +0100 Subject: [PATCH] Add marshall Function --- m3u.go | 40 +++++++++++++++++++++++++++++++--- m3u_test.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 92 insertions(+), 11 deletions(-) diff --git a/m3u.go b/m3u.go index 14ee9d1..e0eb5f0 100644 --- a/m3u.go +++ b/m3u.go @@ -2,7 +2,9 @@ package m3u import ( "bufio" + "bytes" "errors" + "fmt" "io" "net/http" "os" @@ -18,7 +20,7 @@ type Playlist struct { // A Tag is a simple key/value pair type Tag struct { - Name string + Name string Value string } @@ -40,7 +42,7 @@ func Parse(fileName string) (playlist Playlist, err error) { } else { f, err = os.Open(fileName) } - + if err != nil { err = errors.New("Unable to open playlist file") return @@ -50,7 +52,7 @@ 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") { @@ -92,3 +94,35 @@ func Parse(fileName string) (playlist Playlist, err error) { return playlist, nil } + +// Marshall Playlist to an m3u file. +func Marshall(p Playlist) (io.Reader, error) { + buf := new(bytes.Buffer) + w := bufio.NewWriter(buf) + if err := MarshallInto(p, w); err != nil { + return nil, err + } + + return buf, nil +} + +// MarshallInto a *bufio.Writer a Playlist. +func MarshallInto(p Playlist, into *bufio.Writer) error { + into.WriteString("#EXTM3U\n") + for _, track := range p.Tracks { + into.WriteString("#EXTINF:") + into.WriteString(fmt.Sprintf("%d ", track.Length)) + for i := range track.Tags { + if i == len(track.Tags)-1 { + into.WriteString(fmt.Sprintf("%s=%q", track.Tags[i].Name, track.Tags[i].Value)) + continue + } + into.WriteString(fmt.Sprintf("%s=%q ", track.Tags[i].Name, track.Tags[i].Value)) + } + into.WriteString(", ") + + into.WriteString(fmt.Sprintf("%s\n%s\n", track.Name, track.URI)) + } + + return into.Flush() +} diff --git a/m3u_test.go b/m3u_test.go index c581240..0487bfc 100644 --- a/m3u_test.go +++ b/m3u_test.go @@ -1,7 +1,10 @@ package m3u import ( + "bytes" "fmt" + "io/ioutil" + "os" "testing" ) @@ -25,13 +28,13 @@ func TestPlaylist(t *testing.T) { 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" { + 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" { + 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) - } + } } } @@ -55,13 +58,13 @@ func TestRemotePlaylist(t *testing.T) { 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" { + 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" { + 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) - } + } } } @@ -92,3 +95,47 @@ func TestPlaylistMissingInf(t *testing.T) { t.Fatalf("Expected parse error") } } + +func TestMarshallPlaylist(t *testing.T) { + playlist, err := Parse("testdata/playlist.m3u") + if err != nil { + t.Fatal(err) + } + + reader, err := Marshall(playlist) + if err != nil { + t.Fatal(err) + } + + b := reader.(*bytes.Buffer) + + ioutil.WriteFile("/tmp/test_m3u_marshalling.m3u", b.Bytes(), os.ModePerm) + + playlist, _ = Parse("/tmp/test_m3u_marshalling.m3u") + + if len(playlist.Tracks) != 5 { + t.Fatalf("Expected track count to be 5") + } + + for i := 0; i < 5; i++ { + if playlist.Tracks[i].Length != i+1 { + t.Fatalf("Expected track Length to be %d but was %d", i+1, playlist.Tracks[i].Length) + } + + if playlist.Tracks[i].Name != fmt.Sprintf("Track %d", i+1) { + t.Fatalf("Expected track name to be Track %d but was '%s'", i+1, playlist.Tracks[i].Name) + } + + 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) + } + } +}