183 lines
3.1 KiB
Go
183 lines
3.1 KiB
Go
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) {
|
|
// 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())
|
|
}
|