aboutsummaryrefslogtreecommitdiff
path: root/downloader/download_manager.go
blob: 004efc1f696fd6271166770f9b802682eeeec34e (plain) (blame)
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
package downloader

import (
	"time"
)

// DownloadManager handles a download for a particular song.
type DownloadManager struct {
	Url string

	Start    time.Duration
	Duration time.Duration
	End      time.Duration

	pb chan (<-chan []byte)

	info videoInfo
}

const clipTime = 10 * time.Second
const preloadCount = 5

func NewDownload(url string, startTime, dur time.Duration) (*DownloadManager, error) {
	vInfo, err := info(url)
	if err != nil {
		return nil, err
	}

	if dur == 0 {
		dur = vInfo.Duration - startTime
	}

	dl := &DownloadManager{
		Url: url,

		Start:    startTime,
		Duration: dur,
		End:      startTime + dur,

		pb:   make(chan (<-chan []byte), preloadCount),
		info: *vInfo,
	}

	go dl.schedule()

	return dl, nil
}

func (d *DownloadManager) SendOn(ch chan<- []byte) <-chan struct{} {
	out := make(chan struct{}, 1)

	go func() {
		defer close(out)
		for c := range d.pb {
			for b := range c {
				ch <- b
			}
		}
	}()

	return out
}

func (d *DownloadManager) schedule() {
	go func() {
		defer close(d.pb)
		for i := 0; ; i++ {
			clipStart := time.Duration(i)*clipTime + d.Start
			clipEnd := time.Duration(i+1)*clipTime + d.Start

			if clipStart >= d.End {
				return
			}

			dur := clipTime
			if clipEnd > d.End {
				dur = d.End - clipStart
			}

			ch, err := d.download(clipStart, dur)
			if err != nil {
				log.Errorf("error setting up download: %q", err)
				return
			}

			d.pb <- ch
		}
	}()
}