Commit b5e8bad3 authored by Marinus Schraal's avatar Marinus Schraal

Remove old grilo.py

parent 1189232d
# Copyright (c) 2013 Vadim Rutkovsky <vrutkovs@redhat.com>
# Copyright (c) 2013 Arnel A. Borja <kyoushuu@yahoo.com>
# Copyright (c) 2013 Seif Lotfy <seif@lotfy.com>
# Copyright (c) 2013 Guillaume Quintard <guillaume.quintard@gmail.com>
#
# GNOME Music is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# GNOME Music is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with GNOME Music; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# The GNOME Music authors hereby grant permission for non-GPL compatible
# GStreamer plugins to be used and distributed together with GStreamer
# and GNOME Music. This permission is above and beyond the permissions
# granted by the GPL license by which GNOME Music is covered. If you
# modify this code, you may extend this exception to your version of the
# code, but you are not obligated to do so. If you do not wish to do so,
# delete this exception statement from your version.
import gi
gi.require_version('Grl', '0.3')
from gi.repository import GLib, GObject
from gnomemusic.query import Query
from gnomemusic import log
from gnomemusic.trackerwrapper import TrackerWrapper
import logging
import os
os.environ['GRL_PLUGIN_RANKS'] = ("grl-local-metadata:5,"
"grl-filesystem:4,"
"grl-tracker-source:3,"
"grl-lastfm-cover:2,"
"grl-theaudiodb-cover:1")
from gi.repository import Grl
logger = logging.getLogger(__name__)
class Grilo(GObject.GObject):
__gtype_name__ = 'Grilo'
__gsignals__ = {
'ready': (GObject.SignalFlags.RUN_FIRST, None, ()),
'changes-pending': (GObject.SignalFlags.RUN_FIRST, None, ()),
'new-source-added': (GObject.SignalFlags.RUN_FIRST, None, (Grl.Source, ))
}
METADATA_KEYS = [
Grl.METADATA_KEY_ALBUM,
Grl.METADATA_KEY_ALBUM_ARTIST,
Grl.METADATA_KEY_ALBUM_DISC_NUMBER,
Grl.METADATA_KEY_ARTIST,
Grl.METADATA_KEY_CREATION_DATE,
Grl.METADATA_KEY_COMPOSER,
Grl.METADATA_KEY_DURATION,
Grl.METADATA_KEY_FAVOURITE,
Grl.METADATA_KEY_ID,
Grl.METADATA_KEY_LAST_PLAYED,
Grl.METADATA_KEY_LYRICS,
Grl.METADATA_KEY_PLAY_COUNT,
Grl.METADATA_KEY_THUMBNAIL,
Grl.METADATA_KEY_TITLE,
Grl.METADATA_KEY_TRACK_NUMBER,
Grl.METADATA_KEY_URL
]
METADATA_THUMBNAIL_KEYS = [
Grl.METADATA_KEY_ID,
Grl.METADATA_KEY_THUMBNAIL,
]
CHANGED_MEDIA_MAX_ITEMS = 500
CHANGED_MEDIA_SIGNAL_TIMEOUT = 2000
_theaudiodb_api_key = "195003"
sources = GObject.Property()
cover_sources = GObject.Property(type=bool, default=False)
tracker_available = GObject.Property(type=bool, default=False)
def __repr__(self):
return '<Grilo>'
@log
def __init__(self):
super().__init__()
self.playlist_path = GLib.build_filenamev([GLib.get_user_data_dir(),
"gnome-music", "playlists"])
if not (GLib.file_test(self.playlist_path, GLib.FileTest.IS_DIR)):
GLib.mkdir_with_parents(self.playlist_path, int("0755", 8))
Grl.init(None)
self.options = Grl.OperationOptions()
self.options.set_resolution_flags(Grl.ResolutionFlags.FAST_ONLY |
Grl.ResolutionFlags.IDLE_RELAY)
self.full_options = Grl.OperationOptions()
self.full_options.set_resolution_flags(Grl.ResolutionFlags.FULL |
Grl.ResolutionFlags.IDLE_RELAY)
self.props.sources = {}
self.blacklist = [
'grl-filesystem',
'grl-bookmarks',
'grl-metadata-store',
'grl-podcasts',
'grl-spotify-cover'
]
self.tracker = None
self.changed_media_ids = []
self.pending_event_id = 0
self.changes_pending = {'Albums': False, 'Artists': False, 'Songs': False}
self.pending_changed_medias = []
self._thumbnail_sources = []
self._thumbnail_sources_timeout = None
self.registry = Grl.Registry.get_default()
self._tracker_wrapper = TrackerWrapper()
self.tracker_sparql = self._tracker_wrapper.props.tracker
self._tracker_wrapper.bind_property(
"tracker-available", self, "tracker-available",
GObject.BindingFlags.BIDIRECTIONAL |
GObject.BindingFlags.SYNC_CREATE)
self._find_sources()
@log
def _find_sources(self):
config = Grl.Config.new('grl-lua-factory', 'grl-theaudiodb-cover')
config.set_api_key(self._theaudiodb_api_key)
self.registry.add_config(config)
self.registry.connect('source_added', self._on_source_added)
self.registry.connect('source_removed', self._on_source_removed)
try:
self.registry.load_all_plugins(True)
except GLib.GError:
logger.error('Failed to load plugins.')
if self.tracker is not None:
logger.debug("tracker found")
@log
def _rate_limited_content_changed(self, mediaSource, changedMedias, changeType, locationUnknown):
[self.pending_changed_medias.append(media) for media in changedMedias]
if self.content_changed_timeout is None:
self.content_changed_timeout = GLib.timeout_add(
500, self._on_content_changed, mediaSource, self.pending_changed_medias, changeType, locationUnknown)
@log
def _on_content_changed(self, mediaSource, changedMedias, changeType, locationUnknown):
try:
with self.tracker.handler_block(self.notification_handler):
for media in changedMedias:
media_id = media.get_id()
if (changeType == Grl.SourceChangeType.ADDED
and media.is_audio()):
self.changed_media_ids.append(media_id)
if changeType == Grl.SourceChangeType.REMOVED:
# There is no way to check that removed item is a media
# so always do the refresh
# todo: remove one single url
try:
self.changed_media_ids.append(media.get_id())
except Exception:
logger.warning("Skipping {}".format(media))
if self.changed_media_ids == []:
self.pending_changed_medias = []
if self.content_changed_timeout is not None:
GLib.source_remove(self.content_changed_timeout)
self.content_changed_timeout = None
return False
self.changed_media_ids = list(set(self.changed_media_ids))
logger.debug("Changed medias: %s", self.changed_media_ids)
if len(self.changed_media_ids) >= self.CHANGED_MEDIA_MAX_ITEMS:
self.emit_change_signal()
elif self.changed_media_ids != []:
if self.pending_event_id > 0:
GLib.Source.remove(self.pending_event_id)
self.pending_event_id = 0
self.pending_event_id = GLib.timeout_add(self.CHANGED_MEDIA_SIGNAL_TIMEOUT, self.emit_change_signal)
except Exception as error:
logger.warning(
"Exception in _on_content_changed: {}".format(error))
finally:
self.pending_changed_medias = []
if self.content_changed_timeout is not None:
GLib.source_remove(self.content_changed_timeout)
self.content_changed_timeout = None
return False
@log
def emit_change_signal(self):
self.changed_media_ids = []
self.pending_event_id = 0
self.changes_pending['Albums'] = True
self.changes_pending['Artists'] = True
self.changes_pending['Songs'] = True
self.emit('changes-pending')
return False
@log
def _trigger_art_update(self):
self._thumbnail_sources_timeout = None
if len(self._thumbnail_sources) > 0:
self.props.cover_sources = True
return GLib.SOURCE_REMOVE
@log
def _on_source_added(self, pluginRegistry, mediaSource):
if ("net:plaintext" in mediaSource.get_tags()
or mediaSource.get_id() in self.blacklist):
try:
pluginRegistry.unregister_source(mediaSource)
except GLib.GError:
logger.error(
"Failed to unregister {}".format(mediaSource.get_id()))
return
if Grl.METADATA_KEY_THUMBNAIL in mediaSource.supported_keys():
self._thumbnail_sources.append(mediaSource)
if not self._thumbnail_sources_timeout:
# Aggregate sources being added, for example when the
# network comes online.
self._thumbnail_sources_timeout = GLib.timeout_add_seconds(
5, self._trigger_art_update)
id = mediaSource.get_id()
logger.debug("new grilo source %s was added", id)
try:
ops = mediaSource.supported_operations()
if id == 'grl-tracker-source':
if ops & Grl.SupportedOps.SEARCH:
logger.debug("found searchable tracker source")
self.props.sources[id] = mediaSource
self.tracker = mediaSource
self.search_source = mediaSource
if self.tracker is not None:
self.emit('ready')
self.tracker.notify_change_start()
self.content_changed_timeout = None
self.notification_handler = self.tracker.connect(
'content-changed', self._rate_limited_content_changed)
elif (id.startswith('grl-upnp')):
logger.debug("found upnp source %s", id)
self.props.sources[id] = mediaSource
self.emit('new-source-added', mediaSource)
elif (ops & Grl.SupportedOps.SEARCH
and mediaSource.get_supported_media() & Grl.MediaType.AUDIO):
logger.debug("source %s is searchable", id)
self.props.sources[id] = mediaSource
self.emit('new-source-added', mediaSource)
except Exception as e:
logger.debug("Source {}: exception {}".format(id, e))
@log
def _on_source_removed(self, pluginRegistry, mediaSource):
pass
@log
def populate_user_playlists(self, offset, callback, count=-1):
"""Asynchronously get user playlists
:param int offset: start index
:param function callback: callback function
:param int count: limit number of results
"""
self.populate_items(
Query.all_user_playlists(), offset, callback, count)
@log
def populate_playlist_songs(self, playlist, callback, count=-1):
self.populate_items(
Query.playlist_songs(playlist.props.pl_id), 0, callback, count)
@log
def populate_items(self, query, offset, callback, count=-1, data=None):
options = self.options.copy()
options.set_skip(offset)
if count != -1:
options.set_count(count)
def _callback(source, param, item, remaining, data, error):
if error:
logger.warning(
"Error {}: {}".format(error.domain, error.message))
callback(source, param, item, remaining, data)
self.tracker.query(query, self.METADATA_KEYS, options, _callback, data)
@log
def get_album_art_for_item(self, item, callback):
# Tracker not (yet) loaded.
if self.search_source is None:
return
item_id = item.get_id()
if item.is_audio():
query = Query.get_album_for_song_id(item_id)
else:
query = Query.get_album_for_album_id(item_id)
options = self.full_options.copy()
options.set_count(1)
self.search_source.query(query, self.METADATA_THUMBNAIL_KEYS, options,
callback)
@log
def get_playlist_with_id(self, playlist_id, callback):
options = self.options.copy()
query = Query.get_playlist_with_id(playlist_id)
self.tracker.query(query, self.METADATA_KEYS, options, callback, None)
@log
def get_playlist_song_with_id(self, playlist_id, entry_id, callback):
options = self.options.copy()
query = Query.get_playlist_song_with_id(playlist_id, entry_id)
self.tracker.query(query, self.METADATA_KEYS, options, callback, None)
@log
def songs_available(self, callback):
"""Checks if there are any songs available
Calls a callback function with True or False depending on the
availability of songs.
:param callback: Function to call on result
"""
def cursor_next_cb(conn, res, data):
try:
has_next = conn.next_finish(res)
except GLib.Error as err:
logger.warning("Error: {}, {}".format(err.__class__, err))
callback(False)
return
if has_next:
count = conn.get_integer(0)
if count > 0:
callback(True)
return
callback(False)
def songs_query_cb(conn, res, data):
try:
cursor = conn.query_finish(res)
except GLib.Error as err:
logger.warning("Error: {}, {}".format(err.__class__, err))
self.props.tracker_available = False
callback(False)
return
cursor.next_async(None, cursor_next_cb, None)
# TODO: currently just checks tracker, should work with any
# queryable supported Grilo source.
if not self.props.tracker_available:
callback(False)
return
self.tracker_sparql.query_async(
Query.all_songs_count(), None, songs_query_cb, None)
grilo = Grilo()
......@@ -18,7 +18,6 @@ gnomemusic/__init__.py
gnomemusic/albumartcache.py
gnomemusic/application.py
gnomemusic/grilowrappers/grltrackerplaylist.py
gnomemusic/grilo.py
gnomemusic/gstplayer.py
gnomemusic/inhibitsuspend.py
gnomemusic/mpris.py
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment