Blame src/gom-flickr-miner.c

Packit f01ec2
/*
Packit f01ec2
 * GNOME Online Miners - crawls through your online content
Packit f01ec2
 * Copyright (c) 2013 Red Hat, Inc.
Packit f01ec2
 *
Packit f01ec2
 * This program is free software; you can redistribute it and/or
Packit f01ec2
 * modify it under the terms of the GNU General Public License
Packit f01ec2
 * as published by the Free Software Foundation; either version 2
Packit f01ec2
 * of the License, or (at your option) any later version.
Packit f01ec2
 *
Packit f01ec2
 * This program is distributed in the hope that it will be useful,
Packit f01ec2
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit f01ec2
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit f01ec2
 * GNU General Public License for more details.
Packit f01ec2
 *
Packit f01ec2
 * You should have received a copy of the GNU General Public License
Packit f01ec2
 * along with this program; if not, write to the Free Software
Packit f01ec2
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit f01ec2
 * 02110-1301, USA.
Packit f01ec2
 *
Packit f01ec2
 * Author: Marek Chalupa <mchalupa@redhat.com>
Packit f01ec2
 */
Packit f01ec2
Packit f01ec2
#include "config.h"
Packit f01ec2
Packit f01ec2
#include <goa/goa.h>
Packit f01ec2
#include <grilo.h>
Packit f01ec2
Packit f01ec2
#include "gom-flickr-miner.h"
Packit f01ec2
#include "gom-utils.h"
Packit f01ec2
Packit f01ec2
#define MINER_IDENTIFIER "gd:flickr:miner:3c63f509-23e8-4283-8aed-154bb55ef07b"
Packit f01ec2
Packit f01ec2
G_DEFINE_TYPE (GomFlickrMiner, gom_flickr_miner, GOM_TYPE_MINER)
Packit f01ec2
Packit f01ec2
struct _GomFlickrMinerPrivate {
Packit f01ec2
  GQueue *boxes;
Packit f01ec2
};
Packit f01ec2
Packit f01ec2
typedef enum {
Packit f01ec2
  OP_FETCH_ALL,
Packit f01ec2
  OP_CREATE_HIEARCHY
Packit f01ec2
} OpType;
Packit f01ec2
Packit f01ec2
typedef struct {
Packit f01ec2
  GrlMedia  *media;
Packit f01ec2
  GrlMedia  *parent;
Packit f01ec2
} FlickrEntry;
Packit f01ec2
Packit f01ec2
typedef struct {
Packit f01ec2
  FlickrEntry *parent_entry;
Packit f01ec2
  GCancellable *cancellable;
Packit f01ec2
  GHashTable *previous_resources;
Packit f01ec2
  GMainLoop *loop;
Packit f01ec2
  GomAccountMinerJob *job;
Packit f01ec2
  GrlSource *source;
Packit f01ec2
  TrackerSparqlConnection *connection;
Packit f01ec2
  const gchar *datasource_urn;
Packit f01ec2
  const gchar *source_id;
Packit f01ec2
} SyncData;
Packit f01ec2
Packit f01ec2
static void account_miner_job_browse_container (GomAccountMinerJob *job,
Packit f01ec2
                                                TrackerSparqlConnection *connection,
Packit f01ec2
                                                GHashTable *previous_resources,
Packit f01ec2
                                                const gchar *datasource_urn,
Packit f01ec2
                                                FlickrEntry *entry,
Packit f01ec2
                                                GCancellable *cancellable);
