Add tracking of time position in track
This commit is contained in:
parent
4b13e4ad33
commit
077f13a5dd
@ -1,3 +1,5 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
class BaseBackend(object):
|
class BaseBackend(object):
|
||||||
PLAY = u'play'
|
PLAY = u'play'
|
||||||
PAUSE = u'pause'
|
PAUSE = u'pause'
|
||||||
@ -5,6 +7,8 @@ class BaseBackend(object):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.state = self.STOP
|
self.state = self.STOP
|
||||||
|
self._play_time_accumulated = 0
|
||||||
|
self._play_start = False
|
||||||
|
|
||||||
def current_song(self):
|
def current_song(self):
|
||||||
return None
|
return None
|
||||||
@ -38,6 +42,19 @@ class BaseBackend(object):
|
|||||||
return self.state
|
return self.state
|
||||||
|
|
||||||
def status_time(self):
|
def status_time(self):
|
||||||
|
return u'%s:%s' % (
|
||||||
|
self.status_time_position(), self.status_time_total())
|
||||||
|
|
||||||
|
def status_time_position(self):
|
||||||
|
if self.state == self.PAUSE:
|
||||||
|
return self._play_time_accumulated
|
||||||
|
elif self.state == self.PLAY and self._play_start:
|
||||||
|
return self._play_time_accumulated + (
|
||||||
|
int(time.time()) - self._play_start)
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def status_time_total(self):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def status_xfade(self):
|
def status_xfade(self):
|
||||||
@ -49,21 +66,29 @@ class BaseBackend(object):
|
|||||||
|
|
||||||
def pause(self):
|
def pause(self):
|
||||||
self.state = self.PAUSE
|
self.state = self.PAUSE
|
||||||
|
self._play_time_accumulated += int(time.time()) - self._play_start
|
||||||
|
|
||||||
def play(self):
|
def play(self):
|
||||||
self.state = self.PLAY
|
self.state = self.PLAY
|
||||||
|
self._play_time_accumulated = 0
|
||||||
|
self._play_start = int(time.time())
|
||||||
|
|
||||||
def play_pos(self, songpos):
|
def play_pos(self, songpos):
|
||||||
self.state = self.PLAY
|
self.state = self.PLAY
|
||||||
|
self._play_time_accumulated = 0
|
||||||
|
self._play_start = int(time.time())
|
||||||
|
|
||||||
def play_id(self, songid):
|
def play_id(self, songid):
|
||||||
self.state = self.PLAY
|
self.state = self.PLAY
|
||||||
|
self._play_time_accumulated = 0
|
||||||
|
self._play_start = int(time.time())
|
||||||
|
|
||||||
def previous(self):
|
def previous(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def resume(self):
|
def resume(self):
|
||||||
self.state = self.PLAY
|
self.state = self.PLAY
|
||||||
|
self._play_start = int(time.time())
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.state = self.STOP
|
self.state = self.STOP
|
||||||
|
|||||||
@ -63,6 +63,10 @@ class SpotifyBackend(BaseBackend):
|
|||||||
self._x_current_playlist_version = 0
|
self._x_current_playlist_version = 0
|
||||||
return self._x_current_playlist_version
|
return self._x_current_playlist_version
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _current_track(self):
|
||||||
|
return self._current_playlist[self._current_song_id]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _current_song_id(self):
|
def _current_song_id(self):
|
||||||
if not hasattr(self, '_x_current_song_id'):
|
if not hasattr(self, '_x_current_song_id'):
|
||||||
@ -106,42 +110,47 @@ class SpotifyBackend(BaseBackend):
|
|||||||
artist_names = [decode(artist.name) for artist in artists]
|
artist_names = [decode(artist.name) for artist in artists]
|
||||||
return u', '.join(artist_names)
|
return u', '.join(artist_names)
|
||||||
|
|
||||||
|
|
||||||
# Control methods
|
# Control methods
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
self._current_song_id += 1
|
self._current_song_id += 1
|
||||||
self.play_id(self._current_song_id)
|
self.play()
|
||||||
|
|
||||||
def pause(self):
|
def pause(self):
|
||||||
self.state = self.PAUSE
|
super(SpotifyBackend, self).pause()
|
||||||
self.spotify.pause()
|
self.spotify.pause()
|
||||||
|
|
||||||
def play(self):
|
def play(self):
|
||||||
self.play_id(self._current_song_id)
|
if self.state == self.PAUSE:
|
||||||
|
return self.resume()
|
||||||
|
super(SpotifyBackend, self).play()
|
||||||
|
self.spotify.play(self._current_track)
|
||||||
|
|
||||||
def play_pos(self, songpos):
|
def play_pos(self, songpos):
|
||||||
self.play_id(songpos)
|
super(SpotifyBackend, self).play_pos(songpos)
|
||||||
|
self._current_song_id = songpos
|
||||||
|
track = self._current_playlist[songid]
|
||||||
|
self.spotify.play(track)
|
||||||
|
|
||||||
def play_id(self, songid):
|
def play_id(self, songid):
|
||||||
self.state = self.PLAY
|
super(SpotifyBackend, self).play_id(songid)
|
||||||
self._current_song_id = songid
|
self._current_song_id = songid
|
||||||
track = self._current_playlist[songid]
|
track = self._current_playlist[songid]
|
||||||
self.spotify.play(track)
|
self.spotify.play(track)
|
||||||
|
|
||||||
def previous(self):
|
def previous(self):
|
||||||
self._current_song_id -= 1
|
self._current_song_id -= 1
|
||||||
self.play_id(self._current_song_id)
|
self.play()
|
||||||
|
|
||||||
def resume(self):
|
def resume(self):
|
||||||
self.state = self.PLAY
|
super(SpotifyBackend, self).resume()
|
||||||
self.spotify.resume()
|
self.spotify.resume()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
if self.state is not self.STOP:
|
super(SpotifyBackend, self).stop()
|
||||||
self.state = self.STOP
|
self.spotify.stop()
|
||||||
self.spotify.stop()
|
|
||||||
|
|
||||||
### MPD handlers
|
# Unsorted
|
||||||
|
|
||||||
def current_song(self):
|
def current_song(self):
|
||||||
try:
|
try:
|
||||||
@ -184,6 +193,7 @@ class SpotifyBackend(BaseBackend):
|
|||||||
return self._format_playlist(self._current_playlist)
|
return self._format_playlist(self._current_playlist)
|
||||||
|
|
||||||
# Status methods
|
# Status methods
|
||||||
|
|
||||||
def status_playlist(self):
|
def status_playlist(self):
|
||||||
return self._current_playlist_version
|
return self._current_playlist_version
|
||||||
|
|
||||||
@ -193,16 +203,14 @@ class SpotifyBackend(BaseBackend):
|
|||||||
def status_song_id(self):
|
def status_song_id(self):
|
||||||
return self._current_song_id
|
return self._current_song_id
|
||||||
|
|
||||||
def status_time(self):
|
def status_time_total(self):
|
||||||
if self.state is self.PLAY:
|
return self._current_track.length // 1000
|
||||||
return u'0:00'
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def url_handlers(self):
|
def url_handlers(self):
|
||||||
return [u'spotify:', u'http://open.spotify.com/']
|
return [u'spotify:', u'http://open.spotify.com/']
|
||||||
|
|
||||||
# Music database methods
|
# Music database methods
|
||||||
|
|
||||||
def search(self, type, what):
|
def search(self, type, what):
|
||||||
result = self.spotify.search(encode(u'%s:%s' % (type, what)))
|
result = self.spotify.search(encode(u'%s:%s' % (type, what)))
|
||||||
return self._format_playlist(result.playlist.tracks)
|
return self._format_playlist(result.playlist.tracks)
|
||||||
|
|||||||
@ -379,7 +379,7 @@ class MpdHandler(object):
|
|||||||
|
|
||||||
@register(r'^status$')
|
@register(r'^status$')
|
||||||
def _status(self):
|
def _status(self):
|
||||||
return [
|
result = [
|
||||||
('volume', self.backend.status_volume()),
|
('volume', self.backend.status_volume()),
|
||||||
('repeat', self.backend.status_repeat()),
|
('repeat', self.backend.status_repeat()),
|
||||||
('random', self.backend.status_random()),
|
('random', self.backend.status_random()),
|
||||||
@ -391,8 +391,10 @@ class MpdHandler(object):
|
|||||||
('state', self.backend.status_state()),
|
('state', self.backend.status_state()),
|
||||||
('song', self.backend.status_song_id()),
|
('song', self.backend.status_song_id()),
|
||||||
('songid', self.backend.status_song_id()),
|
('songid', self.backend.status_song_id()),
|
||||||
('time', self.backend.status_time()),
|
|
||||||
]
|
]
|
||||||
|
if self.backend.state in (self.backend.PLAY, self.backend.PAUSE):
|
||||||
|
result.append(('time', self.backend.status_time()))
|
||||||
|
return result
|
||||||
|
|
||||||
@register(r'^swap (?P<songpos1>\d+) (?P<songpos2>\d+)$')
|
@register(r'^swap (?P<songpos1>\d+) (?P<songpos2>\d+)$')
|
||||||
def _swap(self, songpos1, songpos2):
|
def _swap(self, songpos1, songpos2):
|
||||||
|
|||||||
@ -73,7 +73,8 @@ class CommandListsTest(unittest.TestCase):
|
|||||||
|
|
||||||
class StatusHandlerTest(unittest.TestCase):
|
class StatusHandlerTest(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.h = handler.MpdHandler(backend=DummyBackend())
|
self.b = DummyBackend()
|
||||||
|
self.h = handler.MpdHandler(backend=self.b)
|
||||||
|
|
||||||
def test_clearerror(self):
|
def test_clearerror(self):
|
||||||
result = self.h.handle_request(u'clearerror')
|
result = self.h.handle_request(u'clearerror')
|
||||||
@ -137,6 +138,15 @@ class StatusHandlerTest(unittest.TestCase):
|
|||||||
self.assert_('state' in result)
|
self.assert_('state' in result)
|
||||||
self.assert_(result['state'] in ('play', 'stop', 'pause'))
|
self.assert_(result['state'] in ('play', 'stop', 'pause'))
|
||||||
|
|
||||||
|
def test_status_method_when_playing(self):
|
||||||
|
self.b.state = self.b.PLAY
|
||||||
|
result = dict(self.h._status())
|
||||||
|
self.assert_('time' in result)
|
||||||
|
(position, total) = result['time'].split(':')
|
||||||
|
position = int(position)
|
||||||
|
total = int(total)
|
||||||
|
self.assert_(position <= total)
|
||||||
|
|
||||||
|
|
||||||
class PlaybackOptionsHandlerTest(unittest.TestCase):
|
class PlaybackOptionsHandlerTest(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user