Release v0.19.2

This commit is contained in:
Stein Magnus Jodal 2014-07-26 14:19:34 +02:00
commit 2f13eaf59d
13 changed files with 123 additions and 27 deletions

View File

@ -40,3 +40,4 @@
- Pierpaolo Frasa <pfrasa@smail.uni-koeln.de>
- Thomas Scholtes <thomas-scholtes@gmx.de>
- Sam Willcocks <sam@wlcx.cc>
- Ignasi Fosch <natx@y10k.ws>

View File

@ -2,24 +2,57 @@
Mopidy
******
Mopidy is a music server which can play music both from multiple sources, like
your local hard drive, radio streams, and from Spotify and SoundCloud. Searches
combines results from all music sources, and you can mix tracks from all
sources in your play queue. Your playlists from Spotify or SoundCloud are also
available for use.
Mopidy is an extensible music server written in Python.
To control your Mopidy music server, you can use one of Mopidy's web clients,
the Ubuntu Sound Menu, any device on the same network which can control UPnP
MediaRenderers, or any MPD client. MPD clients are available for many
platforms, including Windows, OS X, Linux, Android and iOS.
Mopidy plays music from local disk, Spotify, SoundCloud, Google Play Music, and
more. You edit the playlist from any phone, tablet, or computer using a range
of MPD and web clients.
To get started with Mopidy, check out `the docs <http://docs.mopidy.com/>`_.
**Stream music from the cloud**
Vanilla Mopidy only plays music from your local disk and radio streams.
Through extensions, Mopidy can play music from cloud services like Spotify,
SoundCloud, and Google Play Music. With Mopidy's extension support, backends
for new music sources can be easily added.
**Mopidy is just a server**
Mopidy is a Python application that runs in a terminal or in the background on
Linux computers or Macs that have network connectivity and audio output. Out of
the box, Mopidy is an MPD and HTTP server. Additional frontends for controlling
Mopidy can be installed from extensions.
**Everybody use their favorite client**
You and the people around you can all connect their favorite MPD or web client
to the Mopidy server to search for music and manage the playlist together. With
a browser or MPD client, which is available for all popular operating systems,
you can control the music from any phone, tablet, or computer.
**Mopidy on Raspberry Pi**
The Raspberry Pi is a popular device to run Mopidy on, either using Raspbian or
Arch Linux. It is quite slow, but it is very affordable. In fact, the
Kickstarter funded Gramofon: Modern Cloud Jukebox project used Mopidy on a
Raspberry Pi to prototype the Gramofon device. Mopidy is also a major building
block in the Pi Musicbox integrated audio jukebox system for Raspberry Pi.
**Mopidy is hackable**
Mopidy's extension support and Python, JSON-RPC, and JavaScript APIs makes
Mopidy perfect for building your own hacks. In one project, a Raspberry Pi was
embedded in an old cassette player. The buttons and volume control are wired up
with GPIO on the Raspberry Pi, and is used to control playback through a custom
Mopidy extension. The cassettes have NFC tags used to select playlists from
Spotify.
To get started with Mopidy, check out
`the installation docs <http://docs.mopidy.com/en/latest/installation/>`_.
- `Documentation <http://docs.mopidy.com/>`_
- `Source code <https://github.com/mopidy/mopidy>`_
- `Issue tracker <https://github.com/mopidy/mopidy/issues>`_
- `CI server <https://travis-ci.org/mopidy/mopidy>`_
- `Download development snapshot <https://github.com/mopidy/mopidy/archive/develop.tar.gz#egg=mopidy-dev>`_
- `Development branch tarball <https://github.com/mopidy/mopidy/archive/develop.tar.gz#egg=mopidy-dev>`_
- IRC: ``#mopidy`` at `irc.freenode.net <http://freenode.net/>`_
- Mailing list: `mopidy@googlegroups.com <https://groups.google.com/forum/?fromgroups=#!forum/mopidy>`_

View File

@ -4,6 +4,29 @@ Changelog
This changelog is used to track all major changes to Mopidy.
v0.19.2 (2014-07-26)
====================
Bug fix release, directly from the Mopidy development sprint at EuroPython 2014
in Berlin.
**Audio**
- Make :confval:`audio/mixer_volume` work on the software mixer again. This
was broken with the mixer changes in 0.19.0. (Fixes: :issue:`791`)
**HTTP frontend**
- When using Tornado 4.0, allow WebSocket requests from other hosts. (Fixes:
:issue:`788`)
**MPD frontend**
- Fix crash when MPD commands are called with the wrong number of arguments.
This was broken with the MPD command changes in 0.19.0. (Fixes: :issue:`789`)
v0.19.1 (2014-07-23)
====================
@ -15,7 +38,7 @@ Bug fix release.
Mopidy continue to work on Debian/Raspbian stable, where Tornado 2.3 is the
newest version available.
**HTTP**
**HTTP frontend**
- Add missing string interpolation placeholder.

View File

@ -20,6 +20,9 @@ If you are running OS X, you can install everything needed with Homebrew.
brew update
brew upgrade
Notice that this will upgrade all software on your system that have been
installed with Homebrew.
#. Mopidy works out of box if you have installed Python from Homebrew::
brew install python
@ -36,6 +39,10 @@ If you are running OS X, you can install everything needed with Homebrew.
export PYTHONPATH=$(brew --prefix)/lib/python2.7/site-packages:$PYTHONPATH
And then reload the shell's init file or restart your terminal::
source ~/.bashrc
Or, you can prefix the Mopidy command every time you run it::
PYTHONPATH=$(brew --prefix)/lib/python2.7/site-packages mopidy

