static void
resolve_image (ResolveData         *resolve_data,
               resolution_flags_t   flags)
{
  GFile *file;
  GCancellable *cancellable;

  GRL_DEBUG ("resolve_image");

  resolve_data_start_operation (resolve_data, "image");

  if (flags & FLAG_THUMBNAIL) {
    const gchar *attributes;

    file = g_file_new_for_uri (grl_media_get_url (resolve_data->rs->media));

    cancellable = resolve_data_ensure_cancellable (resolve_data);

#if GLIB_CHECK_VERSION (2, 39, 0)
    attributes = G_FILE_ATTRIBUTE_THUMBNAIL_PATH "," \
                 G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID;
#else
    attributes = G_FILE_ATTRIBUTE_THUMBNAIL_PATH;
#endif

    g_file_query_info_async (file, attributes,
                             G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, cancellable,
                             (GAsyncReadyCallback)got_file_info, resolve_data);
    g_object_unref (file);
  } else {
    resolve_data_finish_operation (resolve_data, "image", NULL);
  }
}
static gboolean
has_compatible_media_url (GrlMedia *media)
{
  gboolean ret = FALSE;
  const gchar *url;
  gchar *scheme;

  /* HACK: Cheat slightly, we don't want to use UPnP URLs */
  if (grl_data_has_key (GRL_DATA (media), GRL_METADATA_KEY_SOURCE)) {
    const char *source;

    source = grl_data_get_string (GRL_DATA (media), GRL_METADATA_KEY_SOURCE);

    if (g_str_has_prefix (source, "grl-upnp-uuid:"))
      return FALSE;
    if (g_str_has_prefix (source, "grl-dleyna-uuid:"))
      return FALSE;
  }

  url = grl_media_get_url (media);
  if (!url) {
    return FALSE;
  }
  scheme = g_uri_parse_scheme (url);

  ret = is_supported_scheme (scheme);

  g_free (scheme);

  return ret;
}
static void
parsed_finished (TotemPlParser *pl, GAsyncResult *result, BrowseData *data)
{
  TotemPlParserResult retval;
  GError *error = NULL;

  retval = totem_pl_parser_parse_finish (TOTEM_PL_PARSER (pl), result, &error);

  /* Do the fallback ourselves */
  if (retval == TOTEM_PL_PARSER_RESULT_IGNORED) {
    grl_media_set_url (data->media, grl_media_get_id (data->media));
    retval = TOTEM_PL_PARSER_RESULT_SUCCESS;
  }

  if (retval == TOTEM_PL_PARSER_RESULT_SUCCESS &&
      grl_media_get_url (data->media) != NULL) {
    data->bs->callback (data->bs->source,
                        data->bs->operation_id,
                        data->media,
                        -1,
                        data->bs->user_data,
                        NULL);
  } else {
    if (retval == TOTEM_PL_PARSER_RESULT_ERROR) {
      GRL_WARNING ("Failed to parse '%s': %s",
                   grl_media_get_id (data->media),
                   error->message);
      g_error_free (error);
    }
    g_object_unref (data->media);
  }
  data->media = NULL;

  resolve_disc_urls (data);
}
Example #4
0
static void
grl_vimeo_source_resolve (GrlSource *source,
                          GrlSourceResolveSpec *rs)
{
  gint id;
  const gchar *id_str;

  if (!rs->media || (id_str = grl_media_get_id (rs->media)) == NULL) {
    goto send_unchanged;
  }

  /* As all the keys are added always, except URL, the only case is missing URL */
  if (g_list_find (rs->keys, GRLKEYID_TO_POINTER (GRL_METADATA_KEY_URL)) != NULL &&
      grl_media_get_url (rs->media) == NULL) {
    errno = 0;
    id = (gint) g_ascii_strtod (id_str, NULL);
    if (errno != 0) {
      goto send_unchanged;
    }

    g_vimeo_video_get_play_url (GRL_VIMEO_SOURCE (source)->priv->vimeo,
                                id,
                                video_get_play_url_cb,
                                rs);
  } else {
    goto send_unchanged;
  }

  return;

 send_unchanged:
  rs->callback (rs->source, rs->operation_id, rs->media, rs->user_data, NULL);
}
static void
parsed_finished (TotemPlParser *pl, GAsyncResult *result, BrowseData *data)
{
  TotemPlParserResult retval;
  GError *error = NULL;

  retval = totem_pl_parser_parse_finish (TOTEM_PL_PARSER (pl), result, &error);

  /* Do the fallback ourselves */
  if (retval == TOTEM_PL_PARSER_RESULT_IGNORED) {
    GRL_DEBUG ("%s: Falling back for %s as has it's been ignored", __FUNCTION__,
               grl_media_get_id (data->media));
    grl_media_set_url (data->media, grl_media_get_id (data->media));
    retval = TOTEM_PL_PARSER_RESULT_SUCCESS;
  }

  if (retval == TOTEM_PL_PARSER_RESULT_SUCCESS &&
      grl_media_get_url (data->media) != NULL) {
    GrlOpticalMediaSource *source;

    source = GRL_OPTICAL_MEDIA_SOURCE (data->bs->source);

    GRL_DEBUG ("%s: Adding %s which resolved to %s", __FUNCTION__,
               grl_media_get_id (data->media),
               grl_media_get_url (data->media));
    data->bs->callback (GRL_SOURCE (source),
                        data->bs->operation_id,
                        data->media,
                        -1,
                        data->bs->user_data,
                        NULL);
    source->priv->list = g_list_append (source->priv->list, g_object_ref (data->media));
  } else {
    if (retval == TOTEM_PL_PARSER_RESULT_ERROR ||
        retval == TOTEM_PL_PARSER_RESULT_CANCELLED) {
      GRL_WARNING ("Failed to parse '%s': %s",
                   grl_media_get_id (data->media),
                   error ? error->message : "No reason");
      g_error_free (error);
    }
    g_object_unref (data->media);
  }
  data->media = NULL;

  resolve_disc_urls (data);
}
static void
entry_parsed_cb (TotemPlParser *parser,
                 const char    *uri,
                 GHashTable    *metadata,
                 BrowseData    *data)
{
  g_return_if_fail (data->media != NULL);
  if (grl_media_get_url (data->media) != NULL) {
    GRL_WARNING ("Was going to set media '%s' to URL '%s' but already has URL '%s'",
                 grl_media_get_id (data->media),
                 uri,
                 grl_media_get_url (data->media));
    return;
  }

  grl_media_set_url (data->media, uri);
}
Example #7
0
/*
 * If we need to, generate a thumbnail.
 *
 * If the URL is not file:/// then we assume it's okay to use.
 *
 */
