Author: dmeyer
Date: Sun Aug 20 11:04:27 2006
New Revision: 1890

Modified:
   trunk/WIP/player/src/backends/base.py
   trunk/WIP/player/src/backends/gstreamer/child.py
   trunk/WIP/player/src/backends/gstreamer/player.py
   trunk/WIP/player/src/backends/manager.py
   trunk/WIP/player/src/backends/mplayer/player.py
   trunk/WIP/player/src/backends/xine/child.py
   trunk/WIP/player/src/backends/xine/player.py
   trunk/WIP/player/src/generic.py
   trunk/WIP/player/src/ptypes.py
   trunk/WIP/player/test/play.py
   trunk/WIP/player/test/test_backends.py

Log:
Next try to make the state handling when to open, start or stop working.
Functions now have a decorator to make sure they are called in the correct
state and in the correct order. Two things need to be fixed to make it nicer:
1. To release vo and ao, the player is killed
2. The not running state in generic is realized by setting self._player to None


Modified: trunk/WIP/player/src/backends/base.py
==============================================================================
--- trunk/WIP/player/src/backends/base.py       (original)
+++ trunk/WIP/player/src/backends/base.py       Sun Aug 20 11:04:27 2006
@@ -53,7 +53,6 @@
             "play": kaa.notifier.Signal(),
             "pause_toggle": kaa.notifier.Signal(),
             "seek": kaa.notifier.Signal(),
-            "open": kaa.notifier.Signal(),
             "start": kaa.notifier.Signal(),
             "failed": kaa.notifier.Signal(),
             # Stream ended (either stopped by user or finished)
@@ -61,11 +60,15 @@
             "stream_changed": kaa.notifier.Signal(),
             "frame": kaa.notifier.Signal(), # CAP_CANVAS
             "osd_configure": kaa.notifier.Signal(),  # CAP_OSD
-            # Process is about to die (shared memory will go away)
-            "quit": kaa.notifier.Signal()
+
+            # Player released video and audio devices
+            "release": kaa.notifier.Signal(),
+            
+            # Process died (shared memory will go away)
+            "shm_quit": kaa.notifier.Signal()
         }
 
-        self._state_object = STATE_NOT_RUNNING
+        self._state_object = STATE_IDLE
         self._window = None
         self._size = None
 
@@ -107,20 +110,30 @@
         """
         Set state and emit 'failed', 'start' or 'end' signal if needed.
         """
-        # handle state changes
-        if self._state == STATE_OPENING and \
-               state in (STATE_IDLE, STATE_NOT_RUNNING):
+        if self._state_object == state:
+            return
+        old_state = self._state_object
+        self._state_object = state
+
+        if old_state == STATE_OPENING and state in (STATE_IDLE, 
STATE_NOT_RUNNING):
+            # From STATE_OPENING to not playing. This means something went
+            # wrong and the player failed to play.
             self.signals["failed"].emit()
-        if self._state == STATE_OPENING and \
+
+        if old_state == STATE_OPENING and \
                state in (STATE_PLAYING, STATE_PAUSED):
+            # From STATE_OPENING to playing. Signal playback start
             self.signals["start"].emit()
-        if self._state in (STATE_PLAYING, STATE_PAUSED) and \
+
+        if old_state in (STATE_PLAYING, STATE_PAUSED) and \
                state in (STATE_IDLE, STATE_NOT_RUNNING):
+            # From playing to finished. Signal end.
             self.signals["end"].emit()
 
-        # save new state
-        self._state_object = state
-
+        if state == STATE_NOT_RUNNING == self._state_object:
+            self.signals["release"].emit()
+            self.signals["shm_quit"].emit()
+            
     # state property based on get_state and _set_state
     _state = property(get_state, _set_state, None, 'state of the player')
 
@@ -170,7 +183,7 @@
 
     def play(self):
         """
-        Start or resume playback.
+        Start playback.
         """
         pass
 
