Re: [Easytag-mailing] EasyTAG 0.31_gtk2.4_pre2 has been released!



Hi!

Attached patch is a new version of the previous cover art patch.
Features:

   - Multiple pictures
   - Picture types (cover front/back, leaflet page, artist etc.)
   - Picture descriptions
   - Add pictures by drag-and-drop from Nautilus or File Chooser
   - Save pictures
   - Remove pictures
   - JPEG and PNG supported

Diffstat:

   easytag.c |  502 +++++++++++++++++++++-
   easytag.h |    2
   et_core.c |  295 ++++++++++++
   et_core.h |   57 ++
   id3_tag.c |   93 +++-
   misc.c    |  115 +++++
   misc.h    |    8
   7 files changed, 1066 insertions(+), 6 deletions(-)

Fredrik

diff -Naur easytag-0.31_gtk2.4_pre2.orig/src/easytag.c easytag-0.31_gtk2.4_pre2/src/easytag.c
--- easytag-0.31_gtk2.4_pre2.orig/src/easytag.c	2004-08-21 23:53:46.000000000 +0200
+++ easytag-0.31_gtk2.4_pre2/src/easytag.c	2004-09-12 15:05:17.000000000 +0200
@@ -71,6 +71,9 @@
 /* To remember which button was pressed when deleting file */
 gint     SF_ButtonPressed_Delete_File;
 
+GtkWidget *Picture_Save_Button;
+GtkWidget *Picture_Properties_Button;
+
 
 /**************
  * Prototypes *
@@ -407,6 +410,341 @@
     return FileFrame;
 }
 
+enum {
+  TARGET_URI_LIST
+};
+
+void Tag_Area_Picture_Data(GtkWidget *widget, GdkDragContext *dc, 
+			      gint x, gint y, GtkSelectionData *selection_data,
+			      guint info, guint t, gpointer data)
+{
+	GtkTreeSelection *selection;
+	gchar **uri_list, **uri;
+
+	gtk_drag_finish(dc, TRUE, FALSE, t);
+
+	if (info != TARGET_URI_LIST)
+		return;
+	if(!selection_data)
+		return;
+
+	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(PictureEntry));
+	gtk_tree_selection_unselect_all(selection);
+	
+	uri = uri_list = g_strsplit(selection_data->data, "\r\n", 0);
+	while(*uri && strlen(*uri))
+	{
+		struct Picture *pic;
+		gchar *filename;
+
+		filename = g_filename_from_uri(*uri, 0, 0);
+		if(filename)
+		{
+			pic = Load_Picture(filename);
+			g_free(filename);
+			if(pic)
+				Update_PictureEntry(pic, 1);
+		}
+		uri++;
+	}
+	g_strfreev(uri_list);
+}
+
+static void Picture_Selection_Changed_cb(GtkTreeSelection *selection,
+					 gpointer data)
+{
+	if(gtk_tree_selection_count_selected_rows(GTK_TREE_SELECTION(selection)) == 1)
+	{
+		gtk_widget_set_sensitive(G_OBJECT(Picture_Save_Button), TRUE);
+		gtk_widget_set_sensitive(G_OBJECT(Picture_Properties_Button), TRUE);
+	}
+	else
+	{
+		gtk_widget_set_sensitive(G_OBJECT(Picture_Save_Button), FALSE);
+		gtk_widget_set_sensitive(G_OBJECT(Picture_Properties_Button), FALSE);
+	}
+}
+
+void Clear_Picture_Button_Clicked(GObject *object)
+{
+	GList *paths, *refs = NULL, *node = NULL;
+	GtkTreeSelection *selection;
+	GtkTreeModel **model;
+	GtkTreeIter iter;
+	gpointer proxy;
+	int n = 0;
+	
+	model = gtk_tree_view_get_model(GTK_TREE_VIEW(PictureEntry));
+	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(PictureEntry));
+	paths = gtk_tree_selection_get_selected_rows(selection, 0);
+	proxy = g_object_newv(G_TYPE_OBJECT, 0, NULL);
+
+	for(node = paths; node; node = node->next)
+	{
+		refs = g_list_append(refs, gtk_tree_row_reference_new_proxy(proxy, model, node->data));
+		gtk_tree_path_free(node->data);
+	}
+	g_list_free(paths);
+
+	for(node = refs; node; node = node->next)
+	{
+		GtkTreePath *path =gtk_tree_row_reference_get_path(node->data);
+		struct Picture *pic;
+      
+		gtk_tree_model_get_iter(model, &iter, path);
+		
+		gtk_tree_model_get(model, &iter, PICTURE_DATA_COLUMN, &pic,-1);
+		Free_Picture(pic);
+		
+		gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+		gtk_tree_row_reference_deleted(proxy, path);
+		gtk_tree_path_free(path);
+		gtk_tree_row_reference_free(node->data);
+		n++;
+	}
+	g_list_free(refs);
+	
+	if(!n)
+		/* Delete all if no one was selected. */
+		Clear_PictureEntry();
+}
+
+void Open_Picture_Filename(gchar *filename, gpointer user_data)
+{
+	struct Picture *pic;
+	gchar *tmp;
+	
+        TRANSLATE_FILENAME(filename, tmp, TRUE);
+	pic = Load_Picture(filename);
+	g_free(filename);
+	if(pic)
+		Update_PictureEntry(pic, 1);
+}
+
+void Open_Picture_Button_Clicked(GObject *object)
+{
+    GtkWidget *FileSelectionWindow;
+    GtkWindow *parent_window = NULL;
+
+    parent_window = (GtkWindow*) gtk_widget_get_toplevel(object);
+    if (!GTK_WIDGET_TOPLEVEL(parent_window))
+    {
+        g_warning("Could not get parent window\n");
+        return;
+    }
+
+    FileSelectionWindow =
+	    gtk_file_chooser_dialog_new(_("Open pictures"),
+					parent_window,
+					GTK_FILE_CHOOSER_ACTION_OPEN,
+					GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+					GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+					NULL);
+    gtk_file_chooser_set_select_multiple(FileSelectionWindow, TRUE);
+
+    if (gtk_dialog_run(GTK_DIALOG(FileSelectionWindow)) == GTK_RESPONSE_ACCEPT)
+    {
+	    GtkTreeSelection *selection;
+	    GSList *list;
+
+	    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(PictureEntry));
+	    gtk_tree_selection_unselect_all(selection);
+	
+	    list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(FileSelectionWindow));
+	    g_slist_foreach(list, Open_Picture_Filename, 0);
+	    g_slist_free(list);
+    }
+    gtk_widget_destroy(FileSelectionWindow);
+}
+
+void save_selected_pic(GtkTreeModel *model, GtkTreePath *path,
+		       GtkTreeIter *iter, gchar *filename)
+{
+	struct Picture *pic;
+	
+	gtk_tree_model_get(model, iter, PICTURE_DATA_COLUMN, &pic, -1);
+	Save_Picture(pic, filename);
+}
+
+void get_selected_pic(GtkTreeModel *model, GtkTreePath *path,
+		      GtkTreeIter *iter, GtkTreeIter *iter_set)
+{
+	*iter_set = *iter;
+}
+
+void Properties_Picture_Button_Clicked (GObject *object)
+{
+	GtkWidget *dialog, *type, *label, *desc;
+	GtkWidget *ScrollWindowPictureTypes;
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+	GtkTreeSelection *selection;
+	GtkListStore *store;
+	struct Picture *pic;
+	GtkTreeModel *model2;
+	GtkTreeIter iter2, default_type_iter;
+	GtkWindow *parent_window = NULL;
+	int picture_types[] = 
+		{
+			PICTURE_TYPE_OTHER,
+			PICTURE_TYPE_FILE_ICON,
+			PICTURE_TYPE_OTHER_FILE_ICON,
+			PICTURE_TYPE_FRONT_COVER,
+			PICTURE_TYPE_BACK_COVER,
+			PICTURE_TYPE_LEAFLET_PAGE,
+			PICTURE_TYPE_MEDIA,
+			PICTURE_TYPE_LEAD_ARTIST_LEAD_PERFORMER_SOLOIST,
+			PICTURE_TYPE_ARTIST_PERFORMER,
+			PICTURE_TYPE_CONDUCTOR,
+			PICTURE_TYPE_BAND_ORCHESTRA,
+			PICTURE_TYPE_COMPOSER,
+			PICTURE_TYPE_LYRICIST_TEXT_WRITER,
+			PICTURE_TYPE_RECORDING_LOCATION,
+			PICTURE_TYPE_DURING_RECORDING,
+			PICTURE_TYPE_DURING_PERFORMANCE,
+			PICTURE_TYPE_MOVIDE_VIDEO_SCREEN_CAPTURE,
+			PICTURE_TYPE_A_BRIGHT_COLOURED_FISH,
+			PICTURE_TYPE_ILLUSTRATION,
+			PICTURE_TYPE_BAND_ARTIST_LOGOTYPE,
+			PICTURE_TYPE_PUBLISHER_STUDIO_LOGOTYPE
+		};
+	int i;
+	
+	parent_window = (GtkWindow*) gtk_widget_get_toplevel(object);
+	if (!GTK_WIDGET_TOPLEVEL(parent_window))
+	{
+		g_warning("Could not get parent window\n");
+		return;
+	}
+
+	model2 = gtk_tree_view_get_model(GTK_TREE_VIEW(PictureEntry));
+	gtk_tree_selection_selected_foreach(gtk_tree_view_get_selection(GTK_TREE_VIEW(PictureEntry)),
+					    get_selected_pic, &iter2);
+	gtk_tree_model_get(model2, &iter2, PICTURE_DATA_COLUMN, &pic, -1);
+	
+	dialog = gtk_dialog_new_with_buttons(_("Picture Properties"),
+					     parent_window,
+					     GTK_DIALOG_MODAL |
+					     GTK_DIALOG_DESTROY_WITH_PARENT,
+					     GTK_STOCK_OK,
+					     GTK_RESPONSE_ACCEPT,
+					     GTK_STOCK_CANCEL,
+					     GTK_RESPONSE_REJECT,
+					     NULL);
+	
+	ScrollWindowPictureTypes = gtk_scrolled_window_new(NULL, NULL);
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ScrollWindowPictureTypes),
+				       GTK_POLICY_AUTOMATIC,
+				       GTK_POLICY_AUTOMATIC);
+	store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
+	type = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+	gtk_container_add(GTK_CONTAINER(ScrollWindowPictureTypes), type);
+	renderer = gtk_cell_renderer_text_new();
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_column_pack_start(column, renderer, FALSE);
+	gtk_tree_view_column_set_title(column, _("Picture Type"));
+	gtk_tree_view_column_set_attributes(column, renderer,
+					    "text", 0,
+					    NULL);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(type), column);
+	gtk_widget_set_size_request(type, 256, 256);
+	gtk_container_add(GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
+			  ScrollWindowPictureTypes);
+	
+	for(i = 0; i < sizeof(picture_types)/sizeof(picture_types[0]); i++)
+	{
+	      GtkTreeIter iter;
+	      
+	      gtk_list_store_append(store, &iter);
+	      gtk_list_store_set(store, &iter,
+				 0, picture_type_string(picture_types[i]),
+				 1, picture_types[i],
+				 -1);
+	      if(pic->type == picture_types[i])
+		      default_type_iter = iter;
+	}
+
+	label = gtk_label_new(_("Picture Description:"));
+	gtk_container_add(GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
+	
+	desc = gtk_entry_new();
+	if(pic->description)
+		gtk_entry_set_text(GTK_ENTRY(desc), pic->description);
+	
+	gtk_container_add(GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), desc);
+	
+	gtk_widget_show_all(dialog);
+	gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(type)),
+				       &default_type_iter);
+	
+	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+	{
+		GtkTreeModel **model;
+		GtkTreeIter iter;
+		
+		model = gtk_tree_view_get_model(GTK_TREE_VIEW(type));
+		selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(type));
+		if(gtk_tree_selection_get_selected(selection, &model, &iter))
+		{
+			gchar *buffer;
+			gint t;
+			
+			gtk_tree_model_get(model, &iter, 1, &t, -1);
+			pic->type = t;
+
+			buffer = g_strdup(gtk_entry_get_text(GTK_ENTRY(desc)));
+			Strip_String(buffer);
+			if(pic->description)
+				g_free(pic->description);
+			if ( g_utf8_strlen(buffer, -1) > 0 )
+				pic->description = buffer;
+			else {
+				pic->description = 0;
+				g_free(buffer);
+			}
+			
+			gtk_list_store_set(GTK_LIST_STORE(model2), &iter2,
+					   PICTURE_TEXT_COLUMN,
+					   picture_info(pic),
+					   -1);
+		}
+	}
+	gtk_widget_destroy(dialog);
+}
+
+void Save_Picture_Button_Clicked (GObject *object)
+{
+    GtkWidget *FileSelectionWindow;
+    GtkWindow *parent_window = NULL;
+
+    parent_window = (GtkWindow*) gtk_widget_get_toplevel(object);
+    if (!GTK_WIDGET_TOPLEVEL(parent_window))
+    {
+        g_warning("Could not get parent window\n");
+        return;
+    }
+
+    FileSelectionWindow =
+	    gtk_file_chooser_dialog_new(_("Save picture"),
+					parent_window,
+					GTK_FILE_CHOOSER_ACTION_SAVE,
+					GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+					GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+					NULL);
+
+    if (gtk_dialog_run(GTK_DIALOG(FileSelectionWindow)) == GTK_RESPONSE_ACCEPT)
+    {
+	gchar *tmp, *filename;
+	
+        filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(FileSelectionWindow));
+        TRANSLATE_FILENAME(filename, tmp, TRUE);
+	gtk_tree_selection_selected_foreach(gtk_tree_view_get_selection(GTK_TREE_VIEW(PictureEntry)),
+					    save_selected_pic, filename);
+        g_free(filename);
+    }
+    gtk_widget_destroy(FileSelectionWindow);
+}
+
 GtkWidget *Create_Tag_Area (void)
 {
     GtkWidget *Separator;
@@ -420,7 +758,7 @@
     TagFrame = gtk_frame_new(_("Tag"));
     gtk_container_set_border_width(GTK_CONTAINER(TagFrame),2);
 
-    Table = gtk_table_new(6,11,FALSE);
+    Table = gtk_table_new(9,11,FALSE);
     gtk_container_add(GTK_CONTAINER(TagFrame),Table);
     gtk_container_set_border_width(GTK_CONTAINER(Table),5);
     gtk_table_set_row_spacings(GTK_TABLE(Table),5);
@@ -619,6 +957,125 @@
     g_object_set_data(G_OBJECT(CommentEntry),"MButtonName",CommentMButton);
     g_signal_connect(G_OBJECT(CommentEntry),"key_press_event", G_CALLBACK(Tag_Area_Entry_Key_Press),NULL);
 
+    /* Picture */
+    Label = gtk_label_new(_("Pictures:"));
+    gtk_table_attach(GTK_TABLE(Table),Label,0,1,6,7,GTK_FILL,GTK_FILL,0,0);
+    gtk_misc_set_alignment(GTK_MISC(Label),1,0.5);
+    {
+      GtkListStore *picture_store;
+      GtkCellRenderer *renderer;
+      GtkTreeViewColumn *column;
+      static const GtkTargetEntry drops[] = 
+	{ { "text/uri-list", 0, TARGET_URI_LIST } };
+      GtkWidget *ScrollWindowPictures;
+      GtkTreeSelection *selection;
+
+      ScrollWindowPictures = gtk_scrolled_window_new(NULL, NULL);
+      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ScrollWindowPictures),
+				     GTK_POLICY_AUTOMATIC,
+				     GTK_POLICY_AUTOMATIC);
+      
+      picture_store = gtk_list_store_new(PICTURE_N_COLUMNS,
+					 GDK_TYPE_PIXBUF,
+					 G_TYPE_STRING,
+					 G_TYPE_POINTER);
+      PictureEntry =
+	      gtk_tree_view_new_with_model(GTK_TREE_MODEL(picture_store));
+      gtk_container_add(GTK_CONTAINER(ScrollWindowPictures), PictureEntry);
+      
+      gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(PictureEntry), FALSE);
+      selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(PictureEntry));
+      gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
+      
+      renderer = gtk_cell_renderer_pixbuf_new();
+      column = gtk_tree_view_column_new();
+      gtk_tree_view_column_pack_start(column, renderer, FALSE);
+      gtk_tree_view_column_set_attributes(column, renderer,
+					  "pixbuf", PICTURE_PIC_COLUMN,
+					  NULL);
+      gtk_tree_view_append_column(GTK_TREE_VIEW(PictureEntry), column);
+      renderer = gtk_cell_renderer_text_new();
+      column = gtk_tree_view_column_new();
+      gtk_tree_view_column_pack_start(column, renderer, FALSE);
+      gtk_tree_view_column_set_attributes(column, renderer,
+					  "text", PICTURE_TEXT_COLUMN,
+					  NULL);
+      gtk_tree_view_append_column(GTK_TREE_VIEW(PictureEntry), column);
+      gtk_widget_set_size_request(PictureEntry, -1, 200);
+
+      gtk_drag_dest_set(PictureEntry, 
+			GTK_DEST_DEFAULT_HIGHLIGHT |
+			GTK_DEST_DEFAULT_MOTION    |
+			GTK_DEST_DEFAULT_DROP, 
+			drops, sizeof(drops) / sizeof(GtkTargetEntry),
+			GDK_ACTION_COPY);
+      g_signal_connect(G_OBJECT(PictureEntry),"drag_data_received", 
+		       GTK_SIGNAL_FUNC(Tag_Area_Picture_Data), 0);
+      g_signal_connect(selection, "changed",
+		       G_CALLBACK(Picture_Selection_Changed_cb),
+		       NULL);
+      
+      gtk_table_attach(GTK_TABLE(Table),
+		       ScrollWindowPictures, 1,10,6,7,
+		       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+    }
+    PictureMButton = gtk_button_new();
+    gtk_table_attach(GTK_TABLE(Table),PictureMButton,10,11,6,7,0,0,0,0);
+    gtk_widget_set_usize(PictureMButton,MButtonSize,MButtonSize);
+    gtk_signal_connect(GTK_OBJECT(PictureMButton),"clicked",GTK_SIGNAL_FUNC(Mini_Button_Clicked),NULL);
+    gtk_tooltips_set_tip(Tips,PictureMButton,_("Tag selected files with these pictures"),NULL);
+    {
+      GtkWidget *add_button, *clear_button, *hbox;
+      
+      static const GtkTargetEntry drops[] = 
+	{ { "text/uri-list", 0, TARGET_URI_LIST } };
+
+      hbox = gtk_hbox_new(FALSE, 5);
+      gtk_table_attach(GTK_TABLE(Table), hbox, 1,10,7,8,
+		       GTK_FILL, GTK_FILL, 0, 0);
+      clear_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
+      add_button = gtk_button_new_from_stock(GTK_STOCK_ADD);
+      Picture_Save_Button = gtk_button_new_from_stock(GTK_STOCK_SAVE);
+      gtk_widget_set_sensitive(G_OBJECT(Picture_Save_Button), FALSE);
+      gtk_container_add(GTK_CONTAINER(hbox), clear_button);
+      gtk_container_add(GTK_CONTAINER(hbox), add_button);
+      gtk_container_add(GTK_CONTAINER(hbox), Picture_Save_Button);
+
+      hbox = gtk_hbox_new(FALSE, 5);
+      gtk_table_attach(GTK_TABLE(Table), hbox, 1,10,8,9,
+		       GTK_FILL, GTK_FILL, 0, 0);
+      Picture_Properties_Button =
+	      gtk_button_new_from_stock(GTK_STOCK_PROPERTIES);
+      gtk_widget_set_sensitive(G_OBJECT(Picture_Properties_Button), FALSE);
+      gtk_container_add(GTK_CONTAINER(hbox), Picture_Properties_Button);
+
+      gtk_signal_connect(GTK_OBJECT(add_button), "clicked",
+			 GTK_SIGNAL_FUNC(Open_Picture_Button_Clicked),
+			 NULL);
+      gtk_signal_connect(GTK_OBJECT(clear_button), "clicked",
+			 GTK_SIGNAL_FUNC(Clear_Picture_Button_Clicked),
+			 NULL);
+      gtk_signal_connect(GTK_OBJECT(Picture_Save_Button), "clicked",
+			 GTK_SIGNAL_FUNC(Save_Picture_Button_Clicked),
+			 NULL);
+      gtk_signal_connect(GTK_OBJECT(Picture_Properties_Button), "clicked",
+			 GTK_SIGNAL_FUNC(Properties_Picture_Button_Clicked),
+			 NULL);
+      
+      gtk_drag_dest_set(add_button, 
+			GTK_DEST_DEFAULT_HIGHLIGHT |
+			GTK_DEST_DEFAULT_MOTION    |
+			GTK_DEST_DEFAULT_DROP, 
+			drops, sizeof(drops) / sizeof(GtkTargetEntry),
+			GDK_ACTION_COPY);
+      g_signal_connect(G_OBJECT(add_button),"drag_data_received", 
+		       GTK_SIGNAL_FUNC(Tag_Area_Picture_Data), 0);
+    }
+
+    Attach_Popup_Menu_To_Tag_Entries(GTK_ENTRY(PictureEntry));
+    gtk_object_set_data(GTK_OBJECT(PictureEntry),"MButtonName",PictureMButton);
+    gtk_signal_connect(GTK_OBJECT(PictureEntry),"key_press_event",(GtkSignalFunc)Tag_Area_Entry_Key_Press,NULL);
+
     // Managing of entries when pressing the Enter key
     g_signal_connect_swapped(G_OBJECT(TitleEntry),     "activate",G_CALLBACK(gtk_widget_grab_focus),G_OBJECT(ArtistEntry));
     g_signal_connect_swapped(G_OBJECT(ArtistEntry),    "activate",G_CALLBACK(gtk_widget_grab_focus),G_OBJECT(AlbumEntry));
