diff options
author | Juan A. Suarez Romero <jasuarez@igalia.com> | 2011-04-20 14:29:26 +0000 |
---|---|---|
committer | Juan A. Suarez Romero <jasuarez@igalia.com> | 2011-04-20 14:29:26 +0000 |
commit | 81327d239073f63932ce0062a560b613f68fbd81 (patch) | |
tree | 1b2cd3327b31ad37f5104957f471596968560092 | |
parent | 498270332e2d3910417decadfc4672c8ad06bf79 (diff) | |
parent | 5afd4c310714222786a620a160fe05ba97f166a7 (diff) |
Merge commit 'grilo-0.1.15' into rpm
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | doc/grilo/grilo-docs.sgml | 7 | ||||
-rw-r--r-- | doc/grilo/grilo-sections.txt | 143 | ||||
-rw-r--r-- | doc/grilo/grilo.types | 1 | ||||
-rw-r--r-- | doc/grilo/quick-start-using-grilo.xml | 307 | ||||
-rw-r--r-- | doc/libs/grilo-libs-sections.txt | 2 | ||||
-rw-r--r-- | src/data/grl-media.c | 4 | ||||
-rw-r--r-- | src/grl-media-source.c | 31 | ||||
-rw-r--r-- | src/grl-plugin-registry.c | 6 | ||||
-rw-r--r-- | tools/grilo-inspect/grl-inspect.c | 32 | ||||
-rw-r--r-- | tools/grilo-test-ui/main.c | 2 |
12 files changed, 520 insertions, 28 deletions
@@ -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) { |