Рубрики
Без рубрики

WXPYPHON: Создание простого MP3-плеер

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

В прошлом месяце я начал серию статей о создании простых приложений с WxPython. Первая пара статей была в программе Viewer изображений. Хотя я не буду отказаться от этого проекта, я подумал, что пришло время нами, чтобы разделить на что-то новое. В этой статье мы начнем путешествие в дикий и шерстяный мир игры в MP3. Мы создадим очень простой интерфейс, который мы можем использовать для игры, пауза и остановить песню. Мы также узнаем, как искать в пути и изменить объем музыки. В будущих статьях мы добавим дисплей с музыкальной информацией (например, название, артист, жанр и т. Д.), Списки треков, случайной функцией и многое другое. Давайте начнем!

Готовимся к спину музыки

Есть много разных макетов, с которыми мы могли бы пойти, но для этого примера мы будем использовать традиционную, где у нас есть горизонтальный виджет слайдера трека песен вдоль вершины с элементами управления плеером и регулированием громкости справа. Если вы знакомы с виджетами WXPYPHON, то вы можете подумать, что в шапдбеттонах будут идеальны для этого приложения. Я так тоже так думал, пока не узнал, что они зависели от библиотеки визуализации Python (Pil). Хотя это не имеет большого значения, для простого примера я думал, что это сложные вопросы для этой статьи и заканчивалось использовать некоторые общие кнопки вместо этого. Когда мы улучшаем эту программу позже, мы можем нанять время, чтобы обновить кнопки, чтобы дать им больше Pizazz. Настоятельно наше приложение будет выглядеть так:

Это не самый красивый музыкальный проигрыватель в мире, но мы можем исправить это позже. Точка изучает, как сделать приложение с Wxpython, который работает в кроссплатформе. Когда я запускаю это приложение на моем компьютере Windows XP, он, кажется, использует FFDShow. Когда я бегу на Windows 7, я думаю, что он использует плеер Windows Media на бэкэнде. Насколько я понимаю, wx.mediactrl свяжет gstreamer на Linux. Во всяком случае, давайте посмотрим на источник:

#----------------------------------------------------------------------
# player_skeleton2.py
#----------------------------------------------------------------------

import os
import wx
import wx.media
import wx.lib.buttons as buttons

dirName = os.path.dirname(os.path.abspath(__file__))
bitmapDir = os.path.join(dirName, 'bitmaps')