@@ -189,13 +202,20 @@
         pass
 
 
-    def die(self):
+    def resume(self):
         """
-        Kills the player.  No more files may be played once die() is called.
+        Resume playback.
         """
         pass
 
 
+    def release(self):
+        """
+        Release audio and video devices.
+        """
+        self.die()
+
+        
     def seek_relative(self, offset):
         """
         Seek relative.

Modified: trunk/WIP/player/src/backends/gstreamer/child.py
==============================================================================
--- trunk/WIP/player/src/backends/gstreamer/child.py    (original)
+++ trunk/WIP/player/src/backends/gstreamer/child.py    Sun Aug 20 11:04:27 2006
@@ -17,7 +17,7 @@
 
     def __init__(self, instance_id):
         Player.__init__(self)
-        self.player = None
+        self._gst = None
         self._status_object = Status(self._send_status)
         self._status_last = None
 
@@ -34,12 +34,12 @@
         """
         Outputs stream status information.
         """
-        if not self.player:
+        if not self._gst:
             return
 
         pos = 0
         if self.status == Status.PLAYING:
-            pos = float(self.player.query_position(gst.FORMAT_TIME)[0] / 
1000000) / 1000
+            pos = float(self._gst.query_position(gst.FORMAT_TIME)[0] / 
1000000) / 1000
         current = self.status, pos
         
         if current != self._status_last:
@@ -85,20 +85,27 @@
         vo.set_property('force-aspect-ratio', True)
 
         # now create the player and set the output
-        self.player = gst.element_factory_make("playbin", "player")
-        self.player.set_property('video-sink', vo)
-        self.player.get_bus().add_watch(self._gst_message)
+        self._gst = gst.element_factory_make("playbin", "player")
+        self._gst.set_property('video-sink', vo)
+        self._gst.get_bus().add_watch(self._gst_message)
 
 
     def open(self, uri):
-        self.player.set_property('uri', uri)
-        self.player.set_state(gst.STATE_PLAYING)
+        self._gst.set_property('uri', uri)
+        self._gst.set_state(gst.STATE_PLAYING)
         self.status = Status.OPENING
-        print 'start', uri
+
+
+    def pause(self):
+        self._gst.set_state(gst.STATE_PAUSED)
+
+
+    def resume(self):
+        self._gst.set_state(gst.STATE_PLAYING)
 
 
     def stop(self):
-        self.player.set_state(gst.STATE_NULL)
+        self._gst.set_state(gst.STATE_NULL)
         self.status = Status.IDLE
 
 

Modified: trunk/WIP/player/src/backends/gstreamer/player.py
==============================================================================
--- trunk/WIP/player/src/backends/gstreamer/player.py   (original)
+++ trunk/WIP/player/src/backends/gstreamer/player.py   Sun Aug 20 11:04:27 2006
@@ -30,14 +30,14 @@
         
self.player.set_stop_command(kaa.notifier.WeakCallback(self._end_child))
         self.player.start()
         self._state = STATE_IDLE
-        self._stopping = False
+
 
     def _exited(self, exitcode):
         self._state = STATE_NOT_RUNNING
-        self.signals["quit"].emit()
 
 
     def _end_child(self):
+        self._state = STATE_SHUTDOWN
         self.player.die()
 
 
@@ -50,10 +50,7 @@
             self._position = pos
             return True
         if status == Status.IDLE:
-            if self._stopping and self._state == STATE_OPENING:
-                self._stopping = False
-            else:
-                self._state = STATE_IDLE
+            self._state = STATE_IDLE
         self._position = 0
         
 
@@ -63,7 +60,6 @@
         if mrl.find('://') == -1:
             mrl = 'file://' + mrl
         self._mrl = mrl
-        self.signals["open"].emit()
         if self._state == STATE_NOT_RUNNING:
             self._span()
 
@@ -74,10 +70,6 @@
         async until either the playing has started or an error
         occurred.
         """
