[Easytag-mailing] [PATCH] Basic EasyTAG cover art support



Hi!

Attached patch implements basic cover art support to EasyTAG
0.31_gtk2.3_pre1. Steps to use:

  - Drag pictures from e.g. Nautilus and drop them in the picture area
  - Remove pictures by clicking on the clear button
  - Jpeg (and probably png) works

Some bugs and limitations:

  - When dragging pictures to EasyTAG, file paths cannot contain
    characters like space, utf-8 etc. Some URI decoding would be needed
    so that open(2c) can handle these characters too
  - The File Chooser dialog segfaults (so it's disabled), no idea why
  - Picture description text is currently ignored
  - Support for formats other than jpeg and png would be nice
  - There may be some GTK ref/unref/memory issues in the code
  - Only picture type "Other" is currently supported. Multiple pictures
    and several types (cover front/back, leaflet page, artist/performer
    etc.) would be nice
  - Dragging pictures from EasyTAG to other applications such as
    Gimp or Nautilus isn't currently supported - would be nice too

Diffstat:

 easytag.c |  124 +++++++++++++++-
 easytag.h |    2
 et_core.c |  167 ++++++++++++++++++++++
 et_core.h |   12 +
 id3_tag.c |   85 +++++++++++
 misc.c    |   82 ++++++++++
 misc.h    |    5
 7 files changed, 473 insertions(+), 4 deletions(-)

Fredrik

diff -Naur easytag-0.31_gtk2.4_pre1.orig/src/easytag.c easytag-0.31_gtk2.4_pre1/src/easytag.c
--- easytag-0.31_gtk2.4_pre1.orig/src/easytag.c	2004-07-14 11:56:15.000000000 +0200
+++ easytag-0.31_gtk2.4_pre1/src/easytag.c	2004-09-05 11:01:41.878996712 +0200
@@ -407,6 +407,45 @@
     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)
+{
+  gchar **uri;
+
+  gtk_drag_finish(dc, TRUE, FALSE, t);
+
+  if (info != TARGET_URI_LIST)
+    return;
+  if(!selection_data)
+    return;
+
+  uri = g_strsplit(selection_data->data, "\r\n", 0);
+  if(*uri)
+    {
+      struct Picture *pic;
+
+      pic = Load_Picture(*uri);
+      if(pic)
+	Update_PictureEntry(pic);
+    }
+  g_strfreev(uri);
+}
+
+void Clear_Picture_Button_Clicked (GObject *object)
+{
+  Clear_PictureEntry();
+}
+
+void Open_Picture_Button_Clicked (GObject *object)
+{
+  /* FIXME: File Chooser dialog segfaults (use drag-and-drop meanwhile). */
+}
+
 GtkWidget *Create_Tag_Area (void)
 {
     GtkWidget *Separator;
@@ -420,7 +459,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(8,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 +658,59 @@
     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(_("Picture:"));
+    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);
+    {
+      GtkWidget *open_button, *clear_button;
+
+      open_button = gtk_button_new_from_stock(GTK_STOCK_OPEN);
+      clear_button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
+      gtk_table_attach(GTK_TABLE(Table), clear_button,
+		       1,6,6,7,GTK_FILL,GTK_FILL,0,0);
+      gtk_table_attach(GTK_TABLE(Table), open_button,
+		       6,10,6,7,GTK_FILL,GTK_FILL,0,0);
+
+      gtk_signal_connect(GTK_OBJECT(clear_button), "clicked",
+			 GTK_SIGNAL_FUNC(Clear_Picture_Button_Clicked), NULL);
+      gtk_signal_connect(GTK_OBJECT(open_button), "clicked",
+			 GTK_SIGNAL_FUNC(Open_Picture_Button_Clicked), NULL);
+    }
+    {
+      GdkPixbuf *pixbuf;
+      GdkPixmap *pixmap;
+      GdkBitmap *mask;
+
+      static const GtkTargetEntry drops[] = 
+	{ { "text/uri-list", 0, TARGET_URI_LIST } };
+
+      pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 1, 8, 256, 256);
+      gdk_pixbuf_fill(pixbuf, 0xffffffff);
+      gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &mask, 127);
+      PictureEntry = gtk_pixmap_new(pixmap, mask);
+
+      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);
+    }
+    gtk_table_attach_defaults(GTK_TABLE(Table),PictureEntry,1,10,7,8);
+
+    PictureMButton = gtk_button_new();
+    gtk_widget_set_usize(PictureMButton,MButtonSize,MButtonSize);
+    gtk_table_attach(GTK_TABLE(Table),PictureMButton,10,11,6,7,0,0,0,0);
+    gtk_signal_connect(GTK_OBJECT(PictureMButton),"clicked",GTK_SIGNAL_FUNC(Mini_Button_Clicked),NULL);
+    gtk_tooltips_set_tip(Tips,PictureMButton,_("Tag selected files with this picture"),NULL);
+
+    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 +726,6 @@
 }
 
 
