summaryrefslogtreecommitdiff
path: root/plugins/gtkui/trkproperties.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/gtkui/trkproperties.c')
-rw-r--r--plugins/gtkui/trkproperties.c236
1 files changed, 234 insertions, 2 deletions
diff --git a/plugins/gtkui/trkproperties.c b/plugins/gtkui/trkproperties.c
index cf6af9a8..66eb24e8 100644
--- a/plugins/gtkui/trkproperties.c
+++ b/plugins/gtkui/trkproperties.c
@@ -23,6 +23,7 @@
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <math.h>
+#include <assert.h>
#include "../../gettext.h"
#include "ddblistview.h"
#include "trkproperties.h"
@@ -37,12 +38,71 @@
//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
#define trace(fmt,...)
+#define min(x,y) ((x)<(y)?(x):(y))
+
static GtkWidget *trackproperties;
static DB_playItem_t *track;
static GtkCellRenderer *rend_text2;
static GtkListStore *store;
static GtkListStore *propstore;
static int trkproperties_modified;
+static DB_playItem_t **tracks;
+static int numtracks;
+
+static void
+build_key_list () {
+}
+
+static int
+get_field_value (char *out, int size, const char *key) {
+ int multiple = 0;
+ *out = 0;
+ if (numtracks == 0) {
+ return 0;
+ }
+ char *p = out;
+ deadbeef->pl_lock ();
+ const char **prev = malloc (sizeof (const char *) * numtracks);
+ memset (prev, 0, sizeof (const char *) * numtracks);
+ for (int i = 0; i < numtracks; i++) {
+ const char *val = deadbeef->pl_find_meta (tracks[i], key);
+ if (val && val[0] == 0) {
+ val = NULL;
+ }
+ if (i > 0) {
+ int n = 0;
+ for (; n < i; n++) {
+ if (prev[n] == val) {
+ break;
+ }
+ }
+ if (n == i) {
+ size_t l;
+ l = snprintf (out, size, "; %s", val ? val : "");
+ multiple = 1;
+ l = min (l, size);
+ out += l;
+ size -= l;
+ }
+ }
+ else {
+ size_t l = snprintf (out, size, "%s", val ? val : "");
+ l = min (l, size);
+ out += l;
+ size -= l;
+ }
+ prev[i] = val;
+ if (size <= 1) {
+ break;
+ }
+ }
+ if (size <= 1) {
+ strcpy (out-2, "…");
+ }
+ free (prev);
+ deadbeef->pl_unlock ();
+ return multiple;
+}
gboolean
on_trackproperties_delete_event (GtkWidget *widget,
@@ -68,6 +128,14 @@ on_trackproperties_delete_event (GtkWidget *widget,
deadbeef->pl_item_unref (track);
track = NULL;
}
+ if (tracks) {
+ for (int i = 0; i < numtracks; i++) {
+ deadbeef->pl_item_unref (tracks[i]);
+ }
+ free (tracks);
+ tracks = NULL;
+ numtracks = 0;
+ }
return TRUE;
}
@@ -143,6 +211,8 @@ trkproperties_fill_metadata (void) {
gtk_list_store_clear (store);
deadbeef->pl_lock ();
+ struct timeval tm1;
+ gettimeofday (&tm1, NULL);
// add "standard" fields
int i = 0;
while (types[i]) {
@@ -150,9 +220,15 @@ trkproperties_fill_metadata (void) {
if (!value) {
value = "";
}
+ const char mult[] = _("[Multiple values] ");
+ char val[1000];
+ size_t ml = strlen (mult);
+ memcpy (val, mult, ml+1);
+ int n = get_field_value (val + ml, sizeof (val) - ml, types[i]);
+
GtkTreeIter iter;
gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, 0, _(types[i+1]), 1, value, 2, types[i], -1);
+ gtk_list_store_set (store, &iter, 0, _(types[i+1]), 1, n ? val : val + ml, 2, types[i], -1);
i += 2;
}
@@ -222,6 +298,13 @@ trkproperties_fill_metadata (void) {
snprintf (title, sizeof (title), "<%s>", meta->key);
const char *value = meta->value;
const char *key = meta->key;
+
+ const char mult[] = _("[Multiple values] ");
+ char val[1000];
+ size_t ml = strlen (mult);
+ memcpy (val, mult, ml+1);
+ int n = get_field_value (val + ml, sizeof (val) - ml, meta->key);
+
meta = meta->next;
if (!value) {
@@ -230,14 +313,58 @@ trkproperties_fill_metadata (void) {
GtkTreeIter iter;
gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, 0, _(title), 1, value, 2, key, -1);
+ gtk_list_store_set (store, &iter, 0, _(title), 1, n ? val : val + ml, 2, key, -1);
}
+ struct timeval tm2;
+ gettimeofday (&tm2, NULL);
+ int ms = (tm2.tv_sec*1000+tm2.tv_usec/1000) - (tm1.tv_sec*1000+tm1.tv_usec/1000);
deadbeef->pl_unlock ();
}
void
show_track_properties_dlg (DB_playItem_t *it) {
+
+ deadbeef->plt_lock ();
+ deadbeef->pl_lock ();
+
+ if (tracks) {
+ for (int i = 0; i < numtracks; i++) {
+ deadbeef->pl_item_unref (tracks[i]);
+ }
+ free (tracks);
+ tracks = NULL;
+ numtracks = 0;
+ }
+
+ int nsel = deadbeef->pl_getselcount ();
+ if (0 < nsel) {
+ tracks = malloc (sizeof (DB_playItem_t *) * nsel);
+ if (tracks) {
+ int n = 0;
+ DB_playItem_t *it = deadbeef->pl_get_first (PL_MAIN);
+ while (it) {
+ if (deadbeef->pl_is_selected (it)) {
+ assert (n < nsel);
+ deadbeef->pl_item_ref (it);
+ tracks[n++] = it;
+ }
+ DB_playItem_t *next = deadbeef->pl_get_next (it, PL_MAIN);
+ deadbeef->pl_item_unref (it);
+ it = next;
+ }
+ numtracks = nsel;
+ }
+ else {
+ deadbeef->pl_unlock ();
+ deadbeef->plt_unlock ();
+ return;
+ }
+ }
+
+ deadbeef->pl_unlock ();
+ deadbeef->plt_unlock ();
+
if (track) {
deadbeef->pl_item_unref (track);
track = NULL;
@@ -377,3 +504,108 @@ on_write_tags_clicked (GtkButton *button,
}
trkproperties_modified = 0;
}
+
+void
+on_add_field_activate (GtkMenuItem *menuitem,
+ gpointer user_data) {
+ GtkWidget *dlg = create_entrydialog ();
+ gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK);
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Edit playlist"));
+ GtkWidget *e;
+ e = lookup_widget (dlg, "title_label");
+ gtk_label_set_text (GTK_LABEL(e), _("Name:"));
+ int res = gtk_dialog_run (GTK_DIALOG (dlg));
+ if (res == GTK_RESPONSE_OK) {
+ e = lookup_widget (dlg, "title");
+ const char *text = gtk_entry_get_text (GTK_ENTRY(e));
+
+ int l = strlen (text);
+ char title[l+3];
+ snprintf (title, sizeof (title), "<%s>", text);
+ const char *value = "";
+ const char *key = text;
+
+ GtkTreeIter iter;
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, title, 1, value, 2, key, -1);
+ trkproperties_modified = 1;
+
+ }
+ gtk_widget_destroy (dlg);
+}
+
+void
+on_remove_field_activate (GtkMenuItem *menuitem,
+ gpointer user_data) {
+
+ GtkTreePath *path;
+ GtkTreeViewColumn *col;
+ GtkTreeView *treeview = GTK_TREE_VIEW (lookup_widget (trackproperties, "metalist"));
+ gtk_tree_view_get_cursor (treeview, &path, &col);
+ if (!path || !col) {
+ return;
+ }
+
+ GtkWidget *dlg = gtk_message_dialog_new (GTK_WINDOW (mainwin), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("Really remove selected field?"));
+// gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg), _("Files will be lost. Proceed?\n(This dialog can be turned off in GTKUI plugin settings)"));
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Warning"));
+
+ int response = gtk_dialog_run (GTK_DIALOG (dlg));
+ gtk_widget_destroy (dlg);
+ if (response != GTK_RESPONSE_YES) {
+ return;
+ }
+
+ GtkTreeIter iter;
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
+ GValue value = {0,};
+ gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, 2, &value);
+ const char *svalue = g_value_get_string (&value);
+
+ // delete unknown fields completely; otherwise just clear
+ int i = 0;
+ for (; types[i]; i += 2) {
+ if (!strcmp (svalue, types[i])) {
+ break;
+ }
+ }
+ if (types[i]) { // known val, clear
+ gtk_list_store_set (store, &iter, 1, "", -1);
+ }
+ else {
+ gtk_list_store_remove (store, &iter);
+ }
+ gtk_tree_path_free (path);
+ trkproperties_modified = 1;
+}
+
+gboolean
+on_metalist_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ if (event->button == 3) {
+ GtkWidget *menu;
+ GtkWidget *add;
+ GtkWidget *remove;
+ menu = gtk_menu_new ();
+ add = gtk_menu_item_new_with_mnemonic (_("Add field"));
+ gtk_widget_show (add);
+ gtk_container_add (GTK_CONTAINER (menu), add);
+ remove = gtk_menu_item_new_with_mnemonic (_("Remove field"));
+ gtk_widget_show (remove);
+ gtk_container_add (GTK_CONTAINER (menu), remove);
+
+ g_signal_connect ((gpointer) add, "activate",
+ G_CALLBACK (on_add_field_activate),
+ NULL);
+
+ g_signal_connect ((gpointer) remove, "activate",
+ G_CALLBACK (on_remove_field_activate),
+ NULL);
+
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, widget, event->button, gtk_get_current_event_time());
+ }
+ return FALSE;
+}
+