diff --git a/internal/playlist/playlist.go b/internal/playlist/playlist.go index 2062d2a..5997952 100644 --- a/internal/playlist/playlist.go +++ b/internal/playlist/playlist.go @@ -1,17 +1,24 @@ package playlist import ( + "fmt" "segmento/internal/segment" "time" ) const DefaultPlaylistDuration = 20 * time.Second +type PlaylistListener interface { + OnUpdate(p *Playlist) +} + type Playlist interface { // These could be moved to an interface? Duration() time.Duration TargetDuration() time.Duration AddSegment(s *segment.Segment) error + Render() string + //AddListener(l PlaylistListener) } type MediaPlaylist struct { @@ -57,6 +64,19 @@ func (p *MediaPlaylist) durationOf(ss []*segment.Segment) time.Duration { return t } +func (p *MediaPlaylist) Render() string { + var r string + r += "#EXTM3U\n" + r += "#EXT-X-VERSION:3\n" + r += "#EXT-X-TARGETDURATION:3\n" // TODO + for _, s := range p.Segments { + r += fmt.Sprintf("#EXTINF:%.05f\n", float32(s.Duration())/float32(time.Second)) + r += "http://www.example.com/x.mp3\n" + } + r += "#EXT-X-ENDLIST" + return r +} + func (p *MediaPlaylist) Run() error { for { // TODO block here and listen to the channel of incoming segments. @@ -65,8 +85,3 @@ func (p *MediaPlaylist) Run() error { // What would actually be a useful API and/or Go best practices? } } - -type PlaylistListener interface { - SegmentAdded(s *segment.Segment) error - SegmentRemoved(s *segment.Segment) error -} diff --git a/internal/playlist/playlist_test.go b/internal/playlist/playlist_test.go index 06c62bc..fe5092e 100644 --- a/internal/playlist/playlist_test.go +++ b/internal/playlist/playlist_test.go @@ -3,6 +3,7 @@ package playlist_test import ( "segmento/internal/playlist" "segmento/internal/segment" + "strings" "testing" "time" @@ -17,9 +18,31 @@ func TestMediaPlaylist(t *testing.T) { playlist := playlist.NewMediaPlaylist() for i := 0; i < 8; i++ { - s := segment.NewSegment(10*time.Second, 0) + s := segment.NewSegment(3*time.Second, 0) s.IncrementDuration(3 * time.Second) playlist.AddSegment(s) } require.Equal(t, 21*time.Second, playlist.Duration()) } + +func TestMediaPlaylistRender(t *testing.T) { + playlist := playlist.NewMediaPlaylist() + + s := segment.NewSegment(3*time.Second, 0) + s.IncrementDuration(3 * time.Second) + playlist.AddSegment(s) + + s = segment.NewSegment(3*time.Second, 0) + s.IncrementDuration(2700 * time.Millisecond) + playlist.AddSegment(s) + + lines := strings.Split(playlist.Render(), "\n") + + require.Equal(t, "#EXTM3U", lines[0]) + require.Equal(t, "#EXT-X-VERSION:3", lines[1]) + require.Equal(t, "#EXT-X-TARGETDURATION:3", lines[2]) + require.Equal(t, "#EXTINF:3.00000", lines[3]) + require.Equal(t, "http://www.example.com/x.mp3", lines[4]) + require.Equal(t, "#EXTINF:2.70000", lines[5]) + require.Equal(t, "http://www.example.com/x.mp3", lines[6]) +}