1
##########################################################################
2
# Copyright 2009 Carlos Ribeiro
4
# This file is part of Radio Tray
6
# Radio Tray 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 1 of the License, or
9
# (at your option) any later version.
11
# Radio Tray 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 Radio Tray. If not, see <http://www.gnu.org/licenses/>.
19
##########################################################################
26
ORG_MPRIS_MEDIAPLAYER2="org.mpris.MediaPlayer2"
27
ORG_MPRIS_MEDIAPLAYER2_PLAYER="org.mpris.MediaPlayer2.Player"
28
ORG_MPRIS_MEDIAPLAYER2_TRACKLIST="org.mpris.MediaPlayer2.TrackList"
29
class Mpris2Adapter(dbus.service.Object):
30
""" interface defined by org.mpris.MediaPlayer2"""
31
def __init__(self, provider, mediator, bus):
33
dbus.service.Object.__init__(self, bus, '/org/mpris/MediaPlayer2')
38
def populate(self, interface, *prop_names):
41
props[p] = getattr(self, p)()
42
self.PropertiesChanged(interface, props, [])
44
@dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v')
45
def Get(self, interface, prop):
46
logger.info('dbus get prop: ' + prop)
47
if hasattr(self, prop):
48
result = getattr(self, prop)()
52
@dbus.service.signal(dbus.PROPERTIES_IFACE, signature='sa{sv}as')
53
def PropertiesChanged(self, interface, updated, invalid):
57
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2)
59
self.exaile.gui.main.toggle_visible(True)
61
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2)
71
def HasTrackList(self):
77
def DesktopEntry(self):
80
def SupportedUriSchemes(self):
82
return ['http', 'https', 'file']
84
def SupportedMimeTypes(self):
86
return ['audio/mpeg', 'application/ogg']
88
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER)
90
self.exaile.queue.next()
92
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER)
94
self.exaile.queue.prev()
96
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER)
98
self.exaile.player.pause()
100
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER)
102
if self.exaile.player.is_stopped():
103
self.exaile.queue.play()
105
self.exaile.player.toggle_pause()
107
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER)
109
self.exaile.player.stop()
111
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER)
113
self.exaile.queue.play()
115
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER, in_signature='x')
116
def Seek(self, offset):
117
self.exaile.player.seek(offset)
119
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER, in_signature='ox')
120
def SetPosition(self, track_id, position):
123
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_PLAYER, in_signature='s')
124
def OpenUri(self, uri):
127
def PlaybackStatus(self):
128
if self.exaile.player.is_playing():
130
elif self.exaile.player.is_paused():
135
def LoopStatus(self):
136
playlist = self.exaile.queue.current_playlist
137
if playlist.repeat_enabled:
138
if playlist.repeat_mode == 'playlist':
150
current_track = self.exaile.player.current
151
if current_track is not None:
152
return self._get_metadata(current_track)
162
def MinimumRate(self):
165
def MaximumRate(self):
169
track = self.exaile.player.current
170
playlist = self.exaile.queue.current_playlist
171
return not ((len(playlist)-1) == playlist.index(track))
173
def CanGoPrevious(self):
174
track = self.exaile.player.current
175
playlist = self.exaile.queue.current_playlist
176
return not (playlist.index(track) == 0)
179
return not self.exaile.player.is_playing()
182
return self.exaile.player.is_playing()
187
def CanControl(self):
191
return settings.get_option('playback/shuffle', False)
193
def GetTracksMetadata(self, track_ids):
196
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_TRACKLIST, in_signature='sob')
197
def AddTrack(self, uri, after_track, set_as_current):
200
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_TRACKLIST, in_signature='o')
201
def RemoveTrack(self, trackId):
204
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_TRACKLIST, in_signature='o')
205
def Goto(self, trackId):
208
@dbus.service.method(ORG_MPRIS_MEDIAPLAYER2_TRACKLIST, out_signature='ao')
212
def CanEditTracks(self):
216
def _get_metadata(self, track):
217
## mpris2.0 meta map, defined at http://xmms2.org/wiki/MPRIS_Metadata
220
title = track.get_tag_raw('title')[0] if track.get_tag_raw('title') else ""
221
meta['xesam:title'] = unicode(title)
222
album = track.get_tag_raw('album')[0] if track.get_tag_raw('album') else ""
223
meta['xesam:album'] = unicode(album)
224
artist = track.get_tag_raw('artist')[0] if track.get_tag_raw('artist') else ""
225
meta['xesam:artist'] = dbus.types.Array([unicode(artist)], signature='s')
227
meta['mpris:length'] = dbus.types.Int64(int(track.get_tag_raw('__length') or 0)*1000)
229
## this is a workaround, write data to a tmp file and return name
230
cover_temp = self._get_cover_url(track)
231
if cover_temp is not None:
232
meta['mpris:artUrl'] = cover_temp
234
meta['mpris:trackid'] = track.get_tag_raw('__loc')
235
meta['xesam:url'] = track.get_tag_raw('__loc')
237
return dbus.types.Dictionary(meta, signature='sv', variant_level=1)
239
def _get_cover_url(self, track):
240
trackid = track.get_tag_raw('__loc')
241
if trackid not in self.cover_cache:
242
cover_data = cover_manager.get_cover(track)
243
if cover_data is not None:
244
cover_temp = tempfile.NamedTemporaryFile(prefix='exaile-soundmenu', delete=False)
245
cover_temp.write(cover_data)
247
self.cover_cache[trackid] = "file://"+cover_temp.name
250
return self.cover_cache[trackid]