Merge pull request #864 from jodal/feature/history

Add history controller to core API
This commit is contained in:
Thomas Adamcik 2014-09-23 20:43:03 +02:00
commit 339221089d
8 changed files with 124 additions and 0 deletions

View File

@ -37,6 +37,15 @@ Manages everything related to the tracks we are currently playing.
:members:
History controller
==================
Keeps record of what tracks have been played.
.. autoclass:: mopidy.core.HistoryController
:members:
Playlists controller
====================

View File

@ -10,6 +10,9 @@ v0.20.0 (UNRELEASED)
**Core API**
- Added :class:`mopidy.core.HistoryController` which keeps track of what
tracks have been played. (Fixes: :issue:`423`, PR: :issue:`803`)
- Removed ``clear_current_track`` keyword argument to
:meth:`mopidy.core.Playback.stop`. It was a leaky internal abstraction,
which was never intended to be used externally.

View File

@ -2,6 +2,7 @@ from __future__ import unicode_literals
# flake8: noqa
from .actor import Core
from .history import HistoryController
from .library import LibraryController
from .listener import CoreListener
from .playback import PlaybackController, PlaybackState

View File

@ -7,6 +7,7 @@ import pykka
from mopidy import audio, backend, mixer
from mopidy.audio import PlaybackState
from mopidy.core.history import HistoryController
from mopidy.core.library import LibraryController
from mopidy.core.listener import CoreListener
from mopidy.core.playback import PlaybackController
@ -23,6 +24,10 @@ class Core(
"""The library controller. An instance of
:class:`mopidy.core.LibraryController`."""
history = None
"""The playback history controller. An instance of
:class:`mopidy.core.HistoryController`."""
playback = None
"""The playback controller. An instance of
:class:`mopidy.core.PlaybackController`."""
@ -42,6 +47,8 @@ class Core(
self.library = LibraryController(backends=self.backends, core=self)
self.history = HistoryController()
self.playback = PlaybackController(
mixer=mixer, backends=self.backends, core=self)

54
mopidy/core/history.py Normal file
View File

@ -0,0 +1,54 @@
from __future__ import unicode_literals
import copy
import logging
import time
from mopidy import models
logger = logging.getLogger(__name__)
class HistoryController(object):
def __init__(self):
self._history = []
def add(self, track):
"""Add track to the playback history.
:param track: track to add
:type track: :class:`mopidy.models.Track`
"""
if not isinstance(track, models.Track):
raise TypeError('Only Track objects can be added to the history')
timestamp = int(time.time() * 1000)
name_parts = []
if track.artists:
name_parts.append(
', '.join([artist.name for artist in track.artists]))
if track.name is not None:
name_parts.append(track.name)
name = ' - '.join(name_parts)
ref = models.Ref.track(uri=track.uri, name=name)
self._history.insert(0, (timestamp, ref))
def get_length(self):
"""Get the number of tracks in the history.
:returns: the history length
:rtype: int
"""
return len(self._history)
def get_history(self):
"""Get the track history.
:returns: the track history
:rtype: list of (timestamp, mopidy.models.Ref) tuples
"""
return copy.copy(self._history)

View File

@ -250,6 +250,7 @@ class PlaybackController(object):
if success:
self.core.tracklist.mark_playing(tl_track)
self.core.history.add(tl_track.track)
# TODO: replace with stream-changed
self._trigger_track_playback_started()
else:

View File

@ -41,6 +41,7 @@ def make_jsonrpc_wrapper(core_actor):
objects={
'core.get_uri_schemes': core.Core.get_uri_schemes,
'core.get_version': core.Core.get_version,
'core.history': core.HistoryController,
'core.library': core.LibraryController,
'core.playback': core.PlaybackController,
'core.playlists': core.PlaylistsController,
@ -51,6 +52,7 @@ def make_jsonrpc_wrapper(core_actor):
'core.describe': inspector.describe,
'core.get_uri_schemes': core_actor.get_uri_schemes,
'core.get_version': core_actor.get_version,
'core.history': core_actor.history,
'core.library': core_actor.library,
'core.playback': core_actor.playback,
'core.playlists': core_actor.playlists,

View File

@ -0,0 +1,47 @@
from __future__ import unicode_literals
import unittest
from mopidy.core import HistoryController
from mopidy.models import Artist, Track
class PlaybackHistoryTest(unittest.TestCase):
def setUp(self):
self.tracks = [
Track(uri='dummy1:a', name='foo',
artists=[Artist(name='foober'), Artist(name='barber')]),
Track(uri='dummy2:a', name='foo'),
Track(uri='dummy3:a', name='bar')
]
self.history = HistoryController()
def test_add_track(self):
self.history.add(self.tracks[0])
self.assertEqual(self.history.get_length(), 1)
self.history.add(self.tracks[1])
self.assertEqual(self.history.get_length(), 2)
self.history.add(self.tracks[2])
self.assertEqual(self.history.get_length(), 3)
def test_non_tracks_are_rejected(self):
with self.assertRaises(TypeError):
self.history.add(object())
self.assertEqual(self.history.get_length(), 0)
def test_history_entry_contents(self):
track = self.tracks[0]
self.history.add(track)
result = self.history.get_history()
(timestamp, ref) = result[0]
self.assertIsInstance(timestamp, int)
self.assertEqual(track.uri, ref.uri)
self.assertIn(track.name, ref.name)
for artist in track.artists:
self.assertIn(artist.name, ref.name)