summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan A. Suarez Romero <jasuarez@igalia.com>2011-04-20 14:29:26 +0000
committerJuan A. Suarez Romero <jasuarez@igalia.com>2011-04-20 14:29:26 +0000
commit81327d239073f63932ce0062a560b613f68fbd81 (patch)
tree1b2cd3327b31ad37f5104957f471596968560092
parent498270332e2d3910417decadfc4672c8ad06bf79 (diff)
parent5afd4c310714222786a620a160fe05ba97f166a7 (diff)
Merge commit 'grilo-0.1.15' into rpm
-rw-r--r--NEWS11
-rw-r--r--configure.ac2
-rw-r--r--doc/grilo/grilo-docs.sgml7
-rw-r--r--doc/grilo/grilo-sections.txt143
-rw-r--r--doc/grilo/grilo.types1
-rw-r--r--doc/grilo/quick-start-using-grilo.xml307
-rw-r--r--doc/libs/grilo-libs-sections.txt2
-rw-r--r--src/data/grl-media.c4
-rw-r--r--src/grl-media-source.c31
-rw-r--r--src/grl-plugin-registry.c6
-rw-r--r--tools/grilo-inspect/grl-inspect.c32
-rw-r--r--tools/grilo-test-ui/main.c2
12 files changed, 520 insertions, 28 deletions
diff --git a/NEWS b/NEWS
index ed225e5..3654f02 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+NEW in 0.1.15
+=============
+
+ * Several fixes
+ * Updated documentation
+ * Updated grl-inspect tool
+
+ * Contributors to this release:
+ Juan A. Suarez Romero <jasuarez@igalia.com>
+
+
NEW in 0.1.14
=============
diff --git a/configure.ac b/configure.ac
index 690bd6f..b9071d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9,7 +9,7 @@ m4_define([prj_name], [grilo])
m4_define([prj_gir_name], [Grilo])
m4_define([grl_major_version], [0])
m4_define([grl_minor_version], [1])
-m4_define([grl_micro_version], [14])
+m4_define([grl_micro_version], [15])
m4_define([prj_version], grl_major_version.grl_minor_version.grl_micro_version)
AC_INIT([prj_name], [prj_version])
diff --git a/doc/grilo/grilo-docs.sgml b/doc/grilo/grilo-docs.sgml
index b1d6b7e..332e1e3 100644
--- a/doc/grilo/grilo-docs.sgml
+++ b/doc/grilo/grilo-docs.sgml
@@ -55,10 +55,15 @@
<xi:include href="xml/grl-multiple.xml"/>
</chapter>
+ <chapter id="configure">
+ <title>Configuring plug-ins</title>
+ <xi:include href="xml/grl-config.xml"/>
+ </chapter>
+
<chapter id="data">
<title>Media data</title>
<xi:include href="xml/grl-data.xml"/>
- <xi:include href="xml/grl-config.xml"/>
+ <xi:include href="xml/grl-related-keys.xml"/>
<xi:include href="xml/grl-media.xml"/>
<xi:include href="xml/grl-media-box.xml"/>
<xi:include href="xml/grl-media-video.xml"/>
diff --git a/doc/grilo/grilo-sections.txt b/doc/grilo/grilo-sections.txt
index 32675ae..8f7c08a 100644
--- a/doc/grilo/grilo-sections.txt
+++ b/doc/grilo/grilo-sections.txt
@@ -45,10 +45,14 @@ grl_metadata_source_filter_slow
grl_metadata_source_filter_writable
grl_metadata_source_key_depends
grl_metadata_source_writable_keys
+grl_metadata_source_may_resolve
grl_metadata_source_resolve
grl_metadata_source_resolve_sync
+grl_metadata_source_set_operation_data
+grl_metadata_source_get_opearation_data
grl_metadata_source_set_metadata
grl_metadata_source_set_metadata_sync
+grl_metadata_source_cancel
grl_metadata_source_get_id
grl_metadata_source_get_name
grl_metadata_source_get_description
@@ -100,6 +104,7 @@ GrlMediaPluginPrivate
<SECTION>
<FILE>grl-media-source</FILE>
<TITLE>GrlMediaSource</TITLE>
+GrlMediaSourceChangeType
GrlMediaSource
GrlMediaSourceResultCb
GrlMediaSourceMetadataCb
@@ -132,6 +137,11 @@ grl_media_source_set_auto_split_threshold
grl_media_source_get_auto_split_threshold
grl_media_source_test_media_from_uri
grl_media_source_get_media_from_uri
+grl_media_source_get_media_from_uri_sync
+grl_media_source_notify_change_start
+grl_media_source_notify_change_stop
+grl_media_source_notify_change_list
+grl_media_source_notify_change
<SUBSECTION Standard>
GRL_MEDIA_SOURCE
GRL_IS_MEDIA_SOURCE
@@ -161,13 +171,16 @@ grl_plugin_registry_load
grl_plugin_registry_load_directory
grl_plugin_registry_unload
grl_plugin_registry_load_all
+grl_plugin_registry_load_by_id
grl_plugin_registry_register_source
grl_plugin_registry_unregister_source
grl_plugin_registry_lookup_source
grl_plugin_registry_get_sources
grl_plugin_registry_get_sources_by_operations
grl_plugin_registry_register_metadata_key
+grl_plugin_registry_register_metadata_key_relation
grl_plugin_registry_lookup_metadata_key
+grl_plugin_registry_lookup_metadata_key_relation
grl_plugin_registry_get_metadata_keys
grl_plugin_registry_add_config
grl_plugin_registry_add_config_from_file
@@ -189,27 +202,40 @@ GrlPluginRegistryPrivate
GRL_CONFIG_KEY_PLUGIN
GRL_CONFIG_KEY_SOURCE
GRL_CONFIG_KEY_APIKEY
+GRL_CONFIG_KEY_APIKEY_BLOB
GRL_CONFIG_KEY_APITOKEN
GRL_CONFIG_KEY_APISECRET
+GRL_CONFIG_KEY_USERNAME
+GRL_CONFIG_KEY_PASSWORD
GrlConfigClass
grl_config_set_plugin
grl_config_set_source
grl_config_set_api_key
+grl_config_set_api_key_blob
grl_config_set_api_token
grl_config_set_api_secret
+grl_config_set_username
+grl_config_set_password
grl_config_get_plugin
grl_config_get_api_key
+grl_config_get_api_key_blob
grl_config_get_api_token
grl_config_get_api_secret
+grl_config_get_username
+grl_config_get_password
grl_config_new
grl_config_set
grl_config_set_string
grl_config_set_int
grl_config_set_float
-grl_config_get
+grl_config_set_boolean
+grl_config_set_binary
grl_config_get_string
grl_config_get_int
grl_config_get_float
+grl_config_get_boolean
+grl_config_get_binary
+grl_config_has_param
<SUBSECTION Standard>
GRL_CONFIG
GRL_IS_CONFIG
@@ -234,9 +260,11 @@ grl_media_set_title
grl_media_set_description
grl_media_set_source
grl_media_set_thumbnail
+grl_media_set_thumbnail_binary
grl_media_set_site
grl_media_set_duration
grl_media_set_date
+grl_media_set_creation_date
grl_media_set_mime
grl_media_set_play_count
grl_media_set_last_played
@@ -247,23 +275,39 @@ grl_media_set_studio
grl_media_set_certificate
grl_media_set_license
grl_media_set_rating
+grl_media_set_url_data
+grl_media_add_url_data
+grl_media_add_author
+grl_media_add_thumbnail
+grl_media_add_thumbnail_binary
+grl_media_add_external_player
+grl_media_add_external_url
grl_media_get_id
grl_media_get_url
+grl_media_get_url_data
+grl_media_get_url_data_nth
grl_media_get_author
+grl_media_get_author_nth
grl_media_get_title
grl_media_get_description
grl_media_get_source
grl_media_get_thumbnail
+grl_media_get_thumbnail_nth
+grl_media_get_thumbnail_binary
+grl_media_get_thumbnail_binary_nth
grl_media_get_site
grl_media_get_duration
grl_media_get_date
+grl_media_get_creation_date
grl_media_get_mime
grl_media_get_rating
grl_media_get_play_count
grl_media_get_last_position
grl_media_get_last_played
grl_media_get_player
+grl_media_get_player_nth
grl_media_get_external_url
+grl_media_get_external_url_nth
grl_media_get_studio
grl_media_get_certificate
grl_media_get_license
@@ -290,15 +334,31 @@ grl_data_set
grl_data_set_string
grl_data_set_int
grl_data_set_float
+grl_data_set_binary
grl_data_get
grl_data_get_string
grl_data_get_int
grl_data_get_float
+grl_data_get_binary
grl_data_add
grl_data_remove
grl_data_has_key
grl_data_get_keys
grl_data_key_is_known
+grl_data_add_related_keys
+grl_data_add_string
+grl_data_add_int
+grl_data_add_float
+grl_data_add_binary
+grl_data_length
+grl_data_get_related_keys
+grl_data_get_all_single_related_keys
+grl_data_get-single_values_for_key
+grl_data_get_all_single_related_keys_string
+grl_data_get_single_value_for_key_string
+grl_data_remove_nth
+grl_data_set_related_keys
+grl_data_dup
grl_data_set_overwrite
grl_data_get_overwrite
<SUBSECTION Standard>
@@ -361,11 +421,21 @@ grl_media_audio_set_album
grl_media_audio_set_genre
grl_media_audio_set_lyrics
grl_media_audio_set_bitrate
+grl_media_audio_set_url_data
+grl_media_audio_add_artist
+grl_media_audio_add_genre
+grl_media_audio_add_lyrics
+grl_media_audio_add_url_data
grl_media_audio_get_artist
+grl_media_audio_get_artist_nth
grl_media_audio_get_album
grl_media_audio_get_genre
+grl_media_audio_get_genre_nth
grl_media_audio_get_lyrics
+grl_media_audio_get_lyrics_nth
grl_media_audio_get_bitrate
+grl_media_audio_get_url_data
+grl_media_audio_get_url_data_nth
grl_media_audio_new
<SUBSECTION Standard>
GRL_MEDIA_AUDIO
@@ -385,8 +455,22 @@ grl_media_image_set_width
grl_media_image_set_height
grl_media_image_get_width
grl_media_image_get_height
-grl_media_image_new
+grl_media_image_get_camera_model
+grl_media_image_get_flash_used
+grl_media_image_get_exposure_time
+grl_media_image_get_iso_speed
+grl_media_image_get_orientation
grl_media_image_set_size
+grl_media_image_get_url_data
+grl_media_image_get_url_data_nth
+grl_media_image_set_url_data
+grl_media_image_add_url_data
+grl_media_image_set_camera_model
+grl_media_image_set_flash_used
+grl_media_image_set_exposure_time
+grl_media_image_set_iso_speed
+grl_media_image_set_orientation
+grl_media_image_new
<SUBSECTION Standard>
GRL_MEDIA_IMAGE
GRL_IS_MEDIA_IMAGE
@@ -398,13 +482,46 @@ GRL_MEDIA_IMAGE_GET_CLASS
</SECTION>
<SECTION>
+<FILE>grl-related-keys</FILE>
+<TITLE>GrlRelatedKeys</TITLE>
+GrlRelatedKeysClass
+grl_related_keys_new
+grl_related_keys_new_valist
+grl_related_keys_new_with_keys
+grl_related_keys_set
+grl_related_keys_set_string
+grl_related_keys_set_int
+grl_related_keys_set_float
+grl_related_keys_set_binary
+grl_related_keys_get
+grl_related_keys_get_string
+grl_related_keys_get_int
+grl_related_keys_get_float
+grl_related_keys_get_binary
+grl_related_keys_add
+grl_related_keys_has_key
+grl_related_keys_get_keys
+grl_related_keys_key_is_known
+grl_related_keys_dup
+<SUBSECTION Standard>
+GRL_RELATED_KEYS
+GRL_IS_RELATED_KEYS
+GRL_TYPE_RELATED_KEYS
+grl_related_keys_get_type
+GRL_RELATED_KEYS_CLASS
+GRL_IS_RELATED_KEYS_CLASS
+GRL_RELATED_KEYS_GET_CLASS
+<SUBSECTION Private>
+GrlRelatedKeysPrivate
+</SECTION>
+
+<SECTION>
<FILE>grl-metadata-key</FILE>
<TITLE>GrlMetadataKey<TITLE>
GRL_METADATA_KEY_GET_ID
GRL_METADATA_KEY_GET_NAME
GRL_METADATA_KEY_GET_DESC
GRL_METADATA_KEY_GET_TYPE
-GRL_METADATA_KEY_CHILDCOUNT_UNKNOWN
GRL_KEYID_FORMAT
grl_metadata_key_list_new
GrlKeyID
@@ -434,14 +551,34 @@ GRL_METADATA_KEY_SITE
GRL_METADATA_KEY_SOURCE
GRL_METADATA_KEY_STUDIO
GRL_METADATA_KEY_THUMBNAIL
+GRL_METADATA_KEY_THUMBNAIL_BINARY
GRL_METADATA_KEY_TITLE
GRL_METADATA_KEY_URL
GRL_METADATA_KEY_WIDTH
+GRL_METADATA_KEY_SEASON
+GRL_METADATA_KEY_EPISODE
+GRL_METADATA_KEY_SHOW
+GRL_METADATA_KEY_CREATION_DATE
+GRL_METADATA_KEY_CAMERA_MODEL
+GRL_METADATA_KEY_ORIENTATION
+GRL_METADATA_KEY_KEY_FLASH_USED
+GRL_METADATA_KEY_EXPOSURE_TIME
+GRL_METADATA_KEY_ISO_SPEED
grl_metadata_key_get_name
grl_metadata_key_get_desc
</SECTION>
<SECTION>
+<FILE>grl-definitions</FILE>
+<TITLE>Definitions</TITLE>
+GRL_METADATA_KEY_CHILDCOUNT_UNKNOWN
+GRL_SOURCE_REMAINING_UNKNOWN
+<SUBSECTION Private>
+GRL_PADDING
+GRL_PADDING_SMALL
+</SECTION>
+
+<SECTION>
<FILE>grl-util</FILE>
grl_paging_translate
grl_list_from_va
diff --git a/doc/grilo/grilo.types b/doc/grilo/grilo.types
index 1a4886d..edb02d6 100644
--- a/doc/grilo/grilo.types
+++ b/doc/grilo/grilo.types
@@ -10,6 +10,7 @@
grl_data_get_type
grl_config_get_type
+grl_related_keys_get_type
grl_media_get_type
grl_media_box_get_type
grl_media_audio_get_type
diff --git a/doc/grilo/quick-start-using-grilo.xml b/doc/grilo/quick-start-using-grilo.xml
index 4984edc..81a36c2 100644
--- a/doc/grilo/quick-start-using-grilo.xml
+++ b/doc/grilo/quick-start-using-grilo.xml
@@ -80,6 +80,7 @@ static void
load_plugins (void)
{
GrlPluginRegistry *registry;
+ GError *error = NULL;
registry = grl_plugin_registry_get_default ();
@@ -94,8 +95,8 @@ load_plugins (void)
The registry will look for plugins in the default
plugin path and directories specified using the
GRL_PLUGIN_PATH environment variable */
- if (!grl_plugin_registry_load_all (registry)) {
- g_error ("Failed to load plugins.");
+ if (!grl_plugin_registry_load_all (registry, &error)) {
+ g_error ("Failed to load plugins: %s", error->message);
}
}
@@ -118,6 +119,121 @@ main (int argc, gchar *argv[])
</programlisting>
</section>
+ <section id="programming-with-grilo-configuring-plugins">
+ <title>Programming with Grilo: Configuring plugins</title>
+ <para>Some plugins, in order to work properly, require that user (or
+ application developer) set up some options with the right values. Thus,
+ some plugins would require an username and a password, while others would
+ require an API token in order to access the webservice backend.
+ </para>
+ <para>
+ While some of these options are almost compulsory (without them plugin
+ will not work), other options are more optional, and allowing users to
+ tweak how a plugin (and related sources) work.
+ </para>
+ <para>
+ An example of this is the Youtube plugin: in order to use it, an API key
+ must be provided. It is responsibility of user (or application developer)
+ to get that value (usually registering in Youtube service and applying
+ for an application key) and provide it to plugin.
+ </para>
+ <para>
+ Currently Grilo provides a set of pre-defined configuration keys that
+ developer can use to configure a plugin. The supported ones for each
+ plugin depends on the plugin itself; user must check plugin documentation
+ to know what options are required, and what options are optional.
+ </para>
+ <para>
+ Here is a small program illustrating how you can configure a plugin:
+ </para>
+ <programlisting role="C">
+<![CDATA[
+#include <grilo.h>
+
+#define GRL_LOG_DOMAIN_DEFAULT example_log_domain
+GRL_LOG_DOMAIN_STATIC(example_log_domain);
+
+static void
+source_added_cb (GrlPluginRegistry *registry, gpointer user_data)
+{
+ g_debug ("Detected new source available: '%s'",
+ grl_metadata_source_get_name (GRL_METADATA_SOURCE (user_data)));
+
+ /* Usually you may add the new service to the user interface so the user
+ can interact with it (browse, search, etc) */
+}
+
+static void
+source_removed_cb (GrlPluginRegistry *registry, gpointer user_data)
+{
+ g_debug ("Source '%s' is gone",
+ grl_metadata_source_get_name (GRL_METADATA_SOURCE (user_data)));
+
+ /* Usually you would inform the user that this service is no longer
+ available (for example a UPnP server was shutdown) and remove it
+ from the user interface. */
+}
+
+static void
+load_plugins (void)
+{
+ GrlPluginRegistry *registry;
+ GError *error = NULL;
+
+ registry = grl_plugin_registry_get_default ();
+
+ /* These callback will be invoked when media providers
+ are loaded/unloaded */
+ g_signal_connect (registry, "source-added",
+ G_CALLBACK (source_added_cb), NULL);
+ g_signal_connect (registry, "source-removed",
+ G_CALLBACK (source_removed_cb), NULL);
+
+ /* Command the registry to load all available plugins.
+ The registry will look for plugins in the default
+ plugin path and directories specified using the
+ GRL_PLUGIN_PATH environment variable */
+ if (!grl_plugin_registry_load_all (registry, &error)) {
+ g_error ("Failed to load plugins: %s", error->message);
+ }
+}
+
+static void
+configure_plugins (void)
+{
+ GrlConfig *config;
+ GrlPluginRegistry *registry;
+
+ /* Let's configure only the Youtube plugin. This plugin just requires an API
+ key */
+ config = grl_config_new ("grl-youtube", NULL);
+ grl_config_set_api_key (config,
+ "AI39si4EfscPllSfUy1IwexMf__kntTL_G5dfSr2iUEVN45RHG"
+ "q92Aq0lX25OlnOkG6KTN-4soVAkAf67fWYXuHfVADZYr7S1A");
+ registry = grl_plugin_registry_get_default ();
+ grl_plugin_registry_add_config (registry, config, NULL);
+}
+
+gint
+main (int argc, gchar *argv[])
+{
+ GMainLoop *loop;
+
+ grl_init (&argc, &argv);
+ GRL_LOG_DOMAIN_INIT (example_log_domain, "example");
+ configure_plugins (); /* Configure plugins */
+ load_plugins (); /* Load Grilo plugins */
+
+ /* Run the main loop */
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+
+ return 0;
+}
+]]>
+ </programlisting>
+ </section>
+
<section id="programming-with-grilo-browsing">
<title>Programming with Grilo: Browsing content</title>
<para>Here is a small program illustrating how you can browse
@@ -229,12 +345,13 @@ static void
load_plugins (void)
{
GrlPluginRegistry *registry;
+ GError *error = NULL;
registry = grl_plugin_registry_get_default ();
g_signal_connect (registry, "source-added",
G_CALLBACK (source_added_cb), NULL);
- if (!grl_plugin_registry_load_all (registry)) {
- g_error ("Failed to load plugins.");
+ if (!grl_plugin_registry_load_all (registry, &error)) {
+ g_error ("Failed to load plugins: %s", error->message);
}
}
@@ -338,12 +455,13 @@ static void
load_plugins (void)
{
GrlPluginRegistry *registry;
+ GError *error = NULL;
registry = grl_plugin_registry_get_default ();
g_signal_connect (registry, "source-added",
G_CALLBACK (source_added_cb), NULL);
- if (!grl_plugin_registry_load_all (registry)) {
- g_error ("Failed to load plugins.");
+ if (!grl_plugin_registry_load_all (registry, &error)) {
+ g_error ("Failed to load plugins: %s", error->message);
}
}
@@ -362,6 +480,176 @@ main (int argc, gchar *argv[])
</programlisting>
</section>
+ <section id="programming-with-grilo-multivalued-data">
+ <title>Programming with Grilo: Multi-valued data</title>
+ <para>When working with multimedia content, it can happen that a multimedia
+ element contains several values for one or more keys. Thus, it is quite
+ common having an image with several URLs, each of them providing the image
+ from several places, or moreover, providing the same image with several
+ resolutions.
+ </para>
+ <para>
+ Grilo is able to handle this kind of multimedia content. By default, Grilo
+ handles multi-valued elements in a straight way: developer can add multiple
+ values to a specific key, and retrieve them.
+ </para>
+ <para>
+ An important issue when dealing with multi-valued keys is that there are
+ keys that have values related among them. An example of this is an image
+ providing several URLs, each of them with a different resolution: for each
+ URL, there would be a specific value for WIDTH and HEIGHT. Thus, URL,
+ WIDTH and HEIGHT are multi-valued keys, and those keys are related among
+ them: a specific WIDTH value matches with a specific HEIGHT and URL
+ values. We say those keys are related.
+ </para>
+ <para>
+ The basic idea of related keys is that user sets and gets those keys
+ together. Of course, Grilo still provides API to get one of the values
+ forgetting about the related ones. But the right way is to handling them
+ as a group.
+ </para>
+ <para>
+ In case of pre-defined keys, Grilo already provides high level API to
+ handle several related keys as a group. Thus, in the image example above,
+ there is grl_media_image_add_url_data() and
+ grl_media_image_get_url_data_nth() to add and retrieve the URL values, as
+ well as related values (MIME, WIDTH and HEIGHT).
+ </para>
+ <para>
+ In the case of keys defined by plugins, after registering the keys,
+ plugins must also register which keys are related with. To deal with
+ related keys and values, developers can use GrlRelatedKeys: a placeholder
+ where related keys and their values are stored. Thus, developer would
+ create a GrlRelatedKeys, adds inside the related keys and its values (in
+ the case of image, the URL, WIDTH and HEIGHT), and then add this
+ GrlRelatedKeys in the GrlData.
+ </para>
+ <para>
+ Here is a small program illustrating how to show all URLs from a video, as
+ well the associated MIME value. We use GrlRelatedKeys instead of
+ high-level API from GrlMediaVideo to illustrate how to use them:
+ </para>
+ <programlisting role="C">
+<![CDATA[
+#include <grilo.h>
+#include <string.h>
+
+#define GRL_LOG_DOMAIN_DEFAULT example_log_domain
+GRL_LOG_DOMAIN_STATIC(example_log_domain);
+
+static void
+search_cb (GrlMediaSource *source,
+ guint browse_id,
+ GrlMedia *media,
+ guint remaining,
+ gpointer user_data,
+ const GError *error)
+{
+ guint i;
+ GrlRelatedKeys *url_related;
+
+ if (error) {
+ g_error ("Search operation failed. Reason: %s", error->message);
+ }
+
+ if (media) {
+ for (i = 0; i < grl_data_length (GRL_DATA (media), GRL_METADATA_KEY_URL); i++) {
+ url_related = grl_data_get_related_keys (GRL_DATA (media), GRL_METADATA_KEY_URL, i);
+ /* Print keys and values */
+ g_debug ("\t [%s] Got url '%s' and mime-type '%s'",
+ grl_media_get_id (media),
+ grl_related_keys_get_string (url_related, GRL_METADATA_KEY_URL),
+ grl_related_keys_get_string (url_related, GRL_METADATA_KEY_MIME));
+ }
+ }
+
+ if (remaining == 0) {
+ g_debug ("Search operation finished!");
+ }
+
+ g_object_unref (media);
+}
+
+static void
+source_added_cb (GrlPluginRegistry *registry, gpointer user_data)
+{
+ const gchar *id;
+ GrlMetadataSource *source = GRL_METADATA_SOURCE (user_data);
+ GList * keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE,
+ GRL_METADATA_KEY_URL,
+ GRL_METADATA_KEY_MIME
+ NULL);
+
+ /* Not interested if not searchable */
+ if (!(grl_metadata_source_supported_operations (source) & GRL_OP_SEARCH))
+ return;
+
+ g_debug ("Detected new searchable source available: '%s'",
+ grl_metadata_source_get_name (source));
+
+ /* Only interested in Youtube */
+ id = grl_metadata_source_get_id (source);
+ if (strcmp (id, "grl-youtube"))
+ return;
+
+ g_debug ("Searching \"rock\" in Youtube");
+ grl_media_source_search (GRL_MEDIA_SOURCE (source),
+ "rock",
+ keys,
+ 0, 5,
+ GRL_RESOLVE_IDLE_RELAY,
+ search_cb,
+ NULL);
+
+ g_list_free (keys);
+}
+
+static void
+load_plugins (void)
+{
+ GrlPluginRegistry *registry;
+ GError *error = NULL;
+
+ registry = grl_plugin_registry_get_default ();
+ g_signal_connect (registry, "source-added",
+ G_CALLBACK (source_added_cb), NULL);
+ if (!grl_plugin_registry_load_all (registry, &error)) {
+ g_error ("Failed to load plugins: %s", error->message);
+ }
+}
+
+static void
+configure_plugins (void)
+{
+ GrlConfig *config;
+ GrlPluginRegistry *registry;
+
+ /* Let's configure only the Youtube plugin. This plugin just requires an API
+ key */
+ config = grl_config_new ("grl-youtube", NULL);
+ grl_config_set_api_key (config,
+ "AI39si4EfscPllSfUy1IwexMf__kntTL_G5dfSr2iUEVN45RHG"
+ "q92Aq0lX25OlnOkG6KTN-4soVAkAf67fWYXuHfVADZYr7S1A");
+ registry = grl_plugin_registry_get_default ();
+ grl_plugin_registry_add_config (registry, config, NULL);
+}
+
+gint
+main (int argc, gchar *argv[])
+{
+ GMainLoop *loop;
+ grl_init (&argc, &argv);
+ GRL_LOG_DOMAIN_INIT (example_log_domain, "example");
+ configure_plugins ();
+ load_plugins ();
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+ return 0;
+}
+]]>
+ </programlisting>
+ </section>
+
<section id="programming-with-grilo-efficient-metadata-resolution">
<title>Programming with Grilo: Efficient metadata resolution</title>
<para>When executing operations that return lists of media items (like
@@ -457,6 +745,7 @@ const gchar *target_source_id = NULL;
static void
metadata_cb (GrlMediaSource *source,
+ guint metadata_id,
GrlMedia *media,
gpointer user_data,
const GError *error)
@@ -541,11 +830,13 @@ static void
load_plugins (void)
{
GrlPluginRegistry *registry;
+ GError *error = NULL;
+
registry = grl_plugin_registry_get_default ();
g_signal_connect (registry, "source-added",
G_CALLBACK (source_added_cb), NULL);
- if (!grl_plugin_registry_load_all (registry)) {
- g_error ("Failed to load plugins.");
+ if (!grl_plugin_registry_load_all (registry, &error)) {
+ g_error ("Failed to load plugins: %s", error->message);
}
}
diff --git a/doc/libs/grilo-libs-sections.txt b/doc/libs/grilo-libs-sections.txt
index 03ca2ff..f1605d4 100644
--- a/doc/libs/grilo-libs-sections.txt
+++ b/doc/libs/grilo-libs-sections.txt
@@ -9,6 +9,8 @@ grl_net_wc_request_async
grl_net_wc_request_finish
grl_net_wc_set_log_level
grl_net_wc_set_throttling
+grl_net_wc_set_cache
+grl_net_wc_set_cache_size
grl_net_wc_flush_delayed_requests
<SUBSECTION Standard>
GRL_NET_WC
diff --git a/src/data/grl-media.c b/src/data/grl-media.c
index 80380ee..d467920 100644
--- a/src/data/grl-media.c
+++ b/src/data/grl-media.c
@@ -688,7 +688,7 @@ grl_media_set_date (GrlMedia *media, const gchar *date)
/**
* grl_media_set_creation_date:
- * @image: the media
+ * @media: the media
* @creation_date: date when media was created
*
* Set the creation_date of the media
@@ -1135,7 +1135,7 @@ grl_media_get_date (GrlMedia *media)
/**
* grl_media_get_creation_date:
- * @image: the media
+ * @media: the media
*
* Returns: date when media was created
*
diff --git a/src/grl-media-source.c b/src/grl-media-source.c
index fd1a9ea..51f1d3e 100644
--- a/src/grl-media-source.c
+++ b/src/grl-media-source.c
@@ -994,7 +994,6 @@ full_resolution_done_cb (GrlMetadataSource *source,
{
GRL_DEBUG ("full_resolution_done_cb");
- gboolean cancelled = FALSE;
struct FullResolutionCtlCb *ctl_info;
struct FullResolutionDoneCb *cb_info =
(struct FullResolutionDoneCb *) user_data;
@@ -1028,32 +1027,42 @@ full_resolution_done_cb (GrlMetadataSource *source,
if (g_hash_table_size (cb_info->pending_callbacks) == 0) {
g_hash_table_unref (cb_info->pending_callbacks);
ctl_info = cb_info->ctl_info;
- /* But check if operation was cancelled (or even finished) before emitting
+
+ /* Ignore elements coming after finishing the operation (out-of-order elements) */
+ if (grl_metadata_source_operation_is_finished (GRL_METADATA_SOURCE (cb_info->source),
+ cb_info->browse_id)) {
+ GRL_DEBUG ("operation was finished, skipping full resolutuion done "
+ "result!");
+ if (media) {
+ g_object_unref (media);
+ }
+ return;
+ }
+
+ /* Check if operation was cancelled before emitting
(we execute in the idle loop) */
- if (grl_metadata_source_operation_is_cancelled (GRL_METADATA_SOURCE (cb_info->source),
- cb_info->browse_id)) {
+ if (cb_info->cancelled) {
GRL_DEBUG ("operation was cancelled, skipping full resolution done "
"result!");
if (media) {
g_object_unref (media);
media = NULL;
}
- cancelled = TRUE;
}
- if (!cancelled || cb_info->remaining == 0) {
+ if (!cb_info->cancelled || cb_info->remaining == 0) {
/* We can emit the result, but we have to do it in the right order:
we cannot guarantee that all the elements are fully resolved in
the same order that was requested. Only exception is the operation
was cancelled and this is the one with remaining == 0*/
if (GPOINTER_TO_UINT (ctl_info->next_index->data) == cb_info->remaining
- || cancelled) {
+ || cb_info->cancelled) {
GError *_error = (GError *)error;
gboolean should_free_error = FALSE;
/* Notice we pass NULL as error on purpose
since the result is valid even if the full-resolution failed */
guint remaining = cb_info->remaining;
- if (cancelled && remaining==0
+ if (cb_info->cancelled && remaining==0
&& !g_error_matches (_error, GRL_CORE_ERROR,
GRL_CORE_ERROR_OPERATION_CANCELLED)) {
/* We are cancelled and this is the last callback, cancelled error need to
@@ -1255,7 +1264,11 @@ metadata_full_resolution_ctl_cb (GrlMediaSource *source,
/* If we got an error, invoke the user callback right away and bail out */
if (error) {
- GRL_WARNING ("Operation failed: %s", error->message);
+ if (error->code == GRL_CORE_ERROR_OPERATION_CANCELLED) {
+ GRL_DEBUG ("Operation cancelled");
+ } else {
+ GRL_WARNING ("Operation failed: %s", error->message);
+ }
ctl_info->user_callback (source,
ctl_info->metadata_id,
media,
diff --git a/src/grl-plugin-registry.c b/src/grl-plugin-registry.c
index dc7dc5f..583523e 100644
--- a/src/grl-plugin-registry.c
+++ b/src/grl-plugin-registry.c
@@ -558,10 +558,14 @@ grl_plugin_registry_load (GrlPluginRegistry *registry,
}
/* Insert module name as part of plugin information */
+ if (!plugin_info->optional_info) {
+ plugin_info->optional_info =
+ g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ }
if (!g_hash_table_lookup (plugin_info->optional_info,
GRL_PLUGIN_INFO_MODULE)) {
g_hash_table_insert (plugin_info->optional_info,
- GRL_PLUGIN_INFO_MODULE,
+ g_strdup (GRL_PLUGIN_INFO_MODULE),
g_path_get_basename (plugin_info->filename));
}
diff --git a/tools/grilo-inspect/grl-inspect.c b/tools/grilo-inspect/grl-inspect.c
index da531dd..967bc44 100644
--- a/tools/grilo-inspect/grl-inspect.c
+++ b/tools/grilo-inspect/grl-inspect.c
@@ -23,9 +23,13 @@
#include <grilo.h>
#include <glib.h>
+#define GRL_LOG_DOMAIN_DEFAULT grl_inspect_log_domain
+GRL_LOG_DOMAIN_STATIC(grl_inspect_log_domain);
+
static gint delay = 0;
static GMainLoop *mainloop = NULL;
static gchar **introspect_sources = NULL;
+static gchar *conffile = NULL;
static GrlPluginRegistry *registry = NULL;
static GOptionEntry entries[] = {
@@ -33,6 +37,10 @@ static GOptionEntry entries[] = {
G_OPTION_ARG_INT, &delay,
"Wait some seconds before showing results",
NULL },
+ { "config", 'c', 0,
+ G_OPTION_ARG_STRING, &conffile,
+ "Configuration file to send to sources",
+ NULL },
{ G_OPTION_REMAINING, '\0', 0,
G_OPTION_ARG_STRING_ARRAY, &introspect_sources,
"Sources to introspect",
@@ -120,6 +128,9 @@ introspect_source (const gchar *source_id)
if (supported_ops & GRL_OP_RESOLVE) {
g_print (" grl_metadata_source_resolve():\tResolve Metadata\n");
}
+ if (supported_ops & GRL_OP_SET_METADATA) {
+ g_print (" grl_metadata_source_set_metadata():\tSet Metadata\n");
+ }
if (supported_ops & GRL_OP_METADATA) {
g_print (" grl_media_source_metadata():\t\tRetrieve Metadata\n");
}
@@ -143,12 +154,19 @@ introspect_source (const gchar *source_id)
}
g_print ("\n");
+ /* Print supported signals */
+ g_print ("Supported signals:\n");
+ if (supported_ops & GRL_OP_NOTIFY_CHANGE) {
+ g_print (" \"content-changed\" signal:\tNotify about changes\n");
+ }
+ g_print ("\n");
+
/* Print supported keys */
g_print ("Supported keys:\n");
- g_print (" Readable Keys:\t\t");
+ g_print (" Readable Keys:\t");
print_keys (grl_metadata_source_supported_keys (GRL_METADATA_SOURCE (source)));
g_print ("\n");
- g_print (" Writable Keys:\t\t");
+ g_print (" Writable Keys:\t");
print_keys (grl_metadata_source_writable_keys (GRL_METADATA_SOURCE (source)));
g_print ("\n");
g_print ("\n");
@@ -196,7 +214,17 @@ main (int argc, char *argv[])
grl_init (&argc, &argv);
+ GRL_LOG_DOMAIN_INIT (grl_inspect_log_domain, "grl-inspect");
+
registry = grl_plugin_registry_get_default ();
+ if (conffile) {
+ grl_plugin_registry_add_config_from_file (registry, conffile, &error);
+ if (error) {
+ GRL_WARNING ("Unable to load configuration: %s", error->message);
+ g_error_free (error);
+ }
+ }
+
mainloop = g_main_loop_new (NULL, FALSE);
grl_plugin_registry_load_all (registry, NULL);
diff --git a/tools/grilo-test-ui/main.c b/tools/grilo-test-ui/main.c
index 9620517..209c6fa 100644
--- a/tools/grilo-test-ui/main.c
+++ b/tools/grilo-test-ui/main.c
@@ -552,8 +552,8 @@ metadata_cb (GrlMediaSource *source,
GRL_DEBUG ("Operation cancelled");
} else {
g_critical ("Error: %s", error->message);
+ return;
}
- return;
}
if (media) {