static gboolean grl_metadata_store_source_may_resolve (GrlSource *source, GrlMedia *media, GrlKeyID key_id, GList **missing_keys) { if (!(key_id == GRL_METADATA_KEY_RATING || key_id == GRL_METADATA_KEY_PLAY_COUNT || key_id == GRL_METADATA_KEY_LAST_PLAYED || key_id == GRL_METADATA_KEY_LAST_POSITION || key_id == GRL_METADATA_KEY_FAVOURITE)) return FALSE; if (media) { if (!(GRL_IS_MEDIA_VIDEO (media) || GRL_IS_MEDIA_AUDIO (media) || key_id == GRL_METADATA_KEY_FAVOURITE)) /* the keys we handle for now only make sense for audio and video, with exception of the 'favourite' key, valid as well for pictures and boxes */ return FALSE; if (grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_ID)) return TRUE; } if (missing_keys) *missing_keys = grl_metadata_key_list_new (GRL_METADATA_KEY_ID, NULL); return FALSE; }
static int get_media_type (GrlMedia *media) { if (GRL_IS_MEDIA_AUDIO (media)) { return MEDIA_AUDIO; } if (GRL_IS_MEDIA_VIDEO (media)) { return MEDIA_VIDEO; } if (GRL_IS_MEDIA_IMAGE (media)) { return MEDIA_IMAGE; } if (GRL_IS_MEDIA_BOX (media)) { return MEDIA_BOX; } return MEDIA; }
static void grilo_media_browse_cb (GrlSource *grilo_source, guint operation_id, GrlMedia *media, guint remaining, RBGriloSource *source, const GError *error) { if (operation_id != source->priv->media_browse_op) { return; } if (error != NULL) { /* do something? */ rb_debug ("got error for %s: %s", grl_source_get_name (grilo_source), error->message); return; } GDK_THREADS_ENTER (); if (media != NULL) { source->priv->media_browse_got_results = TRUE; source->priv->media_browse_position++; if (GRL_IS_MEDIA_AUDIO (media)) { RhythmDBEntry *entry; entry = create_entry_for_media (source->priv->db, source->priv->entry_type, GRL_DATA (media), GRL_DATA (source->priv->browse_container)); if (entry != NULL) { rhythmdb_query_model_add_entry (source->priv->query_model, entry, -1); } } else if (GRL_IS_MEDIA_BOX (media)) { source->priv->media_browse_got_containers = TRUE; } } if (remaining == 0) { source->priv->media_browse_op = 0; if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (source->priv->query_model), NULL) == 0 && source->priv->media_browse_position >= CONTAINER_GIVE_UP_POINT) { /* if we don't find any media within the first 100 or so results, * assume this container doesn't have any. otherwise we'd load * the entire thing when it got selected, which would suck. */ rb_debug ("didn't find any media in %s, giving up", grl_media_get_title (source->priv->media_browse_container)); gtk_tree_store_set (source->priv->browser_model, &source->priv->media_browse_container_iter, 2, CONTAINER_NO_MEDIA, -1); } else if (source->priv->media_browse_got_results) { if (source->priv->media_browse_position < source->priv->media_browse_limit) { media_browse_next (source); } else { char *text; text = g_strdup_printf (ngettext ("Only showing %d result", "Only showing %d results", source->priv->media_browse_position), source->priv->media_browse_position); gtk_label_set_text (GTK_LABEL (source->priv->info_bar_label), text); g_free (text); gtk_widget_show (source->priv->info_bar); } } else if (source->priv->media_browse_got_containers == FALSE && source->priv->media_browse_container != NULL) { /* make sure there's no marker row for this container */ delete_marker_row (source, &source->priv->media_browse_container_iter); } } GDK_THREADS_LEAVE (); }
static void grilo_browse_cb (GrlSource *grilo_source, guint operation_id, GrlMedia *media, guint remaining, RBGriloSource *source, const GError *error) { if (operation_id != source->priv->browse_op) { return; } if (error != NULL) { /* do something? */ rb_debug ("got error for %s: %s", grl_source_get_name (grilo_source), error->message); source->priv->browse_op = 0; return; } if (media != NULL) { source->priv->browse_got_results = TRUE; source->priv->browse_position++; } if (media && GRL_IS_MEDIA_BOX (media)) { GtkTreeIter new_row; if (source->priv->browse_container == NULL) { /* insert at the end */ gtk_tree_store_insert_with_values (source->priv->browser_model, &new_row, NULL, -1, 0, g_object_ref (media), 1, grl_media_get_title (media), 2, CONTAINER_UNKNOWN_MEDIA, 3, 0, -1); } else { int n; /* insert before the expand marker row */ n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (source->priv->browser_model), &source->priv->browse_container_iter); gtk_tree_store_insert_with_values (source->priv->browser_model, &new_row, &source->priv->browse_container_iter, n - 1, 0, g_object_ref (media), 1, grl_media_get_title (media), 2, CONTAINER_UNKNOWN_MEDIA, 3, 0, -1); } /* and insert an expand marker below it too */ gtk_tree_store_insert_with_values (source->priv->browser_model, NULL, &new_row, -1, 0, NULL, 1, "...", /* needs to be translatable? */ 2, CONTAINER_NO_MEDIA, 3, 0, -1); } else if (media && GRL_IS_MEDIA_AUDIO (media)) { source->priv->browse_got_media = TRUE; } if (remaining == 0) { source->priv->browse_op = 0; if (source->priv->browse_got_results == FALSE && source->priv->browse_container != NULL) { /* no more results for this container, so delete the marker row */ delete_marker_row (source, &source->priv->browse_container_iter); set_container_type (source, &source->priv->browse_container_iter, source->priv->browse_got_media); gtk_tree_store_set (source->priv->browser_model, &source->priv->browse_container_iter, 3, -1, -1); } else if (source->priv->browse_container != NULL) { if (source->priv->browse_position >= CONTAINER_GIVE_UP_POINT && gtk_tree_model_iter_n_children (GTK_TREE_MODEL (source->priv->browser_model), &source->priv->browse_container_iter) == 1) { /* no containers yet, so remove the marker row */ delete_marker_row (source, &source->priv->browse_container_iter); } else { /* store browse position for next time we want more */ gtk_tree_store_set (source->priv->browser_model, &source->priv->browse_container_iter, 3, source->priv->browse_position, -1); maybe_expand_container (source); } } else if (source->priv->browse_got_results && source->priv->browse_container == NULL) { /* get all top-level containers */ browse_next (source); } } }
static void got_file_info (GFile *file, GAsyncResult *result, gpointer user_data) { GCancellable *cancellable; GFileInfo *info; GError *error = NULL; const gchar *thumbnail_path; gboolean thumbnail_is_valid; GrlLocalMetadataSourcePriv *priv; ResolveData *resolve_data = user_data; GrlSourceResolveSpec *rs = resolve_data->rs; resolution_flags_t flags; GRL_DEBUG ("got_file_info"); priv = GRL_LOCAL_METADATA_SOURCE_GET_PRIVATE (resolve_data->source); cancellable = resolve_data_ensure_cancellable (resolve_data); info = g_file_query_info_finish (file, result, &error); if (error) goto error; thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH); #if GLIB_CHECK_VERSION (2, 39, 0) thumbnail_is_valid = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID); #else thumbnail_is_valid = TRUE; #endif if (thumbnail_path && thumbnail_is_valid) { gchar *thumbnail_uri = g_filename_to_uri (thumbnail_path, NULL, &error); if (error) goto error; GRL_INFO ("Got thumbnail %s for media: %s", thumbnail_uri, grl_media_get_url (rs->media)); grl_media_set_thumbnail (rs->media, thumbnail_uri); g_free (thumbnail_uri); } else if (thumbnail_path && !thumbnail_is_valid) { GRL_INFO ("Found outdated thumbnail %s for media: %s", thumbnail_path, grl_media_get_url (rs->media)); } else { GRL_INFO ("Could not find thumbnail for media: %s", grl_media_get_url (rs->media)); } flags = get_resolution_flags (rs->keys, priv); if (GRL_IS_MEDIA_AUDIO (rs->media) && !(thumbnail_path && thumbnail_is_valid)) { /* We couldn't get a per-track thumbnail; try for a per-album one, * using libmediaart */ resolve_album_art (resolve_data, flags); } if (flags & FLAG_GIBEST_HASH) { extract_gibest_hash_async (resolve_data, file, cancellable); } else { resolve_data_finish_operation (resolve_data, "image", NULL); } goto exit; error: { GError *new_error = g_error_new (GRL_CORE_ERROR, GRL_CORE_ERROR_RESOLVE_FAILED, _("Failed to resolve: %s"), error->message); resolve_data_finish_operation (resolve_data, "image", new_error); g_error_free (error); g_error_free (new_error); } exit: g_clear_object (&info); }
static void grl_local_metadata_source_resolve (GrlSource *source, GrlSourceResolveSpec *rs) { GError *error = NULL; resolution_flags_t flags; GrlLocalMetadataSourcePriv *priv = GRL_LOCAL_METADATA_SOURCE_GET_PRIVATE (source); gboolean can_access; ResolveData *data = NULL; GRL_DEBUG (__FUNCTION__); /* Wrap the whole resolve operation in a GTask, as there are various async * components which need to run in parallel. */ data = g_slice_new0 (ResolveData); data->source = g_object_ref (source); data->rs = rs; data->n_pending_operations = 1; /* to track the initial checks */ /* Can we access the media through gvfs? */ can_access = has_compatible_media_url (rs->media); flags = get_resolution_flags (rs->keys, priv); if (grl_data_get_boolean (GRL_DATA (rs->media), GRL_METADATA_KEY_TITLE_FROM_FILENAME)) flags |= FLAG_VIDEO_TITLE; if (!flags) error = g_error_new_literal (GRL_CORE_ERROR, GRL_CORE_ERROR_RESOLVE_FAILED, _("Cannot resolve any of the given keys")); if (GRL_IS_MEDIA_IMAGE (rs->media) && can_access == FALSE) error = g_error_new_literal (GRL_CORE_ERROR, GRL_CORE_ERROR_RESOLVE_FAILED, _("A GIO supported URL for images is required")); if (error) { /* No can do! */ resolve_data_finish_operation (data, "root", error); g_error_free (error); return; } GRL_DEBUG ("\ttrying to resolve for: %s", grl_media_get_url (rs->media)); if (GRL_IS_MEDIA_VIDEO (rs->media)) { if (priv->guess_video) resolve_video (data, can_access ? GRL_METADATA_KEY_URL : GRL_METADATA_KEY_TITLE, flags); if (can_access) resolve_image (data, flags); } else if (GRL_IS_MEDIA_IMAGE (rs->media)) { resolve_image (data, flags); } else if (GRL_IS_MEDIA_AUDIO (rs->media)) { /* Try for a per-track thumbnail first; we'll fall back to album art * if the track doesn't have one */ resolve_image (data, flags); } /* Finish the overall operation (this might not call the callback if there * are still some sub-operations pending). */ resolve_data_finish_operation (data, "root", NULL); }
static gboolean grl_local_metadata_source_may_resolve (GrlSource *source, GrlMedia *media, GrlKeyID key_id, GList **missing_keys) { GrlLocalMetadataSourcePriv *priv = GRL_LOCAL_METADATA_SOURCE_GET_PRIVATE (source); if (!media) return FALSE; if (GRL_IS_MEDIA_AUDIO (media)) { gboolean have_artist = FALSE, have_album = FALSE; if ((have_artist = grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_ARTIST)) && (have_album = grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_ALBUM)) && key_id == GRL_METADATA_KEY_THUMBNAIL) { return TRUE; } else if (missing_keys) { GList *result = NULL; if (!have_artist) result = g_list_append (result, GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ARTIST)); if (!have_album) result = g_list_append (result, GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ALBUM)); if (result) *missing_keys = result; } return FALSE; } if (GRL_IS_MEDIA_IMAGE (media)) { if (key_id != GRL_METADATA_KEY_THUMBNAIL) return FALSE; if (!grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_URL)) goto missing_url; if (!has_compatible_media_url (media)) return FALSE; return TRUE; } if (GRL_IS_MEDIA_VIDEO (media)) { switch (key_id) { case GRL_METADATA_KEY_TITLE: case GRL_METADATA_KEY_SHOW: case GRL_METADATA_KEY_PUBLICATION_DATE: case GRL_METADATA_KEY_SEASON: case GRL_METADATA_KEY_EPISODE: case GRL_METADATA_KEY_EPISODE_TITLE: if (!priv->guess_video) return FALSE; if (grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_URL) && has_compatible_media_url (media)) return TRUE; if (!grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_TITLE)) goto missing_title; return TRUE; case GRL_METADATA_KEY_THUMBNAIL: if (grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_URL) == FALSE) goto missing_url; return has_compatible_media_url (media); default: if (key_id == priv->hash_keyid) return has_compatible_media_url (media); } } missing_title: if (missing_keys) { if (grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_URL) == FALSE) *missing_keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, GRL_METADATA_KEY_URL, NULL); else *missing_keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, NULL); } return FALSE; missing_url: if (missing_keys) *missing_keys = grl_metadata_key_list_new (GRL_METADATA_KEY_URL, NULL); return FALSE; }