-
Notifications
You must be signed in to change notification settings - Fork 0
/
playlist.go
129 lines (113 loc) · 2.82 KB
/
playlist.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package m3u8
import (
"bytes"
"container/list"
"errors"
"fmt"
"io"
"strings"
)
// exported errors
var (
// ErrUnknownLine = errors.New("unknown line") // DEPRECATED
ErrMissingInf = errors.New("missing #EXTINF tag")
ErrInvalidSeg = errors.New("invalid Entry")
ErrMissingStream = errors.New("missing #EXT-X-STREAM-INF tag")
ErrInvalidPlaylist = errors.New("invalid playlist: neither master nor media playlist")
ErrNotMaster = errors.New("not master playlist")
ErrMissingAttr = errors.New("missing required attribute")
)
// Playlist is a m3u8 playlist.
type Playlist struct {
TargetDuration int // EXT-X-TARGETDURATION
SeqNo int // EXT-X-MEDIA-SEQUENCE
Version int // EXT-X-VERSION
Closed bool // EXT-X-ENDLIST
Directives string // all the un-parsed
// IOnly bool
// Indi bool
// Type string
// StartAttr string
// DisSeq int
// internal list
l *list.List
}
// New returns an empty m3u8 playlist.
func New() *Playlist {
p := new(Playlist)
p.l = list.New()
p.SeqNo = 0
p.Version = -1
return p
}
// Append adds an entry to the end of the playlist.
func (p *Playlist) Append(s Entry) {
e := p.l.PushBack(&s)
s.e = e
}
// Front returns the first entry of the playlist or
// nil if it's empty.
func (p *Playlist) Front() *Entry {
e := p.l.Front()
if e != nil {
return e.Value.(*Entry)
}
return nil
}
// Remove removes the Entry s.
func (p *Playlist) Remove(s *Entry) error {
if s.e != nil {
p.l.Remove(s.e)
return nil
}
return ErrInvalidSeg
}
// InsertAfter inserts the target Entry after Entry ref.
func (p *Playlist) InsertAfter(ref *Entry, target Entry) error {
if ref.e != nil {
e := p.l.InsertAfter(&target, ref.e)
target.e = e
return nil
}
return ErrInvalidSeg
}
// MarshalTo writes the string form of the Playlist to a Writer.
func (p *Playlist) MarshalTo(w io.Writer) {
writeLine(w, starter)
if p.Version > 0 {
writeLine(w, fmt.Sprintf(verTag+":%d", p.Version))
}
if p.TargetDuration > 0 {
writeLine(w, fmt.Sprintf(durTag+":%d", int(p.TargetDuration)))
}
if p.SeqNo >= 0 {
writeLine(w, fmt.Sprintf(seqTag+":%d", p.SeqNo))
}
if p.Directives != "" {
writeLine(w, strings.TrimSpace(p.Directives))
}
for s := p.Front(); s != nil; s = s.Next() {
s.marshalTo(w)
}
if p.Closed {
writeLine(w, ender)
}
}
// MarshalToWithErr writes the string form of the Playlist to a Writer
// and returns error occurred if any.
func (p *Playlist) MarshalToWithErr(iw io.Writer) error {
w := &writer{iw: iw}
p.MarshalTo(w)
return w.err
}
// Len returns #segment of a playlist.
func (p *Playlist) Len() int {
return p.l.Len()
}
// Marshal returns the string form of the Playlist.
func (p *Playlist) Marshal() string {
var b bytes.Buffer
// b.Write never returns error
p.MarshalTo(&b)
return b.String()
}