[gexiv2/wip/phako/gio: 25/27] wip: Add GIO support to Metadata
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gexiv2/wip/phako/gio: 25/27] wip: Add GIO support to Metadata
- Date: Sat, 29 Dec 2018 17:34:43 +0000 (UTC)
commit a049215519bb538149a77e2d606b1e7edc231a95
Author: Jens Georg <mail jensge org>
Date: Tue Jun 19 13:23:51 2018 +0200
wip: Add GIO support to Metadata
Work in progress. Read-only support.
Fixes #15
gexiv2/gexiv2-metadata.cpp | 166 +++++++++++++++++++++++++++++++++++++++++++++
gexiv2/gexiv2-metadata.h | 2 +
gexiv2/meson.build | 6 +-
meson.build | 1 +
test/gexiv2-dump.vala | 4 +-
test/meson.build | 2 +-
6 files changed, 176 insertions(+), 5 deletions(-)
---
diff --git a/gexiv2/gexiv2-metadata.cpp b/gexiv2/gexiv2-metadata.cpp
index 9c791ef..683c82d 100644
--- a/gexiv2/gexiv2-metadata.cpp
+++ b/gexiv2/gexiv2-metadata.cpp
@@ -25,6 +25,157 @@
#include <exiv2/exiv2.hpp>
+namespace {
+class GioIo : public Exiv2::BasicIo {
+public:
+ GioIo (GInputStream *is)
+ : BasicIo ()
+ , _is (G_INPUT_STREAM (g_object_ref (is)))
+ , _seekable(G_IS_SEEKABLE(_is) ? G_SEEKABLE (_is) : NULL) {}
+
+ ~GioIo() { g_clear_object (&_is); _seekable = NULL;}
+#if defined(_MSC_VER)
+ typedef int64_t seek_offset_t;
+#else
+ typedef long seek_offset_t;
+#endif
+
+ int open() { return 0; }
+ int close() { return 0; }
+ long write(const Exiv2::byte *data, long wcount) { return 0; }
+ long write(BasicIo &src) { return 0; }
+ int putb(Exiv2::byte data) { return EOF; }
+
+ Exiv2::DataBuf read(long rcount) {
+ Exiv2::DataBuf b;
+ Exiv2::byte *buf = new Exiv2::byte[rcount];
+
+ long bytes_read = this->read(buf, rcount);
+ if (bytes_read > 0) {
+ b.alloc(bytes_read);
+ memcpy(b.pData_, buf, bytes_read);
+ }
+
+ delete[] buf;
+
+ return b;
+ }
+
+ long read(Exiv2::byte *buf, long rcount) {
+ GError *error = NULL;
+ gssize result = 0;
+
+ result = g_input_stream_read(_is, reinterpret_cast<void *>(buf), rcount, NULL, &error);
+ if (error != NULL) {
+ throw Exiv2::Error(2);
+ return 0;
+ }
+
+ return result;
+ }
+
+ int getb() {
+ Exiv2::byte b;
+ return this->read (&b, 1) == 1 ? b : EOF;
+ }
+
+ void transfer(Exiv2::BasicIo &src) {
+ // TODO: Implement
+ }
+
+ int seek(seek_offset_t offset, Exiv2::BasicIo::Position position) {
+ if (_seekable != NULL && g_seekable_can_seek (_seekable)) {
+ GSeekType t = G_SEEK_SET;
+ switch (position) {
+ case Exiv2::BasicIo::cur:
+ t = G_SEEK_CUR;
+ break;
+ case Exiv2::BasicIo::beg:
+ t = G_SEEK_SET;
+ break;
+ case Exiv2::BasicIo::end:
+ t = G_SEEK_END;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ GError *error = NULL;
+ g_seekable_seek (_seekable, offset, t, NULL, &error);
+ if (error != NULL) {
+ g_critical ("Failed to seek: %s", error->message);
+
+ g_error_free (error);
+
+ return -1;
+ }
+
+ return 0;
+ } else {
+ // Can only seek forward here...
+ if (position != Exiv2::BasicIo::cur) {
+ return -1;
+ }
+
+ GError *error = NULL;
+ g_input_stream_skip (_is, offset, NULL, &error);
+ if (error != NULL) {
+ g_critical("Failed to seek forward: %s", error->message);
+
+ g_error_free(error);
+
+ return -1;
+ }
+
+ return 0;
+ }
+ }
+
+ Exiv2::byte *mmap(bool writable) {
+ return NULL;
+ }
+
+ int munmap() {
+ return 0;
+ }
+
+ long tell() const {
+ return -1;
+ }
+
+ long size() const {
+ return -1;
+ }
+
+ bool isopen() const {
+ return true;
+ }
+
+ int error() const {
+ return 0;
+ }
+
+ bool eof() const {
+ return false;
+ }
+
+ std::string path() const {
+ return "GIO Wrapper";
+ }
+
+ Exiv2::BasicIo::AutoPtr temporary() const {
+ return Exiv2::BasicIo::AutoPtr(new Exiv2::FileIo("/tmp/exiv2-temp"));
+ }
+
+
+private:
+ GInputStream *_is;
+ GSeekable *_seekable;
+
+
+}; // class GioIo
+} // Anonymous namespace
G_BEGIN_DECLS
@@ -197,6 +348,21 @@ gboolean gexiv2_metadata_open_stream (GExiv2Metadata *self, ManagedStreamCallbac
return FALSE;
}
+gboolean gexiv2_metadata_from_stream(GExiv2Metadata *self, GInputStream *stream, GError **error) {
+ g_return_val_if_fail (GEXIV2_IS_METADATA (self), FALSE);
+
+ try {
+ Exiv2::BasicIo::AutoPtr gio_ptr (new GioIo (stream));
+ self->priv->image = Exiv2::ImageFactory::open (gio_ptr);
+
+ return gexiv2_metadata_open_internal (self, error);
+ } catch (Exiv2::Error &e) {
+ g_set_error_literal (error, g_quark_from_string ("GExiv2"), e.code(), e.what());
+ }
+
+ return FALSE;
+}
+
// Exiv2 does not today offer a clean way to decode a buffer with only the JFIF APP1 segment,
// where EXIF lives. This is a common situation when reading EXIF metadata straight from a
// camera (i.e. via gPhoto) where accessing the entire JPEG image is inconvenient.
diff --git a/gexiv2/gexiv2-metadata.h b/gexiv2/gexiv2-metadata.h
index 1b21c0e..035094c 100644
--- a/gexiv2/gexiv2-metadata.h
+++ b/gexiv2/gexiv2-metadata.h
@@ -252,6 +252,8 @@ gboolean gexiv2_metadata_open_buf (GExiv2Metadata
*self, const guint8 *data,
*/
gboolean gexiv2_metadata_open_stream (GExiv2Metadata *self,
ManagedStreamCallbacks* cb, GError **error);
+gboolean gexiv2_metadata_from_stream (GExiv2Metadata *self, GInputStream*
stream, GError **error);
+
/**
* gexiv2_metadata_from_app1_segment:
* @self: An instance of #GExiv2Metadata
diff --git a/gexiv2/meson.build b/gexiv2/meson.build
index 85da997..2ccae82 100644
--- a/gexiv2/meson.build
+++ b/gexiv2/meson.build
@@ -63,7 +63,7 @@ gexiv2 = library('gexiv2',
link_args : vflag,
include_directories : include_directories('..'),
version: '2.0.0',
- dependencies : [gobject, exiv2],
+ dependencies : [gobject, exiv2, gio],
install : true)
libgexiv2 = declare_dependency(
@@ -72,7 +72,7 @@ libgexiv2 = declare_dependency(
dependencies : [gobject, exiv2],
)
-pc_deps = ['glib-2.0', 'gobject-2.0']
+pc_deps = ['glib-2.0', 'gobject-2.0', 'gio-2.0']
pkg.generate(
description : 'GObject bindings for exiv2',
@@ -102,7 +102,7 @@ if introspection_available
symbol_prefix : 'gexiv2',
identifier_prefix : 'GExiv2',
export_packages : 'gexiv2',
- includes : ['GObject-2.0'],
+ includes : ['GObject-2.0', 'Gio-2.0'],
header : 'gexiv2/gexiv2.h',
install : true)
diff --git a/meson.build b/meson.build
index 0430365..f782f48 100644
--- a/meson.build
+++ b/meson.build
@@ -4,6 +4,7 @@ pkg = import('pkgconfig')
exiv2 = dependency('exiv2', version : '>= 0.26')
gobject = dependency('gobject-2.0', version : '>= 2.38.0')
+gio = dependency('gio-2.0', version : '>= 2.32.0')
gir = find_program('g-ir-scanner', required: false)
vapigen = find_program('vapigen', required: false)
diff --git a/test/gexiv2-dump.vala b/test/gexiv2-dump.vala
index 7bf6ef3..0dc7724 100644
--- a/test/gexiv2-dump.vala
+++ b/test/gexiv2-dump.vala
@@ -18,7 +18,9 @@ int main(string[] args) {
foreach (string filename in args[1:args.length]) {
try {
GExiv2.Metadata metadata = new GExiv2.Metadata();
- metadata.open_path(filename);
+// metadata.open_path(filename);
+ var file = File.new_for_path (filename);
+ metadata.from_stream (file.read ());
dump_tags(metadata, metadata.get_exif_tags());
dump_tags(metadata, metadata.get_iptc_tags());
diff --git a/test/meson.build b/test/meson.build
index 50593b8..f3cc10a 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -23,7 +23,7 @@ if vapi_available
executable('gexiv2-dump',
'gexiv2-dump.vala',
include_directories : include_directories('..'),
- dependencies : [gobject, vapi],
+ dependencies : [gobject, vapi, gio],
link_with : gexiv2)
endif
endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]