예제 #1
0
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;
}
예제 #2
0
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;
}