changeset 4027:501f9671be9b

branch merge
author Yoshiki Yazawa <yaz@cc.rim.or.jp>
date Wed, 28 Nov 2007 06:02:59 +0900
parents 17bf734f8187 (current diff) 4f9cf3173e2d (diff)
children 76da6fe8cb39 0b004b3bfb70
files
diffstat 2 files changed, 128 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/src/audacious/plugin.h	Wed Nov 28 06:01:28 2007 +0900
+++ b/src/audacious/plugin.h	Wed Nov 28 06:02:59 2007 +0900
@@ -1087,6 +1087,19 @@
 
     /* Added in Audacious 1.5.0 */
     gboolean (*update_song_tuple)(Tuple *tuple, VFSFile *fd);
+    /* 
+     * Plugin can provide this function for file metadata (aka tag) writing functionality
+     * in case when no reason to provide its own custom file info dialog. Thus in most cases.
+     *
+     * Some notes:
+     *
+     * 1. In current Audacious version, if plugin provides file_info_box(), the latter will be used in any case.
+     * 2. Each field in tuple means operation on one and only one tag's filed:
+     *     2.1. Set this field to appropriate value, if non-empty string or positive number provided.
+     *     2.2. Set this field to blank (or just delete, at plugins`s discretion), if empty string or negative number provided.
+     *
+     * -- eugene.
+     */
 };
 
 struct _GeneralPlugin {
--- a/src/audacious/ui_fileinfo.c	Wed Nov 28 06:01:28 2007 +0900
+++ b/src/audacious/ui_fileinfo.c	Wed Nov 28 06:02:59 2007 +0900
@@ -61,6 +61,7 @@
 #include "ui_playlist.h"
 
 #define G_FREE_CLEAR(a) { if(a != NULL) { g_free(a); a = NULL; } }
+#define STATUS_TIMEOUT 3*1000
 
 GtkWidget *fileinfo_win;
 
@@ -79,9 +80,11 @@
 GtkWidget *label_format_name;
 GtkWidget *label_quality;
 GtkWidget *btn_apply;
+GtkWidget *label_mini_status;
 
 static gchar *current_file = NULL;
 static InputPlugin *current_ip = NULL;
+static gboolean something_changed = FALSE;
 
 static void
 fileinfo_entry_set_text(GtkWidget *widget, const char *text)
@@ -93,18 +96,19 @@
 }
 
 static void
-set_entry_str_from_field(GtkWidget *widget, Tuple *tuple, gint fieldn)
+set_entry_str_from_field(GtkWidget *widget, Tuple *tuple, gint fieldn, gboolean editable)
 {
     gchar *text;
 
     if(widget != NULL) {
         text = (gchar*)tuple_get_string(tuple, fieldn, NULL);
         gtk_entry_set_text(GTK_ENTRY(widget), text != NULL ? text : "");
+        gtk_editable_set_editable(GTK_EDITABLE(widget), editable);
     }
 }
 
 static void
-set_entry_int_from_field(GtkWidget *widget, Tuple *tuple, gint fieldn)
+set_entry_int_from_field(GtkWidget *widget, Tuple *tuple, gint fieldn, gboolean editable)
 {
     gchar *text;
 
@@ -113,9 +117,11 @@
     if(tuple_get_value_type(tuple, fieldn, NULL) == TUPLE_INT) {
         text = g_strdup_printf("%d", tuple_get_int(tuple, fieldn, NULL));
         gtk_entry_set_text(GTK_ENTRY(widget), text);
+        gtk_editable_set_editable(GTK_EDITABLE(widget), editable);
         g_free(text);
     } else {
         gtk_entry_set_text(GTK_ENTRY(widget), "");
+        gtk_editable_set_editable(GTK_EDITABLE(widget), editable);
     }
 }
 
@@ -129,8 +135,14 @@
 static void
 set_field_int_from_entry(Tuple *tuple, gint fieldn, GtkWidget *widget)
 {
+    gchar *tmp;
     if(widget == NULL) return;
-    tuple_associate_int(tuple, fieldn, NULL, atoi(gtk_entry_get_text(GTK_ENTRY(widget))));
+
+    tmp = (gchar*)gtk_entry_get_text(GTK_ENTRY(widget));
+    if(*tmp != '\0')
+        tuple_associate_int(tuple, fieldn, NULL, atoi(tmp));
+    else
+        tuple_associate_int(tuple, fieldn, NULL, -1);
 }
 
 static void
