|
@@ -3,89 +3,159 @@ import os
|
3
|
3
|
import aud
|
4
|
4
|
import random
|
5
|
5
|
import glob
|
|
6
|
+from DList import DoubleList
|
6
|
7
|
from collections import OrderedDict
|
7
|
8
|
from tinytag import TinyTag
|
8
|
9
|
|
9
|
10
|
""" This is the Music Player as a component """
|
10
|
11
|
class MusicPlayer(bge.types.KX_PythonComponent):
|
11
|
12
|
|
12
|
|
- args = OrderedDict([
|
13
|
|
- ("Now Playing", ''),
|
14
|
|
- ("Playlist", None),
|
15
|
|
- ("Last Song", ''),
|
16
|
|
- ("Directory", ''),
|
17
|
|
- ("Current Artist", ''),
|
18
|
|
- ("Current Track Title", ''),
|
19
|
|
- ("Track Path", ''),
|
20
|
|
- ("Is Playing", False),
|
21
|
|
- ("Audio Device", None),
|
22
|
|
- ("Audio Factory", None),
|
23
|
|
- ("Keyboard", None)
|
24
|
|
- ])
|
|
13
|
+ args = OrderedDict([])
|
25
|
14
|
|
26
|
15
|
def start(self, args):
|
27
|
|
- print('Music Player Class Entered')
|
28
|
|
- self.nowPlaying = args['Now Playing']
|
29
|
|
- self.lastSong = args['Last Song']
|
30
|
|
- self.directory = args['Directory']
|
31
|
|
- self.currArtist = args['Current Artist']
|
32
|
|
- self.currTrackTitle = args['Current Track Title']
|
33
|
|
- self.currTrackPath = args['Track Path']
|
34
|
|
- self.isPlaying = args['Is Playing']
|
35
|
|
- self.device = args['Audio Device']
|
36
|
|
- self.factory = args['Audio Factory']
|
37
|
|
- self.keyboard = args['Keyboard']
|
|
16
|
+ # dictionary
|
|
17
|
+ self.dictionary = bge.logic.globalDict
|
38
|
18
|
|
39
|
|
- print('Initilizing...')
|
40
|
|
- self.init()
|
41
|
|
-
|
42
|
|
- print('Printing tag')
|
43
|
|
- self.printTag()
|
44
|
|
-
|
45
|
|
- def init(self):
|
46
|
|
- # Init the playlist and directory
|
|
19
|
+ # get mp3 files from the disk and create a list
|
47
|
20
|
self.directory = bge.logic.expandPath('//Music')
|
48
|
|
- file_name = self.directory + "\\*.mp3"
|
49
|
|
- file_list = glob.glob(file_name)
|
50
|
|
- print('Directory: ' + self.directory)
|
51
|
|
- print(file_list)
|
52
|
|
- self.playlist = file_list
|
53
|
|
- self.nowPlaying = random.choice(self.playlist)
|
|
21
|
+ file_name = self.directory + '\\*.mp3'
|
|
22
|
+ file_list = glob.glob(file_name)
|
|
23
|
+
|
|
24
|
+ # use the mp3 list to make a playlist of nodes
|
|
25
|
+ self.playlist = DoubleList()
|
|
26
|
+ for name in file_list:
|
|
27
|
+ self.playlist.append(name)
|
54
|
28
|
|
55
|
|
- # Init the audio device
|
|
29
|
+ # previously played list of nodes
|
|
30
|
+ self.alreadyPlayed = DoubleList()
|
|
31
|
+
|
|
32
|
+ # get a random song from the playlist,
|
|
33
|
+ # remove it from the playlist
|
|
34
|
+ # add it to the alreadyPlayed list
|
|
35
|
+ # NOTICE: currentNode is a reference to a NODE in a list, if you want to play the song inside the node, use .data
|
|
36
|
+ self.currentNode = self.playlist.get(random.randint(0, self.playlist.getLength()))
|
|
37
|
+ self.nowPlaying = self.currentNode.getData()
|
|
38
|
+ self.playlist.remove(self.currentNode)
|
|
39
|
+ self.alreadyPlayed.append(self.nowPlaying)
|
|
40
|
+ print("Now Playing: " + self.nowPlaying)
|
|
41
|
+ self.setTag()
|
|
42
|
+ self.isPlaying = False
|
|
43
|
+
|
|
44
|
+ # create audio devices
|
56
|
45
|
self.device = aud.device()
|
57
|
46
|
self.factory = aud.Factory(self.nowPlaying)
|
|
47
|
+ self.handle = None
|
|
48
|
+
|
|
49
|
+ """ Update is called once every frame, and this is where
|
|
50
|
+ any input handling should go
|
58
|
51
|
|
59
|
|
- # Init the keyboard
|
60
|
|
- self.keyboard = bge.logic.keyboard.events
|
61
|
|
-
|
|
52
|
+ Controller Buttons:
|
|
53
|
+ Y-Button - Play/Pause
|
|
54
|
+ LB - Previous Track
|
|
55
|
+ RB - Next Track
|
|
56
|
+
|
|
57
|
+ TODO: Keyboard Buttons if these aren't alright
|
|
58
|
+ P - Play/Pause
|
|
59
|
+ Pad Plus - Next Track
|
|
60
|
+ Pad Minus- Prev Track
|
|
61
|
+ """
|
62
|
62
|
def update(self):
|
|
63
|
+ keyboard = bge.logic.keyboard.events
|
|
64
|
+ up_dict = bge.logic.globalDict
|
|
65
|
+ #print(dictionary)
|
|
66
|
+ pKey = keyboard[bge.events.PKEY]
|
|
67
|
+ pPlus = keyboard[bge.events.PADPLUSKEY]
|
|
68
|
+ pMinus = keyboard[bge.events.PADMINUS]
|
|
69
|
+ lb = up_dict['lBump']
|
|
70
|
+ last_lb = up_dict['last_lBump']
|
|
71
|
+ rb = up_dict['rBump']
|
|
72
|
+ last_rb = up_dict['last_rBump']
|
|
73
|
+ y = up_dict['yBut']
|
|
74
|
+ last_y = up_dict['last_yBut']
|
63
|
75
|
JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED
|
64
|
76
|
|
65
|
|
- if self.keyboard.events[bge.events.PKEY] == JUST_ACTIVATED:
|
66
|
|
- if isPlaying:
|
67
|
|
- self.stopMusic()
|
68
|
|
- else:
|
69
|
|
- self.playMusic()
|
|
77
|
+ # Music controls only during pause/replay
|
|
78
|
+ if up_dict['npause'] == True or up_dict['playback'] == True:
|
|
79
|
+ #stop/play
|
|
80
|
+ if (y == False and last_y == True) or pKey == JUST_ACTIVATED:
|
|
81
|
+ if self.isPlaying:
|
|
82
|
+ self.stopMusic()
|
|
83
|
+ else:
|
|
84
|
+ self.playMusic()
|
|
85
|
+ # Prev/Next
|
|
86
|
+ if self.isPlaying and self.handle.status:
|
|
87
|
+ if pMinus == JUST_ACTIVATED or (lb == False and last_lb == True):
|
|
88
|
+ self.prevSong()
|
|
89
|
+
|
|
90
|
+ if pPlus == JUST_ACTIVATED or (rb == False and last_rb == True):
|
|
91
|
+ self.nextSong()
|
|
92
|
+ # if song ends, play next song
|
|
93
|
+ if self.isPlaying and not self.handle.status:
|
|
94
|
+ self.nextSong()
|
70
|
95
|
|
71
|
|
- def printTag(self):
|
72
|
|
- print('Current Track: ', self.nowPlaying)
|
|
96
|
+ """ get info about song using TinyTag, then print to console """
|
|
97
|
+ def setTag(self):
|
73
|
98
|
self.currTrackPath = os.path.join(self.directory, self.nowPlaying)
|
74
|
|
-
|
75
|
|
- try:
|
76
|
|
- tag = TinyTag.get(self.currTrackPath)
|
77
|
|
- self.currArtist = tag.artist
|
78
|
|
- self.currTrackTitle = tag.title
|
79
|
|
- print('Artist: %s' % self.currArtist,
|
|
99
|
+ tag = TinyTag.get(self.currTrackPath)
|
|
100
|
+ self.currArtist = tag.artist
|
|
101
|
+ self.currTrackTitle = tag.title
|
|
102
|
+ self.dictionary['mu_artist'] = self.currArtist
|
|
103
|
+ self.dictionary['mu_title'] = self.currTrackTitle
|
|
104
|
+
|
|
105
|
+ print('Artist: %s' % self.currArtist,
|
80
|
106
|
' Track: %s' % self.currTrackTitle)
|
81
|
|
- except:
|
82
|
|
- print('Track has no tag')
|
83
|
107
|
|
84
|
108
|
def playMusic(self):
|
85
|
|
- handle = self.device.play(self.factory)
|
|
109
|
+ print('Play Music')
|
|
110
|
+ self.setTag()
|
|
111
|
+ self.handle = self.device.play(self.factory)
|
86
|
112
|
self.isPlaying = True
|
87
|
113
|
|
88
|
114
|
def stopMusic(self):
|
89
|
|
- handle = self.device.play(self.factory)
|
90
|
|
- handle.stop(factory)
|
91
|
|
- self.isPlaying = False
|
|
115
|
+ print('Stop Music')
|
|
116
|
+ self.handle.stop()
|
|
117
|
+ self.isPlaying = False
|
|
118
|
+
|
|
119
|
+ def nextSong(self):
|
|
120
|
+ print('Next Song')
|
|
121
|
+ # stop the current song
|
|
122
|
+ self.handle.stop()
|
|
123
|
+
|
|
124
|
+ # get a song from the playlist
|
|
125
|
+ self.currentNode = self.playlist.get(random.randint(0, self.playlist.getLength()))
|
|
126
|
+ self.nowPlaying = self.currentNode.getData()
|
|
127
|
+ self.playlist.remove(self.currentNode)
|
|
128
|
+
|
|
129
|
+ # add the song to the already played list
|
|
130
|
+ self.alreadyPlayed.append(self.nowPlaying)
|
|
131
|
+
|
|
132
|
+ # start the song
|
|
133
|
+ self.factory = aud.Factory(self.nowPlaying)
|
|
134
|
+ self.handle = self.device.play(self.factory)
|
|
135
|
+ self.setTag()
|
|
136
|
+
|
|
137
|
+ # If playlist is empty, re-fill it
|
|
138
|
+ if self.playlist.getLength() == 0:
|
|
139
|
+ file_name = self.directory + '\\*.mp3'
|
|
140
|
+ file_list = glob.glob(file_name)
|
|
141
|
+ for name in file_list:
|
|
142
|
+ self.playlist.append(name)
|
|
143
|
+
|
|
144
|
+ """ Note on first call of this method, the current node will be equal to the tail of the already played list,
|
|
145
|
+ however, it will be a node from a different list. We need to set current node equal to the tail node
|
|
146
|
+ of the already played list so that we can iterate through that list, instead of the other list """
|
|
147
|
+ def prevSong(self):
|
|
148
|
+ print('Prev Song')
|
|
149
|
+ # stop the current song
|
|
150
|
+ self.handle.stop()
|
|
151
|
+
|
|
152
|
+ if self.currentNode.getData() == self.alreadyPlayed.getTail().getData():
|
|
153
|
+ self.currentNode = self.alreadyPlayed.getTail()
|
|
154
|
+
|
|
155
|
+ self.currentNode = self.currentNode.getPrev()
|
|
156
|
+ self.nowPlaying = self.currentNode.getData()
|
|
157
|
+
|
|
158
|
+ # start the song
|
|
159
|
+ self.factory = aud.Factory(self.nowPlaying)
|
|
160
|
+ self.handle = self.device.play(self.factory)
|
|
161
|
+ self.setTag()
|