static gchar * get_lyrics (GrlSource *source, const gchar *artist, const gchar *title) { GList *keys; GrlMedia *audio; GrlOperationOptions *options; GError *error = NULL; gchar *lyrics; audio = grl_media_audio_new (); grl_media_set_artist (audio, artist); grl_media_set_title (audio, title); keys = grl_metadata_key_list_new (GRL_METADATA_KEY_LYRICS, NULL); options = grl_operation_options_new (NULL); grl_operation_options_set_resolution_flags (options, GRL_RESOLVE_NORMAL); grl_source_resolve_sync (source, GRL_MEDIA (audio), keys, options, &error); g_assert_no_error (error); lyrics = g_strdup (grl_media_get_lyrics (audio)); g_list_free (keys); g_object_unref (options); g_object_unref (audio); return lyrics; }
static guint _mex_grilo_feed_search (MexGriloFeed *feed, const char *search_text, int offset, int limit, GrlSourceResultCb callback) { MexGriloFeedPrivate *priv = feed->priv; GrlOperationOptions *options; int op_id; options = grl_operation_options_new (NULL); grl_operation_options_set_flags (options, BROWSE_FLAGS); grl_operation_options_set_skip (options, priv->op->offset); grl_operation_options_set_count (options, priv->op->limit); op_id = grl_source_search (priv->source, priv->op->text, priv->query_keys, options, callback, feed); g_object_unref (options); return op_id; }
static void test_missing_configuration (void) { GrlMedia *media = NULL; GrlOperationOptions *options = NULL; GError *error = NULL; test_setup_tmdb (); /* Doesn't matter. We just need to get it to resolve */ media = grl_media_video_new (); g_assert (media != NULL); grl_media_set_title (media, "Non-Empty"); GrlSource *source = test_get_source(); g_assert (source); options = grl_operation_options_new (NULL); g_assert (options != NULL); grl_source_resolve_sync (source, media, grl_source_supported_keys (source), options, &error); /* Check that the plugin didn't even try to resolve data, otherwise the mock * file would have resulted in an error */ g_assert (error != NULL); g_clear_object (&media); g_clear_object (&options); g_clear_error (&error); test_shutdown_tmdb (); }
static void source_browser (gpointer data, gpointer user_data) { GrlSource *source = GRL_SOURCE (data); GrlMedia *media = GRL_MEDIA (user_data); GList *media_elements; GError *error = NULL; GList *keys; GrlOperationOptions *options = NULL; GrlCaps *caps; keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, GRL_METADATA_KEY_URL, GRL_METADATA_KEY_MODIFICATION_DATE, GRL_METADATA_KEY_MIME, GRL_METADATA_KEY_CHILDCOUNT, NULL); g_debug ("Detected new source available: '%s'", grl_source_get_name (source)); if (!(grl_source_supported_operations (source) & GRL_OP_BROWSE)) goto out; g_debug ("Browsing source: %s", grl_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) Options 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) */ caps = grl_source_get_caps (source, GRL_OP_BROWSE); options = grl_operation_options_new (caps); grl_operation_options_set_count (options, BROWSE_CHUNK_SIZE); grl_operation_options_set_resolution_flags (options, GRL_RESOLVE_IDLE_RELAY); media_elements = grl_pls_browse_sync (GRL_SOURCE (source), media, keys, options, NULL, &error); if (!media_elements) { g_debug ("No elements found for source: %s!", grl_source_get_name (source)); goto out; } if (error) g_error ("Failed to browse source: %s", error->message); g_list_foreach (media_elements, element_browser, source); out: g_list_free (keys); g_clear_object (&options); }
static void test_preconditions (void) { GrlMedia *local_media = NULL; GrlMedia *media = NULL; GError *error = NULL; GrlOperationOptions *options = NULL; test_setup_tmdb (); local_media = grl_media_audio_new (); GrlSource *source = test_get_source(); g_assert (source); options = grl_operation_options_new (NULL); g_assert (options != NULL); grl_source_resolve_sync (source, local_media, grl_source_supported_keys (source), options, &error); /* Check that the plugin didn't even try to resolve data, otherwise the mock * file would have resulted in an error */ g_assert_no_error (error); g_object_unref (local_media); local_media = grl_media_image_new (); grl_source_resolve_sync (source, local_media, grl_source_supported_keys (source), options, &error); /* Check that the plugin didn't even try to resolve data, otherwise the * empty mock file would have resulted in an error */ g_assert (error == NULL); g_object_unref (local_media); /* Check the same for title-less video */ media = grl_media_video_new (); g_assert (media != NULL); grl_source_resolve_sync (source, media, grl_source_supported_keys (source), options, &error); g_assert_no_error (error); g_object_unref (media); media = NULL; g_object_unref (options); options = NULL; test_shutdown_tmdb (); }
static void load_plugins (gchar* playlist) { GrlRegistry *registry; GrlSource *source; GError *error = NULL; GList *keys; GrlOperationOptions *options; GrlCaps *caps; GrlMedia* media; gboolean pls_media; const gchar *mime; registry = grl_registry_get_default (); grl_registry_load_all_plugins (registry, FALSE, NULL); /* Activate plugin */ if (!grl_registry_activate_plugin_by_id (registry, "grl-filesystem", &error)) g_error ("Failed to load plugin: %s", error->message); source = grl_registry_lookup_source (registry, "grl-filesystem"); if (!source) g_error ("Unable to load grl-filesystem plugin"); if (!(grl_source_supported_operations (source) & GRL_OP_MEDIA_FROM_URI)) g_error ("Unable to get media from URI"); keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, GRL_METADATA_KEY_URL, GRL_METADATA_KEY_MIME, NULL); if (!keys) g_error ("Unable to create key list"); caps = grl_source_get_caps (source, GRL_OP_MEDIA_FROM_URI); if (!caps) g_error ("Unable to get source caps"); options = grl_operation_options_new (caps); if (!options) g_error ("Unable to create operation options"); media = grl_source_get_media_from_uri_sync (source, playlist, keys, options, &error); if (!media) g_error ("Unable to get GrlMedia for playlist %s", playlist); g_object_unref (options); mime = grl_media_get_mime (media); pls_media = grl_pls_media_is_playlist (media); g_printf("Got Media for %s - mime=%s\n", playlist, mime); g_printf("\tgrl_pls_media_is_playlist = %d\n", pls_media); if (pls_media) { source_browser (source, media); } g_object_unref (media); g_object_unref (source); }
static GHashTable * get_properties_cb (MS2Server *server, const gchar *id, const gchar **properties, gpointer data, GError **error) { GHashTable *properties_table = NULL; GrlMedia *media; GriloMs2Data *grdata; grdata = g_slice_new0 (GriloMs2Data); grdata->server = g_object_ref (server); grdata->source = (GrlSource *) data; grdata->options = grl_operation_options_new (NULL); grdata->keys = get_grilo_keys (properties, &grdata->other_keys); grl_operation_options_set_resolution_flags (grdata->options, GRL_RESOLVE_FULL | GRL_RESOLVE_IDLE_RELAY); media = unserialize_media (grdata->source, id); if (grdata->keys) { grl_source_resolve (grdata->source, media, grdata->keys, grdata->options, resolve_cb, grdata); } else { resolve_cb (grdata->source, 0, media, grdata, NULL); } wait_for_result (grdata); if (grdata->error) { if (error) { *error = grdata->error; } } else { properties_table = grdata->properties; } g_object_unref (media); g_list_free (grdata->keys); g_list_free (grdata->other_keys); g_free (grdata->parent_id); g_object_unref (grdata->server); g_object_unref (grdata->options); g_slice_free (GriloMs2Data, grdata); return properties_table; }
static GrlOperationOptions * get_grl_options (GrlSource *source) { GrlCaps *caps; GrlOperationOptions *opts = NULL; caps = grl_source_get_caps (source, GRL_OP_BROWSE); opts = grl_operation_options_new (caps); g_return_val_if_fail (opts != NULL, NULL); grl_operation_options_set_flags (opts, GRL_RESOLVE_FAST_ONLY); return opts; }
static GrlOperationOptions * make_operation_options (RBGriloSource *source, GrlSupportedOps op, int position) { GrlOperationOptions *options; GrlCaps *caps; caps = grl_source_get_caps (source->priv->grilo_source, op); options = grl_operation_options_new (caps); grl_operation_options_set_skip (options, position); grl_operation_options_set_count (options, CONTAINER_FETCH_SIZE); grl_operation_options_set_type_filter (options, GRL_TYPE_FILTER_AUDIO); grl_operation_options_set_flags (options, GRL_RESOLVE_NORMAL); return options; }
static void set_test_data (GrlSource **source, GrlMedia **media, GrlOperationOptions **options, GList **keys, GrlSupportedOps source_op) { *source = test_lua_factory_get_source (FAKE_SOURCE_ID, source_op); g_assert_nonnull (*source); *media = grl_media_new (); grl_data_add_string (GRL_DATA (*media), GRL_METADATA_KEY_URL, LOCAL_CONTENT); *keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, NULL); *options = grl_operation_options_new (NULL); grl_operation_options_set_resolution_flags (*options, GRL_RESOLVE_NORMAL); }
/** * grl_operation_options_copy: * @options: a #GrlOperationOptions instance * * Returns: (transfer full): a new #GrlOperationOptions instance with its values being copies of * the values of @options. * * Since: 0.2.0 */ GrlOperationOptions * grl_operation_options_copy (GrlOperationOptions *options) { GrlOperationOptions *copy = grl_operation_options_new (options->priv->caps); copy_option (options, copy, GRL_OPERATION_OPTION_SKIP); copy_option (options, copy, GRL_OPERATION_OPTION_COUNT); copy_option (options, copy, GRL_OPERATION_OPTION_RESOLUTION_FLAGS); copy_option (options, copy, GRL_OPERATION_OPTION_TYPE_FILTER); g_hash_table_foreach (options->priv->key_filter, (GHFunc) key_filter_dup, copy->priv->key_filter); g_hash_table_foreach (options->priv->key_range_filter, (GHFunc) key_range_filter_dup, copy->priv->key_range_filter); return copy; }
int main (int argc, char *argv[]) { #if !GLIB_CHECK_VERSION(2,35,0) g_type_init (); #endif grl_init (&argc, &argv); /* * Set the TMDB API key: * You must use your own TMDB API key in your own application. */ GrlRegistry *reg = grl_registry_get_default (); GrlConfig *config = grl_config_new (TMDB_PLUGIN_ID, NULL); grl_config_set_api_key (config, TMDB_KEY); grl_registry_add_config (reg, config, NULL); /* * Get the plugin: */ GError *error = NULL; gboolean plugin_loaded = grl_registry_load_plugin_by_id (reg, TMDB_PLUGIN_ID, &error); g_assert (plugin_loaded); g_assert_no_error (error); /* * Get the Grilo source: */ GrlSource *src = grl_registry_lookup_source (reg, TMDB_PLUGIN_ID); /* * Check that it has the expected capability: */ g_assert (grl_source_supported_operations (src) & GRL_OP_RESOLVE); GrlCaps *caps = grl_source_get_caps (src, GRL_OP_RESOLVE); g_assert (caps); GrlOperationOptions *options = grl_operation_options_new (caps); /* * A media item that we will give to the TMDB plugin, * to discover its details. */ GrlMedia *media = grl_media_video_new (); grl_media_set_title (media, "Sherlock Holmes"); /* * Discover what keys are provided by the source: */ const GList *keys = grl_source_supported_keys (src); const GList* l = NULL; for (l = keys; l != NULL; l = l->next) { GrlKeyID id = GPOINTER_TO_INT (l->data); g_assert (id); const gchar *name = grl_metadata_key_get_name (id); printf ("Supported key: %s\n", name); /* * Remember this for later use: * You may instead use grl_registry_lookup_metadata_key_name(). */ if (g_strcmp0 (name, "tmdb-director") == 0) { director_key = id; } } /* * Ask the TMDB plugin for the media item's details, * from the TMDB online service: */ grl_source_resolve (src, media, keys, options, resolve_cb, NULL); /* * Start the main loop so our callback can be called: */ loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); /* * Release objects: */ g_object_unref (media); g_object_unref (config); g_object_unref (options); /* * Deinitialize Grilo: */ grl_deinit (); }
static GList * search_objects_cb (MS2Server *server, const gchar *id, const gchar *query, guint offset, guint max_count, const gchar **properties, gpointer data, GError **error) { GList *objects; GriloMs2Data *grdata; gint count; /* Browse is only allowed in root container */ if (g_strcmp0 (id, MS2_ROOT) != 0) { if (error) { /* FIXME: a better error should be reported */ *error = g_error_new (0, 0, "search is only allowed in root container"); } return NULL; } grdata = g_slice_new0 (GriloMs2Data); grdata->server = g_object_ref (server); grdata->source = (GrlSource *) data; grdata->options = grl_operation_options_new (NULL); grdata->keys = get_grilo_keys (properties, &grdata->other_keys); grdata->parent_id = g_strdup (id); grdata->list_type = LIST_ALL; grl_operation_options_set_resolution_flags (grdata->options, GRL_RESOLVE_FULL | GRL_RESOLVE_IDLE_RELAY); /* Adjust limits */ if (offset >= limit) { browse_cb (grdata->source, 0, NULL, 0, grdata, NULL); } else { count = max_count == 0? (limit - offset): CLAMP (max_count, 1, limit - offset); grl_operation_options_set_count (grdata->options, count); grl_operation_options_set_skip (grdata->options, offset); grl_source_search (grdata->source, query, grdata->keys, grdata->options, browse_cb, grdata); } wait_for_result (grdata); if (grdata->error) { if (error) { *error = grdata->error; } g_list_foreach (grdata->children, (GFunc) g_hash_table_unref, NULL); g_list_free (grdata->children); objects = NULL; } else { objects = grdata->children; } g_list_free (grdata->keys); g_list_free (grdata->other_keys); g_free (grdata->parent_id); g_object_unref (grdata->server); g_object_unref (grdata->options); g_slice_free (GriloMs2Data, grdata); return objects; }
static GList * list_children_cb (MS2Server *server, const gchar *id, ListType list_type, guint offset, guint max_count, const gchar **properties, gpointer data, GError **error) { GList *children; GrlMedia *media; GriloMs2Data *grdata; gint count; grdata = g_slice_new0 (GriloMs2Data); grdata->server = g_object_ref (server); grdata->source = (GrlSource *) data; grdata->options = grl_operation_options_new (NULL); grdata->keys = get_grilo_keys (properties, &grdata->other_keys); grdata->parent_id = g_strdup (id); grdata->offset = offset; grdata->list_type = list_type; grl_operation_options_set_resolution_flags (grdata->options, GRL_RESOLVE_FULL | GRL_RESOLVE_IDLE_RELAY); media = unserialize_media (grdata->source, id); /* Adjust limits */ if (offset >= limit) { browse_cb (grdata->source, 0, NULL, 0, grdata, NULL); } else { /* TIP: as Grilo is not able to split containers and items, in this case we will ask for all elements and then remove unneeded children in callback */ switch (list_type) { case LIST_ALL: count = max_count == 0? (limit - offset): CLAMP (max_count, 1, limit - offset); grl_operation_options_set_count (grdata->options, count); grl_operation_options_set_skip (grdata->options, offset); grdata->operation_id = grl_source_browse (grdata->source, media, grdata->keys, grdata->options, browse_cb, grdata); break; case LIST_CONTAINERS: case LIST_ITEMS: count = max_count == 0? limit: max_count; grl_operation_options_set_count (grdata->options, count); grl_operation_options_set_skip (grdata->options, 0); grdata->operation_id = grl_source_browse (grdata->source, media, grdata->keys, grdata->options, browse_cb, grdata); break; default: /* Protection. It should never be reached, unless ListType is extended */ browse_cb (grdata->source, 0, NULL, 0, grdata, NULL); } } wait_for_result (grdata); if (grdata->error) { if (error) { *error = grdata->error; } g_list_foreach (grdata->children, (GFunc) g_hash_table_unref, NULL); g_list_free (grdata->children); children = NULL; } else { children = grdata->children; } g_object_unref (media); g_list_free (grdata->keys); g_list_free (grdata->other_keys); g_free (grdata->parent_id); g_object_unref (grdata->server); g_object_unref (grdata->options); g_slice_free (GriloMs2Data, grdata); return children; }
/** * grl_operation_options_obey_caps: * @options: a #GrlOperationOptions instance * @caps: capabilities against which we want to test @options * @supported_options: (out callee-allocates): if not %NULL, will contain a * newly-allocated #GrlOperationOptions instance containing all the values of * @options that match @caps. * @unsupported_options: (out callee-allocates): if not %NULL, will contain a * newly-allocated #GrlOperationOptions instance containing all the values of * @options that do not match @caps. * * Check whether @options obey to @caps. * Optionally provide the options that match (respectively don't match) @caps * in @supported_options (respectively @unsupported_options). * This would typically (but not necessarily) be used with a * #GrlOperationOptions instance that was created with %NULL caps. * * Returns: %TRUE if @options obey to @caps, %FALSE otherwise. * * Since: 0.2.0 */ gboolean grl_operation_options_obey_caps (GrlOperationOptions *options, GrlCaps *caps, GrlOperationOptions **supported_options, GrlOperationOptions **unsupported_options) { gboolean ret = TRUE; GHashTableIter table_iter; gpointer key_ptr; GValue *value; GrlRangeValue *range_value; if (supported_options) { *supported_options = grl_operation_options_new (caps); /* these options are always supported */ copy_option (options, *supported_options, GRL_OPERATION_OPTION_SKIP); copy_option (options, *supported_options, GRL_OPERATION_OPTION_COUNT); copy_option (options, *supported_options, GRL_OPERATION_OPTION_RESOLUTION_FLAGS); } if (unsupported_options) *unsupported_options = grl_operation_options_new (NULL); ret &= check_and_copy_option (options, caps, GRL_OPERATION_OPTION_TYPE_FILTER, supported_options, unsupported_options); /* Check filter-by-equal-key */ g_hash_table_iter_init (&table_iter, options->priv->key_filter); while (g_hash_table_iter_next (&table_iter, &key_ptr, (gpointer *)&value)) { GrlKeyID key_id = GRLPOINTER_TO_KEYID (key_ptr); if (grl_caps_is_key_filter (caps, key_id)) { if (supported_options) { g_hash_table_insert ((*supported_options)->priv->key_filter, key_ptr, grl_g_value_dup (value)); } } else { ret = FALSE; if (unsupported_options) { g_hash_table_insert ((*unsupported_options)->priv->key_filter, key_ptr, grl_g_value_dup (value)); } } } /* Check filter-by-range-key */ g_hash_table_iter_init (&table_iter, options->priv->key_range_filter); while (g_hash_table_iter_next (&table_iter, &key_ptr, (gpointer *)&range_value)) { GrlKeyID key_id = GRLPOINTER_TO_KEYID (key_ptr); if (grl_caps_is_key_range_filter (caps, key_id)) { if (supported_options) { g_hash_table_insert ((*supported_options)->priv->key_range_filter, key_ptr, grl_range_value_dup (range_value)); } } else { ret = FALSE; if (unsupported_options) { g_hash_table_insert ((*unsupported_options)->priv->key_range_filter, key_ptr, grl_range_value_dup (range_value)); } } } return ret; }