@@ -208,6 +220,14 @@
 
     fileinfo_label_set_text(label_format_name, NULL);
     fileinfo_label_set_text(label_quality, NULL);
+    
+    if (label_mini_status != NULL) {
+        gtk_label_set_text(GTK_LABEL(label_mini_status), "<span size=\"small\"></span>");
+        gtk_label_set_use_markup(GTK_LABEL(label_mini_status), TRUE);
+    }
+    
+    something_changed = FALSE;
+    gtk_widget_set_sensitive(btn_apply, FALSE);
 
     current_ip = NULL;
     G_FREE_CLEAR(current_file);
@@ -215,11 +235,54 @@
     fileinfo_entry_set_image(image_artwork, DATA_DIR "/images/audio.png");
 }
 
-static void fileinfo_update_tuple(gpointer data)
+static void entry_changed (GtkEditable *editable, gpointer user_data)
+{
+    if(current_file != NULL && current_ip != NULL && current_ip->update_song_tuple != NULL) {
+        something_changed = TRUE;
+        gtk_widget_set_sensitive(btn_apply, TRUE);
+    }
+}
+
+static gboolean
+ministatus_timeout_proc (gpointer data)
+{
+    GtkLabel *status = GTK_LABEL(data);
+    gtk_label_set_text(status, "<span size=\"small\"></span>");
+    gtk_label_set_use_markup(status, TRUE);
+
+    return FALSE;
+}
+
+static void
+ministatus_display_message(gchar *text)
+{
+    if(label_mini_status != NULL) {
+        gchar *tmp = g_strdup_printf("<span size=\"small\">%s</span>", text);
+        gtk_label_set_text(GTK_LABEL(label_mini_status), tmp);
+        g_free(tmp);
+        gtk_label_set_use_markup(GTK_LABEL(label_mini_status), TRUE);
+        g_timeout_add (STATUS_TIMEOUT, (GSourceFunc) ministatus_timeout_proc, (gpointer) label_mini_status);
+    }
+}
+
+static void
+message_update_successfull()
+{
+    ministatus_display_message(_("Metadata updated successfully"));
+}
+
+static void
+message_update_failed()
+{
+    ministatus_display_message(_("Metadata updating failed"));
+}
+
+static void
+fileinfo_update_tuple(gpointer data)
 {
         Tuple *tuple;
         VFSFile *fd;
-        if(current_file != NULL && current_ip != NULL && current_ip->update_song_tuple != NULL) { /* TODO only if changed*/
+        if(current_file != NULL && current_ip != NULL && current_ip->update_song_tuple != NULL && something_changed) {
 
             tuple = tuple_new();
             fd = vfs_fopen(current_file, "r+b");
@@ -235,18 +298,17 @@
                 set_field_int_from_entry(tuple, FIELD_TRACK_NUMBER, entry_track);
                 
                 if(current_ip->update_song_tuple(tuple, fd)) {
-                    /* TODO display ok */
-                    fprintf(stderr, "fileinfo_update_tuple(): updated\n");
+                    message_update_successfull();
+                    something_changed = FALSE;
+                    gtk_widget_set_sensitive(btn_apply, FALSE);
                 } else {
-                    /* TODO error message */
-                    fprintf(stderr, "fileinfo_update_tuple(): failed\n");
+                    message_update_failed();
                 }
 
                 vfs_fclose(fd);
 
             } else {
-                /* TODO: error message */
-                fprintf(stderr, "fileinfo_update_tuple(): can't open file %s\n", current_file);
+                message_update_failed();
             }
 
             mowgli_object_unref(tuple);
@@ -319,6 +381,8 @@
 create_fileinfo_window(void)
 {
     GtkWidget *hbox;
+    GtkWidget *hbox_status_and_bbox;
+    GtkWidget *vbox0;
     GtkWidget *vbox1;
     GtkWidget *vbox2;
     GtkWidget *label_title;
@@ -348,8 +412,11 @@
     gtk_window_set_type_hint(GTK_WINDOW(fileinfo_win), GDK_WINDOW_TYPE_HINT_DIALOG);
     gtk_window_set_transient_for(GTK_WINDOW(fileinfo_win), GTK_WINDOW(mainwin));
 
+    vbox0 = gtk_vbox_new(FALSE, 0);
+    gtk_container_add(GTK_CONTAINER(fileinfo_win), vbox0);
+
     hbox = gtk_hbox_new(FALSE, 6);
-    gtk_container_add(GTK_CONTAINER(fileinfo_win), hbox);
+    gtk_box_pack_start(GTK_BOX(vbox0), hbox, TRUE, TRUE, 0);
 
     image_artwork = gtk_image_new();
     gtk_box_pack_start(GTK_BOX(hbox), image_artwork, FALSE, FALSE, 0);
@@ -423,6 +490,7 @@
     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
     entry_title = gtk_entry_new();
     gtk_container_add(GTK_CONTAINER(alignment), entry_title);
+    g_signal_connect(G_OBJECT(entry_title), "changed", (GCallback) entry_changed, NULL);
 
     label_artist = gtk_label_new(_("<span size=\"small\">Artist</span>"));
     gtk_box_pack_start(GTK_BOX(vbox2), label_artist, FALSE, FALSE, 0);
@@ -434,6 +502,7 @@
     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
     entry_artist = gtk_entry_new();
     gtk_container_add(GTK_CONTAINER(alignment), entry_artist);
+    g_signal_connect(G_OBJECT(entry_artist), "changed", (GCallback) entry_changed, NULL);
 
     label_album = gtk_label_new(_("<span size=\"small\">Album</span>"));
     gtk_box_pack_start(GTK_BOX(vbox2), label_album, FALSE, FALSE, 0);
@@ -445,6 +514,7 @@
     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
     entry_album = gtk_entry_new();
     gtk_container_add(GTK_CONTAINER(alignment), entry_album);
+    g_signal_connect(G_OBJECT(entry_album), "changed", (GCallback) entry_changed, NULL);
 
     label_comment = gtk_label_new(_("<span size=\"small\">Comment</span>"));
     gtk_box_pack_start(GTK_BOX(vbox2), label_comment, FALSE, FALSE, 0);
@@ -456,6 +526,7 @@
     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
     entry_comment = gtk_entry_new();
     gtk_container_add (GTK_CONTAINER(alignment), entry_comment);
+    g_signal_connect(G_OBJECT(entry_comment), "changed", (GCallback) entry_changed, NULL);
 
     label_genre = gtk_label_new(_("<span size=\"small\">Genre</span>"));
     gtk_box_pack_start(GTK_BOX(vbox2), label_genre, FALSE, FALSE, 0);
@@ -467,6 +538,7 @@
     gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
     entry_genre = gtk_entry_new();
     gtk_container_add(GTK_CONTAINER(alignment), entry_genre);
+    g_signal_connect(G_OBJECT(entry_genre), "changed", (GCallback) entry_changed, NULL);
 
     alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
     gtk_box_pack_start(GTK_BOX(vbox2), alignment, FALSE, FALSE, 0);
@@ -486,6 +558,7 @@
     gtk_table_attach(GTK_TABLE(table1), entry_year, 0, 1, 1, 2,
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                      (GtkAttachOptions) (0), 0, 0);
+    g_signal_connect(G_OBJECT(entry_year), "changed", (GCallback) entry_changed, NULL);
 
     label_track = gtk_label_new(_("<span size=\"small\">Track Number</span>"));
     gtk_table_attach(GTK_TABLE(table1), label_track, 1, 2, 0, 1,
@@ -498,6 +571,7 @@
     gtk_table_attach(GTK_TABLE(table1), entry_track, 1, 2, 1, 2,
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
                      (GtkAttachOptions) (0), 0, 0);
+    g_signal_connect(G_OBJECT(entry_track), "changed", (GCallback) entry_changed, NULL);
 
     label_location = gtk_label_new(_("<span size=\"small\">Location</span>"));
     gtk_box_pack_start(GTK_BOX(vbox2), label_location, FALSE, FALSE, 0);
@@ -510,10 +584,19 @@
 
     entry_location = gtk_entry_new();
     gtk_container_add(GTK_CONTAINER(alignment), entry_location);
+    gtk_editable_set_editable(GTK_EDITABLE(entry_location), FALSE);
+    
+    hbox_status_and_bbox = gtk_hbox_new(FALSE, 0);
+    gtk_box_pack_start (GTK_BOX (vbox0), hbox_status_and_bbox, FALSE, FALSE, 0);
+
+    label_mini_status = gtk_label_new("<span size=\"small\"></span>");
+    gtk_label_set_use_markup(GTK_LABEL(label_mini_status), TRUE);
+    gtk_misc_set_alignment(GTK_MISC(label_mini_status), 0, 0.5);
+    gtk_box_pack_start (GTK_BOX (hbox_status_and_bbox), label_mini_status, TRUE, TRUE, 0);
     
     bbox_close = gtk_hbutton_box_new();
     gtk_box_set_spacing(GTK_BOX(bbox_close), 6);
-    gtk_box_pack_start(GTK_BOX(vbox1), bbox_close, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox_status_and_bbox), bbox_close, FALSE, FALSE, 0);
     gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox_close), GTK_BUTTONBOX_END);
 
     btn_apply = gtk_button_new_from_stock("gtk-apply");
@@ -526,7 +609,7 @@
     GTK_WIDGET_SET_FLAGS(btn_close, GTK_CAN_DEFAULT);
     g_signal_connect(G_OBJECT(btn_close), "clicked", (GCallback) fileinfo_hide, NULL);
 
-    gtk_widget_show_all (hbox);
+    gtk_widget_show_all (vbox0);
 }
 
 void 