-        if self.get_state() == STATE_PAUSED:
-            self.player.play()
-            return True
-
         wid = None
         if self._window:
             wid = self._window.get_id()
@@ -92,18 +84,22 @@
 
     def pause(self):
         self.player.pause()
+        self._state = STATE_PAUSED
+
 
+    def resume(self):
+        self.player.resume()
+        self._state = STATE_PLAYING
 
+        
     def stop(self):
-        self._stopping = True
         self.player.stop()
-        self._state = STATE_IDLE
 
 
     def die(self):
         self.stop()
         self.player.die()
-        self._state = STATE_NOT_RUNNING
+        self._state = STATE_SHUTDOWN
 
 
     def get_info(self):

Modified: trunk/WIP/player/src/backends/manager.py
==============================================================================
--- trunk/WIP/player/src/backends/manager.py    (original)
+++ trunk/WIP/player/src/backends/manager.py    Sun Aug 20 11:04:27 2006
@@ -34,6 +34,7 @@
 # kaa.player imports
 from kaa.player.backends.base import MediaPlayer
 from kaa.player.ptypes import *
+from kaa.player.utils import parse_mrl
 
 # internal list of players
 _players = {}

Modified: trunk/WIP/player/src/backends/mplayer/player.py
==============================================================================
--- trunk/WIP/player/src/backends/mplayer/player.py     (original)
+++ trunk/WIP/player/src/backends/mplayer/player.py     Sun Aug 20 11:04:27 2006
@@ -329,7 +329,6 @@
 
     def _exited(self, exitcode):
         self._state = STATE_NOT_RUNNING
-        self.signals["quit"].emit()
         # exit code is strange somehow
         # if exitcode != 0:
         #     raise MPlayerExitError, (exitcode, self._last_line)
@@ -339,6 +338,11 @@
         return self._process and self._process.is_alive()
 
     def open(self, mrl, user_args = None):
+
+        if self.get_state() != STATE_NOT_RUNNING:
+            print 'Error: not idle'
+            return False
+
         schemes = self.get_supported_schemes()
         scheme, path = parse_mrl(mrl)
 
@@ -364,19 +368,8 @@
         if user_args:
             self._file_args.append(user_args)
 
-        self.signals["open"].emit()
-
 
     def play(self):
-        state = self.get_state()
-        if state == STATE_PAUSED:
-            self._slave_cmd("pause")
-            return True
-
-        if state != STATE_NOT_RUNNING:
-            print 'Error: not idle'
-            return False
-
         # we know that self._mp_info has to be there or the object would
         # not be selected by the generic one. FIXME: verify that!
         assert(self._mp_info)
@@ -425,6 +418,11 @@
         if self.get_state() == STATE_PLAYING:
             self._slave_cmd("pause")
 
+
+    def resume(self):
+        if self.get_state() == STATE_PAUSED:
+            self._slave_cmd("pause")
+
     def seek_relative(self, offset):
         self._slave_cmd("seek %f 0" % offset)
 
@@ -435,10 +433,8 @@
         self._slave_cmd("seek %f 1" % percent)
 
     def stop(self):
-        #self._slave_cmd("pt_step + 1")
-        #self._state = STATE_IDLE
         self.die()
-        self._state = STATE_NOT_RUNNING
+        self._state = STATE_SHUTDOWN
 
     def _end_child(self):
         self._slave_cmd("quit")

Modified: trunk/WIP/player/src/backends/xine/child.py
==============================================================================
--- trunk/WIP/player/src/backends/xine/child.py (original)
+++ trunk/WIP/player/src/backends/xine/child.py Sun Aug 20 11:04:27 2006
@@ -253,14 +253,18 @@
 
     def play(self):
         status = self._stream.get_status()
-        if status == xine.STATUS_PLAY:
-            self._stream.set_parameter(xine.PARAM_SPEED, xine.SPEED_NORMAL)
-        elif status == xine.STATUS_STOP:
+        if status == xine.STATUS_STOP:
             self._stream.play()
 
