def urlopen(_url, use_cache=True, retries=RETRIES): # set host port from 81 to 80, to fix image problem url = _url.replace(':81', '') if use_cache and ldb_imported: key = hash_byte(url) try: content = ldb_get(key) if content and len(content) > 10: try: timestamp = int(content[:10].decode()) if (time.time() - timestamp) < CACHE_TIMEOUT: return content[10:] except (ValueError, UnicodeDecodeError): logger.debug(traceback.format_exc()) except KeyError: logger.debug(traceback.format_exc()) for i in range(retries): try: req = request.urlopen(url, timeout=TIMEOUT) req_content = req.read() if use_cache and ldb_imported: ldb_put(key, str(int(time.time())).encode() + req_content) return req_content except URLError: logger.warn(traceback.format_exc()) logger.warn('Net.urlopen, url: %s' % url) return None
def get_image(url, filepath=None): if not url or len(url) < 10: logger.error('Net.get_image: url is invalid, %s' % url) return None if not filepath: filename = os.path.split(url)[1] filepath = os.path.join(Config.IMG_DIR, filename) if os.path.exists(filepath): return filepath image = urlopen(url, use_cache=False) if not image: logger.debug('Net.get_image: failed to get image, %s' % image) return None with open(filepath, 'wb') as fh: fh.write(image) # Now, check its mime type file_ = Gio.File.new_for_path(filepath) file_info = file_.query_info(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, Gio.FileQueryInfoFlags.NONE) content_type = file_info.get_content_type() if 'image' in content_type: return filepath else: os.remove(filepath) return None
def parse_lrc(lrc_txt): '''解析歌词''' try: return parser_lex(lrc_txt) except (lex.LrcError, NameError): logger.error(traceback.format_exc()) logger.debug('LrcParser: fallback to regexp parser') return parser_re(lrc_txt)
def do_cache_song_pool(self): def _remove_song(): try: liststore.remove(liststore[path].iter) except IndexError: logger.error(traceback.format_exc()) Gdk.Window.process_all_updates() def _on_disk_error(widget, song_path, eror=None): self.stop_caching_daemon() GLib.idle_add(Widgets.filesystem_error, self.app.window, song_path) def _on_network_error(widget, song_link, error=None): self.stop_caching_daemon() GLib.idle_add(Widgets.network_error, self.app.window, _('Failed to cache song')) def _on_chunk_received(widget, percent): GLib.idle_add(do_on_chunk_received, percent) def do_on_chunk_received(percent): self.cache_local_count += 1 self.cache_speed_label.set_text('{0} %'.format(int(percent * 100))) def _on_downloaded(widget, song_path, error=None): if song_path: GLib.idle_add(_remove_song) if self.cache_enabled: GLib.idle_add(self.do_cache_song_pool) if not self.cache_enabled: return self.cache_local_count = 0 self.cache_global_count = 0 self.cache_speed_label.set_text('0 %') list_name = 'Caching' liststore = self.tabs[list_name].liststore path = 0 if len(liststore) == 0: logger.info('Caching playlist is empty, please add some songs') self.stop_caching_daemon() Notify.init('kwplayer-cache') notify = Notify.Notification.new('Kwplayer', _('All songs in caching list have been downloaded.'), 'kwplayer') notify.show() return song = Widgets.song_row_to_dict(liststore[path], start=0) logger.debug('will download: %s' % song) self.cache_job = Net.AsyncSong(self.app) self.cache_job.connect('chunk-received', _on_chunk_received) self.cache_job.connect('downloaded', _on_downloaded) self.cache_job.connect('disk-error', _on_disk_error) self.cache_job.connect('network-error', _on_network_error) self.cache_job.get_song(song)
def get_image(url, filepath=None): if not url or len(url) < 10: logger.error('Net.get_image: url is invalid, %s' % url) return None if not filepath: filename = os.path.split(url)[1] filepath = os.path.join(Config.IMG_DIR, filename) if os.path.exists(filepath): return filepath image = urlopen(url, use_cache=False) if not image: logger.debug('Net.get_image: failed to get image, %s' % image) return None with open(filepath, 'wb') as fh: fh.write(image) return filepath
def do_cache_song_pool(self): def _remove_song(): try: liststore.remove(liststore.get_iter(path)) except IndexError: logger.error(traceback.format_exc()) Gdk.Window.process_all_updates() def _on_disk_error(widget, song_path, eror=None): def on_disk_error(): logger.warn('Playlist.on_disk_error: %s, %s' % (song_path, error)) self.stop_caching_daemon() Widgets.filesystem_error(self.app.window, song_path) GLib.idle_add(on_disk_error) def _on_network_error(widget, song_link, error=None): def on_network_error(): logger.warn('Playlist.on_network_error: %s, %s' % (song_link, error)) self.stop_caching_daemon() Widgets.network_error(self.app.window, _('Failed to cache song')) GLib.idle_add(on_network_error) def _on_chunk_received(widget, percent): def on_chunk_received(): self.cache_local_count += 1 self.cache_speed_label.set_text('{0} %'.format( int(percent * 100))) GLib.idle_add(on_chunk_received) def _on_downloaded(widget, song_path, error=None): def on_downloaded(): if song_path: _remove_song() if self.cache_enabled: self.do_cache_song_pool() GLib.idle_add(on_downloaded) if not self.cache_enabled: return self.cache_local_count = 0 self.cache_global_count = 0 self.cache_speed_label.set_text('0 %') list_name = 'Caching' liststore = self.tabs[list_name].liststore path = 0 if len(liststore) == 0: logger.info('Caching playlist is empty, please add some songs') self.stop_caching_daemon() Notify.init('kwplayer-cache') notify = Notify.Notification.new( 'Kwplayer', _('All songs in caching list have been downloaded.'), 'kwplayer') notify.show() return song = Widgets.song_row_to_dict(liststore[path], start=0) logger.debug('will download: %s' % song) self.cache_job = Net.AsyncSong(self.app) self.cache_job.connect('chunk-received', _on_chunk_received) self.cache_job.connect('downloaded', _on_downloaded) self.cache_job.connect('disk-error', _on_disk_error) self.cache_job.connect('network-error', _on_network_error) self.cache_job.get_song(song)
from kuwo.MV import MV from kuwo.OSDLrc import OSDLrc from kuwo.Player import Player from kuwo.PlayList import PlayList from kuwo.Radio import Radio from kuwo.Search import Search from kuwo.Shortcut import Shortcut from kuwo.Themes import Themes from kuwo.TopCategories import TopCategories from kuwo.TopList import TopList try: # Ubuntu Unity uses AppIndicator instead of Gtk.StatusIcon gi.require_version('AppIndicator3', '0.1') from gi.repository import AppIndicator3 as AppIndicator except ImportError: logger.debug(traceback.format_exc()) if Gtk.MAJOR_VERSION <= 3 and Gtk.MINOR_VERSION < 10: GObject.threads_init() DBUS_APP_NAME = 'org.liulang.kwplayer' class App: def __init__(self): self.app = Gtk.Application.new(DBUS_APP_NAME, 0) self.app.connect('startup', self.on_app_startup) self.app.connect('activate', self.on_app_activate) self.app.connect('shutdown', self.on_app_shutdown) def on_app_startup(self, app):
from kuwo.MV import MV from kuwo.OSDLrc import OSDLrc from kuwo.Player import Player from kuwo.PlayList import PlayList from kuwo.Radio import Radio from kuwo.Search import Search from kuwo.Shortcut import Shortcut from kuwo.Themes import Themes from kuwo.TopCategories import TopCategories from kuwo.TopList import TopList try: # Ubuntu Unity uses AppIndicator instead of Gtk.StatusIcon from gi.repository import AppIndicator3 as AppIndicator except ImportError: print("importing indicator gets wrong") logger.debug(traceback.format_exc()) if Gtk.MAJOR_VERSION <= 3 and Gtk.MINOR_VERSION < 10: GObject.threads_init() DBUS_APP_NAME = 'org.liulang.kwplayer' class App: def __init__(self): self.app = Gtk.Application.new(DBUS_APP_NAME, 0) self.app.connect('startup', self.on_app_startup) self.app.connect('activate', self.on_app_activate) self.app.connect('shutdown', self.on_app_shutdown) def on_app_startup(self, app): self.conf = Config.load_conf()
def _download_song(self, song, use_mv): cached, song_link, song_path = get_song_link(song, self.app.conf, use_mv=use_mv) # temp file to store data tmp_song_path = '{0}-{1}.part'.format(song_path, int(time.time())) # check song already cached if cached: self.emit('can-play', song_path) self.emit('downloaded', song_path) return # this song has no link to download if not song_link: logger.debug('download_song(): %s.' % song) self.emit('network-error', song_link) return if use_mv: chunk_to_play = CHUNK_MV_TO_PLAY else: chunk_to_play = CHUNK_TO_PLAY for retried in range(RETRIES): try: req = request.urlopen(song_link, timeout=TIMEOUT) received_size = 0 can_play_emited = False content_length = int(req.headers.get('Content-Length')) fh = open(tmp_song_path, 'wb') while True: if self.force_quit: if not fh.closed: fh.close() if os.path.exists(song_path): os.remove(song_path) return chunk = req.read(CHUNK) received_size += len(chunk) percent = received_size / content_length if int(percent * 100) % 5 == 0: self.emit('chunk-received', percent) # this signal only emit once. if ((received_size > chunk_to_play or percent > 0.4) and not can_play_emited): self.emit('can-play', tmp_song_path) can_play_emited = True if not chunk: break fh.write(chunk) fh.close() # download successfully if received_size == content_length: os.rename(tmp_song_path, song_path) self.emit('downloaded', song_path) Utils.iconvtag(song_path, song) return else: logger.warn('Net.received_size: %s, content_length: %s' % (received_size, content_length)) self.emit('network-error', song_link) # remove temp file if os.path.exists(tmp_song_path): os.remove(tmp_song_path) break except URLError: logger.error(traceback.format_exc()) except FileNotFoundError: logger.error(traceback.format_exc()) self.emit('disk-error', song_path) if os.path.exists(tmp_song_path): os.remove(tmp_song_path) return if os.path.exists(tmp_song_path): os.remove(tmp_song_path) self.emit('network-error', song_link)
def _on_list_received(imgs, error=None): if error or not imgs or len(imgs) < 10: logger.debug('get_recommend_lists(): %s, %s' % (imgs, error)) self.recommend_imgs = None else: self.recommend_imgs = imgs.strip().splitlines()