[rhythmbox] ext-db: make it possible to delete metadata and store nulls
- From: Jonathan Matthew <jmatthew src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rhythmbox] ext-db: make it possible to delete metadata and store nulls
- Date: Wed, 28 Jan 2015 22:34:32 +0000 (UTC)
commit 7981c29d6d7bbee7174c812c591767fd31f0d741
Author: Jonathan Matthew <jonathan d14n org>
Date: Wed Dec 24 17:36:14 2014 +1000
ext-db: make it possible to delete metadata and store nulls
To make these capabilities useful, all lookups now return the storage key
along with the lookup result, so the result can easily by deleted (and
subsequently re-fetched) or cleared. When a NULL value is stored, only
a value from a higher priority source type will replace it.
metadata/rb-ext-db-key.c | 67 ++++++++++---
metadata/rb-ext-db-key.h | 2 +-
metadata/rb-ext-db.c | 129 ++++++++++++++++++++++---
metadata/rb-ext-db.h | 10 ++-
plugins/artsearch/songinfo.py | 4 +-
plugins/ipod/rb-ipod-source.c | 2 +-
plugins/mpris/rb-mpris-plugin.c | 2 +-
plugins/mtpdevice/rb-mtp-source.c | 2 +-
plugins/notification/rb-notification-plugin.c | 4 +-
plugins/visualizer/rb-visualizer-fullscreen.c | 2 +-
widgets/rb-header.c | 6 +-
11 files changed, 188 insertions(+), 42 deletions(-)
---
diff --git a/metadata/rb-ext-db-key.c b/metadata/rb-ext-db-key.c
index 09b35b5..63d43d9 100644
--- a/metadata/rb-ext-db-key.c
+++ b/metadata/rb-ext-db-key.c
@@ -502,22 +502,46 @@ rb_ext_db_key_field_matches (RBExtDBKey *key, const char *field, const char *val
return FALSE;
}
-static gboolean
-create_store_key (RBExtDBKey *key, int option, TDB_DATA *data)
+static void
+flatten_store_key (RBExtDBKey *key, TDB_DATA *data)
{
GByteArray *k;
GList *l;
guint8 nul = '\0';
+ g_assert (key->lookup == FALSE);
+
+ k = g_byte_array_sized_new (512);
+ for (l = key->fields; l != NULL; l = l->next) {
+ RBExtDBField *f = l->data;
+ const char *value;
+
+ value = g_ptr_array_index (f->values, 0);
+ g_byte_array_append (k, (guint8 *)f->name, strlen (f->name));
+ g_byte_array_append (k, &nul, 1);
+ g_byte_array_append (k, (guint8 *)value, strlen (value));
+ g_byte_array_append (k, &nul, 1);
+ }
+
+ data->dsize = k->len;
+ data->dptr = g_byte_array_free (k, FALSE);
+}
+
+static RBExtDBKey *
+create_store_key (RBExtDBKey *key, int option)
+{
+ RBExtDBKey *skey = NULL;
+ GList *l;
+
+ g_assert (key->lookup);
if (key->multi_field != NULL &&
option > key->multi_field->values->len &&
key->multi_field->match_null == FALSE) {
- return FALSE;
+ return NULL;
} else if (key->multi_field == NULL && option != 0) {
- return FALSE;
+ return NULL;
}
- k = g_byte_array_sized_new (512);
for (l = key->fields; l != NULL; l = l->next) {
RBExtDBField *f = l->data;
const char *value;
@@ -529,15 +553,13 @@ create_store_key (RBExtDBKey *key, int option, TDB_DATA *data)
} else {
continue;
}
- g_byte_array_append (k, (guint8 *)f->name, strlen (f->name));
- g_byte_array_append (k, &nul, 1);
- g_byte_array_append (k, (guint8 *)value, strlen (value));
- g_byte_array_append (k, &nul, 1);
+ if (skey == NULL)
+ skey = rb_ext_db_key_create_storage (f->name, value);
+ else
+ rb_ext_db_key_add_field (skey, f->name, value);
}
- data->dsize = k->len;
- data->dptr = g_byte_array_free (k, FALSE);
- return TRUE;
+ return skey;
}
/**
@@ -560,14 +582,18 @@ rb_ext_db_key_lookups (RBExtDBKey *key,
{
int i = 0;
while (TRUE) {
+ RBExtDBKey *s;
TDB_DATA sk;
gboolean result;
- if (create_store_key (key, i, &sk) == FALSE)
+ s = create_store_key (key, i);
+ if (s == NULL)
break;
- result = callback (sk, user_data);
+ flatten_store_key (s, &sk);
+ result = callback (sk, s, user_data);
g_free (sk.dptr);
+ rb_ext_db_key_free (s);
if (result == FALSE)
break;
@@ -596,7 +622,18 @@ TDB_DATA
rb_ext_db_key_to_store_key (RBExtDBKey *key)
{
TDB_DATA k = {0,};
- create_store_key (key, 0, &k);
+ RBExtDBKey *sk;
+
+ if (key->lookup) {
+ sk = create_store_key (key, 0);
+ if (sk != NULL) {
+ flatten_store_key (sk, &k);
+ rb_ext_db_key_free (sk);
+ }
+ } else {
+ flatten_store_key (key, &k);
+ }
+
return k;
}
diff --git a/metadata/rb-ext-db-key.h b/metadata/rb-ext-db-key.h
index 4c1d206..73df5ce 100644
--- a/metadata/rb-ext-db-key.h
+++ b/metadata/rb-ext-db-key.h
@@ -77,7 +77,7 @@ const char * rb_ext_db_key_get_info (RBExtDBKey *key,
gboolean rb_ext_db_key_matches (RBExtDBKey *a,
RBExtDBKey *b);
-typedef gboolean (*RBExtDBKeyLookupCallback) (TDB_DATA data, gpointer user_data);
+typedef gboolean (*RBExtDBKeyLookupCallback) (TDB_DATA data, RBExtDBKey *key, gpointer user_data);
void rb_ext_db_key_lookups (RBExtDBKey *key,
RBExtDBKeyLookupCallback callback,
diff --git a/metadata/rb-ext-db.c b/metadata/rb-ext-db.c
index ab14b6a..b443ee1 100644
--- a/metadata/rb-ext-db.c
+++ b/metadata/rb-ext-db.c
@@ -94,6 +94,7 @@ typedef struct {
gpointer user_data;
GDestroyNotify destroy_notify;
+ RBExtDBKey *store_key;
char *filename;
GValue *data;
} RBExtDBRequest;
@@ -115,6 +116,8 @@ static void
free_request (RBExtDBRequest *request)
{
rb_ext_db_key_free (request->key);
+ if (request->store_key)
+ rb_ext_db_key_free (request->store_key);
g_free (request->filename);
@@ -131,10 +134,11 @@ free_request (RBExtDBRequest *request)
static void
answer_request (RBExtDBRequest *request,
+ RBExtDBKey *store_key,
const char *filename,
GValue *data)
{
- request->callback (request->key, filename, data, request->user_data);
+ request->callback (request->key, store_key, filename, data, request->user_data);
free_request (request);
}
@@ -518,12 +522,13 @@ rb_ext_db_new (const char *name)
typedef struct {
RBExtDB *store;
char **filename;
+ RBExtDBKey **store_key;
guint64 search_time;
RBExtDBSourceType source_type;
} RBExtDBLookup;
static gboolean
-lookup_cb (TDB_DATA data, gpointer user_data)
+lookup_cb (TDB_DATA data, RBExtDBKey *key, gpointer user_data)
{
TDB_DATA tdbvalue;
RBExtDBLookup *lookup = user_data;
@@ -545,12 +550,17 @@ lookup_cb (TDB_DATA data, gpointer user_data)
lookup->search_time = search_time;
break;
default:
- if (source_type > lookup->source_type && fn != NULL) {
+ if (source_type > lookup->source_type) {
g_free (*lookup->filename);
*lookup->filename = fn;
+ if (lookup->store_key) {
+ if (*lookup->store_key)
+ rb_ext_db_key_free (*lookup->store_key);
+ *lookup->store_key = rb_ext_db_key_copy (key);
+ }
lookup->source_type = source_type;
lookup->search_time = search_time;
- rb_debug ("found new best match %s, %d", fn, source_type);
+ rb_debug ("found new best match %s, %d", fn ? fn : "none", source_type);
} else {
g_free (fn);
rb_debug ("don't care about match %d", source_type);
@@ -565,13 +575,14 @@ lookup_cb (TDB_DATA data, gpointer user_data)
* rb_ext_db_lookup:
* @store: metadata store instance
* @key: metadata lookup key
+ * @store_key: (out) (transfer full) (allow-none): optionally returns the matching storage key
*
* Looks up a cached metadata item.
*
* Return value: name of the file storing the cached metadata item
*/
char *
-rb_ext_db_lookup (RBExtDB *store, RBExtDBKey *key)
+rb_ext_db_lookup (RBExtDB *store, RBExtDBKey *key, RBExtDBKey **store_key)
{
char *fn = NULL;
RBExtDBLookup lookup;
@@ -579,6 +590,7 @@ rb_ext_db_lookup (RBExtDB *store, RBExtDBKey *key)
lookup.store = store;
lookup.filename = &fn;
+ lookup.store_key = store_key;
lookup.source_type = RB_EXT_DB_SOURCE_NONE;
lookup.search_time = 0;
@@ -600,7 +612,7 @@ load_request_cb (RBExtDB *store, GAsyncResult *result, gpointer data)
req = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
rb_debug ("finished loading %s", req->filename);
- req->callback (req->key, req->filename, req->data, req->user_data);
+ req->callback (req->key, req->store_key, req->filename, req->data, req->user_data);
g_object_unref (result);
}
@@ -680,13 +692,32 @@ rb_ext_db_request (RBExtDB *store,
char *filename;
GList *l;
gboolean emit_request = TRUE;
+ RBExtDBKey *store_key = NULL;
rb_debug ("starting metadata request");
- filename = rb_ext_db_lookup (store, key);
- if (filename != NULL) {
+ filename = rb_ext_db_lookup (store, key, &store_key);
+ if (store_key != NULL) {
GSimpleAsyncResult *load_op;
- rb_debug ("found cached match %s", filename);
+
+ if (filename == NULL) {
+ if (rb_debug_here ()) {
+ char *str = rb_ext_db_key_to_string (store_key);
+ rb_debug ("found empty match under key %s", str);
+ g_free (str);
+ }
+ callback (key, store_key, NULL, NULL, user_data);
+ if (destroy)
+ destroy (user_data);
+ rb_ext_db_key_free (store_key);
+ return FALSE;
+ }
+
+ if (rb_debug_here ()) {
+ char *str = rb_ext_db_key_to_string (store_key);
+ rb_debug ("found cached match %s under key %s", filename, str);
+ g_free (str);
+ }
load_op = g_simple_async_result_new (G_OBJECT (store),
(GAsyncReadyCallback) load_request_cb,
NULL,
@@ -694,6 +725,7 @@ rb_ext_db_request (RBExtDB *store,
req = create_request (key, callback, user_data, destroy);
req->filename = filename;
+ req->store_key = store_key;
g_simple_async_result_set_op_res_gpointer (load_op, req, (GDestroyNotify) free_request);
g_simple_async_result_run_in_thread (load_op,
@@ -732,6 +764,7 @@ rb_ext_db_request (RBExtDB *store,
} else {
last_time = 0;
}
+ g_free (tdbkey.dptr);
/* add stuff to list of outstanding requests */
req = create_request (key, callback, user_data, destroy);
@@ -749,6 +782,27 @@ rb_ext_db_request (RBExtDB *store,
return result;
}
+static void
+delete_file (RBExtDB *store, const char *filename)
+{
+ char *fullname;
+ GFile *f;
+ GError *error = NULL;
+
+ fullname = g_build_filename (rb_user_cache_dir (), store->priv->name, filename, NULL);
+ f = g_file_new_for_path (fullname);
+ g_free (fullname);
+
+ g_file_delete (f, NULL, &error);
+ if (error) {
+ rb_debug ("error deleting %s from %s: %s", filename, store->priv->name, error->message);
+ g_clear_error (&error);
+ } else {
+ rb_debug ("deleted %s from %s", filename, store->priv->name);
+ }
+
+}
+
static void
store_request_cb (RBExtDB *store, GAsyncResult *result, gpointer data)
@@ -768,7 +822,7 @@ store_request_cb (RBExtDB *store, GAsyncResult *result, gpointer data)
if (rb_ext_db_key_matches (sreq->key, req->key)) {
GList *n = l->next;
rb_debug ("answering metadata request %p", req);
- answer_request (req, sreq->filename, sreq->value);
+ answer_request (req, sreq->key, sreq->filename, sreq->value);
store->priv->requests = g_list_delete_link (store->priv->requests, l);
l = n;
} else {
@@ -814,6 +868,11 @@ do_store_request (GSimpleAsyncResult *result, GObject *object, GCancellable *can
g_simple_async_result_set_op_res_gpointer (result, req, (GDestroyNotify)free_store_request);
/* convert key to storage blob */
+ if (rb_debug_here()) {
+ char *str = rb_ext_db_key_to_string (req->key);
+ rb_debug ("storing %s; source = %d", str, req->source_type);
+ g_free (str);
+ }
tdbkey = rb_ext_db_key_to_store_key (req->key);
/* fetch current contents, if any */
@@ -890,7 +949,8 @@ do_store_request (GSimpleAsyncResult *result, GObject *object, GCancellable *can
/* indicates we actually didn't get anything, as opposed to communication errors etc.
* providers just shouldn't call rb_ext_db_store_* in that case.
*/
- req->source_type = RB_EXT_DB_SOURCE_NONE;
+ if (req->source_type != RB_EXT_DB_SOURCE_USER_EXPLICIT)
+ req->source_type = RB_EXT_DB_SOURCE_NONE;
}
/* get data to write to file */
@@ -974,6 +1034,13 @@ do_store_request (GSimpleAsyncResult *result, GObject *object, GCancellable *can
g_free (subdir);
g_object_unref (f);
+ } else if (req->source_type == RB_EXT_DB_SOURCE_USER_EXPLICIT) {
+ if (filename != NULL) {
+ delete_file (store, filename);
+ g_free (filename);
+ filename = NULL;
+ }
+ req->stored = TRUE;
} else if (req->source_type == RB_EXT_DB_SOURCE_NONE) {
req->stored = TRUE;
}
@@ -982,7 +1049,7 @@ do_store_request (GSimpleAsyncResult *result, GObject *object, GCancellable *can
TDB_DATA store_data;
g_get_current_time (&now);
- rb_debug ("actually storing this in the database");
+ rb_debug ("actually storing; time = %lu, filename = %s, source = %d", now.tv_sec, filename,
req->source_type);
store_data = flatten_data (now.tv_sec, filename, req->source_type);
tdb_store (store->priv->tdb_context, tdbkey, store_data, 0);
/* XXX warn on error.. */
@@ -1095,6 +1162,44 @@ rb_ext_db_store_raw (RBExtDB *store,
store_metadata (store, create_store_request (key, source_type, NULL, data, NULL));
}
+/**
+ * rb_ext_db_delete:
+ * @store: metadata store instance
+ * @key: metadata storage key
+ *
+ * Deletes the item stored in the metadata store under the specified storage key.
+ */
+void
+rb_ext_db_delete (RBExtDB *store, RBExtDBKey *key)
+{
+ TDB_DATA k;
+ TDB_DATA value;
+
+ k = rb_ext_db_key_to_store_key (key);
+ if (rb_debug_here ()) {
+ char *str = rb_ext_db_key_to_string (key);
+ rb_debug ("deleting key %s", str);
+ g_free (str);
+ }
+
+ value = tdb_fetch (store->priv->tdb_context, k);
+ if (value.dptr != NULL) {
+ char *fn = NULL;
+
+ extract_data (value, NULL, &fn, NULL);
+ if (fn != NULL) {
+ delete_file (store, fn);
+ g_free (fn);
+ }
+
+ tdb_delete (store->priv->tdb_context, k);
+ free (value.dptr);
+
+ g_signal_emit (store, signals[ADDED], 0, key, NULL, NULL);
+ }
+ g_free (k.dptr);
+}
+
#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
GType
diff --git a/metadata/rb-ext-db.h b/metadata/rb-ext-db.h
index 03b9fcf..aaeea77 100644
--- a/metadata/rb-ext-db.h
+++ b/metadata/rb-ext-db.h
@@ -51,7 +51,7 @@ typedef enum {
RB_EXT_DB_SOURCE_SEARCH, /* found by external search */
RB_EXT_DB_SOURCE_EMBEDDED, /* embedded in media itself */
RB_EXT_DB_SOURCE_USER, /* provided by user (eg image in same dir) */
- RB_EXT_DB_SOURCE_USER_EXPLICIT /* provided explicitly by user */
+ RB_EXT_DB_SOURCE_USER_EXPLICIT, /* provided explicitly by user */
} RBExtDBSourceType;
GType rb_ext_db_source_type_get_type (void);
@@ -87,7 +87,7 @@ struct _RBExtDBClass
GValue *data);
};
-typedef void (*RBExtDBRequestCallback) (RBExtDBKey *key, const char *filename, GValue *data, gpointer
user_data);
+typedef void (*RBExtDBRequestCallback) (RBExtDBKey *key, RBExtDBKey *store_key, const char *filename, GValue
*data, gpointer user_data);
GType rb_ext_db_get_type (void);
@@ -95,7 +95,8 @@ RBExtDB * rb_ext_db_new (const char *name);
/* for requestors */
char * rb_ext_db_lookup (RBExtDB *store,
- RBExtDBKey *key);
+ RBExtDBKey *key,
+ RBExtDBKey **store_key);
gboolean rb_ext_db_request (RBExtDB *store,
RBExtDBKey *key,
@@ -119,6 +120,9 @@ void rb_ext_db_store_raw (RBExtDB *store,
RBExtDBSourceType source_type,
GValue *data);
+void rb_ext_db_delete (RBExtDB *store,
+ RBExtDBKey *key);
+
G_END_DECLS
#endif /* RB_EXT_DB_H */
diff --git a/plugins/artsearch/songinfo.py b/plugins/artsearch/songinfo.py
index f104041..62db362 100644
--- a/plugins/artsearch/songinfo.py
+++ b/plugins/artsearch/songinfo.py
@@ -76,9 +76,9 @@ class AlbumArtPage(object):
print("art added?")
self.art_update(key, data)
- def art_request_cb(self, key, filename, data):
+ def art_request_cb(self, key, skey, filename, data):
print("art request finished?")
- self.art_update(key, data)
+ self.art_update(skey, data)
def get_art(self, entry, user_explicit=False):
self.image.start(100)
diff --git a/plugins/ipod/rb-ipod-source.c b/plugins/ipod/rb-ipod-source.c
index d487e60..21059ec 100644
--- a/plugins/ipod/rb-ipod-source.c
+++ b/plugins/ipod/rb-ipod-source.c
@@ -1537,7 +1537,7 @@ rb_add_artwork_whole_album_cb (GtkTreeModel *query_model,
}
static void
-art_request_cb (RBExtDBKey *key, const char *filename, GValue *data, RBiPodSource *source)
+art_request_cb (RBExtDBKey *key, RBExtDBKey *store_key, const char *filename, GValue *data, RBiPodSource
*source)
{
RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
Itdb_Device *device;
diff --git a/plugins/mpris/rb-mpris-plugin.c b/plugins/mpris/rb-mpris-plugin.c
index 2245569..3d9b8ee 100644
--- a/plugins/mpris/rb-mpris-plugin.c
+++ b/plugins/mpris/rb-mpris-plugin.c
@@ -594,7 +594,7 @@ build_track_metadata (RBMprisPlugin *plugin,
key = rhythmdb_entry_create_ext_db_key (entry, RHYTHMDB_PROP_ALBUM);
- art_filename = rb_ext_db_lookup (plugin->art_store, key);
+ art_filename = rb_ext_db_lookup (plugin->art_store, key, NULL);
if (art_filename != NULL) {
char *uri;
uri = g_filename_to_uri (art_filename, NULL, NULL);
diff --git a/plugins/mtpdevice/rb-mtp-source.c b/plugins/mtpdevice/rb-mtp-source.c
index 61e34dd..b10844a 100644
--- a/plugins/mtpdevice/rb-mtp-source.c
+++ b/plugins/mtpdevice/rb-mtp-source.c
@@ -1095,7 +1095,7 @@ get_db_for_source (RBMtpSource *source)
}
static void
-art_request_cb (RBExtDBKey *key, const char *filename, GValue *data, RBMtpSource *source)
+art_request_cb (RBExtDBKey *key, RBExtDBKey *store_key, const char *filename, GValue *data, RBMtpSource
*source)
{
RBMtpSourcePrivate *priv = MTP_SOURCE_GET_PRIVATE (source);
diff --git a/plugins/notification/rb-notification-plugin.c b/plugins/notification/rb-notification-plugin.c
index 7af1373..3e75f3f 100644
--- a/plugins/notification/rb-notification-plugin.c
+++ b/plugins/notification/rb-notification-plugin.c
@@ -363,7 +363,7 @@ get_artist_album_templates (const char *artist,
}
static void
-art_cb (RBExtDBKey *key, const char *filename, GValue *data, RBNotificationPlugin *plugin)
+art_cb (RBExtDBKey *key, RBExtDBKey *store_key, const char *filename, GValue *data, RBNotificationPlugin
*plugin)
{
RhythmDBEntry *entry;
@@ -372,7 +372,7 @@ art_cb (RBExtDBKey *key, const char *filename, GValue *data, RBNotificationPlugi
return;
}
- if (rhythmdb_entry_matches_ext_db_key (plugin->db, entry, key)) {
+ if (rhythmdb_entry_matches_ext_db_key (plugin->db, entry, store_key)) {
guint elapsed = 0;
plugin->notify_art_path = g_strdup (filename);
diff --git a/plugins/visualizer/rb-visualizer-fullscreen.c b/plugins/visualizer/rb-visualizer-fullscreen.c
index 1443961..f575e66 100644
--- a/plugins/visualizer/rb-visualizer-fullscreen.c
+++ b/plugins/visualizer/rb-visualizer-fullscreen.c
@@ -80,7 +80,7 @@ set_blank_image (MxFrame *frame)
}
static void
-art_cb (RBExtDBKey *key, const char *filename, GValue *data, MxFrame *frame)
+art_cb (RBExtDBKey *key, RBExtDBKey *store_key, const char *filename, GValue *data, MxFrame *frame)
{
ClutterActor *image;
GdkPixbuf *pixbuf;
diff --git a/widgets/rb-header.c b/widgets/rb-header.c
index 82fdb3f..67114b8 100644
--- a/widgets/rb-header.c
+++ b/widgets/rb-header.c
@@ -475,7 +475,7 @@ rb_header_finalize (GObject *object)
}
static void
-art_cb (RBExtDBKey *key, const char *filename, GValue *data, RBHeader *header)
+art_cb (RBExtDBKey *key, RBExtDBKey *store_key, const char *filename, GValue *data, RBHeader *header)
{
RhythmDBEntry *entry;
@@ -484,7 +484,7 @@ art_cb (RBExtDBKey *key, const char *filename, GValue *data, RBHeader *header)
return;
}
- if (rhythmdb_entry_matches_ext_db_key (header->priv->db, entry, key)) {
+ if (rhythmdb_entry_matches_ext_db_key (header->priv->db, entry, store_key)) {
GdkPixbuf *pixbuf = NULL;
if (data != NULL && G_VALUE_HOLDS (data, GDK_TYPE_PIXBUF)) {
@@ -503,7 +503,7 @@ art_cb (RBExtDBKey *key, const char *filename, GValue *data, RBHeader *header)
static void
art_added_cb (RBExtDB *db, RBExtDBKey *key, const char *filename, GValue *data, RBHeader *header)
{
- art_cb (key, filename, data, header);
+ art_cb (key, key, filename, data, header);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]