Packit f01ec2
Packit f01ec2
static FlickrEntry *
Packit f01ec2
create_entry (GrlMedia *media, GrlMedia *parent)
Packit f01ec2
{
Packit f01ec2
  FlickrEntry *entry;
Packit f01ec2
Packit f01ec2
  entry = g_slice_new0 (FlickrEntry);
Packit f01ec2
Packit f01ec2
  entry->media  = (media != NULL) ? g_object_ref (media) : NULL;
Packit f01ec2
  entry->parent = (parent != NULL) ? g_object_ref (parent) : NULL;
Packit f01ec2
Packit f01ec2
  return entry;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
free_entry (FlickrEntry *entry)
Packit f01ec2
{
Packit f01ec2
  g_clear_object (&entry->media);
Packit f01ec2
  g_clear_object (&entry->parent);
Packit f01ec2
  g_slice_free (FlickrEntry, entry);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static GrlOperationOptions *
Packit f01ec2
get_grl_options (GrlSource *source)
Packit f01ec2
{
Packit f01ec2
  GrlCaps *caps;
Packit f01ec2
  GrlOperationOptions *opts = NULL;
Packit f01ec2
Packit f01ec2
  caps = grl_source_get_caps (source, GRL_OP_BROWSE);
Packit f01ec2
  opts = grl_operation_options_new (caps);
Packit f01ec2
Packit f01ec2
  g_return_val_if_fail (opts != NULL, NULL);
Packit f01ec2
Packit f01ec2
  grl_operation_options_set_resolution_flags (opts, GRL_RESOLVE_FAST_ONLY);
Packit f01ec2
Packit f01ec2
  return opts;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static gboolean
Packit f01ec2
account_miner_job_process_entry (GomAccountMinerJob *job,
Packit f01ec2
                                 TrackerSparqlConnection *connection,
Packit f01ec2
                                 GHashTable *previous_resources,
Packit f01ec2
                                 const gchar *datasource_urn,
Packit f01ec2
                                 OpType op_type,
Packit f01ec2
                                 FlickrEntry *entry,
Packit f01ec2
                                 GCancellable *cancellable,
Packit f01ec2
                                 GError **error)
Packit f01ec2
{
Packit f01ec2
  GDateTime *created_time, *modification_date;
Packit f01ec2
  gchar *contact_resource;
Packit f01ec2
  gchar *mime;
Packit f01ec2
  gchar *resource = NULL;
Packit f01ec2
  gchar *date, *identifier;
Packit f01ec2
  const gchar *class = NULL, *id;
Packit f01ec2
  const gchar *url;
Packit f01ec2
  gboolean resource_exists, mtime_changed;
Packit f01ec2
  gint64 new_mtime;
Packit f01ec2
Packit f01ec2
  if (op_type == OP_CREATE_HIEARCHY && entry->parent == NULL && !grl_media_is_container (entry->media))
Packit f01ec2
    return TRUE;
Packit f01ec2
Packit f01ec2
  id = grl_media_get_id (entry->media);
Packit f01ec2
  identifier = g_strdup_printf ("%sflickr:%s",
Packit f01ec2
                                grl_media_is_container (entry->media) ?
Packit f01ec2
                                "photos:collection:" : "",
Packit f01ec2
                                id);
Packit f01ec2
Packit f01ec2
  /* remove from the list of the previous resources */
Packit f01ec2
  g_hash_table_remove (previous_resources, identifier);
Packit f01ec2
Packit f01ec2
  if (grl_media_is_container (entry->media))
Packit f01ec2
    class = "nfo:DataContainer";
Packit f01ec2
  else
Packit f01ec2
    class = "nmm:Photo";
Packit f01ec2
Packit f01ec2
  resource = gom_tracker_sparql_connection_ensure_resource
Packit f01ec2
    (connection,
Packit f01ec2
     cancellable, error,
Packit f01ec2
     &resource_exists,
Packit f01ec2
     datasource_urn, identifier,
Packit f01ec2
     "nfo:RemoteDataObject", class, NULL);
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  gom_tracker_update_datasource (connection, datasource_urn,
Packit f01ec2
                                 resource_exists, identifier, resource,
Packit f01ec2
                                 cancellable, error);
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  if (entry->parent != NULL)
Packit f01ec2
    {
Packit f01ec2
      gchar *parent_resource_urn, *parent_identifier;
Packit f01ec2
      const gchar *parent_id;
Packit f01ec2
Packit f01ec2
      parent_identifier = g_strconcat ("photos:collection:flickr:",
Packit f01ec2
                                        grl_media_get_id (entry->parent) , NULL);
Packit f01ec2
      parent_resource_urn = gom_tracker_sparql_connection_ensure_resource
Packit f01ec2
        (connection, cancellable, error,
Packit f01ec2
         NULL,
Packit f01ec2
         datasource_urn, parent_identifier,
Packit f01ec2
         "nfo:RemoteDataObject", "nfo:DataContainer", NULL);
Packit f01ec2
      g_free (parent_identifier);
Packit f01ec2
Packit f01ec2
      if (*error != NULL)
Packit f01ec2
        goto out;
Packit f01ec2
Packit f01ec2
      gom_tracker_sparql_connection_insert_or_replace_triple
Packit f01ec2
        (connection,
Packit f01ec2
         cancellable, error,
Packit f01ec2
         datasource_urn, resource,
Packit f01ec2
         "nie:isPartOf", parent_resource_urn);
Packit f01ec2
      g_free (parent_resource_urn);
Packit f01ec2
Packit f01ec2
      if (*error != NULL)
Packit f01ec2
        goto out;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  gom_tracker_sparql_connection_insert_or_replace_triple
Packit f01ec2
    (connection,
Packit f01ec2
     cancellable, error,
Packit f01ec2
     datasource_urn, resource,
Packit f01ec2
     "nie:title", grl_media_get_title (entry->media));
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  if (op_type == OP_CREATE_HIEARCHY)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  /* only GRL_METADATA_KEY_CREATION_DATE is
Packit f01ec2
   * implemented, GRL_METADATA_KEY_MODIFICATION_DATE is not
Packit f01ec2
   */
Packit f01ec2
  created_time = modification_date = grl_media_get_creation_date (entry->media);
Packit f01ec2
  new_mtime = g_date_time_to_unix (modification_date);
Packit f01ec2
  mtime_changed = gom_tracker_update_mtime (connection, new_mtime,
Packit f01ec2
                                            resource_exists, identifier, resource,
Packit f01ec2
                                            cancellable, error);
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  /* avoid updating the DB if the entry already exists and has not
Packit f01ec2
   * been modified since our last run.
Packit f01ec2
   */
Packit f01ec2
  if (!mtime_changed)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  /* the resource changed - just set all the properties again */
Packit f01ec2
  if (created_time != NULL)
Packit f01ec2
    {
Packit f01ec2
      date = gom_iso8601_from_timestamp (g_date_time_to_unix (created_time));
Packit f01ec2
      gom_tracker_sparql_connection_insert_or_replace_triple
Packit f01ec2
        (connection,
Packit f01ec2
         cancellable, error,
Packit f01ec2
         datasource_urn, resource,
Packit f01ec2
         "nie:contentCreated", date);
Packit f01ec2
      g_free (date);
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  url = grl_media_get_url (entry->media);
Packit f01ec2
  gom_tracker_sparql_connection_insert_or_replace_triple
Packit f01ec2
    (connection,
Packit f01ec2
     cancellable, error,
Packit f01ec2
     datasource_urn, resource,
Packit f01ec2
     "nie:url", url);
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  gom_tracker_sparql_connection_insert_or_replace_triple
Packit f01ec2
    (connection,
Packit f01ec2
     cancellable, error,
Packit f01ec2
     datasource_urn, resource,
Packit f01ec2
     "nie:description", grl_media_get_description (entry->media));
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  mime = g_content_type_guess (url, NULL, 0, NULL);
Packit f01ec2
  if (mime != NULL)
Packit f01ec2
    {
Packit f01ec2
      gom_tracker_sparql_connection_insert_or_replace_triple
Packit f01ec2
        (connection,
Packit f01ec2
         cancellable, error,
Packit f01ec2
         datasource_urn, resource,
Packit f01ec2
         "nie:mimeType", mime);
Packit f01ec2
      g_free (mime);
Packit f01ec2
Packit f01ec2
      if (*error != NULL)
Packit f01ec2
        goto out;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  contact_resource = gom_tracker_utils_ensure_contact_resource
Packit f01ec2
    (connection,
Packit f01ec2
     cancellable, error,
Packit f01ec2
     datasource_urn, grl_media_get_author (entry->media));
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  gom_tracker_sparql_connection_insert_or_replace_triple
Packit f01ec2
    (connection,
Packit f01ec2
     cancellable, error,
Packit f01ec2
     datasource_urn, resource,
Packit f01ec2
     "nco:creator", contact_resource);
Packit f01ec2
  g_free (contact_resource);
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
 out:
Packit f01ec2
  g_free (resource);
Packit f01ec2
  g_free (identifier);
Packit f01ec2
Packit f01ec2
  if (*error != NULL)
Packit f01ec2
    return FALSE;
Packit f01ec2
Packit f01ec2
  return TRUE;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
source_browse_cb (GrlSource *source,
Packit f01ec2
                  guint operation_id,
Packit f01ec2
                  GrlMedia *media,
Packit f01ec2
                  guint remaining,
Packit f01ec2
                  gpointer user_data,
Packit f01ec2
                  const GError *error)
Packit f01ec2
{
Packit f01ec2
  GError *local_error = NULL;
Packit f01ec2
  SyncData *data = (SyncData *) user_data;
Packit f01ec2
  GomFlickrMiner *self = GOM_FLICKR_MINER (data->job->miner);
Packit f01ec2
Packit f01ec2
  if (error != NULL)
Packit f01ec2
    {
Packit f01ec2
      g_warning ("Unable to browse source %p: %s", source, error->message);
Packit f01ec2
      return;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  if (media != NULL)
Packit f01ec2
    {
Packit f01ec2
      FlickrEntry *entry;
Packit f01ec2
Packit f01ec2
      entry = create_entry (media, data->parent_entry->media);
Packit f01ec2
      account_miner_job_process_entry (data->job,
Packit f01ec2
                                       data->connection,
Packit f01ec2
                                       data->previous_resources,
Packit f01ec2
                                       data->datasource_urn,
Packit f01ec2
                                       OP_CREATE_HIEARCHY,
Packit f01ec2
                                       entry,
Packit f01ec2
                                       data->cancellable,
Packit f01ec2
                                       &local_error);
Packit f01ec2
      if (local_error != NULL)
Packit f01ec2
        {
Packit f01ec2
          g_warning ("Unable to process entry %p: %s", media, local_error->message);
Packit f01ec2
          g_error_free (local_error);
Packit f01ec2
        }
Packit f01ec2
Packit f01ec2
      if (grl_media_is_container (media))
Packit f01ec2
        g_queue_push_tail (self->priv->boxes, entry);
Packit f01ec2
      else
Packit f01ec2
        free_entry (entry);
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  if (remaining == 0)
Packit f01ec2
    g_main_loop_quit (data->loop);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
account_miner_job_browse_container (GomAccountMinerJob *job,
Packit f01ec2
                                    TrackerSparqlConnection *connection,
Packit f01ec2
                                    GHashTable *previous_resources,
Packit f01ec2
                                    const gchar *datasource_urn,
Packit f01ec2
                                    FlickrEntry *entry,
Packit f01ec2
                                    GCancellable *cancellable)
Packit f01ec2
{
Packit f01ec2
  GMainContext *context;
Packit f01ec2
  GrlSource *source;
Packit f01ec2
  GrlOperationOptions *opts;
Packit f01ec2
  const GList *keys;
Packit f01ec2
  SyncData data;
Packit f01ec2
Packit f01ec2
  data.cancellable = cancellable;
Packit f01ec2
  data.connection = connection;
Packit f01ec2
  data.datasource_urn = datasource_urn;
Packit f01ec2
  data.parent_entry = entry;
Packit f01ec2
  data.job = job;
Packit f01ec2
  data.previous_resources = previous_resources;
Packit f01ec2
Packit f01ec2
  context = g_main_context_new ();
Packit f01ec2
  g_main_context_push_thread_default (context);
Packit f01ec2
  data.loop = g_main_loop_new (context, FALSE);
Packit f01ec2
Packit f01ec2
  source = GRL_SOURCE (g_hash_table_lookup (data.job->services, "photos"));
Packit f01ec2
Packit f01ec2
  keys = grl_source_supported_keys (source);
Packit f01ec2
  opts = get_grl_options (source);
Packit f01ec2
Packit f01ec2
  grl_source_browse (source,
Packit f01ec2
                     entry->media,
Packit f01ec2
                     keys,
Packit f01ec2
                     opts,
Packit f01ec2
                     source_browse_cb,
Packit f01ec2
                     &data);
Packit f01ec2
  g_main_loop_run (data.loop);
Packit f01ec2
Packit f01ec2
  g_object_unref (opts);
Packit f01ec2
  g_main_loop_unref (data.loop);
Packit f01ec2
  g_main_context_pop_thread_default (context);
Packit f01ec2
  g_main_context_unref (context);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
source_search_cb (GrlSource *source,
Packit f01ec2
                  guint operation_id,
Packit f01ec2
                  GrlMedia *media,
Packit f01ec2
                  guint remaining,
Packit f01ec2
                  gpointer user_data,
Packit f01ec2
                  const GError *error)
Packit f01ec2
{
Packit f01ec2
  GError *local_error = NULL;
Packit f01ec2
  SyncData *data = (SyncData *) user_data;
Packit f01ec2
Packit f01ec2
  if (error != NULL)
Packit f01ec2
    {
Packit f01ec2
      g_warning ("Unable to search source %p: %s", source, error->message);
Packit f01ec2
      return;
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  if (media != NULL)
Packit f01ec2
    {
Packit f01ec2
      FlickrEntry *entry;
Packit f01ec2
Packit f01ec2
      entry = create_entry (media, NULL);
Packit f01ec2
      account_miner_job_process_entry (data->job,
Packit f01ec2
                                       data->connection,
Packit f01ec2
                                       data->previous_resources,
Packit f01ec2
                                       data->datasource_urn,
Packit f01ec2
                                       OP_FETCH_ALL,
Packit f01ec2
                                       entry,
Packit f01ec2
                                       data->cancellable,
Packit f01ec2
                                       &local_error);
Packit f01ec2
      if (local_error != NULL)
Packit f01ec2
        {
Packit f01ec2
          g_warning ("Unable to process entry %p: %s", media, local_error->message);
Packit f01ec2
          g_error_free (local_error);
Packit f01ec2
        }
Packit f01ec2
Packit f01ec2
      free_entry (entry);
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  if (remaining == 0)
Packit f01ec2
    g_main_loop_quit (data->loop);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
query_flickr (GomAccountMinerJob *job,
Packit f01ec2
              TrackerSparqlConnection *connection,
Packit f01ec2
              GHashTable *previous_resources,
Packit f01ec2
              const gchar *datasource_urn,
Packit f01ec2
              GCancellable *cancellable,
Packit f01ec2
              GError **error)
Packit f01ec2
{
Packit f01ec2
  GomFlickrMiner *self = GOM_FLICKR_MINER (job->miner);
Packit f01ec2
  GomFlickrMinerPrivate *priv = self->priv;
Packit f01ec2
  FlickrEntry *entry;
Packit f01ec2
  const GList *keys;
Packit f01ec2
  GMainContext *context;
Packit f01ec2
  GrlOperationOptions *opts;
Packit f01ec2
  GrlSource *source;
Packit f01ec2
  SyncData data;
Packit f01ec2
Packit f01ec2
  source = GRL_SOURCE (g_hash_table_lookup (job->services, "photos"));
Packit f01ec2
  if (source == NULL)
Packit f01ec2
  {
Packit f01ec2
    /* FIXME: use proper #defines and enumerated types */
Packit f01ec2
    g_set_error (error,
Packit f01ec2
                 g_quark_from_static_string ("gom-error"),
Packit f01ec2
                 0,
Packit f01ec2
                 "Can not query without a service");
Packit f01ec2
    return;
Packit f01ec2
  }
Packit f01ec2
Packit f01ec2
  /* grl_source_browse does not fetch photos that are not part of a
Packit f01ec2
   * set. So, use grl_source_search to fetch all photos and then allot
Packit f01ec2
   * each photo to any set that it might be a part of.
Packit f01ec2
   */
Packit f01ec2
Packit f01ec2
  data.cancellable = cancellable;
Packit f01ec2
  data.connection = connection;
Packit f01ec2
  data.datasource_urn = datasource_urn;
Packit f01ec2
  data.job = job;
Packit f01ec2
  data.previous_resources = previous_resources;
Packit f01ec2
  context = g_main_context_new ();
Packit f01ec2
  g_main_context_push_thread_default (context);
Packit f01ec2
  data.loop = g_main_loop_new (context, FALSE);
Packit f01ec2
Packit f01ec2
  keys = grl_source_supported_keys (source);
Packit f01ec2
  opts = get_grl_options (source);
Packit f01ec2
  grl_source_search (source, NULL, keys, opts, source_search_cb, &data);
Packit f01ec2
  g_main_loop_run (data.loop);
Packit f01ec2
Packit f01ec2
  g_object_unref (opts);
Packit f01ec2
  g_main_loop_unref (data.loop);
Packit f01ec2
  g_main_context_pop_thread_default (context);
Packit f01ec2
  g_main_context_unref (context);
Packit f01ec2
Packit f01ec2
  entry = create_entry (NULL, NULL);
Packit f01ec2
  account_miner_job_browse_container (job, connection, previous_resources, datasource_urn, entry, cancellable);
Packit f01ec2
  free_entry (entry);
Packit f01ec2
Packit f01ec2
  while (!g_queue_is_empty (priv->boxes))
Packit f01ec2
    {
Packit f01ec2
      entry = (FlickrEntry *) g_queue_pop_head (priv->boxes);
Packit f01ec2
      account_miner_job_browse_container (job, connection, previous_resources, datasource_urn, entry, cancellable);
Packit f01ec2
      free_entry (entry);
Packit f01ec2
    }
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
source_added_cb (GrlRegistry *registry, GrlSource *source, gpointer user_data)
Packit f01ec2
{
Packit f01ec2
  SyncData *data = (SyncData *) user_data;
Packit f01ec2
  gchar *source_id;
Packit f01ec2
Packit f01ec2
  g_object_get (source, "source-id", &source_id, NULL);
Packit f01ec2
  if (g_strcmp0 (source_id, data->source_id) != 0)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  data->source = g_object_ref (source);
Packit f01ec2
  g_main_loop_quit (data->loop);
Packit f01ec2
Packit f01ec2
 out:
Packit f01ec2
  g_free (source_id);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static GHashTable *
Packit f01ec2
create_services (GomMiner *self,
Packit f01ec2
                 GoaObject *object)
Packit f01ec2
{
Packit f01ec2
  GHashTable *services;
Packit f01ec2
  GoaAccount *acc;
Packit f01ec2
  GrlRegistry *registry;
Packit f01ec2
  GrlSource *source = NULL;
Packit f01ec2
  gchar *source_id = NULL;
Packit f01ec2
Packit f01ec2
  services = g_hash_table_new_full (g_str_hash, g_str_equal,
Packit f01ec2
                                    NULL, (GDestroyNotify) g_object_unref);
Packit f01ec2
Packit f01ec2
  acc = goa_object_peek_account (object);
Packit f01ec2
  if (acc == NULL)
Packit f01ec2
    goto out;
Packit f01ec2
Packit f01ec2
  if (gom_miner_supports_type (self, "photos"))
Packit f01ec2
    {
Packit f01ec2
      source_id = g_strdup_printf ("grl-flickr-%s", goa_account_get_id (acc));
Packit f01ec2
Packit f01ec2
      registry = grl_registry_get_default ();
Packit f01ec2
Packit f01ec2
      g_debug ("Looking for source %s", source_id);
Packit f01ec2
      source = grl_registry_lookup_source (registry, source_id);
Packit f01ec2
      if (source == NULL)
Packit f01ec2
        {
Packit f01ec2
          GMainContext *context;
Packit f01ec2
          SyncData data;
Packit f01ec2
Packit f01ec2
          context = g_main_context_get_thread_default ();
Packit f01ec2
          data.loop = g_main_loop_new (context, FALSE);
Packit f01ec2
          data.source_id = source_id;
Packit f01ec2
Packit f01ec2
          g_signal_connect (registry, "source-added", G_CALLBACK (source_added_cb), &data);
Packit f01ec2
          g_main_loop_run (data.loop);
Packit f01ec2
          g_main_loop_unref (data.loop);
Packit f01ec2
Packit f01ec2
          /* we steal the ref from data */
Packit f01ec2
          source = data.source;
Packit f01ec2
        }
Packit f01ec2
      else
Packit f01ec2
        {
Packit f01ec2
          /* freeing job calls unref upon this object */
Packit f01ec2
          g_object_ref (source);
Packit f01ec2
        }
Packit f01ec2
      g_free (source_id);
Packit f01ec2
      g_hash_table_insert (services, "photos", source);
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
 out:
Packit f01ec2
  return services;
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_flickr_miner_finalize (GObject *object)
Packit f01ec2
{
Packit f01ec2
  GomFlickrMiner *self = GOM_FLICKR_MINER (object);
Packit f01ec2
Packit f01ec2
  g_queue_free_full (self->priv->boxes, (GDestroyNotify) free_entry);
Packit f01ec2
Packit f01ec2
  G_OBJECT_CLASS (gom_flickr_miner_parent_class)->finalize (object);
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_flickr_miner_init (GomFlickrMiner *self)
Packit f01ec2
{
Packit f01ec2
  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GOM_TYPE_FLICKR_MINER, GomFlickrMinerPrivate);
Packit f01ec2
  self->priv->boxes = g_queue_new ();
Packit f01ec2
}
Packit f01ec2
Packit f01ec2
static void
Packit f01ec2
gom_flickr_miner_class_init (GomFlickrMinerClass *klass)
Packit f01ec2
{
Packit f01ec2
  GObjectClass *oclass = G_OBJECT_CLASS (klass);
Packit f01ec2
  GomMinerClass *miner_class = GOM_MINER_CLASS (klass);
Packit f01ec2
  GrlRegistry *registry;
Packit f01ec2
  GError *error = NULL;
Packit f01ec2
Packit f01ec2
  oclass->finalize = gom_flickr_miner_finalize;
Packit f01ec2
Packit f01ec2
  miner_class->goa_provider_type = "flickr";
Packit f01ec2
  miner_class->miner_identifier = MINER_IDENTIFIER;
Packit f01ec2
  miner_class->version = 1;
Packit f01ec2
Packit f01ec2
  miner_class->create_services = create_services;
Packit f01ec2
  miner_class->query = query_flickr;
Packit f01ec2
Packit f01ec2
  grl_init (NULL, NULL);
Packit f01ec2
  registry = grl_registry_get_default ();
Packit f01ec2
  grl_registry_load_all_plugins (registry, FALSE, &error);
Packit f01ec2
Packit f01ec2
  if (error != NULL || !grl_registry_activate_plugin_by_id (registry, "grl-flickr", &error))
Packit f01ec2
    {
Packit f01ec2
      g_error ("%s", error->message);
Packit f01ec2
      g_error_free (error);
Packit f01ec2
    }
Packit f01ec2
Packit f01ec2
  g_type_class_add_private (klass, sizeof (GomFlickrMinerPrivate));
Packit f01ec2
}