@@ -634,7 +1091,6 @@
 }
 
 
-
 /*
  * Actions when mini buttons are pressed: apply the field to all others files
  */
@@ -892,6 +1348,43 @@
         else
             msg = g_strdup(_("Removed comment from selected files."));
     }
+    else if (object==GTK_OBJECT(PictureMButton))
+    {
+        struct Picture *res = NULL, *pic, *prev_pic;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	    
+	model = gtk_tree_view_get_model(GTK_TREE_VIEW(PictureEntry));
+	if(gtk_tree_model_get_iter_first(model, &iter))
+	  do {
+	      gtk_tree_model_get(model, &iter, PICTURE_DATA_COLUMN, &pic, -1);
+	      pic = Copy_Picture_One(pic);
+	      if(!res)
+		      res = pic;
+	      else
+		      prev_pic->next = pic;
+	      prev_pic = pic;
+	  } while(gtk_tree_model_iter_next(model, &iter));
+
+        while (selfilelist)
+        {
+            etfile = Browser_List_Get_ETFile_From_Path(selfilelist->data);
+            FileTag = ET_File_Tag_Item_New();
+            ET_Copy_File_Tag_Item(etfile,FileTag);
+            ET_Set_Field_File_Tag_Picture(&FileTag->picture, res);
+            ET_Manage_Changes_Of_File_Data(etfile,NULL,FileTag);
+
+            if (!selfilelist->next) break;
+            selfilelist = g_list_next(selfilelist);
+        }
+        if (pic)
+            msg = g_strdup(_("Selected files tagged with pictures."));
+        else
+            msg = g_strdup(_("Removed pictures from selected files."));
+	Free_Picture(res);
+
+	return;
+    }
 
     g_list_foreach(selfilelist, (GFunc) gtk_tree_path_free, NULL);
     g_list_free(selfilelist);
