7b53c3dc9e600dd52774360c5a474e30d480841f
[zukebox] / zukebox_render / src / services / gst_renderer / gst_renderer.py
1
2 import pygst
3 import time
4 pygst.require('0.10')
5 import gst
6
7 from brisa.core import log
8 from brisa.utils.looping_call import LoopingCall
9
10
11 class GSTRenderer(object):
12
13     def __init__(self):
14         self.build_pipeline()
15         self.__av_uri = None
16         self.time_format = gst.Format(gst.FORMAT_TIME)
17         self.player_state = 0
18         loop = LoopingCall(self.poll_bus)
19         loop.start(0.2, True)
20
21     def poll_bus(self):
22         if self.bus:
23             message = self.bus.poll(gst.MESSAGE_ERROR|gst.MESSAGE_EOS,
24                                     timeout=1)
25             if message:
26                 self.on_message(self.bus, message)
27
28     def get_state(self):
29         if self.player_state == 0:
30             return 'STOPPED'
31         if self.player_state == 1:
32             return 'PLAYING'
33         if self.player_state == 2:
34             return 'PAUSED_PLAYBACK'
35
36     def __set_uri(self, uri):
37         self.player.set_property('uri', uri)
38         self.__av_uri = uri
39
40     def __get_uri(self):
41         return self.__av_uri
42
43     av_uri = property(__get_uri, __set_uri)
44
45     def build_pipeline(self):
46         self.player = gst.element_factory_make("playbin", "player")
47         self.bus = self.player.get_bus()
48         self.player.set_state(gst.STATE_READY)
49
50     def on_message(self, bus, message):
51         t = message.type
52         if t == gst.MESSAGE_EOS:
53             self.player.set_state(gst.STATE_NULL)
54             self.player_state = 0
55         elif t == gst.MESSAGE_ERROR:
56             self.player.set_state(gst.STATE_NULL)
57             self.player_state = 0
58
59     def play(self):
60         if self.av_uri is not None:
61             if (self.player.set_state(gst.STATE_PLAYING) ==
62                 gst.STATE_CHANGE_FAILURE):
63                 log.error("error trying to play %s.", self.av_uri)
64             self.player_state = 1
65         else:
66             log.info("av_uri is None, unable to play.")
67
68     def stop(self):
69         if self.player.set_state(gst.STATE_READY) == gst.STATE_CHANGE_FAILURE:
70             log.error("error while stopping the player")
71         self.player_state = 0
72
73     def pause(self):
74         if self.player.set_state(gst.STATE_PAUSED) == gst.STATE_CHANGE_FAILURE:
75             log.error("error while pausing the player")
76         self.player_state = 2
77
78     def seek(self, unit, target):
79         if unit == "ABS_TIME":
80             target_time = self.convert_int(target)
81             self.player.seek_simple(self.time_format, gst.SEEK_FLAG_FLUSH,
82                                     target_time)
83
84         if unit == "REL_TIME":
85             target_time = self.convert_int(target)
86             cur_pos = self.query_position()[1]
87             self.player.seek_simple(self.time_format, gst.SEEK_FLAG_FLUSH,
88                                     target_time+cur_pos)
89
90         if unit == "ABS_COUNT":
91             self.player.seek_simple(self.time_format, gst.SEEK_FLAG_FLUSH,
92                                     target)
93
94         if unit == "REL_COUNT":
95             cur_pos = self.query_position()[1]
96             self.player.seek_simple(self.time_format, gst.SEEK_FLAG_FLUSH,
97                                     target + cur_pos)
98
99     def set_volume(self, volume):
100         self.player.set_property("volume", volume/10)
101
102     def get_volume(self):
103         return int(self.player.get_property("volume")*10)
104
105     def query_duration(self):
106         time.sleep(0.3)
107         try:
108             dur_int = self.player.query_duration(self.time_format, None)[0]
109             dur_str = self.convert_ns(dur_int)
110         except gst.QueryError:
111             dur_int = -1
112             dur_str = ''
113
114         return dur_str, dur_int
115
116     def query_position(self):
117         try:
118             pos_int = self.player.query_position(self.time_format, None)[0]
119             pos_str = self.convert_ns(pos_int)
120         except gst.QueryError:
121             pos_int = -1
122             pos_str = ''
123
124         return pos_str, pos_int
125
126     def convert_ns(self, time):
127         hours, left_time = divmod(time/1000000000, 3600)
128         minutes, left_time = divmod(left_time, 60)
129         return '%02d:%02d:%02d' % (hours, minutes, left_time)
130
131     def convert_int(self, time_str):
132         time_str = time_str.strip('")( ')
133         (hours, min, sec) = time_str.split(":")
134         time_int = int(hours) * 3600 + int(min) * 60 + int(sec)
135         time_int = time_int * 1000000000
136         return time_int
137