[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