def __init__(self, song, songDb, errorNotifyCallback=None, doneCallback=None): """The first parameter, song, may be either a pykdb.SongStruct instance, or it may be a filename. """ pykPlayer.__init__(self, song, songDb, errorNotifyCallback, doneCallback) self.Movie = None manager.setCpuSpeed('mpg') manager.InitPlayer(self) manager.OpenDisplay(depth=DISPLAY_DEPTH) # Close the mixer while using Movie manager.CloseAudio() # Open the Movie module filepath = self.SongDatas[0].GetFilepath() if type(filepath) == unicode: filepath = filepath.encode(sys.getfilesystemencoding()) self.Movie = pygame.movie.Movie(filepath) self.Movie.set_display( manager.display, (0, 0, manager.displaySize[0], manager.displaySize[1]))
def setupSplashScreen(self): # Quick, put up a splash screen for the user to look at while # we're loading. self.splashStart = None manager.OpenDisplay() splashFilename = os.path.join(manager.IconPath, 'splash.png') try: splash = pygame.image.load(splashFilename) except: print("Unable to load splash image.") return # Put the version number up there too. pygame.font.init() font = pygame.font.Font( os.path.join(manager.FontPath, "DejaVuSansCondensed-Bold.ttf"), 12) text = font.render("v%s" % pykversion.PYKARAOKE_VERSION_STRING, True, (0, 0, 0)) rect = text.get_rect() rect = rect.move(225 - rect.width, 43) splash.blit(text, rect) # Center the splash screen within our display window. winWidth, winHeight = manager.displaySize imgWidth, imgHeight = splash.get_size() scale = min(float(winWidth) / imgWidth, float(winHeight) / imgHeight) # We can scale it smaller, but don't scale it bigger. scale = min(scale, 1) scaledWidth = int(scale * imgWidth) scaledHeight = int(scale * imgHeight) xOffset = (winWidth - scaledWidth) / 2 yOffset = (winHeight - scaledHeight) / 2 if scale < 1: scaled = pygame.transform.rotozoom(splash, 0, scale) manager.display.blit(scaled, (xOffset, yOffset)) else: manager.display.blit(splash, (xOffset, yOffset)) pygame.display.flip() # Record the time at which the user was first able to see the # splash screen. self.splashStart = pygame.time.get_ticks()
def errorPopupCallback(self, errorString, wait=True): print(errorString) manager.InitPlayer(self) manager.OpenDisplay() manager.display.fill((0, 0, 0)) # Center the error message onscreen. winWidth, winHeight = manager.displaySize winCenter = winWidth / 2 lines = manager.WordWrapText(errorString, self.subtitleFont, winWidth - X_BORDER * 2) row = (winHeight - len(lines) * self.subtitleHeight) / 2 for line in lines: line = line.strip() text = self.subtitleFont.render(line, True, (255, 255, 255)) rect = text.get_rect() rect = rect.move(winCenter - rect.centerx, row) manager.display.blit(text, rect) row += self.subtitleHeight pygame.display.flip() self.screenDirty = True if not wait: return # Now wait a certain amount of time--say 5 seconds. waitUntil = pygame.time.get_ticks() + 5000 # But also, wait a quarter second to give the user a chance to # react and stop hitting buttons. pygame.time.wait(250) # Discard any events that occurred in that quarter second. for event in pygame.event.get(): pass # Now start listening for events. The first key or button # event gets us out of here. buttonPressed = False while not buttonPressed and pygame.time.get_ticks() < waitUntil: for event in pygame.event.get(): if event.type == pygame.KEYDOWN or \ (env == ENV_GP2X and event.type == pygame.JOYBUTTONDOWN): buttonPressed = True break
def showProgressCallback(self, label, progress): """ This is called by the MiniBusyCancelDialog to show progress as we're scanning the database. """ manager.InitPlayer(self) manager.OpenDisplay() manager.display.fill((0, 0, 0)) # Center the error message onscreen. winWidth, winHeight = manager.displaySize winCenter = winWidth / 2 lines = manager.WordWrapText(label, self.subtitleFont, winWidth - X_BORDER * 2) row = winHeight / 2 - 2 * self.subtitleHeight for line in lines: line = line.strip() text = self.subtitleFont.render(line, True, (255, 255, 255)) rect = text.get_rect() rect = rect.move(winCenter - rect.centerx, row) manager.display.blit(text, rect) row += self.subtitleHeight # Now draw the progress bar. width = winWidth / 2 height = self.subtitleHeight top = winHeight / 2 left = winWidth / 2 - width / 2 rect = pygame.Rect(left, top, width, height) manager.display.fill((255, 255, 255), rect) fill = int((width - 2) * progress + 0.5) rect = pygame.Rect(left + 1 + fill, top + 1, width - 2 - fill, height - 2) manager.display.fill((0, 0, 0), rect) pygame.display.flip() self.screenDirty = True
def beginSong(self, file): self.selectedSong = None manager.setCpuSpeed('load') manager.display.fill((0, 0, 0)) winWidth, winHeight = manager.displaySize winCenter = winWidth / 2 rowA = winHeight / 3 rowC = winHeight * 5 / 6 self.__writeSongTitle(file, rowA) text = self.subtitleFont.render("Loading", True, (255, 255, 255)) rect = text.get_rect() rect = rect.move(winCenter - rect.centerx, rowC) manager.display.blit(text, rect) pygame.display.flip() # This will call the songFinishedCallback, so call it early. self.shutdown() self.writeMarkedSongs() player = file.MakePlayer(self.songDb, self.errorPopupCallback, self.songFinishedCallback) if player == None: return # Start playing. try: player.Play() except: self.errorPopupCallback("Error starting player.\n%s\n%s" % (sys.exc_info()[0], sys.exc_info()[1])) return # Go to sleep until the song is over. try: manager.WaitForPlayer() except: self.errorPopupCallback("Error while playing song.\n%s\n%s" % (sys.exc_info()[0], sys.exc_info()[1])) return # The song is over. Now recover control and redisplay the # song list. manager.OpenCPUControl() manager.setCpuSpeed('menu_fast') self.heldStartTicks = pygame.time.get_ticks() manager.InitPlayer(self) manager.OpenDisplay() # In case the screen has been resized during the song. self.setupScrollWindow() self.screenDirty = True # Discard any events that occurred while we were resetting the # display. for event in pygame.event.get(): pass
def __init__(self, song, songDb, errorNotifyCallback=None, doneCallback=None): """The first parameter, song, may be either a pykdb.SongStruct instance, or it may be a filename. """ pykPlayer.__init__(self, song, songDb, errorNotifyCallback, doneCallback) # With the nomusic option no music will be played. soundFileData = None if not manager.options.nomusic: # Check for a matching mp3 or ogg file. Check extensions # in the following order. validexts = ['.wav', '.ogg', '.mp3'] for ext in validexts: for data in self.SongDatas: if data.Ext == ext: # Found a match! soundFileData = data break if soundFileData: break if not soundFileData: ErrorString = "There is no mp3 or ogg file to match " + self.Song.DisplayFilename self.ErrorNotifyCallback(ErrorString) raise 'NoSoundFile' self.cdgFileData = self.SongDatas[0] self.soundFileData = soundFileData self.soundLength = 0 # Handle a bug in pygame (pre-1.7) which means that the position # timer carries on even when the song has been paused. self.pauseOffsetTime = 0 manager.InitPlayer(self) manager.OpenDisplay() manager.surface.fill((0, 0, 0)) # A working surface for blitting tiles, one at a time. self.workingTile = pygame.Surface((TILE_WIDTH, TILE_HEIGHT), 0, manager.surface) # A surface that contains the set of all tiles as they are to # be assembled onscreen. This surface is kept at the original # scale, then zoomed to display size. It is only used if # settings.CdgZoom == 'soft'. self.workingSurface = pygame.Surface( (CDG_DISPLAY_WIDTH, CDG_DISPLAY_HEIGHT), pygame.HWSURFACE, manager.surface) self.borderColour = None self.computeDisplaySize() aux = aux_c if not aux or not manager.settings.CdgUseC: print("Using Python implementation of CDG interpreter.") aux = aux_python # Open the cdg and sound files self.packetReader = aux.CdgPacketReader(self.cdgFileData.GetData(), self.workingTile) manager.setCpuSpeed('cdg') if self.soundFileData: # Play the music normally. audioProperties = None if manager.settings.UseMp3Settings: audioProperties = self.getAudioProperties(self.soundFileData) if audioProperties == None: audioProperties = (None, None, None) try: manager.OpenAudio(*audioProperties) audio_path = self.soundFileData.GetFilepath() if type(audio_path) == unicode: audio_path = audio_path.encode(sys.getfilesystemencoding()) pygame.mixer.music.load(audio_path) except: self.Close() raise # Set an event for when the music finishes playing pygame.mixer.music.set_endevent(pygame.USEREVENT) # Account for the size of the playback buffer in the lyrics # display. Assume that the buffer will be mostly full. On a # slower computer that's struggling to keep up, this may not # be the right amount of delay, but it should usually be # pretty close. self.InternalOffsetTime = -manager.GetAudioBufferMS() else: # Don't play anything. self.InternalOffsetTime = 0 # Set the CDG file at the beginning self.cdgReadPackets = 0 self.cdgPacketsDue = 0 self.LastPos = self.curr_pos = 0 # Some session-wide constants. self.ms_per_update = (1000.0 / manager.options.fps)
def __init__(self, song, errorNotifyCallback=None, doneCallback=None, Charset="iso-8859-1"): """The first parameter, song, may be either a pykdb.SongStruct instance, or it may be a filename. """ pykPlayer.__init__(self, song, errorNotifyCallback, doneCallback) self.SupportsFontZoom = True # Parse the MIDI file self.midifile = midiParseData(self.SongDatas[0].GetData(), self.ErrorNotifyCallback, Charset) if (self.midifile == None): ErrorString = "ERROR: Could not parse the MIDI file" self.ErrorNotifyCallback(ErrorString) return elif (self.midifile.lyrics == None): ErrorString = "ERROR: Could not get any lyric data from file" self.ErrorNotifyCallback(ErrorString) return # Debug out the found lyrics if debug: self.midifile.lyrics.write() manager.InitPlayer(self) manager.OpenDisplay() # Reduce the default sample rate on the GP2x to save CPU time. if env == ENV_GP2X: manager.OpenAudio(suggestedProperties=(12000, -16, 1)) else: manager.OpenAudio(suggestedProperties=(22050, -16, 2)) # Account for the size of the playback buffer in the lyrics # display. Assume that the buffer will be mostly full. On a # slower computer that's struggling to keep up, this may not # be the right amount of delay, but it should usually be # pretty close. self.InternalOffsetTime = -manager.GetAudioBufferMS() self.screenDirty = False self.initFont() # Windows reports the song time correctly (including period up # to the first note), so no need for the earliest note hack # there. On timidity-based platforms, we anticipate our # lyrics display by the time of the first note. if env != ENV_WINDOWS: self.InternalOffsetTime += self.midifile.earliestNoteMS # Now word-wrap the text to fit our window. self.lyrics = self.midifile.lyrics.wordWrapLyrics(self.font) # By default, we will use the get_pos() functionality returned # by pygame to get the current time through the song, to # synchronize lyric display with the music. self.useMidiTimer = True if env == ENV_WINDOWS: # Unless we're running on Windows. For some reason, MIDI # playback on Windows reports an unreliable time. To # avoid that problem, we'll always use the CPU timer # instead of the MIDI timer. self.useMidiTimer = False # Load the MIDI player if not manager.options.nomusic: pygame.mixer.music.load(self.SongDatas[0].GetFilepath()) # Set an event for when the music finishes playing pygame.mixer.music.set_endevent(pygame.USEREVENT) else: # If we're not playing music, use the CPU timer instead of # the MIDI timer. self.useMidiTimer = False # Reset all the state (current lyric index etc) and # paint the first numRows lines. self.resetPlayingState()