View File

@ -21,4 +21,4 @@ if (isinstance(pykka.__version__, basestring)
warnings.filterwarnings('ignore', 'could not open display')
__version__ = '0.19.1'
__version__ = '0.19.2'

View File

@ -195,6 +195,14 @@ class Audio(pykka.ThreadingActor):
self._connect(self._playbin, 'notify::volume', self._on_mixer_change)
self._connect(self._playbin, 'notify::mute', self._on_mixer_change)
# The Mopidy startup procedure will set the initial volume of a mixer,
# but this happens before the audio actor is injected into the software
# mixer and has no effect. Thus, we need to set the initial volume
# again.
initial_volume = self._config['audio']['mixer_volume']
if initial_volume is not None:
self._mixer.set_volume(initial_volume)
def _on_mixer_change(self, element, gparamspec):
self._mixer.trigger_events_for_changed_values()

View File

@ -112,6 +112,11 @@ class WebSocketHandler(tornado.websocket.WebSocketHandler):
logger.error('WebSocket request error: %s', e)
self.close()
def check_origin(self, origin):
# Allow cross-origin WebSocket connections, like Tornado before 4.0
# defaulted to.
return True
def set_mopidy_headers(request_handler):
request_handler.set_header('Cache-Control', 'no-cache')

View File

@ -138,7 +138,13 @@ class Commands(object):
def validate(*args, **kwargs):
if varargs:
return func(*args, **kwargs)
callargs = inspect.getcallargs(func, *args, **kwargs)
try:
callargs = inspect.getcallargs(func, *args, **kwargs)
except TypeError:
raise exceptions.MpdArgError(
'wrong number of arguments for "%s"' % name)
for key, value in callargs.items():
default = defaults.get(key, object())
if key in validators and value != default:
@ -146,6 +152,7 @@ class Commands(object):
callargs[key] = validators[key](value)
except ValueError:
raise exceptions.MpdArgError('incorrect arguments')
return func(**callargs)
validate.auth_required = auth_required

View File

@ -143,21 +143,23 @@ def _gstreamer_check_elements():
# Spotify
'appsrc',
# Mixers and sinks
'alsamixer',
# Audio sinks
'alsasink',
'ossmixer',
'osssink',
'oss4mixer',
'oss4sink',
'pulsemixer',
'pulsesink',
# MP3 encoding and decoding
'mp3parse',
#
# One of flump3dec, mad, and mpg123audiodec is required for MP3
# playback.
'flump3dec',
'id3demux',
'id3v2mux',
'lame',
'mad',
'mp3parse',
# 'mpg123audiodec', # Only available in GStreamer 1.x
# Ogg Vorbis encoding and decoding
'vorbisdec',

View File

@ -19,6 +19,12 @@ class AuthenticationActiveTest(protocol.BaseTestCase):
self.assertFalse(self.dispatcher.authenticated)
self.assertEqualResponse('ACK [3@0] {password} incorrect password')
def test_authentication_without_password_fails(self):
self.sendRequest('password')
self.assertFalse(self.dispatcher.authenticated)
self.assertEqualResponse(
'ACK [2@0] {password} wrong number of arguments for "password"')
def test_anything_when_not_authenticated_should_fail(self):
self.sendRequest('any request at all')
self.assertFalse(self.dispatcher.authenticated)

View File

@ -169,15 +169,15 @@ class TestCommands(unittest.TestCase):
def test_call_incorrect_args(self):
self.commands.add('foo')(lambda context: context)
with self.assertRaises(TypeError):
with self.assertRaises(exceptions.MpdArgError):
self.commands.call(['foo', 'bar'])
self.commands.add('bar')(lambda context, required: context)
with self.assertRaises(TypeError):
with self.assertRaises(exceptions.MpdArgError):
self.commands.call(['bar', 'bar', 'baz'])
self.commands.add('baz')(lambda context, optional=None: context)
with self.assertRaises(TypeError):
with self.assertRaises(exceptions.MpdArgError):
self.commands.call(['baz', 'bar', 'baz'])
def test_validator_gets_applied_to_required_arg(self):

View File

@ -14,7 +14,10 @@ class HelpTest(unittest.TestCase):
args = [sys.executable, mopidy_dir, '--help']
process = subprocess.Popen(
args,
env={'PYTHONPATH': os.path.join(mopidy_dir, '..')},
env={'PYTHONPATH': ':'.join([
os.path.join(mopidy_dir, '..'),
os.environ.get('PYTHONPATH', '')
])},
stdout=subprocess.PIPE)
output = process.communicate()[0]
self.assertIn('--version', output)

View File

@ -47,5 +47,6 @@ class VersionTest(unittest.TestCase):
self.assertLess(SV('0.18.1'), SV('0.18.2'))
self.assertLess(SV('0.18.2'), SV('0.18.3'))
self.assertLess(SV('0.18.3'), SV('0.19.0'))
self.assertLess(SV('0.19.0'), SV(__version__))
self.assertLess(SV(__version__), SV('0.19.2'))
self.assertLess(SV('0.19.0'), SV('0.19.1'))
self.assertLess(SV('0.19.1'), SV(__version__))
self.assertLess(SV(__version__), SV('0.19.3'))