static void
mex_grilo_program_thumbnail (MexContent *content, GrlMedia *media)
{
  const char *url;
  char *thumb_path;

  /* If the media isn't local, then we'll ignore it for now */
  url = grl_media_get_url (media);
  if (url == NULL || !g_str_has_prefix (url, "file:///"))
    return;

  if (GRL_IS_MEDIA_BOX (media))
    {
      gchar *tmp;

      tmp = g_build_filename (mex_get_data_dir (), "common", "folder-tile.png",
                              NULL);
      mex_grilo_program_set_metadata (content, MEX_CONTENT_METADATA_STILL, tmp);
      g_free (tmp);
      return;
    }

  /*
   * If we're already got a thumbnail, see if we're happy with it or want to
   * ignore it.
   */
  thumb_path = (char*)mex_content_get_metadata (content,
                                                MEX_CONTENT_METADATA_STILL);
  if (thumb_path) {
    /* If the thumbnail is already a good one, we're done */
    if (thumb_path && strstr (thumb_path, "/.thumbnails/x-huge/"))
      return;

    /*
     * If the thumbnail currently set is a "normal" thumbnail we ignore it on the
     * basis that it's likely to have been generated by Totem, and thus is bad.
     * If your platform doesn't have Totem then this can be removed!
     */
    if (thumb_path && strstr (thumb_path, "/.thumbnails/normal/"))
      mex_grilo_program_set_metadata (content, MEX_CONTENT_METADATA_STILL, NULL);
  }

  /*
   * Now see if we've a thumbnail generated already.  TODO: use the Tumbler API
   * to do this.
   */
  thumb_path = get_thumbnail_path_for_uri (url);
  if (g_file_test (thumb_path, G_FILE_TEST_EXISTS)) {
    gchar *thumb_uri = g_filename_to_uri (thumb_path, NULL, NULL);
    mex_grilo_program_set_metadata (content, MEX_CONTENT_METADATA_STILL,
                                    thumb_uri);
    g_free (thumb_uri);
  } else {
    mex_thumbnailer_generate (url, grl_media_get_mime (media),
                              thumbnail_cb, content);
  }
  g_free (thumb_path);
}
static void
media_found_cb (BgPicturesSource *self, GrlMedia *media)
{
  GFile *file = NULL;
  const gchar *uri;

  uri = grl_media_get_url (media);
  file = g_file_new_for_uri (uri);
  g_object_set_data_full (G_OBJECT (file), "grl-media", g_object_ref (media), g_object_unref);
  add_single_file_from_media (self, file, media);
}
static void
entry_parsed_cb (TotemPlParser  *parser,
                 const char     *uri,
                 GHashTable     *metadata,
                 GrlMedia      **media)
{
  char *scheme;

  g_return_if_fail (*media != NULL);
  if (grl_media_get_url (*media) != NULL) {
    GRL_WARNING ("Was going to set media '%s' to URL '%s' but already has URL '%s'",
                 grl_media_get_id (*media),
                 uri,
                 grl_media_get_url (*media));
    return;
  }

  scheme = g_uri_parse_scheme (uri);
  if (scheme != NULL && !g_str_equal (scheme, "file"))
    grl_media_set_url (*media, uri);
  g_free (scheme);
}
static void
parsed_finished_item (TotemPlParser         *pl,
                      GAsyncResult          *result,
                      GrlOpticalMediaSource *source)
{
  GrlMedia **media;
  TotemPlParserResult retval;

  media = g_object_get_data (G_OBJECT (pl), "media");
  retval = totem_pl_parser_parse_finish (TOTEM_PL_PARSER (pl), result, NULL);
  if (retval == TOTEM_PL_PARSER_RESULT_SUCCESS &&
      grl_media_get_url (*media) != NULL) {
    source->priv->list = g_list_append (source->priv->list, g_object_ref (*media));
    if (source->priv->notify_changes) {
      grl_source_notify_change (GRL_SOURCE (source), *media, GRL_CONTENT_ADDED, FALSE);
    }
  }

  g_object_unref (*media);
  g_object_unref (pl);
}
Example #11
0
static void
mex_grilo_program_get_stream_cb (GrlMediaSource *source,
                                 guint           operation_id,
                                 GrlMedia       *media,
                                 gpointer        userdata,
                                 const GError   *error)
{
  MexGriloProgramClosure *closure = userdata;
  MexContent *content = MEX_CONTENT (closure->self);
  const gchar *url = grl_media_get_url (media);

  MEX_CONTENT_IFACE (mex_grilo_program_parent_class)->set_metadata (content,
                                                                    MEX_CONTENT_METADATA_STREAM,
                                                                    url);

  closure->reply (MEX_PROGRAM (content),
                  url, error, closure->userdata);

  g_object_unref (content);
  g_object_unref (source);
  g_slice_free (MexGriloProgramClosure, closure);
}
Example #12
0
static void
element_browser (gpointer data,
                 gpointer user_data)
{
  GrlMedia *media = GRL_MEDIA (data);
  GrlSource *source = GRL_SOURCE (user_data);

  /* 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) {
    g_debug ("Media element is NULL!");
    goto out;
  }

  const gchar *title = grl_media_get_title (media);

  /* If the media is a container, that means we will browse it again */
  if (grl_media_is_container (media)) {
    guint childcount = grl_media_get_childcount (media);
    g_debug ("\t Got '%s' (container with %d elements)", title, childcount);

    source_browser (source, media);
  } else {
    const gchar *url = grl_media_get_url (media);
    const gchar *mime = grl_media_get_mime (media);
    GDateTime *date = grl_media_get_modification_date (media);
    time_t rawdate = g_date_time_to_unix(date);
    g_printf ("\t Got '%s', of type '%s', ctime is '%s'\n", title, mime, ctime(&rawdate));
    g_printf ("\t\t URL: %s\n", url);
  }

out:
  g_object_unref (media);
}
static void
grl_local_metadata_source_resolve (GrlSource *source,
                                   GrlSourceResolveSpec *rs)
{
  GError *error = NULL;
  resolution_flags_t flags;
  GrlLocalMetadataSourcePriv *priv =
    GRL_LOCAL_METADATA_SOURCE_GET_PRIVATE (source);
  gboolean can_access;
  ResolveData *data = NULL;

  GRL_DEBUG (__FUNCTION__);

  /* Wrap the whole resolve operation in a GTask, as there are various async
   * components which need to run in parallel. */
  data = g_slice_new0 (ResolveData);
  data->source = g_object_ref (source);
  data->rs = rs;
  data->n_pending_operations = 1;  /* to track the initial checks */

  /* Can we access the media through gvfs? */
  can_access = has_compatible_media_url (rs->media);

  flags = get_resolution_flags (rs->keys, priv);
  if (grl_data_get_boolean (GRL_DATA (rs->media), GRL_METADATA_KEY_TITLE_FROM_FILENAME))
    flags |= FLAG_VIDEO_TITLE;

   if (!flags)
     error = g_error_new_literal (GRL_CORE_ERROR,
                                  GRL_CORE_ERROR_RESOLVE_FAILED,
                                  _("Cannot resolve any of the given keys"));
   if (GRL_IS_MEDIA_IMAGE (rs->media) && can_access == FALSE)
     error = g_error_new_literal (GRL_CORE_ERROR,
                                  GRL_CORE_ERROR_RESOLVE_FAILED,
                                  _("A GIO supported URL for images is required"));

  if (error) {
    /* No can do! */
    resolve_data_finish_operation (data, "root", error);
    g_error_free (error);
    return;
  }

  GRL_DEBUG ("\ttrying to resolve for: %s", grl_media_get_url (rs->media));

  if (GRL_IS_MEDIA_VIDEO (rs->media)) {
    if (priv->guess_video)
      resolve_video (data, can_access ? GRL_METADATA_KEY_URL : GRL_METADATA_KEY_TITLE, flags);
    if (can_access)
      resolve_image (data, flags);
  } else if (GRL_IS_MEDIA_IMAGE (rs->media)) {
    resolve_image (data, flags);
  } else if (GRL_IS_MEDIA_AUDIO (rs->media)) {
    /* Try for a per-track thumbnail first; we'll fall back to album art
     * if the track doesn't have one */
    resolve_image (data, flags);
  }

  /* Finish the overall operation (this might not call the callback if there
   * are still some sub-operations pending). */
  resolve_data_finish_operation (data, "root", NULL);
}
Example #14
0
static void
store_bookmark (GrlBookmarksSource *bookmarks_source,
                GList **keylist,
                GrlMediaBox *parent,
                GrlMedia *bookmark,
                GError **error)
{
  GomResource *resource;
  const gchar *title;
  const gchar *url;
  const gchar *desc;
  const gchar *thumb;
  GTimeVal now;
  gint64 parent_id;
  const gchar *mime;
  gchar *date;
  guint type;
  gint64 id;
  gchar *str_id;
  GError *local_error = NULL;
  gboolean ret;

  GRL_DEBUG ("store_bookmark");

  title = grl_media_get_title (bookmark);
  url = grl_media_get_url (bookmark);
  thumb = grl_media_get_thumbnail (bookmark);
  desc = grl_media_get_description (bookmark);
  mime = grl_media_get_mime (bookmark);
  g_get_current_time (&now);
  date = g_time_val_to_iso8601 (&now);

  if (!parent) {
    parent_id = 0;
  } else {
    parent_id = g_ascii_strtoll (grl_media_get_id (GRL_MEDIA (parent)), NULL, 0);
  }
  if (parent_id < 0) {
    parent_id = 0;
  }

  GRL_DEBUG ("URL: '%s'", url);

  if (GRL_IS_MEDIA_BOX (bookmark)) {
    type = BOOKMARK_TYPE_CATEGORY;
  } else {
    type = BOOKMARK_TYPE_STREAM;
  }

  resource = g_object_new (BOOKMARKS_TYPE_RESOURCE,
                           "repository", bookmarks_source->priv->repository,
                           "parent", parent_id,
                           "type", type,
                           NULL);

  if (type == BOOKMARK_TYPE_STREAM) {
    g_object_set (G_OBJECT (resource), "url", url, NULL);
    *keylist = g_list_remove (*keylist,
                              GRLKEYID_TO_POINTER (GRL_METADATA_KEY_URL));
  }
  if (title) {
    g_object_set (G_OBJECT (resource), "title", title, NULL);
    *keylist = g_list_remove (*keylist,
                              GRLKEYID_TO_POINTER (GRL_METADATA_KEY_TITLE));
  } else if (url) {
    g_object_set (G_OBJECT (resource), "title", url, NULL);
  } else {
    g_object_set (G_OBJECT (resource), "title", "(unknown)", NULL);
  }
  if (date) {
    g_object_set (G_OBJECT (resource), "date", date, NULL);
  }
  if (mime) {
    g_object_set (G_OBJECT (resource), "mime", mime, NULL);
    *keylist = g_list_remove (*keylist,
                              GRLKEYID_TO_POINTER (GRL_METADATA_KEY_MIME));
  }
  if (desc) {
    g_object_set (G_OBJECT (resource), "desc", desc, NULL);
    *keylist = g_list_remove (*keylist,
                              GRLKEYID_TO_POINTER (GRL_METADATA_KEY_DESCRIPTION));
  }
  if (thumb) {
    g_object_set (G_OBJECT (resource), "thumbnail-url", desc, NULL);
    *keylist = g_list_remove (*keylist,
                              GRLKEYID_TO_POINTER (GRL_METADATA_KEY_THUMBNAIL));
  }

  ret = gom_resource_save_sync (resource, &local_error);
  if (!ret) {
    GRL_WARNING ("Failed to store bookmark '%s': %s", title,
                 local_error->message);
    *error = g_error_new (GRL_CORE_ERROR,
                          GRL_CORE_ERROR_STORE_FAILED,
                          _("Failed to store: %s"),
                          local_error->message);
    g_error_free (local_error);
    g_object_unref (resource);
    return;
  }

  g_object_get (resource, "id", &id, NULL);
  str_id = g_strdup_printf ("%" G_GINT64_FORMAT, id);
  grl_media_set_id (bookmark, str_id);
  g_free (str_id);

  g_object_unref (resource);

  if (bookmarks_source->priv->notify_changes) {
    grl_source_notify_change (GRL_SOURCE (bookmarks_source),
                              bookmark,
                              GRL_CONTENT_ADDED,
                              FALSE);
  }
}
static void
got_file_info (GFile *file,
               GAsyncResult *result,
               gpointer user_data)
{
  GCancellable *cancellable;
  GFileInfo *info;
  GError *error = NULL;
  const gchar *thumbnail_path;
  gboolean thumbnail_is_valid;
  GrlLocalMetadataSourcePriv *priv;
  ResolveData *resolve_data = user_data;
  GrlSourceResolveSpec *rs = resolve_data->rs;
  resolution_flags_t flags;

  GRL_DEBUG ("got_file_info");

  priv = GRL_LOCAL_METADATA_SOURCE_GET_PRIVATE (resolve_data->source);

  cancellable = resolve_data_ensure_cancellable (resolve_data);

  info = g_file_query_info_finish (file, result, &error);
  if (error)
    goto error;

  thumbnail_path =
      g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
#if GLIB_CHECK_VERSION (2, 39, 0)
  thumbnail_is_valid =
      g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID);
