1package dlna
2
3import (
4	"fmt"
5	"strings"
6	"time"
7)
8
9const (
10	TimeSeekRangeDomain   = "TimeSeekRange.dlna.org"
11	ContentFeaturesDomain = "contentFeatures.dlna.org"
12	TransferModeDomain    = "transferMode.dlna.org"
13)
14
15type ContentFeatures struct {
16	ProfileName     string
17	SupportTimeSeek bool
18	SupportRange    bool
19	// Play speeds, DLNA.ORG_PS would go here if supported.
20	Transcoded bool
21}
22
23func BinaryInt(b bool) uint {
24	if b {
25		return 1
26	} else {
27		return 0
28	}
29}
30
31// flags are in hex. trailing 24 zeroes, 26 are after the space
32// "DLNA.ORG_OP=" time-seek-range-supp bytes-range-header-supp
33func (cf ContentFeatures) String() (ret string) {
34	//DLNA.ORG_PN=[a-zA-Z0-9_]*
35	params := make([]string, 0, 2)
36	if cf.ProfileName != "" {
37		params = append(params, "DLNA.ORG_PN="+cf.ProfileName)
38	}
39	params = append(params, fmt.Sprintf(
40		"DLNA.ORG_OP=%b%b;DLNA.ORG_CI=%b",
41		BinaryInt(cf.SupportTimeSeek),
42		BinaryInt(cf.SupportRange),
43		BinaryInt(cf.Transcoded)))
44	return strings.Join(params, ";")
45}
46
47func ParseNPTTime(s string) (time.Duration, error) {
48	var h, m, sec, ms time.Duration
49	n, err := fmt.Sscanf(s, "%d:%2d:%2d.%3d", &h, &m, &sec, &ms)
50	if err != nil {
51		return -1, err
52	}
53	if n < 3 {
54		return -1, fmt.Errorf("invalid npt time: %s", s)
55	}
56	ret := time.Duration(h) * time.Hour
57	ret += time.Duration(m) * time.Minute
58	ret += sec * time.Second
59	ret += ms * time.Millisecond
60	return ret, nil
61}
62
63func FormatNPTTime(npt time.Duration) string {
64	npt /= time.Millisecond
65	ms := npt % 1000
66	npt /= 1000
67	s := npt % 60
68	npt /= 60
69	m := npt % 60
70	npt /= 60
71	h := npt
72	return fmt.Sprintf("%02d:%02d:%02d.%03d", h, m, s, ms)
73}
74
75type NPTRange struct {
76	Start, End time.Duration
77}
78
79func ParseNPTRange(s string) (ret NPTRange, err error) {
80	ss := strings.SplitN(s, "-", 2)
81	if ss[0] != "" {
82		ret.Start, err = ParseNPTTime(ss[0])
83		if err != nil {
84			return
85		}
86	}
87	if ss[1] != "" {
88		ret.End, err = ParseNPTTime(ss[1])
89		if err != nil {
90			return
91		}
92	}
93	return
94}
95
96func (me NPTRange) String() (ret string) {
97	ret = me.Start.String() + "-"
98	if me.End >= 0 {
99		ret += me.End.String()
100	}
101	return
102}
103