diff options
author | Juan A. Suarez Romero <jasuarez@igalia.com> | 2011-06-09 15:11:12 +0000 |
---|---|---|
committer | Juan A. Suarez Romero <jasuarez@igalia.com> | 2011-06-10 08:56:18 +0000 |
commit | 62b05b33408669f9f3bd748db5351cb9f8c7201c (patch) | |
tree | 4d94ef5f6fdef7f361211a3fdf0626f4dba3a563 | |
parent | f3bbda716318865ccc9cabebdb9613158f7b48bd (diff) | |
download | grilo-62b05b33408669f9f3bd748db5351cb9f8c7201c.tar.gz |
doc: Split code examples from documentation
Put examples in a separated directory, so user can easily compile them, and
embed those files in the documentation.
Signed-off-by: Juan A. Suarez Romero <jasuarez@igalia.com>
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | doc/grilo/quick-start-using-grilo.xml | 664 | ||||
-rw-r--r-- | examples/Makefile.am | 20 | ||||
-rw-r--r-- | examples/browsing.c | 128 | ||||
-rw-r--r-- | examples/configuring-plugins.c | 69 | ||||
-rw-r--r-- | examples/efficient-metadata-resolution.c | 149 | ||||
-rw-r--r-- | examples/loading-plugins.c | 71 | ||||
-rw-r--r-- | examples/multivalues.c | 123 | ||||
-rw-r--r-- | examples/searching.c | 105 |
10 files changed, 698 insertions, 634 deletions
diff --git a/Makefile.am b/Makefile.am index bb1290b..e364cc2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src libs bindings tools +SUBDIRS = src libs bindings tools examples if ENABLE_TESTS SUBDIRS += tests diff --git a/configure.ac b/configure.ac index 5bee9af..8f84fdd 100644 --- a/configure.ac +++ b/configure.ac @@ -279,6 +279,7 @@ AC_CONFIG_FILES([ doc/Makefile doc/grilo/Makefile doc/libs/Makefile + examples/Makefile ]) AC_OUTPUT diff --git a/doc/grilo/quick-start-using-grilo.xml b/doc/grilo/quick-start-using-grilo.xml index c2d019a..4567754 100644 --- a/doc/grilo/quick-start-using-grilo.xml +++ b/doc/grilo/quick-start-using-grilo.xml @@ -23,7 +23,7 @@ $ cd grilo-plugins $ ./autogen.sh --prefix=/usr $ make $ sudo make install - </programlisting> + </programlisting> <para> You should now see the grilo libraries installed under /usr/lib and the @@ -38,8 +38,8 @@ $ sudo make install <programlisting> # Execute Grilo's test GUI $ /usr/bin/grilo-test-ui - </programlisting> - + </programlisting> + <para> This is a simple playground application that you can use to test the framework and its plugins. @@ -50,87 +50,23 @@ $ /usr/bin/grilo-test-ui <title>Compiling Grilo based programs</title> <programlisting> gcc -o example `pkg-config --cflags --libs grilo-x.y` example.c - </programlisting> + </programlisting> </section> <section id="programming-with-grilo-loading-plugins"> <title>Programming with Grilo: Loading plugins</title> <para>Here is a small program illustrating how you can load plugins:</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); - } -} - -gint -main (int argc, gchar *argv[]) -{ - GMainLoop *loop; - - grl_init (&argc, &argv); - GRL_LOG_DOMAIN_INIT (example_log_domain, "example"); - load_plugins (); /* Load Grilo plugins */ - - /* Run the main loop */ - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); - - return 0; -} -]]> + <xi:include href="../../examples/loading-plugins.c" + parse="text" + xmlns:xi="http://www.w3.org/2001/XInclude"/> </programlisting> <para> For more information on how to operate with plugins and media providers (sources), please check the <link linkend="GrlPluginRegistry">GrlPluginRegistry</link> - API reference. + API reference. </para> </section> @@ -163,78 +99,16 @@ main (int argc, gchar *argv[]) application: </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) -{ - /* If the Youtube plugin is installed, you should see it here now! */ - g_debug ("Detected new source available: '%s'", - grl_metadata_source_get_name (GRL_METADATA_SOURCE (user_data))); -} - -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 (only 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); - - /* When the plugin is loaded, the framework will provide - this configuration for it */ -} - -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; -} -]]> + <xi:include href="../../examples/configuring-plugins.c" + parse="text" + xmlns:xi="http://www.w3.org/2001/XInclude"/> </programlisting> <para> For more information on how to configure plugins plase check the <link linkend="GrlConfig">GrlConfig</link> - API reference. + API reference. </para> </section> @@ -244,137 +118,16 @@ main (int argc, gchar *argv[]) content from a particular media source (a similar approach can be used for searching content instead of browsing):</para> <programlisting role="C"> -<![CDATA[ -#include <grilo.h> - -#define GRL_LOG_DOMAIN_DEFAULT example_log_domain -GRL_LOG_DOMAIN_STATIC(example_log_domain); - -/* This callback is invoked for each result that matches our - browse operation. The arguments are: - 1) The source we obtained the content from. - 2) The operation identifier this result relates to. - 3) A media object representing content that matched the browse operation. - 4) Estimation of the number of remaining media objects that will be sent - after this one as part of the same resultset (0 means that the browse - operation is finished). - 5) User data passed to the grl_media_source_browse method. - 6) A GError if an error happened, NULL otherwise */ -static void -browse_cb (GrlMediaSource *source, - guint browse_id, - GrlMedia *media, - guint remaining, - gpointer user_data, - const GError *error) -{ - /* First we check if the operation failed for some reason */ - if (error) { - g_error ("Browse operation failed. Reason: %s", error->message); - } - - /* Check if we got a valid media object as some plugins may call the callback - with a NULL media under certain circumstances (for example when they - cannot estimate the number of remaining results and they find suddenly they - don't have any more results to send) */ - if (media) { - /* Get the metadata we are interested in */ - const gchar *title = grl_media_get_title (media); - - /* If the media is a container (box) that means we could - browse it again (that is, we could use it as the second parameter - of the grl_media_source_browse method) */ - if (GRL_IS_MEDIA_BOX (media)) { - guint childcount = grl_media_box_get_childcount (GRL_MEDIA_BOX (media)); - g_debug ("\t Got '%s' (container with %d elements)", title, childcount); - } else { - guint seconds = grl_media_get_duration (media); - const gchar *url = grl_media_get_url (media); - g_debug ("\t Got '%s' (media - length: %d seconds)", title, seconds); - g_debug ("\t\t URL: %s", url); - } - g_object_unref (media); - } - - /* Check if this was the last result */ - if (remaining == 0) { - g_debug ("Browse operation finished!"); - } -} - -static void -source_added_cb (GrlPluginRegistry *registry, gpointer user_data) -{ - static gboolean first = TRUE; - GrlMetadataSource *source = GRL_METADATA_SOURCE (user_data); - GList * keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, - GRL_METADATA_KEY_DURATION, - GRL_METADATA_KEY_URL, - GRL_METADATA_KEY_CHILDCOUNT, - NULL); - g_debug ("Detected new source available: '%s'", - grl_metadata_source_get_name (source)); - - /* We will just issue a browse operation on the first browseble - source we find */ - if (first && - grl_metadata_source_supported_operations (source) & GRL_OP_BROWSE) { - first = FALSE; - g_debug ("Browsing source: %s", grl_metadata_source_get_name (source)); - /* Here is how you can browse a source, you have to provide: - 1) The source you want to browse contents from. - 2) The container object you want to browse (NULL for the root container) - 3) A list of metadata keys we are interested in. - 4) Flags to control certain aspects of the browse operation. - 5) A callback that the framework will invoke for each available result - 6) User data for the callback - It returns an operation identifier that you can use to match results - with the corresponding request (we ignore it here) */ - grl_media_source_browse (GRL_MEDIA_SOURCE (source), - NULL, - keys, - 0, 5, - GRL_RESOLVE_IDLE_RELAY, - browse_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); - } -} - -gint -main (int argc, gchar *argv[]) -{ - GMainLoop *loop; - grl_init (&argc, &argv); - GRL_LOG_DOMAIN_INIT (example_log_domain, "example"); - load_plugins (); - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); - return 0; -} -]]> - </programlisting> + <xi:include href="../../examples/browsing.c" + parse="text" + xmlns:xi="http://www.w3.org/2001/XInclude"/> + </programlisting> <para> For more information on how to operate media sources plase check the <link linkend="GrlMediaSource">GrlMediaSource</link> - API reference. + API reference. </para> </section> @@ -384,114 +137,16 @@ main (int argc, gchar *argv[]) content by text from a particular media source (Jamendo in this example):</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) -{ - if (error) { - g_error ("Search operation failed. Reason: %s", error->message); - } - - if (media) { - const gchar *title = grl_media_get_title (media); - if (GRL_IS_MEDIA_BOX (media)) { - guint childcount = grl_media_box_get_childcount (GRL_MEDIA_BOX (media)); - g_debug ("\t Got '%s' (container with %d elements)", title, childcount); - } else { - guint seconds = grl_media_get_duration (media); - const gchar *url = grl_media_get_url (media); - g_debug ("\t Got '%s' (media - length: %d seconds)", title, seconds); - g_debug ("\t\t URL: %s", url); - } - } - - if (remaining == 0) { - g_debug ("Search operation finished!"); - } else { - g_debug ("\t%d results remaining!", remaining); - } - - 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_DURATION, - GRL_METADATA_KEY_CHILDCOUNT, - 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 Jamendo */ - id = grl_metadata_source_get_id (source); - if (strcmp (id, "grl-jamendo")) - return; - - g_debug ("Searching \"rock\" in Jamendo"); - 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); - } -} - -gint -main (int argc, gchar *argv[]) -{ - GMainLoop *loop; - grl_init (&argc, &argv); - GRL_LOG_DOMAIN_INIT (example_log_domain, "example"); - load_plugins (); - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); - return 0; -} -]]> - </programlisting> + <xi:include href="../../examples/searching.c" + parse="text" + xmlns:xi="http://www.w3.org/2001/XInclude"/> + </programlisting> <para> For more information on how to operate media sources plase check the <link linkend="GrlMediaSource">GrlMediaSource</link> - API reference. + API reference. </para> </section> @@ -507,7 +162,7 @@ main (int argc, gchar *argv[]) to handle multi-valued properties. </para> <para> - One issue concerning multi-valued properties are their relations with + One issue concerning multi-valued properties are their relations with other properties. Following the example of the video resource with multiple URIs, each of these URIs should have its own mime-type associated, as well as its own width and height values. When dealing with multi-valued @@ -535,131 +190,16 @@ main (int argc, gchar *argv[]) to illustrate how to use it: </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_info; - - if (error) { - g_error ("Search operation failed. Reason: %s", error->message); - } - - if (media) { - /* Look through all available URLs for this video resource */ - for (i = 0; i < grl_data_length (GRL_DATA (media), GRL_METADATA_KEY_URL); i++) { - /* Here we use the low-level GrlRelatedKeys API for demonstration purposes only, - but we could have just used the more convenient - grl_media_video_get_url_data_nth() API instead in this case */ - url_info = grl_data_get_related_keys (GRL_DATA (media), GRL_METADATA_KEY_URL, i); - g_debug ("\t [%s] Got url '%s' and mime-type '%s'", - grl_media_get_id (media), - grl_related_keys_get_string (url_info, GRL_METADATA_KEY_URL), - grl_related_keys_get_string (url_info, 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; - - 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; -} -]]> + <xi:include href="../../examples/multivalues.c" + parse="text" + xmlns:xi="http://www.w3.org/2001/XInclude"/> </programlisting> <para> For more information on how to operate with media objects plase check the <link linkend="GrlData">GrlData</link> hierarchy - API reference. + API reference. </para> </section> @@ -747,152 +287,10 @@ main (int argc, gchar *argv[]) be an acceptable delay. </para> <programlisting role="C"> -<![CDATA[ -#include <grilo.h> -#include <string.h> -#include <stdlib.h> - -#define GRL_LOG_DOMAIN_DEFAULT example_log_domain -GRL_LOG_DOMAIN_STATIC(example_log_domain); - -const gchar *target_source_id = NULL; - -static void -metadata_cb (GrlMediaSource *source, - guint metadata_id, - GrlMedia *media, - gpointer user_data, - const GError *error) -{ - if (error) - g_error ("Metadata operation failed. Reason: %s", error->message); - - const gchar *url = grl_media_get_url (media); - g_debug ("\tURL: %s", url); - g_object_unref (media); - exit (0); -} - -static void -search_cb (GrlMediaSource *source, - guint browse_id, - GrlMedia *media, - guint remaining, - gpointer user_data, - const GError *error) -{ - if (error) - g_error ("Search operation failed. Reason: %s", error->message); - - if (!media) { - g_error ("No media items found matching the text \"rock\"!"); - return; - } - - g_debug ("Got matching media from %s. Details:", target_source_id); - const gchar *title = grl_media_get_title (media); - g_debug ("\tTitle: %s", title); - const gchar *url = grl_media_get_url (media); - if (url) { - g_debug ("\tURL: %s:", url); - g_object_unref (media); - exit (0); - } else { - g_debug ("URL no available, trying with slow keys now"); - GList *keys = grl_metadata_key_list_new (GRL_METADATA_KEY_URL, NULL); - grl_media_source_metadata (source, - media, - keys, - GRL_RESOLVE_IDLE_RELAY, - metadata_cb, - NULL); - g_list_free (keys); - } -} - -static void -source_added_cb (GrlPluginRegistry *registry, gpointer user_data) -{ - GrlMetadataSource *source = GRL_METADATA_SOURCE (user_data); - const gchar *source_id = grl_metadata_source_get_id (source); - - /* We are looking for one source in particular */ - if (strcmp (source_id, target_source_id)) - return; - - GList *keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, - GRL_METADATA_KEY_URL, - NULL); - - /* The source must be searchable */ - if (!(grl_metadata_source_supported_operations (source) & GRL_OP_SEARCH)) - g_error ("Source %s is not searchable!", source_id); - - /* Retrieve the first media from the source matching the text "rock" */ - g_debug ("Searching \"rock\" in \"%s\"", source_id); - grl_media_source_search (GRL_MEDIA_SOURCE (source), - "rock", - keys, - 0, 1, - GRL_RESOLVE_IDLE_RELAY | GRL_RESOLVE_FAST_ONLY, - search_cb, - NULL); - g_list_free (keys); -} - -static void -configure_plugins (void) -{ - GrlConfig *config; - GrlPluginRegistry *registry; - - /* Let's configure only the Youtube plugin (only 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); -} - -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); - } -} - -gint -main (int argc, gchar *argv[]) -{ - GMainLoop *loop; - grl_init (&argc, &argv); - - if (argc != 2) { - g_print ("Please specify id of the source to search " \ - "(example: grl-youtube)\n"); - exit (1); - } else { - target_source_id = argv[1]; - } - - 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> + <xi:include href="../../examples/efficient-metadata-resolution.c" + parse="text" + xmlns:xi="http://www.w3.org/2001/XInclude"/> + </programlisting> </section> </section> diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..6e8e8c7 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,20 @@ +AM_CFLAGS = $(DEPS_CFLAGS) -I$(top_srcdir)/src -I$(top_srcdir)/src/data +LDADD = $(DEPS_LIBS) $(top_builddir)/src/lib@GRL_NAME@.la + +noinst_PROGRAMS = browsing configuring-plugins efficient-metadata-resolution \ + loading-plugins multivalues searching + +browsing_SOURCES = browsing.c + +configuring_plugins_SOURCES = configuring-plugins.c + +efficient_metadata_resolution_SOURCES = efficient-metadata-resolution.c + +loading_plugins_SOURCES = loading-plugins.c + +multivalues_SOURCES = multivalues.c + +searching_SOURCES = searching.c + +MAINTAINERCLEANFILES = Makefile.in *~ +DISTCLEANFILES = $(MAINTAINERCLEANFILES) diff --git a/examples/browsing.c b/examples/browsing.c new file mode 100644 index 0000000..bd88bd2 --- /dev/null +++ b/examples/browsing.c @@ -0,0 +1,128 @@ + +/* + * Browsing in Grilo. + * Shows the first 5 elements of each browsable source + */ + +#include <grilo.h> + +#define GRL_LOG_DOMAIN_DEFAULT example_log_domain +GRL_LOG_DOMAIN_STATIC(example_log_domain); + +/* This callback is invoked for each result that matches our + browse operation. The arguments are: + 1) The source we obtained the content from. + 2) The operation identifier this result relates to. + 3) A media object representing content that matched the browse operation. + 4) Estimation of the number of remaining media objects that will be sent + after this one as part of the same resultset (0 means that the browse + operation is finished). + 5) User data passed to the grl_media_source_browse method. + 6) A GError if an error happened, NULL otherwise */ +static void +browse_cb (GrlMediaSource *source, + guint browse_id, + GrlMedia *media, + guint remaining, + gpointer user_data, + const GError *error) +{ + /* First we check if the operation failed for some reason */ + if (error) { + g_error ("Browse operation failed. Reason: %s", error->message); + } + + /* Check if we got a valid media object as some plugins may call the callback + with a NULL media under certain circumstances (for example when they + cannot estimate the number of remaining results and they find suddenly they + don't have any more results to send) */ + if (media) { + /* Get the metadata we are interested in */ + const gchar *title = grl_media_get_title (media); + + /* If the media is a container (box) that means we could + browse it again (that is, we could use it as the second parameter + of the grl_media_source_browse method) */ + if (GRL_IS_MEDIA_BOX (media)) { + guint childcount = grl_media_box_get_childcount (GRL_MEDIA_BOX (media)); + g_debug ("\t Got '%s' (container with %d elements)", title, childcount); + } else { + guint seconds = grl_media_get_duration (media); + const gchar *url = grl_media_get_url (media); + g_debug ("\t Got '%s' (media - length: %d seconds)", title, seconds); + g_debug ("\t\t URL: %s", url); + } + g_object_unref (media); + } + + /* Check if this was the last result */ + if (remaining == 0) { + g_debug ("Browse operation finished!"); + } +} + +static void +source_added_cb (GrlPluginRegistry *registry, gpointer user_data) +{ + static gboolean first = TRUE; + GrlMetadataSource *source = GRL_METADATA_SOURCE (user_data); + GList * keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, + GRL_METADATA_KEY_DURATION, + GRL_METADATA_KEY_URL, + GRL_METADATA_KEY_CHILDCOUNT, + NULL); + g_debug ("Detected new source available: '%s'", + grl_metadata_source_get_name (source)); + + /* We will just issue a browse operation on the first browseble + source we find */ + if (first && + grl_metadata_source_supported_operations (source) & GRL_OP_BROWSE) { + first = FALSE; + g_debug ("Browsing source: %s", grl_metadata_source_get_name (source)); + /* Here is how you can browse a source, you have to provide: + 1) The source you want to browse contents from. + 2) The container object you want to browse (NULL for the root container) + 3) A list of metadata keys we are interested in. + 4) Flags to control certain aspects of the browse operation. + 5) A callback that the framework will invoke for each available result + 6) User data for the callback + It returns an operation identifier that you can use to match results + with the corresponding request (we ignore it here) */ + grl_media_source_browse (GRL_MEDIA_SOURCE (source), + NULL, + keys, + 0, 5, + GRL_RESOLVE_IDLE_RELAY, + browse_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); + } +} + +gint +main (int argc, gchar *argv[]) +{ + GMainLoop *loop; + grl_init (&argc, &argv); + GRL_LOG_DOMAIN_INIT (example_log_domain, "example"); + load_plugins (); + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + return 0; +} diff --git a/examples/configuring-plugins.c b/examples/configuring-plugins.c new file mode 100644 index 0000000..6e75427 --- /dev/null +++ b/examples/configuring-plugins.c @@ -0,0 +1,69 @@ + +/* + * Configuring plugins in Grilo. + * Shows how to configure the Youtube plugin. + */ + +#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) +{ + /* If the Youtube plugin is installed, you should see it here now! */ + g_debug ("Detected new source available: '%s'", + grl_metadata_source_get_name (GRL_METADATA_SOURCE (user_data))); +} + +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 (only 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); + + /* When the plugin is loaded, the framework will provide + this configuration for it */ +} + +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; +} diff --git a/examples/efficient-metadata-resolution.c b/examples/efficient-metadata-resolution.c new file mode 100644 index 0000000..3dd578e --- /dev/null +++ b/examples/efficient-metadata-resolution.c @@ -0,0 +1,149 @@ + +/* + * Shows how to get content in an efficient way. + * Search 'rock' content in all searchable sources. + */ + +#include <grilo.h> +#include <string.h> +#include <stdlib.h> + +#define GRL_LOG_DOMAIN_DEFAULT example_log_domain +GRL_LOG_DOMAIN_STATIC(example_log_domain); + +const gchar *target_source_id = NULL; + +static void +metadata_cb (GrlMediaSource *source, + guint metadata_id, + GrlMedia *media, + gpointer user_data, + const GError *error) +{ + if (error) + g_error ("Metadata operation failed. Reason: %s", error->message); + + const gchar *url = grl_media_get_url (media); + g_debug ("\tURL: %s", url); + g_object_unref (media); + exit (0); +} + +static void +search_cb (GrlMediaSource *source, + guint browse_id, + GrlMedia *media, + guint remaining, + gpointer user_data, + const GError *error) +{ + if (error) + g_error ("Search operation failed. Reason: %s", error->message); + + if (!media) { + g_error ("No media items found matching the text \"rock\"!"); + return; + } + + g_debug ("Got matching media from %s. Details:", target_source_id); + const gchar *title = grl_media_get_title (media); + g_debug ("\tTitle: %s", title); + const gchar *url = grl_media_get_url (media); + if (url) { + g_debug ("\tURL: %s:", url); + g_object_unref (media); + exit (0); + } else { + g_debug ("URL no available, trying with slow keys now"); + GList *keys = grl_metadata_key_list_new (GRL_METADATA_KEY_URL, NULL); + grl_media_source_metadata (source, + media, + keys, + GRL_RESOLVE_IDLE_RELAY, + metadata_cb, + NULL); + g_list_free (keys); + } +} + +static void +source_added_cb (GrlPluginRegistry *registry, gpointer user_data) +{ + GrlMetadataSource *source = GRL_METADATA_SOURCE (user_data); + const gchar *source_id = grl_metadata_source_get_id (source); + + /* We are looking for one source in particular */ + if (strcmp (source_id, target_source_id)) + return; + + GList *keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, + GRL_METADATA_KEY_URL, + NULL); + + /* The source must be searchable */ + if (!(grl_metadata_source_supported_operations (source) & GRL_OP_SEARCH)) + g_error ("Source %s is not searchable!", source_id); + + /* Retrieve the first media from the source matching the text "rock" */ + g_debug ("Searching \"rock\" in \"%s\"", source_id); + grl_media_source_search (GRL_MEDIA_SOURCE (source), + "rock", + keys, + 0, 1, + GRL_RESOLVE_IDLE_RELAY | GRL_RESOLVE_FAST_ONLY, + search_cb, + NULL); + g_list_free (keys); +} + +static void +configure_plugins (void) +{ + GrlConfig *config; + GrlPluginRegistry *registry; + + /* Let's configure only the Youtube plugin (only 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); +} + +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); + } +} + +gint +main (int argc, gchar *argv[]) +{ + GMainLoop *loop; + grl_init (&argc, &argv); + + if (argc != 2) { + g_print ("Please specify id of the source to search " \ + "(example: grl-youtube)\n"); + exit (1); + } else { + target_source_id = argv[1]; + } + + 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; +} diff --git a/examples/loading-plugins.c b/examples/loading-plugins.c new file mode 100644 index 0000000..b23e04d --- /dev/null +++ b/examples/loading-plugins.c @@ -0,0 +1,71 @@ + +/* + * Loading plugins in Grilo. + * Tracks sources adding and removing + */ + +#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); + } +} + +gint +main (int argc, gchar *argv[]) +{ + GMainLoop *loop; + + grl_init (&argc, &argv); + GRL_LOG_DOMAIN_INIT (example_log_domain, "example"); + load_plugins (); /* Load Grilo plugins */ + + /* Run the main loop */ + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/multivalues.c b/examples/multivalues.c new file mode 100644 index 0000000..ed5e17c --- /dev/null +++ b/examples/multivalues.c @@ -0,0 +1,123 @@ + +/* + * Handling multivalued elements in Grilo. + * Search all 'rock' content in Youtube, and for each one prints the available + * URLs. + */ + +#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_info; + + if (error) { + g_error ("Search operation failed. Reason: %s", error->message); + } + + if (media) { + /* Look through all available URLs for this video resource */ + for (i = 0; i < grl_data_length (GRL_DATA (media), GRL_METADATA_KEY_URL); i++) { + /* Here we use the low-level GrlRelatedKeys API for demonstration purposes only, + but we could have just used the more convenient + grl_media_video_get_url_data_nth() API instead in this case */ + url_info = grl_data_get_related_keys (GRL_DATA (media), GRL_METADATA_KEY_URL, i); + g_debug ("\t [%s] Got url '%s' and mime-type '%s'", + grl_media_get_id (media), + grl_related_keys_get_string (url_info, GRL_METADATA_KEY_URL), + grl_related_keys_get_string (url_info, 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; + + 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; +} diff --git a/examples/searching.c b/examples/searching.c new file mode 100644 index 0000000..c9804ee --- /dev/null +++ b/examples/searching.c @@ -0,0 +1,105 @@ + +/* + * Searching in Grilo. + * Search all media in Jamendo with the word 'rock'. + */ + +#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) +{ + if (error) { + g_error ("Search operation failed. Reason: %s", error->message); + } + + if (media) { + const gchar *title = grl_media_get_title (media); + if (GRL_IS_MEDIA_BOX (media)) { + guint childcount = grl_media_box_get_childcount (GRL_MEDIA_BOX (media)); + g_debug ("\t Got '%s' (container with %d elements)", title, childcount); + } else { + guint seconds = grl_media_get_duration (media); + const gchar *url = grl_media_get_url (media); + g_debug ("\t Got '%s' (media - length: %d seconds)", title, seconds); + g_debug ("\t\t URL: %s", url); + } + } + + if (remaining == 0) { + g_debug ("Search operation finished!"); + } else { + g_debug ("\t%d results remaining!", remaining); + } + + 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_DURATION, + GRL_METADATA_KEY_CHILDCOUNT, + 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 Jamendo */ + id = grl_metadata_source_get_id (source); + if (strcmp (id, "grl-jamendo")) + return; + + g_debug ("Searching \"rock\" in Jamendo"); + 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); + } +} + +gint +main (int argc, gchar *argv[]) +{ + GMainLoop *loop; + grl_init (&argc, &argv); + GRL_LOG_DOMAIN_INIT (example_log_domain, "example"); + load_plugins (); + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + return 0; +} |