########################################################################
class MediaPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent=parent)
        
        self.frame = parent
        self.currentVolume = 50
        self.createMenu()
        self.layoutControls()
        
        sp = wx.StandardPaths.Get()
        self.currentFolder = sp.GetDocumentsDir()
        
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer)
        self.timer.Start(100)
        
    #----------------------------------------------------------------------
    def layoutControls(self):
        """
        Create and layout the widgets
        """
        
        try:
            self.mediaPlayer = wx.media.MediaCtrl(self, style=wx.SIMPLE_BORDER)
        except NotImplementedError:
            self.Destroy()
            raise
                
        # create playback slider
        self.playbackSlider = wx.Slider(self, size=wx.DefaultSize)
        self.Bind(wx.EVT_SLIDER, self.onSeek, self.playbackSlider)
        
        self.volumeCtrl = wx.Slider(self, style=wx.SL_VERTICAL|wx.SL_INVERSE)
        self.volumeCtrl.SetRange(0, 100)
        self.volumeCtrl.SetValue(self.currentVolume)
        self.volumeCtrl.Bind(wx.EVT_SLIDER, self.onSetVolume)
                
        # Create sizers
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        audioSizer = self.buildAudioBar()
                
        # layout widgets
        mainSizer.Add(self.playbackSlider, 1, wx.ALL|wx.EXPAND, 5)
        hSizer.Add(audioSizer, 0, wx.ALL|wx.CENTER, 5)
        hSizer.Add(self.volumeCtrl, 0, wx.ALL, 5)
        mainSizer.Add(hSizer)
        
        self.SetSizer(mainSizer)
        self.Layout()
        
    #----------------------------------------------------------------------
    def buildAudioBar(self):
        """
        Builds the audio bar controls
        """
        audioBarSizer = wx.BoxSizer(wx.HORIZONTAL)
        
        self.buildBtn({'bitmap':'player_prev.png', 'handler':self.onPrev,
                       'name':'prev'},
                      audioBarSizer)
        
        # create play/pause toggle button
        img = wx.Bitmap(os.path.join(bitmapDir, "player_play.png"))
        self.playPauseBtn = buttons.GenBitmapToggleButton(self, bitmap=img, name="play")
        self.playPauseBtn.Enable(False)
        
        img = wx.Bitmap(os.path.join(bitmapDir, "player_pause.png"))
        self.playPauseBtn.SetBitmapSelected(img)
        self.playPauseBtn.SetInitialSize()
        
        self.playPauseBtn.Bind(wx.EVT_BUTTON, self.onPlay)
        audioBarSizer.Add(self.playPauseBtn, 0, wx.LEFT, 3)
        
        btnData = [{'bitmap':'player_stop.png',
                    'handler':self.onStop, 'name':'stop'},
                    {'bitmap':'player_next.png',
                     'handler':self.onNext, 'name':'next'}]
        for btn in btnData:
            self.buildBtn(btn, audioBarSizer)
            
        return audioBarSizer
                    
    #----------------------------------------------------------------------
    def buildBtn(self, btnDict, sizer):
        """"""
        bmp = btnDict['bitmap']
        handler = btnDict['handler']
                
        img = wx.Bitmap(os.path.join(bitmapDir, bmp))
        btn = buttons.GenBitmapButton(self, bitmap=img, name=btnDict['name'])
        btn.SetInitialSize()
        btn.Bind(wx.EVT_BUTTON, handler)
        sizer.Add(btn, 0, wx.LEFT, 3)
        
    #----------------------------------------------------------------------
    def createMenu(self):
        """
        Creates a menu
        """
        menubar = wx.MenuBar()
        
        fileMenu = wx.Menu()
        open_file_menu_item = fileMenu.Append(wx.NewId(), "&Open", "Open a File")
        menubar.Append(fileMenu, '&File')
        self.frame.SetMenuBar(menubar)
        self.frame.Bind(wx.EVT_MENU, self.onBrowse, open_file_menu_item)
        
    #----------------------------------------------------------------------
    def loadMusic(self, musicFile):
        """
        Load the music into the MediaCtrl or display an error dialog
        if the user tries to load an unsupported file type
        """
        if not self.mediaPlayer.Load(musicFile):
            wx.MessageBox("Unable to load %s: Unsupported format?" % musicFile,
                          "ERROR",
                          wx.ICON_ERROR | wx.OK)
        else:
            self.mediaPlayer.SetInitialSize()
            self.GetSizer().Layout()
            self.playbackSlider.SetRange(0, self.mediaPlayer.Length())
            self.playPauseBtn.Enable(True)
    
    #----------------------------------------------------------------------
    def onBrowse(self, event):
        """
        Opens file dialog to browse for music
        """
        wildcard = "MP3 (*.mp3)|*.mp3|"     \
                   "WAV (*.wav)|*.wav"
        dlg = wx.FileDialog(
            self, message="Choose a file",
            defaultDir=self.currentFolder, 
            defaultFile="",
            wildcard=wildcard,
            style=wx.OPEN | wx.CHANGE_DIR
            )
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.currentFolder = os.path.dirname(path)
            self.loadMusic(path)
        dlg.Destroy()
            
    #----------------------------------------------------------------------
    def onNext(self, event):
        """
        Not implemented!
        """
        pass
    
    #----------------------------------------------------------------------
    def onPause(self):
        """
        Pauses the music
        """
        self.mediaPlayer.Pause()
    
    #----------------------------------------------------------------------
    def onPlay(self, event):
        """
        Plays the music
        """
        if not event.GetIsDown():
            self.onPause()
            return
        
        if not self.mediaPlayer.Play():
            wx.MessageBox("Unable to Play media : Unsupported format?",
                          "ERROR",
                          wx.ICON_ERROR | wx.OK)
        else:
            self.mediaPlayer.SetInitialSize()
            self.GetSizer().Layout()
            self.playbackSlider.SetRange(0, self.mediaPlayer.Length())
            
        event.Skip()
    
    #----------------------------------------------------------------------
    def onPrev(self, event):
        """
        Not implemented!
        """
        pass
    
    #----------------------------------------------------------------------
    def onSeek(self, event):
        """
        Seeks the media file according to the amount the slider has
        been adjusted.
        """
        offset = self.playbackSlider.GetValue()
        self.mediaPlayer.Seek(offset)
        
    #----------------------------------------------------------------------
    def onSetVolume(self, event):
        """
        Sets the volume of the music player
        """
        self.currentVolume = self.volumeCtrl.GetValue()
        print "setting volume to: %s" % int(self.currentVolume)
        self.mediaPlayer.SetVolume(self.currentVolume)
    
    #----------------------------------------------------------------------
    def onStop(self, event):
        """
        Stops the music and resets the play button
        """
        self.mediaPlayer.Stop()
        self.playPauseBtn.SetToggle(False)
        
    #----------------------------------------------------------------------
    def onTimer(self, event):
        """
        Keeps the player slider updated
        """
        offset = self.mediaPlayer.Tell()
        self.playbackSlider.SetValue(offset)

