void
test_setup_thetvdb (void)
{
  GrlConfig *config;
  GrlRegistry *registry;
  GError *error = NULL;

  if (tmp_dir == NULL) {
    /* Only create tmp dir and set the XDG_DATA_HOME once */
    tmp_dir = g_build_filename (g_get_tmp_dir (), "test-thetvdb-XXXXXX", NULL);
    tmp_dir = g_mkdtemp (tmp_dir);
    g_assert_nonnull (tmp_dir);

    g_setenv ("XDG_DATA_HOME", tmp_dir, TRUE);
  }

  config = grl_config_new (THETVDB_ID, NULL);
  grl_config_set_api_key (config, "THETVDB_TEST_MOCK_API_KEY");

  registry = grl_registry_get_default ();
  grl_registry_add_config (registry, config, &error);
  g_assert_no_error (error);

  grl_registry_load_plugin_by_id (registry, THETVDB_ID, &error);
  g_assert_no_error (error);

  source = GRL_SOURCE (grl_registry_lookup_source (registry, THETVDB_ID));
  g_assert (source != NULL);

  g_assert (grl_source_supported_operations (source) & GRL_OP_RESOLVE);
}
Example #2
0
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);
}
Example #3
0
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 GrlSource*
test_lua_factory_get_source (gchar *source_id,
                             GrlSupportedOps source_ops)
{
  GrlRegistry *registry = grl_registry_get_default ();
  GrlSource *source = grl_registry_lookup_source (registry, source_id);
  g_assert_nonnull (source);
  g_assert (grl_source_supported_operations (source) & source_ops);
  return source;
}
Example #5
0
static void
grilo_source_added_cb (GrlRegistry *registry, GrlSource *grilo_source, RBGriloPlugin *plugin)
{
	GrlPlugin *grilo_plugin;
	GrlSupportedOps ops;
	const GList *keys;
	RBSource *source;
	RBShell *shell;
	int i;

	if (!(grl_source_get_supported_media (grilo_source) & GRL_MEDIA_TYPE_AUDIO)) {
		rb_debug ("grilo source %s doesn't support audio",
			  grl_source_get_name (grilo_source));
		goto ignore;
	}

	grilo_plugin = grl_source_get_plugin (grilo_source);
	for (i = 0; i < G_N_ELEMENTS (ignored_plugins); i++) {
		if (g_str_equal (ignored_plugins[i], grl_plugin_get_id (grilo_plugin))) {
			rb_debug ("grilo source %s is blacklisted",
				  grl_source_get_name (grilo_source));
			goto ignore;
		}
	}

	ops = grl_source_supported_operations (grilo_source);
	if (((ops & GRL_OP_BROWSE) == 0) && ((ops & GRL_OP_SEARCH) == 0)) {
		rb_debug ("grilo source %s is not interesting",
			  grl_source_get_name (grilo_source));
		goto ignore;
	}

	keys = grl_source_supported_keys (grilo_source);
	if (g_list_find ((GList *)keys, GINT_TO_POINTER (GRL_METADATA_KEY_URL)) == NULL) {
		rb_debug ("grilo source %s doesn't do urls", grl_source_get_name (grilo_source));
		goto ignore;
	}

	rb_debug ("new grilo source: %s", grl_source_get_name (grilo_source));

	source = rb_grilo_source_new (G_OBJECT (plugin), grilo_source);
	g_hash_table_insert (plugin->sources, g_object_ref (grilo_source), g_object_ref_sink (source));

	/* probably put some sources under 'shared', some under 'stores'? */
	g_object_get (plugin, "object", &shell, NULL);
	rb_shell_append_display_page (shell, RB_DISPLAY_PAGE (source), RB_DISPLAY_PAGE_GROUP_SHARED);
	g_object_unref (shell);

	return;

ignore:
	grl_registry_unregister_source (registry, grilo_source, NULL);
}
void
test_setup_tmdb (void)
{
  GrlConfig *config;
  GrlRegistry *registry;
  GError *error = NULL;

  config = grl_config_new (TMDB_PLUGIN_ID, NULL);
  /* It does not matter what we set this to. It just needs to be non-empty because we're
   * going to fake the network responses. */
  grl_config_set_api_key (config, "TMDB_TEST_API_KEY");

  registry = grl_registry_get_default ();
  grl_registry_add_config (registry, config, &error);
  g_assert_no_error (error);

  grl_registry_load_plugin_by_id (registry, TMDB_PLUGIN_ID, &error);
  g_assert_no_error (error);

  source = GRL_SOURCE (grl_registry_lookup_source (registry, TMDB_PLUGIN_ID));
  g_assert (source != NULL);

  g_assert (grl_source_supported_operations (source) & GRL_OP_RESOLVE);
}
static void
rb_grilo_source_constructed (GObject *object)
{
	RBGriloSource *source;
	RBShell *shell;
	RBShellPlayer *shell_player;
	const GList *source_keys;
	GtkTreeViewColumn *column;
	GtkCellRenderer *renderer;
	GtkTreeSelection *selection;
	GtkWidget *scrolled;
	GtkWidget *browserbox;
	GtkWidget *vbox;
	GtkWidget *mainbox;
	GtkAdjustment *adjustment;

	RB_CHAIN_GOBJECT_METHOD (rb_grilo_source_parent_class, constructed, object);
	source = RB_GRILO_SOURCE (object);

	g_object_get (source, "shell", &shell, NULL);
	g_object_get (shell,
		      "db", &source->priv->db,
		      "shell-player", &shell_player,
		      NULL);
	g_object_unref (shell);

	g_object_get (source, "entry-type", &source->priv->entry_type, NULL);

	source->priv->entry_view = rb_entry_view_new (source->priv->db, G_OBJECT (shell_player), TRUE, FALSE);
	g_object_unref (shell_player);
	g_signal_connect (source->priv->entry_view,
			  "notify::sort-order",
			  G_CALLBACK (notify_sort_order_cb),
			  source);

	source_keys = grl_source_supported_keys (source->priv->grilo_source);

	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_TRACK_NUMBER))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_TRACK_NUMBER, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_TRACK_NUMBER));
	}

	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_TITLE))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_TITLE, TRUE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_TITLE));
	}

	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_GENRE))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_GENRE, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_GENRE));
	}
	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_ARTIST))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_ARTIST, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_ARTIST));
	}
	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_ALBUM))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_ALBUM, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_ALBUM));
	}
	/*
	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_DATE))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_YEAR, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_DATE));
	}
	*/
	if (g_list_find ((GList *)source_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_DURATION))) {
		rb_entry_view_append_column (source->priv->entry_view, RB_ENTRY_VIEW_COL_DURATION, FALSE);
		source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys,
							   GUINT_TO_POINTER(GRL_METADATA_KEY_DURATION));
	}

	source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_CHILDCOUNT));
	source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_URL));
	source->priv->grilo_keys = g_list_prepend (source->priv->grilo_keys, GUINT_TO_POINTER(GRL_METADATA_KEY_THUMBNAIL));

	/* probably add an image column too? */
	source->priv->browser_model = gtk_tree_store_new (4, GRL_TYPE_MEDIA, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
	source->priv->browser_view = gtk_tree_view_new ();
	gtk_tree_view_set_model (GTK_TREE_VIEW (source->priv->browser_view), GTK_TREE_MODEL (source->priv->browser_model));

	column = gtk_tree_view_column_new ();
	renderer = gtk_cell_renderer_text_new ();
	gtk_tree_view_column_set_title (column, _("Browse"));
	gtk_tree_view_column_pack_start (column, renderer, FALSE);
	gtk_tree_view_column_add_attribute (column, renderer, "text", 1);
	gtk_tree_view_column_set_expand (column, TRUE);
	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);

	gtk_tree_view_append_column (GTK_TREE_VIEW (source->priv->browser_view), column);
	gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (source->priv->browser_view), TRUE);
	gtk_tree_view_set_expander_column (GTK_TREE_VIEW (source->priv->browser_view), column);
	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (source->priv->browser_view), TRUE);
	gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (source->priv->browser_view), TRUE);

	g_signal_connect (source->priv->browser_view, "row-expanded", G_CALLBACK (browser_row_expanded_cb), source);
	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (source->priv->browser_view));
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);	/* should be multiple eventually */
	g_signal_connect (selection, "changed", G_CALLBACK (browser_selection_changed_cb), source);

	scrolled = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN);
	adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled));
	g_signal_connect (adjustment, "changed", G_CALLBACK (scroll_adjust_changed_cb), source);
	g_signal_connect (adjustment, "value-changed", G_CALLBACK (scroll_adjust_value_changed_cb), source);

	browserbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);

	/* search bar (if the source supports searching) */
	if (grl_source_supported_operations (source->priv->grilo_source) & GRL_OP_SEARCH) {
		source->priv->search_entry = rb_search_entry_new (FALSE);
		g_object_set (source->priv->search_entry, "explicit-mode", TRUE, NULL);
		g_signal_connect (source->priv->search_entry, "search", G_CALLBACK (search_cb), source);
		g_signal_connect (source->priv->search_entry, "activate", G_CALLBACK (search_cb), source);
		gtk_box_pack_start (GTK_BOX (browserbox), GTK_WIDGET (source->priv->search_entry), FALSE, FALSE, 6);
	}
	gtk_container_add (GTK_CONTAINER (scrolled), source->priv->browser_view);
	gtk_box_pack_start (GTK_BOX (browserbox), scrolled, TRUE, TRUE, 0);

	mainbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
	gtk_box_pack_start (GTK_BOX (source), mainbox, TRUE, TRUE, 0);

	/* info bar */
	source->priv->info_bar_label = gtk_label_new ("");
	source->priv->info_bar = gtk_info_bar_new ();
	gtk_info_bar_set_message_type (GTK_INFO_BAR (source->priv->info_bar), GTK_MESSAGE_INFO);
	gtk_info_bar_add_button (GTK_INFO_BAR (source->priv->info_bar), _("Fetch more tracks"), GTK_RESPONSE_OK);
	gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (source->priv->info_bar))),
			   source->priv->info_bar_label);
	gtk_widget_show (GTK_WIDGET (source->priv->info_bar_label));
	gtk_widget_set_no_show_all (GTK_WIDGET (source->priv->info_bar), TRUE);
	g_signal_connect (source->priv->info_bar, "response", G_CALLBACK (fetch_more_cb), source);

	/* don't allow the browser to be hidden? */
	source->priv->paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
	rb_source_bind_settings (RB_SOURCE (source), GTK_WIDGET (source->priv->entry_view), source->priv->paned, NULL);
	gtk_paned_pack1 (GTK_PANED (source->priv->paned), browserbox, FALSE, FALSE);

	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
	gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (source->priv->entry_view), TRUE, TRUE, 0);
	gtk_box_pack_start (GTK_BOX (vbox), source->priv->info_bar, FALSE, FALSE, 0);
	gtk_paned_pack2 (GTK_PANED (source->priv->paned), vbox, TRUE, FALSE);

	gtk_box_pack_start (GTK_BOX (mainbox), source->priv->paned, TRUE, TRUE, 0);

	gtk_widget_show_all (GTK_WIDGET (source));
}
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 ();
}
/* Callback invoked whenever a new source comes up */
static void
source_added_cb (GrlRegistry *registry,
                 GrlSource *source,
                 gpointer user_data)
{
  GrlSupportedOps supported_ops;
  MS2Server *server;
  const gchar *source_name;
  gchar *sanitized_source_id;
  gchar *source_id;

  /* Only sources that implement browse and resolve are of interest */
  supported_ops =
    grl_source_supported_operations (source);
  if (supported_ops & GRL_OP_BROWSE &&
      supported_ops & GRL_OP_RESOLVE) {

    source_id =
      (gchar *) grl_source_get_id (source);

    /* Check if there is already another provider with the same name */
    if (!dups) {
      source_name =
        grl_source_get_name (source);
      if (g_list_find_custom (providers_names,
                              source_name,
                              (GCompareFunc) g_strcmp0)) {
        g_debug ("Skipping %s [%s] source", source_id, source_name);
        return;
      }
    }

    /* Register a new service name */
    sanitized_source_id = g_strdup (source_id);

    g_debug ("Registering %s [%s] source", sanitized_source_id, source_name);

    sanitize (sanitized_source_id);

    server = ms2_server_new (sanitized_source_id, source);

    if (!server) {
      g_warning ("Cannot register %s", sanitized_source_id);
      g_free (sanitized_source_id);
    } else {
      ms2_server_set_get_properties_func (server, get_properties_cb);
      ms2_server_set_list_children_func (server, list_children_cb);
      /* Add search  */
      if (supported_ops & GRL_OP_SEARCH) {
        ms2_server_set_search_objects_func (server, search_objects_cb);
      }
      /* Save reference */
      if (!dups) {
        providers_names = g_list_prepend (providers_names,
                                          g_strdup(source_name));
      }
      g_hash_table_insert (servers, sanitized_source_id, server);
    }
  } else {
    g_debug ("%s source does not support either browse or resolve",
             grl_source_get_id (source));
  }
}
static void
fill_other_properties_table (MS2Server *server,
                             GrlSource *source,
                             GHashTable *properties_table,
                             GList *keys,
                             GrlMedia *media)
{
  GList *key;
  gint childcount;

  /* Compute childcount */
  if (grl_media_is_container (media)) {
    childcount = grl_media_get_childcount (media);
    if (childcount == GRL_METADATA_KEY_CHILDCOUNT_UNKNOWN) {
      childcount = G_MAXINT;
    }
  } else {
    childcount = 0;
  }

  for (key = keys; key; key = g_list_next (key)) {
    if (g_strcmp0 (key->data, MS2_PROP_TYPE) == 0) {
      if (grl_media_is_container (media)) {
        ms2_server_set_item_type (server,
                                  properties_table,
                                  MS2_ITEM_TYPE_CONTAINER);
      } else if (grl_media_is_image (media)) {
        ms2_server_set_item_type (server,
                                  properties_table,
                                  MS2_ITEM_TYPE_IMAGE);
      } else if (grl_media_is_audio (media)) {
        ms2_server_set_item_type (server,
                                  properties_table,
                                  MS2_ITEM_TYPE_AUDIO);
      } else if (grl_media_is_video (media)) {
        ms2_server_set_item_type (server,
                                  properties_table,
                                  MS2_ITEM_TYPE_VIDEO);
      } else {
        ms2_server_set_item_type (server,
                                  properties_table,
                                  MS2_ITEM_TYPE_UNKNOWN);
      }
    } else if (g_strcmp0 (key->data, MS2_PROP_CHILD_COUNT) == 0) {
      ms2_server_set_child_count (server, properties_table, childcount);
    } else if (g_strcmp0 (key->data, MS2_PROP_ITEM_COUNT) == 0) {
      ms2_server_set_item_count (server, properties_table, childcount);
    } else if (g_strcmp0 (key->data, MS2_PROP_CONTAINER_COUNT) == 0) {
      ms2_server_set_container_count (server, properties_table, childcount);
    } else if (g_strcmp0 (key->data, MS2_PROP_SEARCHABLE) == 0) {
      /* Only supports search in the root level */
      if (grl_media_get_id (media) == NULL &&
          grl_source_supported_operations (source) & GRL_OP_SEARCH) {
        ms2_server_set_searchable (server,
                                   properties_table,
                                   TRUE);
      } else {
        ms2_server_set_searchable (server,
                                   properties_table,
                                   FALSE);
      }
    }
  }
}