[exaile] Update to 3.3.2
Deji Akingunola
deji at fedoraproject.org
Fri Feb 21 05:51:10 UTC 2014
commit cf56c702b958e6d941d71807d2e457cb760cd414
Author: Deji Akingunola <dakingun at gmail.com>
Date: Fri Feb 21 00:52:00 2014 -0500
Update to 3.3.2
.gitignore | 1 +
exaile-3.3.1-udisks.patch | 223 -----------------------------
exaile-3.3.2-udisks.patch | 343 +++++++++++++++++++++++++++++++++++++++++++++
exaile.spec | 11 +-
sources | 2 +-
5 files changed, 352 insertions(+), 228 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 2a19c8e..974efc6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ exaile-0.3.2.0.tar.gz
/exaile-0.3.2.2.tar.gz
/exaile-3.3.0.tar.gz
/exaile-3.3.1.tar.gz
+/exaile-3.3.2.tar.gz
diff --git a/exaile-3.3.2-udisks.patch b/exaile-3.3.2-udisks.patch
new file mode 100644
index 0000000..303ff51
--- /dev/null
+++ b/exaile-3.3.2-udisks.patch
@@ -0,0 +1,343 @@
+=== 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 2fec552..c8eac3d 100644
--- a/exaile.spec
+++ b/exaile.spec
@@ -1,13 +1,13 @@
Summary: A music player
Name: exaile
-Version: 3.3.1
-Release: 4%{?dist}
+Version: 3.3.2
+Release: 1%{?dist}
Group: Applications/Multimedia
License: GPLv2+
URL: http://www.exaile.org
-Source0: http://launchpad.net/exaile/3.3.x/3.3.1/+download/exaile-%{version}.tar.gz
+Source0: http://launchpad.net/exaile/3.3.x/3.3.2/+download/exaile-%{version}.tar.gz
Patch0: exaile-3.3.1-makefile.patch
-Patch1: exaile-3.3.1-udisks.patch
+Patch1: exaile-3.3.2-udisks.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: pygobject2-devel
BuildRequires: desktop-file-utils
@@ -70,6 +70,9 @@ rm -rf %{buildroot}
%{_mandir}/man1/exaile*.*
%changelog
+* Fri Feb 21 2014 Deji Akingunola <dakingun at gmail.com> - 3.3.2-1
+- Update to 3.3.2
+
* Sat Aug 03 2013 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 3.3.1-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
diff --git a/sources b/sources
index 21b30fd..8f007e3 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-cd7ea267a9d53cdd5231912f19ae03f8 exaile-3.3.1.tar.gz
+117994e96065b4f767ac552c80808040 exaile-3.3.2.tar.gz
More information about the scm-commits
mailing list