@@ -2655,6 +3148,7 @@
     gtk_widget_set_sensitive(GTK_WIDGET(TrackTotalEntry),       activate);
     gtk_widget_set_sensitive(GTK_WIDGET(CommentEntry),          activate);
     gtk_widget_set_sensitive(GTK_WIDGET(GenreCombo),            activate);
+    gtk_widget_set_sensitive(GTK_WIDGET(PictureEntry),          activate);
     // Mini buttons
     gtk_widget_set_sensitive(GTK_WIDGET(TitleMButton),          activate);
     gtk_widget_set_sensitive(GTK_WIDGET(ArtistMButton),         activate);
@@ -2664,7 +3158,8 @@
     gtk_widget_set_sensitive(GTK_WIDGET(TrackMButtonSequence),  activate);
     gtk_widget_set_sensitive(GTK_WIDGET(TrackMButtonNbrFiles),  activate);
     gtk_widget_set_sensitive(GTK_WIDGET(CommentMButton),        activate);
-    gtk_widget_set_sensitive(GTK_WIDGET(GenreMButton),          activate);*/
+    gtk_widget_set_sensitive(GTK_WIDGET(GenreMButton),          activate);
+    gtk_widget_set_sensitive(GTK_WIDGET(PictureMButton),        activate);*/
 }
 
 /*
@@ -2692,6 +3187,7 @@
     gtk_entry_set_text(GTK_ENTRY(TrackTotalEntry),"");
     gtk_entry_set_text(GTK_ENTRY(GTK_BIN(GenreCombo)->child),"");
     gtk_entry_set_text(GTK_ENTRY(CommentEntry),"");
+    Clear_PictureEntry();
 }
 
 
diff -Naur easytag-0.31_gtk2.4_pre2.orig/src/easytag.h easytag-0.31_gtk2.4_pre2/src/easytag.h
--- easytag-0.31_gtk2.4_pre2.orig/src/easytag.h	2004-06-25 23:19:01.000000000 +0200
+++ easytag-0.31_gtk2.4_pre2/src/easytag.h	2004-09-12 15:05:17.000000000 +0200
@@ -91,6 +91,7 @@
 GtkListStore *TrackEntryComboModel;
 GtkWidget    *TrackTotalEntry;
 GtkWidget    *CommentEntry;
+GtkWidget    *PictureEntry;
 GtkWidget    *GenreCombo;
 GtkListStore *GenreComboModel;
 /* Mini buttons */
@@ -102,6 +103,7 @@
 GtkWidget *TrackMButtonSequence;
 GtkWidget *TrackMButtonNbrFiles;
 GtkWidget *CommentMButton;
+GtkWidget *PictureMButton;
 GtkWidget *GenreMButton;
 
 GdkCursor *MouseCursor;
