import bge import os import aud import random import glob from DList import DoubleList from collections import OrderedDict from tinytag import TinyTag """ This is the Music Player as a component """ class MusicPlayer(bge.types.KX_PythonComponent): args = OrderedDict([]) def start(self, args): # dictionary self.dictionary = bge.logic.globalDict # get mp3 files from the disk and create a list self.directory = bge.logic.expandPath('//Music') file_name = self.directory + '\\*.mp3' file_list = glob.glob(file_name) # use the mp3 list to make a playlist of nodes self.playlist = DoubleList() for name in file_list: self.playlist.append(name) # previously played list of nodes self.alreadyPlayed = DoubleList() # get a random song from the playlist, # remove it from the playlist # add it to the alreadyPlayed list # NOTICE: currentNode is a reference to a NODE in a list, if you want to play the song inside the node, use .data self.currentNode = self.playlist.get(random.randint(0, self.playlist.getLength())) self.nowPlaying = self.currentNode.getData() self.playlist.remove(self.currentNode) self.alreadyPlayed.append(self.nowPlaying) print("Now Playing: " + self.nowPlaying) self.setTag() self.isPlaying = False # create audio devices self.device = aud.device() self.factory = aud.Factory(self.nowPlaying) self.handle = None """ Update is called once every frame, and this is where any input handling should go Controller Buttons: Y-Button - Play/Pause LB - Previous Track RB - Next Track TODO: Keyboard Buttons if these aren't alright P - Play/Pause Pad Plus - Next Track Pad Minus- Prev Track """ def update(self): keyboard = bge.logic.keyboard.events up_dict = bge.logic.globalDict #print(dictionary) pKey = keyboard[bge.events.PKEY] pPlus = keyboard[bge.events.PADPLUSKEY] pMinus = keyboard[bge.events.PADMINUS] lb = up_dict['lBump'] last_lb = up_dict['last_lBump'] rb = up_dict['rBump'] last_rb = up_dict['last_rBump'] y = up_dict['yBut'] last_y = up_dict['last_yBut'] JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED #Run player on startup if up_dict['music_start'] == True: if self.isPlaying: self.stopMusic() else: self.playMusic() up_dict['music_start'] = False # Music controls only during pause/replay if (up_dict['npause'] == True or up_dict['playback'] == True) or up_dict['music_start'] == True: #stop/play if (y == False and last_y == True) or pKey == JUST_ACTIVATED: if self.isPlaying: self.stopMusic() up_dict['music_player'] = 0 else: self.playMusic() up_dict['music_player'] = 1 # Prev/Next if self.isPlaying and self.handle.status: if pMinus == JUST_ACTIVATED or (lb == False and last_lb == True): self.prevSong() if pPlus == JUST_ACTIVATED or (rb == False and last_rb == True): self.nextSong() # if song ends, play next song if self.isPlaying and not self.handle.status: self.nextSong() """ get info about song using TinyTag, then print to console """ def setTag(self): self.currTrackPath = os.path.join(self.directory, self.nowPlaying) tag = TinyTag.get(self.currTrackPath) self.currArtist = tag.artist self.currTrackTitle = tag.title self.dictionary['mu_artist'] = self.currArtist self.dictionary['mu_title'] = self.currTrackTitle print('Artist: %s' % self.currArtist, ' Track: %s' % self.currTrackTitle) def playMusic(self): print('Play Music') self.setTag() self.handle = self.device.play(self.factory) self.isPlaying = True def stopMusic(self): print('Stop Music') self.handle.stop() self.isPlaying = False def nextSong(self): print('Next Song') # stop the current song self.handle.stop() # get a song from the playlist self.currentNode = self.playlist.get(random.randint(0, self.playlist.getLength())) self.nowPlaying = self.currentNode.getData() self.playlist.remove(self.currentNode) # add the song to the already played list self.alreadyPlayed.append(self.nowPlaying) # start the song self.factory = aud.Factory(self.nowPlaying) self.handle = self.device.play(self.factory) self.setTag() # If playlist is empty, re-fill it if self.playlist.getLength() == 0: file_name = self.directory + '\\*.mp3' file_list = glob.glob(file_name) for name in file_list: self.playlist.append(name) """ Note on first call of this method, the current node will be equal to the tail of the already played list, however, it will be a node from a different list. We need to set current node equal to the tail node of the already played list so that we can iterate through that list, instead of the other list """ def prevSong(self): print('Prev Song') # stop the current song self.handle.stop() if self.currentNode.getData() == self.alreadyPlayed.getTail().getData(): self.currentNode = self.alreadyPlayed.getTail() self.currentNode = self.currentNode.getPrev() self.nowPlaying = self.currentNode.getData() # start the song self.factory = aud.Factory(self.nowPlaying) self.handle = self.device.play(self.factory) self.setTag()