+
     def pause(self):
         self._stream.set_parameter(xine.PARAM_SPEED, xine.SPEED_PAUSE)
 
+
+    def resume(self):
+        self._stream.set_parameter(xine.PARAM_SPEED, xine.SPEED_NORMAL)
+
+
     def seek(self, whence, value):
         if whence == 0:
             self._stream.seek_relative(value)
@@ -270,18 +274,19 @@
             self._stream.play(pos = value)
 
 
-    def die(self):
-        self.stop()
-        sys.exit(0)
-
-
     def stop(self):
         self._status.stop()
         if self._stream:
             self._stream.stop()
             self._stream.close()
+        self.parent.play_stopped()
 
 
+    def die(self):
+        self.stop()
+        sys.exit(0)
+        
+
     def frame_output(self, vo, notify, size):
         if not self._driver_control:
             # FIXME: Tack, what am I doing here?
@@ -328,5 +333,3 @@
 gc.collect()
 
 sys.exit(0)
-
-

Modified: trunk/WIP/player/src/backends/xine/player.py
==============================================================================
--- trunk/WIP/player/src/backends/xine/player.py        (original)
+++ trunk/WIP/player/src/backends/xine/player.py        Sun Aug 20 11:04:27 2006
@@ -69,19 +69,14 @@
 
 
     def _end_child(self):
+        self._state = STATE_SHUTDOWN
         self._xine.die()
 
 
-    def die(self):
-        if self._xine:
-            self._xine.die()
-
-
     def _exited(self, exitcode):
-        self._state = STATE_NOT_RUNNING
+        self._xine = None
         self._remove_shmem()
-        self.signals["quit"].emit()
-
+        self._state = STATE_NOT_RUNNING
 
 
     # 
#############################################################################
@@ -113,7 +108,6 @@
             if self.get_state() in (STATE_PAUSED, STATE_PLAYING):
                 # Stream ended.
                 self._state = STATE_IDLE
-                self.signals["end"].emit()
 
 
     def _child_osd_configure(self, width, height, aspect):
@@ -144,7 +138,7 @@
             # failed playback
             self._state = STATE_IDLE
             return
-        
+
         changed = info != self._stream_info
         self._stream_info = info
 
@@ -155,11 +149,16 @@
         if changed:
             self.signals["stream_changed"].emit()
 
+
     def _child_xine_event(self, event, data):
         if event == xine.EVENT_UI_NUM_BUTTONS:
             self._is_in_menu = data["num_buttons"] > 0
 
 
+    def _child_play_stopped(self):
+        self._state = STATE_IDLE
+
+
     # 
#############################################################################
     # Window handling
     # 
#############################################################################
@@ -180,7 +179,7 @@
 
 
     # 
#############################################################################
-    # Public API
+    # API exposed to generic player
     # 
#############################################################################
 
 
@@ -190,14 +189,11 @@
             raise ValueError, "Unsupported mrl scheme '%s'" % scheme
 
         self._mrl = "%s:%s" % (scheme, path)
-        # Open with kaa.metadata
-        self.signals["open"].emit()
 
 
     def play(self, video=True):
-        if self.get_state() == STATE_PAUSED:
-            self._xine.play()
-            return
+        if not self._xine:
+            self._spawn()
 
         wid = None
         if self._window:
@@ -207,17 +203,25 @@
         self._position = 0.0
         self._xine.open(self._mrl)
         self._state = STATE_OPENING
-        return
-    
+
 
     def pause(self):
         self._xine.pause()
 
 
+    def resume(self):
+        self._xine.resume()
+
+
     def stop(self):
         self._xine.stop()
 
 
+    def die(self):
+        self._state = STATE_SHUTDOWN
+        self._xine.die()
+
+        
     def seek_relative(self, offset):
         self._xine.seek(0, offset)
 
