Adding more controls to the player

Now that we have a playlist, we need to ensure that songs play in a queue. We also need to add a few more controls typically found in audio players, such as Next, Previous, Fast Forward, Rewind, and Mute buttons. We also need to provide a method to change the volume of playback.

At the end of this iteration, our player would have the following additional controls in the top-button frame:

Adding more controls to the player

The pyglet API documentation provides simple interfaces for all these controls. For your reference, the documentation is available at:

http://www.pyglet.org/doc/api/pyglet.media.Player-class.html

Let's begin by adding methods to handle these in our Player class.

Engage Thrusters

Step 1 – fast forwarding a track

We can fast forward a track as follows (see code 5.03 player.py):

FWDREWNDTIME = 20
#time to seek ahead or backwards in seconds
def fast_fwd(self):
   try:
     current_time = self.myplayer.time
     self.myplayer.seek(current_time+FWDREWNDTIME)
   except:pass

Step 2 – rewinding a track

We can rewind a track as follows:

def rewind(self):
   try:
     current_time = self.myplayer.time
     self.myplayer.seek(current_time-FWDREWNDTIME)
   except:pass

Step 3 – pausing a track

We can pause a track as follows:

def pause(self):
   try:
     self.myplayer.pause()
     self.paused = True
   except: pass

Step 4 – setting the volume of playback

We can set the volume of playback as follows:

def set_vol(self, vol):
   try:
     self.myplayer.volume = vol
   except:pass

Step 5 – muting and unmuting a track

We can mute and unmute a track as follows:

def mute(self):
   try:
     self.myplayer.volume = 0.0
     self.parent.volscale.set(0.0)
   except:pass

def unmute(self):
   self.set_vol(self.vol)
   self.parent.volscale.set(0.3)

We will not discuss the code here in detail. For coding these functionalities, we have used the API documentation for pyglet available at:

http://www.pyglet.org/doc/api/pyglet.media.Player-class.html

You can also access this documentation for the pyglet media player class by typing these two lines in your Python interactive shell:

>>> import pyglet
>>> help (pyglet.media.Player)

Note

We have been indiscriminately using try/except blocks in this program to hide all errors emanating from the player class.

This might not be the best programming practice, but we ignore all player class errors so as not to deviate from our discussion on Tkinter.

In a normal case, you would handle all different kind of errors using different except blocks.

Step 6 – adding the control buttons

Now that we have the backend code to handle events, such as fast forward, rewind, volume change, mute, and others, it is simply time to add buttons for each of these controls to our GUI class. We link each of the buttons to its respective command callback.

So, we modify our create_button_frame widget to add buttons for these new controls.

We have added hundreds of buttons so far in our previous project. So, we do not reproduce the entire code here for sake of brevity. Rather, we simply show the implementation of the Previous Track button as one of its sample, and how it calls the associated command callback to the previous() method of the player class as follows (see code 5.03 GUI.py):

previcon = PhotoImage(file='../icons/previous.gif')
prevbtn=Button(buttonframe, image=previcon, borderwidth=0, padx=0, command=self.prev_track)
prevbtn.image = previcon
prevbtn.grid(row=3, column=1, sticky='w')

Step 7 – changing volume with the ttk Scale widget

In addition to these buttons, we also use the ttk Scale widget to allow the users to change the volume. The native Scale widget implementation in core Tkinter looks rather old fashioned and we instead settle for the ttk Scale widget, which has same set of configurable options as the core Tkinter Scale widget, as follows:

self.volscale = ttk.Scale(buttonframe, from_=0.0, to =1.0 , command=self.vol_update)
self.volscale.set(0.6)
self.volscale.grid(row=3, column=7, padx=5)

As per the pyglet documentation, the volume of playback must be specified as a float ranging from 0.0 (no sound) to 1.0 (maximum sound), and our updateVolume method uses this as the basis.

This has an attached callback to another method, vol_update, in the GUI class, which simply delegates the task to the player method to handle volume changes.

def vol_update(self, e):
    vol = float(e)
    self.player.set_vol(vol)

The description of the code is listed as follows:

  • The pyglet Player class expects volume to be specified as a float, but the command here receives the new value of scale as a string. We, therefore, first convert it to float, and then pass it to the set_vol method of the player class.

Objective Complete – Mini Debriefing

This completes the second iteration where we added playback control features to our program.

This section was more about sticking to the API documentation of pyglet and trusting it as a blackbox to deliver what it says: namely, to be able to play and control audio.

We also saw how to use the ttk Scale widget in a practical demonstration of building our volume control.

Classified Intel

When it came to choosing an external implementation (as we did for audio API here), we first searched through the Python Standard Library at:

http://docs.python.org/library/

Because the Standard Library does not have a suitable package for us, we turned our attention to Python Package Index to see if there exists another high-level audio interface implementation. The Python package index lives at:

http://pypi.python.org/

Fortunately, we came across several audio packages. After comparing the packages against our needs and seeing how active its community was, we settled for pyglet. The same program could have been implemented with several other packages, though with varying levels of complexity.

Tip

In general, the lower you go down the protocol stack, the more complex your programs would get.

However, at lower layers of the protocol, you get a finer control over the implementation at the cost of increasing learning curves.

For instance, because the pyglet player class does not differentiate between pause and stop functionality, we had to altogether do away with the pause functionality and settle for a simpler implementation where pause and stop mean the same.

For a finer control of audio source, we will have to go deeper into the protocol stacks, which we will avoid for now, so as not to digress from our topic.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.214.27