This repository has been archived on 2019-06-23. You can view files and clone it, but cannot push or open issues or pull requests.
mumbledj/songqueue.go

146 lines
3.7 KiB
Go
Raw Permalink Normal View History

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
*/
package main
2014-12-15 06:37:55 +01:00
import (
"errors"
"fmt"
2015-10-06 20:26:09 +02:00
"math/rand"
2015-12-15 02:07:12 +01:00
"time"
)
2015-10-06 20:26:09 +02:00
func init() {
2015-12-15 02:07:12 +01:00
rand.Seed(time.Now().UTC().UnixNano())
2015-10-06 20:26:09 +02:00
}
// SongQueue type declaration.
type SongQueue struct {
queue []Song
}
2014-12-15 06:37:55 +01:00
2015-05-10 07:00:24 +02:00
// NewSongQueue initializes a new queue and returns it.
func NewSongQueue() *SongQueue {
return &SongQueue{
queue: make([]Song, 0),
}
}
2015-05-10 07:00:24 +02:00
// AddSong adds a Song to the SongQueue.
func (q *SongQueue) AddSong(s Song) error {
beforeLen := q.Len()
q.queue = append(q.queue, s)
if len(q.queue) == beforeLen+1 {
return nil
}
2015-05-10 07:00:24 +02:00
return errors.New("Could not add Song to the SongQueue.")
}
2015-12-15 02:07:12 +01:00
// InsertSong inserts a Song to the SongQueue at a location.
func (q *SongQueue) InsertSong(s Song, i int) error {
beforeLen := q.Len()
q.queue = append(q.queue[:i], append([]Song{s}, q.queue[i:]...)...)
if len(q.queue) == beforeLen+1 {
return nil
}
return errors.New("Could not insert Song to the SongQueue.")
}
2015-05-10 07:00:24 +02:00
// CurrentSong returns the current Song.
func (q *SongQueue) CurrentSong() Song {
return q.queue[0]
}
2015-05-10 07:00:24 +02:00
// NextSong moves to the next Song in SongQueue. NextSong() removes the first Song in the queue.
func (q *SongQueue) NextSong() {
if !isNil(q.CurrentSong().Playlist()) {
if s, err := q.PeekNext(); err == nil {
if !isNil(s.Playlist()) {
if q.CurrentSong().Playlist().ID() != s.Playlist().ID() {
q.CurrentSong().Playlist().DeleteSkippers()
}
}
} else {
2015-04-16 08:44:35 +02:00
q.CurrentSong().Playlist().DeleteSkippers()
}
}
q.queue = q.queue[1:]
}
2015-05-10 07:00:24 +02:00
// PeekNext peeks at the next Song and returns it.
func (q *SongQueue) PeekNext() (Song, error) {
if q.Len() > 1 {
2015-12-15 02:07:12 +01:00
if dj.conf.General.AutomaticShuffleOn { //Shuffle mode is active
2015-10-09 21:49:56 +02:00
q.RandomNextSong(false)
}
return q.queue[1], nil
2015-01-13 01:02:20 +01:00
}
2015-05-10 07:00:24 +02:00
return nil, errors.New("There isn't a Song coming up next.")
2015-01-13 01:02:20 +01:00
}
2015-05-10 07:00:24 +02:00
// Len returns the length of the SongQueue.
func (q *SongQueue) Len() int {
return len(q.queue)
}
2015-05-10 07:00:24 +02:00
// Traverse is a traversal function for SongQueue. Allows a visit function to be passed in which performs
// the specified action on each queue item.
func (q *SongQueue) Traverse(visit func(i int, s Song)) {
for sQueue, queueSong := range q.queue {
visit(sQueue, queueSong)
}
}
// OnSongFinished event. Deletes Song that just finished playing, then queues the next Song (if exists).
func (q *SongQueue) OnSongFinished() {
resetOffset, _ := time.ParseDuration(fmt.Sprintf("%ds", 0))
dj.audioStream.Offset = resetOffset
2015-01-06 04:16:59 +01:00
if q.Len() != 0 {
2015-04-16 08:44:35 +02:00
if dj.queue.CurrentSong().DontSkip() == true {
dj.queue.CurrentSong().SetDontSkip(false)
q.PrepareAndPlayNextSong()
2015-01-06 04:16:59 +01:00
} else {
q.NextSong()
if q.Len() != 0 {
q.PrepareAndPlayNextSong()
}
}
}
}
2015-05-10 07:00:24 +02:00
// PrepareAndPlayNextSong prepares next song and plays it if the download succeeds.
// Otherwise the function will print an error message to the channel and skip to the next song.
func (q *SongQueue) PrepareAndPlayNextSong() {
if err := q.CurrentSong().Download(); err == nil {
q.CurrentSong().Play()
} else {
dj.client.Self.Channel.Send(fmt.Sprintf(AUDIO_FAIL_MSG, q.CurrentSong().Title()), false)
q.OnSongFinished()
}
}
2015-10-06 20:26:09 +02:00
// Shuffles the songqueue using inside-out algorithm
func (q *SongQueue) ShuffleSongs() {
2015-12-15 02:07:12 +01:00
for i := range q.queue[1:] { //Don't touch currently playing song
j := rand.Intn(i + 1)
q.queue[i+1], q.queue[j+1] = q.queue[j+1], q.queue[i+1]
2015-10-06 20:26:09 +02:00
}
}
2015-10-09 00:15:34 +02:00
// Sets a random song as next song to be played
2015-10-09 21:49:56 +02:00
// queueWasEmpty wether the queue was empty before adding the last song
2015-12-15 02:07:12 +01:00
func (q *SongQueue) RandomNextSong(queueWasEmpty bool) {
if q.Len() > 1 {
nextSongIndex := 1
2015-12-15 02:07:12 +01:00
if queueWasEmpty {
nextSongIndex = 0
}
2015-12-15 02:07:12 +01:00
swapIndex := nextSongIndex + rand.Intn(q.Len()-1)
q.queue[nextSongIndex], q.queue[swapIndex] = q.queue[swapIndex], q.queue[nextSongIndex]
2015-10-09 00:15:34 +02:00
}
}