2014-12-15 06:37:55 +01:00
|
|
|
/*
|
|
|
|
* MumbleDJ
|
|
|
|
* By Matthieu Grieger
|
|
|
|
* songqueue.go
|
2015-01-18 23:44:40 +01:00
|
|
|
* Copyright (c) 2014, 2015 Matthieu Grieger (MIT License)
|
2014-12-15 06:37:55 +01:00
|
|
|
*/
|
|
|
|
|
2014-12-16 01:41:58 +01:00
|
|
|
package main
|
2014-12-15 06:37:55 +01:00
|
|
|
|
2014-12-27 09:25:49 +01:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
)
|
|
|
|
|
2015-01-03 20:31:29 +01:00
|
|
|
// QueueItem type declaration. QueueItem is an interface that groups together Song and Playlist
|
|
|
|
// types in a queue.
|
|
|
|
type QueueItem interface {
|
|
|
|
AddSkip(string) error
|
|
|
|
RemoveSkip(string) error
|
|
|
|
SkipReached(int) bool
|
|
|
|
ItemType() string
|
|
|
|
}
|
|
|
|
|
2014-12-27 19:05:13 +01:00
|
|
|
// SongQueue type declaration. Serves as a wrapper around the queue structure defined in queue.go.
|
2014-12-16 01:41:58 +01:00
|
|
|
type SongQueue struct {
|
2015-01-03 20:31:29 +01:00
|
|
|
queue []QueueItem
|
2014-12-16 01:41:58 +01:00
|
|
|
}
|
2014-12-15 06:37:55 +01:00
|
|
|
|
2014-12-27 19:05:13 +01:00
|
|
|
// Initializes a new queue and returns the new SongQueue.
|
2014-12-16 01:41:58 +01:00
|
|
|
func NewSongQueue() *SongQueue {
|
2014-12-19 01:28:27 +01:00
|
|
|
return &SongQueue{
|
2015-01-03 20:31:29 +01:00
|
|
|
queue: make([]QueueItem, 0),
|
2014-12-19 01:28:27 +01:00
|
|
|
}
|
2014-12-16 01:41:58 +01:00
|
|
|
}
|
|
|
|
|
2015-01-03 20:31:29 +01:00
|
|
|
// Adds an item to the SongQueue.
|
|
|
|
func (q *SongQueue) AddItem(i QueueItem) error {
|
|
|
|
beforeLen := q.Len()
|
|
|
|
q.queue = append(q.queue, i)
|
2014-12-31 23:36:53 +01:00
|
|
|
if len(q.queue) == beforeLen+1 {
|
2014-12-27 09:25:49 +01:00
|
|
|
return nil
|
2014-12-19 01:28:27 +01:00
|
|
|
} else {
|
2015-01-03 20:31:29 +01:00
|
|
|
return errors.New("Could not add QueueItem to the SongQueue.")
|
2014-12-19 01:28:27 +01:00
|
|
|
}
|
2014-12-16 01:41:58 +01:00
|
|
|
}
|
|
|
|
|
2015-01-03 20:31:29 +01:00
|
|
|
// Returns the current QueueItem.
|
|
|
|
func (q *SongQueue) CurrentItem() QueueItem {
|
|
|
|
return q.queue[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Moves to the next item in SongQueue. NextItem() removes the first value in the queue.
|
|
|
|
func (q *SongQueue) NextItem() {
|
|
|
|
q.queue = q.queue[1:]
|
2014-12-16 01:41:58 +01:00
|
|
|
}
|
|
|
|
|
2015-01-13 01:02:20 +01:00
|
|
|
// Peeks at the next item and returns the title, submitter, and error status.
|
|
|
|
func (q *SongQueue) PeekNext() (string, string, error) {
|
|
|
|
var title, submitter string
|
|
|
|
if q.Len() > 1 {
|
2015-01-13 01:21:53 +01:00
|
|
|
if q.queue[1].ItemType() == "playlist" {
|
2015-01-13 01:02:20 +01:00
|
|
|
title = q.queue[1].(*Playlist).songs.queue[0].(*Song).title
|
|
|
|
submitter = q.queue[1].(*Playlist).submitter
|
|
|
|
} else {
|
|
|
|
title = q.queue[1].(*Song).title
|
|
|
|
submitter = q.queue[1].(*Song).submitter
|
|
|
|
}
|
|
|
|
return title, submitter, nil
|
2015-01-13 01:21:53 +01:00
|
|
|
} else if q.Len() == 0 {
|
|
|
|
return "", "", errors.New("There is no item next in the queue.")
|
|
|
|
} else if q.CurrentItem().ItemType() == "playlist" {
|
2015-01-13 01:02:20 +01:00
|
|
|
title = q.CurrentItem().(*Playlist).songs.queue[1].(*Song).title
|
|
|
|
submitter = q.CurrentItem().(*Playlist).submitter
|
|
|
|
return title, submitter, nil
|
|
|
|
} else {
|
|
|
|
return "", "", errors.New("There is no item next in the queue.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-27 19:05:13 +01:00
|
|
|
// Returns the length of the SongQueue.
|
2014-12-27 09:25:49 +01:00
|
|
|
func (q *SongQueue) Len() int {
|
2014-12-31 23:36:53 +01:00
|
|
|
return len(q.queue)
|
2014-12-19 01:28:27 +01:00
|
|
|
}
|
2015-01-03 20:31:29 +01:00
|
|
|
|
2015-01-10 22:03:52 +01:00
|
|
|
// A traversal function for SongQueue. Allows a visit function to be passed in which performs
|
|
|
|
// the specified action on each queue item. Traverses all individual songs, and all songs
|
|
|
|
// within playlists.
|
|
|
|
func (q *SongQueue) Traverse(visit func(i int, item QueueItem)) {
|
|
|
|
for iQueue, queueItem := range q.queue {
|
|
|
|
if queueItem.ItemType() == "playlist" {
|
|
|
|
for iPlaylist, playlistItem := range q.queue[iQueue].(*Playlist).songs.queue {
|
|
|
|
visit(iPlaylist, playlistItem)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
visit(iQueue, queueItem)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-03 20:31:29 +01:00
|
|
|
// OnItemFinished event. Deletes item that just finished playing, then queues the next item.
|
|
|
|
func (q *SongQueue) OnItemFinished() {
|
2015-01-06 04:16:59 +01:00
|
|
|
if q.Len() != 0 {
|
|
|
|
if q.CurrentItem().ItemType() == "playlist" {
|
|
|
|
if err := q.CurrentItem().(*Playlist).songs.CurrentItem().(*Song).Delete(); err == nil {
|
|
|
|
if q.CurrentItem().(*Playlist).skipped == true {
|
|
|
|
if q.Len() > 1 {
|
|
|
|
q.NextItem()
|
|
|
|
q.PrepareAndPlayNextItem()
|
|
|
|
} else {
|
|
|
|
q.queue = q.queue[:0]
|
|
|
|
}
|
|
|
|
} else if q.CurrentItem().(*Playlist).songs.Len() > 1 {
|
|
|
|
q.CurrentItem().(*Playlist).songs.NextItem()
|
2015-01-03 20:31:29 +01:00
|
|
|
q.PrepareAndPlayNextItem()
|
|
|
|
} else {
|
2015-01-06 04:16:59 +01:00
|
|
|
if q.Len() > 1 {
|
|
|
|
q.NextItem()
|
|
|
|
q.PrepareAndPlayNextItem()
|
|
|
|
} else {
|
|
|
|
q.queue = q.queue[:0]
|
|
|
|
}
|
2015-01-03 20:31:29 +01:00
|
|
|
}
|
|
|
|
} else {
|
2015-01-06 04:16:59 +01:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err := q.CurrentItem().(*Song).Delete(); err == nil {
|
2015-01-03 20:31:29 +01:00
|
|
|
if q.Len() > 1 {
|
|
|
|
q.NextItem()
|
|
|
|
q.PrepareAndPlayNextItem()
|
2015-01-06 04:00:05 +01:00
|
|
|
} else {
|
|
|
|
q.queue = q.queue[:0]
|
2015-01-03 20:31:29 +01:00
|
|
|
}
|
2015-01-06 04:00:05 +01:00
|
|
|
} else {
|
2015-01-06 04:16:59 +01:00
|
|
|
panic(err)
|
2015-01-03 20:31:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *SongQueue) PrepareAndPlayNextItem() {
|
2015-01-06 04:16:59 +01:00
|
|
|
if q.Len() != 0 {
|
|
|
|
if q.CurrentItem().ItemType() == "playlist" {
|
|
|
|
if err := q.CurrentItem().(*Playlist).songs.CurrentItem().(*Song).Download(); err == nil {
|
|
|
|
q.CurrentItem().(*Playlist).songs.CurrentItem().(*Song).Play()
|
|
|
|
} else {
|
|
|
|
username := q.CurrentItem().(*Playlist).submitter
|
|
|
|
user := dj.client.Self().Channel().Users().Find(username)
|
|
|
|
user.Send(AUDIO_FAIL_MSG)
|
|
|
|
q.OnItemFinished()
|
|
|
|
}
|
2015-01-03 20:31:29 +01:00
|
|
|
} else {
|
2015-01-06 04:16:59 +01:00
|
|
|
if err := q.CurrentItem().(*Song).Download(); err == nil {
|
|
|
|
q.CurrentItem().(*Song).Play()
|
|
|
|
} else {
|
|
|
|
username := q.CurrentItem().(*Song).submitter
|
|
|
|
user := dj.client.Self().Channel().Users().Find(username)
|
|
|
|
user.Send(AUDIO_FAIL_MSG)
|
|
|
|
q.OnItemFinished()
|
|
|
|
}
|
2015-01-03 20:31:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|