diff -Naur easytag-0.31_gtk2.4_pre2.orig/src/et_core.c easytag-0.31_gtk2.4_pre2/src/et_core.c
--- easytag-0.31_gtk2.4_pre2.orig/src/et_core.c	2004-08-30 23:50:54.000000000 +0200
+++ easytag-0.31_gtk2.4_pre2/src/et_core.c	2004-09-12 15:06:57.000000000 +0200
@@ -343,6 +343,7 @@
         FileTag->year        = NULL;
         FileTag->genre       = NULL;
         FileTag->comment     = NULL;
+        FileTag->picture     = NULL;
         FileTag->other       = NULL;
     }
 }
@@ -1740,6 +1741,7 @@
     g_free(FileTag->track_total);
     g_free(FileTag->genre);
     g_free(FileTag->comment);
+    Free_Picture(FileTag->picture);
     // Free list of other fields
     ET_Free_File_Tag_Item_Other_Field(FileTag);
 
@@ -1934,6 +1936,18 @@
         FileTag->comment = NULL;
     }
 
+    if(FileTagCur->picture)
+      {
+	if(FileTag->picture)
+	  Free_Picture(FileTag->picture);
+	FileTag->picture = Copy_Picture(FileTagCur->picture);
+      }
+    else if(FileTag->picture)
+      {
+	Free_Picture(FileTag->picture);
+	FileTag->picture = 0;
+      }
+
     if (FileTagCur->other)
     {
         ET_Copy_File_Tag_Item_Other_Field(ETFile,FileTag);
@@ -1977,6 +1991,27 @@
 }
 
 
+/*
+ * Set the value of a field of a FileTag Picture item.
+ */
+gboolean ET_Set_Field_File_Tag_Picture (gchar **FileTagField, 
+					struct Picture *pic)
+{
+    if (!FileTagField) return FALSE;
+
+    if (*FileTagField != NULL)
+    {
+      Free_Picture(*FileTagField);
+      *FileTagField = 0;
+    }
+
+    if (pic)
+        *FileTagField = Copy_Picture(pic);
+
+    return TRUE;
+}
+
+
 /************************
  * Displaying functions *
  ************************/
@@ -2170,6 +2205,184 @@
     g_free(text1);
 }
 
+int picture_format(struct Picture *pic)
+	/* FIXME: Possibly use gnome_vfs_get_mime_type_for_buffer. */
+{
+	if(pic->data && pic->size > 2 &&
+	   pic->data[0] == 0xff &&
+	   pic->data[1] == 0xd8)
+		return PICTURE_FORMAT_JPEG;
+	if(pic->data && pic->size > 8 &&
+	   pic->data[0] == 0x89 &&
+	   pic->data[1] == 0x50 &&
+	   pic->data[2] == 0x4e &&
+	   pic->data[3] == 0x47 &&
+	   pic->data[4] == 0x0d &&
+	   pic->data[5] == 0x0a &&
+	   pic->data[6] == 0x1a &&
+	   pic->data[7] == 0x0a)
+		return PICTURE_FORMAT_PNG;
+	return PICTURE_FORMAT_UNKNOWN;
+}
+
+const gchar *picture_format_string(int format)
+{
+	switch(format)
+	{
+		case PICTURE_FORMAT_JPEG:
+			return _("JPEG image");
+		case PICTURE_FORMAT_PNG:
+			return _("PNG image");
+		default:
+			return _("Unknown image");
+	}
+}
+
+const gchar *picture_type_string(int type)
+{
+	switch(type)
+	{
+		case PICTURE_TYPE_OTHER:
+			return _("Other");
+		case PICTURE_TYPE_FILE_ICON:
+			return _("32x32 pixel PNG file icon");
+		case PICTURE_TYPE_OTHER_FILE_ICON:
+			return _("Other file icon");
+		case PICTURE_TYPE_FRONT_COVER:
+			return _("Cover (front)");
+		case PICTURE_TYPE_BACK_COVER:
+			return _("Cover (back)");
+		case PICTURE_TYPE_LEAFLET_PAGE:
+			return _("Leaflet page");
+		case PICTURE_TYPE_MEDIA:
+			return _("Media (e.g. label side of CD)");
+		case PICTURE_TYPE_LEAD_ARTIST_LEAD_PERFORMER_SOLOIST:
+			return _("Lead artist/lead performer/soloist");
+		case PICTURE_TYPE_ARTIST_PERFORMER:
+			return _("Artist/performer");
+		case PICTURE_TYPE_CONDUCTOR:
+			return _("Conductor");
+		case PICTURE_TYPE_BAND_ORCHESTRA:
+			return _("Band/Orchestra");
+		case PICTURE_TYPE_COMPOSER:
+			return _("Composer");
+		case PICTURE_TYPE_LYRICIST_TEXT_WRITER:
+			return _("Lyricist/text writer");
+		case PICTURE_TYPE_RECORDING_LOCATION:
+			return _("Recording location");
+		case PICTURE_TYPE_DURING_RECORDING:
+			return _("During recording");
+		case PICTURE_TYPE_DURING_PERFORMANCE:
+			return _("During performance");
+		case PICTURE_TYPE_MOVIDE_VIDEO_SCREEN_CAPTURE:
+			return _("Movie/video screen capture");
+		case PICTURE_TYPE_A_BRIGHT_COLOURED_FISH:
+			return _("A bright coloured fish");
+		case PICTURE_TYPE_ILLUSTRATION:
+			return _("Illustration");
+		case PICTURE_TYPE_BAND_ARTIST_LOGOTYPE:
+			return _("Band/Artist logotype");
+		case PICTURE_TYPE_PUBLISHER_STUDIO_LOGOTYPE:
+			return _("Publisher/studio logotype");
+		default:
+			return _("Unknown picture type");
+	}
+}
+
+gchar *picture_info(struct Picture *pic)
+{
+	gchar *format, *desc, *type, *r;
+	GString *s;
+
+	format = picture_format_string(picture_format(pic));
+	
+	if(pic->description)
+		desc = pic->description;
+	else
+		desc = "";
+
+	type = picture_type_string(pic->type);
+
+	s = g_string_new(0);
+	g_string_sprintf(s, "%s (%d K)\n%s: %s\n%s: %s",
+			 format, pic->size/1000,
+			 _("Type"), type,
+			 _("Description"), desc);
+	r = s->str;
+	g_string_free(s, FALSE);
+	return r;
+}
+
+void Clear_PictureEntry()
+{
+      GtkListStore *picture_store;
+      GtkTreeModel *model;
+      GtkTreeIter iter;
+      struct Picture *pic;
+
+      model = gtk_tree_view_get_model(GTK_TREE_VIEW(PictureEntry));
+      if(gtk_tree_model_get_iter_first(model, &iter))
+          do {
+	      gtk_tree_model_get(model, &iter, PICTURE_DATA_COLUMN, &pic,-1);
+	      Free_Picture(pic);
+	  } while(gtk_tree_model_iter_next(model, &iter));
+      
+      picture_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(PictureEntry)));
+      if(picture_store)
+	      gtk_list_store_clear(picture_store);
+}
+
+void Update_PictureEntry(struct Picture *pic, int select)
+{
+  GdkPixbufLoader * loader = 0;
+
+  if(!pic->data)
+    {
+      Clear_PictureEntry();
+      return;
+    }
+  
+  loader = gdk_pixbuf_loader_new();
+  if (loader)
+    {
+      if(gdk_pixbuf_loader_write(loader, pic->data, pic->size, 0))
+	{
+	  GtkTreeSelection *selection;
+	  GdkPixbuf *pixbuf;
+
+	  selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(PictureEntry));
+	  
+	  pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+	  if(pixbuf)
+	    {
+	      GtkListStore *picture_store;
+	      GtkTreeIter iter1;
+	      GdkPixbuf *scaled_pixbuf;
+	      
+	      scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, 
+						      96, 96,
+						      GDK_INTERP_BILINEAR);
+	      gdk_pixbuf_unref(pixbuf);
+	      
+	      picture_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(PictureEntry)));
+	      gtk_list_store_append(picture_store, &iter1);
+	      gtk_list_store_set(picture_store, &iter1,
+				 PICTURE_PIC_COLUMN, scaled_pixbuf,
+				 PICTURE_TEXT_COLUMN, picture_info(pic),
+				 PICTURE_DATA_COLUMN, Copy_Picture_One(pic),
+				 -1);
+	      if(select)
+		      gtk_tree_selection_select_iter(selection, &iter1);
+	      gdk_pixbuf_unref(scaled_pixbuf);
+	    }
+	}
+    }
+  gdk_pixbuf_loader_close(loader, 0);
+
+  if(pic->next)
+	  Update_PictureEntry(pic->next, select);
+}
+
 
 /*
  * Display all tag infos (tags fields) into entry boxes of the user interface.
@@ -2189,6 +2402,7 @@
         gtk_entry_set_text(GTK_ENTRY(TrackTotalEntry),             "");
         gtk_entry_set_text(GTK_ENTRY(GTK_BIN(GenreCombo)->child),  "");
         gtk_entry_set_text(GTK_ENTRY(CommentEntry),                "");
+	Clear_PictureEntry();
         //Tag_Area_Set_Sensitive(FALSE);
         return FALSE;
     }
@@ -2245,6 +2459,11 @@
     else
         gtk_entry_set_text(GTK_ENTRY(CommentEntry),"");
 
+    /* Show picture */
+    Clear_PictureEntry();
+    if (FileTag && FileTag->picture)
+      Update_PictureEntry(FileTag->picture, 0);
+
     return TRUE;
 }
 
