[easytag] Use GIO when reading and writing ID3v2.4 files
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [easytag] Use GIO when reading and writing ID3v2.4 files
- Date: Sat, 20 Dec 2014 18:49:50 +0000 (UTC)
commit 1342885c94e73a865b7775fae419f11171c85700
Author: David King <amigadave amigadave com>
Date: Sat Dec 20 18:11:37 2014 +0000
Use GIO when reading and writing ID3v2.4 files
src/tags/id3v24_tag.c | 333 +++++++++++++++++++++++++++++--------------------
1 files changed, 198 insertions(+), 135 deletions(-)
---
diff --git a/src/tags/id3v24_tag.c b/src/tags/id3v24_tag.c
index 279ff6b..a855f13 100644
--- a/src/tags/id3v24_tag.c
+++ b/src/tags/id3v24_tag.c
@@ -21,8 +21,6 @@
#include "config.h"
#include <glib/gi18n.h>
-#include <fcntl.h>
-#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
@@ -50,6 +48,7 @@
****************/
#define MULTIFIELD_SEPARATOR " - "
#define EASYTAG_STRING_ENCODEDBY "Encoded by"
+#define ID3V1_TAG_SIZE 128
enum {
EASYTAG_ID3_FIELD_LATIN1 = 0x0001,
@@ -190,7 +189,7 @@ id3tag_read_file_tag (GFile *gfile,
}
/* Go to the beginning of ID3v1 tag. */
- if (g_seekable_seek (seekable, -128, G_SEEK_END, NULL, error)
+ if (g_seekable_seek (seekable, -ID3V1_TAG_SIZE, G_SEEK_END, NULL, error)
&& (string1)
&& g_input_stream_read_all (istream, string1, 3, &bytes_read, NULL,
NULL /* Ignore errors. */)
@@ -1514,29 +1513,36 @@ etag_write_tags (const gchar *filename,
{
id3_byte_t *v1buf, *v2buf;
id3_length_t v1size = 0, v2size = 0;
- char tmp[ID3_TAG_QUERYSIZE];
- int fd;
- int curpos;
+ gchar tmp[ID3_TAG_QUERYSIZE];
+ GFile *file;
+ GFileIOStream *iostream;
+ GSeekable *seekable;
+ GInputStream *istream;
+ GOutputStream *ostream;
long filev2size;
gsize ctxsize;
- char *ctx = NULL;
+ gchar *ctx = NULL;
gboolean success = TRUE;
- gssize size_read = 0;
+ gsize bytes_read;
+ gsize bytes_written;
v1buf = v2buf = NULL;
- if ( !strip_tags )
+
+ if (!strip_tags)
{
/* Render v1 tag */
if (v1tag)
{
- v1size = id3_tag_render(v1tag, NULL);
- if (v1size == 128)
+ v1size = id3_tag_render (v1tag, NULL);
+
+ if (v1size == ID3V1_TAG_SIZE)
{
- v1buf = g_try_malloc(v1size);
- if (id3_tag_render(v1tag, v1buf) != v1size)
+ v1buf = g_malloc (v1size);
+
+ if (id3_tag_render (v1tag, v1buf) != v1size)
{
/* NOTREACHED */
- g_free(v1buf);
+ g_free (v1buf);
v1buf = NULL;
}
}
@@ -1545,14 +1551,16 @@ etag_write_tags (const gchar *filename,
/* Render v2 tag */
if (v2tag)
{
- v2size = id3_tag_render(v2tag, NULL);
+ v2size = id3_tag_render (v2tag, NULL);
+
if (v2size > 10)
{
- v2buf = g_try_malloc0(v2size);
- if ((v2size = id3_tag_render(v2tag, v2buf)) == 0)
+ v2buf = g_malloc0 (v2size);
+
+ if ((v2size = id3_tag_render (v2tag, v2buf)) == 0)
{
/* NOTREACHED */
- g_free(v2buf);
+ g_free (v2buf);
v2buf = NULL;
}
}
@@ -1560,184 +1568,239 @@ etag_write_tags (const gchar *filename,
}
if (v1buf == NULL)
+ {
v1size = 0;
+ }
if (v2buf == NULL)
+ {
v2size = 0;
+ }
+
+ file = g_file_new_for_path (filename);
+ iostream = g_file_open_readwrite (file, NULL, error);
- if ((fd = open (filename, O_RDWR)) < 0)
+ if (!iostream)
{
- g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
- "%s", g_strerror (errno));
- g_free (v1buf);
- g_free (v2buf);
- return FALSE;
+ goto err;
+ }
+
+ /* Seeking on the IOStream seeks to the same position on both the input and
+ * output streams. */
+ seekable = G_SEEKABLE (iostream);
+
+ if (!g_seekable_can_seek (seekable))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_BADF, "%s",
+ g_strerror (EBADF));
+ goto err;
}
success = FALSE;
- /* Handle Id3v1 tag */
- if ((curpos = lseek (fd, -128, SEEK_END)) < 0)
- goto out;
- if ((size_read = read (fd, tmp, ID3_TAG_QUERYSIZE)) != ID3_TAG_QUERYSIZE)
+ /* Handle ID3v1 tag */
+ if (!g_seekable_seek (seekable, -ID3V1_TAG_SIZE, G_SEEK_END, NULL, error))
{
- goto out;
+ goto err;
}
- if ( (tmp[0] == 'T')
- && (tmp[1] == 'A')
- && (tmp[2] == 'G')
- )
+ istream = g_io_stream_get_input_stream (G_IO_STREAM (iostream));
+
+ if (!g_input_stream_read_all (istream, tmp, ID3_TAG_QUERYSIZE, &bytes_read,
+ NULL, error))
{
- if ((curpos = lseek(fd, -128, SEEK_END)) < 0)
+ goto err;
+ }
+
+ /* Seek to the beginning of the ID3v1 tag, if it exists. */
+ if ((tmp[0] == 'T') && (tmp[1] == 'A') && (tmp[2] == 'G'))
+ {
+ if (!g_seekable_seek (seekable, -ID3V1_TAG_SIZE, G_SEEK_END, NULL,
+ error))
{
- goto out;
+ goto err;
}
- }else
+ }
+ else
{
- if ((curpos = lseek(fd, 0, SEEK_END)) < 0)
+ if (!g_seekable_seek (seekable, 0, G_SEEK_END, NULL, error))
{
- goto out;
+ goto err;
}
}
- /* Search id3v2 tags at the end of the file (before any ID3v1 tag) */
+ /* Search ID3v2 tags at the end of the file (before any ID3v1 tag) */
/* XXX: Unsafe */
- if ((curpos = lseek (fd, -ID3_TAG_QUERYSIZE, SEEK_CUR)) >= 0)
+ if (g_seekable_seek (seekable, -ID3_TAG_QUERYSIZE, G_SEEK_CUR, NULL,
+ error))
{
- if (read (fd, tmp, ID3_TAG_QUERYSIZE) != ID3_TAG_QUERYSIZE)
- goto out;
- filev2size = id3_tag_query((id3_byte_t const *)tmp, ID3_TAG_QUERYSIZE);
- if ((filev2size > 10) && (curpos = lseek (fd, -filev2size, SEEK_CUR)))
+ if (!g_input_stream_read_all (istream, tmp, ID3_TAG_QUERYSIZE,
+ &bytes_read, NULL, error))
+ {
+ goto err;
+ }
+
+ filev2size = id3_tag_query ((id3_byte_t const *)tmp,
+ ID3_TAG_QUERYSIZE);
+
+ if (filev2size > 10)
{
- if ((size_read = read (fd, tmp, ID3_TAG_QUERYSIZE)) != ID3_TAG_QUERYSIZE)
+ if (!g_seekable_seek (seekable, -filev2size, G_SEEK_CUR, NULL,
+ error))
+ {
+ goto err;
+ }
+
+ if (!g_input_stream_read_all (istream, tmp, ID3_TAG_QUERYSIZE,
+ &bytes_read, NULL, error))
+ {
+ goto err;
+ }
+
+ if (id3_tag_query ((id3_byte_t const *)tmp, ID3_TAG_QUERYSIZE)
+ != filev2size)
{
- goto out;
+ if (!g_seekable_seek (seekable,
+ -ID3_TAG_QUERYSIZE - filev2size,
+ G_SEEK_CUR, NULL, error))
+ {
+ goto err;
+ }
}
- if (id3_tag_query((id3_byte_t const *)tmp, ID3_TAG_QUERYSIZE) != filev2size)
- curpos = lseek (fd, -ID3_TAG_QUERYSIZE - filev2size, SEEK_CUR);
else
- curpos = lseek (fd, -ID3_TAG_QUERYSIZE, SEEK_CUR);
+ {
+ if (!g_seekable_seek (seekable, -ID3_TAG_QUERYSIZE,
+ G_SEEK_CUR, NULL, error))
+ {
+ goto err;
+ }
+ }
}
}
+ ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
+
/* Write id3v1 tag */
if (v1buf)
{
- if (write (fd, v1buf, v1size) != v1size)
- goto out;
+ if (!g_output_stream_write_all (ostream, v1buf, v1size, &bytes_written,
+ NULL, error))
+ {
+ goto err;
+ }
}
/* Truncate file (strip tags at the end of file) */
- if ((curpos = lseek (fd, 0, SEEK_CUR)) <= 0)
- goto out;
- if (ftruncate (fd, curpos) == -1)
- goto out;
+ if (!g_seekable_can_truncate (seekable))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_BADF, "%s",
+ g_strerror (EBADF));
+ goto err;
+ }
+
+ if (!g_seekable_truncate (seekable, g_seekable_tell (seekable), NULL,
+ error))
+ {
+ goto err;
+ }
/* Handle Id3v2 tag */
- if ((curpos = lseek(fd, 0, SEEK_SET)) < 0)
- goto out;
+ if (!g_seekable_seek (seekable, 0, G_SEEK_SET, NULL, error))
+ {
+ goto err;
+ }
- if ( (size_read = read(fd, tmp, ID3_TAG_QUERYSIZE)) != ID3_TAG_QUERYSIZE)
+ if (!g_input_stream_read_all (istream, tmp, ID3_TAG_QUERYSIZE, &bytes_read,
+ NULL, error))
{
- goto out;
+ goto err;
}
- filev2size = id3_tag_query((id3_byte_t const *)tmp, ID3_TAG_QUERYSIZE);
+ filev2size = id3_tag_query ((id3_byte_t const *)tmp, ID3_TAG_QUERYSIZE);
- // No ID3v2 tag in the file, and no new tag
- if ( (filev2size == 0)
- && (v2size == 0) )
- goto out;
+ /* No ID3v2 tag in the file, and no new tag. */
+ if ((filev2size == 0) && (v2size == 0))
+ {
+ /* TODO: Improve error description. */
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_BADF, "%s",
+ g_strerror (EBADF));
+ goto err;
+ }
if (filev2size == v2size)
{
- if ((curpos = lseek(fd, 0, SEEK_SET)) < 0)
- goto out;
- if (write(fd, v2buf, v2size) != v2size)
- goto out;
- }else
+ if (!g_seekable_seek (seekable, 0, G_SEEK_SET, NULL, error))
+ {
+ goto err;
+ }
+
+ if (!g_output_stream_write_all (ostream, v2buf, v2size, &bytes_written,
+ NULL, error))
+ {
+ goto err;
+ }
+ }
+ else
{
/* XXX */
- // Size of audio data (tags at the end were already removed)
- ctxsize = lseek (fd, 0, SEEK_END) - filev2size;
-
- if ((ctx = g_try_malloc(ctxsize)) == NULL)
- goto out;
- if ((curpos = lseek (fd, filev2size, SEEK_SET)) < 0)
- goto out;
- if ((size_read = read (fd, ctx, ctxsize)) != ctxsize)
+ /* Size of audio data (tags at the end were already removed) */
+ if (!g_seekable_seek (seekable, 0, G_SEEK_END, NULL, error))
{
- gchar *filename_utf8 = filename_to_display(filename);
- gchar *basename_utf8 = g_path_get_basename(filename_utf8);
- gchar *bytes_missing = g_strdup_printf ("%" G_GSIZE_FORMAT,
- ctxsize - size_read);
-
- /* Construct the string in this awkward way as xgettext does not
- * support macros in extracted strings.
- * https://bugzilla.gnome.org/show_bug.cgi?id=705952
- */
- g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
- /* Translators: The first string is a filename, the
- * second string is the number of bytes that were
- * missing (not read for some reason) while reading
- * from the file.
- */
- ngettext ("Cannot write tag of file ‘%s’ (a byte was missing)",
- "Cannot write tag of file ‘%s’ (%s bytes were missing)",
- ctxsize - size_read),
- basename_utf8, bytes_missing);
- g_free (filename_utf8);
- g_free (basename_utf8);
- g_free (bytes_missing);
- goto out;
+ goto err;
+ }
+
+ ctxsize = g_seekable_tell (seekable) - filev2size;
+
+ ctx = g_malloc (ctxsize);
+
+ if (!g_seekable_seek (seekable, filev2size, G_SEEK_SET, NULL, error))
+ {
+ goto err;
+ }
+
+ if (!g_input_stream_read_all (istream, ctx, ctxsize, &bytes_read, NULL,
+ error))
+ {
+ goto err;
}
- // Return to the beginning of the file
- if (lseek (fd, 0, SEEK_SET) < 0)
- goto out;
-
- // Write the ID3v2 tag
+ /* Return to the beginning of the file. */
+ if (!g_seekable_seek (seekable, 0, G_SEEK_SET, NULL, error))
+ {
+ goto err;
+ }
+
+ /* Write the ID3v2 tag. */
if (v2buf)
{
- if (write (fd, v2buf, v2size) != v2size)
+ if (!g_output_stream_write_all (ostream, v2buf, v2size,
+ &bytes_written, NULL, error))
{
- gchar *filename_utf8 = filename_to_display (filename);
- gchar *basename_utf8 = g_path_get_basename (filename_utf8);
- g_set_error (error, G_FILE_ERROR,
- g_file_error_from_errno (errno),
- _("Cannot save tag of file ‘%s’"), basename_utf8);
- g_free (basename_utf8);
- goto out;
+ goto err;
}
}
- // Write audio data
- if (write(fd, ctx, ctxsize) != ctxsize)
+
+ /* Write audio data. */
+ if (!g_output_stream_write_all (ostream, ctx, ctxsize, &bytes_written,
+ NULL, error))
{
- gchar *filename_utf8 = filename_to_display(filename);
- gchar *basename_utf8 = g_path_get_basename(filename_utf8);
- g_set_error (error, G_FILE_ERROR,
- g_file_error_from_errno (errno),
- _("Size error while saving tag of ‘%s’"),
- basename_utf8);
- g_free (filename_utf8);
- g_free (basename_utf8);
- goto out;
+ goto err;
}
- if ((curpos = lseek (fd, 0, SEEK_CUR)) <= 0)
- goto out;
-
- if (ftruncate (fd, curpos) < 0)
- goto out;
+ if (!g_seekable_truncate (seekable, g_seekable_tell (seekable), NULL,
+ error))
+ {
+ goto err;
+ }
}
success = TRUE;
-out:
- g_free(ctx);
- lseek(fd, 0, SEEK_SET);
- close(fd);
- g_free(v1buf);
- g_free(v2buf);
+
+err:
+ g_free (ctx);
+ g_object_unref (file);
+ g_clear_object (&iostream);
+ g_free (v1buf);
+ g_free (v2buf);
return success;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]