-
 /*
  * Actions when mini buttons are pressed: apply the field to all others files
  */
@@ -894,6 +985,30 @@
         else
             msg = g_strdup(_("Removed comment from selected files."));
     }
+    else if (object==GTK_OBJECT(PictureMButton))
+    {
+        struct Picture *pic = 
+	  g_object_get_qdata(PictureEntry, 
+			     g_quark_from_static_string("Picture"));
+
+        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, Copy_Picture(pic));
+            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 picture."));
+        else
+            msg = g_strdup(_("Removed picture from selected files."));
+
+	return;
+    }
 
     g_list_foreach(selfilelist, (GFunc) gtk_tree_path_free, NULL);
     g_list_free(selfilelist);
@@ -2657,6 +2772,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);
@@ -2666,7 +2782,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);*/
 }
 
 /*
@@ -2694,6 +2811,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_pre1.orig/src/easytag.h easytag-0.31_gtk2.4_pre1/src/easytag.h
--- easytag-0.31_gtk2.4_pre1.orig/src/easytag.h	2004-06-25 23:19:01.000000000 +0200
+++ easytag-0.31_gtk2.4_pre1/src/easytag.h	2004-09-04 22:46:51.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_pre1.orig/src/et_core.c easytag-0.31_gtk2.4_pre1/src/et_core.c
--- easytag-0.31_gtk2.4_pre1.orig/src/et_core.c	2004-06-24 00:47:21.000000000 +0200
+++ easytag-0.31_gtk2.4_pre1/src/et_core.c	2004-09-05 11:02:49.875659648 +0200
@@ -344,6 +344,7 @@
         FileTag->year        = NULL;
         FileTag->genre       = NULL;
         FileTag->comment     = NULL;
+        FileTag->picture     = NULL;
         FileTag->other       = NULL;
     }
 }
@@ -1744,6 +1745,8 @@
     if (FileTag->track_total) g_free(FileTag->track_total);
     if (FileTag->genre)       g_free(FileTag->genre);
     if (FileTag->comment)     g_free(FileTag->comment);
+    if (FileTag->picture)
+      Free_Picture(FileTag->picture);
     // Free list of other fields
     ET_Free_File_Tag_Item_Other_Field(FileTag);
 
@@ -1947,6 +1950,32 @@
         FileTag->comment = NULL;
     }
 
+    if(FileTagCur->picture)
+      {
+	if(FileTag->picture)
+	  Free_Picture(FileTag->picture);
+	FileTag->picture = Allocate_Picture();
+
+	if (FileTagCur->picture->data)
+	  {
+	    FileTag->picture->size = FileTagCur->picture->size;
+	    FileTag->picture->data = g_malloc(FileTagCur->picture->size);
+	    memcpy(FileTag->picture->data,
+		   FileTagCur->picture->data, FileTagCur->picture->size);
+	  }
+	else
+	  {
+	    if (FileTag->picture->data)
+	      g_free(FileTag->picture->data);
+	    FileTag->picture->data = 0;
+	  }
+      }
+    else if(FileTag->picture)
+      {
+	Free_Picture(FileTag->picture);
+	FileTag->picture = 0;
+      }
+
     if (FileTagCur->other)
     {
         ET_Copy_File_Tag_Item_Other_Field(ETFile,FileTag);
@@ -1990,6 +2019,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 *
  ************************/