@@ -543,13 +626,15 @@
             G_FREE_CLEAR(current_file);
         }
 
+        something_changed = FALSE;
+
         if(!GTK_WIDGET_REALIZED(fileinfo_win)) gtk_widget_realize(fileinfo_win);
 
-        set_entry_str_from_field(entry_title, tuple, FIELD_TITLE);
-        set_entry_str_from_field(entry_artist, tuple, FIELD_ARTIST);
-        set_entry_str_from_field(entry_album, tuple, FIELD_ALBUM);
-        set_entry_str_from_field(entry_comment, tuple, FIELD_COMMENT);
-        set_entry_str_from_field(entry_genre, tuple, FIELD_GENRE);
+        set_entry_str_from_field(entry_title, tuple, FIELD_TITLE, updating_enabled);
+        set_entry_str_from_field(entry_artist, tuple, FIELD_ARTIST, updating_enabled);
+        set_entry_str_from_field(entry_album, tuple, FIELD_ALBUM, updating_enabled);
+        set_entry_str_from_field(entry_comment, tuple, FIELD_COMMENT, updating_enabled);
+        set_entry_str_from_field(entry_genre, tuple, FIELD_GENRE, updating_enabled);
 
         tmp = g_strdup_printf("%s/%s",
                 tuple_get_string(tuple, FIELD_FILE_PATH, NULL),
@@ -563,8 +648,8 @@
         }
         
         /* set empty string if field not availaible. --eugene */
