mirror of
https://github.com/vale981/clay
synced 2025-03-05 09:31:40 -05:00
Added track caching option & more debugging.
This commit is contained in:
parent
75e62e5fe3
commit
c4cb66a759
7 changed files with 108 additions and 3 deletions
|
@ -63,6 +63,7 @@ Documentation is .
|
|||
- Notifications
|
||||
- Audio equalizer
|
||||
- Global hotkeys
|
||||
- Song file caching
|
||||
- Configuration UI
|
||||
- Token caching for faster authorizations
|
||||
- Song operations (add to library, start station etc.)
|
||||
|
|
|
@ -615,3 +615,10 @@ class GP(object):
|
|||
Return True if user is authenticated on Google Play Music, false otherwise.
|
||||
"""
|
||||
return self.mobile_client.is_authenticated()
|
||||
|
||||
@property
|
||||
def is_subscribed(self):
|
||||
"""
|
||||
Return True if user is subscribed on Google Play Music, false otherwise.
|
||||
"""
|
||||
return self.mobile_client.is_subscribed
|
||||
|
|
|
@ -7,7 +7,7 @@ except ImportError:
|
|||
codename = None
|
||||
|
||||
APP_NAME = 'Clay Player'
|
||||
VERSION = '0.5.6'
|
||||
VERSION = '0.6.0'
|
||||
if codename is not None:
|
||||
VERSION_WITH_CODENAME = VERSION + '-' + codename(separator='-', id=VERSION)
|
||||
else:
|
||||
|
|
|
@ -6,6 +6,7 @@ import urwid
|
|||
from clay.pages.page import AbstractPage
|
||||
from clay.log import Logger
|
||||
from clay.clipboard import copy
|
||||
from clay.gp import GP
|
||||
|
||||
|
||||
class DebugItem(urwid.AttrMap):
|
||||
|
@ -52,12 +53,38 @@ class DebugPage(urwid.Pile, AbstractPage):
|
|||
self._append_log(log_record)
|
||||
Logger.get().on_log_event += self._append_log
|
||||
self.listbox = urwid.ListBox(self.walker)
|
||||
|
||||
self.debug_data = urwid.Text('')
|
||||
|
||||
super(DebugPage, self).__init__([
|
||||
('pack', self.debug_data),
|
||||
('pack', urwid.Text('')),
|
||||
('pack', urwid.Text('Hit "Enter" to copy selected message to clipboard.')),
|
||||
('pack', urwid.Divider(u'\u2550')),
|
||||
self.listbox
|
||||
])
|
||||
|
||||
GP.get().auth_state_changed += self.update
|
||||
|
||||
self.update()
|
||||
|
||||
def update(self, *_):
|
||||
"""
|
||||
Update this widget.
|
||||
"""
|
||||
gpclient = GP.get()
|
||||
self.debug_data.set_text(
|
||||
'- Is authenticated: {}\n'
|
||||
'- Is subscribed: {}'.format(
|
||||
gpclient.is_authenticated,
|
||||
gpclient.is_subscribed if gpclient.is_authenticated else None
|
||||
)
|
||||
)
|
||||
|
||||
def _append_log(self, log_record):
|
||||
"""
|
||||
Add log record to list.
|
||||
"""
|
||||
self.walker.insert(0, urwid.Divider(u'\u2500'))
|
||||
self.walker.insert(0, DebugItem(log_record))
|
||||
|
||||
|
|
|
@ -138,6 +138,10 @@ class SettingsPage(urwid.Columns, AbstractPage):
|
|||
self.device_id = urwid.Edit(
|
||||
edit_text=config.get('device_id', '')
|
||||
)
|
||||
self.download_tracks = urwid.CheckBox(
|
||||
'Download tracks before playback',
|
||||
state=config.get('download_tracks', False)
|
||||
)
|
||||
self.equalizer = Equalizer()
|
||||
super(SettingsPage, self).__init__([urwid.ListBox(urwid.SimpleListWalker([
|
||||
urwid.Text('Settings'),
|
||||
|
@ -151,6 +155,8 @@ class SettingsPage(urwid.Columns, AbstractPage):
|
|||
urwid.Text('Device ID'),
|
||||
urwid.AttrWrap(self.device_id, 'input', 'input_focus'),
|
||||
urwid.Divider(' '),
|
||||
self.download_tracks,
|
||||
urwid.Divider(' '),
|
||||
urwid.AttrWrap(urwid.Button(
|
||||
'Save', on_press=self.on_save
|
||||
), 'input', 'input_focus'),
|
||||
|
@ -165,7 +171,8 @@ class SettingsPage(urwid.Columns, AbstractPage):
|
|||
Settings.set_config(dict(
|
||||
username=self.username.edit_text,
|
||||
password=self.password.edit_text,
|
||||
device_id=self.device_id.edit_text
|
||||
device_id=self.device_id.edit_text,
|
||||
download_tracks=self.download_tracks.state
|
||||
))
|
||||
self.app.set_page('MyLibraryPage')
|
||||
self.app.log_in()
|
||||
|
|
|
@ -5,12 +5,18 @@ Media player built using libVLC.
|
|||
# pylint: disable=too-many-public-methods
|
||||
from random import randint
|
||||
import json
|
||||
try: # Python 3.x
|
||||
from urllib.request import urlopen
|
||||
except ImportError: # Python 2.x
|
||||
from urllib2 import urlopen
|
||||
|
||||
from clay import vlc
|
||||
from clay.eventhook import EventHook
|
||||
from clay.notifications import NotificationArea
|
||||
from clay.hotkeys import HotkeyManager
|
||||
from clay.settings import Settings
|
||||
from clay import meta
|
||||
from clay.log import Logger
|
||||
|
||||
|
||||
class Queue(object):
|
||||
|
@ -329,10 +335,34 @@ class Player(object):
|
|||
if track is None:
|
||||
return
|
||||
self._is_loading = True
|
||||
track.get_url(callback=self._play_ready)
|
||||
self.broadcast_state()
|
||||
self.track_changed.fire(track)
|
||||
|
||||
if Settings.get_config().get('download_tracks', False):
|
||||
path = Settings.get_cached_file_path(track.store_id + '.mp3')
|
||||
if path is None:
|
||||
Logger.get().debug('Track %s not in cache, downloading...', track.store_id)
|
||||
track.get_url(callback=self._download_track)
|
||||
else:
|
||||
Logger.get().debug('Track %s in cache, playing', track.store_id)
|
||||
self._play_ready(path, None, track)
|
||||
else:
|
||||
Logger.get().debug('Starting to stream %s', track.store_id)
|
||||
track.get_url(callback=self._play_ready)
|
||||
|
||||
def _download_track(self, url, error, track):
|
||||
if error:
|
||||
NotificationArea.notify('Failed to request media URL: {}'.format(str(error)))
|
||||
Logger.get().error(
|
||||
'Failed to request media URL for track %s: %s',
|
||||
track.store_id,
|
||||
str(error)
|
||||
)
|
||||
return
|
||||
response = urlopen(url)
|
||||
path = Settings.save_file_to_cache(track.store_id + '.mp3', response.read())
|
||||
self._play_ready(path, None, track)
|
||||
|
||||
def _play_ready(self, url, error, track):
|
||||
"""
|
||||
Called once track's media stream URL request completes.
|
||||
|
@ -341,6 +371,11 @@ class Player(object):
|
|||
self._is_loading = False
|
||||
if error:
|
||||
NotificationArea.notify('Failed to request media URL: {}'.format(str(error)))
|
||||
Logger.get().error(
|
||||
'Failed to request media URL for track %s: %s',
|
||||
track.store_id,
|
||||
str(error)
|
||||
)
|
||||
return
|
||||
assert track
|
||||
media = vlc.Media(url)
|
||||
|
|
|
@ -25,6 +25,12 @@ class Settings(object):
|
|||
if error.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
try:
|
||||
os.makedirs(appdirs.user_cache_dir('clay', 'Clay'))
|
||||
except OSError as error:
|
||||
if error.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
path = os.path.join(filedir, 'config.yaml')
|
||||
if not os.path.exists(path):
|
||||
with open(path, 'w') as settings:
|
||||
|
@ -48,3 +54,25 @@ class Settings(object):
|
|||
config.update(new_config)
|
||||
with open(Settings.get_config_filename(), 'w') as settings:
|
||||
settings.write(yaml.dump(config, default_flow_style=False))
|
||||
|
||||
@classmethod
|
||||
def get_cached_file_path(cls, filename):
|
||||
"""
|
||||
Get full path to cached file.
|
||||
"""
|
||||
cache_dir = appdirs.user_cache_dir('clay', 'Clay')
|
||||
path = os.path.join(cache_dir, filename)
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def save_file_to_cache(cls, filename, content):
|
||||
"""
|
||||
Save content into file in cache.
|
||||
"""
|
||||
cache_dir = appdirs.user_cache_dir('clay', 'Clay')
|
||||
path = os.path.join(cache_dir, filename)
|
||||
with open(path, 'wb') as cachefile:
|
||||
cachefile.write(content)
|
||||
return path
|
||||
|
|
Loading…
Add table
Reference in a new issue