123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- 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()
|