[easytag/wip/help: 10/18] Add GIO/TagLib compatibility layer
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [easytag/wip/help: 10/18] Add GIO/TagLib compatibility layer
- Date: Fri, 11 Apr 2014 13:08:34 +0000 (UTC)
commit 44ee383fb2d981c165c72e3d962df0a6dd131add
Author: Santtu Lakkala <inz inz fi>
Date: Thu Apr 10 11:01:52 2014 +0300
Add GIO/TagLib compatibility layer
Create GIO based implementations of TagLib::IOStream, so TagLib can be used
over GIO. The implementation still lacks almost all error handling, but works
in normal situations.
Makefile.am | 2 +
src/gio_wrapper.cc | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gio_wrapper.h | 76 ++++++++++++
3 files changed, 417 insertions(+), 0 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index f090579..1f58f47 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,6 +52,7 @@ easytag_SOURCES = \
src/et_core.c \
src/flac_header.c \
src/flac_tag.c \
+ src/gio_wrapper.cc \
src/gtk2_compat.c \
src/id3_tag.c \
src/id3v24_tag.c \
@@ -94,6 +95,7 @@ easytag_headers = \
src/flac_header.h \
src/flac_tag.h \
src/genres.h \
+ src/gio_wrapper.h \
src/gtk2_compat.h \
src/id3_tag.h \
src/log.h \
diff --git a/src/gio_wrapper.cc b/src/gio_wrapper.cc
new file mode 100644
index 0000000..e9cd0cd
--- /dev/null
+++ b/src/gio_wrapper.cc
@@ -0,0 +1,339 @@
+/*
+ * EasyTAG - Tag editor for audio files
+ * Copyright (C) 2014 Santtu Lakkala <inz inz fi>
+ *
+ * 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 "gio_wrapper.h"
+
+GIO_InputStream::GIO_InputStream (GFile * file_) :
+ file ((GFile *)g_object_ref (gpointer (file_))),
+ filename (g_file_get_uri (file))
+{
+ stream = g_file_read (file, NULL, NULL);
+}
+
+GIO_InputStream::~GIO_InputStream ()
+{
+ g_input_stream_close (G_INPUT_STREAM (stream), NULL, NULL);
+ g_free (filename);
+ g_object_unref (G_OBJECT (file));
+}
+
+TagLib::FileName
+GIO_InputStream::name () const
+{
+ return TagLib::FileName (filename);
+}
+
+TagLib::ByteVector
+GIO_InputStream::readBlock (ulong length)
+{
+ TagLib::ByteVector rv (length, 0);
+ rv = rv.mid (0, g_input_stream_read (G_INPUT_STREAM (stream),
+ (void *)rv.data (), length, NULL,
+ NULL));
+
+ return rv;
+}
+
+void
+GIO_InputStream::writeBlock (TagLib::ByteVector const &data)
+{
+ g_warning ("%s", "Trying to write to read-only file!");
+}
+
+void
+GIO_InputStream::insert (TagLib::ByteVector const &data, ulong start, ulong replace)
+{
+ g_warning ("%s", "Trying to write to read-only file!");
+}
+
+void
+GIO_InputStream::removeBlock (ulong start, ulong length)
+{
+ g_warning ("%s", "Trying to write to read-only file!");
+}
+
+bool
+GIO_InputStream::readOnly () const
+{
+ return true;
+}
+
+bool
+GIO_InputStream::isOpen () const
+{
+ return !!stream;
+}
+
+void
+GIO_InputStream::seek (long int offset, TagLib::IOStream::Position p)
+{
+ GSeekType type;
+
+ switch (p)
+ {
+ case TagLib::IOStream::Beginning:
+ type = G_SEEK_SET;
+ break;
+ case TagLib::IOStream::Current:
+ type = G_SEEK_CUR;
+ break;
+ case TagLib::IOStream::End:
+ type = G_SEEK_END;
+ break;
+ default:
+ g_warning ("Unknown seek");
+ return;
+ }
+
+ g_seekable_seek (G_SEEKABLE (stream), offset, type, NULL, NULL);
+}
+
+void
+GIO_InputStream::clear ()
+{
+}
+
+long int
+GIO_InputStream::tell () const
+{
+ return g_seekable_tell (G_SEEKABLE (stream));
+}
+
+long int
+GIO_InputStream::length ()
+{
+ long rv;
+ GFileInfo *info = g_file_input_stream_query_info (stream,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ NULL, NULL);
+ rv = g_file_info_get_size (info);
+ g_object_unref (info);
+
+ return rv;
+}
+
+void
+GIO_InputStream::truncate (long int length)
+{
+ g_warning ("%s", "Trying to truncate read-only file");
+}
+
+GIO_IOStream::GIO_IOStream (GFile *file_) :
+ file ((GFile *)g_object_ref (gpointer (file_))),
+ filename (g_file_get_uri (file_))
+{
+ stream = g_file_open_readwrite (file, NULL, NULL);
+}
+
+GIO_IOStream::~GIO_IOStream ()
+{
+ g_io_stream_close (G_IO_STREAM (stream), NULL, NULL);
+ g_free (filename);
+ g_object_unref (G_OBJECT (file));
+}
+
+TagLib::FileName
+GIO_IOStream::name () const
+{
+ return TagLib::FileName (filename);
+}
+
+TagLib::ByteVector
+GIO_IOStream::readBlock (ulong length)
+{
+ TagLib::ByteVector rv (length, 0);
+ GInputStream *istream = g_io_stream_get_input_stream (G_IO_STREAM (stream));
+ rv = rv.mid (0, g_input_stream_read (istream, (void *)rv.data (), length,
+ NULL, NULL));
+
+ return rv;
+}
+
+void
+GIO_IOStream::writeBlock (TagLib::ByteVector const &data)
+{
+ GOutputStream *ostream = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+ g_output_stream_write (ostream, data.data (), data.size (), NULL, NULL);
+}
+
+void
+GIO_IOStream::insert (TagLib::ByteVector const &data,
+ ulong start,
+ ulong replace)
+{
+ if (data.size () == replace)
+ {
+ seek (start, TagLib::IOStream::Beginning);
+ writeBlock (data);
+ return;
+ }
+ else if (data.size () < replace)
+ {
+ removeBlock (start, replace - data.size ());
+ seek (start);
+ writeBlock (data);
+ return;
+ }
+
+ GFileIOStream *tstr;
+ GFile *tmp = g_file_new_tmp ("easytag-XXXXXX", &tstr, NULL);
+ char *buffer[4096];
+ gsize r;
+ GOutputStream *ostream = g_io_stream_get_output_stream (G_IO_STREAM (tstr));
+ GInputStream *istream = g_io_stream_get_input_stream (G_IO_STREAM (stream));
+
+ seek (0);
+
+ while (g_input_stream_read_all (istream, buffer,
+ MIN (sizeof (buffer), start), &r, NULL,
+ NULL) && r > 0)
+ {
+ gsize w;
+ g_output_stream_write_all (ostream, buffer, r, &w, NULL, NULL);
+
+ if (w != r)
+ {
+ g_warning ("%s", "Unable to write all bytes");
+ }
+
+ start -= r;
+ g_warning ("Wrote %lu bytes of %lu: %.*s", r, start, (int)r, buffer);
+ }
+
+ g_output_stream_write (ostream, data.data (), data.size (), NULL, NULL);
+ seek (replace, TagLib::IOStream::Current);
+
+ while (g_input_stream_read_all (istream, buffer, sizeof (buffer), &r,
+ NULL, NULL) && r > 0)
+ {
+ gsize w;
+ g_output_stream_write_all (ostream, buffer, r, &w, NULL, NULL);
+
+ if (w != r)
+ {
+ g_warning ("%s", "Unable to write all bytes");
+ }
+ }
+
+ g_io_stream_close (G_IO_STREAM (tstr), NULL, NULL);
+ g_io_stream_close (G_IO_STREAM (stream), NULL, NULL);
+ g_file_move (tmp, file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL);
+ g_object_unref (gpointer(tmp));
+ stream = g_file_open_readwrite (file, NULL, NULL);
+}
+
+void
+GIO_IOStream::removeBlock (ulong start, ulong len)
+{
+ if (start + len >= (ulong)length ())
+ {
+ truncate (start);
+ return;
+ }
+
+ char *buffer[4096];
+ gsize r;
+ GInputStream *istream = g_io_stream_get_input_stream (G_IO_STREAM (stream));
+ GOutputStream *ostream = g_io_stream_get_output_stream (G_IO_STREAM (stream));
+ seek (start + len);
+
+ while (g_input_stream_read_all (istream, buffer, sizeof (buffer), &r, NULL,
+ NULL) && r > 0)
+ {
+ gsize w;
+ seek (start);
+ g_output_stream_write_all (ostream, buffer, r, &w, NULL, NULL);
+
+ if (w != r)
+ {
+ g_warning ("%s", "Unable to write all bytes");
+ }
+
+ start += r;
+ seek (start + len);
+ }
+
+ truncate (start);
+}
+
+bool
+GIO_IOStream::readOnly () const
+{
+ return !stream;
+}
+
+bool
+GIO_IOStream::isOpen () const
+{
+ return !!stream;
+}
+
+void
+GIO_IOStream::seek (long int offset, TagLib::IOStream::Position p)
+{
+ GSeekType type;
+
+ switch (p)
+ {
+ case TagLib::IOStream::Beginning:
+ type = G_SEEK_SET;
+ break;
+ case TagLib::IOStream::Current:
+ type = G_SEEK_CUR;
+ break;
+ case TagLib::IOStream::End:
+ type = G_SEEK_END;
+ break;
+ default:
+ g_warning ("%s", "Unknown seek");
+ return;
+ }
+
+ g_seekable_seek (G_SEEKABLE (stream), offset, type, NULL, NULL);
+}
+
+void
+GIO_IOStream::clear ()
+{
+}
+
+long int
+GIO_IOStream::tell () const
+{
+ return g_seekable_tell (G_SEEKABLE (stream));
+}
+
+long int
+GIO_IOStream::length ()
+{
+ long rv;
+ GFileInfo *info = g_file_io_stream_query_info (stream,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ NULL, NULL);
+ rv = g_file_info_get_size (info);
+ g_object_unref (info);
+
+ return rv;
+}
+
+void
+GIO_IOStream::truncate (long int length)
+{
+ g_seekable_truncate (G_SEEKABLE (stream), length, NULL, NULL);
+}
diff --git a/src/gio_wrapper.h b/src/gio_wrapper.h
new file mode 100644
index 0000000..d6f1b76
--- /dev/null
+++ b/src/gio_wrapper.h
@@ -0,0 +1,76 @@
+/*
+ * EasyTAG - Tag editor for audio files
+ * Copyright (C) 2014 Santtu Lakkala <inz inz fi>
+ *
+ * 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_GIO_WRAPPER_H_
+#define ET_GIO_WRAPPER_H_
+
+#include <tiostream.h>
+#include <gio/gio.h>
+
+class GIO_InputStream : public TagLib::IOStream
+{
+public:
+ GIO_InputStream (GFile *file_);
+ virtual ~GIO_InputStream ();
+ virtual TagLib::FileName name () const;
+ virtual TagLib::ByteVector readBlock (ulong length);
+ virtual void writeBlock (TagLib::ByteVector const &data);
+ virtual void insert (TagLib::ByteVector const &data, ulong start = 0, ulong replace = 0);
+ virtual void removeBlock (ulong start = 0, ulong length = 0);
+ virtual bool readOnly () const;
+ virtual bool isOpen () const;
+ virtual void seek (long int offset, TagLib::IOStream::Position p = TagLib::IOStream::Beginning);
+ virtual void clear ();
+ virtual long int tell () const;
+ virtual long int length ();
+ virtual void truncate (long int length);
+
+private:
+ GIO_InputStream (const GIO_InputStream &other);
+ GFile *file;
+ GFileInputStream *stream;
+ char *filename;
+};
+
+class GIO_IOStream : public TagLib::IOStream
+{
+public:
+ GIO_IOStream (GFile *file_);
+ virtual ~GIO_IOStream ();
+ virtual TagLib::FileName name () const;
+ virtual TagLib::ByteVector readBlock (ulong length);
+ virtual void writeBlock (TagLib::ByteVector const &data);
+ virtual void insert (TagLib::ByteVector const &data, ulong start = 0, ulong replace = 0);
+ virtual void removeBlock (ulong start = 0, ulong len = 0);
+ virtual bool readOnly () const;
+ virtual bool isOpen () const;
+ virtual void seek (long int offset, TagLib::IOStream::Position p = TagLib::IOStream::Beginning);
+ virtual void clear ();
+ virtual long int tell () const;
+ virtual long int length ();
+ virtual void truncate (long int length);
+
+private:
+ GIO_IOStream (const GIO_IOStream &other);
+ GFile *file;
+ GFileIOStream *stream;
+ char *filename;
+};
+
+#endif /* ET_GIO_WRAPPER_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]