I am somewhat new to programming. I am building a simple app using Kivy framework. The app has 15 buttons. When you press the button, it starts playing a melody. If any other button is playing at that moment, it should stop, i.e. multiple sounds (from different instances) should not play at the same time.
This is what I did — I created a class method that handles stopping and playing sounds. On press, the button instance passes sound object to this class method. However, on first press, since the sound object does not yet exist my app crashes. Hence the reason for try … except AttributeError
part.
class Gumb(Button):
soundfile = StringProperty(None)
sound = ObjectProperty(None)
now_playing_object = None
def on_soundfile(self, instance, value):
self.sound = SoundLoader.load(value)
def on_press(self):
if self.sound:
self.__class__.play_sound(self.sound)
@classmethod
def play_sound(cls, new_sound_object):
try:
if cls.now_playing_object.state != 'stop':
cls.now_playing_object.stop()
except AttributeError:
pass
cls.now_playing_object = new_sound_object
cls.now_playing_object.play()
This works, however I do not like it, especially thetry … except
part. There has to be a better way to do this. Any ideas?
Thanks!
Update 1:
@toto_tico provided me with a couple of solutions to circumvent the try ... except
part.
Use
if
instead of exception:if cls.now_playing_object != None and cls.now_playing_object.state != 'stop': cls.now_playing_object.stop()
Although, after reading about efficiency of python's ifs vs exceptions, I am not sure that I should be trying to eliminate
try ... except
at all.Initialize the
now_playing_object
on the very beginning. To do this I used:now_playing_object = SoundLoader.load(‘non_existant_file.wav’)
This works, but it feels a bit unreliable (it is strange that Kivy complains if the filename misses extension, but not if there is no file at all). Nevertheless, I think I'll use this one.
Update 2:
It turns out that the solution was right in front of me. I just couldn't see it. There was really no need for @classmethod
:
class Gumb(Button):
...
def play_sound(self):
if self.__class__.now_playing_object.state is not 'stop':
self.__class__.now_playing_object.stop()
self.__class__.now_playing_object = self.sound
self.__class__.now_playing_object.play()
I've accepted the answer, but the real answer is in the comments. Thanks @toto_tico.