Clean up platform detection code
[panucci.git] / src / panucci / backends / gstbase.py
blob016f4f6f3540dca1459b37a210d8c2e20590281b
1 #!/usr/bin/env python
3 # This file is part of Panucci.
4 # Copyright (c) 2008-2010 The Panucci Audiobook and Podcast Player Project
6 # Panucci is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # Panucci is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Panucci. If not, see <http://www.gnu.org/licenses/>.
20 from __future__ import absolute_import
22 import gst
23 import logging
25 from panucci.backends import base
27 import panucci
28 from panucci.settings import settings
29 from panucci import util
31 class GstBasePlayer(base.BasePlayer):
32 """ A player that uses Gstreamer for playback """
34 def __init__(self):
35 base.BasePlayer.__init__(self)
36 self.__log = logging.getLogger('panucci.backends.GstPlayer')
38 # have we preformed the initial seek?
39 self.__initial_seek_completed = False
41 self._player = None
42 self._filesrc = None
43 self._filesrc_property = None
44 self._volume_control = None
45 self._volume_multiplier = 1
46 self._volume_property = None
47 self._time_format = gst.Format(gst.FORMAT_TIME)
48 self._current_filetype = None
50 def _get_position_duration(self):
51 try:
52 pos_int = self._player.query_position(self._time_format,None)[0]
53 dur_int = self._player.query_duration(self._time_format,None)[0]
54 except Exception, e:
55 self.__log.exception('Error getting position...')
56 pos_int = dur_int = 0
58 return pos_int, dur_int
60 def get_state(self):
61 if self._player is None:
62 return self.STATE_NULL
63 else:
64 state = self._player.get_state()[1]
65 return { gst.STATE_NULL : self.STATE_STOPPED,
66 gst.STATE_PAUSED : self.STATE_PAUSED,
67 gst.STATE_PLAYING : self.STATE_PLAYING
68 }.get( state, self.STATE_NULL )
70 def pause(self):
71 pos, dur = self.get_position_duration()
72 self.notify('paused', pos, dur, caller=self.pause)
73 self._player.set_state(gst.STATE_PAUSED)
74 return pos
76 def play(self):
77 have_player = self._player is not None
78 if have_player or self.__setup_player():
79 self._initial_seek_completed = have_player
80 self._player.set_state(gst.STATE_PLAYING)
81 return True
82 else:
83 # should something happen here? perhaps self.stop()?
84 return False
86 def stop(self):
87 self.notify('stopped', caller=self.stop)
89 if self._player is not None:
90 position, duration = self.get_position_duration()
91 self._player.set_state(gst.STATE_NULL)
92 self._player = None
94 def _seek(self, position):
95 self.seeking = True
96 error = False
98 try:
99 self._player.seek_simple(
100 self._time_format, gst.SEEK_FLAG_FLUSH, position )
101 except Exception, e:
102 self.__log.exception( 'Error seeking' )
103 error = True
105 self.seeking = False
106 return not error
108 def _set_volume_level(self, level):
109 assert 0 <= level <= 1
111 if util.platform.FREMANTLE:
112 # No volume setting on Fremantle
113 return
115 if self._volume_control is not None:
116 vol = level * self._volume_multiplier
117 self._volume_control.set_property( self._volume_property, vol )
119 def __setup_player(self):
120 if self._setup_player(self._current_filetype):
121 bus = self._player.get_bus()
122 bus.add_signal_watch()
123 bus.connect('message', self.__on_message)
124 self._set_volume_level( settings.volume )
125 return True
127 return False
129 def _setup_player(self, filetype=None):
130 pass
132 def _on_decoder_pad_added(self, decoder, src_pad, sink_pad):
133 # link the decoder's new "src_pad" to "sink_pad"
134 src_pad.link( sink_pad )
136 def load_media( self, uri ):
137 filetype = util.detect_filetype(uri)
139 if filetype != self._current_filetype or self._player is None:
140 self.__setup_player()
142 if self._player is not None:
143 self._filesrc.set_property( self._filesrc_property, uri )
145 self._current_filetype = filetype
147 def __on_message(self, bus, message):
148 t = message.type
149 # self.__log.debug('Got message of type %s', t)
151 if t == gst.MESSAGE_EOS:
152 self.notify( "eof", caller=self.__on_message )
154 elif t == gst.MESSAGE_ERROR:
155 err, debug = message.parse_error()
156 self.__log.critical( 'Error: %s %s', err, debug )
157 self.notify( "error", debug, caller=self.__on_message )
159 elif t == gst.MESSAGE_STATE_CHANGED:
160 if ( message.src == self._player and
161 message.structure['new-state'] == gst.STATE_PLAYING ):
163 self.notify('playing', caller=self.__on_message)