133 lines
2.6 KiB
Go
133 lines
2.6 KiB
Go
package queue
|
|
|
|
import "math/rand/v2"
|
|
|
|
// nextIndex returns the next track index respecting shuffle and repeat modes.
|
|
// Returns -1 if there is no next track (queue exhausted).
|
|
func (q *Queue) nextIndex() int {
|
|
if len(q.tracks) == 0 {
|
|
return -1
|
|
}
|
|
|
|
if q.shuffleMode && len(q.shuffleOrder) > 0 {
|
|
return q.nextShuffledIndex()
|
|
}
|
|
|
|
next := q.currentIndex + 1
|
|
if next >= len(q.tracks) {
|
|
if q.repeatMode == RepeatAll {
|
|
return 0
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
return next
|
|
}
|
|
|
|
// previousIndex returns the previous track index respecting shuffle and repeat.
|
|
// Returns -1 if there is no previous track.
|
|
func (q *Queue) previousIndex() int {
|
|
if len(q.tracks) == 0 {
|
|
return -1
|
|
}
|
|
|
|
if q.shuffleMode && len(q.shuffleOrder) > 0 {
|
|
return q.previousShuffledIndex()
|
|
}
|
|
|
|
prev := q.currentIndex - 1
|
|
if prev < 0 {
|
|
if q.repeatMode == RepeatAll {
|
|
return len(q.tracks) - 1
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
return prev
|
|
}
|
|
|
|
// nextShuffledIndex finds the next index in the shuffle order.
|
|
func (q *Queue) nextShuffledIndex() int {
|
|
shufflePos := q.currentShufflePosition()
|
|
if shufflePos == -1 {
|
|
// Current track not found in shuffle order — shouldn't happen.
|
|
return -1
|
|
}
|
|
|
|
nextShufflePos := shufflePos + 1
|
|
if nextShufflePos >= len(q.shuffleOrder) {
|
|
if q.repeatMode == RepeatAll {
|
|
return q.shuffleOrder[0]
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
return q.shuffleOrder[nextShufflePos]
|
|
}
|
|
|
|
// previousShuffledIndex finds the previous index in the shuffle order.
|
|
func (q *Queue) previousShuffledIndex() int {
|
|
shufflePos := q.currentShufflePosition()
|
|
if shufflePos == -1 {
|
|
return -1
|
|
}
|
|
|
|
prevShufflePos := shufflePos - 1
|
|
if prevShufflePos < 0 {
|
|
if q.repeatMode == RepeatAll {
|
|
return q.shuffleOrder[len(q.shuffleOrder)-1]
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
return q.shuffleOrder[prevShufflePos]
|
|
}
|
|
|
|
// currentShufflePosition finds where the current track index is in the shuffle order.
|
|
func (q *Queue) currentShufflePosition() int {
|
|
for i, idx := range q.shuffleOrder {
|
|
if idx == q.currentIndex {
|
|
return i
|
|
}
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
// generateShuffleOrder creates a Fisher-Yates shuffled index order,
|
|
// placing the current track at position 0 so it doesn't replay immediately.
|
|
func (q *Queue) generateShuffleOrder() {
|
|
n := len(q.tracks)
|
|
if n == 0 {
|
|
q.shuffleOrder = nil
|
|
|
|
return
|
|
}
|
|
|
|
order := make([]int, n)
|
|
for i := range order {
|
|
order[i] = i
|
|
}
|
|
|
|
// Fisher-Yates shuffle.
|
|
for i := n - 1; i > 0; i-- {
|
|
j := rand.IntN(i + 1)
|
|
order[i], order[j] = order[j], order[i]
|
|
}
|
|
|
|
// Move the current track to position 0 so it doesn't replay immediately.
|
|
for i, idx := range order {
|
|
if idx == q.currentIndex {
|
|
order[0], order[i] = order[i], order[0]
|
|
|
|
break
|
|
}
|
|
}
|
|
|
|
q.shuffleOrder = order
|
|
}
|