Creating the Player class

Now, let's write the code for the Player class. This class will be responsible for the handling of audio playback and its related functions, such as pause, stop, seek, fast forward, rewind, change of volume, mute, and so on.

We will use the pyglet library to handle these functions.

Pyglet is a cross-platform library that uses the AVbin module to support a large variety of audio files.

You might want to look at the API documentation of the pyglet player, which is available at https://bitbucket.org/pyglet/pyglet/wiki/Home.

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

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

The online documentation at https://pyglet.readthedocs.org/ tells us that we can play an audio file by using the following code:

 player= pyglet.media.Player()
source = pyglet.media.load(<<audio file to be played>>)
player.queue(source)
player.play()

Accordingly, the code for the Player class is as follows (see code 5.02player.py):

 import pyglet

FORWARD_REWIND_JUMP_TIME = 20

class Player:
def __init__(self):
self.player = pyglet.media.Player()
self.player.volume = 0.6

def play_media(self, audio_file):
self.reset_player()
self.player = pyglet.media.Player()
self.source = pyglet.media.load(audio_file)
self.player.queue(self.source)
self.player.play()

def reset_player(self):
self.player.pause()
self.player.delete()

def is_playing(self):
try:
elapsed_time = int(self.player.time)
is_playing = elapsed_time < int(self.track_length)
except:
is_playing = False
return is_playing

def seek(self, time):
try:
self.player.seek(time)
except AttributeError:
pass

@property
def track_length(self):
try:
return self.source.duration
except AttributeError:
return 0

@property
def volume(self):
return self.player.volume

@property
def elapsed_play_duration(self):
return self.player.time

@volume.setter
def volume(self, volume):
self.player.volume = volume

def unpause(self):
self.player.play()

def pause(self):
self.player.pause()

def stop(self):
self.reset_player()

def mute(self):
self.player.volume = 0.0

def unmute(self, newvolume_level):
self.player.volume = newvolume_level

def fast_forward(self):
time = self.player.time + FORWARD_REWIND_JUMP_TIME
try:
if self.source.duration > time:
self.seek(time)
else:
self.seek(self.source.duration)
except AttributeError:
pass

def rewind(self):
time = self.player.time - FORWARD_REWIND_JUMP_TIME
try:
self.seek(time)
except:
self.seek(0)

The preceding code is built on the pyglet API, which is quite intuitive. We will not get into the details of audio programming here and trust the pyglet library as a black box that delivers what it says, namely, to be able to play and control audio.

The following are the important things that you should note about the preceding code:

  • We defined the play_media method, which is responsible for the playing of audio. All the other methods support other functions related to playback, such as pause, stop, rewind, forward, mute, and so on.
  • Note that the code defines a new pyglet Player class every time it wants to play an audio file. Though we could have used the same player instance to play multiple audio files, it turns out that the pyglet library does not have a stop method. The only way we can stop an audio file from playing is by killing the Player object and creating a fresh Player object for the next audio file playback.
  • When it came to choosing an external implementation as we did for the audio API here, we first searched through the Python standard library at https://docs.python.org/3.6/library/.
  • Because the standard library does not have a suitable package for us, we turned our attention to the Python package index to check whether there exists another high-level audio interface implementation. The Python package index can be found at http://pypi.python.org/
  • Fortunately, we came across several audio packages. After comparing the packages against our needs and seeing how active their communities were, we settled for pyglet. The same program could have been implemented with several other packages, though this would be done with varying levels of complexity. 
In general, the lower you go down the protocol stack, the more complex your programs will get.
However, at the lower layers of the protocol, you will get a finer control over the implementation at the cost of increasing learning curves.
Also, note that most of the audio libraries change over a period of time. While this current audio library may become nonfunctional over time, you can easily modify the Player class to use some other audio library and still be able to use this program as long as you keep the interface defined in the Player class.

This concludes the iteration. We now have a functional Player class that can manipulate audio files. We have a data structure that consists of a play_list with various methods to add and remove files from a playlist. We will next look at how to add and remove files from a playlist from the frontend of the program.

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

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