########################################################################
class MediaFrame(wx.Frame):
 
    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Python Music Player")
        panel = MediaPanel(self)
        
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MediaFrame()
    frame.Show()
    app.MainLoop()

Вы можете заметить, что это на самом деле версия № 2 этого приложения. В загружаемом источнике внизу этой статьи я включаю оригинал, который использует Андреа Гавана Виджеты Sapedbutton для контроля игрока. Я рекомендую вам получить SVN версия Из этого виджета от официальных репозиториев WXPYPHON, поскольку в версии имеется известная ошибка, которая включена в установку по умолчанию WX. Он также зависит от растровых изображений, которые включены в приложение WXPYPHON DEMO, поэтому вам нужно будет скопировать их в соответствующее место.

Во всяком случае, давайте перейдем на несколько вещей в коде выше. Во-первых, мы настроили пару «глобальных» переменных, которые удерживают путь каталога приложения, поэтому мы можем найти наши папку Bitmaps. Далее мы создаем приложение. Поскольку многие люди хранят свою музыку в папке своих документов, мы используем WX.StandardPaths, чтобы найти это место на перекрестной платформе и установить Currentfolder атрибут этому местоположению. Мы будем использовать этот атрибут для хранения последней открытой папки, когда мы просматриваем музыку, чтобы прослушать. Мы также устанавливаем таймер, который используется для обновления слайдера трека проигрывателя, когда он играет. Это скопировано дословно от демонстрации WXPYPHON MEDIACTRL.

В LayoutControls Способ, мы создаем необходимые виджеты и добавьте их в соответствующие сизуры по мере необходимости. Мы также делаем привязки событий виджета здесь. Остальная часть кода обрабатывает другие планировки или события, которые генерируются. Они также довольно объяснительны. Обратите внимание, что ОнПрев и onnext Методы ничего не делают. Это предназначено, поскольку в настоящее время у нас нет способа загрузить более одной песни за раз. Мы добавим эту функциональность в будущей версии программы.

Итак, основные шаги для воспроизведения песни с этим приложением следующие:

  1. Перейти к файлу и открыть
  2. Перейдите к файлу MP3 и откройте его
  3. Нажмите кнопку PLAY под ползуном воспроизведения, чтобы начать слушать музыку

Это все, что есть к этому. Теперь у вас есть полнофункциональный музыкальный плеер. Да, это ограничено, но он должен дать вам представление о том, насколько мощный Wxpython и насколько легко продлить этот пример, чтобы соответствовать вашим потребностям.

Загрузки

  • Music_Player.zip
  • Music_player.tar.tar.tar