@@ -2183,6 +2233,73 @@
     g_free(text1);
 }
 
+void Clear_PictureEntry()
+{
+  GdkPixbuf *pixbuf;
+  GdkPixmap *pixmap;
+  GdkBitmap *mask;
+  
+  pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, 1, 8, 256, 256);
+  gdk_pixbuf_fill(pixbuf, 0xffffffff);
+  gdk_pixbuf_render_pixmap_and_mask(pixbuf, &pixmap, &mask, 127);
+  gtk_pixmap_set(GTK_PIXMAP(PictureEntry), pixmap, mask);
+#if 0
+  /* Doesn't work? */
+  gdk_pixmap_unref(pixmap);
+  gdk_bitmap_unref(mask);
+#endif
+
+  g_object_set_qdata(PictureEntry, g_quark_from_static_string("Picture"), 0);
+}
+
+void Update_PictureEntry(struct Picture *pic)
+{
+  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))
+	{
+	  GdkPixbuf *pixbuf;
+
+	  pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+	  if(pixbuf)
+	    {
+	      GdkPixbuf *scaled_pixbuf;
+	      GdkPixmap *pixmap;
+	      GdkBitmap *mask;
+
+	      scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, 
+						      256, 256,
+						      GDK_INTERP_BILINEAR);
+		    
+	      gdk_pixbuf_render_pixmap_and_mask(scaled_pixbuf, 
+						&pixmap, &mask, 127);
+	      gdk_pixbuf_unref(scaled_pixbuf);
+	      gdk_pixbuf_unref(pixbuf);
+
+	      gtk_pixmap_set(GTK_PIXMAP(PictureEntry), pixmap, mask);
+#if 0
+	      gdk_pixmap_unref(pixmap);
+	      gdk_bitmap_unref(mask);
+#endif
+	      g_object_set_qdata_full(PictureEntry, 
+				      g_quark_from_static_string("Picture"), 
+				      Copy_Picture(pic), Free_Picture);
+
+	    }
+	}
+    }
+  gdk_pixbuf_loader_close(loader, 0);
+}
+
 
 /*
  * Display all tag infos (tags fields) into entry boxes of the user interface.
@@ -2202,6 +2319,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;
     }
@@ -2258,6 +2376,12 @@
     else
         gtk_entry_set_text(GTK_ENTRY(CommentEntry),"");
 
+    /* Show picture */
+    if (FileTag && FileTag->picture)
+      Update_PictureEntry(FileTag->picture);
+    else
+      Clear_PictureEntry();
+
     return TRUE;
 }
 
@@ -2602,6 +2726,12 @@
         g_free(buffer);
     }
 
+
+    /* Picture */
+    FileTag->picture = 
+      Copy_Picture(g_object_get_qdata(PictureEntry, 
+				      g_quark_from_static_string("Picture")));
+
     return TRUE;
 }
 
@@ -2717,6 +2847,32 @@
     }
     Strip_String(FileTag->comment);
 
+    /* Picture */
+    if(FileTagCur->picture)
+      {
+	if(FileTag->picture)
+	  Free_Picture(FileTag->picture);
+	FileTag->picture = Allocate_Picture();
+
+	if ( FileTagCur->picture->data)
+	  {
+	    FileTag->picture->size = FileTagCur->picture->size;
+	    FileTag->picture->data = g_malloc(FileTagCur->picture->size);
+	    memcpy(FileTag->picture->data,
+		   FileTagCur->picture->data, FileTagCur->picture->size);
+	  } 
+	else
+	  {
+	    if (FileTag->picture->data)
+	      g_free(FileTag->picture->data);
+	    FileTag->picture->data = 0;
+	  }
+      } 
+    else if(FileTag->picture)
+      {
+	Free_Picture(FileTag->picture);
+	FileTag->picture = 0;
+      }
 
     return TRUE;
 }
