Here's the patch I worked out following the discussion on IRC yesterday. It includes a single retry if the initial set_state(NULL) fails in __load_song, and some streamlining of control flow. I also have init() bump the GStreamer default debug level from NONE to ERROR, so that future problems of this kind will be easier to diagnose.
Patch is versus top-of-trunk -- how far off is that from what's currently packaged for Debian? zw * player.py (PlaylistPlayer#__load_song): Take third 'lock' argument. Retry initial set_state once if it fails. Call self.error here if initial set_state fails twice in a row, or if final set_state fails at all. (PlaylistPlayer#__get_song): Remove try/except wrapper around call to __load_song. (init): Set default GStreamer debug level to LEVEL_ERROR. =================================================================== Index: player.py --- player.py (revision 2406) +++ player.py (working copy) @@ -100,14 +100,32 @@ self.info.song_started(None) config.set("memory", "song", "") - def __load_song(self, song): + def __load_song(self, song, lock): + # Under as-yet-undetermined conditions, the initial set_state() + # can mysteriously fail -- if you turn GStreamer debugging on you + # get diagnostics like this: + # alsa( 1481) gstalsa.c(1632):gst_alsa_open_audio:<alsasink0> + # ALSA device "default" is already in use by another program. + # + # This is believed to be a GStreamer bug. If it happens, try again + # after pausing a little. st = self.bin.set_state(gst.STATE_NULL) - if st != gst.STATE_SUCCESS: raise Exception(st) + if st != gst.STATE_SUCCESS: + import time + time.sleep(0.01) + st = self.bin.set_state(gst.STATE_NULL) + if st != gst.STATE_SUCCESS: + # FIXME: feed self.error a useful error message + # (and do something sensible with it in SongWatcher#error) + self.error('', lock) + return + self.bin.set_property('uri', song("~uri")) self.__length = song["~#length"] * 1000 if self.__paused: st = self.bin.set_state(gst.STATE_PAUSED) else: st = self.bin.set_state(gst.STATE_PLAYING) - if st != gst.STATE_SUCCESS: raise Exception(st) + if st != gst.STATE_SUCCESS: + self.error('', lock) def quit(self): self.bin.set_state(gst.STATE_NULL) @@ -135,11 +153,7 @@ self.volume = self.__volume if song is not None: config.set("memory", "song", song["~filename"]) - try: self.__load_song(song) - except Exception, err: - import traceback; traceback.print_exc() - self.error(err, lock) - return + self.__load_song(song, lock) else: config.set("memory", "song", "") self.paused = True @@ -225,6 +239,7 @@ playlist = None def init(pipeline): + gst.debug_set_default_threshold(gst.LEVEL_ERROR) if gst.element_make_from_uri(gst.URI_SRC, "file://", ""): global playlist playlist = PlaylistPlayer(pipeline or "gconf") -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]