package main import ( "container/list" "log" "time" "github.com/faiface/beep" "github.com/kataras/go-events" "dndmusicbot/ffmpeg" discordspeaker "dndmusicbot/speaker" ) type Ambiance struct { Type string URL string } func init() { app.ambiance = beep.Mixer{} discordspeaker.Play(&app.ambiance) app.queue = new(Queue) app.queue.list = list.New() app.queue.Events = app.events discordspeaker.Play(app.queue) log.Println("queue.go done.") } type Song struct { Title string Channel string VideoID string Length time.Duration PCM *ffmpeg.PCM Playlist Playlist DLuri string } func (s *Song) NewStream() (err error) { s.PCM, err = ffmpeg.NewPCM(s.DLuri, sampleRate, channels) return } type Queue struct { Events events.EventEmmiter playing bool yt VideoInfo list *list.List current *list.Element } func (q Queue) IsPlaying() bool { return q.playing } func (q *Queue) Play() { q.playing = true if q.list.Len() > 0 { play := q.list.Front() q.current = play app.events.Emit("song_start") } } func (q *Queue) Add(s *Song) { el := q.list.PushBack(s) if el == q.list.Front() { q.Play() } } func (q Queue) QLen() int { return q.list.Len() } func (q Queue) Current() *Song { if q.current == nil { return new(Song) } return q.current.Value.(*Song) } func (q *Queue) Reset() { q.playing = false q.current = nil q.list = q.list.Init() } func (q *Queue) Next() { if q.current == nil { return } next := q.current.Next() if next == nil { next = q.list.Front() } pcm := next.Value.(*Song).PCM if pcm != nil && pcm.Position() != 0 { err := next.Value.(*Song).NewStream() log.Println(err) } q.current = next return } func (q *Queue) Prev() { if q.current == nil { return } prev := q.current.Prev() if prev == nil { prev = q.list.Back() } err := prev.Value.(*Song).NewStream() if err != nil { log.Println(err) } q.current = prev return } func (q *Queue) Preload() { } func (q *Queue) Stream(samples [][2]float64) (n int, ok bool) { if q.current != nil && !q.current.Value.(*Song).PCM.Player.Started { q.current.Value.(*Song).PCM.Player.Start() } // We use the filled variable to track how many samples we've // successfully filled already. We loop until all samples are filled. filled := 0 for filled < len(samples) { // There are no streamers in the queue, so we stream silence. if q.current == nil || q.list.Len() == 0 { for i := range samples[filled:] { samples[i][0] = 0 samples[i][1] = 0 } break } // We stream from the first streamer in the queue. n, ok := q.current.Value.(*Song).PCM.Stream(samples[filled:]) // If it's drained, we pop it from the queue, thus continuing with // the next streamer. if !ok { q.Next() q.Events.Emit("song_over", nil) } // We update the number of filled samples. filled += n } return len(samples), true } func (q *Queue) Err() error { return nil } func (q *Queue) Position() int { if q.current == nil || q.current.Value.(*Song).PCM == nil { return 0 } return q.current.Value.(*Song).PCM.Position() } func (q Queue) Len() int { if q.current == nil { return 0 } return int(q.current.Value.(*Song).Length.Milliseconds()) }