@@ -230,6 +234,7 @@
         pos = (percent / 100.0) * 65535
         self._xine.seek(2, pos)
 
+
     def get_info(self):
         return self._stream_info
 
@@ -259,7 +264,7 @@
         if size != None:
             self._cur_frame_output_mode[2] = size
 
-        if self.get_state() in (STATE_NOT_RUNNING, STATE_OPENING):
+        if self.get_state() == STATE_OPENING:
             return
 
         vo, notify, size = self._cur_frame_output_mode

Modified: trunk/WIP/player/src/generic.py
==============================================================================
--- trunk/WIP/player/src/generic.py     (original)
+++ trunk/WIP/player/src/generic.py     Sun Aug 20 11:04:27 2006
@@ -44,6 +44,30 @@
 # get logging object
 log = logging.getLogger('player')
 
+def required_states(*states):
+    """
+    Decorator to make sure a function is only called in the corrent state
+    and in the correct order of all pending calls.
+    """
+    def decorator(func):
+
+        def newfunc(self, *args, **kwargs):
+            if self.get_state() in states and not self._pending:
+                return func(self, *args, **kwargs)
+            # print 'pending:', func, self.get_state(), states
+            callback = kaa.notifier.Callback(func, self, *args, **kwargs)
+            self._pending.append((states, callback))
+            
+        try:
+            newfunc.func_name = func.func_name
+        except TypeError:
+            pass
+        newfunc.states = states
+        return newfunc
+
+    return decorator
+
+
 class Player(object):
     """
     Generic player. On object of this class will use the players from the
@@ -56,15 +80,18 @@
         self._window = window
 
         self.signals = {
-            "pause": kaa.notifier.Signal(),
-            "play": kaa.notifier.Signal(),
-            "pause_toggle": kaa.notifier.Signal(),
-            "seek": kaa.notifier.Signal(),
+
+            # signals created by this class
             "open": kaa.notifier.Signal(),
             "start": kaa.notifier.Signal(),
             "failed": kaa.notifier.Signal(),
-            # Stream ended (either stopped by user or finished)
             "end": kaa.notifier.Signal(),
+
+            # pass thru signals from player
+            "pause": kaa.notifier.Signal(),
+            "play": kaa.notifier.Signal(),
+            "pause_toggle": kaa.notifier.Signal(),
+            "seek": kaa.notifier.Signal(),
             "stream_changed": kaa.notifier.Signal(),
             # Emitted when a new frame is availabnle.  See 
             # set_frame_output_mode() doc for more info.
@@ -72,137 +99,158 @@
             # Emitted when OSD buffer has changed.  See osd_update() doc
             # for more info.
             "osd_configure": kaa.notifier.Signal(),  # CAP_OSD
-            # Process is about to die (shared memory will go away)
-            "quit": kaa.notifier.Signal()
+            # Process died (shared memory will go away)
+            "shm_quit": kaa.notifier.Signal()
         }
 
+        # pending commands
+        self._pending = []
+        self._blocked = False
+        self._player = None
+        self._failed_player = []
+        
 
-    def open(self, mrl, caps = None, player = None):
+    def _state_change(self, signal):
         """
