Write more docs, using Sphinx
This commit is contained in:
parent
5ef7d17deb
commit
d471b30afe
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,8 @@
|
||||
*.pyc
|
||||
*.swp
|
||||
.coverage
|
||||
.idea
|
||||
docs/_build
|
||||
local_settings.py
|
||||
pip-log.txt
|
||||
spotify_appkey.key
|
||||
|
||||
153
README.rst
153
README.rst
@ -1,147 +1,16 @@
|
||||
******
|
||||
mopidy
|
||||
Mopidy
|
||||
******
|
||||
|
||||
mopidy is an MPD server with a Spotify backend.
|
||||
Mopidy is an `MPD <http://mpd.wikia.com/>`_ server with a
|
||||
`Spotify <http://www.spotify.com/>`_ backend. Using a standard MPD client you
|
||||
can search for music in Spotify's wast archive, manage Spotify play lists and
|
||||
play music from Spotify.
|
||||
|
||||
Mopidy is currently under development. Unless you want to contribute to the
|
||||
development, you should probably wait for our first release before trying out
|
||||
Mopidy.
|
||||
|
||||
Goal
|
||||
====
|
||||
|
||||
Using a standard MPD client we want to search for music in Spotify, manage
|
||||
Spotify play lists and play music from Spotify.
|
||||
|
||||
To limit scope, we will start by implementing an MPD server which only
|
||||
supports Spotify, and not playback of files from disk. We will make mopidy
|
||||
modular, so we can extend it with other backends in the future, like file
|
||||
playback and other online music services such as Last.fm.
|
||||
|
||||
|
||||
Backends
|
||||
========
|
||||
|
||||
To use the despotify backend, you first need to install despotify and spytify.
|
||||
Alternatively, we are working on a libspotify backend, which requires you to
|
||||
install libspotify and pyspotify.
|
||||
|
||||
Both backends require a Spotify premium account, while only the libspotify
|
||||
backend requires you to get an application key from Spotify before use.
|
||||
|
||||
|
||||
Installing despotify and spytify
|
||||
--------------------------------
|
||||
|
||||
Check out the despotify source code revision 497 (or possibly newer)::
|
||||
|
||||
svn co https://despotify.svn.sourceforge.net/svnroot/despotify@497 despotify
|
||||
|
||||
Install despotify's dependencies. At Debian/Ubuntu systems::
|
||||
|
||||
sudo aptitude install libssl-dev zlib1g-dev libvorbis-dev \
|
||||
libtool libncursesw5-dev libao-dev
|
||||
|
||||
Build and install despotify::
|
||||
|
||||
cd despotify/src/
|
||||
make
|
||||
sudo make install
|
||||
|
||||
Build and install spytify::
|
||||
|
||||
cd despotify/src/bindings/python/
|
||||
make
|
||||
sudo make install
|
||||
|
||||
To validate that everything is working, run the ``test.py`` script which is
|
||||
distributed with spytify::
|
||||
|
||||
python test.py
|
||||
|
||||
The test script should ask for your username and password (which must be for a
|
||||
Spotify Premium account), ask for a search query, list all your playlists with
|
||||
tracks, play 10s from a random song from the search result, pause for two
|
||||
seconds, play for five more seconds, and quit.
|
||||
|
||||
|
||||
Installing libspotify and pyspotify
|
||||
-----------------------------------
|
||||
|
||||
As libspotify's installation script at the moment is somewhat broken (see this
|
||||
`GetSatisfaction thread <http://getsatisfaction.com/spotify/topics/libspotify_please_fix_the_installation_script>`_
|
||||
for details), it is easiest to use the libspotify files bundled with pyspotify.
|
||||
The files bundled with pyspotify are for 64-bit, so if you run a 32-bit OS, you
|
||||
must get libspotify from https://developer.spotify.com/en/libspotify/.
|
||||
|
||||
Install pyspotify's dependencies. At Debian/Ubuntu systems::
|
||||
|
||||
sudo aptitude install python-alsaaudio
|
||||
|
||||
Check out the pyspotify code, and install it::
|
||||
|
||||
git clone git://github.com/winjer/pyspotify.git
|
||||
cd pyspotify
|
||||
export LD_LIBRARY_PATH=$PWD/lib
|
||||
sudo python setup.py develop
|
||||
|
||||
Apply for an application key at
|
||||
https://developer.spotify.com/en/libspotify/application-key, download the
|
||||
binary version, and place the file at ``pyspotify/spotify_appkey.key``.
|
||||
|
||||
Test your libspotify setup::
|
||||
|
||||
./example1.py -u USERNAME -p PASSWORD
|
||||
|
||||
Until Spotify fixes their installation script, you'll have to set
|
||||
``LD_LIBRARY_PATH`` every time you are going to use libspotify (in other words
|
||||
before starting mopidy).
|
||||
|
||||
|
||||
Running mopidy
|
||||
==============
|
||||
|
||||
Create a file name ``local_settings.py`` in the same directory as
|
||||
``settings.py``. Enter your Spotify Premium account's username and password
|
||||
into the file, like this::
|
||||
|
||||
SPOTIFY_USERNAME = u'myusername'
|
||||
SPOTIFY_PASSWORD = u'mysecret'
|
||||
|
||||
To start mopidy, go to the root of the mopidy project, then simply run::
|
||||
|
||||
python mopidy
|
||||
|
||||
To stop mopidy, press ``CTRL+C``.
|
||||
|
||||
|
||||
Running tests
|
||||
=============
|
||||
|
||||
To run tests, you need a couple of dependiencies. Some can be installed through Debian/Ubuntu package management::
|
||||
|
||||
sudo aptitude install python-coverage
|
||||
|
||||
The rest can be installed using pip::
|
||||
|
||||
sudo aptitude install python-pip python-setuptools bzr
|
||||
pip install -r test-requirements.txt
|
||||
|
||||
Then, to run all tests::
|
||||
|
||||
python tests
|
||||
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
- MPD
|
||||
|
||||
- `MPD protocol documentation <http://www.musicpd.org/doc/protocol/>`_
|
||||
- The original `MPD server <http://mpd.wikia.com/>`_
|
||||
|
||||
- Spotify
|
||||
|
||||
- `spytify <http://despotify.svn.sourceforge.net/viewvc/despotify/src/bindings/python/>`_,
|
||||
the Python bindings for `despotify <http://despotify.se/>`_
|
||||
- `pyspotify <http://github.com/winjer/pyspotify/>`_,
|
||||
Python bindings for the official Spotify library, libspotify
|
||||
- `Spotify's official metadata API <http://developer.spotify.com/en/metadata-api/overview/>`_
|
||||
* `Source code <http://github.com/jodal/mopidy>`_
|
||||
* `Documentation <http://www.mopidy.com/>`_
|
||||
* IRC: ``#mopidy`` at `irc.freenode.net <http://freenode.net/>`_
|
||||
|
||||
104
docs/Makefile
Normal file
104
docs/Makefile
Normal file
@ -0,0 +1,104 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf _build/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in _build/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in _build/dirhtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in _build/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in _build/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator _build/qthelp/Mopidy.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile _build/qthelp/Mopidy.qhc"
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in _build/latex."
|
||||
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
|
||||
"run these through (pdf)latex."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
|
||||
@echo
|
||||
@echo "The overview file is in _build/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in _build/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in _build/doctest/output.txt."
|
||||
|
||||
public: clean html
|
||||
rm -rf /tmp/mopidy-html && cp -r _build/html /tmp/mopidy-html
|
||||
git stash save
|
||||
cd .. && \
|
||||
git checkout gh-pages && \
|
||||
git pull && \
|
||||
rm -r * && \
|
||||
cp -r /tmp/mopidy-html/* . && \
|
||||
mv _sources sources && \
|
||||
(find . -type f | xargs sed -i -e 's/_sources/sources/g') && \
|
||||
mv _static static && \
|
||||
(find . -type f | xargs sed -i -e 's/_static/static/g') && \
|
||||
mv _images images && \
|
||||
(find . -type f | xargs sed -i -e 's/_images/images/g') && \
|
||||
git add *
|
||||
229
docs/_themes/nature/static/nature.css_t
vendored
Normal file
229
docs/_themes/nature/static/nature.css_t
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
/**
|
||||
* Sphinx stylesheet -- default theme
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #111;
|
||||
color: #555;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 230px;
|
||||
}
|
||||
|
||||
hr{
|
||||
border: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #3E4349;
|
||||
padding: 0 30px 30px 30px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #555;
|
||||
width: 100%;
|
||||
padding: 13px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #444;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: #6BA81E;
|
||||
line-height: 32px;
|
||||
color: #fff;
|
||||
text-shadow: 0px 1px 0 #444;
|
||||
font-size: 0.80em;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #E2F3CC;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
font-size: 0.75em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper{
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: Arial, sans-serif;
|
||||
color: #222;
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 5px 10px;
|
||||
background-color: #ddd;
|
||||
text-shadow: 1px 1px 0 white
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4{
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #888;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px 20px;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #ccc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input[type=text]{
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #005B81;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #E32E00;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #BED4EB;
|
||||
font-weight: normal;
|
||||
color: #212224;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 5px 0 5px 10px;
|
||||
text-shadow: 0px 1px 0 white
|
||||
}
|
||||
|
||||
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
|
||||
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
|
||||
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
|
||||
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
|
||||
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #c60f0f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.highlight{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 10px;
|
||||
background-color: White;
|
||||
color: #222;
|
||||
line-height: 1.2em;
|
||||
border: 1px solid #C6C9CB;
|
||||
font-size: 1.2em;
|
||||
margin: 1.5em 0 1.5em 0;
|
||||
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
|
||||
-moz-box-shadow: 1px 1px 1px #d8d8d8;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
color: #222;
|
||||
padding: 1px 2px;
|
||||
font-size: 1.2em;
|
||||
font-family: monospace;
|
||||
}
|
||||
54
docs/_themes/nature/static/pygments.css
vendored
Normal file
54
docs/_themes/nature/static/pygments.css
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
.c { color: #999988; font-style: italic } /* Comment */
|
||||
.k { font-weight: bold } /* Keyword */
|
||||
.o { font-weight: bold } /* Operator */
|
||||
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.cp { color: #999999; font-weight: bold } /* Comment.preproc */
|
||||
.c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.ge { font-style: italic } /* Generic.Emph */
|
||||
.gr { color: #aa0000 } /* Generic.Error */
|
||||
.gh { color: #999999 } /* Generic.Heading */
|
||||
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.go { color: #111 } /* Generic.Output */
|
||||
.gp { color: #555555 } /* Generic.Prompt */
|
||||
.gs { font-weight: bold } /* Generic.Strong */
|
||||
.gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.kc { font-weight: bold } /* Keyword.Constant */
|
||||
.kd { font-weight: bold } /* Keyword.Declaration */
|
||||
.kp { font-weight: bold } /* Keyword.Pseudo */
|
||||
.kr { font-weight: bold } /* Keyword.Reserved */
|
||||
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.m { color: #009999 } /* Literal.Number */
|
||||
.s { color: #bb8844 } /* Literal.String */
|
||||
.na { color: #008080 } /* Name.Attribute */
|
||||
.nb { color: #999999 } /* Name.Builtin */
|
||||
.nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.no { color: #ff99ff } /* Name.Constant */
|
||||
.ni { color: #800080 } /* Name.Entity */
|
||||
.ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.nn { color: #555555 } /* Name.Namespace */
|
||||
.nt { color: #000080 } /* Name.Tag */
|
||||
.nv { color: purple } /* Name.Variable */
|
||||
.ow { font-weight: bold } /* Operator.Word */
|
||||
.mf { color: #009999 } /* Literal.Number.Float */
|
||||
.mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.sb { color: #bb8844 } /* Literal.String.Backtick */
|
||||
.sc { color: #bb8844 } /* Literal.String.Char */
|
||||
.sd { color: #bb8844 } /* Literal.String.Doc */
|
||||
.s2 { color: #bb8844 } /* Literal.String.Double */
|
||||
.se { color: #bb8844 } /* Literal.String.Escape */
|
||||
.sh { color: #bb8844 } /* Literal.String.Heredoc */
|
||||
.si { color: #bb8844 } /* Literal.String.Interpol */
|
||||
.sx { color: #bb8844 } /* Literal.String.Other */
|
||||
.sr { color: #808000 } /* Literal.String.Regex */
|
||||
.s1 { color: #bb8844 } /* Literal.String.Single */
|
||||
.ss { color: #bb8844 } /* Literal.String.Symbol */
|
||||
.bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.vc { color: #ff99ff } /* Name.Variable.Class */
|
||||
.vg { color: #ff99ff } /* Name.Variable.Global */
|
||||
.vi { color: #ff99ff } /* Name.Variable.Instance */
|
||||
.il { color: #009999 } /* Literal.Number.Integer.Long */
|
||||
4
docs/_themes/nature/theme.conf
vendored
Normal file
4
docs/_themes/nature/theme.conf
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = nature.css
|
||||
pygments_style = tango
|
||||
15
docs/changes.rst
Normal file
15
docs/changes.rst
Normal file
@ -0,0 +1,15 @@
|
||||
*******
|
||||
Changes
|
||||
*******
|
||||
|
||||
This change log is used to track all major changes to Mopidy.
|
||||
|
||||
|
||||
0.1 (unreleased)
|
||||
================
|
||||
|
||||
Initial version.
|
||||
|
||||
Features:
|
||||
|
||||
* *TODO:* Fill out
|
||||
194
docs/conf.py
Normal file
194
docs/conf.py
Normal file
@ -0,0 +1,194 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Mopidy documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Feb 5 22:19:08 2010.
|
||||
#
|
||||
# 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.append(os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = []
|
||||
|
||||
# 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'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Mopidy'
|
||||
copyright = u'2010, Stein Magnus Jodal'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.1'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.1'
|
||||
|
||||
# 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 documents that shouldn't be included in the build.
|
||||
#unused_docs = []
|
||||
|
||||
# List of directories, relative to source directory, that shouldn't be searched
|
||||
# for source files.
|
||||
exclude_trees = ['_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. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
html_theme = 'nature'
|
||||
|
||||
# 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 = ['_themes']
|
||||
|
||||
# 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_use_modindex = 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, 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 = ''
|
||||
|
||||
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'Mopidydoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Mopidy.tex', u'Mopidy Documentation',
|
||||
u'Stein Magnus Jodal', '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
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_use_modindex = True
|
||||
@ -1,18 +0,0 @@
|
||||
Despotify issues
|
||||
----------------
|
||||
|
||||
* r483: s.lookup('spotify:track:1mr3616BzLdhXfJmLmRsO8') returns error:
|
||||
"SpytifyError: URI specifies invalid type: track"
|
||||
Possibly fixed in r497.
|
||||
* r483: When accessing an_artist.albums one get the error:
|
||||
"TypeError: Cannot convert spytify.AlbumDataFull to spytify.ArtistDataFull"
|
||||
* r483: Sometimes segfaults when traversing stored playlists. May work if one
|
||||
try again immediately. Another example segfault::
|
||||
|
||||
>>> In [45]: s.lookup('spotify:user:klette:playlist:5rOGYPwwKqbAcVX8bW4k5V')
|
||||
Segmentation fault
|
||||
|
||||
* r497: spytify fails on ``make''::
|
||||
|
||||
src/spytify.c: In function ‘__pyx_pf_7spytify_7Spytify___init__’:
|
||||
src/spytify.c:7325: error: too few arguments to function ‘despotify_init_client’
|
||||
132
docs/development.rst
Normal file
132
docs/development.rst
Normal file
@ -0,0 +1,132 @@
|
||||
***********
|
||||
Development
|
||||
***********
|
||||
|
||||
Development of Mopidy is coordinated through the IRC channel ``#mopidy`` at
|
||||
``irc.freenode.net`` and through `GitHub <http://github.com/>`_.
|
||||
|
||||
|
||||
Scope
|
||||
=====
|
||||
|
||||
To limit scope, we will start by implementing an MPD server which only
|
||||
supports Spotify, and not playback of files from disk. We will make Mopidy
|
||||
modular, so we can extend it with other backends in the future, like file
|
||||
playback and other online music services such as Last.fm.
|
||||
|
||||
|
||||
Running tests
|
||||
=============
|
||||
|
||||
To run tests, you need a couple of dependiencies. Some can be installed through Debian/Ubuntu package management::
|
||||
|
||||
sudo aptitude install python-coverage
|
||||
|
||||
The rest can be installed using pip::
|
||||
|
||||
sudo aptitude install python-pip python-setuptools bzr
|
||||
pip install -r test-requirements.txt
|
||||
|
||||
Then, to run all tests::
|
||||
|
||||
python tests
|
||||
|
||||
|
||||
Music Player Daemon (MPD)
|
||||
=========================
|
||||
|
||||
The `MPD protocol documentation <http://www.musicpd.org/doc/protocol/>`_ is a
|
||||
useful resource. It is rather incomplete with regards to data formats, both for
|
||||
requests and responses. Thus we have to talk a great deal with the the original
|
||||
`MPD server <http://mpd.wikia.com/>`_ using telnet to get the details we need
|
||||
to implement our own MPD server which is compatible with the numerous existing
|
||||
`MPD clients <http://mpd.wikia.com/wiki/Clients>`_.
|
||||
|
||||
|
||||
spytify
|
||||
=======
|
||||
|
||||
`spytify <http://despotify.svn.sourceforge.net/viewvc/despotify/src/bindings/python/>`_
|
||||
is the Python bindings for the open source `despotify <http://despotify.se/>`_
|
||||
library. It got no documentation to speak of, but a couple of examples are
|
||||
available.
|
||||
|
||||
Issues
|
||||
------
|
||||
|
||||
A list of the issues we currently experience with spytify, both bugs and
|
||||
features we wished was there.
|
||||
|
||||
* r483: Track lookup support. Possibly fixed in r497. To reproduce::
|
||||
|
||||
>>> import spytify
|
||||
>>> s = spytify.Spytify('alice', 'secret')
|
||||
>>> s.lookup('spotify:track:1mr3616BzLdhXfJmLmRsO8')
|
||||
---------------------------------------------------------------------------
|
||||
SpytifyError Traceback (most recent call last)
|
||||
|
||||
/home/jodal/<ipython console> in <module>()
|
||||
|
||||
/usr/local/lib/python2.6/dist-packages/spytify.so in spytify.Spytify.lookup (src/spytify.c:7914)()
|
||||
|
||||
SpytifyError: URI specifies invalid type: track
|
||||
|
||||
* r483: Error when accessing an album through an artist. To reproduce::
|
||||
|
||||
>>> import spytify
|
||||
>>> s = spytify.Spytify('alice', 'secret')
|
||||
>>> result = s.search('Gorillaz')
|
||||
>>> artist = result.playlist.tracks[0].artists[0]
|
||||
>>> artist
|
||||
<Artist: Gorillaz (75f4ed7ec8514e91abaab17306ebbbb6)>
|
||||
>>> artist.albums
|
||||
ERROR: An unexpected error occurred while tokenizing input
|
||||
The following traceback may be corrupted or invalid
|
||||
The error message is: ('EOF in multi-line statement', (1423, 0))
|
||||
|
||||
ERROR: An unexpected error occurred while tokenizing input
|
||||
The following traceback may be corrupted or invalid
|
||||
The error message is: ('EOF in multi-line statement', (1455, 0))
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
TypeError Traceback (most recent call last)
|
||||
|
||||
/home/jodal/<ipython console> in <module>()
|
||||
|
||||
/usr/local/lib/python2.6/dist-packages/spytify.so in spytify.Artist.albums.__get__ (src/spytify.c:4867)()
|
||||
|
||||
/usr/local/lib/python2.6/dist-packages/spytify.so in spytify.Artist.get_full_data (src/spytify.c:4539)()
|
||||
|
||||
TypeError: Cannot convert spytify.AlbumDataFull to spytify.ArtistDataFull
|
||||
|
||||
* r483: Sometimes segfaults when traversing stored playlists, their tracks,
|
||||
artists, and albums. As it is not predictable, it may be a concurrency issue.
|
||||
|
||||
* r483: Segfaults when looking up playlists, both your own lists and other
|
||||
peoples shared lists. To reproduce::
|
||||
|
||||
>>> import spytify
|
||||
>>> s = spytify.Spytify('alice', 'secret')
|
||||
>>> s.lookup('spotify:user:klette:playlist:5rOGYPwwKqbAcVX8bW4k5V')
|
||||
Segmentation fault
|
||||
|
||||
* r497: spytify fails on ``make`` because the despotify API has changed::
|
||||
|
||||
src/spytify.c: In function ‘__pyx_pf_7spytify_7Spytify___init__’:
|
||||
src/spytify.c:7325: error: too few arguments to function ‘despotify_init_client’
|
||||
|
||||
|
||||
pyspotify
|
||||
=========
|
||||
|
||||
`pyspotify <http://github.com/winjer/pyspotify/>`_ is the Python bindings for
|
||||
the official Spotify library, libspotify. It got no documentation to speak of,
|
||||
but multiple examples are available.
|
||||
|
||||
Issues
|
||||
------
|
||||
|
||||
A list of the issues we currently experience with pyspotify, both bugs and
|
||||
features we wished was there.
|
||||
|
||||
* None at the moment.
|
||||
18
docs/index.rst
Normal file
18
docs/index.rst
Normal file
@ -0,0 +1,18 @@
|
||||
.. include:: ../README.rst
|
||||
|
||||
Contents
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
changes
|
||||
installation
|
||||
development
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
||||
|
||||
135
docs/installation.rst
Normal file
135
docs/installation.rst
Normal file
@ -0,0 +1,135 @@
|
||||
************
|
||||
Installation
|
||||
************
|
||||
|
||||
Mopidy itself is a breeze to install, as it just requires a standard Python
|
||||
installation. The libraries we depend on to connect to the Spotify service is
|
||||
far more tricky to get working for the time being. Until installation of these
|
||||
libraries are either well documented by their developers, or the libraries are
|
||||
packaged for various Linux distributions, we will supply our own installation
|
||||
guides here.
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
* Python >= 2.5
|
||||
* Dependencies for at least one Mopidy backend:
|
||||
|
||||
* :ref:`despotify`
|
||||
* :ref:`libspotify`
|
||||
|
||||
|
||||
.. _despotify:
|
||||
|
||||
despotify backend
|
||||
=================
|
||||
|
||||
To use the despotify backend, you first need to install despotify and spytify.
|
||||
|
||||
*This backend requires a Spotify premium account.*
|
||||
|
||||
|
||||
Installing despotify and spytify
|
||||
--------------------------------
|
||||
|
||||
Install despotify's dependencies. At Debian/Ubuntu systems::
|
||||
|
||||
sudo aptitude install libssl-dev zlib1g-dev libvorbis-dev \
|
||||
libtool libncursesw5-dev libao-dev
|
||||
|
||||
Check out revision 483 of the despotify source code::
|
||||
|
||||
svn co https://despotify.svn.sourceforge.net/svnroot/despotify@483 despotify
|
||||
|
||||
Build and install despotify::
|
||||
|
||||
cd despotify/src/
|
||||
make
|
||||
sudo make install
|
||||
|
||||
Build and install spytify::
|
||||
|
||||
cd despotify/src/bindings/python/
|
||||
make
|
||||
sudo make install
|
||||
|
||||
To validate that everything is working, run the ``test.py`` script which is
|
||||
distributed with spytify::
|
||||
|
||||
python test.py
|
||||
|
||||
The test script should ask for your username and password (which must be for a
|
||||
Spotify Premium account), ask for a search query, list all your playlists with
|
||||
tracks, play 10s from a random song from the search result, pause for two
|
||||
seconds, play for five more seconds, and quit.
|
||||
|
||||
.. _libspotify:
|
||||
|
||||
libspotify backend
|
||||
==================
|
||||
|
||||
As an alternative to the despotify backend, we are working on a libspotify
|
||||
backend. To use the libspotify backend you must install libspotify and
|
||||
pyspotify.
|
||||
|
||||
*This backend requires a Spotify premium account.*
|
||||
|
||||
*This backend requires you to get an application key from Spotify before use.*
|
||||
|
||||
|
||||
Installing libspotify and pyspotify
|
||||
-----------------------------------
|
||||
|
||||
As libspotify's installation script at the moment is somewhat broken (see this
|
||||
`GetSatisfaction thread <http://getsatisfaction.com/spotify/topics/libspotify_please_fix_the_installation_script>`_
|
||||
for details), it is easiest to use the libspotify files bundled with pyspotify.
|
||||
The files bundled with pyspotify are for 64-bit, so if you run a 32-bit OS, you
|
||||
must get libspotify from https://developer.spotify.com/en/libspotify/.
|
||||
|
||||
Install pyspotify's dependencies. At Debian/Ubuntu systems::
|
||||
|
||||
sudo aptitude install python-alsaaudio
|
||||
|
||||
Check out the pyspotify code, and install it::
|
||||
|
||||
git clone git://github.com/winjer/pyspotify.git
|
||||
cd pyspotify
|
||||
export LD_LIBRARY_PATH=$PWD/lib
|
||||
sudo python setup.py develop
|
||||
|
||||
Apply for an application key at
|
||||
https://developer.spotify.com/en/libspotify/application-key, download the
|
||||
binary version, and place the file at ``pyspotify/spotify_appkey.key``.
|
||||
|
||||
Test your libspotify setup::
|
||||
|
||||
./example1.py -u USERNAME -p PASSWORD
|
||||
|
||||
Until Spotify fixes their installation script, you'll have to set
|
||||
``LD_LIBRARY_PATH`` every time you are going to use libspotify (in other words
|
||||
before starting Mopidy).
|
||||
|
||||
|
||||
Running Mopidy
|
||||
==============
|
||||
|
||||
Create a file name ``local_settings.py`` in the same directory as
|
||||
``settings.py``. Enter your Spotify Premium account's username and password
|
||||
into the file, like this::
|
||||
|
||||
SPOTIFY_USERNAME = u'myusername'
|
||||
SPOTIFY_PASSWORD = u'mysecret'
|
||||
|
||||
Currently the despotify backend is the default. If you want to use the
|
||||
libspotify backend, copy the Spotify application key to
|
||||
``mopidy/spotify_appkey.key``, and add the following to
|
||||
``mopidy/mopidy/local_settings.py``::
|
||||
|
||||
BACKEND=u'mopidy.backends.libspotify.LibspotifyBackend'
|
||||
|
||||
To start Mopidy, go to the root of the Mopidy project, then simply run::
|
||||
|
||||
python mopidy
|
||||
|
||||
To stop Mopidy, press ``CTRL+C``.
|
||||
@ -1,4 +0,0 @@
|
||||
Pyspotify issues
|
||||
----------------
|
||||
|
||||
* None at the moment.
|
||||
Loading…
Reference in New Issue
Block a user