@@ -2992,6 +3148,17 @@
     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 */
+    if ( FileTag1->picture && !FileTag2->picture && FileTag1->picture->data) 
+      return TRUE;
+    if (!FileTag1->picture &&  FileTag2->picture && FileTag2->picture->data) 
+      return TRUE;
+    if ( FileTag1->picture && FileTag2->picture && 
+	 (FileTag1->picture->size != FileTag2->picture->size ||
+	  memcmp(FileTag1->picture->data, FileTag2->picture->data,
+		 FileTag1->picture->size)))
+      return TRUE;
+
     return FALSE; /* No changes */
 }
 
diff -Naur easytag-0.31_gtk2.4_pre1.orig/src/et_core.h easytag-0.31_gtk2.4_pre1/src/et_core.h
--- easytag-0.31_gtk2.4_pre1.orig/src/et_core.h	2004-07-01 22:56:42.000000000 +0200
+++ easytag-0.31_gtk2.4_pre1/src/et_core.h	2004-09-04 23:59:24.000000000 +0200
@@ -135,6 +135,12 @@
 /*
  * Description of each item of the TagList list
  */
+struct Picture
+{
+  gulong size;
+  guchar *data;
+};
+
 typedef struct _File_Tag File_Tag;
 struct _File_Tag
 {
@@ -148,6 +154,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) */
 };
 
@@ -315,6 +322,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);
@@ -327,6 +336,9 @@
 
 gboolean ET_Set_Displayed_File_List         (GList *ETFileList);
 
+void Clear_PictureEntry();
+void Update_PictureEntry(struct Picture *pic);
+
 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_pre1.orig/src/id3_tag.c easytag-0.31_gtk2.4_pre1/src/id3_tag.c
--- easytag-0.31_gtk2.4_pre1.orig/src/id3_tag.c	2004-06-24 00:47:21.000000000 +0200
+++ easytag-0.31_gtk2.4_pre1/src/id3_tag.c	2004-09-05 00:24:33.000000000 +0200
@@ -384,6 +384,43 @@
         g_free(comment2);
         }*/
     }
+
+    /***********
+     * Picture *
+     ***********/
+    id3_frame = ID3Tag_FindFrameWithINT(id3_tag, ID3FID_PICTURE,
+					ID3FN_PICTURETYPE, ID3PT_OTHER);
+    if(!id3_frame)
+      id3_frame = ID3Tag_FindFrameWithINT(id3_tag, ID3FID_PICTURE,
+					  ID3FN_PICTURETYPE, ID3PT_COVERFRONT);
+    if(!id3_frame)
+      id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_PICTURE);
+    if(id3_frame)
+      {
+	FileTag->picture = Allocate_Picture();
+
+	if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_IMAGEFORMAT)) )
+	  if ( (num_chars = ID3Field_GetASCII_1(id3_field, string,
+						ID3V2_MAX_STRING_LEN, 
+						field_num)) > 0 && 
+	       string != NULL )
+	    fprintf(stderr, "ID3FN_IMAGEFORMAT: %s\n", string);
+	if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_MIMETYPE)) )
+	  if ( (num_chars = ID3Field_GetASCII_1(id3_field, string,
+						ID3V2_MAX_STRING_LEN, 
+						field_num)) > 0 && 
+	       string != NULL )
+	    fprintf(stderr, "ID3FN_MIMEFORMAT: %s\n", string);
+	if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_DATA)) )
+	  {
+	    FileTag->picture->size = ID3Field_Size(id3_field);
+	    FileTag->picture->data = g_malloc(FileTag->picture->size);
+	    ID3Field_GetBINARY(id3_field, 
+			       FileTag->picture->data, FileTag->picture->size);
+	    fprintf(stderr, "ID3FN size: %d\n", (int)FileTag->picture->size);
+	  }
+      }
+
     g_free(string);
 
     /* Free allocated data */
@@ -420,6 +457,7 @@
     gboolean has_track    = 1;
     gboolean has_genre    = 1;
     gboolean has_comment  = 1;
