http: Extend player resource, add tracklist and playlists resources
This commit is contained in:
parent
5458c1271f
commit
86e0eff21d
@ -11,14 +11,96 @@ class ApiResource(object):
|
||||
|
||||
def __init__(self, core):
|
||||
self.core = core
|
||||
self.player = PlayerResource(core)
|
||||
self.tracklist = TrackListResource(core)
|
||||
self.playlists = PlaylistsResource(core)
|
||||
|
||||
@cherrypy.tools.json_out()
|
||||
def GET(self):
|
||||
playback_state = self.core.playback.state.get()
|
||||
track = self.core.playback.current_track.get()
|
||||
if track:
|
||||
track = track.serialize()
|
||||
return {
|
||||
'playback_state': playback_state,
|
||||
'current_track': track,
|
||||
'resources': {
|
||||
'player': {
|
||||
'href': '/api/player/',
|
||||
},
|
||||
'tracklist': {
|
||||
'href': '/api/tracklist/',
|
||||
},
|
||||
'playlists': {
|
||||
'href': '/api/playlists/',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PlayerResource(object):
|
||||
exposed = True
|
||||
|
||||
def __init__(self, core):
|
||||
self.core = core
|
||||
|
||||
@cherrypy.tools.json_out()
|
||||
def GET(self):
|
||||
futures = {
|
||||
'state': self.core.playback.state,
|
||||
'current_track': self.core.playback.current_track,
|
||||
'consume': self.core.playback.consume,
|
||||
'random': self.core.playback.random,
|
||||
'repeat': self.core.playback.repeat,
|
||||
'single': self.core.playback.single,
|
||||
'volume': self.core.playback.volume,
|
||||
'time_position': self.core.playback.time_position,
|
||||
}
|
||||
current_track = futures['current_track'].get()
|
||||
if current_track:
|
||||
current_track = current_track.serialize()
|
||||
return {
|
||||
'properties': {
|
||||
'state': futures['state'].get(),
|
||||
'currentTrack': current_track,
|
||||
'consume': futures['consume'].get(),
|
||||
'random': futures['random'].get(),
|
||||
'repeat': futures['repeat'].get(),
|
||||
'single': futures['single'].get(),
|
||||
'volume': futures['volume'].get(),
|
||||
'timePosition': futures['time_position'].get(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TrackListResource(object):
|
||||
exposed = True
|
||||
|
||||
def __init__(self, core):
|
||||
self.core = core
|
||||
|
||||
@cherrypy.tools.json_out()
|
||||
def GET(self):
|
||||
futures = {
|
||||
'cp_tracks': self.core.current_playlist.cp_tracks,
|
||||
'current_cp_track': self.core.playback.current_cp_track,
|
||||
}
|
||||
cp_tracks = futures['cp_tracks'].get()
|
||||
tracks = []
|
||||
for cp_track in cp_tracks:
|
||||
track = cp_track.track.serialize()
|
||||
track['cpid'] = cp_track.cpid
|
||||
tracks.append(track)
|
||||
current_cp_track = futures['current_cp_track'].get()
|
||||
return {
|
||||
'currentTrackCpid': current_cp_track and current_cp_track.cpid,
|
||||
'tracks': tracks,
|
||||
}
|
||||
|
||||
|
||||
class PlaylistsResource(object):
|
||||
exposed = True
|
||||
|
||||
def __init__(self, core):
|
||||
self.core = core
|
||||
|
||||
@cherrypy.tools.json_out()
|
||||
def GET(self):
|
||||
playlists = self.core.stored_playlists.playlists.get()
|
||||
return {
|
||||
'playlists': [p.serialize() for p in playlists],
|
||||
}
|
||||
|
||||
0
tests/frontends/http/__init__.py
Normal file
0
tests/frontends/http/__init__.py
Normal file
118
tests/frontends/http/api_test.py
Normal file
118
tests/frontends/http/api_test.py
Normal file
@ -0,0 +1,118 @@
|
||||
import pykka
|
||||
|
||||
from tests import unittest
|
||||
|
||||
from mopidy import core
|
||||
from mopidy.backends import dummy
|
||||
from mopidy.frontends.http import api
|
||||
from mopidy.models import Track
|
||||
|
||||
|
||||
class ApiResourceTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.backend = dummy.DummyBackend.start(audio=None).proxy()
|
||||
self.core = core.Core.start(backends=[self.backend]).proxy()
|
||||
self.api = api.ApiResource(core=self.core)
|
||||
|
||||
self.core.stored_playlists.create('x')
|
||||
self.core.stored_playlists.create('y')
|
||||
self.core.stored_playlists.create('z')
|
||||
self.core.current_playlist.append([
|
||||
Track(uri='dummy:a'),
|
||||
Track(uri='dummy:b'),
|
||||
Track(uri='dummy:c'),
|
||||
])
|
||||
|
||||
def tearDown(self):
|
||||
pykka.ActorRegistry.stop_all()
|
||||
|
||||
def test_api_get_returns_list_of_resources(self):
|
||||
result = self.api.GET()
|
||||
|
||||
self.assertIn('resources', result)
|
||||
|
||||
self.assertIn('player', result['resources'])
|
||||
self.assertEquals('/api/player/',
|
||||
result['resources']['player']['href'])
|
||||
|
||||
self.assertIn('tracklist', result['resources'])
|
||||
self.assertEquals('/api/tracklist/',
|
||||
result['resources']['tracklist']['href'])
|
||||
|
||||
self.assertIn('playlists', result['resources'])
|
||||
self.assertEquals('/api/playlists/',
|
||||
result['resources']['playlists']['href'])
|
||||
|
||||
def test_player_get_returns_playback_properties(self):
|
||||
result = self.api.player.GET()
|
||||
|
||||
self.assertIn('properties', result)
|
||||
|
||||
self.assertIn('state', result['properties'])
|
||||
self.assertEqual('stopped', result['properties']['state'])
|
||||
|
||||
self.assertIn('currentTrack', result['properties'])
|
||||
self.assertEqual(None, result['properties']['currentTrack'])
|
||||
|
||||
self.assertIn('consume', result['properties'])
|
||||
self.assertEqual(False, result['properties']['consume'])
|
||||
|
||||
self.assertIn('random', result['properties'])
|
||||
self.assertEqual(False, result['properties']['random'])
|
||||
|
||||
self.assertIn('repeat', result['properties'])
|
||||
self.assertEqual(False, result['properties']['repeat'])
|
||||
|
||||
self.assertIn('single', result['properties'])
|
||||
self.assertEqual(False, result['properties']['single'])
|
||||
|
||||
self.assertIn('volume', result['properties'])
|
||||
self.assertEqual(None, result['properties']['volume'])
|
||||
|
||||
self.assertIn('timePosition', result['properties'])
|
||||
self.assertEqual(0, result['properties']['timePosition'])
|
||||
|
||||
def test_player_state_changes_when_playing(self):
|
||||
self.core.playback.play()
|
||||
|
||||
result = self.api.player.GET()
|
||||
|
||||
self.assertEqual('playing', result['properties']['state'])
|
||||
|
||||
def test_player_volume_changes(self):
|
||||
self.core.playback.volume = 37
|
||||
|
||||
result = self.api.player.GET()
|
||||
|
||||
self.assertEqual(37, result['properties']['volume'])
|
||||
|
||||
def test_tracklist_returns_current_playlist(self):
|
||||
result = self.api.tracklist.GET()
|
||||
|
||||
self.assertIn('tracks', result)
|
||||
self.assertEqual(3, len(result['tracks']))
|
||||
|
||||
self.assertEqual('dummy:a', result['tracks'][0]['uri'])
|
||||
self.assertEqual(0, result['tracks'][0]['cpid'])
|
||||
|
||||
self.assertEqual('dummy:b', result['tracks'][1]['uri'])
|
||||
self.assertEqual(1, result['tracks'][1]['cpid'])
|
||||
|
||||
self.assertEqual('dummy:c', result['tracks'][2]['uri'])
|
||||
self.assertEqual(2, result['tracks'][2]['cpid'])
|
||||
|
||||
def test_tracklist_includes_current_track(self):
|
||||
self.core.playback.play()
|
||||
|
||||
result = self.api.tracklist.GET()
|
||||
|
||||
self.assertIn('currentTrackCpid', result)
|
||||
self.assertEqual(0, result['currentTrackCpid'])
|
||||
|
||||
def test_playlists_returns_stored_playlists(self):
|
||||
result = self.api.playlists.GET()
|
||||
|
||||
self.assertIn('playlists', result)
|
||||
self.assertEqual('x', result['playlists'][0]['name'])
|
||||
self.assertEqual('y', result['playlists'][1]['name'])
|
||||
self.assertEqual('z', result['playlists'][2]['name'])
|
||||
5
tests/frontends/http/ws_test.py
Normal file
5
tests/frontends/http/ws_test.py
Normal file
@ -0,0 +1,5 @@
|
||||
from tests import unittest
|
||||
|
||||
|
||||
class WebSocketsTest(unittest.TestCase):
|
||||
pass # TODO
|
||||
Loading…
Reference in New Issue
Block a user