[grilo-plugins/wip/carlosg/tracker3: 17/30] tracker3: Port store_metadata to tracker3




commit ba6ef2127f0217919c8c0da898fc4250c071488d
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun May 24 18:13:33 2020 +0200

    tracker3: Port store_metadata to tracker3
    
    The data stored by miner-fs is no longer considered readwrite for
    all. These updates used to trigger the tracker writeback service
    which would rewrite file metadata and make everything match again.
    Make this use the writeback service directly, the miner-fs data
    will then be updated indirectly.

 src/tracker3/grl-tracker-source-api.c  |  83 ++++++--------
 src/tracker3/grl-tracker-source-priv.h |   1 +
 src/tracker3/grl-tracker-source.c      |  18 +++
 src/tracker3/grl-tracker-utils.c       | 193 +++++++++++++++++++++++++++++++++
 src/tracker3/grl-tracker-utils.h       |   2 +
 5 files changed, 245 insertions(+), 52 deletions(-)
---
diff --git a/src/tracker3/grl-tracker-source-api.c b/src/tracker3/grl-tracker-source-api.c
index 11143749..0148e949 100644
--- a/src/tracker3/grl-tracker-source-api.c
+++ b/src/tracker3/grl-tracker-source-api.c
@@ -55,15 +55,6 @@ GRL_LOG_DOMAIN_STATIC(tracker_source_result_log_domain);
   GRL_LOG (tracker_source_result_log_domain,    \
            GRL_LOG_LEVEL_DEBUG, args)
 
-/* ------- Definitions ------- */
-
-#define TRACKER_DELETE_REQUEST                          \
-  "DELETE { <%s> %s } WHERE { <%s> a nfo:Media . %s }"
-
-#define TRACKER_SAVE_REQUEST                            \
-  "DELETE { <%s> %s } WHERE { <%s> a nfo:Media . %s } " \
-  "INSERT { <%s> a nfo:Media ; %s . }"
-
 /**/
 
 /**/
