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
25 from panucci
.backends
import base
28 from panucci
.settings
import settings
29 from panucci
import util
31 class GstBasePlayer(base
.BasePlayer
):
32 """ A player that uses Gstreamer for playback """
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
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
):
52 pos_int
= self
._player
.query_position(self
._time
_format
,None)[0]
53 dur_int
= self
._player
.query_duration(self
._time
_format
,None)[0]
55 self
.__log
.exception('Error getting position...')
58 return pos_int
, dur_int
61 if self
._player
is None:
62 return self
.STATE_NULL
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
)
71 pos
, dur
= self
.get_position_duration()
72 self
.notify('paused', pos
, dur
, caller
=self
.pause
)
73 self
._player
.set_state(gst
.STATE_PAUSED
)
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
)
83 # should something happen here? perhaps self.stop()?
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
)
94 def _seek(self
, position
):
99 self
._player
.seek_simple(
100 self
._time
_format
, gst
.SEEK_FLAG_FLUSH
, position
)
102 self
.__log
.exception( 'Error seeking' )
108 def _set_volume_level(self
, level
):
109 assert 0 <= level
<= 1
111 if util
.platform
.FREMANTLE
:
112 # No volume setting on Fremantle
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
)
129 def _setup_player(self
, filetype
=None):
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
):
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
)