1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) *
4  * Copyright 2001, 2002 Sun Microsystems Inc.,
5  * Copyright 2001, 2002 Ximian, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 /* streamablecontent.c : implements the StreamableContent interface */
24 
25 #include "config.h"
26 
27 #include <libspi/component.h>
28 #include <libspi/streamablecontent.h>
29 
30 #include <stdio.h>
31 #include <string.h>
32 
33 /* Our parent Gtk object type */
34 #define PARENT_TYPE SPI_TYPE_BASE
35 
36 /* A pointer to our parent object class */
37 static GObjectClass *spi_streamable_parent_class;
38 
39 #define SPI_CONTENT_STREAM_TYPE            (spi_content_stream_get_type ())
40 #define SPI_CONTENT_STREAM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPI_CONTENT_STREAM_TYPE, SpiContentStream))
41 #define SPI_CONTENT_STREAM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), SPI_CONTENT_STREAM_TYPE, SpiContentStreamClass))
42 #define SPI_IS_CONTENT_STREAM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPI_CONTENT_STREAM_TYPE))
43 #define SPI_IS_CONTENT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPI_CONTENT_STREAM_TYPE))
44 
45 typedef struct _SpiContentStream SpiContentStream;
46 typedef struct _SpiContentStreamClass SpiContentStreamClass;
47 
48 struct _SpiContentStream
49 {
50   BonoboObject parent;
51   GIOChannel *gio;
52 };
53 
54 struct _SpiContentStreamClass
55 {
56   BonoboObjectClass parent_class;
57   POA_Accessibility_ContentStream__epv epv;
58 };
59 
60 GType spi_content_stream_get_type (void);
61 
62 static SpiContentStream *
spi_content_stream_new(GIOChannel * gio)63 spi_content_stream_new (GIOChannel * gio)
64 {
65   SpiContentStream *new_stream = g_object_new (SPI_CONTENT_STREAM_TYPE, NULL);
66   new_stream->gio = gio;
67   return new_stream;
68 }
69 
70 static void
spi_content_stream_dispose(GObject * o)71 spi_content_stream_dispose (GObject * o)
72 {
73   if (SPI_IS_CONTENT_STREAM (o))
74     {
75       SpiContentStream *stream = SPI_CONTENT_STREAM (o);
76       if (stream->gio)
77         g_io_channel_unref (stream->gio);
78     }
79 }
80 
81 static CORBA_long
impl_content_stream_seek(PortableServer_Servant servant,const CORBA_long offset,const Accessibility_ContentStream_SeekType whence,CORBA_Environment * ev)82 impl_content_stream_seek (PortableServer_Servant servant,
83                           const CORBA_long offset,
84                           const Accessibility_ContentStream_SeekType whence,
85                           CORBA_Environment * ev)
86 {
87   SpiContentStream *stream =
88     SPI_CONTENT_STREAM (bonobo_object_from_servant (servant));
89   if (stream && stream->gio)
90     {
91       GError *err;
92       GSeekType seektype = G_SEEK_SET;
93       switch (whence)
94         {
95         case Accessibility_ContentStream_SEEK_CURRENT:
96           seektype = G_SEEK_CUR;
97           break;
98         case Accessibility_ContentStream_SEEK_END:
99           seektype = G_SEEK_END;
100           break;
101         }
102       if (g_io_channel_seek_position (stream->gio, (gint64) offset,
103                                       seektype, &err) == G_IO_STATUS_NORMAL)
104         return offset;
105       else
106         return -1;
107     }
108   else
109     return -1;
110 }
111 
112 static CORBA_long
impl_content_stream_read(PortableServer_Servant servant,const CORBA_long count,Accessibility_ContentStream_iobuf ** buffer,CORBA_Environment * ev)113 impl_content_stream_read (PortableServer_Servant servant,
114                           const CORBA_long count,
115                           Accessibility_ContentStream_iobuf ** buffer,
116                           CORBA_Environment * ev)
117 {
118   SpiContentStream *stream =
119     SPI_CONTENT_STREAM (bonobo_object_from_servant (servant));
120   CORBA_long realcount = 0;
121 
122   if (stream && stream->gio)
123     {
124       gchar *gbuf = NULL;
125       GIOStatus status;
126       GError *err = NULL;
127 
128       /* read the giochannel and determine the actual bytes read... */
129       if (count != -1)
130         {
131           gbuf = g_malloc (count + 1);
132           status =
133             g_io_channel_read_chars (stream->gio, gbuf, count, &realcount,
134                                      &err);
135         }
136       else
137         status =
138           g_io_channel_read_to_end (stream->gio, &gbuf, &realcount, &err);
139 
140       if (status == G_IO_STATUS_NORMAL || status == G_IO_STATUS_EOF)
141         {
142           *buffer = Bonobo_Stream_iobuf__alloc ();
143           CORBA_sequence_set_release (*buffer, TRUE);
144 
145           (*buffer)->_buffer =
146             CORBA_sequence_CORBA_octet_allocbuf (realcount);
147           (*buffer)->_length = realcount;
148 
149           g_memmove ((*buffer)->_buffer, gbuf, realcount);
150         }
151 
152       g_free (gbuf);
153     }
154 
155   return realcount;
156 }
157 
158 static void
impl_content_stream_close(PortableServer_Servant servant,CORBA_Environment * ev)159 impl_content_stream_close (PortableServer_Servant servant,
160                            CORBA_Environment * ev)
161 {
162   GIOStatus status;
163   GError *err;
164   SpiContentStream *stream =
165     SPI_CONTENT_STREAM (bonobo_object_from_servant (servant));
166   if (stream && stream->gio)
167     {
168       status = g_io_channel_shutdown (stream->gio, TRUE, &err);
169       g_io_channel_unref (stream->gio);
170     }
171   if (err)
172     g_free (err);
173 }
174 
175 static void
spi_content_stream_class_init(SpiContentStreamClass * klass)176 spi_content_stream_class_init (SpiContentStreamClass * klass)
177 {
178   POA_Accessibility_ContentStream__epv *epv = &klass->epv;
179   GObjectClass *object_class = (GObjectClass *) klass;
180 
181   epv->seek = impl_content_stream_seek;
182   epv->read = impl_content_stream_read;
183   epv->close = impl_content_stream_close;
184 
185   object_class->dispose = spi_content_stream_dispose;
186 }
187 
188 
189 static void
spi_content_stream_init(SpiContentStream * stream)190 spi_content_stream_init (SpiContentStream * stream)
191 {
192 }
193 
194 
BONOBO_TYPE_FUNC_FULL(SpiContentStream,Accessibility_ContentStream,BONOBO_TYPE_OBJECT,spi_content_stream)195 BONOBO_TYPE_FUNC_FULL (SpiContentStream,
196                        Accessibility_ContentStream,
197                        BONOBO_TYPE_OBJECT, spi_content_stream)
198      static AtkStreamableContent
199        *get_streamable_from_servant (PortableServer_Servant servant)
200 {
201   SpiBase *object = SPI_BASE (bonobo_object_from_servant (servant));
202   g_return_val_if_fail (object != NULL, NULL);
203   g_return_val_if_fail (ATK_IS_STREAMABLE_CONTENT (object->gobj), NULL);
204   return ATK_STREAMABLE_CONTENT (object->gobj);
205 }
206 
207 /*
208  * CORBA Accessibility::StreamableContent::getContentTypes method implementation
209  */
210 static Accessibility_StringSeq *
impl_accessibility_streamable_get_content_types(PortableServer_Servant servant,CORBA_Environment * ev)211 impl_accessibility_streamable_get_content_types (PortableServer_Servant
212                                                  servant,
213                                                  CORBA_Environment * ev)
214 {
215   Accessibility_StringSeq *typelist = Accessibility_StringSeq__alloc ();
216   AtkStreamableContent *streamable = get_streamable_from_servant (servant);
217   int n_types, i;
218 
219   typelist->_length = typelist->_maximum = 0;
220 
221   g_return_val_if_fail (streamable != NULL, typelist);
222 
223   n_types = atk_streamable_content_get_n_mime_types (streamable);
224 
225   if (n_types)
226     {
227       typelist->_length = typelist->_maximum = n_types;
228       typelist->_buffer = Accessibility_StringSeq_allocbuf (n_types);
229       for (i = 0; i < n_types; ++i)
230         {
231           const gchar *mimetype =
232             atk_streamable_content_get_mime_type (streamable, i);
233           typelist->_buffer[i] = CORBA_string_dup (mimetype ? mimetype : "");
234         }
235     }
236   return typelist;
237 }
238 
239 /*
240  * CORBA Accessibility::StreamableContent::getContent method implementation
241  */
242 static Bonobo_Stream
impl_accessibility_streamable_get_content(PortableServer_Servant servant,const CORBA_char * content_type,CORBA_Environment * ev)243 impl_accessibility_streamable_get_content (PortableServer_Servant servant,
244                                            const CORBA_char * content_type,
245                                            CORBA_Environment * ev)
246 {
247   Bonobo_Stream stream;
248   AtkStreamableContent *streamable = get_streamable_from_servant (servant);
249   GIOChannel *gio;
250 
251   g_return_val_if_fail (streamable != NULL, NULL);
252 
253   gio = atk_streamable_content_get_stream (streamable, content_type);
254 
255   stream = CORBA_OBJECT_NIL;    /* deprecated,
256                                  * and it was never implemented,
257                                  * so don't bother fixing this
258                                  */
259   return stream;
260 }
261 
262 /*
263  * CORBA Accessibility::StreamableContent::getStream method implementation
264  */
265 static Accessibility_ContentStream
impl_accessibility_streamable_get_stream(PortableServer_Servant servant,const CORBA_char * content_type,CORBA_Environment * ev)266 impl_accessibility_streamable_get_stream (PortableServer_Servant servant,
267                                           const CORBA_char * content_type,
268                                           CORBA_Environment * ev)
269 {
270   SpiContentStream *stream;
271   AtkStreamableContent *streamable = get_streamable_from_servant (servant);
272   GIOChannel *gio;
273 
274   g_return_val_if_fail (streamable != NULL, NULL);
275 
276   gio = atk_streamable_content_get_stream (streamable, content_type);
277 
278   stream = spi_content_stream_new (gio);
279 
280   return bonobo_object_dup_ref (BONOBO_OBJREF (stream), ev);
281 }
282 
283 /*
284  * CORBA Accessibility::StreamableContent::GetURI method implementation
285  */
286 static CORBA_string
impl_accessibility_streamable_get_uri(PortableServer_Servant servant,const CORBA_char * content_type,CORBA_Environment * ev)287 impl_accessibility_streamable_get_uri (PortableServer_Servant servant,
288                                        const CORBA_char * content_type,
289                                        CORBA_Environment * ev)
290 {
291   gchar *uri;
292   AtkStreamableContent *streamable = get_streamable_from_servant (servant);
293 
294   g_return_val_if_fail (streamable != NULL, NULL);
295 
296   uri = atk_streamable_content_get_uri (streamable, content_type);
297 
298   return (uri != NULL ? CORBA_string_dup (uri) : CORBA_string_dup (""));
299 }
300 
301 static void
spi_streamable_class_init(SpiStreamableClass * klass)302 spi_streamable_class_init (SpiStreamableClass * klass)
303 {
304   POA_Accessibility_StreamableContent__epv *epv = &klass->epv;
305   spi_streamable_parent_class = g_type_class_peek_parent (klass);
306 
307   epv->getContentTypes = impl_accessibility_streamable_get_content_types;
308   epv->getContent = impl_accessibility_streamable_get_content;
309   epv->getStream = impl_accessibility_streamable_get_stream;
310   epv->GetURI = impl_accessibility_streamable_get_uri;
311 }
312 
313 static void
spi_streamable_init(SpiStreamable * streamable)314 spi_streamable_init (SpiStreamable * streamable)
315 {
316 }
317 
318 
319 SpiStreamable *
spi_streamable_interface_new(AtkObject * o)320 spi_streamable_interface_new (AtkObject * o)
321 {
322   SpiStreamable *retval = g_object_new (SPI_STREAMABLE_TYPE, NULL);
323 
324   spi_base_construct (SPI_BASE (retval), G_OBJECT (o));
325 
326   return retval;
327 }
328 
329 BONOBO_TYPE_FUNC_FULL (SpiStreamable,
330                        Accessibility_StreamableContent,
331                        PARENT_TYPE, spi_streamable)
332