[Python-modules-commits] [python-soco] 01/07: import soco_0.12.orig.tar.gz
Ruben Undheim
rubund-guest at moszumanska.debian.org
Tue Dec 13 18:37:30 UTC 2016
This is an automated email from the git hooks/post-receive script.
rubund-guest pushed a commit to branch master
in repository python-soco.
commit 8249c94b02bec986251eeb8819fb79a44472dcd1
Author: Ruben Undheim <ruben.undheim at gmail.com>
Date: Sun Dec 11 19:23:14 2016 +0100
import soco_0.12.orig.tar.gz
---
AUTHORS.rst | 36 +
LICENSE.rst | 22 +
MANIFEST.in | 24 +
PKG-INFO | 242 +++
README.rst | 217 +++
dev_tools/analyse_ws.ini | 2 +
dev_tools/analyse_ws.py | 530 ++++++
dev_tools/pychecker.bat | 6 +
dev_tools/pychecker.sh | 17 +
dev_tools/sonosdump.py | 72 +
doc/Makefile | 192 ++
doc/_static/imageMapResizer.min.js | 8 +
doc/_templates/page.html | 23 +
doc/advanced/data-structures-mod.rst | 49 +
doc/advanced/events.rst | 54 +
doc/advanced/index.rst | 7 +
doc/advanced/services.rst | 43 +
doc/advanced/topology.rst | 60 +
doc/api/soco.alarms.rst | 4 +
doc/api/soco.cache.rst | 7 +
doc/api/soco.compat.rst | 4 +
doc/api/soco.config.rst | 4 +
doc/api/soco.core.rst | 4 +
doc/api/soco.data_structures.rst | 4 +
doc/api/soco.discovery.rst | 4 +
doc/api/soco.events.rst | 4 +
doc/api/soco.exceptions.rst | 4 +
doc/api/soco.groups.rst | 4 +
doc/api/soco.ms_data_structures.rst | 4 +
doc/api/soco.music_library.rst | 4 +
doc/api/soco.music_services.accounts.rst | 4 +
doc/api/soco.music_services.music_service.rst | 4 +
doc/api/soco.music_services.rst | 11 +
doc/api/soco.plugins.example.rst | 4 +
doc/api/soco.plugins.rst | 16 +
doc/api/soco.plugins.spotify.rst | 4 +
doc/api/soco.plugins.wimp.rst | 4 +
doc/api/soco.rst | 35 +
doc/api/soco.services.rst | 4 +
doc/api/soco.snapshot.rst | 4 +
doc/api/soco.soap.rst | 4 +
doc/api/soco.utils.rst | 4 +
doc/api/soco.xml.rst | 4 +
doc/authors.rst | 7 +
doc/conf.py | 397 ++++
doc/development/index.rst | 8 +
doc/development/release-howto.rst | 64 +
doc/development/unittests.rst | 227 +++
doc/examples.rst | 115 ++
doc/getting_started.rst | 115 ++
doc/graphics/data_structures.png | Bin 0 -> 76169 bytes
doc/graphics/data_structures.svg | 1273 +++++++++++++
doc/index.rst | 89 +
doc/make.bat | 263 +++
doc/plugins.rst | 58 +
doc/release_notes.rst | 11 +
doc/releases/0.10.rst | 83 +
doc/releases/0.11.1.rst | 16 +
doc/releases/0.11.rst | 91 +
doc/releases/0.12.rst | 146 ++
doc/releases/0.6.rst | 41 +
doc/releases/0.7.rst | 121 ++
doc/releases/0.8.rst | 104 ++
doc/releases/0.9.rst | 99 +
doc/releases/index.rst | 17 +
doc/tutorial.rst | 8 +
examples/commandline/README.rst | 4 +
examples/commandline/discover.py | 7 +
examples/commandline/screenshot.png | Bin 0 -> 59104 bytes
examples/commandline/tunein.py | 67 +
examples/play_local_files/play_local_files.py | 106 ++
examples/plugins/socoplugins.py | 46 +
examples/webapp/.gitignore | 3 +
examples/webapp/README.md | 22 +
examples/webapp/index.py | 96 +
examples/webapp/requirements.txt | 2 +
examples/webapp/screenshot.png | Bin 0 -> 264587 bytes
examples/webapp/settings.py.example | 3 +
examples/webapp/static/css/bootstrap.min.css | 689 +++++++
examples/webapp/static/css/main.css | 17 +
examples/webapp/static/img/blank.jpg | Bin 0 -> 15285 bytes
.../static/img/glyphicons-halflings-white.png | Bin 0 -> 4352 bytes
.../webapp/static/img/glyphicons-halflings.png | Bin 0 -> 4352 bytes
examples/webapp/static/js/bootstrap.min.js | 6 +
examples/webapp/static/js/jquery.min.js | 4 +
examples/webapp/templates/index.html | 100 +
makefile | 22 +
pylintrc | 28 +
requirements-dev.txt | 10 +
requirements.txt | 2 +
setup.cfg | 34 +
setup.py | 90 +
soco.egg-info/PKG-INFO | 242 +++
soco.egg-info/SOURCES.txt | 137 ++
soco.egg-info/dependency_links.txt | 1 +
soco.egg-info/requires.txt | 2 +
soco.egg-info/top_level.txt | 1 +
soco/__init__.py | 36 +
soco/alarms.py | 319 ++++
soco/cache.py | 216 +++
soco/compat.py | 73 +
soco/config.py | 41 +
soco/core.py | 1960 ++++++++++++++++++++
soco/data_structures.py | 1141 ++++++++++++
soco/discovery.py | 210 +++
soco/events.py | 611 ++++++
soco/exceptions.py | 78 +
soco/groups.py | 113 ++
soco/ms_data_structures.py | 548 ++++++
soco/music_library.py | 555 ++++++
soco/music_services/__init__.py | 14 +
soco/music_services/accounts.py | 199 ++
soco/music_services/music_service.py | 869 +++++++++
soco/plugins/__init__.py | 45 +
soco/plugins/example.py | 54 +
soco/plugins/spotify.py | 34 +
soco/plugins/wimp.py | 540 ++++++
soco/services.py | 798 ++++++++
soco/snapshot.py | 258 +++
soco/soap.py | 314 ++++
soco/utils.py | 188 ++
soco/xml.py | 97 +
tests/conftest.py | 24 +
tests/soco_unittest.py | 458 +++++
tests/test_alarms.py | 18 +
tests/test_cache.py | 75 +
tests/test_core.py | 1026 ++++++++++
tests/test_discovery.py | 64 +
tests/test_events.py | 95 +
tests/test_integration.py | 837 +++++++++
tests/test_ms_data_structures.py | 341 ++++
tests/test_musicservices.py | 326 ++++
tests/test_new_datastructures.py | 357 ++++
tests/test_services.py | 225 +++
tests/test_singleton.py | 56 +
tests/test_soap.py | 135 ++
tests/test_utils.py | 37 +
tests/test_xml.py | 22 +
138 files changed, 20258 insertions(+)
diff --git a/AUTHORS.rst b/AUTHORS.rst
new file mode 100644
index 0000000..f87a698
--- /dev/null
+++ b/AUTHORS.rst
@@ -0,0 +1,36 @@
+Project Creator
+===============
+SoCo was created in 2012 at Music Hack Day Sydney by Rahim Sonawalla
+
+
+Maintainers
+===========
+
+* Lawrence Akka
+* Stefan Kögl
+* Kenneth Nielsen
+
+
+Contributors
+============
+
+(alphabetical)
+
+* Petter Aas
+* Murali Allada
+* Joel Björkman
+* Aaron Daubman
+* Johan Elmerfjord
+* David H
+* Jeff Hinrichs
+* Jeroen Idserda
+* Todd Neal
+* nixscripter
+* Kenneth Nielsen
+* Dave O'Connor
+* Dennnis O'Reilly
+* phut
+* Dan Poirier
+* Jason Ting
+* Scott G Waters
+
diff --git a/LICENSE.rst b/LICENSE.rst
new file mode 100644
index 0000000..23ff495
--- /dev/null
+++ b/LICENSE.rst
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+=====================
+
+Copyright (c) Rahim Sonawalla and individual contributors (see AUTHORS)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..e543a86
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,24 @@
+# Specifies files to be included in a python sdist
+
+# Top level directory
+include requirements.txt requirements-dev.txt
+include setup.cfg pylintrc makefile
+include *.rst
+
+# dev-tools
+recursive-include dev_tools *.ini *.py *.bat *.sh
+
+# Documentation
+
+recursive-include doc *
+recursive-exclude doc *.pyc *.pyo *.rej *.orig .DS_Store
+# We don't want any built docs
+prune doc/_build
+
+# Tests
+recursive-include tests *.py
+
+# Examples
+recursive-include examples *
+recursive-exclude examples *.pyc *.pyo *.rej *.orig .DS_Store
+
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..a1f7c24
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,242 @@
+Metadata-Version: 1.1
+Name: soco
+Version: 0.12
+Summary: SoCo (Sonos Controller) is a simple library to control Sonos speakers.
+Home-page: https://github.com/SoCo/SoCo
+Author: The SoCo-Team
+Author-email: python-soco at googlegroups.com
+License: MIT License
+Description: SoCo
+ ====
+
+ SoCo (Sonos Controller) is a simple Python class that allows you to
+ programmatically control `Sonos speakers`_. It was originally created at `Music
+ Hack Day Sydney`_ by `Rahim Sonawalla`_ and is now developed by a `team of
+ people`_ at its `GitHub repository`_
+
+ For more background on the project, please see Rahim's `blog post
+ <http://www.hirahim.com/blog/2012/04/29/dissecting-the-sonos-controller/>`_.
+
+ Visit the `SoCo documentation`_ for a more detailed overview of all the functionailty.
+
+ .. image:: https://travis-ci.org/SoCo/SoCo.svg?branch=master
+ :target: https://travis-ci.org/SoCo/SoCo
+ :alt: Build Status
+
+ .. image:: https://img.shields.io/requires/github/SoCo/SoCo/master.svg?style=flat
+ :target: https://requires.io/github/SoCo/SoCo/requirements/?branch=master
+ :alt: Requirements Status
+
+ .. image:: https://img.shields.io/pypi/v/soco.svg?style=flat
+ :target: https://pypi.python.org/pypi/soco/
+ :alt: Latest PyPI version
+
+ .. image:: https://img.shields.io/pypi/dm/soco.svg?style=flat
+ :target: https://pypi.python.org/pypi/soco/
+ :alt: Number of PyPI downloads
+
+ Installation
+ ------------
+
+ SoCo requires Python 2.7, or 3.3 or newer.
+
+ Use pip:
+
+ ``pip install soco``
+
+
+ SoCo depends on the `Requests`_ HTTP library. If you use pip to install Soco,
+ Requests will be installed automatically for you. If not, you can use:
+
+ ``pip install requests``
+
+
+ Basic Usage
+ -----------
+
+ You can interact with a Sonos Zone Player through a SoCo object. If you know
+ the IP address of a Zone Player, you can create a SoCo object directly:
+
+ .. code:: python
+
+ >>> from soco import SoCo
+ >>> my_zone = SoCo('192.168.1.101')
+ >>> my_zone.player_name
+ Kitchen
+ >>> my_zone.status_light = True
+ >>> my_zone.volume = 6
+
+
+ But perhaps the easiest way is to use the module-level `discover` function.
+ This will find all the Zone Players on your network, and return a python
+ set containing them:
+
+ .. code:: python
+
+ >>> import soco
+ >>> for zone in soco.discover():
+ ... print zone.player_name
+ Living Room
+ Kitchen
+
+
+ If you prefer a list to a set:
+
+ .. code:: python
+
+ >>> zone_list = list(soco.discover())
+ >>> zone_list
+ [SoCo("192.168.1.101"), SoCo("192.168.1.102")]
+ >>> zone_list[0].mute = True
+
+ Of course, you can also play music!
+
+ .. code:: python
+
+ #!/usr/bin/env python
+ from soco import SoCo
+
+ if __name__ == '__main__':
+ sonos = SoCo('192.168.1.102') # Pass in the IP of your Sonos speaker
+ # You could use the discover function instead, if you don't know the IP
+
+ # Pass in a URI to a media file to have it streamed through the Sonos
+ # speaker
+ sonos.play_uri(
+ 'http://archive.org/download/TenD2005-07-16.flac16/TenD2005-07-16t10Wonderboy_64kb.mp3')
+
+ track = sonos.get_current_track_info()
+
+ print track['title']
+
+ sonos.pause()
+
+ # Play a stopped or paused track
+ sonos.play()
+
+
+ Example Applications
+ --------------------
+
+ To show off what can be made with SoCo, a simple web application is included in
+ the ``examples`` folder.
+
+ .. figure:: https://github.com/SoCo/SoCo/raw/master/examples/webapp/screenshot.png
+ :alt: Screenshot of web app
+
+ Screenshot of web app
+
+
+ Features
+ --------
+
+ SoCo supports the following controls amongst others:
+
+ - Play
+ - Pause
+ - Stop
+ - Next track
+ - Previous track
+ - Get current transport information(if speaker is
+ playing,paused,stopped)
+ - Get information about the currently playing track
+
+ - Track title
+ - Artist
+ - Album
+ - Album Art (if available)
+ - Track length
+ - Duration played (for example, 30 seconds into a 3 minute song)
+ - Playlist position (for example, item 5 in the playlist)
+ - Track URI
+
+ - Mute (or unmute) the speaker
+ - Get or set the speaker volume
+ - Get or set the speaker’s bass EQ
+ - Get or set the speaker’s treble EQ
+ - Toggle the speaker’s loudness compensation
+ - Turn on (or off) the white status light on the unit
+ - Switch the speaker’s source to line-in or TV input (if the Zone Player
+ supports it)
+ - Get the speaker’s information
+
+ - Zone Name
+ - Zone Icon
+ - UID (usually something like RINCON\_XXXXXXXXXXXXXXXXX)
+ - Serial Number
+ - Software version
+ - Hardware version
+ - MAC Address
+
+ - Set the speaker’s Zone Name
+ - Find all the Sonos speakers in a network.
+ - Put all Sonos speakers in a network into “party mode”.
+ - “Unjoin” speakers from a group.
+ - Manage the Sonos queue (get the items in it, add to it, clear it,
+ play a specific song from it)
+ - Get the saved favorite radio stations and shows (title and stream
+ URI)
+ - Search for and play item from your music library
+ - Start a music library update and determine if one is in progress
+
+ SoCo also supports lower level access from Python to all Sonos services (eg
+ Alarms)
+
+
+ Related Projects
+ ----------------
+
+ Socos is a command line tool for controlling Sonos devices. It is developed
+ in conjunction with Soco, but in a `separate repository <https://github.com/SoCo/socos>`_.
+
+ More of a Ruby fan? Not a problem, `Sam Soffes`_ is building out an
+ awesome `Ruby gem`_.
+
+ Looking for a GUI that’s more than just a sample project? `Joel
+ Björkman`_ is building a Sonos Controller GUI–great for folks on Linux
+ where there isn’t an official Sonos Controller application! Find, fork,
+ and contribute to it here: https://github.com/labero/SoCo-Tk.
+
+
+ Google Group
+ ------------
+
+ There is a Soco group over at `Google Groups`_. Feel free to drop in.
+
+
+ License
+ -------
+
+ SoCo is released under the `MIT license`_.
+
+
+ .. _Sonos speakers: http://www.sonos.com/system/
+ .. _Music Hack Day Sydney: http://sydney.musichackday.org/2012/
+ .. _blog post: http://www.hirahim.com/blog/2012/04/29/dissecting-the-sonos-controller/
+ .. _Requests: http://docs.python-requests.org/
+ .. _Sam Soffes: https://github.com/soffes
+ .. _Ruby gem: https://github.com/soffes/sonos
+ .. _Joel Björkman: https://github.com/labero
+ .. _MIT license: http://www.opensource.org/licenses/mit-license.php
+ .. _Rahim Sonawalla: https://github.com/rahims/SoCo
+ .. _GitHub repository: https://github.com/SoCo/SoCo
+ .. _team of people: https://github.com/SoCo/SoCo/blob/master/AUTHORS.rst
+ .. _Google Groups: https://groups.google.com/forum/#!forum/python-soco
+ .. _SoCo documentation: https://soco.readthedocs.org/en/latest/
+
+Platform: UNKNOWN
+Classifier: Development Status :: 3 - Alpha
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Home Automation
+Classifier: Topic :: Multimedia :: Sound/Audio
+Classifier: Topic :: Multimedia :: Sound/Audio :: Players
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..3bc27d9
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,217 @@
+SoCo
+====
+
+SoCo (Sonos Controller) is a simple Python class that allows you to
+programmatically control `Sonos speakers`_. It was originally created at `Music
+Hack Day Sydney`_ by `Rahim Sonawalla`_ and is now developed by a `team of
+people`_ at its `GitHub repository`_
+
+For more background on the project, please see Rahim's `blog post
+<http://www.hirahim.com/blog/2012/04/29/dissecting-the-sonos-controller/>`_.
+
+Visit the `SoCo documentation`_ for a more detailed overview of all the functionailty.
+
+.. image:: https://travis-ci.org/SoCo/SoCo.svg?branch=master
+ :target: https://travis-ci.org/SoCo/SoCo
+ :alt: Build Status
+
+.. image:: https://img.shields.io/requires/github/SoCo/SoCo/master.svg?style=flat
+ :target: https://requires.io/github/SoCo/SoCo/requirements/?branch=master
+ :alt: Requirements Status
+
+.. image:: https://img.shields.io/pypi/v/soco.svg?style=flat
+ :target: https://pypi.python.org/pypi/soco/
+ :alt: Latest PyPI version
+
+.. image:: https://img.shields.io/pypi/dm/soco.svg?style=flat
+ :target: https://pypi.python.org/pypi/soco/
+ :alt: Number of PyPI downloads
+
+Installation
+------------
+
+SoCo requires Python 2.7, or 3.3 or newer.
+
+Use pip:
+
+``pip install soco``
+
+
+SoCo depends on the `Requests`_ HTTP library. If you use pip to install Soco,
+Requests will be installed automatically for you. If not, you can use:
+
+``pip install requests``
+
+
+Basic Usage
+-----------
+
+You can interact with a Sonos Zone Player through a SoCo object. If you know
+the IP address of a Zone Player, you can create a SoCo object directly:
+
+.. code:: python
+
+ >>> from soco import SoCo
+ >>> my_zone = SoCo('192.168.1.101')
+ >>> my_zone.player_name
+ Kitchen
+ >>> my_zone.status_light = True
+ >>> my_zone.volume = 6
+
+
+But perhaps the easiest way is to use the module-level `discover` function.
+This will find all the Zone Players on your network, and return a python
+set containing them:
+
+.. code:: python
+
+ >>> import soco
+ >>> for zone in soco.discover():
+ ... print zone.player_name
+ Living Room
+ Kitchen
+
+
+If you prefer a list to a set:
+
+.. code:: python
+
+ >>> zone_list = list(soco.discover())
+ >>> zone_list
+ [SoCo("192.168.1.101"), SoCo("192.168.1.102")]
+ >>> zone_list[0].mute = True
+
+Of course, you can also play music!
+
+.. code:: python
+
+ #!/usr/bin/env python
+ from soco import SoCo
+
+ if __name__ == '__main__':
+ sonos = SoCo('192.168.1.102') # Pass in the IP of your Sonos speaker
+ # You could use the discover function instead, if you don't know the IP
+
+ # Pass in a URI to a media file to have it streamed through the Sonos
+ # speaker
+ sonos.play_uri(
+ 'http://archive.org/download/TenD2005-07-16.flac16/TenD2005-07-16t10Wonderboy_64kb.mp3')
+
+ track = sonos.get_current_track_info()
+
+ print track['title']
+
+ sonos.pause()
+
+ # Play a stopped or paused track
+ sonos.play()
+
+
+Example Applications
+--------------------
+
+To show off what can be made with SoCo, a simple web application is included in
+the ``examples`` folder.
+
+.. figure:: https://github.com/SoCo/SoCo/raw/master/examples/webapp/screenshot.png
+ :alt: Screenshot of web app
+
+ Screenshot of web app
+
+
+Features
+--------
+
+SoCo supports the following controls amongst others:
+
+- Play
+- Pause
+- Stop
+- Next track
+- Previous track
+- Get current transport information(if speaker is
+ playing,paused,stopped)
+- Get information about the currently playing track
+
+ - Track title
+ - Artist
+ - Album
+ - Album Art (if available)
+ - Track length
+ - Duration played (for example, 30 seconds into a 3 minute song)
+ - Playlist position (for example, item 5 in the playlist)
+ - Track URI
+
+- Mute (or unmute) the speaker
+- Get or set the speaker volume
+- Get or set the speaker’s bass EQ
+- Get or set the speaker’s treble EQ
+- Toggle the speaker’s loudness compensation
+- Turn on (or off) the white status light on the unit
+- Switch the speaker’s source to line-in or TV input (if the Zone Player
+ supports it)
+- Get the speaker’s information
+
+ - Zone Name
+ - Zone Icon
+ - UID (usually something like RINCON\_XXXXXXXXXXXXXXXXX)
+ - Serial Number
+ - Software version
+ - Hardware version
+ - MAC Address
+
+- Set the speaker’s Zone Name
+- Find all the Sonos speakers in a network.
+- Put all Sonos speakers in a network into “party mode”.
+- “Unjoin” speakers from a group.
+- Manage the Sonos queue (get the items in it, add to it, clear it,
+ play a specific song from it)
+- Get the saved favorite radio stations and shows (title and stream
+ URI)
+- Search for and play item from your music library
+- Start a music library update and determine if one is in progress
+
+SoCo also supports lower level access from Python to all Sonos services (eg
+Alarms)
+
+
+Related Projects
+----------------
+
+Socos is a command line tool for controlling Sonos devices. It is developed
+in conjunction with Soco, but in a `separate repository <https://github.com/SoCo/socos>`_.
+
+More of a Ruby fan? Not a problem, `Sam Soffes`_ is building out an
+awesome `Ruby gem`_.
+
+Looking for a GUI that’s more than just a sample project? `Joel
+Björkman`_ is building a Sonos Controller GUI–great for folks on Linux
+where there isn’t an official Sonos Controller application! Find, fork,
+and contribute to it here: https://github.com/labero/SoCo-Tk.
+
+
+Google Group
+------------
+
+There is a Soco group over at `Google Groups`_. Feel free to drop in.
+
+
+License
+-------
+
+SoCo is released under the `MIT license`_.
+
+
+.. _Sonos speakers: http://www.sonos.com/system/
+.. _Music Hack Day Sydney: http://sydney.musichackday.org/2012/
+.. _blog post: http://www.hirahim.com/blog/2012/04/29/dissecting-the-sonos-controller/
+.. _Requests: http://docs.python-requests.org/
+.. _Sam Soffes: https://github.com/soffes
+.. _Ruby gem: https://github.com/soffes/sonos
+.. _Joel Björkman: https://github.com/labero
+.. _MIT license: http://www.opensource.org/licenses/mit-license.php
+.. _Rahim Sonawalla: https://github.com/rahims/SoCo
+.. _GitHub repository: https://github.com/SoCo/SoCo
+.. _team of people: https://github.com/SoCo/SoCo/blob/master/AUTHORS.rst
+.. _Google Groups: https://groups.google.com/forum/#!forum/python-soco
+.. _SoCo documentation: https://soco.readthedocs.org/en/latest/
diff --git a/dev_tools/analyse_ws.ini b/dev_tools/analyse_ws.ini
new file mode 100644
index 0000000..50f57f8
--- /dev/null
+++ b/dev_tools/analyse_ws.ini
@@ -0,0 +1,2 @@
+[General]
+browser_command: epiphany {0}
diff --git a/dev_tools/analyse_ws.py b/dev_tools/analyse_ws.py
new file mode 100644
index 0000000..8f9992a
--- /dev/null
+++ b/dev_tools/analyse_ws.py
@@ -0,0 +1,530 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# pylint: disable=E0611,R0913
+
+""" Script to analyse ws dumps """
+
+import argparse
+import os
+import sys
+import math
+import textwrap
+PLATFORM = sys.platform.lower()
+if PLATFORM == 'win32':
+ import msvcrt
+ COLOR = False
+else:
+ import tty
+ import termios
+ COLOR = True
+import re
+import codecs
+import ConfigParser
+import StringIO
+try:
+ import pygments
+ from pygments.lexers import XmlLexer
+ from pygments.formatters import TerminalFormatter
+except ImportError:
+ print 'Module "pygments" could not be imported. Please install it. '\
+ 'Exiting!'
+ sys.exit(100)
+try:
+ # Temporarily re-directing stderr to StringIO to prevent start-up message
+ # from rdpcap import
+ STDERR = sys.stderr
+ sys.stderr = StringIO.StringIO()
+ from scapy.all import rdpcap
+ sys.stderr = STDERR
+except ImportError:
+ print 'Module "scapy" could not be imported. Please install it. Exiting!'
+ sys.exit(101)
+try:
+ from lxml import etree
+ PARSER = etree.XMLParser(remove_blank_text=True)
+except ImportError:
+ print 'Module "lxml" could not be imported. Please install it. Exiting!'
+ sys.exit(102)
+import subprocess
+
+# Text bits that starts and ends the Sonos UPnP content
+STARTS = ['<s:Envelope', '<e:propertyset']
+ENDS = ['</s:Envelope>', '</e:propertyset>']
+
+
+class AnalyzeWS(object):
+ """ Class for analysis of WireShark dumps. Also shows the parts of the
+ WireShark dumps syntax highlighted in the terminal and/or writes them to
+ files and shows them in a browser.
+
+ The order of processing a file with this class is the following. The
+ class is initialized purely with options. All the content is added with
+ the set_file method. This method will load the ws file with rdpcap. For
+ each part in the ws file that has a load, it will look for Sonos
+ content. If such content is present one of three things will happen. If
+ it is the beginning of a Sonos message, it will initialize a WSPart. If
+ it is the middle part, it will add it to the content of the current
+ WSPart with WSPart.add_content. If it is the end, it will finalize the
+ WSPart with WSPart.finalize_content. Finalizing the WSPart will, apart
+ from closing it for writing also decode the body and parse the XML.
+
+ """
+
+ def __init__(self, args):
+ self.messages = []
+ self.args = args
+ self.output_prefix = args.output_prefix
+ try:
+ this_dir = os.path.dirname(os.path.abspath(__file__))
+ with open(os.path.join(this_dir, 'analyse_ws.ini')) as file__:
+ self.config = ConfigParser.ConfigParser()
+ self.config.readfp(file__)
+ except IOError:
+ self.config = None
+ self.pages = {}
+
+ def set_file(self, filename):
+ """ Analyse the file with the captured content """
+ # Use the file name as prefix if none is given
+ if self.output_prefix is None:
+ _, self.output_prefix = os.path.split(filename)
+ # Check if the file is present, since rdpcap will not do that
+ if not (os.path.isfile(filename) and os.access(filename, os.R_OK)):
+ print 'The file \'{0}\' is either not present or not readable. '\
+ 'Exiting!'.format(filename)
+ sys.exit(1)
+ try:
+ packets = rdpcap(filename)
+ except NameError:
+ # Due probably to a bug in rdpcap, this kind of error raises a
+ # NameError, because the exception that is tried to raise, is not
+ # defined
+ print 'The file \'{}\' is not a pcap capture file. Exiting!'\
+ .format(filename)
+ sys.exit(2)
+
+ for number, packet in enumerate(packets):
+ # See if there is a field called load
+ self._debug('\nNUMBER {0}'.format(number), no_prefix=True)
+ try:
+ # Will cause AttributeError if there is no load
+ packet.getfieldval('load')
+ # Get the full load
+ load = packet.sprintf('%TCP.payload%')
+ self._debug('PAYLOAD LENGTH {0}'.format(len(load)),
+ no_prefix=True)
+ self._debug(load, load=True)
+ self._parse_load(load)
+ except AttributeError:
+ self._debug('LOAD EXCEPTION', no_prefix=True)
+ if len(self.messages) > 0 and not self.messages[-1].write_closed:
+ self._debug('DELETE LAST OPEN FILE')
+ del self.messages[-1]
+
+ if self.args.debug_analysis:
+ sys.exit(0)
+
+ def _parse_load(self, load):
+ """ Parse the load from a single packet """
+ # If the load is ??
+ if load in ['??']:
+ self._debug('IGNORING')
+ # If there is a start in load
+ elif any([start in load for start in STARTS]):
+ self._debug('START')
+ self.messages.append(WSPart(load, self.args))
+ # and there is also an end
+ if any([end in load for end in ENDS]):
+ self.messages[-1].finalize_content()
+ self._debug('AND END')
+ # If there is an end in load
+ elif any([end in load for end in ENDS]):
+ # If there is an open WSPart
+ if len(self.messages) > 0 and not\
+ self.messages[-1].write_closed:
+ self._debug('END ON OPEN FILE')
+ self.messages[-1].add_content(load)
+ self.messages[-1].finalize_content()
+ # Ignore ends before start
+ else:
+ self._debug('END BUT NO OPEN FILE')
+ else:
+ # If there is an open WSPart
+ if len(self.messages) > 0 and not\
+ self.messages[-1].write_closed:
+ self._debug('ADD TO OPEN FILE')
+ self.messages[-1].add_content(load)
+ # else ignore
+ else:
+ self._debug('NOTHING TO DO')
+
+ def _debug(self, message, load=False, no_prefix=False):
+ """ Output debug information """
+ if self.args.debug_analysis:
+ if load:
+ message = '\r\n'.join(
+ ['# ' + line for line in message.strip().split('\r\n')]
+ )
+ print '{0}\n{1}\n{0}'.format('#' * 78, message)
+ else:
+ # If open message and no_prefix is False
+ if (len(self.messages) > 0 and not
+ self.messages[-1].write_closed) and not no_prefix:
+ print '--OPEN--> {0}'.format(message)
+ else:
+ print message
+
+ def to_file_mode(self):
+ """ Write all the messages to files """
+ for message_no in range(len(self.messages)):
+ self.__to_file(message_no)
+
+ def __to_file(self, message_no):
+ """ Write a single message to file """
+ filename = self.__create_file_name(message_no)
+ try:
+ with codecs.open(filename, mode='w',
+ encoding=self.messages[message_no].encoding)\
+ as file__:
+ file__.write(self.messages[message_no].output)
+ except IOError as excep:
+ print 'Unable for open the file \'{0}\' for writing. The '\
+ 'following exception was raised:'.format(filename)
+ print excep
+ print 'Exiting!'
+ sys.exit(2)
+ return filename
+
+ def __create_file_name(self, message_no):
+ """ Create the filename to save to """
+ cwd = os.getcwd()
+ filename = '{0}_{1}.xml'.format(self.output_prefix, message_no)
+ return os.path.join(cwd, filename)
+
+ def to_browser_mode(self):
+ """ Write all the messages to files and open them in the browser """
+ for message_no in range(len(self.messages)):
+ self.__to_browser(message_no)
+
+ def __to_browser(self, message_no):
+ """ Write a single message to file and open the file in a
+ browser
+
+ """
+ filename = self.__to_file(message_no)
+ try:
+ command = self.config.get('General', 'browser_command')
+ except (ConfigParser.NoOptionError, AttributeError):
+ print 'Incorrect or missing .ini file. See --help.'
+ sys.exit(5)
+ command = str(command).format(filename)
+ command_list = command.split(' ')
+ try:
+ subprocess.Popen(command_list, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ except OSError:
+ print 'Unable to execute the browsercommand:'
+ print command
+ print 'Exiting!'
+ sys.exit(21)
+
+ def interactive_mode(self):
+ """ Interactive mode """
+ if PLATFORM == 'win32':
+ # Defaulting to 80 on windows, better ideas are welcome, but the
+ # solutions I found online are rather bulky
+ height = 20
+ width = 80
+ else:
+ height, width = os.popen('stty size', 'r').read().split()
+ width = int(width)
+ height = int(height)
+
+ message_no = 0
+ page_no = 0
+ action = None
+ while action != 'q':
+ page_no = self.__update_window(width, height, message_no, page_no)
+ action = getch()
+ if action == 's':
+ # Coerce in range
+ message_no = \
+ max(min(len(self.messages) - 1, message_no + 1), 0)
+ page_no = 0
+ elif action == 'w':
+ # Coerce in range
+ message_no = \
+ max(min(len(self.messages) - 1, message_no - 1), 0)
+ page_no = 0
+ elif action == 'a':
+ page_no -= 1
+ elif action == 'd':
+ page_no += 1
+ elif action == 'b':
+ self.__to_browser(message_no)
+ elif action == 'f':
+ self.__to_file(message_no)
+
+ def __update_window(self, width, height, message_no, page_no):
... 20228 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-soco.git
More information about the Python-modules-commits
mailing list