@@ -2589,6 +2808,32 @@
         g_free(buffer);
     }
 
+
+    /* Picture */
+    {
+      struct Picture *pic, *prev_pic = NULL;
+      GtkTreeModel *model;
+      GtkTreeIter iter;
+
+      if(FileTag->picture)
+      {
+	      Free_Picture(FileTag->picture);
+	      FileTag->picture = NULL;
+      }
+      
+      model = gtk_tree_view_get_model(GTK_TREE_VIEW(PictureEntry));
+      if(gtk_tree_model_get_iter_first(model, &iter))
+	do {
+		gtk_tree_model_get(model, &iter, PICTURE_DATA_COLUMN, &pic,-1);
+		pic = Copy_Picture_One(pic);
+		if(!FileTag->picture)
+			FileTag->picture = pic;
+		else
+			prev_pic->next = pic;
+		prev_pic = pic;
+	} while(gtk_tree_model_iter_next(model, &iter));
+    }
+
     return TRUE;
 }
 
@@ -2704,6 +2949,18 @@
     }
     Strip_String(FileTag->comment);
 
+    /* Picture */
+    if(FileTagCur->picture)
+      {
+	if(FileTag->picture)
+	  Free_Picture(FileTag->picture);
+	FileTag->picture = Copy_Picture(FileTagCur->picture);
+      } 
+    else if(FileTag->picture)
+      {
+	Free_Picture(FileTag->picture);
+	FileTag->picture = 0;
+      }
 
     return TRUE;
 }
@@ -2981,6 +3238,44 @@
     if (!FileTag1->comment &&  FileTag2->comment && g_utf8_strlen(FileTag2->comment, -1)>0 ) return TRUE;
     if ( FileTag1->comment &&  FileTag2->comment && g_utf8_collate(FileTag1->comment,FileTag2->comment)!=0 ) return TRUE;
 
+    /* Picture */
+    {
+	    struct Picture *pic1 = FileTag1->picture;
+	    struct Picture *pic2 = FileTag2->picture;
+
+	    for(;;)
+	    {
+		    if(pic1 && !pic2 || !pic1 && pic2)
+			    return TRUE;
+		    if(!pic1 || !pic2)
+			    break;
+
+		    if ( pic1->data && !pic2->data) 
+			    return TRUE;
+		    if (!pic1->data &&  pic2->data)
+			    return TRUE;
+		    if ( pic1->size != pic2->size ||
+			 memcmp(pic1->data, pic2->data, pic1->size))
+			    return TRUE;
+		    if ( pic1->type != pic2->type)
+			    return TRUE;
+		    if ( pic1->description && !pic2->description &&
+			 g_utf8_strlen(pic1->description, -1)>0 )
+			    return TRUE;
+		    if ( !pic1->description &&
+			 pic2->description &&
+			 g_utf8_strlen(pic2->description, -1)>0 )
+			    return TRUE;
+		    if ( pic1->description && pic2->description &&
+			 g_utf8_collate(pic1->description,
+					pic2->description)!=0 )
+			    return TRUE;
+		    
+		    pic1 = pic1->next;
+		    pic2 = pic2->next;
+	    }
+    }
+
     return FALSE; /* No changes */
 }
 
diff -Naur easytag-0.31_gtk2.4_pre2.orig/src/et_core.h easytag-0.31_gtk2.4_pre2/src/et_core.h
--- easytag-0.31_gtk2.4_pre2.orig/src/et_core.h	2004-08-30 23:50:56.000000000 +0200
+++ easytag-0.31_gtk2.4_pre2/src/et_core.h	2004-09-12 15:05:17.000000000 +0200
@@ -136,6 +136,55 @@
 /*
  * Description of each item of the TagList list
  */
