Files
yellowjacket/backend/queue/navigation.go
T

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
}