-        Open mrl. The parameter 'caps' defines the needed capabilities the
-        player must have. If 'player' is given, force playback with the
-        given player.
-        """
-        cls = get_player_class(mrl = mrl, player = player, caps = caps)
-        self._open_mrl = mrl
-        self._open_caps = caps
-
-        if not cls:
-            raise PlayerError("No supported player found to play %s", mrl)
-
-        if self._player != None:
-            running = self.get_state() != STATE_IDLE
-            self._player.stop()
-            if isinstance(self._player, cls):
-                return self._player.open(mrl)
-
-            # Continue open once our current player is dead.  We want to wait
-            # before spawning the new one so that it releases the audio
-            # device.
-            if running:
-                self._player.signals["quit"].connect_once(self._open, mrl, cls)
-                self._player.die()
+        The used player changed its state and emited a signal. This function
+        will emit the same signal to the application, handles some internal
+        changes and will call the pending calls based on the new state.
+        """
+        if signal == 'failed':
+            # The playing has failed. This means that the player we wanted to
+            # use was unable to play this file. In that case we add the player
+            # the list of of failed_player and try to find a better one.
+            # TODO: What happens if the user tries to open a new file while
+            # we are trying to find a good player for the old mrl?
+            self._failed_player.append(self.get_player_id())
+            self._pending = []
+            self._player.release()
+            cls = get_player_class(mrl = self._open_mrl, caps = 
self._open_caps,
+                                   exclude = self._failed_player)
+            if cls:
+                # a new possible player is found, try it
+                self._create_player(cls)
+                self._open(self._open_mrl)
+                self.play()
                 return
+            
+        if signal in self.signals:
+            # signal the change
+            self.signals[signal].emit()
+
+        if signal in ('end', 'failed') and self.get_state() == STATE_IDLE \
+               and not self._pending:
+            # no new mrl to play, release player
+            log.info('release player')
+            return self._player.release()
+
+        if signal == 'release':
+            # Player released the video and audio device. Right now we set
+            # self._player to None to simulate STATE_NOT_RUNNING.
+            # This needs to be fixed.
+            self._player = None
+
+        # Handle pending calls based on the new state. The variable blocked is
+        # used to avoid calling this function recursive.
+        if self._blocked:
+            return
+        self._blocked = True
+        while self._pending and self.get_state() in self._pending[0][0]:
+            self._pending.pop(0)[1]()
+        self._blocked = False
 
-        return self._open(mrl, cls)
 
-
-    def _open(self, mrl, cls):
+    @required_states(STATE_NOT_RUNNING)
+    def _create_player(self, cls):
         """
-        The real open function called from 'open'.
+        Create a player based on cls.
         """
         self._player = cls()
-
         for sig in self.signals:
             if sig in self._player.signals and \
-                   not sig in ('start', 'failed', 'open'):
+                   not sig in ('start', 'failed', 'end'):
                 self._player.signals[sig].connect_weak(self.signals[sig].emit)
+        for sig in ('start', 'end', 'release', 'failed'):
+            self._player.signals[sig].connect_weak(self._state_change, sig)
 
+    
+    @required_states(STATE_IDLE)
+    def _open(self, mrl):
+        """
+        The real open function called from 'open'.
+        """
+        log.info('open')
         self._player.open(mrl)
         self._player.set_window(self._window)
         self._player.set_size(self._size)
         self.signals['open'].emit()
 
 
-    @kaa.notifier.yield_execution()
-    def play(self, __player_list=None, **kwargs):
+    # Player API
+
+    def open(self, mrl, caps = None, player = None):
         """
-        Play the opened mrl with **kwargs. This function may return an
-        InProgress object which will be finished once the playing is
-        started or failed to start.
+        Open mrl. The parameter 'caps' defines the needed capabilities the
+        player must have. If 'player' is given, force playback with the
+        given player.
         """
-        if self.get_state() in (STATE_PLAYING, STATE_PAUSED):
-            self._player.play(**kwargs)
+        cls = get_player_class(mrl = mrl, player = player, caps = caps)
+        self._open_mrl = mrl
+        self._open_caps = caps
+        
+        if not cls:
+            raise PlayerError("No supported player found to play %s", mrl)
 
+        self._pending = []
+        self._failed_player = []
         if not self._player:
-            raise PlayerError, "play called before open"
-            yield False
+            self._create_player(cls)
+        else:
+            self._player.stop()
+            if not isinstance(self._player, cls):
+                self._player.release()
+                self._create_player(cls)
+        self._open(mrl)
 