@@ -470,15 +461,13 @@ tracker_store_metadata_cb (GObject      *source_object,
 {
   GrlSourceStoreMetadataSpec *sms =
     (GrlSourceStoreMetadataSpec *) os->data;
-  GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (sms->source);
   GError *tracker_error = NULL, *error = NULL;
 
-  tracker_sparql_connection_update_finish (priv->tracker_connection,
-                                           result,
-                                           &tracker_error);
+  g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+                            result, &tracker_error);
 
   if (tracker_error) {
-    GRL_WARNING ("Could not execute sparql update : %s",
+    GRL_WARNING ("Could not writeback metadata: %s",
                  tracker_error->message);
 
     error = g_error_new (GRL_CORE_ERROR,
@@ -491,7 +480,7 @@ tracker_store_metadata_cb (GObject      *source_object,
     g_error_free (tracker_error);
     g_error_free (error);
   } else {
-    sms->callback (sms->source, sms->media, NULL, sms->user_data, error);
+    sms->callback (sms->source, sms->media, NULL, sms->user_data, NULL);
   }
 
   grl_tracker_op_free (os);
@@ -510,15 +499,24 @@ grl_tracker_source_writable_keys (GrlSource *source)
     registry = grl_registry_get_default ();
     grl_metadata_key_chromaprint = grl_registry_lookup_metadata_key (registry, "chromaprint");
 
-    keys = grl_metadata_key_list_new (GRL_METADATA_KEY_PLAY_COUNT,
-                                      GRL_METADATA_KEY_LAST_PLAYED,
-                                      GRL_METADATA_KEY_LAST_POSITION,
-                                      GRL_METADATA_KEY_FAVOURITE,
+    keys = grl_metadata_key_list_new (GRL_METADATA_KEY_ALBUM,
+                                      GRL_METADATA_KEY_ALBUM_DISC_NUMBER,
+                                      GRL_METADATA_KEY_ARTIST,
+                                      GRL_METADATA_KEY_ALBUM_ARTIST,
+                                      GRL_METADATA_KEY_AUTHOR,
+                                      GRL_METADATA_KEY_COMPOSER,
+                                      GRL_METADATA_KEY_CREATION_DATE,
                                       GRL_METADATA_KEY_TITLE,
+                                      GRL_METADATA_KEY_SEASON,
+                                      GRL_METADATA_KEY_EPISODE,
                                       GRL_METADATA_KEY_TRACK_NUMBER,
-                                      GRL_METADATA_KEY_CREATION_DATE,
+                                      GRL_METADATA_KEY_MB_RELEASE_ID,
+                                      GRL_METADATA_KEY_MB_RELEASE_GROUP_ID,
+                                      GRL_METADATA_KEY_MB_RECORDING_ID,
+                                      GRL_METADATA_KEY_MB_TRACK_ID,
+                                      GRL_METADATA_KEY_MB_ARTIST_ID,
                                       grl_metadata_key_chromaprint,
-                                      NULL);
+                                      GRL_METADATA_KEY_INVALID);
   }
   return keys;
 }
@@ -713,42 +711,23 @@ grl_tracker_source_store_metadata (GrlSource *source,
                                    GrlSourceStoreMetadataSpec *sms)
 {
   GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
-  gchar *sparql_delete, *sparql_cdelete, *sparql_insert, *sparql_final;
-  const gchar *urn = grl_data_get_string (GRL_DATA (sms->media),
-                                          grl_metadata_key_tracker_urn);
+  TrackerResource *resource;
   GrlTrackerOp *os;
 
-  GRL_IDEBUG ("%s: urn=%s", G_STRFUNC, urn);
-
-  sparql_delete = grl_tracker_get_delete_string (sms->keys);
-  sparql_cdelete = grl_tracker_get_delete_conditional_string (urn, sms->keys);
-  sparql_insert = grl_tracker_tracker_get_insert_string (sms->media, sms->keys);
-
-  if (g_strcmp0 (sparql_insert, "") == 0) {
-    sparql_final = g_strdup_printf (TRACKER_DELETE_REQUEST,
-                                    urn, sparql_delete,
-                                    urn, sparql_cdelete);
-  } else {
-    sparql_final = g_strdup_printf (TRACKER_SAVE_REQUEST,
-                                    urn, sparql_delete,
-                                    urn, sparql_cdelete,
-                                    urn, sparql_insert);
-  }
-
-  GRL_IDEBUG ("\trequest: '%s'", sparql_final);
+  resource = grl_tracker_build_resource_from_media (sms->media, sms->keys);
 
   os = grl_tracker_op_new (GRL_TYPE_FILTER_ALL, sms->keys, sms);
 
-  tracker_sparql_connection_update_async (priv->tracker_connection,
-                                          sparql_final,
-                                          G_PRIORITY_DEFAULT,
-                                          os->cancel,
-                                          tracker_store_metadata_cb,
-                                          os);
-
-  g_free (sparql_delete);
-  g_free (sparql_cdelete);
-  g_free (sparql_insert);
+  g_dbus_proxy_call (priv->writeback,
+                     "Writeback",
+                     g_variant_new ("(@a{sv})",
+                                    tracker_resource_serialize (resource)),
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     os->cancel,
+                     (GAsyncReadyCallback) tracker_store_metadata_cb,
+                     os);
+  g_object_unref (resource);
 }
 
 void
diff --git a/src/tracker3/grl-tracker-source-priv.h b/src/tracker3/grl-tracker-source-priv.h
index 1d324823..226087c2 100644
--- a/src/tracker3/grl-tracker-source-priv.h
+++ b/src/tracker3/grl-tracker-source-priv.h
@@ -64,6 +64,7 @@ typedef enum {
 
 struct _GrlTrackerSourcePriv {
   TrackerSparqlConnection *tracker_connection;
+  GDBusProxy *writeback;
 
   GHashTable *operations;
   GrlTrackerSourceNotify *notifier;
diff --git a/src/tracker3/grl-tracker-source.c b/src/tracker3/grl-tracker-source.c
index 1af6a4a7..8fb23a8d 100644
--- a/src/tracker3/grl-tracker-source.c
+++ b/src/tracker3/grl-tracker-source.c
@@ -50,6 +50,10 @@ GRL_LOG_DOMAIN_STATIC(tracker_source_log_domain);
 
 #define TRACKER_ITEM_CACHE_SIZE (10000)
 
+#define WRITEBACK_DBUS_NAME "org.freedesktop.Tracker3.Writeback"
+#define WRITEBACK_DBUS_PATH "/org/freedesktop/Tracker3/Writeback"
+#define WRITEBACK_DBUS_IFACE "org.freedesktop.Tracker3.Writeback"
+
 /* --- Other --- */
 
 enum {
@@ -128,10 +132,23 @@ static void
 grl_tracker_source_init (GrlTrackerSource *source)
 {
   GrlTrackerSourcePriv *priv = GRL_TRACKER_SOURCE_GET_PRIVATE (source);
+  GDBusConnection *connection;
 
   source->priv = priv;
 
   priv->operations = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+  connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+  if (connection) {
+    priv->writeback =
+      g_dbus_proxy_new_sync (connection,
+                             G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION,
+                             NULL,
+                             WRITEBACK_DBUS_NAME,
+                             WRITEBACK_DBUS_PATH,
+                             WRITEBACK_DBUS_IFACE,
+                             NULL, NULL);
+  }
 }
 
 static void
@@ -143,6 +160,7 @@ grl_tracker_source_finalize (GObject *object)
 
   g_clear_object (&self->priv->notifier);
   g_clear_object (&self->priv->tracker_connection);
+  g_clear_object (&self->priv->writeback);
 
   G_OBJECT_CLASS (grl_tracker_source_parent_class)->finalize (object);
 }
diff --git a/src/tracker3/grl-tracker-utils.c b/src/tracker3/grl-tracker-utils.c
index e8a6bfcd..e915c34f 100644
--- a/src/tracker3/grl-tracker-utils.c
+++ b/src/tracker3/grl-tracker-utils.c
@@ -886,3 +886,196 @@ grl_tracker_key_get_sparql_statement (const GrlKeyID key,
 
   return assoc->sparql_key_attr_call;
 }
+
+static TrackerResource *
+ensure_resource_for_property (TrackerResource *resource,
+                              const gchar     *prop,
+                              gboolean         multivalued)
+{
+  TrackerResource *child = NULL;
+
+  if (!multivalued)
+    child = tracker_resource_get_first_relation (resource, prop);
+
+  if (!child) {
+    child = tracker_resource_new (NULL);
+    tracker_resource_add_take_relation (resource, prop, child);
+  }
+
+  return child;
+}
+
+static TrackerResource *
+ensure_resource_for_musicbrainz_tag (TrackerResource *resource,
+                                     const gchar     *source,
+                                     const gchar     *identifier)
+{
+  TrackerResource *reference;
+
+  reference = ensure_resource_for_property (resource,
+                                            "tracker:hasExternalReference",
+                                            TRUE);
+  tracker_resource_set_uri (reference,
+                            "tracker:referenceSource",
+                            source);
+  tracker_resource_set_string (reference,
+                               "tracker:referenceIdentifier",
+                               identifier);
+  return reference;
+}
+
+TrackerResource *
+grl_tracker_build_resource_from_media (GrlMedia *media, GList *keys)
+{
+  TrackerResource *resource;
+  GrlRegistry *registry;
+  GrlKeyID grl_metadata_key_chromaprint;
+  GrlMediaType type;
+  GList *l;
+
+  registry = grl_registry_get_default ();
+  grl_metadata_key_chromaprint = grl_registry_lookup_metadata_key (registry, "chromaprint");
+
+  resource = tracker_resource_new (NULL);
+  tracker_resource_set_uri (resource, "nie:isStoredAs",
+                            grl_media_get_url (media));
+
+  type = grl_media_get_media_type (media);
+  if (type & GRL_MEDIA_TYPE_IMAGE)
+    tracker_resource_add_uri (resource, "rdf:type", "nfo:Image");
+  if (type & GRL_MEDIA_TYPE_AUDIO)
+    tracker_resource_add_uri (resource, "rdf:type", "nfo:Audio");
+  if (type & GRL_MEDIA_TYPE_VIDEO)
+    tracker_resource_add_uri (resource, "rdf:type", "nfo:Video");
+
+  for (l = keys; l; l = l->next) {
+    if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_TITLE)) {
+      tracker_resource_set_string (resource, "nie:title",
+                                   grl_media_get_title (media));
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_TRACK_NUMBER)) {
+      tracker_resource_set_int (resource, "nmm:trackNumber",
+                                grl_media_get_track_number (media));
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_EPISODE)) {
+      tracker_resource_set_int (resource, "nmm:episodeNumber",
+                                grl_media_get_episode (media));
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_CREATION_DATE)) {
+      GDateTime *creation;
+      gchar *date;
+
+      creation = grl_media_get_creation_date (media);
+      date = g_date_time_format_iso8601 (creation);
+      tracker_resource_set_string (resource, "nie:contentCreated", date);
+      g_free (date);
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ALBUM)) {
+      TrackerResource *album;
+      album = ensure_resource_for_property (resource, "nmm:musicAlbum", FALSE);
+      tracker_resource_set_string (album, "nie:title",
+                                   grl_media_get_album (media));
+
+      /* Handle MB release/release group inline */
+      if (g_list_find (keys, GRLKEYID_TO_POINTER (GRL_METADATA_KEY_MB_RELEASE_ID))) {
+        const gchar *mb_release_id;
+
+        mb_release_id = grl_media_get_mb_release_id (media);
+        if (mb_release_id) {
+          ensure_resource_for_musicbrainz_tag (resource,
+                                               "https://musicbrainz.org/doc/Release";,
+                                               mb_release_id);
+        }
+      }
+
+      if (g_list_find (keys, GRLKEYID_TO_POINTER (GRL_METADATA_KEY_MB_RELEASE_GROUP_ID))) {
+        const gchar *mb_release_group_id;
+
+        mb_release_group_id = grl_media_get_mb_release_group_id (media);
+        if (mb_release_group_id) {
+          ensure_resource_for_musicbrainz_tag (resource,
+                                               "https://musicbrainz.org/doc/Release_Group";,
+                                               mb_release_group_id);
+        }
+      }
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ALBUM_DISC_NUMBER)) {
+      TrackerResource *disc;
+      disc = ensure_resource_for_property (resource, "nmm:musicAlbumDisc", FALSE);
+      tracker_resource_set_int (disc, "nmm:setNumber",
+                                grl_media_get_album_disc_number (media));
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_SEASON)) {
+      TrackerResource *season;
+      season = ensure_resource_for_property (resource, "nmm:isPartOfSeason", FALSE);
+      tracker_resource_set_int (season, "nmm:seasonNumber",
+                                grl_media_get_season (media));
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ALBUM_ARTIST)) {
+      TrackerResource *album, *album_artist;
+      album = ensure_resource_for_property (resource, "nmm:musicAlbum", FALSE);
+      album_artist = ensure_resource_for_property (album, "nmm:albumArtist", FALSE);
+      tracker_resource_set_string (album_artist, "nmm:artistName",
+                                   grl_media_get_album_artist (media));
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_MB_RECORDING_ID)) {
+      const gchar *mb_recording_id;
+      mb_recording_id = grl_media_get_mb_recording_id (media);
+      if (mb_recording_id) {
+        ensure_resource_for_musicbrainz_tag (resource,
+                                             "https://musicbrainz.org/doc/Recording";,
+                                             mb_recording_id);
+      }
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_MB_TRACK_ID)) {
+      const gchar *mb_track_id;
+      mb_track_id = grl_media_get_mb_track_id (media);
+      if (mb_track_id) {
+        ensure_resource_for_musicbrainz_tag (resource,
+                                             "https://musicbrainz.org/doc/Track";,
+                                             mb_track_id);
+      }
+    } else if (l->data == GRLKEYID_TO_POINTER (grl_metadata_key_chromaprint)) {
+      TrackerResource *hash;
+      hash = ensure_resource_for_property (resource, "nfo:hasHash", FALSE);
+      tracker_resource_set_string (hash, "nfo:hashAlgorithm", "chromaprint");
+      tracker_resource_set_string (hash, "nfo:hashValue",
+                                   grl_data_get_string (GRL_DATA (media), l->data));
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ARTIST)) {
+      TrackerResource *artist;
+      const gchar *artist_name;
+      gint i;
+
+      for (i = 0; artist_name != NULL; i++) {
+        artist_name = grl_media_get_artist_nth (media, i);
+        artist = ensure_resource_for_property (resource, "nmm:performer", TRUE);
+        tracker_resource_set_string (artist, "nmm:artistName", artist_name);
+
+        /* Handle MB artist inline */
+        if (g_list_find (keys, GRLKEYID_TO_POINTER (GRL_METADATA_KEY_MB_ARTIST_ID))) {
+          const gchar *mb_artist_id;
+
+          mb_artist_id = grl_media_get_mb_artist_id_nth (media, i);
+          if (mb_artist_id) {
+            ensure_resource_for_musicbrainz_tag (resource,
+                                                 "https://musicbrainz.org/doc/Artist";,
+                                                 mb_artist_id);
+          }
+        }
+      }
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_AUTHOR)) {
+      TrackerResource *artist;
+      const gchar *artist_name;
+      gint i;
+
+      for (i = 0; artist_name != NULL; i++) {
+        artist_name = grl_media_get_artist_nth (media, i);
+        artist = ensure_resource_for_property (resource, "nmm:performer", TRUE);
+        tracker_resource_set_string (artist, "nmm:artistName", artist_name);
+      }
+    } else if (l->data == GRLKEYID_TO_POINTER (GRL_METADATA_KEY_COMPOSER)) {
+      TrackerResource *composer;
+      const gchar *composer_name;
+      gint i;
+
+      for (i = 0; composer_name != NULL; i++) {
+        composer_name = grl_media_get_composer_nth (media, i);
+        composer = ensure_resource_for_property (resource, "nmm:composer", TRUE);
+        tracker_resource_set_string (composer, "nmm:artistName", composer_name);
+      }
+    }
+  }
+
+  return resource;
+}
diff --git a/src/tracker3/grl-tracker-utils.h b/src/tracker3/grl-tracker-utils.h
index 7db23331..e4a5a99e 100644
--- a/src/tracker3/grl-tracker-utils.h
+++ b/src/tracker3/grl-tracker-utils.h
@@ -76,6 +76,8 @@ const gchar * grl_tracker_key_get_sparql_statement (const GrlKeyID key,
 
 void grl_tracker_setup_key_mappings (void);
 
+TrackerResource * grl_tracker_build_resource_from_media (GrlMedia *media, GList *keys);
+
 tracker_grl_sparql_t *grl_tracker_get_mapping_from_sparql (const gchar *key);
 
 GrlMedia *grl_tracker_build_grilo_media (const gchar   *rdf_type,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]