+struct Picture
+{
+	gint type;
+	gchar *description;
+	gulong size;
+	guchar *data;
+	struct Picture *next;
+};
+
+enum
+{
+	PICTURE_TYPE_OTHER,
+	PICTURE_TYPE_FILE_ICON,
+	PICTURE_TYPE_OTHER_FILE_ICON,
+	PICTURE_TYPE_FRONT_COVER,
+	PICTURE_TYPE_BACK_COVER,
+	PICTURE_TYPE_LEAFLET_PAGE,
+	PICTURE_TYPE_MEDIA,
+	PICTURE_TYPE_LEAD_ARTIST_LEAD_PERFORMER_SOLOIST,
+	PICTURE_TYPE_ARTIST_PERFORMER,
+	PICTURE_TYPE_CONDUCTOR,
+	PICTURE_TYPE_BAND_ORCHESTRA,
+	PICTURE_TYPE_COMPOSER,
+	PICTURE_TYPE_LYRICIST_TEXT_WRITER,
+	PICTURE_TYPE_RECORDING_LOCATION,
+	PICTURE_TYPE_DURING_RECORDING,
+	PICTURE_TYPE_DURING_PERFORMANCE,
+	PICTURE_TYPE_MOVIDE_VIDEO_SCREEN_CAPTURE,
+	PICTURE_TYPE_A_BRIGHT_COLOURED_FISH,
+	PICTURE_TYPE_ILLUSTRATION,
+	PICTURE_TYPE_BAND_ARTIST_LOGOTYPE,
+	PICTURE_TYPE_PUBLISHER_STUDIO_LOGOTYPE
+};
+
+enum
+{
+	PICTURE_FORMAT_JPEG,
+	PICTURE_FORMAT_PNG,
+	PICTURE_FORMAT_UNKNOWN
+};
+
+enum
+{
+	PICTURE_PIC_COLUMN,
+	PICTURE_TEXT_COLUMN,
+	PICTURE_DATA_COLUMN,
+	PICTURE_N_COLUMNS
+};
+
 typedef struct _File_Tag File_Tag;
 struct _File_Tag
 {
@@ -149,6 +198,7 @@
     gchar *track_total;    /* The number of tracks for the album (ex: 12/20) */
     gchar *genre;          /* Genre of song */
     gchar *comment;        /* Comment */
+    struct Picture *picture; /* Picture */
     GList *other;          /* List of unsupported fields (used for ogg only) */
 };
 
@@ -317,6 +367,8 @@
 gboolean ET_Copy_File_Tag_Item       (ET_File *ETFile, File_Tag *FileTag);
 gboolean ET_Set_Field_File_Name_Item (gchar **FileNameField, gchar *value);
 gboolean ET_Set_Field_File_Tag_Item  (gchar **FileTagField,  gchar *value);
+gboolean ET_Set_Field_File_Tag_Picture (gchar **FileTagField, 
+					struct Picture *pic);
 
 GList   *ET_Displayed_File_List_First       (void);
 GList   *ET_Displayed_File_List_Previous    (void);
@@ -329,6 +381,11 @@
 
 gboolean ET_Set_Displayed_File_List         (GList *ETFileList);
 
+int picture_format(struct Picture *pic);
+gchar *picture_info(struct Picture *pic);
+void Clear_PictureEntry();
+void Update_PictureEntry(struct Picture *pic, int select);
+
 void     ET_Display_File_Data_To_UI (ET_File *ETFile);
 void     ET_Save_File_Data_From_UI  (ET_File *ETFile);
 gboolean ET_Save_File_Tag_To_HD     (ET_File *ETFile);
diff -Naur easytag-0.31_gtk2.4_pre2.orig/src/id3_tag.c easytag-0.31_gtk2.4_pre2/src/id3_tag.c
--- easytag-0.31_gtk2.4_pre2.orig/src/id3_tag.c	2004-09-11 23:09:10.000000000 +0200
+++ easytag-0.31_gtk2.4_pre2/src/id3_tag.c	2004-09-12 15:12:14.000000000 +0200
@@ -92,11 +92,12 @@
     ID3Tag *id3_tag = NULL;    /* Tag defined by the id3lib */
     gchar  *string, *string1, *string2;
     gchar *filename_real = filename_utf8;
-    ID3Frame *id3_frame;
+    ID3Frame *id3_frame, *id3_first_frame;
     ID3Field *id3_field;
     size_t offset;
     luint num_chars;
     guint field_num = 0; // First field
+    struct Picture *prev_pic = NULL;
 
     if (!filename_real || !FileTag)
         return FALSE;
@@ -385,6 +386,44 @@
         g_free(comment2);
         }*/
     }
+
+    /***********
+     * Picture *
+     ***********/
+    id3_first_frame = NULL;
+    for(;;)
+    {
+      struct Picture *pic;
+	    
+      id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_PICTURE);
+      if(!id3_frame || id3_frame == id3_first_frame)
+	break;
+      if(!id3_first_frame)
+	      id3_first_frame = id3_frame;
+
+      pic = Allocate_Picture();
+      if(!prev_pic)
+	      FileTag->picture = pic;
+      else
+	      prev_pic->next = pic;
+      prev_pic = pic;
+      
+      if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_DATA)) )
+      {
+	      pic->size = ID3Field_Size(id3_field);
+	      pic->data = g_malloc(pic->size);
+	      ID3Field_GetBINARY(id3_field, pic->data, pic->size);
+      }
+      if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_PICTURETYPE)) )
+	      pic->type = ID3Field_GetINT(id3_field);
+      if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_DESCRIPTION)) )
+	      if ( (num_chars = ID3Field_GetASCII_1(id3_field, string,
+						    ID3V2_MAX_STRING_LEN, 
+						    field_num)) > 0 && 
+		   string != NULL )
+		      pic->description = g_strdup(string);
+    }
+    
     g_free(string);
 
     /* Free allocated data */
@@ -421,18 +460,19 @@
     gboolean has_track    = 1;
     gboolean has_genre    = 1;
     gboolean has_comment  = 1;
+    gboolean has_picture  = 1;
     gboolean has_song_len = 1;
 
     ID3Frame *id3_frame;
     ID3Field *id3_field;
     gchar *string, *string1;
+    struct Picture *pic;
 
     if (!ETFile || !ETFile->FileTag)
         return FALSE;
 
     FileTag = (File_Tag *)ETFile->FileTag->data;
     filename_utf8 = ((File_Name *)ETFile->FileNameCur->data)->value;
-
     filename_real = filename_utf8;
     TRANSLATE_FILENAME_SAVE(filename_real, temp, FALSE);
 
@@ -658,6 +698,53 @@
     }
 
 