#else
  thumbnail_is_valid = TRUE;
#endif


  if (thumbnail_path && thumbnail_is_valid) {
    gchar *thumbnail_uri = g_filename_to_uri (thumbnail_path, NULL, &error);
    if (error)
      goto error;

    GRL_INFO ("Got thumbnail %s for media: %s", thumbnail_uri,
              grl_media_get_url (rs->media));
    grl_media_set_thumbnail (rs->media, thumbnail_uri);
    g_free (thumbnail_uri);
  } else if (thumbnail_path && !thumbnail_is_valid) {
    GRL_INFO ("Found outdated thumbnail %s for media: %s", thumbnail_path,
              grl_media_get_url (rs->media));
  } else {
    GRL_INFO ("Could not find thumbnail for media: %s",
              grl_media_get_url (rs->media));
  }

  flags = get_resolution_flags (rs->keys, priv);

  if (GRL_IS_MEDIA_AUDIO (rs->media) &&
      !(thumbnail_path && thumbnail_is_valid)) {
    /* We couldn't get a per-track thumbnail; try for a per-album one,
     * using libmediaart */
    resolve_album_art (resolve_data, flags);
  }

  if (flags & FLAG_GIBEST_HASH) {
    extract_gibest_hash_async (resolve_data, file, cancellable);
  } else {
    resolve_data_finish_operation (resolve_data, "image", NULL);
  }

  goto exit;

