-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make class(es) more self-contained, reduce globals #146
base: master
Are you sure you want to change the base?
Changes from all commits
bc474c6
ccd8394
3f4d8c4
6e71969
a57828a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,6 +74,9 @@ | |
|
||
_ = gettext.gettext | ||
|
||
logger = logging.getLogger('mpDris2') | ||
logger.propagate = False | ||
|
||
identity = "Music Player Daemon" | ||
|
||
params = { | ||
|
@@ -102,8 +105,6 @@ | |
'cover_regex': r'^(album|cover|\.?folder|front).*\.(gif|jpeg|jpg|png)$', | ||
} | ||
|
||
notification = None | ||
|
||
# MPRIS allowed metadata tags | ||
allowed_tags = { | ||
'mpris:trackid': dbus.ObjectPath, | ||
|
@@ -247,7 +248,7 @@ class MPDWrapper(object): | |
errors and similar | ||
""" | ||
|
||
def __init__(self, params): | ||
def __init__(self, params, loop=None): | ||
self.client = mpd.MPDClient() | ||
|
||
self._dbus = dbus | ||
|
@@ -278,6 +279,10 @@ def __init__(self, params): | |
if self._params['mmkeys']: | ||
self.setup_mediakeys() | ||
|
||
self._loop = loop | ||
ferdnyc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Wrapper to send notifications | ||
self._notification = NotifyWrapper(self._params) | ||
|
||
def run(self): | ||
""" | ||
Try to connect to MPD; retry every 5 seconds on failure. | ||
|
@@ -320,7 +325,7 @@ def my_connect(self): | |
self._can_single = True | ||
|
||
if self._errors > 0: | ||
notification.notify(identity, _('Reconnected')) | ||
self._notification.notify(identity, _('Reconnected')) | ||
logger.info('Reconnected to MPD server.') | ||
else: | ||
logger.debug('Connected to MPD server.') | ||
|
@@ -329,7 +334,7 @@ def my_connect(self): | |
self.client._sock.settimeout(5.0) | ||
# Export our DBUS service | ||
if not self._dbus_service: | ||
self._dbus_service = MPRISInterface(self._params) | ||
self._dbus_service = MPRISInterface(self._params, mpd_wrapper=self) | ||
else: | ||
# Add our service to the session bus | ||
#self._dbus_service.add_to_connection(dbus.SessionBus(), | ||
|
@@ -371,7 +376,7 @@ def my_connect(self): | |
|
||
def reconnect(self): | ||
logger.warning("Disconnected") | ||
notification.notify(identity, _('Disconnected'), 'error') | ||
self._notification.notify(identity, _('Disconnected'), 'error') | ||
|
||
# Release the DBus name and disconnect from bus | ||
if self._dbus_service is not None: | ||
|
@@ -610,11 +615,11 @@ def notify_about_track(self, meta, state='play'): | |
uri = 'media-playback-pause-symbolic' | ||
body += ' (%s)' % _('Paused') | ||
|
||
notification.notify(title, body, uri) | ||
self._notification.notify(title, body, uri) | ||
|
||
def notify_about_state(self, state): | ||
if state == 'stop': | ||
notification.notify(identity, _('Stopped'), 'media-playback-stop-symbolic') | ||
self._notification.notify(identity, _('Stopped'), 'media-playback-stop-symbolic') | ||
else: | ||
self.notify_about_track(self.metadata, state) | ||
|
||
|
@@ -972,15 +977,18 @@ class MPRISInterface(dbus.service.Object): | |
__path = "/org/mpris/MediaPlayer2" | ||
__introspect_interface = "org.freedesktop.DBus.Introspectable" | ||
__prop_interface = dbus.PROPERTIES_IFACE | ||
__wrapper = None | ||
|
||
def __init__(self, params): | ||
def __init__(self, params, mpd_wrapper=None): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
dbus.service.Object.__init__(self, dbus.SessionBus(), | ||
MPRISInterface.__path) | ||
self._params = params or {} | ||
self._name = self._params["bus_name"] or "org.mpris.MediaPlayer2.mpd" | ||
if not self._name.startswith("org.mpris.MediaPlayer2."): | ||
logger.warn("Configured bus name %r is outside MPRIS2 namespace" % self._name) | ||
|
||
MPRISInterface.__wrapper = mpd_wrapper | ||
|
||
self._bus = dbus.SessionBus() | ||
self._uname = self._bus.get_unique_name() | ||
self._dbus_obj = self._bus.get_object("org.freedesktop.DBus", | ||
|
@@ -998,7 +1006,8 @@ def _name_owner_changed_callback(self, name, old_owner, new_owner): | |
except: | ||
pid = None | ||
logger.info("Replaced by %s (PID %s)" % (new_owner, pid or "unknown")) | ||
loop.quit() | ||
if self._loop: | ||
self._loop.quit() | ||
|
||
def acquire_name(self): | ||
self._bus_name = dbus.service.BusName(self._name, | ||
|
@@ -1022,29 +1031,29 @@ def release_name(self): | |
} | ||
|
||
def __get_playback_status(): | ||
status = mpd_wrapper.last_status() | ||
status = MPRISInterface.__wrapper.last_status() | ||
return {'play': 'Playing', 'pause': 'Paused', 'stop': 'Stopped'}[status['state']] | ||
|
||
def __set_loop_status(value): | ||
if value == "Playlist": | ||
mpd_wrapper.repeat(1) | ||
if mpd_wrapper._can_single: | ||
mpd_wrapper.single(0) | ||
MPRISInterface.__wrapper.repeat(1) | ||
if MPRISInterface.__wrapper._can_single: | ||
MPRISInterface.__wrapper.single(0) | ||
elif value == "Track": | ||
if mpd_wrapper._can_single: | ||
mpd_wrapper.repeat(1) | ||
mpd_wrapper.single(1) | ||
if MPRISInterface.__wrapper._can_single: | ||
MPRISInterface.__wrapper.repeat(1) | ||
MPRISInterface.__wrapper.single(1) | ||
elif value == "None": | ||
mpd_wrapper.repeat(0) | ||
if mpd_wrapper._can_single: | ||
mpd_wrapper.single(0) | ||
MPRISInterface.__wrapper.repeat(0) | ||
if MPRISInterface.__wrapper._can_single: | ||
MPRISInterface.__wrapper.single(0) | ||
else: | ||
raise dbus.exceptions.DBusException("Loop mode %r not supported" % | ||
value) | ||
return | ||
|
||
def __get_loop_status(): | ||
status = mpd_wrapper.last_status() | ||
status = MPRISInterface.__wrapper.last_status() | ||
if int(status['repeat']) == 1: | ||
if int(status.get('single', 0)) == 1: | ||
return "Track" | ||
|
@@ -1054,32 +1063,32 @@ def __get_loop_status(): | |
return "None" | ||
|
||
def __set_shuffle(value): | ||
mpd_wrapper.random(value) | ||
MPRISInterface.__wrapper.random(value) | ||
return | ||
|
||
def __get_shuffle(): | ||
if int(mpd_wrapper.last_status()['random']) == 1: | ||
if int(MPRISInterface.__wrapper.last_status()['random']) == 1: | ||
return True | ||
else: | ||
return False | ||
|
||
def __get_metadata(): | ||
return dbus.Dictionary(mpd_wrapper.metadata, signature='sv') | ||
return dbus.Dictionary(MPRISInterface.__wrapper.metadata, signature='sv') | ||
|
||
def __get_volume(): | ||
vol = float(mpd_wrapper.last_status().get('volume', 0)) | ||
vol = float(MPRISInterface.__wrapper.last_status().get('volume', 0)) | ||
if vol > 0: | ||
return vol / 100.0 | ||
else: | ||
return 0.0 | ||
|
||
def __set_volume(value): | ||
if value >= 0 and value <= 1: | ||
mpd_wrapper.setvol(int(value * 100)) | ||
MPRISInterface.__wrapper.setvol(int(value * 100)) | ||
return | ||
Comment on lines
1078
to
1088
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @grawity This is what I was referring to — the setters and getters aren't defined as methods of |
||
|
||
def __get_position(): | ||
status = mpd_wrapper.last_status() | ||
status = MPRISInterface.__wrapper.last_status() | ||
if 'time' in status: | ||
current, end = status['time'].split(':') | ||
return dbus.Int64((int(current) * 1000000)) | ||
|
@@ -1169,46 +1178,46 @@ def Quit(self): | |
# Player methods | ||
@dbus.service.method(__player_interface, in_signature='', out_signature='') | ||
def Next(self): | ||
mpd_wrapper.next() | ||
MPRISInterface.__wrapper.next() | ||
return | ||
Comment on lines
1178
to
1182
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @grawity I could use |
||
|
||
@dbus.service.method(__player_interface, in_signature='', out_signature='') | ||
def Previous(self): | ||
mpd_wrapper.previous() | ||
MPRISInterface.__wrapper.previous() | ||
return | ||
|
||
@dbus.service.method(__player_interface, in_signature='', out_signature='') | ||
def Pause(self): | ||
mpd_wrapper.pause(1) | ||
mpd_wrapper.notify_about_state('pause') | ||
MPRISInterface.__wrapper.pause(1) | ||
MPRISInterface.__wrapper.notify_about_state('pause') | ||
return | ||
|
||
@dbus.service.method(__player_interface, in_signature='', out_signature='') | ||
def PlayPause(self): | ||
status = mpd_wrapper.status() | ||
status = MPRISInterface.__wrapper.status() | ||
if status['state'] == 'play': | ||
mpd_wrapper.pause(1) | ||
mpd_wrapper.notify_about_state('pause') | ||
MPRISInterface.__wrapper.pause(1) | ||
MPRISInterface.__wrapper.notify_about_state('pause') | ||
else: | ||
mpd_wrapper.play() | ||
mpd_wrapper.notify_about_state('play') | ||
MPRISInterface.__wrapper.play() | ||
MPRISInterface.__wrapper.notify_about_state('play') | ||
return | ||
|
||
@dbus.service.method(__player_interface, in_signature='', out_signature='') | ||
def Stop(self): | ||
mpd_wrapper.stop() | ||
mpd_wrapper.notify_about_state('stop') | ||
MPRISInterface.__wrapper.stop() | ||
MPRISInterface.__wrapper.notify_about_state('stop') | ||
return | ||
|
||
@dbus.service.method(__player_interface, in_signature='', out_signature='') | ||
def Play(self): | ||
mpd_wrapper.play() | ||
mpd_wrapper.notify_about_state('play') | ||
MPRISInterface.__wrapper.play() | ||
MPRISInterface.__wrapper.notify_about_state('play') | ||
return | ||
|
||
@dbus.service.method(__player_interface, in_signature='x', out_signature='') | ||
def Seek(self, offset): | ||
status = mpd_wrapper.status() | ||
status = MPRISInterface.__wrapper.status() | ||
current, end = status['time'].split(':') | ||
current = int(current) | ||
end = int(end) | ||
|
@@ -1217,12 +1226,13 @@ def Seek(self, offset): | |
position = current + offset | ||
if position < 0: | ||
position = 0 | ||
mpd_wrapper.seekid(int(status['songid']), position) | ||
MPRISInterface.__wrapper.seekid(int(status['songid']), position) | ||
self.Seeked(position * 1000000) | ||
return | ||
|
||
@dbus.service.method(__player_interface, in_signature='ox', out_signature='') | ||
def SetPosition(self, trackid, position): | ||
song = MPRISInterface.__wrapper.last_currentsong() | ||
song = mpd_wrapper.last_currentsong() | ||
if not song: | ||
logger.error("Failed to retrieve song position, can't seek") | ||
|
@@ -1233,7 +1243,7 @@ def SetPosition(self, trackid, position): | |
# Convert position to seconds | ||
position = int(position) / 1000000 | ||
if position <= int(song['time']): | ||
mpd_wrapper.seekid(int(song['id']), position) | ||
MPRISInterface.__wrapper.seekid(int(song['id']), position) | ||
self.Seeked(position * 1000000) | ||
return | ||
|
||
|
@@ -1376,8 +1386,6 @@ def usage(params): | |
usage(params) | ||
sys.exit() | ||
|
||
logger = logging.getLogger('mpDris2') | ||
logger.propagate = False | ||
logger.setLevel(log_level) | ||
|
||
# Attempt to configure systemd journal logging, if enabled | ||
|
@@ -1481,11 +1489,8 @@ def usage(params): | |
logger.debug('Using legacy pygobject2 main loop.') | ||
loop = GLib.MainLoop() | ||
|
||
# Wrapper to send notifications | ||
notification = NotifyWrapper(params) | ||
|
||
# Create wrapper to handle connection failures with MPD more gracefully | ||
mpd_wrapper = MPDWrapper(params) | ||
mpd_wrapper = MPDWrapper(params, loop=loop) | ||
mpd_wrapper.run() | ||
|
||
# Run idle loop | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't
loop
be a required argument ?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eonpatapon
Wow, ancient history, I don't know how I missed these! Sorry about that.
...I think I originally set these up as defaulted arguments because I didn't want to change the class constructors' semantics until I had my additions finalized. But they probably don't need to stay in that state now.
As far as
loop
goes, though... I mean, I'm not sure it really has to be required.The only reason
loop
is passed in is so the relaunch code in_name_owner_changed_callback()
can callself._loop.quit()
. Ifself._loop
isNone
(it checks), it just won't callquit()
on it.Which... seems like it would be fine? In situations where a
loop
isn't supplied (say, in testing).