/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * gsf-input-bonobo.c: bonobo based input * * Copyright (C) 2002-2003 Jon K Hellan (hellan@acm.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2.1 of the GNU Lesser General Public * License as published by the Free Software Foundation. * * 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 Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ #include #include #include #include #include #include #include #include /* FIXME: Should make CORBA environment available to caller somehow. */ struct _GsfInputBonobo { GsfInput input; GsfSharedBonoboStream *shared; guint8 *buf; size_t buf_size; gsf_off_t pos; }; typedef struct { GsfInputClass input_class; } GsfInputBonoboClass; static int gib_synch_shared_ptr (GsfInputBonobo *binput) { CORBA_Environment ev; CORBA_long new_pos; if (binput->shared == NULL) return 0; if (binput->pos == (gsf_off_t) binput->shared->pos) return 0; CORBA_exception_init (&ev); new_pos = (CORBA_long) binput->pos; Bonobo_Stream_seek (binput->shared->stream, new_pos, Bonobo_Stream_SeekSet, &ev); if (BONOBO_EX (&ev)) { g_warning (bonobo_exception_get_text (&ev)); CORBA_exception_free (&ev); return -1; } else { binput->shared->pos = new_pos; return 0; } } /** * gsf_input_bonobo_new : * @stream : Bonobo stream * @err : optionally %NULL. * * Returns: a new input object or %NULL. **/ GsfInput * gsf_input_bonobo_new (Bonobo_Stream const stream, GError **err) { GsfInputBonobo *input; Bonobo_StorageInfo *info; CORBA_Environment ev; CORBA_long size; if (stream == NULL) { if (err != NULL) *err = g_error_new (gsf_input_error_id (), 0, "stream is NULL"); return NULL; } CORBA_exception_init (&ev); /* info->size doesn't work */ size = Bonobo_Stream_seek (stream, 0, Bonobo_Stream_SeekEnd, &ev); if (BONOBO_EX (&ev)) { if (err != NULL) *err = g_error_new (gsf_input_error_id (), 0, "%s: %s", "Error seeking to get stream size", bonobo_exception_get_text (&ev)); CORBA_exception_free (&ev); return NULL; } Bonobo_Stream_seek (stream, 0, Bonobo_Stream_SeekSet, &ev); if (BONOBO_EX (&ev)) { if (err != NULL) *err = g_error_new (gsf_input_error_id (), 0, "%s: %s", "Error seeking to get stream size", bonobo_exception_get_text (&ev)); CORBA_exception_free (&ev); return NULL; } /* */ info = Bonobo_Stream_getInfo (stream, 0, &ev); if (BONOBO_EX (&ev)) { if (err != NULL) *err = g_error_new (gsf_input_error_id (), 0, "%s: %s", "Error getting stream info", bonobo_exception_get_text (&ev)); CORBA_exception_free (&ev); return NULL; } input = g_object_new (GSF_INPUT_BONOBO_TYPE, NULL); if (G_UNLIKELY (NULL == input)) { CORBA_free (info); return NULL; } input->shared = gsf_shared_bonobo_stream_new (stream); input->buf = NULL; input->buf_size = 0; gsf_input_set_size (GSF_INPUT (input), (gsf_off_t) size); gsf_input_set_name (GSF_INPUT (input), info->name); CORBA_free (info); return GSF_INPUT (input); } static void gsf_input_bonobo_finalize (GObject *obj) { GObjectClass *parent_class; GsfInputBonobo *input = (GsfInputBonobo *)obj; if (input->shared) g_object_unref (G_OBJECT (input->shared)); input->shared = NULL; g_free (input->buf); input->buf = NULL; input->buf_size = 0; parent_class = g_type_class_peek (GSF_INPUT_TYPE); if (parent_class && parent_class->finalize) parent_class->finalize (obj); } static GsfInput * gsf_input_bonobo_dup (GsfInput *src_input, GError **err) { GsfInputBonobo const *src = (GsfInputBonobo *)src_input; GsfInputBonobo *dst = g_object_new (GSF_INPUT_BONOBO_TYPE, NULL); if (G_UNLIKELY (NULL == dst)) return NULL; (void) err; dst->shared = src->shared; g_object_ref (G_OBJECT (dst->shared)); return GSF_INPUT (dst); } static guint8 const * gsf_input_bonobo_read (GsfInput *input, size_t num_bytes, guint8 *buffer) { GsfInputBonobo *binput = GSF_INPUT_BONOBO (input); CORBA_unsigned_long num_read; Bonobo_Stream_iobuf *bsibuf; CORBA_Environment ev; g_return_val_if_fail (binput != NULL, NULL); g_return_val_if_fail (binput->shared != NULL, NULL); g_return_val_if_fail (binput->shared->stream != NULL, NULL); if (buffer == NULL) { if (binput->buf_size < num_bytes) { binput->buf_size = num_bytes; g_free (binput->buf); binput->buf = g_new (guint8, binput->buf_size); } buffer = binput->buf; } if (gib_synch_shared_ptr (binput) != 0) return NULL; CORBA_exception_init (&ev); Bonobo_Stream_read (binput->shared->stream, (CORBA_long) num_bytes, &bsibuf, &ev); if (BONOBO_EX (&ev)) { g_warning (bonobo_exception_get_text (&ev)); return NULL; } else { memcpy (buffer, bsibuf->_buffer, bsibuf->_length); num_read = bsibuf->_length; CORBA_free (bsibuf); } if ((size_t) num_read == num_bytes) { return buffer; } else { g_warning ("Only read %ld bytes, asked for %ld", (long)num_read, (long)num_bytes); return NULL; } } static gboolean gsf_input_bonobo_seek (GsfInput *input, gsf_off_t offset, GSeekType whence) { GsfInputBonobo *binput = GSF_INPUT_BONOBO (input); Bonobo_Stream_SeekType bwhence; CORBA_long pos, coffset; CORBA_Environment ev; g_return_val_if_fail (binput != NULL, TRUE); g_return_val_if_fail (binput->shared != NULL, TRUE); g_return_val_if_fail (binput->shared->stream != NULL, TRUE); if (whence == G_SEEK_CUR) { if (gib_synch_shared_ptr (binput) != 0) return TRUE; } switch (whence) { case G_SEEK_SET : bwhence = Bonobo_Stream_SeekSet; break; case G_SEEK_CUR : bwhence = Bonobo_Stream_SeekCur; break; case G_SEEK_END : bwhence = Bonobo_Stream_SeekEnd; break; default: return TRUE; } coffset = offset; if ((gsf_off_t) coffset != offset) { /* Check for overflow */ g_warning ("offset too large for Bonobo_Stream_seek"); return TRUE; } CORBA_exception_init (&ev); pos = Bonobo_Stream_seek (binput->shared->stream, coffset, bwhence, &ev); if (BONOBO_EX (&ev)) { g_warning (bonobo_exception_get_text (&ev)); return TRUE; } else { binput->shared->pos = pos; binput->pos = (gsf_off_t) pos; return FALSE; } } static void gsf_input_bonobo_init (GObject *obj) { GsfInputBonobo *binput = GSF_INPUT_BONOBO (obj); binput->shared = NULL; binput->buf = NULL; binput->buf_size = 0; } static void gsf_input_bonobo_class_init (GObjectClass *gobject_class) { GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class); gobject_class->finalize = gsf_input_bonobo_finalize; input_class->Dup = gsf_input_bonobo_dup; input_class->Read = gsf_input_bonobo_read; input_class->Seek = gsf_input_bonobo_seek; } GSF_CLASS (GsfInputBonobo, gsf_input_bonobo, gsf_input_bonobo_class_init, gsf_input_bonobo_init, GSF_INPUT_TYPE)