-        set_entry_int_from_field(entry_year, tuple, FIELD_YEAR);
-        set_entry_int_from_field(entry_track, tuple, FIELD_TRACK_NUMBER);
+        set_entry_int_from_field(entry_year, tuple, FIELD_YEAR, updating_enabled);
+        set_entry_int_from_field(entry_track, tuple, FIELD_TRACK_NUMBER, updating_enabled);
 
         fileinfo_label_set_text(label_format_name, tuple_get_string(tuple, FIELD_CODEC, NULL));
         fileinfo_label_set_text(label_quality, tuple_get_string(tuple, FIELD_QUALITY, NULL));
@@ -586,10 +671,17 @@
                 g_free(tmp);
         }
 
-        if(updating_enabled && current_file != NULL && current_ip != NULL && current_ip->update_song_tuple != NULL)
+        /*if(updating_enabled && current_file != NULL && current_ip != NULL && current_ip->update_song_tuple != NULL)
                 gtk_widget_set_sensitive(btn_apply, TRUE);
         else
-                gtk_widget_set_sensitive(btn_apply, FALSE);
+                gtk_widget_set_sensitive(btn_apply, FALSE);*/
+        
+        gtk_widget_set_sensitive(btn_apply, FALSE);
+    
+        if (label_mini_status != NULL) {
+            gtk_label_set_text(GTK_LABEL(label_mini_status), "<span size=\"small\"></span>");
+            gtk_label_set_use_markup(GTK_LABEL(label_mini_status), TRUE);
+        }
         
         if(! GTK_WIDGET_VISIBLE(fileinfo_win)) gtk_widget_show(fileinfo_win);
 }