Shuvit game master repo. http://shuvit.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MusicPlayer.py 5.8KB

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