+    gboolean has_picture  = 1;
     gboolean has_song_len = 1;
 
     ID3Frame *id3_frame;
@@ -431,7 +469,6 @@
 
     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);
 
@@ -656,6 +693,52 @@
     }
 
 
+    /***********
+     * Picture *
+     ***********/
+    while ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_PICTURE)) )
+        ID3Tag_RemoveFrame(id3_tag,id3_frame);
+    if (FileTag->picture)
+    {
+        id3_frame = ID3Frame_NewID(ID3FID_PICTURE);
+        ID3Tag_AttachFrame(id3_tag,id3_frame);
+
+	/* FIXME: Possibly use gnome_vfs_get_mime_type_for_buffer. */
+	if(FileTag->picture->data && FileTag->picture->size > 2 &&
+	   FileTag->picture->data[0] == 0xff &&
+	   FileTag->picture->data[1] == 0xd8)
+	  {
+	    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");
+	  }
+	else if(FileTag->picture->data && FileTag->picture->size > 8 &&
+		FileTag->picture->data[0] == 0x89 &&
+		FileTag->picture->data[1] == 0x50 &&
+		FileTag->picture->data[2] == 0x4e &&
+		FileTag->picture->data[3] == 0x47 &&
+		FileTag->picture->data[4] == 0x0d &&
+		FileTag->picture->data[5] == 0x0a &&
+		FileTag->picture->data[6] == 0x1a &&
+		FileTag->picture->data[7] == 0x0a)
+	  {
+	    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");
+	  }
+        if ((id3_field = ID3Frame_GetField(id3_frame, ID3FN_PICTURETYPE)))
+	  ID3Field_SetINT(id3_field, ID3PT_OTHER);
+        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_DATA)))
+	  ID3Field_SetBINARY(id3_field, 
+			     FileTag->picture->data, FileTag->picture->size);
+    } else
+    {
+        has_picture = 0;
+    }
+
+
     /*********************************
      * File length (in milliseconds) *
      *********************************/
diff -Naur easytag-0.31_gtk2.4_pre1.orig/src/misc.c easytag-0.31_gtk2.4_pre1/src/misc.c
--- easytag-0.31_gtk2.4_pre1.orig/src/misc.c	2004-07-14 12:15:22.000000000 +0200
+++ easytag-0.31_gtk2.4_pre1/src/misc.c	2004-09-04 23:12:58.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"
@@ -2721,3 +2723,83 @@
 
     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(struct Picture *pic)
+{
+  struct Picture *pic2;
+
+  if(!pic)
+    return 0;
+  pic2 = Allocate_Picture();
+  if(pic->data)
+    {
+      pic2->size = pic->size;
+      pic2->data = g_malloc(pic2->size);
+      memcpy(pic2->data, pic->data, pic->size);
+    }
+  return pic2;
+}
+
+void Free_Picture(struct Picture *pic)
+{
+  if(pic->data)
+    g_free(pic->data);
+  g_free(pic);
+}
+
+#define LOAD_BUFFER_SIZE 4096
+
+struct Picture *Load_Picture(const gchar *uri)
+{
+  struct Picture *pic;
+  gchar *buffer = 0;
+  size_t size = 0;
+  int fd;
+
+  if(g_ascii_strncasecmp("file:", uri, 5))
+    return FALSE;
+  fd = open(uri + 5, 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;
+}
diff -Naur easytag-0.31_gtk2.4_pre1.orig/src/misc.h easytag-0.31_gtk2.4_pre1/src/misc.h
--- easytag-0.31_gtk2.4_pre1.orig/src/misc.h	2004-07-01 21:46:28.000000000 +0200
+++ easytag-0.31_gtk2.4_pre1/src/misc.h	2004-09-04 19:29:52.000000000 +0200
@@ -112,5 +112,10 @@
 // Load filenames window
 void Open_Load_Filename_Window (void);
 
+struct Picture;
+
+struct Picture *Allocate_Picture(void);
+void Free_Picture(struct Picture *pic);
+struct Picture *Load_Picture(const gchar *uri);
 
 #endif /* __MISC_H__ */


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