HydrogenAudio

Hosted Forums => foobar2000 => Development - (fb2k) => Topic started by: MordredKLB on 2018-02-07 06:55:38

Title: Watching tag edits to update metadb hashes
Post by: MordredKLB on 2018-02-07 06:55:38
So thanks to Peter's help I've been able to get my plugin working correctly with creating a metadb, and storing values in it based on a hash.  Now what I need is a way to move the data in the metadb from the old to new hash when tag content changes (I'm trying to emulate foo_playcount's behavior).

I'm using metadb_io_edit_callback because I need before and after values. Here's what I've got so far:

Code: [Select]
	class metadb_io_edit_callback_impl : public metadb_io_edit_callback {
public:
typedef const pfc::list_base_const_t<const file_info*> & t_infosref;
void on_edited(metadb_handle_list_cref items, t_infosref before, t_infosref after) {
for (size_t t = 0; t < items.get_count(); t++) {
metadb_handle_ptr p_item = items[t];
file_info_impl info;
if (p_item->get_info(info)) {
pfc::string8 artist;
pfc::string8 album;
pfc::string8 title;
artist = info.meta_get("ARTIST", 0);
album = info.meta_get("ALBUM", 0);
title = info.meta_get("TITLE", 0);
metadb_index_hash hash;
g_client->hashHandle(p_item, hash);
FB2K_console_formatter() << artist << " - " << album << " - " << title << " - " << hash;

artist = after[t]->meta_get("ARTIST", 0);
album = after[t]->meta_get("ALBUM", 0);
title = after[t]->meta_get("TITLE", 0);
FB2K_console_formatter() << "after: " << artist << " - " << album << " - " << title;
}
}
}
};

static service_factory_single_t<metadb_io_edit_callback_impl> g_my_metadb_io;

This works great so far. Calling meta_get on the entries in metadb_handle_list_cref spits out the old pre-edit values just fine, and because it's the old values I can only assume that the hash is the pre-edit hash. Calling meta_get() on the after[t] also returns the post-edit values. I'm logging to the console for sanity purposes and it all looks correct.

Where I'm stuck now is I'm not sure how to actually take the file_info* I get from after[t] and turn that into the new hash. Maybe I have to do this manually the same way it's done in the metadb_index_client::transform() I have?

I obviously also need to figure out how to copy the value at the old hash and store it at the new hash, but I assume that's mostly trivial once I know what the post change hash is going to be.

Any help you guys can provide would be much appreciated.
Title: Re: Watching tag edits to update metadb hashes
Post by: MordredKLB on 2018-02-10 03:12:47
In case anyone was having the same issue I was, I figured out how to do it. I'm not 100% sure if this is the BEST way to do it, and I really hate being forced to use individual meta_get's instead of a single title format, but unless I'm missing something meta_get is the only option on a file_info*.

Code: [Select]
	class metadb_io_edit_callback_impl : public metadb_io_edit_callback {
public:
typedef const pfc::list_base_const_t<const file_info*> & t_infosref;
void on_edited(metadb_handle_list_cref items, t_infosref before, t_infosref after) {
static static_api_ptr_t<metadb_index_manager> api; // initialized once here
for (size_t t = 0; t < items.get_count(); t++) {
metadb_index_hash hashOld, hashNew;

g_client->hashHandle(items[t], hashOld);

// my hash is pinned to "%artist% %album% $if2(%discnumber%,1) %tracknumber% %title%
pfc::string8 artist = meta_get_if_exists(after[t], "ARTIST", "");
pfc::string8 album = meta_get_if_exists(after[t], "ALBUM", "");
pfc::string8 discnum = meta_get_if_exists(after[t], "DISCNUMBER", "1");
pfc::string8 tracknum = meta_get_if_exists(after[t], "TRACKNUMBER", "");
pfc::string8 title = meta_get_if_exists(after[t], "TITLE", "");

pfc::string_formatter strAfter;
strAfter << artist << " " << album << " " << discnum << " " << tracknum << " " << title;

hashNew = static_api_ptr_t<hasher_md5>()->process_single_string(strAfter).xorHalve();
if (hashOld != hashNew) {
record_t record = getRecord(hashOld, api); // this is my function for retrieving the data structure from metadb
record_t newRecord = getRecord(hashNew, api);
// use whatever logic you want to determine if a record at the old hash exists and whether to overwrite a record at the new hash
}
}
}
};

static service_factory_single_t<metadb_io_edit_callback_impl> g_my_metadb_io;

// helper function to get meta value or return default if not found. equivalent to $if2
pfc::string8 meta_get_if_exists(const file_info * info, const char* key, const char* default) {
if (info->meta_exists(key)) {
return info->meta_get(key, 0);
}
return default;
}