-        if self._open in self._player.signals["quit"]:
-            # wait for old player to die
-            block = kaa.notifier.InProgress()
-            self.signals['open'].connect_once(block.finished, True)
-            yield block
-
-        state = self._player.get_state()
-        self._player.play(**kwargs)
-        if state == self._player.get_state() or \
-               self._player.get_state() != STATE_OPENING:
-            yield True
-
-        # wait for 'start' or 'failed'
-        block = kaa.notifier.InProgress()
-        self._player.signals['failed'].connect_once(block.finished, False)
-        self._player.signals['start'].connect_once(block.finished, True)
-        yield block
-        self._player.signals['failed'].disconnect(block.finished)
-        self._player.signals['start'].disconnect(block.finished)
-
-        if not block():
-            # failed, try more player
-            if __player_list is None:
-                # FIXME: only try player with needed caps
-                __player_list = get_all_players()
-            if self._player._player_id in __player_list:
-                __player_list.remove(self._player._player_id)
-            if not __player_list:
-                # no more player to try
-                self.signals['failed'].emit()
-                yield False
-            # try next
-            log.warning('unable to play with %s, try %s',
-                        self._player._player_id, __player_list[0])
-            self.open(self._open_mrl, self._open_caps, player=__player_list[0])
-            sync = self.play(__player_list, **kwargs)
-            # wait for the recursive call to return
-            yield sync
-            # now the recursive call is finished. We return the result to 
signal
-            # if playing is started (True) or failed (False).
-            status = sync()
-            yield status
-        # playing
-        self.signals['start'].emit()
-        yield True
 
+    @required_states(STATE_IDLE, STATE_PLAYING, STATE_PAUSED)
+    def play(self):
+        if self.get_state() in (STATE_PLAYING, STATE_PAUSED):
+            # called to toggle play/pause
+            log.info('resume playback')
+            self._player.resume()
+        else:
+            log.info('start playback')
+            self._player.play()
 
-    # Player API
 
+    @required_states(STATE_PLAYING, STATE_PAUSED)
     def stop(self):
         """
         Stop playback.
         """
-        if self._player:
-            self._player.stop()
+        # FIXME: handle player that are in a deadlock and do not
+        # want to be killed.
+        self._player.stop()
 
 
+    @required_states(STATE_PLAYING, STATE_PAUSED)
     def pause(self):
         """
         Pause playback.
         """
-        if self._player:
-            self._player.pause()
+        self._player.pause()
 
 
+    @required_states(STATE_PLAYING, STATE_PAUSED)
+    def resume(self):
+        """
+        Resume playback.
+        """
+        self._player.resume()
+
+
+    @required_states(STATE_PLAYING, STATE_PAUSED)
     def pause_toggle(self):
         """
         Toggle play / pause.
@@ -211,31 +259,31 @@
         if state == STATE_PLAYING:
             self._player.pause()
         if state == STATE_PAUSED:
-            self._player.play()
+            self._player.resume()
 
 
+    @required_states(STATE_IDLE, STATE_PLAYING, STATE_PAUSED)
     def seek_relative(self, offset):
         """
         Seek relative.
         """
-        if self._player:
-            self._player.seek_relative(offset)
+        self._player.seek_relative(offset)
 
 
+    @required_states(STATE_IDLE, STATE_PLAYING, STATE_PAUSED)
     def seek_absolute(self, position):
         """
         Seek absolute.
         """
-        if self._player:
-            self._player.seek_absolute(position)
+        self._player.seek_absolute(position)
 
 
+    @required_states(STATE_IDLE, STATE_PLAYING, STATE_PAUSED)
     def seek_percentage(self, percent):
         """
         Seek percentage.
         """
-        if self._player:
-            self._player.seek_percent(position)
+        self._player.seek_percent(position)
 
 
     def get_position(self):
@@ -301,7 +349,9 @@
         Get state of the player. Note: STATE_NOT_RUNNING is for internal use.
         This function will return STATE_IDLE if the player is not running.
         """
