"Initial commit to Gerrit"
[profile/ivi/libgsf.git] / gsf-gnome / gsf-input-bonobo.c
1  /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * gsf-input-bonobo.c: bonobo based input
4  *
5  * Copyright (C) 2002-2003 Jon K Hellan (hellan@acm.org)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of version 2.1 of the GNU Lesser General Public
9  * License as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
19  * USA
20  */
21
22 #include <gsf-config.h>
23 #include <gsf-gnome/gsf-input-bonobo.h>
24 #include <gsf/gsf-input-impl.h>
25 #include <gsf/gsf-impl-utils.h>
26 #include <gsf-gnome/gsf-shared-bonobo-stream.h>
27 #include <bonobo/bonobo-persist-stream.h>
28 #include <bonobo/bonobo-exception.h>
29 #include <string.h>
30
31 /* FIXME: Should make CORBA environment available to caller somehow. */
32 struct _GsfInputBonobo {
33         GsfInput input;
34         GsfSharedBonoboStream *shared;
35         guint8   *buf;
36         size_t   buf_size;
37         gsf_off_t pos;
38 };
39
40 typedef struct {
41         GsfInputClass input_class;
42 } GsfInputBonoboClass;
43
44 static int
45 gib_synch_shared_ptr (GsfInputBonobo *binput)
46 {
47         CORBA_Environment ev;
48         CORBA_long new_pos;
49
50         if (binput->shared == NULL)
51                 return 0;
52         if (binput->pos == (gsf_off_t) binput->shared->pos)
53                 return 0;
54
55         CORBA_exception_init (&ev);
56         new_pos = (CORBA_long) binput->pos;
57         Bonobo_Stream_seek (binput->shared->stream, new_pos,
58                             Bonobo_Stream_SeekSet, &ev);
59         if (BONOBO_EX (&ev)) {
60                 g_warning ("%s", bonobo_exception_get_text (&ev));
61                 CORBA_exception_free (&ev);
62                 return -1;
63         } else {
64                 binput->shared->pos = new_pos;
65                 return 0;
66         }
67 }
68
69 /**
70  * gsf_input_bonobo_new :
71  * @stream   : Bonobo stream
72  * @err      : optionally %NULL.
73  *
74  * Returns: a new input object or %NULL.
75  **/
76 GsfInput *
77 gsf_input_bonobo_new (Bonobo_Stream const stream, GError **err)
78 {
79         GsfInputBonobo *input;
80         Bonobo_StorageInfo   *info;
81         CORBA_Environment ev;
82         CORBA_long size;
83
84         if (stream == NULL) {
85                 if (err != NULL)
86                         *err = g_error_new (gsf_input_error_id (), 0,
87                                 "stream is NULL");
88                 return NULL;
89         }
90
91         CORBA_exception_init (&ev);
92         /* <ICK!> info->size doesn't work */
93         size = Bonobo_Stream_seek (stream, 0, Bonobo_Stream_SeekEnd, &ev);
94         if (BONOBO_EX (&ev)) {
95                 if (err != NULL)
96                         *err = g_error_new (gsf_input_error_id (), 0,
97                                             "%s: %s",
98                                             "Error seeking to get stream size",
99                                             bonobo_exception_get_text (&ev));
100                 CORBA_exception_free (&ev);
101                 return NULL;
102         }
103         Bonobo_Stream_seek (stream, 0, Bonobo_Stream_SeekSet, &ev);
104         if (BONOBO_EX (&ev)) {
105                 if (err != NULL)
106                         *err = g_error_new (gsf_input_error_id (), 0,
107                                             "%s: %s",
108                                             "Error seeking to get stream size",
109                                             bonobo_exception_get_text (&ev));
110                 CORBA_exception_free (&ev);
111                 return NULL;
112         }
113         /* </ICK!> */
114
115         info = Bonobo_Stream_getInfo (stream, 0, &ev);
116         if (BONOBO_EX (&ev)) {
117                 if (err != NULL)
118                         *err = g_error_new (gsf_input_error_id (), 0,
119                                             "%s: %s",
120                                             "Error getting stream info",
121                                             bonobo_exception_get_text (&ev));
122                 CORBA_exception_free (&ev);
123                 return NULL;
124         }
125
126         input = g_object_new (GSF_INPUT_BONOBO_TYPE, NULL);
127         if (G_UNLIKELY (NULL == input)) {
128                 CORBA_free (info);
129                 return NULL;
130         }
131
132         input->shared = gsf_shared_bonobo_stream_new (stream);
133         input->buf  = NULL;
134         input->buf_size = 0;
135         gsf_input_set_size (GSF_INPUT (input), (gsf_off_t) size);
136         gsf_input_set_name (GSF_INPUT (input), info->name);
137
138         CORBA_free (info);
139
140         return GSF_INPUT (input);
141 }
142
143 static void
144 gsf_input_bonobo_finalize (GObject *obj)
145 {
146         GObjectClass *parent_class;
147         GsfInputBonobo *input = (GsfInputBonobo *)obj;
148
149         if (input->shared)
150                 g_object_unref (G_OBJECT (input->shared));
151         input->shared = NULL;
152
153         g_free (input->buf);
154         input->buf = NULL;
155         input->buf_size = 0;
156
157         parent_class = g_type_class_peek (GSF_INPUT_TYPE);
158         if (parent_class && parent_class->finalize)
159                 parent_class->finalize (obj);
160 }
161
162 static GsfInput *
163 gsf_input_bonobo_dup (GsfInput *src_input, GError **err)
164 {
165         GsfInputBonobo const *src = (GsfInputBonobo *)src_input;
166         GsfInputBonobo *dst = g_object_new (GSF_INPUT_BONOBO_TYPE, NULL);
167         if (G_UNLIKELY (NULL == dst)) return NULL;
168
169         (void) err;
170
171         dst->shared = src->shared;
172         g_object_ref (G_OBJECT (dst->shared));
173
174         return GSF_INPUT (dst);
175 }
176
177 static guint8 const *
178 gsf_input_bonobo_read (GsfInput *input, size_t num_bytes,
179                        guint8 *buffer)
180 {
181         GsfInputBonobo *binput = GSF_INPUT_BONOBO (input);
182         CORBA_unsigned_long num_read;
183         Bonobo_Stream_iobuf *bsibuf;
184         CORBA_Environment ev;
185
186         g_return_val_if_fail (binput != NULL, NULL);
187         g_return_val_if_fail (binput->shared != NULL, NULL);
188         g_return_val_if_fail (binput->shared->stream != NULL, NULL);
189
190         if (buffer == NULL) {
191                 if (binput->buf_size < num_bytes) {
192                         binput->buf_size = num_bytes;
193                         g_free (binput->buf);
194                         binput->buf = g_new (guint8, binput->buf_size);
195                 }
196                 buffer = binput->buf;
197         }
198
199         if (gib_synch_shared_ptr (binput) != 0)
200                 return NULL;
201
202         CORBA_exception_init (&ev);
203         Bonobo_Stream_read (binput->shared->stream, (CORBA_long) num_bytes,
204                             &bsibuf, &ev);
205         if (BONOBO_EX (&ev)) {
206                 g_warning ("%s", bonobo_exception_get_text (&ev));
207                 return NULL;
208         } else {
209                 memcpy (buffer, bsibuf->_buffer, bsibuf->_length);
210                 num_read = bsibuf->_length;
211                 CORBA_free (bsibuf);
212         }
213         if ((size_t) num_read == num_bytes) {
214                 return buffer;
215         } else {
216                 g_warning ("Only read %ld bytes, asked for %ld",
217                            (long)num_read, (long)num_bytes);
218                 return NULL;
219         }
220 }
221
222 static gboolean
223 gsf_input_bonobo_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
224 {
225         GsfInputBonobo *binput = GSF_INPUT_BONOBO (input);
226         Bonobo_Stream_SeekType bwhence;
227         CORBA_long pos, coffset;
228         CORBA_Environment ev;
229
230         g_return_val_if_fail (binput != NULL, TRUE);
231         g_return_val_if_fail (binput->shared != NULL, TRUE);
232         g_return_val_if_fail (binput->shared->stream != NULL, TRUE);
233
234         if (whence == G_SEEK_CUR) {
235                 if (gib_synch_shared_ptr (binput) != 0)
236                         return TRUE;
237         }
238         
239         switch (whence) {
240         case G_SEEK_SET :
241                 bwhence =  Bonobo_Stream_SeekSet;
242                 break;
243         case G_SEEK_CUR :
244                 bwhence = Bonobo_Stream_SeekCur;
245                 break;
246         case G_SEEK_END :
247                 bwhence = Bonobo_Stream_SeekEnd;
248                 break;
249         default:
250                 return TRUE;
251         }
252         
253
254         coffset = offset;
255         if ((gsf_off_t) coffset != offset) { /* Check for overflow */
256                 g_warning ("offset too large for Bonobo_Stream_seek");
257                 return TRUE;
258         }
259         CORBA_exception_init (&ev);
260         pos = Bonobo_Stream_seek
261                 (binput->shared->stream, coffset, bwhence, &ev);
262         if (BONOBO_EX (&ev)) {
263                 g_warning ("%s", bonobo_exception_get_text (&ev));
264                 return TRUE;
265         } else {
266                 binput->shared->pos = pos;
267                 binput->pos = (gsf_off_t) pos;
268                 return FALSE;
269         }
270 }
271
272 static void
273 gsf_input_bonobo_init (GObject *obj)
274 {
275         GsfInputBonobo *binput = GSF_INPUT_BONOBO (obj);
276
277         binput->shared = NULL;
278         binput->buf  = NULL;
279         binput->buf_size = 0;
280 }
281
282 static void
283 gsf_input_bonobo_class_init (GObjectClass *gobject_class)
284 {
285         GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
286
287         gobject_class->finalize = gsf_input_bonobo_finalize;
288         input_class->Dup        = gsf_input_bonobo_dup;
289         input_class->Read       = gsf_input_bonobo_read;
290         input_class->Seek       = gsf_input_bonobo_seek;
291 }
292
293 GSF_CLASS (GsfInputBonobo, gsf_input_bonobo,
294            gsf_input_bonobo_class_init, gsf_input_bonobo_init, GSF_INPUT_TYPE)