Back to development
[platform/upstream/gstreamer.git] / subprojects / gst-python / old_examples / segments.py
1 #! /usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # Segments.py
5 # Copyright (C) 2006 Artem Popov <artfwo@gmail.com>
6 #
7 # This example demonstrates segment seeking
8 # and seamless looping within playbin.
9
10 import pygst
11 pygst.require ("0.10")
12 import gst
13
14 import pygtk
15 pygtk.require ("2.0")
16 import gobject
17
18 class Looper (gobject.GObject):
19         __gproperties__ = {
20                 "loop": (gobject.TYPE_BOOLEAN,
21                         "loop",
22                         "Whether to loop the segment",
23                         False,
24                         gobject.PARAM_READWRITE),
25                 "start-pos": (gobject.TYPE_UINT64,
26                         "start position",
27                         "The segment start marker",
28                         0,
29                         0xfffffffffffffff, # max long possible
30                         0,
31                         gobject.PARAM_READWRITE),
32                 "stop-pos": (gobject.TYPE_UINT64,
33                         "stop position",
34                         "The segment stop marker",
35                         0,
36                         0xfffffffffffffff, # max long possible
37                         0,
38                         gobject.PARAM_READWRITE),
39         } # __gproperties__
40         
41         __gsignals__ = {
42                 "stopped": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
43                 "position-updated": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_FLOAT,)),
44                 "error": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
45         } # __gsignals__
46         
47         def __init__ (self, location = None):
48                 gobject.GObject.__init__ (self)
49                 
50                 self.__playbin = gst.element_factory_make ("playbin")
51                 self.__playbin.props.video_sink = gst.element_factory_make ("fakesink")
52                 
53                 bus = self.__playbin.get_bus ()
54                 bus.add_watch (self.__on_bus_message)
55                 
56                 self.__loop = False
57                 self.__start_pos = 0
58                 self.__stop_pos = 0
59                 
60                 self.__timeout_id = 0
61                 
62                 if location:
63                         self.load (location)
64         
65         def load (self, location):
66                 self.__playbin.props.uri = location
67                 self.__start_position = 0
68                 self.__stop_position = 0
69         
70         def set_segment (self, start, stop):
71                 self.props.start_pos = start
72                 self.props.stop_pos = stop
73         
74         def play (self):
75                 if not (self.__start_pos or self.__stop_pos):
76                         raise RuntimeError, "Cannot start playback, segment was not set!"
77                 
78                 self.__playbin.set_state (gst.STATE_PLAYING)
79         
80         def stop (self, silent = False):
81                 self.__playbin.set_state (gst.STATE_NULL)
82                 if not silent:
83                         self.emit ("stopped")
84         
85         def do_get_property (self, property):
86                 if property.name == "loop":
87                         return self.__loop
88                 elif property.name == "start-pos":
89                         return self.__start_pos
90                 elif property.name == "stop-pos":
91                         return self.__stop_pos
92                 else:
93                         raise AttributeError, "Unknown property %s" % property.name
94         
95         def do_set_property (self, property, value):
96                 if property.name == "loop":
97                         self.__loop = value
98                 elif property.name == "start-pos":
99                         self.__start_pos = value
100                 elif property.name == "stop-pos":
101                         self.__stop_pos = value
102                 else:
103                         raise AttributeError, "Unknown property %s" % property.name
104         
105         def do_stopped (self):
106                 if self.__timeout_id:
107                         gobject.source_remove (self.__timeout_id)
108                         self.__timeout_id = 0
109         
110         def __seek (self, start, stop, flush):
111                 flags = gst.SEEK_FLAG_SEGMENT | gst.SEEK_FLAG_ACCURATE
112                 if flush:
113                         flags = flags | gst.SEEK_FLAG_FLUSH
114                 self.__playbin.seek (1.0, gst.FORMAT_TIME, flags,
115                         gst.SEEK_TYPE_SET, start,
116                         gst.SEEK_TYPE_SET, stop)
117         
118         def __on_timeout (self):
119                 position = self.__playbin.query_position (gst.FORMAT_TIME) [0]
120                 self.emit ("position-updated", float (position))
121                 return True
122         
123         def __on_bus_message (self, bus, message):
124                 if message.type == gst.MESSAGE_ERROR:
125                         error, debug = message.parse_error ()
126                         self.stop () # this looks neccessary here
127                         self.emit ("error", (error, debug))
128                 
129                 elif message.type == gst.MESSAGE_NEW_CLOCK:
130                         # we connect the timeout handler here to be sure that further queries succeed
131                         interval = int ((self.__stop_position - self.__start_position) / (2 * gst.SECOND) + 50)
132                         self.__timeout_id = gobject.timeout_add (interval, self.__on_timeout)
133                 
134                 elif message.type == gst.MESSAGE_STATE_CHANGED:
135                         old_state, new_state, pending = message.parse_state_changed ()
136                         if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED and message.src == self.__playbin:
137                                 self.__seek (self.__start_pos, self.__stop_pos, True)
138                 
139                 elif message.type == gst.MESSAGE_SEGMENT_DONE:
140                         if self.__loop:
141                                 self.__seek (self.__start_pos, self.__stop_pos, False)
142                         else:
143                                 src = self.__playbin.get_property ("source")
144                                 pad = src.get_pad ('src')
145                                 pad.push_event (gst.event_new_eos ())
146                                 
147                                 # this is the good old way:
148                                 #
149                                 # pads = src.src_pads ()
150                                 # while True:
151                                 #       try:
152                                 #               pad = pads.next ()
153                                 #               pad.push_event (gst.event_new_eos ())
154                                 #       except:
155                                 #               break
156                 
157                 elif message.type == gst.MESSAGE_EOS:
158                         self.stop ()
159                 
160                 return True
161
162 mainloop = gobject.MainLoop ()
163
164 def on_looper_stopped (looper):
165         mainloop.quit ()
166
167 def on_looper_pos_updated (looper, position):
168         print round (position / gst.SECOND, 2)
169
170 def on_looper_error (looper, error_tuple):
171         error, debug = error_tuple
172         print "\n\n%s\n\n%s\n\n" % (error, debug)
173         mainloop.quit ()
174
175 if __name__ == "__main__":
176         import sys
177         if len (sys.argv) != 5:
178                 print "Usage: %s <filename|uri> <start_seconds> <stop_seconds> <loop = 0|1>" % sys.argv [0]
179                 sys.exit (1)
180         
181         if "://" in sys.argv [1]:
182                 uri = sys.argv [1]
183         else:
184                 import os.path
185                 uri = "file://" + os.path.abspath (sys.argv [1])
186         
187         looper = Looper (uri)
188         
189         looper.props.start_pos = long (sys.argv [2]) * gst.SECOND
190         looper.props.stop_pos = long (sys.argv [3]) * gst.SECOND
191         looper.props.loop = int (sys.argv [4])
192         
193         looper.connect ("stopped", on_looper_stopped)
194         looper.connect ("position-updated", on_looper_pos_updated)
195         looper.connect ("error", on_looper_error)
196         
197         looper.play ()
198         mainloop.run ()