-
Notifications
You must be signed in to change notification settings - Fork 0
/
songlist.go
161 lines (138 loc) · 3.34 KB
/
songlist.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* This file controls the "playlist" that songs are played from.
It keeps track of upcoming songs as well as history of songs that have been played.
It provides functions for going to the next or previous song, as well as
toggling Shuffle and Repeat functionality.
*/
package main
import (
"os"
"path/filepath"
"math/rand"
"time"
"github.com/dhowden/tag"
)
// Song: keeps track of file and metadata for every song
type Song struct {
FilePath string
Title string
Artist string
Album string
}
// Stacks for upcoming songs and previously played songs
type stack struct {
data []*Song
}
func (s *stack) push(elem *Song) {
s.data = append(s.data, elem)
}
func (s *stack) pop() *Song {
if(len(s.data) == 0) {
return nil
}
n := len(s.data) - 1
elem := s.data[n]
s.data[n] = nil
s.data = s.data[:n]
return elem
}
func (s *stack) shuffle() {
rand.Seed(time.Now().UnixNano())
n := len(s.data)
for i:=n-1; i>0; i-- {
j := rand.Intn(i)
temp := s.data[j]
s.data[j] = s.data[i]
s.data[i] = temp
}
}
// keeping track of different things
var playlist []*Song = nil
//var songplaylist []song = make([]song, 0)
var nextUp *stack = &stack{data:make([]*Song, 0)}
var history *stack = &stack{data:make([]*Song, 0)}
var currentSong *Song = nil
var shuffle bool = false // not yet implemented
var repeat bool = true
/* Initializes everything from an initial array of songs (file paths)
This sets the `playlist` variable which lets us know which songs
we have to work with and will not change unless InitializePlaylist is called again.
It also initializes nextUp with all of the songs.
*/
func InitializePlaylist(initialPlaylist []string) {
playlist = make([]*Song, len(initialPlaylist))
for i:=len(initialPlaylist)-1; i >= 0; i-- {
f, err := os.Open(initialPlaylist[i])
if err != nil {
continue
}
m, err := tag.ReadFrom(f)
var title string
var artist string
var album string
if err != nil {
title = filepath.Base(initialPlaylist[i])
artist = "No Data"
album = "No Data"
} else {
title = m.Title()
if title == "" {
title = filepath.Base(initialPlaylist[i])
}
artist = m.Artist()
if artist == "" {
artist = "No Data"
}
album = m.Album()
if album == "" {
album = "No Data"
}
}
var song *Song = &Song{
FilePath: initialPlaylist[i],
Title: title,
Artist: artist,
Album: album,
}
playlist[i] = song
f.Close()
}
populateNextUp()
}
func populateNextUp() {
// Going through array backwards because we are pushing onto a stack
for i := len(playlist) - 1; i >= 0; i-- {
nextUp.push(playlist[i])
}
if shuffle {
nextUp.shuffle()
}
}
func ToggleRepeat() bool {
repeat = !repeat
return repeat
}
func ToggleShuffle() bool {
shuffle = !shuffle
nextUp.shuffle()
return shuffle
}
func GetNextSong() *Song {
if(currentSong != nil) {
history.push(currentSong)
}
currentSong = nextUp.pop()
if(currentSong == nil && repeat) {
// We ran out of songs and need to repeat the playlist
populateNextUp()
currentSong = nextUp.pop()
}
return currentSong
}
func GetPrevSong() *Song {
if(currentSong == nil) {
return nil
}
nextUp.push(currentSong)
currentSong = history.pop()
return currentSong
}