error:
    {
      GError *new_error = g_error_new (GRL_CORE_ERROR,
                                       GRL_CORE_ERROR_RESOLVE_FAILED,
                                       _("Failed to resolve: %s"),
                                       error->message);
      resolve_data_finish_operation (resolve_data, "image", new_error);

      g_error_free (error);
      g_error_free (new_error);
    }

exit:
    g_clear_object (&info);
}
static void
resolve_video (ResolveData         *resolve_data,
               GrlKeyID             key,
               resolution_flags_t   flags)
{
  gchar *title, *showname, *display_name;
  GDateTime *date;
  gint season, episode;
  GrlData *data = GRL_DATA (resolve_data->rs->media);
  resolution_flags_t miss_flags = 0, fill_flags;

  GRL_DEBUG ("%s",__FUNCTION__);

  resolve_data_start_operation (resolve_data, "video");

  if (!(flags & (FLAG_VIDEO_TITLE |
                 FLAG_VIDEO_SHOWNAME |
                 FLAG_VIDEO_DATE |
                 FLAG_VIDEO_SEASON |
                 FLAG_VIDEO_EPISODE |
                 FLAG_VIDEO_EPISODE_TITLE))) {
    resolve_data_finish_operation (resolve_data, "video", NULL);
    return;
  }

  if (grl_data_has_key (data, GRL_METADATA_KEY_TITLE)) {
    if (grl_data_get_boolean (data, GRL_METADATA_KEY_TITLE_FROM_FILENAME)) {
      miss_flags = FLAG_VIDEO_TITLE;
    } else
      miss_flags = 0;
  } else {
    miss_flags = FLAG_VIDEO_TITLE;
  }
  miss_flags |= grl_data_has_key (data, GRL_METADATA_KEY_SHOW) ?
    0 : FLAG_VIDEO_SHOWNAME;
  miss_flags |= grl_data_has_key (data, GRL_METADATA_KEY_PUBLICATION_DATE) ?
    0 : FLAG_VIDEO_DATE;
  miss_flags |= grl_data_has_key (data, GRL_METADATA_KEY_SEASON) ?
    0 : FLAG_VIDEO_SEASON;
  miss_flags |= grl_data_has_key (data, GRL_METADATA_KEY_EPISODE) ?
    0 : FLAG_VIDEO_EPISODE;
  miss_flags |= grl_data_has_key (data, GRL_METADATA_KEY_EPISODE_TITLE) ?
    0 : FLAG_VIDEO_EPISODE_TITLE;

  fill_flags = flags & miss_flags;

  if (!fill_flags) {
    resolve_data_finish_operation (resolve_data, "video", NULL);
    return;
  }

  if (key == GRL_METADATA_KEY_URL) {
    GFile *file;

    file = g_file_new_for_uri (grl_media_get_url (resolve_data->rs->media));
    display_name = g_file_get_basename (file);
    g_object_unref (file);
  } else {
    display_name = g_strdup (grl_media_get_title (resolve_data->rs->media));
  }

  video_guess_values_from_display_name (display_name,
                                        &title, &showname, &date,
                                        &season, &episode);

  g_free (display_name);

  GRL_DEBUG ("\tfound title=%s/showname=%s/year=%i/season=%i/episode=%i",
             title, showname,
             date != NULL ? g_date_time_get_year (date) : 0,
             season, episode);

  if (showname) {
    if (fill_flags & FLAG_VIDEO_SHOWNAME) {
      grl_data_set_string (data, GRL_METADATA_KEY_SHOW, showname);
    }
    g_free (showname);

    if (fill_flags & FLAG_VIDEO_EPISODE_TITLE &&
        title != NULL) {
      grl_data_set_string (data, GRL_METADATA_KEY_EPISODE_TITLE, title);
    }
  } else {
    /* As this is just a guess, don't erase already provided values,
     * unless GRL_METADATA_KEY_TITLE_FROM_FILENAME is set */
    if (grl_data_get_boolean (data, GRL_METADATA_KEY_TITLE_FROM_FILENAME)) {
      if (fill_flags & FLAG_VIDEO_TITLE) {
        grl_data_set_string (data, GRL_METADATA_KEY_TITLE, title);
      }
    }
  }
  g_free (title);

  if (date) {
    if (fill_flags & FLAG_VIDEO_DATE) {
      grl_data_set_boxed (data, GRL_METADATA_KEY_PUBLICATION_DATE, date);
    }
    g_date_time_unref (date);
  }

  if (season && (fill_flags & FLAG_VIDEO_SEASON)) {
    grl_data_set_int (data, GRL_METADATA_KEY_SEASON, season);
  }

  if (episode && (fill_flags & FLAG_VIDEO_EPISODE)) {
    grl_data_set_int (data, GRL_METADATA_KEY_EPISODE, episode);
  }

  resolve_data_finish_operation (resolve_data, "video", NULL);
}
static void
grl_raitv_source_resolve (GrlSource *source,
                          GrlSourceResolveSpec *rs)
{
  gchar *urltarget;
  GrlRaitvSource *self = GRL_RAITV_SOURCE (source);
  RaitvOperation *op;
  RaitvMediaType mediatype;

  GRL_DEBUG ("Starting resolve source: url=%s",grl_media_get_url (rs->media));

  if (!GRL_IS_MEDIA_VIDEO (rs->media) && !GRL_IS_MEDIA_BOX (rs->media)) {
    rs->callback (rs->source, rs->operation_id, rs->media, rs->user_data, NULL);
    return;
  }

  mediatype = classify_media_id (grl_media_get_id (rs->media));
  switch (mediatype) {
  case RAITV_MEDIA_TYPE_ROOT:
    rs->media = produce_container_from_directory (rs->media, NULL, 0, mediatype);
    break;
  case RAITV_MEDIA_TYPE_POPULARS:
    rs->media = produce_container_from_directory (rs->media, root_dir, ROOT_DIR_POPULARS_INDEX, mediatype);
    break;
  case RAITV_MEDIA_TYPE_RECENTS:
    rs->media = produce_container_from_directory (rs->media, root_dir, ROOT_DIR_RECENTS_INDEX, mediatype);
    break;
  case RAITV_MEDIA_TYPE_POPULAR_THEME:
  case RAITV_MEDIA_TYPE_RECENT_THEME:
    rs->media = produce_container_from_directory (rs->media,
                                                  themes_dir,
                                                  get_theme_index_from_id (grl_media_get_id (rs->media)),
                                                  mediatype);
    break;
  case RAITV_MEDIA_TYPE_VIDEO:
    op = g_slice_new0 (RaitvOperation);
    op->source       = g_object_ref (source);
    op->cancellable  = g_cancellable_new ();
    op->operation_id = rs->operation_id;
    op->resolveCb    = rs->callback;
    op->user_data    = rs->user_data;
    op->media	      = rs->media;

    grl_operation_set_data_full (rs->operation_id, op, (GDestroyNotify) raitv_operation_free);

    urltarget = g_strdup_printf ("http://www.rai.tv/dl/RaiTV/programmi/media/%s.html",
                                 grl_media_get_id(rs->media));

    GRL_DEBUG ("Opening '%s'", urltarget);

    grl_net_wc_request_async (self->priv->wc,
                              urltarget,
                              op->cancellable,
                              proxy_call_resolve_grlnet_async_cb,
                              op);

    g_free(urltarget);
    return;
  }
  rs->callback (rs->source, rs->operation_id, rs->media, rs->user_data, NULL);
  return;

  if ( grl_media_get_url (rs->media) != NULL) {
    rs->callback (rs->source, rs->operation_id, rs->media, rs->user_data, NULL);
    return;
  }

  op = g_slice_new0 (RaitvOperation);
  op->source       = g_object_ref (source);
  op->cancellable  = g_cancellable_new ();
  op->operation_id = rs->operation_id;
  op->resolveCb     = rs->callback;
  op->user_data    = rs->user_data;
  op->media	   = rs->media;

  grl_operation_set_data_full (rs->operation_id, op, (GDestroyNotify) raitv_operation_free);

  urltarget = g_strdup_printf("%s/%s.html","http://www.rai.tv/dl/RaiTV/programmi/media",grl_media_get_id(rs->media));

  GRL_DEBUG ("Opening '%s'", urltarget);

  grl_net_wc_request_async (self->priv->wc,
                            urltarget,
                            op->cancellable,
                            proxy_call_resolve_grlnet_async_cb,
                            op);

  g_free(urltarget);
}
static RhythmDBEntry *
create_entry_for_media (RhythmDB *db, RhythmDBEntryType *entry_type, GrlData *data, GrlData *container)
{
	RhythmDBEntry *entry;
	RBGriloEntryData *entry_data;

	entry = rhythmdb_entry_lookup_by_location (db, grl_media_get_url (GRL_MEDIA (data)));
	if (entry != NULL) {
		return entry;
	}

	rb_debug ("creating entry for %s / %s", grl_media_get_url (GRL_MEDIA (data)), grl_media_get_id (GRL_MEDIA (data)));

	entry = rhythmdb_entry_new (db, entry_type, grl_media_get_url (GRL_MEDIA (data)));	/* just use the url? */
	if (entry == NULL) {
		/* crap. */
		return NULL;
	}

	set_string_prop_from_key (db, entry, RHYTHMDB_PROP_TITLE, data, GRL_METADATA_KEY_TITLE);
	set_string_prop_from_key (db, entry, RHYTHMDB_PROP_ALBUM, data, GRL_METADATA_KEY_ALBUM);
	set_string_prop_from_key (db, entry, RHYTHMDB_PROP_ARTIST, data, GRL_METADATA_KEY_ARTIST);
	set_string_prop_from_key (db, entry, RHYTHMDB_PROP_GENRE, data, GRL_METADATA_KEY_GENRE);
	set_string_prop_from_key (db, entry, RHYTHMDB_PROP_TITLE, data, GRL_METADATA_KEY_TITLE);

	if (grl_data_has_key (data, GRL_METADATA_KEY_PUBLICATION_DATE)) {
		/* something - grilo has this as a string? */
	}

	if (grl_data_has_key (data, GRL_METADATA_KEY_BITRATE)) {
		GValue v = {0,};
		g_value_init (&v, G_TYPE_ULONG);
		g_value_set_ulong (&v, grl_data_get_int (data, GRL_METADATA_KEY_BITRATE));
		rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_BITRATE, &v);
		g_value_unset (&v);
	}

	if (grl_data_has_key (data, GRL_METADATA_KEY_DURATION)) {
		/* this is probably in seconds */
		GValue v = {0,};
		g_value_init (&v, G_TYPE_ULONG);
		g_value_set_ulong (&v, grl_data_get_int (data, GRL_METADATA_KEY_DURATION));
		rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_DURATION, &v);
		g_value_unset (&v);
	}

	if (grl_data_has_key (data, GRL_METADATA_KEY_MIME)) {
		const char *media_type;
		media_type = rb_gst_mime_type_to_media_type (grl_data_get_string (data, GRL_METADATA_KEY_MIME));
		if (media_type) {
			GValue v = {0,};
			g_value_init (&v, G_TYPE_STRING);
			g_value_set_string (&v, media_type);
			rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_MEDIA_TYPE, &v);
			g_value_unset (&v);
		}
	}

	if (grl_data_has_key (data, GRL_METADATA_KEY_TRACK_NUMBER)) {
		GValue v = {0,};
		g_value_init (&v, G_TYPE_ULONG);
		g_value_set_ulong (&v, grl_data_get_int (data, GRL_METADATA_KEY_TRACK_NUMBER));
		rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_TRACK_NUMBER, &v);
		g_value_unset (&v);
	}

	/* rating and play count? */

	entry_data = RHYTHMDB_ENTRY_GET_TYPE_DATA (entry, RBGriloEntryData);
	entry_data->grilo_data = g_object_ref (data);
	if (container != NULL) {
		entry_data->grilo_container = g_object_ref (container);
	}

	/* might want to consider batching this */
	rhythmdb_commit (db);

	return entry;
}
static void
fill_properties_table (MS2Server *server,
                       GHashTable *properties_table,
                       GList *keys,
                       GrlMedia *media)
{
  GList *prop;
  GrlKeyID key;
  const gchar *title;
  gchar *id;
  gchar *urls[2] = { 0 };

  for (prop = keys; prop; prop = g_list_next (prop)) {
    key = GRLPOINTER_TO_KEYID (prop->data);
    if (key == GRL_METADATA_KEY_ID ||
        grl_data_has_key (GRL_DATA (media), key)) {
      if (key == GRL_METADATA_KEY_ID) {
        id = serialize_media (media);
        if (id) {
          ms2_server_set_path (server,
                               properties_table,
                               id,
                               grl_media_is_container (media));
          g_free (id);
        }
      } else if (key == GRL_METADATA_KEY_TITLE) {
        /* Ensure we always insert a valid title */
        title = grl_media_get_title (media);
        if (!title) {
          title = "Unknown";
        }
        ms2_server_set_display_name (server,
                                     properties_table,
                                     title);
      } else if (key == GRL_METADATA_KEY_ALBUM) {
        ms2_server_set_album (server,
                              properties_table,
                              grl_data_get_string (GRL_DATA (media),
                                                   GRL_METADATA_KEY_ALBUM));
      } else if (key == GRL_METADATA_KEY_ARTIST) {
        ms2_server_set_artist (server,
                               properties_table,
                               grl_data_get_string (GRL_DATA (media),
                                                    GRL_METADATA_KEY_ARTIST));
      } else if (key == GRL_METADATA_KEY_GENRE) {
        ms2_server_set_genre (server,
                              properties_table,
                              grl_data_get_string (GRL_DATA (media),
                                                   GRL_METADATA_KEY_GENRE));
      } else if (key == GRL_METADATA_KEY_MIME) {
        ms2_server_set_mime_type (server,
                                  properties_table,
                                  grl_media_get_mime (media));
      } else if (key == GRL_METADATA_KEY_URL) {
        urls[0] = (gchar *) grl_media_get_url (media);
        ms2_server_set_urls (server, properties_table, urls);
      } else if (key == GRL_METADATA_KEY_BITRATE) {
        ms2_server_set_bitrate (server,
                                properties_table,
                                grl_data_get_int (GRL_DATA (media),
                                                  GRL_METADATA_KEY_BITRATE));
      } else if (key == GRL_METADATA_KEY_DURATION) {
        ms2_server_set_duration (server,
                                 properties_table,
                                 grl_media_get_duration (media));
      } else if (key == GRL_METADATA_KEY_HEIGHT) {
        ms2_server_set_height (server,
                               properties_table,
                               grl_data_get_int (GRL_DATA (media),
                                                 GRL_METADATA_KEY_HEIGHT));
      } else if (key == GRL_METADATA_KEY_WIDTH) {
        ms2_server_set_width (server,
                              properties_table,
                              grl_data_get_int (GRL_DATA (media),
                                                GRL_METADATA_KEY_WIDTH));
      } else if (key == GRL_METADATA_KEY_GRILO_MS2_PARENT) {
        if (grl_media_get_id (media) == NULL) {
          ms2_server_set_parent (server,
                                 properties_table,
                                 MS2_ROOT);
        } else {
          ms2_server_set_parent (server,
                                 properties_table,
                                 grl_media_get_grilo_ms2_parent (media));
        }
      }
    }
  }
}