76312ac3ff490cdf033fe1329680b002020e189d
[platform/core/uifw/at-spi2-atk.git] / cspi / spi_streamablecontent.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include <string.h>
25 #include <libbonobo.h>
26 #include <cspi/spi-private.h>
27
28
29 /* TODO: factor/wrap Bonobo_Stream dependency to cspi/bonobo */
30
31 struct StreamCacheItem {
32   Bonobo_Stream stream;
33   gchar *mimetype;
34 };
35
36 static gboolean
37 streams_equal_func (gconstpointer a, gconstpointer b)
38 {
39   const struct StreamCacheItem *c1 = a, *c2 = b;
40   return CORBA_Object_is_equivalent (c1->stream, c2->stream, cspi_ev ());
41 }
42
43 static void
44 stream_cache_item_free (gpointer a)
45 {
46   struct StreamCacheItem *cache_item = a;
47
48   cspi_release_unref (cache_item->stream);
49   SPI_freeString (cache_item->mimetype);
50   g_free (cache_item);
51 }
52
53 static GHashTable *streams = NULL;
54
55 GHashTable *
56 get_streams (void) 
57 {
58   if (streams == NULL)
59       streams = g_hash_table_new_full (g_direct_hash, streams_equal_func, 
60                                        NULL, stream_cache_item_free);
61   return streams;
62 }
63
64 static CORBA_long
65 accessible_bonobo_stream_client_seek (const Bonobo_Stream stream,
66                                       CORBA_long offset,
67                                       Bonobo_Stream_SeekType seek_type,
68                                       CORBA_Environment  *opt_ev)
69 {
70         CORBA_Environment  *ev, temp_ev;
71         CORBA_long ret_offset;
72        
73         if (!opt_ev) {
74                 CORBA_exception_init (&temp_ev);
75                 ev = &temp_ev;
76         } else
77                 ev = opt_ev;
78
79         ret_offset = Bonobo_Stream_seek (stream, offset, seek_type, ev);
80         if (BONOBO_EX (ev))
81                 ret_offset = -1;
82
83         if (!opt_ev)
84                 CORBA_exception_free (&temp_ev);
85         
86         return ret_offset;
87 }
88
89 /* internal use only, declared in cspi-private.h */
90 void
91 cspi_streams_close_all (void)
92 {
93   if (streams)
94     {
95       g_hash_table_destroy (streams);
96       streams = NULL;
97     }
98 }
99
100 /**
101  * AccessibleStreamableContent_ref:
102  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to
103  *       operate.
104  *
105  * Increment the reference count for an #AccessibleStreamableContent object.
106  *
107  **/
108 void
109 AccessibleStreamableContent_ref (AccessibleStreamableContent *obj)
110 {
111   cspi_object_ref (obj);
112 }
113
114 /**
115  * AccessibleStreamableContent_unref:
116  * @obj: a pointer to the #AccessibleStreamableContent implementor
117  *       on which to operate. 
118  *
119  * Decrement the reference count for an #AccessibleStreamableContent object.
120  *
121  **/
122 void
123 AccessibleStreamableContent_unref (AccessibleStreamableContent *obj)
124 {
125   cspi_object_unref (obj);
126 }
127
128 /**
129  * AccessibleStreamableContent_getContentTypes:
130  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
131  *
132  * Get a list of strings containing the content mimetypes available from an
133  *       #AccessibleStreamableContent implementor.
134  *
135  * Returns: an array of strings, terminated by a NULL string, specifying the
136  *       mimetypes for which the streamed content is available.
137  *
138  **/
139
140 char **
141 AccessibleStreamableContent_getContentTypes (AccessibleStreamableContent *obj)
142 {
143   Accessibility_StringSeq *mimeseq;
144   char **content_types;
145   int i;
146
147   mimeseq = Accessibility_StreamableContent_getContentTypes (CSPI_OBJREF (obj),
148                                                              cspi_ev ());
149   cspi_return_val_if_ev ("getContentTypes", NULL); 
150
151   content_types = g_new0 (char *, mimeseq->_length + 1);
152   for (i = 0; i < mimeseq->_length; ++i)
153     content_types[i] = CORBA_string_dup (mimeseq->_buffer[i]);
154   content_types [mimeseq->_length] = NULL;
155   CORBA_free (mimeseq);
156
157   return content_types;
158 }
159
160 void
161 AccessibleStreamableContent_freeContentTypesList (AccessibleStreamableContent *obj,
162                                                   char **content_types)
163 {
164   if (content_types) 
165     {
166       gint i = 0;
167       while (content_types[i])
168         {
169           g_free (content_types[i]);
170           i++;
171         }
172       g_free (content_types);
173     }
174 }
175
176 /**
177  * AccessibleStreamableContent_open:
178  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
179  * @content_type: a string specifying the content type to retrieve (should match one
180  * of the return strings from #AccessibleStreamableContent_getContentTypes ()).
181  *
182  * Open a streaming connection to an AccessibleStreamableContent implementor,
183  *       of a particular content type
184  *
185  * Returns: #TRUE if successful, #FALSE if unsuccessful.
186  *
187  **/
188 SPIBoolean
189 AccessibleStreamableContent_open (AccessibleStreamableContent *obj,
190                                   const char *content_type)
191 {
192   Bonobo_Stream stream;
193   struct StreamCacheItem *cache;
194   stream = Accessibility_StreamableContent_getContent (CSPI_OBJREF (obj),
195                                                        content_type,
196                                                        cspi_ev ());
197   cspi_return_val_if_ev ("getContent", FALSE); 
198
199   if (stream != CORBA_OBJECT_NIL) {
200     cache = g_new0 (struct StreamCacheItem, 1);
201     cache->stream = stream;
202     cache->mimetype = CORBA_string_dup (content_type);
203     g_hash_table_replace (get_streams (), stream, cache);
204     return TRUE;
205   }
206   return FALSE;
207 }
208
209 /**
210  * AccessibleStreamableContent_close:
211  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
212  *
213  * Close the current streaming connection to an AccessibleStreamableContent implementor.
214  * This must be called before any subsequent AccessibleStreamableContent_open
215  * calls on the same object.
216  *
217  * Returns: #TRUE if successful, #FALSE if unsuccessful.
218  *
219  **/
220 SPIBoolean
221 AccessibleStreamableContent_close (AccessibleStreamableContent *obj)
222 {
223   if (CSPI_OBJREF (obj) != CORBA_OBJECT_NIL) {
224     if (g_hash_table_remove (get_streams (), CSPI_OBJREF (obj)))
225       return TRUE;
226   }
227   return FALSE;
228 }
229
230 /**
231  * AccessibleStreamableContent_seek:
232  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
233  * @offset: a long int specifying the offset into the stream.
234  * @seek_type: an enum indicating the seek offset type, may be SEEK_SET,
235  *            SEEK_CUR, SEEK_END (as in the lseek() libc command).
236  *
237  * Cause the current streamable content connection (obtained via
238  *     #AccessibleStreamableContent_open()) to seek to a particular offset in the
239  *     stream.
240  *
241  * Returns: #TRUE if successful, #FALSE if unsuccessful.
242  *
243  **/
244 long int
245 AccessibleStreamableContent_seek (AccessibleStreamableContent *obj,
246                                   long int offset,
247                                   AccessibleStreamableContentSeekType seek_type)
248 {
249   Bonobo_Stream stream;
250   long int ret_offset = 0;
251   struct StreamCacheItem *cached; 
252   Bonobo_Stream_SeekType bonobo_seek_type;
253
254   cached = g_hash_table_lookup (get_streams (), CSPI_OBJREF (obj));
255   if (cached)
256     {
257       stream = cached->stream;
258       if (stream != CORBA_OBJECT_NIL)
259         {
260           switch (seek_type) {
261           case SPI_STREAM_SEEK_SET:
262             bonobo_seek_type = Bonobo_Stream_SeekSet; 
263             break;
264           case SPI_STREAM_SEEK_END:
265             bonobo_seek_type = Bonobo_Stream_SeekEnd; 
266             break;
267           case SPI_STREAM_SEEK_CUR:
268           default:
269             bonobo_seek_type = Bonobo_Stream_SeekCur; 
270             break;
271           }
272           /* bonobo-client doesn't wrap seek yet, so we have to. */
273           ret_offset = accessible_bonobo_stream_client_seek (stream, offset, 
274                                                              bonobo_seek_type, cspi_ev ());
275           cspi_return_val_if_ev ("seek", FALSE);
276         }
277     }
278   return ret_offset;
279 }
280
281 /**
282  * AccessibleStreamableContent_read:
283  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
284  * @buff: a pointer to a buffer into which the resulting bytes read from the stream
285  *        are to be written.
286  * @nbytes: a long integer indicating the number of bytes to read/write.
287  * @read_type: currently unused, specifies behavior of reads for streamed content
288  *        if blocking is not allowed, etc.
289  *
290  * Copy (read) bytes from the currently open streamable content connection
291  *     to a buffer.  This is a blocking API, in the sense that it does not 
292  *     return until the bytes have been read, or an error condition is 
293  *     detected.
294  *
295  * Returns: an integer indicating the number of bytes read, or -1 on error.
296  *
297  **/
298 SPIBoolean
299 AccessibleStreamableContent_read (AccessibleStreamableContent *obj,
300                                   void *buff,
301                                   long int nbytes,
302                                   unsigned int read_type)
303 {
304   Bonobo_Stream stream;
305   struct StreamCacheItem *cached; 
306   cached = g_hash_table_lookup (get_streams (), CSPI_OBJREF (obj));
307   if (cached)
308     {
309       CORBA_long len_read;
310       stream = cached->stream;
311       if (stream != CORBA_OBJECT_NIL)
312         {
313           guint8 *mem;
314           mem = bonobo_stream_client_read (stream, (size_t) nbytes, &len_read, cspi_ev ());
315           cspi_return_val_if_ev ("read", FALSE);
316           if (mem)
317             {
318               memcpy (buff, mem, len_read);
319               g_free (mem);
320               if ((nbytes == -1) || (len_read == nbytes))
321                 return TRUE;
322             }
323         }
324     }
325   return FALSE;
326 }
327