[easytag/wip/dsf-support: 2/2] Read ID3v2 tags from DSF files
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [easytag/wip/dsf-support: 2/2] Read ID3v2 tags from DSF files
- Date: Sun, 9 Nov 2014 12:38:41 +0000 (UTC)
commit 33ea6f630464064de96e6fcac75bda2686136e18
Author: David King <amigadave amigadave com>
Date: Sun Nov 9 12:32:14 2014 +0000
Read ID3v2 tags from DSF files
Split off a helper et_id3tag_fill_file_tag_from_id3tag() function from
id3tag_read_file_tag() and use it to read the parsed id3_tag struct.
Makefile.am | 2 +
src/et_core.c | 24 +++-
src/et_core.h | 1 +
src/tag_area.c | 20 +++
src/tags/dsf_tag.c | 242 +++++++++++++++++++++++++++++++++
src/tags/dsf_tag.h | 31 +++++
src/tags/id3_tag.h | 7 +
src/tags/id3v24_tag.c | 359 ++++++++++++++++++++-----------------------------
8 files changed, 473 insertions(+), 213 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 0fc9d46..a787261 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -71,6 +71,7 @@ easytag_SOURCES = \
src/tags/libapetag/info_mpc.c \
src/tags/ape_tag.c \
src/tags/dsf_header.c \
+ src/tags/dsf_tag.c \
src/tags/flac_header.c \
src/tags/flac_tag.c \
src/tags/gio_wrapper.cc \
@@ -124,6 +125,7 @@ easytag_headers = \
src/tags/libapetag/info_mpc.h \
src/tags/ape_tag.h \
src/tags/dsf_header.h \
+ src/tags/dsf_tag.h \
src/tags/flac_header.h \
src/tags/flac_tag.h \
src/tags/gio_wrapper.h \
diff --git a/src/et_core.c b/src/et_core.c
index fabf16f..cb163c3 100644
--- a/src/et_core.c
+++ b/src/et_core.c
@@ -39,7 +39,8 @@
#include "monkeyaudio_header.h"
#include "musepack_header.h"
#ifdef ENABLE_MP3
-# include "id3_tag.h"
+#include "dsf_tag.h"
+#include "id3_tag.h"
#endif
#include "picture.h"
#include "ape_tag.h"
@@ -111,7 +112,7 @@ const ET_File_Description ETFileDescription[] =
{ MP4_FILE, ".m4p", MP4_TAG}, /* Implemented by Michael Ihde. */
{ MP4_FILE, ".m4v", MP4_TAG},
#endif
- { DSF_FILE, ".dsf", UNKNOWN_TAG },
+ { DSF_FILE, ".dsf", DSF_TAG }, /* ID3v2 tag at offset in DSF file. */
#ifdef ENABLE_WAVPACK
{ WAVPACK_FILE, ".wv", WAVPACK_TAG}, /* Implemented by Maarten Maathuis. */
#endif
@@ -581,6 +582,17 @@ GList *ET_Add_File_To_File_List (gchar *filename)
}
break;
#endif
+#ifdef ENABLE_MP3 /* DSF tags use an embedded ID3v2 tag. */
+ case DSF_TAG:
+ if (!et_dsf_tag_read_file_tag (file, FileTag, &error))
+ {
+ Log_Print (LOG_ERROR,
+ _("Error reading tag from DSF file ‘%s’: %s"),
+ filename_utf8, error->message);
+ g_clear_error (&error);
+ }
+ break;
+#endif
#ifdef ENABLE_WAVPACK
case WAVPACK_TAG:
if (!wavpack_tag_read_file_tag (file, FileTag, &error))
@@ -3120,6 +3132,9 @@ void ET_Save_File_Data_From_UI (ET_File *ETFile)
#ifdef ENABLE_MP4
case MP4_TAG:
#endif
+#ifdef ENABLE_MP3
+ case DSF_TAG:
+#endif
#ifdef ENABLE_WAVPACK
case WAVPACK_TAG:
#endif
@@ -3570,6 +3585,11 @@ ET_Save_File_Tag_To_HD (ET_File *ETFile, GError **error)
state = mp4tag_write_file_tag (ETFile, error);
break;
#endif
+#ifdef ENABLE_MP3
+ case DSF_TAG:
+ state = et_dsf_tag_write_file_tag (ETFile, error);
+ break;
+#endif
#ifdef ENABLE_WAVPACK
case WAVPACK_TAG:
state = wavpack_tag_write_file_tag (ETFile, error);
diff --git a/src/et_core.h b/src/et_core.h
index 785a9aa..9b6f993 100644
--- a/src/et_core.h
+++ b/src/et_core.h
@@ -67,6 +67,7 @@ typedef enum
MP4_TAG,
WAVPACK_TAG,
OPUS_TAG,
+ DSF_TAG, /* ID3v2 tag in DSF file. */
UNKNOWN_TAG
} ET_Tag_Type;
diff --git a/src/tag_area.c b/src/tag_area.c
index 7c6c98b..dd03722 100644
--- a/src/tag_area.c
+++ b/src/tag_area.c
@@ -1431,6 +1431,7 @@ load_picture_from_file (GFile *file,
case OPUS_TAG:
case APE_TAG:
case FLAC_TAG:
+ case DSF_TAG:
case WAVPACK_TAG:
pic->description = g_strdup (filename_utf8);
@@ -2608,6 +2609,25 @@ et_tag_area_update_controls (EtTagArea *self,
break;
#endif
+ /* Identical to ID3v2. */
+#ifdef ENABLE_MP3
+ case DSF_TAG:
+ gtk_widget_show (priv->disc_number_label);
+ gtk_widget_show (priv->disc_number_entry);
+ gtk_widget_show (priv->composer_label);
+ gtk_widget_show (priv->composer_entry);
+ gtk_widget_show (priv->orig_artist_label);
+ gtk_widget_show (priv->orig_artist_entry);
+ gtk_widget_show (priv->copyright_label);
+ gtk_widget_show (priv->copyright_entry);
+ gtk_widget_show (priv->url_label);
+ gtk_widget_show (priv->url_entry);
+ gtk_widget_show (priv->encoded_by_label);
+ gtk_widget_show (priv->encoded_by_entry);
+ et_tag_area_show_images_tab (self);
+ break;
+#endif /* ENABLE_MP3 */
+
#ifdef ENABLE_WAVPACK
case WAVPACK_TAG:
gtk_widget_show (priv->disc_number_label);
diff --git a/src/tags/dsf_tag.c b/src/tags/dsf_tag.c
new file mode 100644
index 0000000..6bf7d89
--- /dev/null
+++ b/src/tags/dsf_tag.c
@@ -0,0 +1,242 @@
+/* EasyTAG - Tag editor for audio files.
+ * Copyright (C) 2014 David King <amigadave amigadave com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <errno.h>
+
+#include "dsf_tag.h"
+
+#include "easytag.h"
+#include "et_core.h"
+#include "misc.h"
+
+#ifdef ENABLE_MP3
+
+#include <id3tag.h>
+#include "id3_tag.h"
+
+#define DSF_HEADER_LENGTH 80
+
+/* Read the little-endian 64-bit integer from the next 8 characters. */
+static guint64
+guint64_from_bytes (guchar *str)
+{
+ gsize i;
+ guint64 result = 0;
+
+ for (i = 8; i > 0; i--)
+ {
+ result = (result << 8) + str[i - 1];
+ }
+
+ return result;
+}
+
+gboolean
+et_dsf_tag_read_file_tag (GFile *file,
+ File_Tag *FileTag,
+ GError **error)
+{
+ GInputStream *istream;
+ guchar header[DSF_HEADER_LENGTH];
+ gsize bytes_read;
+ guint64 size;
+ guint64 id3_offset;
+ GSeekable *seekable;
+ guchar id3_query[ID3_TAG_QUERYSIZE];
+ long tagsize;
+ guchar *id3_buffer;
+ struct id3_tag *tag;
+ gboolean update;
+
+ g_return_val_if_fail (file != NULL && FileTag != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ istream = G_INPUT_STREAM (g_file_read (file, NULL, error));
+
+ if (!istream)
+ {
+ return FALSE;
+ }
+
+ /* Read the complete header from the file. */
+ if (!g_input_stream_read_all (istream, &header, DSF_HEADER_LENGTH,
+ &bytes_read, NULL, error))
+ {
+ g_debug ("Only %" G_GSIZE_FORMAT " bytes out of %d "
+ "bytes were read", bytes_read, DSF_HEADER_LENGTH);
+ goto err;
+ }
+
+ if (memcmp (&header, "DSD ", 4) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ _("Not a DSD file"));
+ goto err;
+ }
+
+ if (memcmp (&header[28], "fmt ", 4) != 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ _("Not a DSD file"));
+ goto err;
+ }
+
+ /* 12 (8 bytes) total file size. */
+ size = guint64_from_bytes (&header[12]);
+
+ /* 20 (8 bytes) metadata chunk offset, or 0 if no tag is present. */
+ id3_offset = guint64_from_bytes (&header[20]);
+
+ if (id3_offset == 0)
+ {
+ /* No ID3v2 tag. */
+ g_object_unref (istream);
+ return TRUE;
+ }
+
+ if (id3_offset >= size)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ _("Invalid DSF header"));
+ goto err;
+ }
+
+ seekable = G_SEEKABLE (istream);
+
+ if (!g_seekable_can_seek (seekable))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_BADF, "%s",
+ g_strerror (EBADF));
+ goto err;
+ }
+
+ if (!g_seekable_seek (seekable, id3_offset, G_SEEK_SET, NULL, error))
+ {
+ goto err;
+ }
+
+ if (!g_input_stream_read_all (istream, id3_query, ID3_TAG_QUERYSIZE,
+ &bytes_read, NULL, error))
+ {
+ goto err;
+ }
+ else if (bytes_read != ID3_TAG_QUERYSIZE)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, "%s",
+ _("Error reading tags from file"));
+ goto err;
+ }
+
+ if ((tagsize = id3_tag_query ((id3_byte_t const *)id3_query,
+ ID3_TAG_QUERYSIZE)) <= ID3_TAG_QUERYSIZE)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, "%s",
+ _("Error reading tags from file"));
+ goto err;
+ }
+
+ id3_buffer = g_malloc0 (tagsize);
+ /* Copy the query buffer. */
+ memcpy (id3_buffer, id3_query, ID3_TAG_QUERYSIZE);
+
+ if (!g_input_stream_read_all (istream, &id3_buffer[ID3_TAG_QUERYSIZE],
+ tagsize - ID3_TAG_QUERYSIZE, &bytes_read,
+ NULL, error))
+ {
+ g_free (id3_buffer);
+ goto err;
+ }
+ else if (bytes_read != tagsize - ID3_TAG_QUERYSIZE)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, "%s",
+ _("Error reading tags from file"));
+ g_free (id3_buffer);
+ goto err;
+ }
+
+ g_object_unref (istream);
+
+ if ((tag = id3_tag_parse ((id3_byte_t const *)id3_buffer, tagsize)))
+ {
+ unsigned version = id3_tag_version (tag);
+
+#ifdef ENABLE_ID3LIB
+ /* Besides upgrading old tags, downgrade ID3v2.4 to ID3v2.3 */
+ if (g_settings_get_boolean (MainSettings, "id3v2-version-4"))
+ {
+ update = (ID3_TAG_VERSION_MAJOR (version) < 4);
+ }
+ else
+ {
+ update = ((ID3_TAG_VERSION_MAJOR (version) < 3)
+ | (ID3_TAG_VERSION_MAJOR (version) == 4));
+ }
+#else
+ update = (ID3_TAG_VERSION_MAJOR (version) < 4);
+#endif
+ }
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ _("Error reading tags from file"));
+ g_free (id3_buffer);
+ return FALSE;
+ }
+
+ g_free (id3_buffer);
+
+ /* Check for an empty tag. */
+ if (tag->nframes == 0)
+ {
+ id3_tag_delete (tag);
+ return TRUE;
+ }
+
+ update |= et_id3tag_fill_file_tag_from_id3tag (tag, FileTag);
+
+ if (update)
+ {
+ FileTag->saved = FALSE;
+ }
+
+ id3_tag_delete (tag);
+
+ return TRUE;
+
+err:
+ g_object_unref (istream);
+ return FALSE;
+}
+
+gboolean
+et_dsf_tag_write_file_tag (const ET_File *ETFile,
+ GError **error)
+{
+ g_return_val_if_fail (ETFile != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* TODO: Implement! */
+ /* TODO: Read header, seek to ID3v2 offset, truncate file, write new tag,
+ * using ID3v2.3 or 2.4 depending on id3v2-version-4 setting. */
+ return FALSE;
+}
+
+#endif /* ENABLE_MP3 */
diff --git a/src/tags/dsf_tag.h b/src/tags/dsf_tag.h
new file mode 100644
index 0000000..ba32b6f
--- /dev/null
+++ b/src/tags/dsf_tag.h
@@ -0,0 +1,31 @@
+/* EasyTAG - Tag editor for audio files
+ * Copyright (C) 2014 David King <amigadave amigadave com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ET_DSF_TAG_H_
+#define ET_DSF_TAG_H_
+
+#include "et_core.h"
+
+G_BEGIN_DECLS
+
+gboolean et_dsf_tag_read_file_tag (GFile *file, File_Tag *FileTag, GError **error);
+gboolean et_dsf_tag_write_file_tag (const ET_File *ETFile, GError **error);
+
+G_END_DECLS
+
+#endif /* ET_DSF_TAG_H_ */
diff --git a/src/tags/id3_tag.h b/src/tags/id3_tag.h
index fd72dcc..5f74991 100644
--- a/src/tags/id3_tag.h
+++ b/src/tags/id3_tag.h
@@ -20,6 +20,8 @@
#ifndef ET_ID3TAG_H_
#define ET_ID3TAG_H_
+#include "config.h"
+
#include <glib.h>
#include "et_core.h"
@@ -36,6 +38,11 @@ guchar Id3tag_String_To_Genre (const gchar *genre);
gchar *et_id3tag_get_tpos_from_file_tag (const File_Tag *file_tag);
+#ifdef ENABLE_MP3
+#include <id3tag.h>
+gboolean et_id3tag_fill_file_tag_from_id3tag (struct id3_tag *tag, File_Tag *file_tag);
+#endif /* ENABLE_MP3 */
+
G_END_DECLS
#endif /* ET_ID3TAG_H_ */
diff --git a/src/tags/id3v24_tag.c b/src/tags/id3v24_tag.c
index ee7739b..6f0c54c 100644
--- a/src/tags/id3v24_tag.c
+++ b/src/tags/id3v24_tag.c
@@ -80,168 +80,16 @@ static int etag_set_tags (const gchar *str, const char *frame_nam
static gboolean etag_write_tags (const gchar *filename, struct id3_tag const *v1tag,
struct id3_tag const *v2tag, gboolean strip_tags, GError **error);
-/*************
- * Functions *
- *************/
-
-/*
- * Read id3v1.x / id3v2 tag and load data into the File_Tag structure.
- * Returns TRUE on success, else FALSE.
- * If a tag entry exists (ex: title), we allocate memory, else value stays to NULL
- */
gboolean
-id3tag_read_file_tag (GFile *gfile,
- File_Tag *FileTag,
- GError **error)
+et_id3tag_fill_file_tag_from_id3tag (struct id3_tag *tag,
+ File_Tag *FileTag)
{
- GInputStream *istream;
- gsize bytes_read;
- GSeekable *seekable;
- gchar *filename;
- struct id3_file *file;
- struct id3_tag *tag;
struct id3_frame *frame;
union id3_field *field;
gchar *string1, *string2;
Picture *prev_pic = NULL;
- int i, j;
- unsigned tmpupdate, update = 0;
- long tagsize;
-
- g_return_val_if_fail (gfile != NULL && FileTag != NULL, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- istream = G_INPUT_STREAM (g_file_read (gfile, NULL, error));
-
- if (!istream)
- {
- return FALSE;
- }
-
- string1 = g_malloc0 (ID3_TAG_QUERYSIZE);
-
- /* Check if the file has an ID3v2 tag or/and an ID3v1 tags.
- * 1) ID3v2 tag. */
- if (!g_input_stream_read_all (istream, string1, ID3_TAG_QUERYSIZE,
- &bytes_read, NULL, error))
- {
- g_object_unref (istream);
- g_free (string1);
- return FALSE;
- }
- else if (bytes_read != ID3_TAG_QUERYSIZE)
- {
- g_object_unref (istream);
- g_free (string1);
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, "%s",
- _("Error reading tags from file"));
- return FALSE;
- }
-
- if ((tagsize = id3_tag_query((id3_byte_t const *)string1, ID3_TAG_QUERYSIZE)) <= ID3_TAG_QUERYSIZE)
- {
- /* ID3v2 tag not found! */
- update = g_settings_get_boolean (MainSettings, "id3v2-enabled");
- }else
- {
- /* ID3v2 tag found */
- if (!g_settings_get_boolean (MainSettings, "id3v2-enabled"))
- {
- /* To delete the tag. */
- update = 1;
- }else
- {
- /* Determine version if user want to upgrade old tags */
- if (g_settings_get_boolean (MainSettings, "id3v2-convert-old")
- && (string1 = g_realloc (string1, tagsize))
- && g_input_stream_read_all (istream,
- &string1[ID3_TAG_QUERYSIZE],
- tagsize - ID3_TAG_QUERYSIZE,
- &bytes_read, NULL, error)
- && bytes_read == tagsize - ID3_TAG_QUERYSIZE
- && (tag = id3_tag_parse((id3_byte_t const *)string1, tagsize))
- )
- {
- unsigned version = id3_tag_version(tag);
-#ifdef ENABLE_ID3LIB
- /* Besides upgrade old tags we will downgrade id3v2.4 to id3v2.3 */
- if (g_settings_get_boolean (MainSettings, "id3v2-version-4"))
- {
- update = (ID3_TAG_VERSION_MAJOR(version) < 4);
- }else
- {
- update = ((ID3_TAG_VERSION_MAJOR(version) < 3)
- | (ID3_TAG_VERSION_MAJOR(version) == 4));
- }
-#else
- update = (ID3_TAG_VERSION_MAJOR(version) < 4);
-#endif
- id3_tag_delete(tag);
- }
- }
- }
-
- /* 2) ID3v1 tag. */
- seekable = G_SEEKABLE (istream);
-
- if (!g_seekable_can_seek (seekable))
- {
- g_object_unref (istream);
- g_free (string1);
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, "%s",
- _("Error reading tags from file"));
- return FALSE;
- }
-
- /* Go to the beginning of ID3v1 tag. */
- if (g_seekable_seek (seekable, -128, G_SEEK_END, NULL, error)
- && (string1)
- && g_input_stream_read_all (istream, string1, 3, &bytes_read, NULL,
- NULL /* Ignore errors. */)
- && bytes_read == 3
- && (string1[0] == 'T')
- && (string1[1] == 'A')
- && (string1[2] == 'G')
- )
- {
- /* ID3v1 tag found! */
- if (!g_settings_get_boolean (MainSettings, "id3v1-enabled"))
- {
- update = 1;
- }
- }else
- {
- /* ID3v1 tag not found! */
- if (g_settings_get_boolean (MainSettings, "id3v1-enabled"))
- {
- update = 1;
- }
- }
-
- g_free (string1);
- g_object_unref (istream);
-
- filename = g_file_get_path (gfile);
-
- if ((file = id3_file_open (filename, ID3_FILE_MODE_READONLY)) == NULL)
- {
- g_free (filename);
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
- _("Error reading tags from file"));
- return FALSE;
- }
-
- g_free (filename);
-
- if ( ((tag = id3_file_tag(file)) == NULL)
- || (tag->nframes == 0))
- {
- id3_file_close(file);
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
- _("Error reading tags from file"));
- return FALSE;
- }
-
+ gsize i, j;
+ gboolean tmpupdate, update = 0;
/****************
* Title (TIT2) *
@@ -487,79 +335,168 @@ id3tag_read_file_tag (GFile *gfile,
}
}
- // Picture description
+ /* Picture description. */
update |= libid3tag_Get_Frame_Str(frame, EASYTAG_ID3_FIELD_STRING, &pic->description);
}
- /**********************
- * Lyrics (SYLC/USLT) *
- **********************/
- /** see also id3/misc_support.h **
- if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_SYNCEDLYRICS)) )
+ return update;
+}
+
+/*
+ * Read id3v1.x / id3v2 tag and load data into the File_Tag structure.
+ * Returns TRUE on success, else FALSE.
+ * If a tag entry exists (ex: title), we allocate memory, else value stays to NULL
+ */
+gboolean
+id3tag_read_file_tag (GFile *gfile,
+ File_Tag *FileTag,
+ GError **error)
+{
+ GInputStream *istream;
+ gchar *string1;
+ gsize bytes_read;
+ GSeekable *seekable;
+ gchar *filename;
+ struct id3_file *file;
+ struct id3_tag *tag;
+ gboolean update = 0;
+ long tagsize;
+
+ g_return_val_if_fail (gfile != NULL && FileTag != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ istream = G_INPUT_STREAM (g_file_read (gfile, NULL, error));
+
+ if (!istream)
+ {
+ return FALSE;
+ }
+
+ string1 = g_malloc0 (ID3_TAG_QUERYSIZE);
+
+ /* Check if the file has an ID3v2 tag or/and an ID3v1 tags.
+ * 1) ID3v2 tag. */
+ if (!g_input_stream_read_all (istream, string1, ID3_TAG_QUERYSIZE,
+ &bytes_read, NULL, error))
+ {
+ g_object_unref (istream);
+ g_free (string1);
+ return FALSE;
+ }
+ else if (bytes_read != ID3_TAG_QUERYSIZE)
+ {
+ g_object_unref (istream);
+ g_free (string1);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, "%s",
+ _("Error reading tags from file"));
+ return FALSE;
+ }
+
+ if ((tagsize = id3_tag_query((id3_byte_t const *)string1, ID3_TAG_QUERYSIZE)) <= ID3_TAG_QUERYSIZE)
{
- gulong size = 0;
- guchar *data = NULL;
- gchar *description = NULL;
- gchar *language = NULL;
- gint timestamp_format = 0;
- gint sync_type = 0;
-
- // SyncLyrics data
- if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_DATA)) )
+ /* ID3v2 tag not found! */
+ update = g_settings_get_boolean (MainSettings, "id3v2-enabled");
+ }else
+ {
+ /* ID3v2 tag found */
+ if (!g_settings_get_boolean (MainSettings, "id3v2-enabled"))
{
- size = ID3Field_Size(id3_field);
- data = g_malloc(size);
- ID3Field_GetBINARY(id3_field, data, size);
+ /* To delete the tag. */
+ update = 1;
+ }else
+ {
+ /* Determine version if user want to upgrade old tags */
+ if (g_settings_get_boolean (MainSettings, "id3v2-convert-old")
+ && (string1 = g_realloc (string1, tagsize))
+ && g_input_stream_read_all (istream,
+ &string1[ID3_TAG_QUERYSIZE],
+ tagsize - ID3_TAG_QUERYSIZE,
+ &bytes_read, NULL, error)
+ && bytes_read == tagsize - ID3_TAG_QUERYSIZE
+ && (tag = id3_tag_parse((id3_byte_t const *)string1, tagsize))
+ )
+ {
+ unsigned version = id3_tag_version(tag);
+#ifdef ENABLE_ID3LIB
+ /* Besides upgrade old tags we will downgrade id3v2.4 to id3v2.3 */
+ if (g_settings_get_boolean (MainSettings, "id3v2-version-4"))
+ {
+ update = (ID3_TAG_VERSION_MAJOR(version) < 4);
+ }else
+ {
+ update = ((ID3_TAG_VERSION_MAJOR(version) < 3)
+ | (ID3_TAG_VERSION_MAJOR(version) == 4));
+ }
+#else
+ update = (ID3_TAG_VERSION_MAJOR(version) < 4);
+#endif
+ id3_tag_delete(tag);
+ }
}
+ }
- // SyncLyrics description
- description = Id3tag_Get_Field(id3_frame, ID3FN_DESCRIPTION);
+ /* 2) ID3v1 tag. */
+ seekable = G_SEEKABLE (istream);
- // SyncLyrics language
- language = Id3tag_Get_Field(id3_frame, ID3FN_LANGUAGE);
+ if (!g_seekable_can_seek (seekable))
+ {
+ g_object_unref (istream);
+ g_free (string1);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, "%s",
+ _("Error reading tags from file"));
+ return FALSE;
+ }
- // SyncLyrics timestamp field
- if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TIMESTAMPFORMAT)) )
+ /* Go to the beginning of ID3v1 tag. */
+ if (g_seekable_seek (seekable, -128, G_SEEK_END, NULL, error)
+ && (string1)
+ && g_input_stream_read_all (istream, string1, 3, &bytes_read, NULL,
+ NULL /* Ignore errors. */)
+ && bytes_read == 3
+ && (string1[0] == 'T')
+ && (string1[1] == 'A')
+ && (string1[2] == 'G')
+ )
+ {
+ /* ID3v1 tag found! */
+ if (!g_settings_get_boolean (MainSettings, "id3v1-enabled"))
{
- timestamp_format = ID3Field_GetINT(id3_field);
+ update = 1;
}
-
- // SyncLyrics content type
- if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_CONTENTTYPE)) )
+ }else
+ {
+ /* ID3v1 tag not found! */
+ if (g_settings_get_boolean (MainSettings, "id3v1-enabled"))
{
- sync_type = ID3Field_GetINT(id3_field);
+ update = 1;
}
+ }
- // Print data
- // j.a. Pouwelse - pouwelse :
- // http://sourceforge.net/tracker/index.php?func=detail&aid=401873&group_id=979&atid=300979
- {
- char tag[255];
- unsigned int time;
- luint pos = 0;
+ g_free (string1);
+ g_object_unref (istream);
+
+ filename = g_file_get_path (gfile);
- g_print("SyncLyrics/description : %s\n",description);
- g_print("SyncLyrics/language : %s\n",language);
- g_print("SyncLyrics/timestamp format : %s (%d)\n",timestamp_format==ID3TSF_FRAME ?
"ID3TSF_FRAME" : timestamp_format==ID3TSF_MS ? "ID3TSF_MS" : "" ,timestamp_format);
- g_print("SyncLyrics/sync type : %s (%d)\n",sync_type==ID3CT_LYRICS ? "ID3CT_LYRICS" :
"",sync_type);
+ if ((file = id3_file_open (filename, ID3_FILE_MODE_READONLY)) == NULL)
+ {
+ g_free (filename);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ _("Error reading tags from file"));
+ return FALSE;
+ }
+ g_free (filename);
- g_print("SyncLyrics size : %d\n", size);
- g_print("Lyrics/data :\n");
- while (pos < size)
- {
- strcpy(tag,data+pos);
- //g_print("txt start=%d ",pos);
- pos+=strlen(tag)+1; // shift string and terminating \0
- //g_print("txt end=%d ",pos);
- memcpy(&time,data+pos,4);
- pos+=4;
- //g_print("%d -> %s\n",time,tag);
- g_print("%s",tag);
- }
- }
+ if ( ((tag = id3_file_tag(file)) == NULL)
+ || (tag->nframes == 0))
+ {
+ id3_file_close(file);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s",
+ _("Error reading tags from file"));
+ return FALSE;
+ }
- } **/
+ update |= et_id3tag_fill_file_tag_from_id3tag (tag, FileTag);
if (update)
FileTag->saved = FALSE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]