3
# =============================================================================
5
# Remuco - A remote control system for media players.
6
# Copyright (C) 2006-2009 Oben Sonne <obensonne@googlemail.com>
8
# This file is part of Remuco.
10
# Remuco is free software: you can redistribute it and/or modify
11
# it under the terms of the GNU General Public License as published by
12
# the Free Software Foundation, either version 3 of the License, or
13
# (at your option) any later version.
15
# Remuco is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
# GNU General Public License for more details.
20
# You should have received a copy of the GNU General Public License
21
# along with Remuco. If not, see <http://www.gnu.org/licenses/>.
23
# =============================================================================
25
"""Remuco player adapter for Audacious, implemented as an executable script."""
28
from dbus.exceptions import DBusException
32
from remuco import log
34
# =============================================================================
36
# =============================================================================
38
IA_JUMP = remuco.ItemAction("Jump to")
39
PLAYLIST_ACTIONS = (IA_JUMP,)
41
# =============================================================================
43
# =============================================================================
45
class AudaciousAdapter(remuco.MPRISAdapter):
49
remuco.MPRISAdapter.__init__(self, "audacious", "Audacious",
50
mime_types=("audio",),
51
extra_playlist_actions=PLAYLIST_ACTIONS)
54
self.__poll_for_repeat_and_shuffle = False
58
remuco.MPRISAdapter.start(self)
61
bus = dbus.SessionBus()
62
proxy = bus.get_object("org.atheme.audacious", "/org/atheme/audacious")
63
self.__ad = dbus.Interface(proxy, "org.atheme.audacious")
64
except DBusException, e:
65
raise StandardError("dbus error: %s" % e)
69
remuco.MPRISAdapter.stop(self)
75
remuco.MPRISAdapter.poll(self)
77
if self.__poll_for_repeat_and_shuffle:
81
def __poll_repeat(self):
83
# used if audacious still does not provide this by signal "StatusChange"
86
repeat = bool(self.__ad.Repeat())
87
except DBusException, e:
88
log.warning("dbus error: %s" % e)
92
self.update_repeat(repeat)
94
def __poll_shuffle(self):
96
# used if audacious still does not provide this by signal "StatusChange"
99
shuffle = bool(self.__ad.Shuffle())
100
except DBusException, e:
101
log.warning("dbus error: %s" % e)
104
self._shuffle = shuffle
105
self.update_shuffle(shuffle)
107
# =========================================================================
109
# =========================================================================
111
def ctrl_toggle_repeat(self):
113
# audacious uses wrong method name for setting repeat mode
116
self._mp_t.Loop(not self._repeat,
117
reply_handler=self._dbus_ignore,
118
error_handler=self._dbus_error)
119
except DBusException, e:
120
log.warning("dbus error: %s" % e)
122
if self.__poll_for_repeat_and_shuffle:
125
def ctrl_toggle_shuffle(self):
127
# audacious uses wrong method name for setting shuffle mode
130
self._mp_t.Random(not self._shuffle,
131
reply_handler=self._dbus_ignore,
132
error_handler=self._dbus_error)
133
except DBusException, e:
134
log.warning("dbus error: %s" % e)
136
if self.__poll_for_repeat_and_shuffle:
137
self.__poll_shuffle()
139
# =========================================================================
141
# =========================================================================
143
def action_playlist_item(self, action_id, positions, ids):
145
if action_id == IA_JUMP.id:
148
self.__ad.Jump(positions[0],
149
reply_handler=self._dbus_ignore,
150
error_handler=self._dbus_error)
151
except DBusException, e:
152
log.warning("dbus error: %s" % e)
155
remuco.MPRISAdapter.action_playlist_item(self, action_id,
159
# =========================================================================
160
# internal methods which must be adapted to provide MPRIS conformity
161
# =========================================================================
163
def _notify_status(self, status):
165
if isinstance(status, int):
166
# audacious only provides playback status here
167
self.__poll_for_repeat_and_shuffle = True
168
status = (status, self._shuffle, self._repeat, self._repeat)
170
# it looks like audacious has fixed its MPRIS interface
171
self.__poll_for_repeat_and_shuffle = False
173
remuco.MPRISAdapter._notify_status(self, status)
175
def _notify_track(self, track):
177
# audacious provides length in 'length', not in 'time' or 'mtime'
178
if "length" in track and not "mtime" in track:
179
track["mtime"] = track["length"]
181
# audacious provides length in 'URI', not in 'location'
183
track["location"] = track["URI"]
185
remuco.MPRISAdapter._notify_track(self, track)
187
# =============================================================================
189
# =============================================================================
191
if __name__ == '__main__':
193
pa = AudaciousAdapter()
194
mg = remuco.Manager(pa, player_dbus_name="org.mpris.audacious")