2025-05-28 18:33:04 +02:00

175 lines
6.2 KiB
Python
Executable File

# -*- coding: utf-8 -*-
###
# Copyright (c) 2011, Johannes Nixdorf <mixi@shadowice.org>
# Copyright (c) 2014, Mantas Mikulėnas <grawity@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###
###
# ChangeLog:
# 0.4.3 - grawity:
# * allow the default player to be set
# 0.4.2 - grawity:
# * show a better message in "Stopped" state
# 0.4.1 - grawity:
# * inform the user about MPRIS v1 players
# 0.4 - grawity:
# * ported to MPRIS v2
# 0.3 - Johannes:
# * don't excpect every metadata key to be available
# 0.2 - Johannes:
# * fix an error when the player isn't running
# * don't display the song if it playing is paused/stopped
# * fix an error when the player is changed while the plugin is loaded
# * make fewer dbus calls
# 0.1 - Johannes:
# * first version
###
from __future__ import print_function
import dbus
try:
import weechat
weechat.register('mpris2_np',
'Mantas Mikulėnas <grawity@gmail.com>',
'0.4.3',
'BSD',
'Print information on the currently played song',
'',
'')
except ImportError:
print('This script must be called from inside weechat')
raise
BUS_NAME_PREFIX_V2 = 'org.mpris.MediaPlayer2.'
BUS_NAME_PREFIX_V1 = 'org.mpris.'
IF_MPRIS_ROOT = 'org.mpris.MediaPlayer2'
IF_MPRIS_PLAYER = 'org.mpris.MediaPlayer2.Player'
IF_DBUS_PROP = 'org.freedesktop.DBus.Properties'
class FubarException(Exception):
"""
For some reason, reloading either mpris2_np or the python plugin always
breaks the DBus connection irrecoverably.
"""
def list_players(prefix=BUS_NAME_PREFIX_V2):
bus = dbus.SessionBus()
return [name[len(prefix):] for name in bus.list_names()
if name.startswith(prefix)]
def get_player(name):
bus = dbus.SessionBus()
try:
return bus.get_object(BUS_NAME_PREFIX_V2 + name, '/org/mpris/MediaPlayer2')
except TypeError:
raise FubarException()
def print_info(data, buffer, args):
err = None
msg = None
player_name = args.strip()
if not player_name:
player_name = weechat.config_get_plugin('default_player')
if player_name:
try:
player_obj = get_player(player_name)
prop_if = dbus.Interface(player_obj, IF_DBUS_PROP)
_props = prop_if.GetAll(IF_MPRIS_ROOT)
identity = _props.get('Identity', player_name)
_props = prop_if.GetAll(IF_MPRIS_PLAYER)
status = _props.get('PlaybackStatus', 'Stopped')
metadata = _props.get('Metadata', {})
if status == 'Stopped':
msg = u'not listening to anything on %s' % identity
else:
artist = u', '.join(metadata.get('xesam:artist', [u'Unknown artist']))
genre = u'/'.join(metadata.get('xesam:genre', []))
album = metadata.get('xesam:album', None)
track = metadata.get('xesam:trackNumber', None)
title = metadata.get('xesam:title', u'Unknown title')
year = metadata.get('xesam:contentCreated', None)
msg = u'"%s" by %s' % (title, artist)
if album:
msg += u' from "%s"' % album
if year:
msg += u' (%s)' % year
msg = msg.encode('utf-8')
except dbus.exceptions.DBusException as e:
if e.get_dbus_name() == 'org.freedesktop.DBus.Error.ServiceUnknown':
err = 'player "%s" is not running' % player_name
else:
err = 'DBus error %s: "%s"' % (e.get_dbus_name(), e.get_dbus_message())
except FubarException:
err = 'player "%s" is not running (or pydbus is broken again)' % player_name
else:
players = list_players()
if players:
players.sort()
err = 'running players: %s' % ', '.join(players)
else:
err = 'no MPRIS v2 players are running'
v1_players = [p for p in list_players(BUS_NAME_PREFIX_V1) if '.' not in p]
if v1_players:
err += ' (I found "%s", but it only supports MPRIS v1)' \
% ('" and "'.join(v1_players))
if err:
weechat.prnt(buffer, 'np: %s' % err)
else:
weechat.prnt(buffer, 'np: %s' % msg)
weechat.command(buffer, 'np: %s' % msg)
return weechat.WEECHAT_RC_OK
if __name__ == '__main__':
weechat.hook_command('np',
'Print information on the currently played song',
'',
'',
'',
'print_info',
'')
if not weechat.config_is_set_plugin('default_player'):
weechat.config_set_plugin('default_player', '')
weechat.config_set_desc_plugin('default_player',
'Player name to use for "/np" (default: "", shows a list)')