-        if self._player and self._player.get_state() != STATE_NOT_RUNNING:
+        if not self._player:
+            return STATE_NOT_RUNNING
+        if self._player.get_state() != STATE_NOT_RUNNING:
             return self._player.get_state()
         return STATE_IDLE
 

Modified: trunk/WIP/player/src/ptypes.py
==============================================================================
--- trunk/WIP/player/src/ptypes.py      (original)
+++ trunk/WIP/player/src/ptypes.py      Sun Aug 20 11:04:27 2006
@@ -38,9 +38,9 @@
 CAP_DEINTERLACE = 9
 CAP_CANVAS = 10
 
-STATE_NOT_RUNNING = 0
-STATE_IDLE = 1
-STATE_OPENING = 2
-STATE_PLAYING = 3
-STATE_PAUSED = 4
-
+STATE_NOT_RUNNING = 'STATE_NOT_RUNNING'
+STATE_IDLE = 'STATE_IDLE'
+STATE_OPENING = 'STATE_OPENING'
+STATE_PLAYING = 'STATE_PLAYING'
+STATE_PAUSED = 'STATE_PAUSED'
+STATE_SHUTDOWN = 'STATE_SHUTDOWN'

Modified: trunk/WIP/player/test/play.py
==============================================================================
--- trunk/WIP/player/test/play.py       (original)
+++ trunk/WIP/player/test/play.py       Sun Aug 20 11:04:27 2006
@@ -1,8 +1,13 @@
 import sys
+import logging
 
 import kaa
 import kaa.display
 import kaa.player
+import kaa.input.stdin
+
+logging.getLogger('player').setLevel(logging.INFO)
+
 
 def print_msg(msg):
     print '>', msg
@@ -11,7 +16,16 @@
     print 'play with', id
     player.open(sys.argv[1], player=id)
     player.play()
-    
+
+def handle_key(key, player):
+    if key in ("space", "enter"):
+        player.pause_toggle()
+    elif key == "q":
+        player.stop()
+    elif key == "f" and player.get_window():
+        win = player.get_window()
+        win.set_fullscreen(not win.get_fullscreen())
+
 window = kaa.display.X11Window(size = (800,600), title = "kaa.player")
 
 player = kaa.player.Player(window)
@@ -20,7 +34,10 @@
 player.signals["end"].connect(print_msg, 'playback end')
 player.signals["failed"].connect(print_msg, 'playback failed')
 
+kaa.signals["stdin_key_press_event"].connect(handle_key, player)
+if player.get_window():
+    player.get_window().signals["key_press_event"].connect(handle_key, player)
 
-kaa.notifier.OneShotTimer(next, 'gstreamer').start(0)
+kaa.notifier.OneShotTimer(next, 'xine').start(0)
 
 kaa.main()

Modified: trunk/WIP/player/test/test_backends.py
==============================================================================
--- trunk/WIP/player/test/test_backends.py      (original)
+++ trunk/WIP/player/test/test_backends.py      Sun Aug 20 11:04:27 2006
@@ -1,9 +1,12 @@
 import sys
+import logging
 
 import kaa
 import kaa.display
 import kaa.player
 
+logging.getLogger('player.child').setLevel(logging.INFO)
+
 def print_msg(msg):
     print '>', msg
 
@@ -20,11 +23,9 @@
 player.signals["end"].connect(print_msg, 'playback end')
 player.signals["failed"].connect(print_msg, 'playback failed')
 
-
 kaa.notifier.OneShotTimer(next, 'xine').start(0)
 kaa.notifier.OneShotTimer(next, 'gstreamer').start(5)
 kaa.notifier.OneShotTimer(next, 'mplayer').start(10)
-
 kaa.notifier.OneShotTimer(next, 'xine').start(15)
 kaa.notifier.OneShotTimer(next, 'xine').start(20)
 kaa.notifier.OneShotTimer(next, 'gstreamer').start(25)

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to