diff options
Diffstat (limited to 'src/mp4_tag.c')
-rwxr-xr-x | src/mp4_tag.c | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/src/mp4_tag.c b/src/mp4_tag.c new file mode 100755 index 0000000..86b4cff --- /dev/null +++ b/src/mp4_tag.c @@ -0,0 +1,429 @@ +/* mp4_tag.c - 2005/08/06 */ +/* + * EasyTAG - Tag editor for MP3 and Ogg Vorbis files + * Copyright (C) 2001-2005 Jerome Couderc <easytag@gmail.com> + * Copyright (C) 2005 Michael Ihde <mike.ihde@randomwalking.com> + * Copyright (C) 2005 Stewart Whitman <swhitman@cox.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Portions of this code was borrowed from the MPEG4IP tools project */ +#include <config.h> // For definition of ENABLE_MP4 + +#ifdef ENABLE_MP4 + +#include <gtk/gtk.h> +#include <glib/gi18n-lib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#include "mp4_tag.h" +#include "picture.h" +#include "easytag.h" +#include "setting.h" +#include "log.h" +#include "misc.h" +#include "et_core.h" +#include "charset.h" + +/* These undefs are because the mpeg4ip library contains a gnu config file in it's .h file */ +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#include <mp4.h> + + +/**************** + * Declarations * + ****************/ + + +/************** + * Prototypes * + **************/ + + +/************* + * Functions * + *************/ + +/* + * Mp4_Tag_Read_File_Tag: + * + * Read tag data into an Mp4 file. + * + * Note: + * - for string fields, //if field is found but contains no info (strlen(str)==0), we don't read it + * - for track numbers, if they are zero, then we don't read it + */ +gboolean Mp4tag_Read_File_Tag (gchar *filename, File_Tag *FileTag) +{ + FILE *file; + MP4FileHandle mp4file = NULL; + uint16_t track, track_total; + uint16_t disk, disktotal; + u_int8_t *coverArt; + u_int32_t coverSize; + + if (!filename || !FileTag) + return FALSE; + + if ( (file=fopen(filename,"r"))==NULL ) + { + gchar *filename_utf8 = filename_to_display(filename); + Log_Print(_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno)); + g_free(filename_utf8); + return FALSE; + } + fclose(file); // We close it cause mp4 opens/closes file itself + + /* Get data from tag */ + mp4file = MP4Read(filename, 0); + if (mp4file == MP4_INVALID_FILE_HANDLE) + { + gchar *filename_utf8 = filename_to_display(filename); + Log_Print(_("ERROR while opening file: '%s' (%s)."),filename_utf8,_("MP4 format invalid")); + g_free(filename_utf8); + return FALSE; + } + + /* TODO Add error detection */ + + /********* + * Title * + *********/ + MP4GetMetadataName(mp4file, &FileTag->title); + + /********** + * Artist * + **********/ + MP4GetMetadataArtist(mp4file, &FileTag->artist); + + /********* + * Album * + *********/ + MP4GetMetadataAlbum(mp4file, &FileTag->album); + + /********************** + * Disk / Total Disks * + **********************/ + if (MP4GetMetadataDisk(mp4file, &disk, &disktotal)) + { + if (disk != 0 && disktotal != 0) + FileTag->disc_number = g_strdup_printf("%d/%d",(gint)disk,(gint)disktotal); + else if (disk != 0) + FileTag->disc_number = g_strdup_printf("%d",(gint)disk); + else if (disktotal != 0) + FileTag->disc_number = g_strdup_printf("/%d",(gint)disktotal); + //if (disktotal != 0) + // FileTag->disk_number_total = g_strdup_printf("%d",(gint)disktotal); + } + + /******** + * Year * + ********/ + MP4GetMetadataYear(mp4file, &FileTag->year); + + /************************* + * Track and Total Track * + *************************/ + if (MP4GetMetadataTrack(mp4file, &track, &track_total)) + { + if (track != 0) + FileTag->track = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,(gint)track); // Just to have numbers like this : '01', '05', '12', ... + if (track_total != 0) + FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,(gint)track_total); // Just to have numbers like this : '01', '05', '12', ... + } + + /********* + * Genre * + *********/ + MP4GetMetadataGenre(mp4file, &FileTag->genre); + + /*********** + * Comment * + ***********/ + MP4GetMetadataComment(mp4file, &FileTag->comment); + + /********************** + * Composer or Writer * + **********************/ + MP4GetMetadataWriter(mp4file, &FileTag->composer); + + /***************** + * Encoding Tool * + *****************/ + MP4GetMetadataTool(mp4file, &FileTag->encoded_by); + + /* Unimplemented + + Tempo / BPM + MP4GetMetadataTempo(file, &string) + */ + + /*********** + * Picture * + ***********/ + // There is only one picture! + if ( MP4GetMetadataCoverArt( mp4file, &coverArt, &coverSize ) ) + { + Picture *pic = Picture_Allocate(); + pic->size = coverSize; + pic->data = coverArt; + pic->type = PICTURE_TYPE_FRONT_COVER; + pic->description = NULL; + + FileTag->picture = pic; + } + + + /* Free allocated data */ + MP4Close(mp4file); + + return TRUE; +} + + +/* + * Mp4_Tag_Write_File_Tag: + * + * Write tag data into an Mp4 file. + * + * Note: + * - for track numbers, we write 0's if one or the other is blank + */ +gboolean Mp4tag_Write_File_Tag (ET_File *ETFile) +{ + File_Tag *FileTag; + gchar *filename; + gchar *filename_utf8; + FILE *file; + MP4FileHandle mp4file = NULL; + gint error = 0; + + if (!ETFile || !ETFile->FileTag) + return FALSE; + + FileTag = (File_Tag *)ETFile->FileTag->data; + filename = ((File_Name *)ETFile->FileNameCur->data)->value; + filename_utf8 = ((File_Name *)ETFile->FileNameCur->data)->value_utf8; + + /* Test to know if we can write into the file */ + if ( (file=fopen(filename,"r+"))==NULL ) + { + Log_Print(_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno)); + return FALSE; + } + fclose(file); + + /* Open file for writing */ + mp4file = MP4Modify(filename,0,0); + if (mp4file == MP4_INVALID_FILE_HANDLE) + { + Log_Print(_("ERROR while opening file: '%s' (%s)."),filename_utf8,_("MP4 format invalid")); + return FALSE; + } + + /********* + * Title * + *********/ + if (FileTag->title && g_utf8_strlen(FileTag->title, -1) > 0) + { + MP4SetMetadataName(mp4file, FileTag->title); + }else + { + //MP4DeleteMetadataName(mp4file); // Not available on mpeg4ip-1.2 (only in 1.3) + MP4SetMetadataName(mp4file, ""); + } + + /********** + * Artist * + **********/ + if (FileTag->artist && g_utf8_strlen(FileTag->artist, -1) > 0) + { + MP4SetMetadataArtist(mp4file, FileTag->artist); + }else + { + //MP4DeleteMetadataArtist(mp4file); + MP4SetMetadataArtist(mp4file, ""); + } + + /********* + * Album * + *********/ + if (FileTag->album && g_utf8_strlen(FileTag->album, -1) > 0) + { + MP4SetMetadataAlbum(mp4file, FileTag->album); + }else + { + //MP4DeleteMetadataAlbum(mp4file); + MP4SetMetadataAlbum(mp4file, ""); + } + + /********************** + * Disk / Total Disks * + **********************/ + if (FileTag->disc_number && g_utf8_strlen(FileTag->disc_number, -1) > 0) + //|| FileTag->disc_number_total && g_utf8_strlen(FileTag->disc_number_total, -1) > 0) + { + uint16_t disk = 0; + uint16_t disktotal = 0; + + /* At the present time, we manage only disk number like '1' or '1/2', we + * don't use disk number total... so here we try to decompose */ + if (FileTag->disc_number) + { + gchar *dn_tmp = g_strdup(FileTag->disc_number); + gchar *tmp = strchr(dn_tmp,'/'); + if (tmp) + { + // A disc_number_total was entered + if ( (tmp+1) && atoi(tmp+1) ) + disktotal = atoi(tmp+1); + + // Fill disc_number + *tmp = '\0'; + disk = atoi(dn_tmp); + }else + { + disk = atoi(FileTag->disc_number); + } + g_free(dn_tmp); + } + /*if (FileTag->disc_number) + disk = atoi(FileTag->disc_number); + if (FileTag->disc_number_total) + disktotal = atoi(FileTag->disc_number_total); + */ + MP4SetMetadataDisk(mp4file, disk, disktotal); + }else + { + //MP4DeleteMetadataDisk(mp4file); + MP4SetMetadataDisk(mp4file, 0, 0); + } + + /******** + * Year * + ********/ + if (FileTag->year && g_utf8_strlen(FileTag->year, -1) > 0) + { + MP4SetMetadataYear(mp4file, FileTag->year); + }else + { + //MP4DeleteMetadataYear(mp4file); + MP4SetMetadataYear(mp4file, ""); + } + + /************************* + * Track and Total Track * + *************************/ + if ( (FileTag->track && g_utf8_strlen(FileTag->track, -1) > 0) + || (FileTag->track_total && g_utf8_strlen(FileTag->track_total, -1) > 0) ) + { + uint16_t track = 0; + uint16_t track_total = 0; + if (FileTag->track) + track = atoi(FileTag->track); + if (FileTag->track_total) + track_total = atoi(FileTag->track_total); + MP4SetMetadataTrack(mp4file, track, track_total); + }else + { + //MP4DeleteMetadataTrack(mp4file); + MP4SetMetadataTrack(mp4file, 0, 0); + } + + /********* + * Genre * + *********/ + if (FileTag->genre && g_utf8_strlen(FileTag->genre, -1) > 0 ) + { + MP4SetMetadataGenre(mp4file, FileTag->genre); + }else + { + //MP4DeleteMetadataGenre(mp4file); + MP4SetMetadataGenre(mp4file, ""); + } + + /*********** + * Comment * + ***********/ + if (FileTag->comment && g_utf8_strlen(FileTag->comment, -1) > 0) + { + MP4SetMetadataComment(mp4file, FileTag->comment); + }else + { + //MP4DeleteMetadataComment(mp4file); + MP4SetMetadataComment(mp4file, ""); + } + + /********************** + * Composer or Writer * + **********************/ + if (FileTag->composer && g_utf8_strlen(FileTag->composer, -1) > 0) + { + MP4SetMetadataWriter(mp4file, FileTag->composer); + }else + { + //MP4DeleteMetadataWriter(mp4file); + MP4SetMetadataWriter(mp4file, ""); + } + + /***************** + * Encoding Tool * + *****************/ + if (FileTag->encoded_by && g_utf8_strlen(FileTag->encoded_by, -1) > 0) + { + MP4SetMetadataTool(mp4file, FileTag->encoded_by); + }else + { + //MP4DeleteMetadataTool(mp4file); + MP4SetMetadataTool(mp4file, ""); + } + + /*********** + * Picture * + ***********/ + { + Picture *pic; + + //MP4DeleteMetadataCoverArt(mp4file); + MP4SetMetadataCoverArt(mp4file, NULL, 0); + for( pic = FileTag->picture; pic; pic = pic->next ) + { + if( pic->type == PICTURE_TYPE_FRONT_COVER ) + { + MP4SetMetadataCoverArt(mp4file, pic->data, pic->size); + } + } + } + + + MP4Close(mp4file); + + if (error) return FALSE; + else return TRUE; +} + + +#endif /* ENABLE_MP4 */ |