From fea893b36fdc331d81e738a7732508128b5da6ca Mon Sep 17 00:00:00 2001 From: Leigh Scott Date: Jun 20 2019 09:48:49 +0000 Subject: Update to 4.0.0 --- diff --git a/.gitignore b/.gitignore index 6893cc6..0a2c2ea 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ exaile-0.3.2.0.tar.gz /exaile-3.4.2.tar.gz /exaile-3.4.3.tar.gz /exaile-3.4.5.tar.gz +/exaile-4.0.0.tar.gz diff --git a/exaile-3.3.2-udisks.patch b/exaile-3.3.2-udisks.patch deleted file mode 100644 index 303ff51..0000000 --- a/exaile-3.3.2-udisks.patch +++ /dev/null @@ -1,343 +0,0 @@ -=== modified file 'plugins/cd/__init__.py' ---- plugins/cd/__init__.py 2012-10-03 04:43:15 +0000 -+++ plugins/cd/__init__.py 2012-11-09 04:25:00 +0000 -@@ -27,12 +27,12 @@ - - from xl.nls import gettext as _ - from xl import providers, event --from xl.hal import Handler -+from xl.hal import Handler, UDisksProvider - from xl.devices import Device - import logging - logger = logging.getLogger(__name__) - --PROVIDER = None -+PROVIDER = PROVIDER_UDISKS = None - - import dbus, threading, os, struct - from fcntl import ioctl -@@ -61,15 +61,17 @@ - CDROM_DATA_TRACK = 0x04 - - def enable(exaile): -- global PROVIDER -- PROVIDER = CDHandler() -- providers.register("hal", PROVIDER) -- -+ global PROVIDER, PROVIDER_UDISKS -+ #~ PROVIDER = CDHandler() -+ #~ providers.register("hal", PROVIDER) -+ PROVIDER_UDISKS = UDisksCdProvider() -+ providers.register("udisks", PROVIDER_UDISKS) - - def disable(exaile): -- global PROVIDER -+ global PROVIDER, PROVIDER_UDISKS - providers.unregister("hal", PROVIDER) -- PROVIDER = None -+ providers.unregister("udisks", PROVIDER_UDISKS) -+ PROVIDER = PROVIDER_UDISKS = None - - class CDTocParser(object): - #based on code from http://carey.geek.nz/code/python-cdrom/cdtoc.py -@@ -186,7 +188,7 @@ - tr.set_tag_raw('genre', - info['DGENRE']) - -- self._set_name(title[1].decode('iso-8859-15', 'replace')) -+ self.name = title[1].decode('iso-8859-15', 'replace') - event.log_event('cddb_info_retrieved', self, True) - - class CDDevice(Device): -@@ -244,8 +246,25 @@ - - return cddev - -+class UDisksCdProvider(UDisksProvider): -+ name = 'cd' -+ PRIORITY = UDisksProvider.NORMAL -+ -+ def get_priority(self, obj): -+ props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') -+ iface = 'org.freedesktop.UDisks.Device' -+ # DeviceChanged is called before and after tracks are read. We only want -+ # the second case, so use number of audio tracks to identify supported -+ # media. As a bonus, this means we never have to care about the type of -+ # disc (CD, DVD, etc.). -+ ntracks = props.Get(iface, 'OpticalDiscNumAudioTracks') -+ return self.PRIORITY if ntracks > 0 else None -+ -+ def get_device(self, obj): -+ # TODO: If this is the same disc, return old device object. -+ props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') -+ iface = 'org.freedesktop.UDisks.Device' -+ return CDDevice(dev=str(props.Get(iface, 'DeviceFile'))) -+ - - # vim: et sts=4 sw=4 -- -- -- - -=== modified file 'xl/hal.py' ---- xl/hal.py 2012-10-03 04:43:15 +0000 -+++ xl/hal.py 2012-11-09 04:25:00 +0000 -@@ -24,7 +24,7 @@ - # do so. If you do not wish to do so, delete this exception statement - # from your version. - --import logging -+import logging, threading, time - import dbus - - from xl import common, providers, event, devices, settings -@@ -32,6 +32,183 @@ - - logger = logging.getLogger(__name__) - -+class UDisks(providers.ProviderHandler): -+ """ -+ Provides support for UDisks devices. -+ -+ If the D-Bus connection fails, this object will grow a "failed" -+ attribute with True as the value. Plugins should check for this when -+ registering if they want to provide HAL fallback. FIXME: There's a race -+ condition here. -+ """ -+ -+ # States: start -> init -> addremove <-> listening -> end. -+ # The addremove state acts as a lock against concurrent changes. -+ -+ def __init__(self, devicemanager): -+ self._lock = lock = threading.Lock() -+ self._state = 'init' -+ logger.debug("UDisks: state = init") -+ -+ providers.ProviderHandler.__init__(self, 'udisks') -+ self.devicemanager = devicemanager -+ -+ self.bus = self.obj = self.iface = None -+ self.devices = {} -+ self.providers = {} -+ -+ #~ @common.threaded -+ def connect(self): -+ assert self._state == 'init' -+ logger.debug("Connecting to UDisks") -+ try: -+ self.bus = bus = dbus.SystemBus() -+ self.obj = obj = bus.get_object('org.freedesktop.UDisks', '/org/freedesktop/UDisks') -+ self.iface = iface = dbus.Interface(obj, 'org.freedesktop.UDisks') -+ iface.connect_to_signal('DeviceAdded', self._udisks_device_added) -+ iface.connect_to_signal('DeviceRemoved', self._udisks_device_removed) -+ iface.connect_to_signal('DeviceChanged', self._udisks_device_added) -+ logger.info("Connected to UDisks") -+ event.log_event("hal_connected", self, None) -+ except Exception: -+ logger.warning("Failed to connect to UDisks, " \ -+ "autodetection of devices will be disabled.") -+ common.log_exception() -+ self._state = 'listening' -+ logger.debug("UDisks: state = listening") -+ self.failed = True -+ return -+ self._state = 'addremove' -+ logger.debug("UDisks: state = addremove") -+ self._add_all() -+ self._state = 'listening' -+ logger.debug("UDisks: state = listening") -+ -+ def _add_all(self): -+ assert self._state == 'addremove' -+ for path in self.iface.EnumerateDevices(): -+ self._add_device(path) -+ -+ def _add_device(self, path=None, obj=None): -+ """ -+ Call with either path or obj (obj gets priority). Not thread-safe. -+ """ -+ assert self._state == 'addremove' -+ if obj is None: -+ obj = self.bus.get_object('org.freedesktop.UDisks', path) -+ -+ # In the following code, `old` and `new` are providers, while -+ # `self.devices[path]` and `device` are old/new devices. There are -+ # several possible code paths that should be correctly handled: -+ # - No old nor new provider for this path. -+ # - Provider changes (nothing to something, something to nothing, -+ # something to something else); obviously device changes as well. -+ # - Provider stays the same, but device changes (i.e. instant media- -+ # swapping; not sure it can happen). -+ # - Provider and device stay the same. -+ old, new = self._get_provider_for(obj) -+ if new is None: -+ if old is not None: -+ self.devicemanager.remove_device(self.devices[path]) -+ del self.devices[path] -+ return -+ device = new.get_device(obj) -+ if new is old and device is self.devices[path]: -+ return # Exactly the same device -+ if old is not None: -+ self.devicemanager.remove_device(self.devices[path]) -+ if new is None: -+ return -+ try: -+ device.autoconnect() -+ except: -+ logger.exception("Failed autoconnecting device " + str(device)) -+ else: -+ self.devicemanager.add_device(device) -+ self.providers[path] = new -+ self.devices[path] = device -+ -+ def _get_provider_for(self, obj): -+ """ -+ Return (old_provider, old_priority), (new_provider, new_priority). -+ Not thread-safe. -+ """ -+ assert self._state == 'addremove' -+ highest_prio = -1 -+ highest = None -+ old = self.providers.get(obj.object_path) -+ for provider in self.get_providers(): -+ priority = provider.get_priority(obj) -+ if priority is None: continue -+ # Find highest priority, preferring old provider. -+ if priority > highest_prio or \ -+ (priority == highest_prio and provider is old): -+ highest_prio = priority -+ highest = provider -+ return old, highest -+ -+ def _remove_device(self, path): -+ assert self._state == 'addremove' -+ try: -+ self.devicemanager.remove_device(self.devices[path]) -+ del self.devices[path] -+ except KeyError: -+ logger.warning("UDisks: Can't remove device (not found): " + path) -+ -+ def _udisks_device_added(self, path): -+ logger.debug("UDisks: Device added: " + str(path)) -+ if self._addremove(): -+ self._add_device(path) -+ self._state = 'listening' -+ logger.debug("UDisks: state = listening (_device_added)") -+ -+ def _udisks_device_removed(self, path): -+ if self._addremove(): -+ try: -+ self._remove_device(path) -+ logger.debug("UDisks: Device removed: " + str(path)) -+ except KeyError: # Not ours -+ pass -+ self._state = 'listening' -+ logger.debug("UDisks: state = listening") -+ -+ # FIXME: Handle provider add/remove (following code unused & untested). -+ -+ def on_provider_added(self, provider): -+ if self._addremove(): -+ self._connect_all() -+ self._state = 'listening' -+ logger.debug("UDisks: state = listening") -+ -+ def on_provider_removed(self, provider): -+ if self._addremove(): -+ for path, provider_ in self.providers.iteritems(): -+ if provider_ is provider: -+ self._remove_device(path) -+ self._state = 'listening' -+ logger.debug("UDisks: state = listening") -+ -+ def _addremove(self): -+ """ -+ Helper to transition safely from listening to addremove state. -+ -+ Returns whether the transition happens. -+ """ -+ i = 0 -+ while True: -+ with self._lock: -+ if self._state == 'listening': -+ self._state = 'addremove' -+ logger.debug("UDisks: state = addremove") -+ return True -+ # If active state is init, we sleep and try again a few times. -+ # TODO: Whose thread is this we are blocking? -+ if i == 5: -+ logger.error("UDisks: Failed to acquire lock. Ignoring device event.") -+ return False -+ i += 1 -+ time.sleep(1) -+ - class HAL(providers.ProviderHandler): - """ - HAL interface -@@ -144,6 +321,12 @@ - def device_from_udi(self, hal, udi): - pass - -+class UDisksProvider: -+ VERY_LOW, LOW, NORMAL, HIGH, VERY_HIGH = range(0, 101, 25) -+ def get_priority(self, obj): -+ pass # return: int [0..100] or None -+ def get_device(self, obj): -+ pass # return: xl.devices.Device -+ - - # vim: et sts=4 sw=4 -- - -=== modified file 'xl/main.py' ---- xl/main.py 2012-10-24 04:33:53 +0000 -+++ xl/main.py 2012-11-09 04:25:00 +0000 -@@ -254,6 +254,8 @@ - # Initialize HAL - if self.options.Hal: - from xl import hal -+ self.udisks = hal.UDisks(self.devices) -+ self.udisks.connect() - self.hal = hal.HAL(self.devices) - self.hal.connect() - else: - -=== modified file 'xl/trax/util.py' ---- xl/trax/util.py 2012-10-03 04:43:15 +0000 -+++ xl/trax/util.py 2012-11-09 04:25:00 +0000 -@@ -65,14 +65,17 @@ - tracks = [] - - gloc = gio.File(uri) -+ - # don't do advanced checking on streaming-type uris as it can fail or - # otherwise be terribly slow. - # TODO: move uri definition somewhere more common for easy reuse? -- - if gloc.get_uri_scheme() in ('http', 'mms', 'cdda'): - return [Track(uri)] - -- file_type = gloc.query_info("standard::type").get_file_type() -+ try: -+ file_type = gloc.query_info("standard::type").get_file_type() -+ except gio.Error: # E.g. cdda -+ file_type = None - if file_type == gio.FILE_TYPE_DIRECTORY: - # TODO: refactor Library so we dont need the collection obj - from xl.collection import Library, Collection - -=== modified file 'xlgui/panel/flatplaylist.py' ---- xlgui/panel/flatplaylist.py 2012-10-03 04:43:15 +0000 -+++ xlgui/panel/flatplaylist.py 2012-11-09 04:25:00 +0000 -@@ -121,8 +121,7 @@ - def set_playlist(self, playlist): - self.model.clear() - -- tracks = [track for track in playlist] -- self.tracks = tracks -+ self.tracks = tracks = list(playlist) - for i, track in enumerate(tracks): - self.model.append([i + 1, track.get_tag_display("title"), track]) - - diff --git a/exaile.spec b/exaile.spec index e1152ef..58886c0 100644 --- a/exaile.spec +++ b/exaile.spec @@ -3,26 +3,27 @@ %global _python_bytecompile_extra 1 Name: exaile -Version: 3.4.5 -Release: 10%{?dist} +Version: 4.0.0 +Release: 1%{?dist} Summary: Simple but powerful Amarok-style music player for GTK users License: GPLv2+ URL: http://www.exaile.org -Source0: https://github.com/exaile/exaile/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz +Source0: https://github.com/exaile/exaile/archive/%{version}/%{name}-%{version}.tar.gz BuildArch: noarch + BuildRequires: desktop-file-utils BuildRequires: gettext BuildRequires: help2man BuildRequires: libappstream-glib BuildRequires: pygobject2-devel >= 2.18 + # Warning for the future releases: # gstreamer 1.x transition required. # RPM weak dependencies support. Requires: python2-dbus -Requires: gstreamer-plugins-good -Requires: python2-gstreamer >= 0.10 +Requires: gstreamer1-plugins-good +Requires: python2-gstreamer1 >= 1.4 Requires: librsvg2 -Requires: pygtk2 >= 2.17 Requires: pygobject2 >= 2.18 Requires: python2-cddb Requires: python2-mutagen >= 1.10 @@ -55,7 +56,7 @@ find . -type f -name "Makefile" -exec \ %make_build %install -%make_install PREFIX=%{_prefix} LIBINSTALLDIR=/share PYTHON2_CMD=%{__python2} +%make_install PREFIX=%{_prefix} LIBINSTALLDIR=%{_datadir} PYTHON2_CMD=%{__python2} desktop-file-install --delete-original \ --dir=%{buildroot}%{_datadir}/applications \ @@ -68,11 +69,13 @@ appstream-util validate-relax --nonet %{buildroot}%{_datadir}/appdata/*.appdata. #make test %files -f %{name}.lang -%doc FUTURE +%doc README.md %license COPYING %{_bindir}/exaile %{_datadir}/appdata/exaile.appdata.xml %{_datadir}/applications/exaile.desktop +%{_datadir}/bash-completion/completions/exaile +%{_datadir}/fish/vendor_completions.d/exaile.fish %{_datadir}/pixmaps/exaile.png %{_datadir}/exaile/ %{_datadir}/dbus-1/services/org.exaile.Exaile.service @@ -81,6 +84,9 @@ appstream-util validate-relax --nonet %{buildroot}%{_datadir}/appdata/*.appdata. %{_mandir}/man1/exaile*.1* %changelog +* Thu Jun 20 2019 Leigh Scott - 4.0.0-1 +- Update to 4.0.0 + * Thu Jan 31 2019 Fedora Release Engineering - 3.4.5-10 - Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild diff --git a/sources b/sources index 9498b4e..fb58118 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -bd0d0fbc4edfc9dfb9d18513614c0184 exaile-3.4.5.tar.gz +SHA512 (exaile-4.0.0.tar.gz) = 66ec7cafed6ac12dd528d0e7d7262e0b3300269e4fd3ded2016dfd5ea308d08b8b6000e61366de0d381b299c955442454559154d5f4e1f7e48cd62298f6a3e43