Hello community, here is the log from the commit of package pithos for openSUSE:Factory checked in at 2019-10-23 15:52:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pithos (Old) and /work/SRC/openSUSE:Factory/.pithos.new.2352 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pithos" Wed Oct 23 15:52:19 2019 rev:13 rq:742024 version:1.5.0 Changes: -------- --- /work/SRC/openSUSE:Factory/pithos/pithos.changes 2019-06-01 09:56:22.571183429 +0200 +++ /work/SRC/openSUSE:Factory/.pithos.new.2352/pithos.changes 2019-10-23 15:52:23.858794959 +0200 @@ -1,0 +2,22 @@ +Tue Oct 22 21:10:54 UTC 2019 - Bjørn Lie <[email protected]> + +- Update to version 1.5.0: + + This is a relatively small release fixing appmenu integration + on modern versions of GNOME as well as using more sandbox + (Flatpak) friendly APIs. Note that this move may introduce + behavior changes on some platforms. + + Remove appmenu and move into a menu button in the toolbar. + + Fix preference dialog accidentally getting destroyed. + + Notify: Migrate to GNotification. + + MPRIS: Rename name to match app-id + (org.mpris.MediaPlayer2.io.github.Pithos). + + Screensaver Pause: Remove platform specific screensaver support + and use GTK's built-in detection. +- Drop pithos-fix-deprecated-pygobject.patch: Fixed upstream. +- Drop post(un) handling of glib2_gsettings_schema_post(un), + desktop_database_post(un) and icon_theme_cache_post(un), no + longer needed for any supported version of openSUSE. +- Drop update-desktop-files BuildRequires and macro, no longer + needed. + +------------------------------------------------------------------- Old: ---- pithos-1.4.1.tar.xz pithos-fix-deprecated-pygobject.patch New: ---- pithos-1.5.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pithos.spec ++++++ --- /var/tmp/diff_new_pack.cnw6rr/_old 2019-10-23 15:52:24.578795737 +0200 +++ /var/tmp/diff_new_pack.cnw6rr/_new 2019-10-23 15:52:24.578795737 +0200 @@ -1,7 +1,7 @@ # # spec file for package pithos # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # Copyright (c) 2012-2014 Malcolm J Lewis <[email protected]> # # All modifications and additions to the file contributed by third parties @@ -13,31 +13,28 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # %global appid io.github.Pithos Name: pithos -Version: 1.4.1 +Version: 1.5.0 Release: 0 Summary: Native Pandora Radio client for Linux License: GPL-3.0-only Group: Productivity/Multimedia/Other Url: https://pithos.github.io/ Source0: https://github.com/pithos/pithos/releases/download/%{version}/pithos-%{version}.tar.xz -# PATCH-FIX-UPSTREAM pithos-fix-deprecated-pygobject.patch -- Fix deprecated PyGObject usage -Patch0: pithos-fix-deprecated-pygobject.patch BuildRequires: gdk-pixbuf-devel BuildRequires: glib2-devel -BuildRequires: meson +BuildRequires: meson >= 0.50.0 # Needed for automatic typelib() Requires. BuildRequires: gobject-introspection BuildRequires: hicolor-icon-theme BuildRequires: intltool BuildRequires: python3-devel >= 3.4 -BuildRequires: update-desktop-files Requires: gstreamer-plugins-bad Requires: gstreamer-plugins-good Requires: python3-cairo @@ -60,39 +57,26 @@ %install %meson_install -find %{buildroot} -name \*.pyc -delete # boo#1110032 + +# Fix boo#1110032 - Create noarch pyc files +find %{buildroot} -name \*.pyc -delete %py3_compile %{buildroot} # Remove unnecessary icons rm -rf %{buildroot}%{_datadir}/icons/ubuntu-mono* -%suse_update_desktop_file %{appid} - -%if 0%{?suse_version} < 1330 -%post -%glib2_gsettings_schema_post -%desktop_database_post -%icon_theme_cache_post - -%postun -%glib2_gsettings_schema_postun -%desktop_database_postun -%icon_theme_cache_postun -%endif - %files -%defattr(-,root,root) -%doc license README.md +%license license +%doc README.md %{_bindir}/%{name} %{_datadir}/%{name}/ %{_datadir}/applications/%{appid}.desktop %{_datadir}/glib-2.0/schemas/%{appid}.gschema.xml %{_datadir}/icons/hicolor/ -%dir %{_datadir}/appdata/ -%{_datadir}/appdata/%{appid}.appdata.xml +%{_datadir}/metainfo/%{appid}.appdata.xml %dir %{_datadir}/dbus-1 %dir %{_datadir}/dbus-1/services -%{_datadir}/dbus-1/services/io.github.Pithos.service +%{_datadir}/dbus-1/services/%{appid}.service %{_mandir}/man1/pithos.1%{?ext_man} %changelog ++++++ pithos-1.4.1.tar.xz -> pithos-1.5.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/data/gtk/menus.ui new/pithos-1.5.0/data/gtk/menus.ui --- old/pithos-1.4.1/data/gtk/menus.ui 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/data/gtk/menus.ui 1970-01-01 01:00:00.000000000 +0100 @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - <menu id="app-menu"> - <section> - <item> - <attribute name="action">app.stations</attribute> - <attribute name="label" translatable="yes">_Stations</attribute> - <attribute name="accel"><Primary>s</attribute> - </item> - <item> - <attribute name="action">app.preferences</attribute> - <attribute name="label" translatable="yes">_Preferences</attribute> - <attribute name="accel"><Primary>p</attribute> - </item> - </section> - <section> - <item> - <attribute name="action">app.help</attribute> - <attribute name="label" translatable="yes">_Help</attribute> - <attribute name="accel">F1</attribute> - </item> - <item> - <attribute name="action">app.about</attribute> - <attribute name="label" translatable="yes">_About</attribute> - </item> - <item> - <attribute name="action">app.quit</attribute> - <attribute name="label" translatable="yes">_Quit</attribute> - <attribute name="accel"><Primary>q</attribute> - </item> - </section> - </menu> -</interface> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/data/io.github.Pithos.appdata.xml.in new/pithos-1.5.0/data/io.github.Pithos.appdata.xml.in --- old/pithos-1.4.1/data/io.github.Pithos.appdata.xml.in 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/data/io.github.Pithos.appdata.xml.in 2019-10-06 22:36:47.000000000 +0200 @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <component type="desktop"> - <id>io.github.Pithos.desktop</id> + <id>io.github.Pithos</id> + <launchable type="desktop-id">io.github.Pithos.desktop</launchable> <translation type="gettext">pithos</translation> <name>Pithos</name> <developer_name>Pithos</developer_name> @@ -23,6 +24,18 @@ </screenshot> </screenshots> <releases> + <release date="2019-09-06" version="1.5.0"> + <description> + <p>This is a relatively small release fixing appmenu integration on modern versions of GNOME as well as using more sandbox (Flatpak) friendly APIs. Note that this move may introduce behavior changes on some platforms.</p> + <ul> + <li>Remove appmenu and move into a menu button in the toolbar</li> + <li>Fix preference dialog accidentaly getting destroyed</li> + <li>Notify: Migrate to GNotification</li> + <li>MPRIS: Rename name to match app-id (org.mpris.MediaPlayer2.io.github.Pithos)</li> + <li>Screensaver Pause: Remove platform specific screensaver support and use GTK's built-in detection</li> + </ul> + </description> + </release> <release date="2017-11-26" version="1.4.1"> <description> <p>This is a minor release fixing up some bugs:</p> @@ -113,5 +126,6 @@ <kudo>Notifications</kudo> <kudo>UserDocs</kudo> </kudos> + <content_rating type="oars-1.1"/> <update_contact>tingping_at_fedoraproject.org</update_contact> </component> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/data/io.github.Pithos.gresource.xml new/pithos-1.5.0/data/io.github.Pithos.gresource.xml --- old/pithos-1.4.1/data/io.github.Pithos.gresource.xml 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/data/io.github.Pithos.gresource.xml 2019-10-06 22:36:47.000000000 +0200 @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <gresources> <gresource prefix="/io/github/Pithos"> - <file preprocess="xml-stripblanks">gtk/menus.ui</file> <file preprocess="xml-stripblanks">gtk/help-overlay.ui</file> <file preprocess="xml-stripblanks">ui/PithosWindow.ui</file> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/data/meson.build new/pithos-1.5.0/data/meson.build --- old/pithos-1.4.1/data/meson.build 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/data/meson.build 2019-10-06 22:36:47.000000000 +0200 @@ -36,7 +36,7 @@ output: 'io.github.Pithos.appdata.xml', po_dir: '../po', install: true, - install_dir: join_paths(get_option('datadir'), 'appdata') + install_dir: join_paths(get_option('datadir'), 'metainfo') ) pithos_settings = gnome.compile_schemas() @@ -72,7 +72,6 @@ ['ui', 'StationsDialog.ui'], ['ui', 'EqDialog.ui'], ['gtk', 'help-overlay.ui'], - ['gtk', 'menus.ui'], ] foreach ui_file : ui_files test('Validate @0@'.format(ui_file[1]), gtk_builder_tool, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/data/ui/PithosWindow.ui new/pithos-1.5.0/data/ui/PithosWindow.ui --- old/pithos-1.4.1/data/ui/PithosWindow.ui 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/data/ui/PithosWindow.ui 2019-10-06 22:36:47.000000000 +0200 @@ -2,6 +2,35 @@ <!-- Generated with glade 3.18.1 --> <interface> <requires lib="gtk+" version="3.14"/> + <menu id="app-menu"> + <section> + <item> + <attribute name="action">app.stations</attribute> + <attribute name="label" translatable="yes">_Stations</attribute> + <attribute name="accel"><Primary>s</attribute> + </item> + </section> + <section> + <item> + <attribute name="action">app.preferences</attribute> + <attribute name="label" translatable="yes">_Preferences</attribute> + <attribute name="accel"><Primary>p</attribute> + </item> + <item> + <attribute name="action">win.show-help-overlay</attribute> + <attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute> + </item> + <item> + <attribute name="action">app.help</attribute> + <attribute name="label" translatable="yes">_Help</attribute> + <attribute name="accel">F1</attribute> + </item> + <item> + <attribute name="action">app.about</attribute> + <attribute name="label" translatable="yes">_About</attribute> + </item> + </section> + </menu> <object class="GtkAdjustment" id="adjustment1"> <property name="upper">100</property> <property name="step_increment">1</property> @@ -169,6 +198,32 @@ </object> </child> </object> + </child> + </object> + </child> + <child> + <object class="GtkToolItem"> + <property name="visible">1</property> + <child> + <object class="GtkMenuButton"> + <property name="visible">1</property> + <property name="can_focus">1</property> + <property name="use-popover">TRUE</property> + <property name="menu-model">app-menu</property> + <property name="halign">end</property> + <child internal-child="accessible"> + <object class="AtkObject"> + <property name="AtkObject::accessible-description" translatable="yes">menu</property> + </object> + </child> + <child> + <object class="GtkImage"> + <property name="visible">1</property> + <property name="icon_name">open-menu-symbolic</property> + <property name="icon_size">1</property> + </object> + </child> + </object> </child> </object> </child> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/data/ui/PreferencesPithosDialog.ui new/pithos-1.5.0/data/ui/PreferencesPithosDialog.ui --- old/pithos-1.4.1/data/ui/PreferencesPithosDialog.ui 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/data/ui/PreferencesPithosDialog.ui 2019-10-06 22:36:47.000000000 +0200 @@ -8,6 +8,7 @@ <property name="resizable">False</property> <property name="modal">1</property> <signal name="show" handler="on_show" swapped="no"/> + <signal name="delete-event" handler="on_delete_event" swapped="no"/> <child type="action"> <object class="GtkButton" id="button_cancel"> <property name="label">Cancel</property> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/docs/pithos.1 new/pithos-1.5.0/docs/pithos.1 --- old/pithos-1.4.1/docs/pithos.1 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/docs/pithos.1 2019-10-06 22:36:47.000000000 +0200 @@ -1,7 +1,7 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.5. -.TH PITHOS "1" "November 2017" "Pithos 1.4.1" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.11. +.TH PITHOS "1" "October 2019" "Pithos 1.5.0" "User Commands" .SH NAME -Pithos \- manual page for Pithos 1.4.1 +Pithos \- manual page for Pithos 1.5.0 .SH DESCRIPTION .SS "Usage:" .IP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/meson.build new/pithos-1.5.0/meson.build --- old/pithos-1.4.1/meson.build 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/meson.build 2019-10-06 22:36:47.000000000 +0200 @@ -1,6 +1,6 @@ project('pithos', - version: '1.4.1', - meson_version: '>= 0.40.0' + version: '1.5.0', + meson_version: '>= 0.50.0' ) i18n = import('i18n') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/pithos/PreferencesPithosDialog.py new/pithos-1.5.0/pithos/PreferencesPithosDialog.py --- old/pithos-1.4.1/pithos/PreferencesPithosDialog.py 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/pithos/PreferencesPithosDialog.py 2019-10-06 22:36:47.000000000 +0200 @@ -176,6 +176,12 @@ self.last_email = self.settings['email'] SecretService.get_account_password(self.last_email, cb) + @GtkTemplate.Callback + def on_delete_event(self, *ignore): + self.hide() + self.settings.revert() + return True + def do_response(self, response_id): if response_id == Gtk.ResponseType.APPLY: def cb(success): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/pithos/application.py new/pithos-1.5.0/pithos/application.py --- old/pithos-1.4.1/pithos/application.py 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/pithos/application.py 2019-10-06 22:36:47.000000000 +0200 @@ -32,11 +32,15 @@ super().__init__(application_id='io.github.Pithos', flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE) + if hasattr(self.props, 'register_session'): + self.props.register_session = True + # First, get rid of existing logging handlers due to call in header as per # http://stackoverflow.com/questions/1943747/python-logging-before-you-run-logging-basicconfig logging.root.handlers = [] os.environ['PULSE_PROP_application.name'] = 'Pithos' + os.environ['PULSE_PROP_application.id'] = 'io.github.Pithos' os.environ['PULSE_PROP_application.version'] = version os.environ['PULSE_PROP_application.icon_name'] = 'io.github.Pithos' os.environ['PULSE_PROP_media.role'] = 'music' @@ -79,14 +83,16 @@ action = Gio.SimpleAction.new("quit", None) action.connect("activate", self.quit_cb) self.add_action(action) + self.set_accels_for_action('app.quit', ['<Primary>q']) + + action = Gio.SimpleAction.new("next-song", None) + action.connect("activate", lambda action, param: self.window.next_song()) + self.add_action(action) - if Gtk.get_major_version() > 3 or Gtk.get_minor_version() >= 20: - menu = self.get_app_menu() - it = menu.iterate_item_links(menu.get_n_items() - 1) - assert(it.next()) - last_section = it.get_value() - shortcuts_item = Gio.MenuItem.new(_('Keyboard Shortcuts'), 'win.show-help-overlay') - last_section.prepend_item(shortcuts_item) + # Needed for notifications to function as expected in KDE. + action = Gio.SimpleAction.new("activate", None) + action.connect("activate", lambda action, param: self.activate()) + self.add_action(action) def do_command_line(self, command_line): options = command_line.get_options_dict() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/pithos/plugins/dbus_util/GioNotify.py new/pithos-1.5.0/pithos/plugins/dbus_util/GioNotify.py --- old/pithos-1.4.1/pithos/plugins/dbus_util/GioNotify.py 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/pithos/plugins/dbus_util/GioNotify.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,223 +0,0 @@ -# -# Copyright (C) 2016 Jason Gray <[email protected]> -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 3, as published -# by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranties of -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR -# PURPOSE. See the GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see <http://www.gnu.org/licenses/>. -# END LICENSE - -# See <https://developer.gnome.org/notification-spec/> and -# <https://github.com/JasonLG1979/possibly-useful-scraps/wiki/GioNotify> -# for documentation. - -import logging - -from enum import Enum - -from gi.repository import GLib, GObject, Gio - - -class GioNotify(Gio.DBusProxy): - - # Notification Closed Reason Constants. - class Closed(Enum): - REASON_EXPIRED = 1 - REASON_DISMISSED = 2 - REASON_CLOSEMETHOD = 3 - REASON_UNDEFINED = 4 - - @property - def explanation(self): - value = self.value - if value == 1: - return 'The notification expired.' - elif value == 2: - return 'The notification was dismissed by the user.' - elif value == 3: - return 'The notification was closed by a call to CloseNotification.' - elif value == 4: - return 'The notification was closed by undefined/reserved reasons.' - - __gtype_name__ = 'GioNotify' - __gsignals__ = { - 'action-invoked': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_STRING,)), - 'closed': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)), - } - - def __init__(self, **kwargs): - super().__init__( - g_bus_type=Gio.BusType.SESSION, - g_interface_name='org.freedesktop.Notifications', - g_name='org.freedesktop.Notifications', - g_object_path='/org/freedesktop/Notifications', - **kwargs - ) - - self._app_name = '' - self._last_signal = None - self._vendor_is_gnome = False - self._replace_id = 0 - self._server_info = {} - self._broken_signals = [] - self._actions = [] - self._callbacks = {} - self._hints = {} - - @classmethod - def async_init(cls, app_name, callback): - def on_init_finish(self, result, data): - try: - self.init_finish(result) - except GLib.Error as e: - callback(None, None, None, error=e) - else: - if not self.get_name_owner(): - callback(None, None, None, error='Notification service is unowned') - else: - self.call( - 'GetCapabilities', - None, - Gio.DBusCallFlags.NONE, - -1, - None, - on_GetCapabilities_finish, - None, - ) - - def on_GetCapabilities_finish(self, result, data): - try: - caps = self.call_finish(result).unpack()[0] - except GLib.Error as e: - callback(None, None, None, error=e) - else: - self.call( - 'GetServerInformation', - None, - Gio.DBusCallFlags.NONE, - -1, - None, - on_GetServerInformation_finish, - caps, - ) - - def on_GetServerInformation_finish(self, result, caps): - try: - info = self.call_finish(result).unpack() - except GLib.Error as e: - callback(None, None, None, error=e) - else: - self._server_info = { - 'name': info[0], - 'vendor': info[1], - 'version': info[2], - 'spec_version': info[3], - } - self._vendor_is_gnome = info[1] == 'GNOME' - self._app_name = app_name - - callback(self, self._server_info, caps) - - self = cls() - self.init_async(GLib.PRIORITY_DEFAULT, None, on_init_finish, None) - - def show_new(self, summary, body, icon): - def on_Notify_finish(self, result): - self._replace_id = self.call_finish(result).unpack()[0] - - # If the Notification server implementation's 'ActionInvoked' signal is broken - # our action buttons will be non-functional, so don't add them. - actions = self._actions if 'ActionInvoked' not in self._broken_signals else [] - args = GLib.Variant('(susssasa{sv}i)', (self._app_name, self._replace_id, - icon, summary, body, - actions, self._hints, -1)) - - self.call( - 'Notify', - args, - Gio.DBusCallFlags.NONE, - -1, - None, - on_Notify_finish, - ) - - def add_action(self, action_id, label, callback): - self._actions += [action_id, label] - self._callbacks[action_id] = callback - - def clear_actions(self): - self._actions.clear() - self._callbacks.clear() - - def set_hint(self, key, value): - if value is None: - if key in self._hints: - del self._hints[key] - else: - self._hints[key] = value - - def do_g_signal(self, sender_name, signal_name, parameters): - try: - notification_id, signal_value = parameters.unpack() - except ValueError: - # Deepin's notification system is broken, see: - # https://github.com/gnumdk/lollypop/issues/1203 - # This will stop exceptions by ignoring parameters - # and send a warning message about the broken signal. - # Don't spam the logs only send 1 warning message per signal name. - if signal_name not in self._broken_signals: - self._broken_signals.append(signal_name) - server_info = '\n'.join(('{}: {}'.format(k, v) for k, v in self._server_info.items())) - logging.warning('Broken Notification server implementation.\n' - 'Missing parameter(s) for the "{}" signal.\n' - 'Please file a bug report with the developers ' - 'of your current Notification server:\n{}'.format(signal_name, server_info)) - else: - # We only care about our notifications. - if notification_id != self._replace_id: - return - if self._vendor_is_gnome: - # In GNOME this stops multiple redundant 'NotificationClosed' - # signals from being emmitted. see: https://bugzilla.gnome.org/show_bug.cgi?id=790636 - if (notification_id, signal_name) == self._last_signal: - return - self._last_signal = notification_id, signal_name - if signal_name == 'ActionInvoked': - if signal_name not in self._broken_signals: - callback = self._callbacks.get(signal_value) - if callback: - self.emit('action-invoked', signal_value) - callback() - else: - self._broken_signals.append(signal_name) - server_info = '\n'.join(('{}: {}'.format(k, v) for k, v in self._server_info.items())) - logging.warning('Broken Notification server implementation.\n' - 'Invalid "ActionInvoked" signal value: "{}".\n' - 'Please file a bug report with the developers ' - 'of your current Notification server:\n{}'.format(signal_value, server_info)) - elif signal_name == 'NotificationClosed': - if signal_name not in self._broken_signals: - try: - closed_reason = GioNotify.Closed(signal_value) - except ValueError: - self._broken_signals.append(signal_name) - server_info = '\n'.join(('{}: {}'.format(k, v) for k, v in self._server_info.items())) - logging.warning('Broken Notification server implementation.\n' - 'Invalid "NotificationClosed" signal value: "{}".\n' - 'Please file a bug report with the developers ' - 'of your current Notification server:\n{}'.format(signal_value, server_info)) - else: - self.emit('closed', closed_reason) - else: - logging.debug('Unknown signal: "{}", value: "{}"'.format(signal_name, signal_value)) - - def __getattr__(self, name): - # PyGObject ships an override that breaks our usage. - return object.__getattr__(self, name) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/pithos/plugins/mediakeys.py new/pithos-1.5.0/pithos/plugins/mediakeys.py --- old/pithos-1.4.1/pithos/plugins/mediakeys.py 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/pithos/plugins/mediakeys.py 2019-10-06 22:36:47.000000000 +0200 @@ -149,11 +149,14 @@ logging.error('Failed to bind media keys with Keybinder') self.on_error('Failed to bind media keys with Keybinder') return - self.keybinder.bind('XF86AudioStop', self.window.user_pause, None) - self.keybinder.bind('XF86AudioPause', self.window.user_pause, None) - self.keybinder.bind('XF86AudioNext', self.window.next_song, None) - self.keybinder.bind('XF86AudioPrev', self.window.bring_to_top, None) - logging.info('Bound media keys with Keybinder') + if all((self.keybinder.bind('XF86AudioStop', self.window.user_pause, None), + self.keybinder.bind('XF86AudioPause', self.window.user_pause, None), + self.keybinder.bind('XF86AudioNext', self.window.next_song, None), + self.keybinder.bind('XF86AudioPrev', self.window.bring_to_top, None))): + logging.info('Bound media keys with Keybinder') + else: + # Keybinder hardcodes a warning with the specific failures + logging.warning('Some media keys failed to bind with Keybinder') def on_disable(self): if self.mediakeys: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/pithos/plugins/mpris.py new/pithos-1.5.0/pithos/plugins/mpris.py --- old/pithos-1.4.1/pithos/plugins/mpris.py 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/pithos/plugins/mpris.py 2019-10-06 22:36:47.000000000 +0200 @@ -116,7 +116,7 @@ self.bus_id = Gio.bus_own_name_on_connection( self.connection, - 'org.mpris.MediaPlayer2.pithos', + 'org.mpris.MediaPlayer2.io.github.Pithos', Gio.BusNameOwnerFlags.NONE, on_name_acquired, None, @@ -837,7 +837,7 @@ self.pithos = window self.settings = settings - self.window_delete_handler = None + self.delete_handler = None box = Gtk.Box() label = Gtk.Label() @@ -864,19 +864,27 @@ def on_activated(self, *ignore): if self.switch.get_active(): self.settings['data'] = 'True' - self.delete_callback_handle = self.pithos.connect('delete-event', self.on_close) + self._enable_hide_on_delete() else: self.settings['data'] = 'False' - self._disable() + self._disable_hide_on_delete() def _on_plugin_enabled(self, *ignore): if self.settings['enabled']: self.switch.set_active(self.settings['data'] == 'True') + if self.switch.get_active(): + self._enable_hide_on_delete() + else: + self._disable_hide_on_delete() else: - self._disable() + self._disable_hide_on_delete() - def _disable(self): - if self.delete_callback_handle: - self.pithos.disconnect(self.delete_callback_handle) - self.pithos.connect('delete-event', self.pithos.on_destroy) - self.window_delete_handler = None + def _disable_hide_on_delete(self): + if self.delete_handler: + self.pithos.disconnect(self.delete_handler) + self.delete_handler = self.pithos.connect('delete-event', self.pithos.on_destroy) + + def _enable_hide_on_delete(self): + if self.delete_handler: + self.pithos.disconnect(self.delete_handler) + self.delete_handler = self.pithos.connect('delete-event', self.on_close) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/pithos/plugins/notification_icon.py new/pithos-1.5.0/pithos/plugins/notification_icon.py --- old/pithos-1.4.1/pithos/plugins/notification_icon.py 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/pithos/plugins/notification_icon.py 2019-10-06 22:36:47.000000000 +0200 @@ -164,10 +164,10 @@ def button(text, action, checked=False): if checked: - item = Gtk.CheckMenuItem(text) + item = Gtk.CheckMenuItem.new_with_label(text) item.set_active(True) else: - item = Gtk.MenuItem(text) + item = Gtk.MenuItem.new_with_label(text) handler = item.connect('activate', action) item.show() menu.append(item) @@ -253,16 +253,16 @@ def __init__(self, parent, settings): super().__init__( - _('Icon Type'), - parent, - 0, - ('_Cancel', Gtk.ResponseType.CANCEL, '_Apply', Gtk.ResponseType.APPLY), + title=_('Icon Type'), + transient_for=parent, use_header_bar=1, resizable=False, default_width=300 ) self.settings = settings + self.add_buttons('_Cancel', Gtk.ResponseType.CANCEL, '_Apply', Gtk.ResponseType.APPLY) + self.connect('delete-event', lambda *ignore: self.response(Gtk.ResponseType.CANCEL) or True) sub_title = Gtk.Label.new(_('Set the Notification Icon Type')) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/pithos/plugins/notify.py new/pithos-1.5.0/pithos/plugins/notify.py --- old/pithos-1.4.1/pithos/plugins/notify.py 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/pithos/plugins/notify.py 2019-10-06 22:36:47.000000000 +0200 @@ -12,107 +12,67 @@ # You should have received a copy of the GNU General Public License along # with this program. If not, see <http://www.gnu.org/licenses/>. -import html -import logging +import os -from gi.repository import (GLib, Gtk) +from gi.repository import Gio from pithos.plugin import PithosPlugin -from .dbus_util.GioNotify import GioNotify - class NotifyPlugin(PithosPlugin): preference = 'notify' description = 'Shows notifications on song change' - notification = None - supports_actions = False - escape_markup = False + _app = None + _app_id = None + _fallback_icon = None def on_prepare(self): - def on_notify_init_finish(notification, server_info, caps, error=None): - if error: - logging.warning('Notification server not found: {}'.format(error)) - self.prepare_complete(error='Notification server not found') - else: - self.notification = notification - self.supports_actions = 'actions' in caps - self.escape_markup = 'body-markup' in caps - - self.notification.set_hint('desktop-entry', GLib.Variant('s', 'io.github.Pithos')) - self.notification.set_hint('category', GLib.Variant('s', 'x-gnome.music')) - if 'action-icons' in caps: - self.notification.set_hint('action-icons', GLib.Variant('b', True)) - - # GNOME Shell 3.20 or higher has bultin MPRIS functionality that makes - # persistent song notifications redundant. - has_built_in_mpris = False - version = server_info['version'].split('.') - if server_info['name'] == 'gnome-shell' and len(version) >= 2: - major_version, minor_version = (int(x) if x.isdigit() else 0 for x in version[0:2]) - if major_version == 3 and minor_version >= 20: - has_built_in_mpris = True - - if 'persistence' in caps and has_built_in_mpris: - self.notification.set_hint('transient', GLib.Variant('b', True)) - - server_info = '\n'.join(('{}: {}'.format(k, v) for k, v in server_info.items())) - logging.debug('\nNotification Server Information:\n{}'.format(server_info)) - - caps = '\n'.join((cap for cap in caps)) - logging.debug('\nNotification Server Capabilities:\n{}'.format(caps)) - self.prepare_complete() - - GioNotify.async_init('Pithos', on_notify_init_finish) + # We prefer the behavior of the fdo backend to the gtk backend + # as it doesn't force persistance which doesn't make sense for + # this application. + if not os.path.exists('/.flatpak-info'): + os.environ['GNOTIFICATION_BACKEND'] = 'freedesktop' + + self._app = Gio.Application.get_default() + self._app_id = self._app.get_application_id() + self._fallback_icon = Gio.ThemedIcon.new('audio-x-generic') + self.prepare_complete() def on_enable(self): - self.song_change_handler = self.window.connect('song-changed', self.send_notification) - self.state_change_handler = self.window.connect('user-changed-play-state', self.send_notification) - self.closed_handler = self.notification.connect('closed', self.on_notification_closed) - self.action_invoked_handler = self.notification.connect('action-invoked', self.on_notification_action_invoked) - - def on_notification_closed(self, notification, closed_reason): - logging.debug(closed_reason.explanation) - - def on_notification_action_invoked(self, notification, action_id): - logging.debug('Notification action invoked: {}'.format(action_id)) - - def set_actions(self, playing): - pause_action = 'media-playback-pause' - play_action = 'media-playback-start' - skip_action = 'media-skip-forward' - if Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL: - play_action += '-rtl' - skip_action += '-rtl' - if playing: - self.notification.add_action(pause_action, 'Pause', - self.window.playpause_notify) - else: - self.notification.add_action(play_action, 'Play', - self.window.playpause_notify) - - self.notification.add_action(skip_action, 'Skip', - self.window.next_song) + self._song_change_handler = self.window.connect('song-changed', self.send_notification) + self._shutdown_handler = self._app.connect('shutdown', lambda app: app.withdraw_notification(self._app_id)) def send_notification(self, window, *ignore): if window.is_active(): - return - if self.supports_actions: - self.notification.clear_actions() - self.set_actions(window.playing is not False) - song = window.current_song - summary = song.title - body = 'by {} from {}'.format(song.artist, song.album) - if self.escape_markup: - body = html.escape(body, quote=False) - icon = song.artUrl or 'audio-x-generic' - self.notification.show_new(summary, body, icon) + # GNOME-Shell will auto dismiss notifications + # when the window becomes "active" but other DE's may not (KDE for example). + # If we're not going to replace a previous notification + # we should withdraw said stale previous notification. + self._app.withdraw_notification(self._app_id) + else: + song = window.current_song + # This matches GNOME-Shell's format + notification = Gio.Notification.new(song.artist) + # GNOME focuses the application by default, we want to match that behavior elsewhere such as on KDE. + notification.set_default_action('app.activate') + notification.set_body(song.title) + + if song.artUrl: + icon = Gio.FileIcon.new(Gio.File.new_for_uri(song.artUrl)) + else: + icon = self._fallback_icon + notification.set_icon(icon) + + notification.add_button(_('Skip'), 'app.next-song') + + self._app.send_notification(self._app_id, notification) def on_disable(self): - if self.notification is None: - return - self.window.disconnect(self.song_change_handler) - self.window.disconnect(self.state_change_handler) - self.notification.disconnect(self.closed_handler) - self.notification.disconnect(self.action_invoked_handler) + self._app.withdraw_notification(self._app_id) + if self._song_change_handler: + self.window.disconnect(self._song_change_handler) + self._song_change_handler = 0 + if self._shutdown_handler: + self._app.disconnect(self._shutdown_handler) + self._shutdown_handler = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pithos-1.4.1/pithos/plugins/screensaver_pause.py new/pithos-1.5.0/pithos/plugins/screensaver_pause.py --- old/pithos-1.4.1/pithos/plugins/screensaver_pause.py 2017-11-26 20:11:26.000000000 +0100 +++ new/pithos-1.5.0/pithos/plugins/screensaver_pause.py 2019-10-06 22:36:47.000000000 +0200 @@ -12,75 +12,38 @@ # You should have received a copy of the GNU General Public License along # with this program. If not, see <http://www.gnu.org/licenses/>. -import logging - -from gi.repository import (GLib, Gio) +from gi.repository import Gio from pithos.plugin import PithosPlugin -SCREENSAVERS = ( - # interface, path - ('org.gnome.ScreenSaver', '/org/gnome/ScreenSaver'), - ('org.cinnamon.ScreenSaver', '/org/cinnamon/ScreenSaver'), - ('org.freedesktop.ScreenSaver', '/org/freedesktop/ScreenSaver'), -) - class ScreenSaverPausePlugin(PithosPlugin): preference = 'enable_screensaverpause' description = 'Pause playback on screensaver' - locked = 0 - wasplaying = False - subs = [] + _signal_handle = 0 + _app = None + _wasplaying = False def on_prepare(self): - if self.bus is None: - logging.debug('Failed to connect to DBus') - self.prepare_complete(error='Failed to connect to DBus') + self._app = Gio.Application.get_default() + if not hasattr(self._app.props, 'screensaver_active'): + self.prepare_complete(error='Gtk 3.24+ required') else: self.prepare_complete() + def _on_screensaver_active(self, pspec, user_data=None): + if self._app.props.screensaver_active: + self._wasplaying = self.window.playing + self.window.pause() + elif self._wasplaying: + self.window.user_play() + def on_enable(self): - self._connect_events() + self._signal_handle = self._app.connect('notify::screensaver-active', + self._on_screensaver_active) def on_disable(self): - for sub in self.subs: - self.bus.signal_unsubscribe(sub) - - self.locked = 0 - self.wasplaying = False - self.subs = [] - - def _connect_events(self): - def on_screensaver_active_changed(conn, sender, path, interface, sig, param, userdata=None): - self._pause() if param[0] else self._play() - - def on_unity_session_changed(conn, sender, path, interface, sig, param, userdata=None): - self._pause() if sig == 'Locked' else self._play() - - for ss in SCREENSAVERS: - self.subs.append(self.bus.signal_subscribe( - None, ss[0], 'ActiveChanged', ss[1], - None, Gio.DBusSignalFlags.NONE, - on_screensaver_active_changed, None)) - - for sig in ('Locked', 'Unlocked'): - self.subs.append(self.bus.signal_subscribe( - None, 'com.canonical.Unity.Session', - sig, '/com/canonical/Unity/Session', - None, Gio.DBusSignalFlags.NONE, - on_unity_session_changed, None)) - - def _play(self): - self.locked -= 1 - if self.locked < 0: - self.locked = 0 - if not self.locked and self.wasplaying: - self.window.user_play() - - def _pause(self): - if not self.locked: - self.wasplaying = self.window.playing - self.window.pause() - self.locked += 1 + if self._signal_handle: + self._app.disconnect(self._signal_handle) + self._signal_handle = 0
