Hello community,

here is the log from the commit of package pithos for openSUSE:Factory checked 
in at 2014-12-05 21:04:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/pithos (Old)
 and      /work/SRC/openSUSE:Factory/.pithos.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "pithos"

Changes:
--------
--- /work/SRC/openSUSE:Factory/pithos/pithos.changes    2014-09-30 
19:36:15.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.pithos.new/pithos.changes       2014-12-05 
21:05:00.000000000 +0100
@@ -1,0 +2,17 @@
+Sun Nov 30 05:27:22 UTC 2014 - malcolmle...@opensuse.org
+
+- Update to version 1.0.1:
+  + Automatically install missing codecs if supported.
+  + Save window position between sessions.
+  + Fix saving last station on quit.
+  + Fix pacparser support.
+  + Improve pandora module docs.
+  + Add setup.py command to build docs.
+  + Add appdata file.
+  + Notification_icon: Make toggling visibility more reliable.
+  + mpris: Fix exception when querying positon.
+  + mpris: Implement setting volume.
+- Update fixes Pandora stream and hangs at "loading songs" This
+  occurs randomly, sometimes very frequently (boo#907701).
+
+-------------------------------------------------------------------

Old:
----
  1.0.0.tar.gz

New:
----
  1.0.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ pithos.spec ++++++
--- /var/tmp/diff_new_pack.OC3zRt/_old  2014-12-05 21:05:01.000000000 +0100
+++ /var/tmp/diff_new_pack.OC3zRt/_new  2014-12-05 21:05:01.000000000 +0100
@@ -18,13 +18,13 @@
 
 
 Name:           pithos
-Version:        1.0.0
+Version:        1.0.1
 Release:        0
 Summary:        Native Pandora Radio client for Linux
 License:        GPL-3.0
 Group:          Productivity/Multimedia/Other
 Url:            http://pithos.github.io/
-Source0:        https://github.com/pithos/pithos/archive/1.0.0.tar.gz
+Source0:        https://github.com/pithos/pithos/archive/1.0.1.tar.gz
 BuildRequires:  fdupes
 # Needed for automatic typelib() Requires.
 BuildRequires:  gobject-introspection
@@ -78,5 +78,7 @@
 %{python3_sitelib}/pithos-%{version}-py%{py3_ver}.egg-info
 %{_datadir}/applications/pithos.desktop
 %{_datadir}/icons/hicolor/*/apps/pithos*
+%dir %{_datadir}/appdata/
+%{_datadir}/appdata/pithos.appdata.xml
 
 %changelog

++++++ 1.0.0.tar.gz -> 1.0.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/MANIFEST.in new/pithos-1.0.1/MANIFEST.in
--- old/pithos-1.0.0/MANIFEST.in        2014-05-02 00:33:16.000000000 +0200
+++ new/pithos-1.0.1/MANIFEST.in        2014-09-21 12:30:03.000000000 +0200
@@ -1,4 +1,4 @@
 include README.md
-recursive-include data *.svg pithos.desktop
+recursive-include data *.svg pithos.desktop *.xml
 recursive-include pithos/data/ui *.ui *.xml
 recursive-include pithos/data/media *.png *.svg
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/data/pithos.appdata.xml 
new/pithos-1.0.1/data/pithos.appdata.xml
--- old/pithos-1.0.0/data/pithos.appdata.xml    1970-01-01 01:00:00.000000000 
+0100
+++ new/pithos-1.0.1/data/pithos.appdata.xml    2014-09-21 12:30:03.000000000 
+0200
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<application>
+       <id type="desktop">pithos.desktop</id>
+       <metadata_license>CC0</metadata_license>
+       <project_license>GPL-3.0+</project_license>
+       <description>
+               <p>Pithos is a easy to use native Pandora Radio client that is 
more lightweight than the pandora.com web client and integrates with the 
desktop.</p>
+               <p>It supports most functionality of pandora.com such as rating 
songs, creating/managing stations, quickmix, etc. On top of that it has 
features such as last.fm scrobbling, media keys, notifications, proxies, and 
mpris support.</p>
+       </description>
+       <url type="homepage">https://pithos.github.io</url>
+       <screenshots>
+               <screenshot 
type="default">https://i.imgur.com/1vl3Dsk.png</screenshot>
+       </screenshots>
+       <updatecontact>tingping_at_fedoraproject.org</updatecontact>
+</application>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/docs/conf.py 
new/pithos-1.0.1/docs/conf.py
--- old/pithos-1.0.0/docs/conf.py       1970-01-01 01:00:00.000000000 +0100
+++ new/pithos-1.0.1/docs/conf.py       2014-09-21 12:30:03.000000000 +0200
@@ -0,0 +1,234 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Pithos documentation build configuration file, created by
+# sphinx-quickstart on Mon Sep 15 20:13:58 2014.
+#
+# This file is execfile()d with the current directory set to its containing 
dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration 
-----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be 
extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'Pithos'
+copyright = '2014, Kevin Mehall'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all 
documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output 
---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Pithosdoc'
+
+
+# -- Options for LaTeX output 
--------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass 
[howto/manual]).
+latex_documents = [
+  ('index', 'Pithos.tex', 'Pithos Documentation',
+   'Kevin Mehall', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output 
--------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'pithos', 'Pithos Documentation',
+     ['Kevin Mehall'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output 
------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'Pithos', 'Pithos Documentation',
+   'Kevin Mehall', 'Pithos', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/docs/index.rst 
new/pithos-1.0.1/docs/index.rst
--- old/pithos-1.0.0/docs/index.rst     1970-01-01 01:00:00.000000000 +0100
+++ new/pithos-1.0.1/docs/index.rst     2014-09-21 12:30:03.000000000 +0200
@@ -0,0 +1,38 @@
+.. Pithos documentation master file, created by
+   sphinx-quickstart on Mon Sep 15 20:13:58 2014.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Welcome to Pithos's documentation!
+==================================
+
+Pandora
+-------
+
+.. autoclass:: pithos.pandora.Pandora
+   :members:
+   :undoc-members:
+
+.. autoclass:: pithos.pandora.Station
+   :members:
+   :undoc-members:
+
+.. autoclass:: pithos.pandora.Song
+   :members:
+   :undoc-members:
+
+.. autoclass:: pithos.pandora.SearchResult
+   :members:
+   :undoc-members:
+
+.. autoclass:: pithos.pandora.PandoraError
+   :members:
+   :undoc-members:
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/PreferencesPithosDialog.py 
new/pithos-1.0.1/pithos/PreferencesPithosDialog.py
--- old/pithos-1.0.0/pithos/PreferencesPithosDialog.py  2014-05-02 
00:33:16.000000000 +0200
+++ new/pithos-1.0.1/pithos/PreferencesPithosDialog.py  2014-09-21 
12:30:03.000000000 +0200
@@ -87,6 +87,8 @@
         self.__preferences = {
             "username":'',
             "password":'',
+            "x_pos": None,
+            "y_pos": None,
             "notify":True,
             "last_station_id":None,
             "proxy":'',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/__main__.py 
new/pithos-1.0.1/pithos/__main__.py
--- old/pithos-1.0.0/pithos/__main__.py 1970-01-01 01:00:00.000000000 +0100
+++ new/pithos-1.0.1/pithos/__main__.py 2014-09-21 12:30:03.000000000 +0200
@@ -0,0 +1,3 @@
+from pithos.pithos import main
+
+main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/data/ui/PithosWindow.ui 
new/pithos-1.0.1/pithos/data/ui/PithosWindow.ui
--- old/pithos-1.0.0/pithos/data/ui/PithosWindow.ui     2014-05-02 
00:33:16.000000000 +0200
+++ new/pithos-1.0.1/pithos/data/ui/PithosWindow.ui     2014-09-21 
12:30:03.000000000 +0200
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.0 -->
+<!-- Generated with glade 3.16.1 -->
 <interface>
   <requires lib="gtk+" version="3.6"/>
-  <requires lib="pithos_window" version="1.0"/>
+  <!-- interface-requires pithos_window 1.0 -->
   <object class="GtkAdjustment" id="adjustment1">
     <property name="upper">100</property>
     <property name="step_increment">1</property>
@@ -17,6 +17,7 @@
     <property name="icon_name">pithos</property>
     <signal name="destroy" handler="on_destroy" swapped="no"/>
     <signal name="key-press-event" handler="on_kb_playpause" swapped="no"/>
+    <signal name="configure-event" handler="on_configure_event" swapped="no"/>
     <child>
       <object class="GtkBox" id="vbox1">
         <property name="visible">True</property>
@@ -243,7 +244,6 @@
   <object class="GtkMessageDialog" id="api_update_dialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
-    <property name="type">popup</property>
     <property name="modal">True</property>
     <property name="type_hint">dialog</property>
     <property name="transient_for">pithos_window</property>
@@ -308,7 +308,6 @@
   <object class="GtkMessageDialog" id="fatal_error_dialog">
     <property name="can_focus">False</property>
     <property name="border_width">5</property>
-    <property name="type">popup</property>
     <property name="modal">True</property>
     <property name="type_hint">dialog</property>
     <property name="skip_taskbar_hint">True</property>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/mpris.py 
new/pithos-1.0.1/pithos/mpris.py
--- old/pithos-1.0.0/pithos/mpris.py    2014-05-02 00:33:16.000000000 +0200
+++ new/pithos-1.0.1/pithos/mpris.py    2014-09-21 12:30:03.000000000 +0200
@@ -96,8 +96,11 @@
     def _get_volume(self):
         return self.window.player.get_property("volume")
 
+    def _set_volume(self, new_volume):
+        self.window.player.set_property('volume', new_volume)
+
     def _get_position(self):
-        return self.window.player.query_position(self.window.time_format, 
None)[0] / 1000
+        return self.window.player.query_position(self.window.time_format)[0] / 
1000
 
     @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature='ss', 
out_signature='v')
     def Get(self, interface_name, property_name):
@@ -112,7 +115,8 @@
         if interface_name == self.MEDIA_PLAYER2_IFACE:
             pass
         elif interface_name == self.MEDIA_PLAYER2_PLAYER_IFACE:
-            pass # TODO: volume
+            if property_name == 'Volume':
+                self._set_volume(new_value)
         else:
             raise dbus.exceptions.DBusException(
                 'org.mpris.MediaPlayer2.pithos',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/pandora/__init__.py 
new/pithos-1.0.1/pithos/pandora/__init__.py
--- old/pithos-1.0.0/pithos/pandora/__init__.py 2014-05-02 00:33:16.000000000 
+0200
+++ new/pithos-1.0.1/pithos/pandora/__init__.py 2014-09-21 12:30:03.000000000 
+0200
@@ -14,7 +14,7 @@
 #with this program.  If not, see <http://www.gnu.org/licenses/>.
 ### END LICENSE
 
-from pithos.pandora.pandora import *
+from .pandora import *
 
 def make_pandora(testing=False):
     if testing:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/pandora/fake.py 
new/pithos-1.0.1/pithos/pandora/fake.py
--- old/pithos-1.0.0/pithos/pandora/fake.py     2014-05-02 00:33:16.000000000 
+0200
+++ new/pithos-1.0.1/pithos/pandora/fake.py     2014-09-21 12:30:03.000000000 
+0200
@@ -14,7 +14,7 @@
 #with this program.  If not, see <http://www.gnu.org/licenses/>.
 ### END LICENSE
 
-from pithos.pandora.pandora import *
+from .pandora import *
 from gi.repository import Gtk
 import logging
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/pandora/pandora.py 
new/pithos-1.0.1/pithos/pandora/pandora.py
--- old/pithos-1.0.0/pithos/pandora/pandora.py  2014-05-02 00:33:16.000000000 
+0200
+++ new/pithos-1.0.1/pithos/pandora/pandora.py  2014-09-21 12:30:03.000000000 
+0200
@@ -15,6 +15,11 @@
 #with this program.  If not, see <http://www.gnu.org/licenses/>.
 ### END LICENSE
 
+"""Pandora JSON v5 API
+
+See http://6xq.net/playground/pandora-apidoc/json/ for API documentation.
+"""
+
 from .blowfish import Blowfish
 # from Crypto.Cipher import Blowfish
 from xml.dom import minidom
@@ -25,10 +30,6 @@
 import urllib.request, urllib.parse, urllib.error
 import codecs
 
-# This is an implementation of the Pandora JSON API using Android partner
-# credentials.
-# See http://pan-do-ra-api.wikia.com/wiki/Json/5 for API documentation.
-
 HTTP_TIMEOUT = 30
 USER_AGENT = 'pithos'
 
@@ -65,6 +66,17 @@
     return s + b'\0' * (l - len(s))
 
 class Pandora(object):
+    """Access the Pandora API
+
+    To use the Pandora class, make sure to call :py:meth:`set_audio_quality`
+    and :py:meth:`connect` methods.
+
+    Get information from Pandora using:
+
+    - :py:meth:`get_stations` which populates the :py:attr:`stations` attribute
+    - :py:meth:`search` to find songs to add to stations or create a new 
station with
+    - :py:meth:`json_call` call into the JSON API directly
+    """
     def __init__(self):
         self.opener = urllib.request.build_opener()
         pass
@@ -131,7 +143,7 @@
                 raise PandoraAuthTokenInvalid(msg)
             elif code == API_ERROR_COUNTRY_NOT_SUPPORTED:
                  raise PandoraError("Pandora not available", code,
-                    submsg="Pandora is not available outside the United 
States.")
+                    submsg="Pandora is not available in your country.")
             elif code == API_ERROR_API_VERSION_NOT_SUPPORTED:
                 raise PandoraAPIVersionError(msg)
             elif code == API_ERROR_INSUFFICIENT_CONNECTIVITY:
@@ -158,12 +170,24 @@
             return tree['result']
 
     def set_audio_quality(self, fmt):
+        """Set the desired audio quality
+
+        Used by the :py:attr:`Song.audioUrl` property.
+
+        :param fmt: An audio quality format from 
:py:data:`pithos.pandora.data.valid_audio_formats`
+        """
         self.audio_quality = fmt
 
     def set_url_opener(self, opener):
         self.opener = opener
 
     def connect(self, client, user, password):
+        """Connect to the Pandora API and log the user in
+
+        :param client:   The client ID from 
:py:data:`pithos.pandora.data.client_keys`
+        :param user:     The user's login email
+        :param password: The user's login password
+        """
         self.partnerId = self.userId = self.partnerAuthToken = None
         self.userAuthToken = self.time_offset = None
 
@@ -201,6 +225,8 @@
                 if i.id in self.quickMixStationIds:
                     i.useQuickMix = True
 
+        return self.stations
+
     def save_quick_mix(self):
         stationIds = []
         for i in self.stations:
@@ -281,6 +307,14 @@
         logging.info("pandora: Deleting Station")
         self.pandora.json_call('station.deleteStation', {'stationToken': 
self.idToken})
 
+    def __repr__(self):
+        return '<{}.{} {} "{}">'.format(
+            __name__,
+            __class__.__name__,
+            self.id,
+            self.name,
+        )
+
 class Song(object):
     def __init__(self, pandora, d):
         self.pandora = pandora
@@ -378,6 +412,16 @@
     def is_still_valid(self):
         return (time.time() - self.playlist_time) < PLAYLIST_VALIDITY_TIME
 
+    def __repr__(self):
+        return '<{}.{} {} "{}" by "{}" from "{}">'.format(
+            __name__,
+            __class__.__name__,
+            self.trackToken,
+            self.songName,
+            self.artist,
+            self.album,
+        )
+
 
 class SearchResult(object):
     def __init__(self, resultType, d):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/pithos.py 
new/pithos-1.0.1/pithos/pithos.py
--- old/pithos-1.0.0/pithos/pithos.py   2014-05-02 00:33:16.000000000 +0200
+++ new/pithos-1.0.1/pithos/pithos.py   2014-09-21 12:30:03.000000000 +0200
@@ -23,7 +23,7 @@
 
 import gi
 gi.require_version('Gst', '1.0')
-from gi.repository import Gst, GObject, Gtk, Gdk, Pango, GdkPixbuf, Gio, GLib
+from gi.repository import Gst, GstPbutils, GObject, Gtk, Gdk, Pango, 
GdkPixbuf, Gio, GLib
 import contextlib
 import html
 import math
@@ -201,6 +201,7 @@
         bus.connect("message::eos", self.on_gst_eos)
         bus.connect("message::buffering", self.on_gst_buffering)
         bus.connect("message::error", self.on_gst_error)
+        bus.connect("message::element", self.on_gst_element)
         bus.connect("message::tag", self.on_gst_tag)
         self.player.connect("notify::volume", self.on_gst_volume)
         self.player.connect("notify::source", self.on_gst_source)
@@ -284,6 +285,8 @@
         self.stations_combo.add_attribute(render_text, "text", 1)
         self.stations_combo.set_row_separator_func(lambda model, iter, 
data=None: model.get_value(iter, 0) is None, None)
 
+        self.set_initial_pos()
+
     def worker_run(self, fn, args=(), callback=None, message=None, 
context='net'):
         if context and message:
             self.statusbar.push(self.statusbar.get_context_id(context), 
message)
@@ -353,15 +356,24 @@
 
         elif control_proxy_pac and pacparser_imported:
             pacparser.init()
-            
pacparser.parse_pac_string(urllib.request.urlopen(control_proxy_pac).read())
-            proxies = pacparser.find_proxy("http://pandora.com";, 
"pandora.com").split(";")
-            for proxy in proxies:
-                match = re.search("PROXY (.*)", proxy)
-                if match:
-                    control_proxy = match.group(1)
-                    break
+            with urllib.request.urlopen(control_proxy_pac) as f:
+                pacstring = f.read().decode('utf-8')
+                try:
+                    pacparser.parse_pac_string(pacstring)
+                except:
+                    logging.warning('Failed to parse PAC.')
+            try:
+                proxies = pacparser.find_proxy("http://pandora.com";, 
"pandora.com").split(";")
+                for proxy in proxies:
+                    match = re.search("PROXY (.*)", proxy)
+                    if match:
+                        control_proxy = match.group(1)
+                        break
+            except:
+                logging.warning('Failed to find proxy via PAC.')
+            pacparser.cleanup()
         elif control_proxy_pac and not pacparser_imported:
-            logging.warn("Disabled proxy auto-config support because 
python-pacparser module was not found.")
+            logging.warning("Disabled proxy auto-config support because 
python-pacparser module was not found.")
 
         self.worker_run('set_url_opener', (control_opener,))
 
@@ -572,6 +584,10 @@
         dialog.props.secondary_text = submsg
         dialog.set_default_response(3)
 
+        if retry_cb is None:
+            btn = self.builder.get_object("button2")
+            btn.hide()
+
         response = dialog.run()
         dialog.hide()
 
@@ -622,19 +638,34 @@
         logging.info("EOS")
         self.next_song()
 
+    def on_gst_plugin_installed(self, result, userdata):
+        if result == GstPbutils.InstallPluginsReturn.SUCCESS:
+            self.fatal_error_dialog("Codec installation successful",
+                        submsg="The required codec was installed, please 
restart Pithos.")
+        else:
+            self.error_dialog("Codec installation failed", None,
+                        submsg="The required codec failed to install. Either 
manually install it or try another quality setting.")
+
+    def on_gst_element(self, bus, message):
+        if GstPbutils.is_missing_plugin_message(message):
+            if GstPbutils.install_plugins_supported():
+                details = 
GstPbutils.missing_plugin_message_get_installer_detail(message)
+                GstPbutils.install_plugins_async([details,], None, 
self.on_gst_plugin_installed, None)
+            else:
+                self.error_dialog("Missing codec", None,
+                        submsg="GStreamer is missing a plugin and it could not 
be automatically installed. Either manually install it or try another quality 
setting.")
+
     def on_gst_error(self, bus, message):
         err, debug = message.parse_error()
         logging.error("Gstreamer error: %s, %s, %s" % (err, debug, err.code))
         if self.current_song:
             self.current_song.message = "Error: "+str(err)
 
-        #if err.code is int(Gst.CORE_ERROR_MISSING_PLUGIN):
-        #    self.fatal_error_dialog("Missing codec", submsg="GStreamer is 
missing a plugin")
-        #    return
-
         self.gstreamer_error = str(err)
         self.gstreamer_errorcount_1 += 1
-        self.next_song()
+
+        if not GstPbutils.install_plugins_installation_in_progress():
+            self.next_song()
 
     def gst_tag_handler(self, tag_info):
         def handler(_x, tag, _y):
@@ -951,10 +982,20 @@
     def refresh_stations(self, *ignore):
         self.worker_run(self.pandora.get_stations, (), self.process_stations, 
"Refreshing stations...")
 
+    def set_initial_pos(self):
+        """ Moves window to position stored in preferences """
+        x, y = self.preferences['x_pos'], self.preferences['y_pos']
+        if not x is None and not y is None:
+            self.move(int(x), int(y))
+
     def bring_to_top(self, *ignore):
+        self.set_initial_pos()
         self.show()
         self.present()
 
+    def on_configure_event(self, widget, event):
+        self.preferences['x_pos'], self.preferences['y_pos'] = event.x, event.y
+
     def on_kb_playpause(self, widget=None, data=None):
         if not isinstance(widget.get_focus(), Gtk.Button) and data.keyval == 
32:
             self.playpause()
@@ -1053,7 +1094,7 @@
 
     def do_shutdown(self):
         Gtk.Application.do_shutdown(self)
-        self.quit()
+        self.window.destroy()
 
     def stations_cb(self, action, param):
         self.window.show_stations()
@@ -1065,7 +1106,7 @@
         self.window.show_about()
 
     def quit_cb(self, action, param):
-        self.quit()
+        self.window.destroy()
 
 def main():
     app = PithosApplication()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/pithosconfig.py 
new/pithos-1.0.1/pithos/pithosconfig.py
--- old/pithos-1.0.0/pithos/pithosconfig.py     2014-05-02 00:33:16.000000000 
+0200
+++ new/pithos-1.0.1/pithos/pithosconfig.py     2014-09-21 12:30:03.000000000 
+0200
@@ -19,7 +19,7 @@
 __pithos_data_directory__ = 'data/'
 __license__ = 'GPL-3'
 
-VERSION = '1.0.0'
+VERSION = '1.0.1'
 
 import os
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/plugins/mediakeys.py 
new/pithos-1.0.1/pithos/plugins/mediakeys.py
--- old/pithos-1.0.0/pithos/plugins/mediakeys.py        2014-05-02 
00:33:16.000000000 +0200
+++ new/pithos-1.0.1/pithos/plugins/mediakeys.py        2014-09-21 
12:30:03.000000000 +0200
@@ -22,7 +22,7 @@
 
 class MediaKeyPlugin(PithosPlugin):
     preference = 'enable_mediakeys'
-    
+
     def bind_dbus(self):
         try:
             import dbus
@@ -86,12 +86,42 @@
         self.hookman.KeyDown = self.kbevent
         self.hookman.HookKeyboard()
         return True
+
+    def osx_playpause_handler(self):
+        self.window.playpause_notify()
+        return False # Don't let others get event
+
+    def osx_skip_handler(self):
+        self.window.next_song()
+        return False
+
+    def bind_osx(self):
+        try:
+            import osxmmkeys
+        except ImportError:
+            logging.warning('Please install osxmmkeys: 
https://github.com/pushrax/osxmmkeys')
+            return False
+        except RuntimeError as e:
+            logging.warning('osxmmkeys failed to import: {}'.format(e))
+            return False
+
+        tap = osxmmkeys.Tap()
+        tap.on('play_pause', self.osx_playpause_handler)
+        tap.on('next_track', self.osx_skip_handler)
+        tap.start()
+
+        return True
         
     def on_enable(self):
         if sys.platform == 'win32':
-            self.bind_win32() or logging.error("Could not bind media keys")
+            loaded = self.bind_win32()
+        elif sys.platform == 'darwin':
+            loaded = self.bind_osx()
         else:
-            self.bind_dbus() or self.bind_keybinder() or logging.error("Could 
not bind media keys")
+            loaded = self.bind_dbus() or self.bind_keybinder()
+
+        if not loaded:
+            logging.error("Could not bind media keys")
         
     def on_disable(self):
         logging.error("Not implemented: Can't disable media keys")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/plugins/notification_icon.py 
new/pithos-1.0.1/pithos/plugins/notification_icon.py
--- old/pithos-1.0.0/pithos/plugins/notification_icon.py        2014-05-02 
00:33:16.000000000 +0200
+++ new/pithos-1.0.1/pithos/plugins/notification_icon.py        2014-09-21 
12:30:03.000000000 +0200
@@ -40,7 +40,6 @@
                                    get_data_file('media'))
     
     def on_enable(self):
-        self.visible = True
         self.delete_callback_handle = self.window.connect("delete-event", 
self.toggle_visible)
         self.state_callback_handle = self.window.connect("play-state-changed", 
self.play_state_changed)
         self.song_callback_handle = self.window.connect("song-changed", 
self.song_changed)
@@ -131,16 +130,14 @@
             self.statusicon.set_tooltip_text("%s by %s"%(song.title, 
song.artist))
         
     def _toggle_visible(self, *args):
-        if self.visible:
-            self.window.hide()
-        else:
+        self.window.set_visible(not self.window.get_visible())
+
+        if self.window.get_visible(): # Ensure it's on top
             self.window.bring_to_top()
         
-        self.visible = not self.visible
-        
     def toggle_visible(self, *args):
         if hasattr(self, 'visible_check'):
-            self.visible_check.set_active(not self.visible)
+            self.visible_check.set_active(not self.window.get_visible())
         else:
             self._toggle_visible()
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/plugins/notify.py 
new/pithos-1.0.1/pithos/plugins/notify.py
--- old/pithos-1.0.0/pithos/plugins/notify.py   2014-05-02 00:33:16.000000000 
+0200
+++ new/pithos-1.0.1/pithos/plugins/notify.py   2014-09-21 12:30:03.000000000 
+0200
@@ -16,6 +16,7 @@
 
 import logging
 import html
+from sys import platform
 from pithos.plugin import PithosPlugin
 from pithos.pithosconfig import get_data_file
 from gi.repository import (GLib, Gtk)
@@ -23,13 +24,29 @@
 class NotifyPlugin(PithosPlugin):
     preference = 'notify'
 
-    has_notify = False
+    has_notifications = False
     supports_actions = False
 
     def on_prepare(self):
+        if platform == 'darwin':
+            self.prepare_osx()
+        else:
+            self.prepare_notify()
+
+    def prepare_osx(self):
+        try:
+            from pync import Notifier
+            self.has_notifications = True
+        except ImportError:
+            logging.warning("pync not found.")
+            return
+
+        self.notifier = Notifier
+
+    def prepare_notify(self):
         try:
             from gi.repository import Notify
-            self.has_notify = True
+            self.has_notifications = True
         except ImportError:
             logging.warning ("libnotify not found.")
             return
@@ -62,7 +79,7 @@
         #    self.notification.set_hint('resident', 
GLib.Variant.new_boolean(True))
 
     def on_enable(self):
-        if self.has_notify:
+        if self.has_notifications:
             self.song_callback_handle = self.window.connect("song-changed", 
self.song_changed)
             self.state_changed_handle = 
self.window.connect("user-changed-play-state", self.playstate_changed)
 
@@ -87,7 +104,7 @@
         self.notification.add_action(skip_action, 'Skip',
                                      self.notification_skip_cb, None)
 
-    def set_notification(self, song, playing=True):
+    def set_notification_notify(self, song, playing):
         if self.supports_actions:
             self.set_actions(playing)
 
@@ -100,6 +117,18 @@
         self.notification.update(song.title, msg, 'audio-x-generic')
         self.notification.show()
 
+    def set_notification_osx(self, song, playing):
+        # TODO: Icons (buttons not possible?)
+        if playing:
+            self.notifier.notify('by {} from {}'.format(song.artist, 
song.album),
+                                title=song.title)
+
+    def set_notification(self, song, playing=True):
+        if platform == 'darwin':
+            self.set_notification_osx(song, playing)
+        else:
+            self.set_notification_notify(song, playing)
+
     def notification_playpause_cb(self, notification, action, data, 
ignore=None):
         self.window.playpause_notify()
 
@@ -115,6 +144,6 @@
             GLib.idle_add(self.set_notification, window.current_song, state)
 
     def on_disable(self):
-        if self.has_notify:
+        if self.has_notifications:
             self.window.disconnect(self.song_callback_handle)
             self.window.disconnect(self.state_changed_handle)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/pithos/plugins/screensaver_pause.py 
new/pithos-1.0.1/pithos/plugins/screensaver_pause.py
--- old/pithos-1.0.0/pithos/plugins/screensaver_pause.py        2014-05-02 
00:33:16.000000000 +0200
+++ new/pithos-1.0.1/pithos/plugins/screensaver_pause.py        2014-09-21 
12:30:03.000000000 +0200
@@ -1,29 +1,30 @@
 # -*- coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*-
 ### BEGIN LICENSE
 # Copyright (C) 2010-2012 Kevin Mehall <k...@kevinmehall.net>
-#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 
+#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 
+#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 
+#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
 
 from pithos.plugin import PithosPlugin
 import logging
 
-
+dbus = None
 class ScreenSaverPausePlugin(PithosPlugin):
     preference = 'enable_screensaverpause'
 
     session_bus = None
-    
+
     def bind_session_bus(self):
+        global dbus
         try:
             import dbus
         except ImportError:
@@ -34,13 +35,16 @@
             return True
         except dbus.DBusException:
             return False
-        
+
     def on_enable(self):
         if not self.bind_session_bus():
             logging.error("Could not bind session bus")
             return
         self.connect_events() or logging.error("Could not connect events")
 
+        self.locked = 0
+        self.wasplaying = False
+
     def on_disable(self):
         if self.session_bus:
             self.disconnect_events()
@@ -49,9 +53,16 @@
 
     def connect_events(self):
         try:
-            self.session_bus.add_signal_receiver(self.playPause, 
'ActiveChanged', 'org.gnome.ScreenSaver')
-            self.session_bus.add_signal_receiver(self.playPause, 
'ActiveChanged', 'org.cinnamon.ScreenSaver')
-            self.session_bus.add_signal_receiver(self.playPause, 
'ActiveChanged', 'org.freedesktop.ScreenSaver')
+            self.receivers = [
+                self.session_bus.add_signal_receiver(*args)
+                for args in ((self.playPause, 'ActiveChanged', 
'org.gnome.ScreenSaver'),
+                             (self.playPause, 'ActiveChanged', 
'org.cinnamon.ScreenSaver'),
+                             (self.playPause, 'ActiveChanged', 
'org.freedesktop.ScreenSaver'),
+                             (self.pause, 'Locked', 
'com.canonical.Unity.Session'),
+                             (self.play, 'Unlocked', 
'com.canonical.Unity.Session'),
+                            )
+                ]
+
             return True
         except dbus.DBusException:
             logging.info("Enable failed")
@@ -59,18 +70,27 @@
 
     def disconnect_events(self):
         try:
-            self.session_bus.remove_signal_receiver(self.playPause, 
'ActiveChanged', 'org.gnome.ScreenSaver')
-            self.session_bus.remove_signal_receiver(self.playPause, 
'ActiveChanged', 'org.cinnamon.ScreenSaver')
-            self.session_bus.remove_signal_receiver(self.playPause, 
'ActiveChanged', 'org.freedesktop.ScreenSaver')
+            for r in self.receivers:
+                r.remove()
             return True
         except dbus.DBusException:
             return False
-            
-    
-    def playPause(self,state):
-        if not state:
-            if self.wasplaying:
-                self.window.user_play()
-        else:
+
+    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
+
+    def playPause(self, screensaver_on):
+        if screensaver_on:
+            self.pause()
+        else:
+            self.play()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/requirements-osx.txt 
new/pithos-1.0.1/requirements-osx.txt
--- old/pithos-1.0.0/requirements-osx.txt       1970-01-01 01:00:00.000000000 
+0100
+++ new/pithos-1.0.1/requirements-osx.txt       2014-09-21 12:30:03.000000000 
+0200
@@ -0,0 +1,11 @@
+# scrobble
+pylast
+
+# notify
+pync
+
+# mediakeys
+pyobjc-core
+pyobjc-framework-Cocoa
+pyobjc-framework-Quartz
+osxmmkeys
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pithos-1.0.0/setup.py new/pithos-1.0.1/setup.py
--- old/pithos-1.0.0/setup.py   2014-05-02 00:33:16.000000000 +0200
+++ new/pithos-1.0.1/setup.py   2014-09-21 12:30:03.000000000 +0200
@@ -18,11 +18,27 @@
 ###################### DO NOT TOUCH THIS (HEAD TO THE SECOND PART) 
######################
 
 try:
-    from setuptools import setup, find_packages
+    from setuptools import setup, find_packages, Command
 except ImportError:
     import ez_setup
     ez_setup.use_setuptools()
-    from setuptools import setup, find_packages
+    from setuptools import setup, find_packages, Command
+
+try:
+    from sphinx.setup_command import BuildDoc
+except ImportError:
+    class BuildDoc(Command):
+        description = "Build documentation with Sphinx."
+        user_options = []
+        version = None
+        release = None
+
+        def initialize_options(self):
+            pass
+        def finalize_options(self):
+            pass
+        def run(self):
+            print("Error: Sphinx not found!")
 
 import os
 import sys
@@ -41,6 +57,7 @@
         ('/usr/share/icons/hicolor/48x48/apps', 
['data/icons/hicolor/pithos-tray-icon.png']),
         ('/usr/share/icons/ubuntu-mono-dark/apps/16', 
['data/icons/ubuntu-mono-dark/pithos-tray-icon.svg']),
         ('/usr/share/icons/ubuntu-mono-light/apps/16', 
['data/icons/ubuntu-mono-light/pithos-tray-icon.svg']),
+        ('/usr/share/appdata', ['data/pithos.appdata.xml']),
         ('/usr/share/applications', ['data/pithos.desktop'])
     ]
 else:
@@ -64,6 +81,15 @@
         'Programming Language :: Python',
         'Programming Language :: Python :: 3'
     ],
+    cmdclass={
+        'build_doc': BuildDoc
+    },
+    command_options={
+        'build_doc': {
+            'version': ('setup.py', VERSION),
+            'release': ('setup.py', VERSION)
+        }
+    },
     data_files=data_files,
     package_data={
         'pithos': [

-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to