+    /***********
+     * Picture *
+     ***********/
+    while ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_PICTURE)) )
+        ID3Tag_RemoveFrame(id3_tag,id3_frame);
+    pic = FileTag->picture;
+    if(!pic)
+        has_picture = 0;
+    while(pic)
+    {
+        id3_frame = ID3Frame_NewID(ID3FID_PICTURE);
+        ID3Tag_AttachFrame(id3_tag,id3_frame);
+
+	switch(picture_format(pic))
+	{
+		case PICTURE_FORMAT_JPEG:
+			if ((id3_field = ID3Frame_GetField(id3_frame,
+							   ID3FN_MIMETYPE)))
+				ID3Field_SetASCII(id3_field, "image/jpeg");
+			if ((id3_field = ID3Frame_GetField(id3_frame,
+							   ID3FN_IMAGEFORMAT)))
+				ID3Field_SetASCII(id3_field, "JPG");
+			break;
+
+		case PICTURE_FORMAT_PNG:
+			if ((id3_field = ID3Frame_GetField(id3_frame,
+							   ID3FN_MIMETYPE)))
+				ID3Field_SetASCII(id3_field, "image/png");
+			if ((id3_field = ID3Frame_GetField(id3_frame,
+							   ID3FN_IMAGEFORMAT)))
+				ID3Field_SetASCII(id3_field, "PNG");
+			break;
+	}
+	
+        if ((id3_field = ID3Frame_GetField(id3_frame, ID3FN_PICTURETYPE)))
+	  ID3Field_SetINT(id3_field, pic->type);
+        if (pic->description &&
+	    (id3_field = ID3Frame_GetField(id3_frame,ID3FN_DESCRIPTION)))
+        {
+            HANDLE_TRANSLATION_SAVE(string, pic->description, id3_field);
+        }
+        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_DATA)))
+	  ID3Field_SetBINARY(id3_field, pic->data, pic->size);
+
+	pic = pic->next;
+    }
+
     /*********************************
      * File length (in milliseconds) *
      *********************************/
@@ -690,7 +777,7 @@
      * is set to 1, we strip the ID3v1.x and ID3v2 tags. Else let see... :)
      */
     if ( STRIP_TAG_WHEN_EMPTY_FIELDS && !has_title && !has_artist && !has_album
-         && !has_year && !has_track && !has_genre && !has_comment )//&& !has_song_len )
+         && !has_year && !has_track && !has_genre && !has_comment && !has_picture )//&& !has_song_len )
     {
         error_strip_id3v1 = ID3Tag_Strip(id3_tag,ID3TT_ID3V1);
         error_strip_id3v2 = ID3Tag_Strip(id3_tag,ID3TT_ID3V2);
diff -Naur easytag-0.31_gtk2.4_pre2.orig/src/misc.c easytag-0.31_gtk2.4_pre2/src/misc.c
--- easytag-0.31_gtk2.4_pre2.orig/src/misc.c	2004-09-11 23:19:06.000000000 +0200
+++ easytag-0.31_gtk2.4_pre2/src/misc.c	2004-09-12 15:07:26.000000000 +0200
@@ -30,6 +30,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
 
 #include "misc.h"
 #include "easytag.h"
@@ -2727,3 +2729,116 @@
 
     g_signal_handler_unblock(entry, handler);
 }
+
+/*
+ * Pictures 
+ */
+
+struct Picture *Allocate_Picture(void)
+{
+  struct Picture *pic = g_malloc(sizeof(struct Picture));
+  memset(pic, 0, sizeof(struct Picture));
+  return pic;
+}
+
+struct Picture *Copy_Picture_One(const struct Picture *pic)
+{
+  struct Picture *pic2;
+
+  if(!pic)
+    return 0;
+  pic2 = Allocate_Picture();
+  pic2->type = pic->type;
+  if(pic->description)
+	  pic2->description = g_strdup(pic->description);
+  if(pic->data)
+    {
+      pic2->size = pic->size;
+      pic2->data = g_malloc(pic2->size);
+      memcpy(pic2->data, pic->data, pic->size);
+    }
+  return pic2;
+}
+
+struct Picture *Copy_Picture(const struct Picture *pic)
+{
+  struct Picture *pic2 = Copy_Picture_One(pic);
+  if(pic->next)
+    pic2->next = Copy_Picture(pic->next);
+  return pic2;
+}
+
+void Free_Picture(struct Picture *pic)
+{
+  if(!pic)
+    return;
+  if(pic->next)
+    Free_Picture(pic->next);
+  if(pic->description)
+    g_free(pic->description);
+  if(pic->data)
+    g_free(pic->data);
+  g_free(pic);
+}
+
+#define LOAD_BUFFER_SIZE 4096
+
+struct Picture *Load_Picture(const gchar *filename)
+{
+  struct Picture *pic;
+  gchar *buffer = 0;
+  size_t size = 0;
+  int fd;
+
+  fd = open(filename, O_RDONLY);
+  if(fd == -1)
+    return FALSE;
+  
+  do {
+    ssize_t r;
+    gchar *p;
+    
+    p = g_realloc(buffer, size + LOAD_BUFFER_SIZE);
+    if(!p)
+      goto fail;
+    buffer = p;
+    
+    r = read(fd, buffer + size, LOAD_BUFFER_SIZE);
+    if(r == -1)
+      goto fail;
+    if(!r)
+      break;
+
+    size += r;
+  } while(1);
+  close(fd);
+
+  pic = Allocate_Picture();
+  pic->size = size;
+  pic->data = buffer;
+  return pic;
+
+ fail:
+  if(buffer)
+    g_free(buffer);
+  close(fd);
+  return 0;
+}
+
+gboolean Save_Picture(const struct Picture *pic, const gchar *filename)
+{
+  int fd;
+	
+  fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+  if(fd == -1)
+    return FALSE;
+  
+  if(write(fd, pic->data, pic->size) != pic->size)
+  {
+    close(fd);
+    return FALSE;
+  }
+  
+  close(fd);
+  return TRUE;
+}
diff -Naur easytag-0.31_gtk2.4_pre2.orig/src/misc.h easytag-0.31_gtk2.4_pre2/src/misc.h
--- easytag-0.31_gtk2.4_pre2.orig/src/misc.h	2004-07-01 21:46:28.000000000 +0200
+++ easytag-0.31_gtk2.4_pre2/src/misc.h	2004-09-12 15:05:17.000000000 +0200
@@ -112,5 +112,13 @@
 // Load filenames window
 void Open_Load_Filename_Window (void);
 
+struct Picture;
+
+struct Picture *Allocate_Picture(void);
+void Free_Picture(struct Picture *pic);
+struct Picture *Copy_Picture_One(const struct Picture *pic);
+struct Picture *Copy_Picture(const struct Picture *pic);
+struct Picture *Load_Picture(const gchar *filename);
+gboolean Save_Picture(const struct Picture *pic, const gchar *filename);
 
 #endif /* __MISC_H__ */


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