2e0c080f5fe95238946dc0a31c52f4df8289f3ea
[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 static 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  * @Since: AT-SPI 1.4
108  **/
109 void
110 AccessibleStreamableContent_ref (AccessibleStreamableContent *obj)
111 {
112   cspi_object_ref (obj);
113 }
114
115 /**
116  * AccessibleStreamableContent_unref:
117  * @obj: a pointer to the #AccessibleStreamableContent implementor
118  *       on which to operate. 
119  *
120  * Decrement the reference count for an #AccessibleStreamableContent object.
121  *
122  * @Since: AT-SPI 1.4
123  **/
124 void
125 AccessibleStreamableContent_unref (AccessibleStreamableContent *obj)
126 {
127   cspi_object_unref (obj);
128 }
129
130 /**
131  * AccessibleStreamableContent_getContentTypes:
132  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
133  *
134  * Get a list of strings containing the content mimetypes available from an
135  *       #AccessibleStreamableContent implementor.
136  *
137  * @Since: AT-SPI 1.4
138  *
139  * Returns: an array of strings, terminated by a NULL string, specifying the
140  *       mimetypes for which the streamed content is available.
141  *
142  **/
143
144 char **
145 AccessibleStreamableContent_getContentTypes (AccessibleStreamableContent *obj)
146 {
147   Accessibility_StringSeq *mimeseq;
148   char **content_types;
149   int i;
150
151   mimeseq = Accessibility_StreamableContent_getContentTypes (CSPI_OBJREF (obj),
152                                                              cspi_ev ());
153   cspi_return_val_if_ev ("getContentTypes", NULL); 
154
155   content_types = g_new0 (char *, mimeseq->_length + 1);
156   for (i = 0; i < mimeseq->_length; ++i)
157     content_types[i] = CORBA_string_dup (mimeseq->_buffer[i]);
158   content_types [mimeseq->_length] = NULL;
159   CORBA_free (mimeseq);
160
161   return content_types;
162 }
163 /**
164 * AccessibleStreamableContent_freeContentTypesList:
165 * @obj: the AccessibleStreamableContent implementor on which to operate.
166 * @content_types: a list of content types previously returned by 
167 *     #AccessibleStreamableContent_getContentTypes.
168 *
169 * Free the memory associated with a call to #AccessibleStreamableContent_getContentTypes, once 
170 * the result has been used.
171 *
172 * @Since: AT-SPI 1.4
173 **/
174 void
175 AccessibleStreamableContent_freeContentTypesList (AccessibleStreamableContent *obj,
176                                                   char **content_types)
177 {
178   if (content_types) 
179     {
180       gint i = 0;
181       while (content_types[i])
182         {
183           g_free (content_types[i]);
184           i++;
185         }
186       g_free (content_types);
187     }
188 }
189
190 /**
191  * AccessibleStreamableContent_open:
192  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
193  * @content_type: a string specifying the content type to retrieve (should match one
194  * of the return strings from #AccessibleStreamableContent_getContentTypes ()).
195  *
196  * Open a streaming connection to an AccessibleStreamableContent implementor,
197  *       of a particular content type
198  *
199  * @Since: AT-SPI 1.4
200  *
201  * Returns: #TRUE if successful, #FALSE if unsuccessful.
202  *
203  **/
204 SPIBoolean
205 AccessibleStreamableContent_open (AccessibleStreamableContent *obj,
206                                   const char *content_type)
207 {
208   Bonobo_Stream stream;
209   struct StreamCacheItem *cache;
210   stream = Accessibility_StreamableContent_getContent (CSPI_OBJREF (obj),
211                                                        content_type,
212                                                        cspi_ev ());
213   cspi_return_val_if_ev ("getContent", FALSE); 
214
215   if (stream != CORBA_OBJECT_NIL) {
216     cache = g_new0 (struct StreamCacheItem, 1);
217     cache->stream = stream;
218     cache->mimetype = CORBA_string_dup (content_type);
219     g_hash_table_replace (get_streams (), stream, cache);
220     return TRUE;
221   }
222   return FALSE;
223 }
224
225 /**
226  * AccessibleStreamableContent_close:
227  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
228  *
229  * Close the current streaming connection to an AccessibleStreamableContent implementor.
230  * This must be called before any subsequent AccessibleStreamableContent_open
231  * calls on the same object.
232  * 
233  * @Since: AT-SPI 1.4
234  *
235  * Returns: #TRUE if successful, #FALSE if unsuccessful.
236  *
237  **/
238 SPIBoolean
239 AccessibleStreamableContent_close (AccessibleStreamableContent *obj)
240 {
241   if (CSPI_OBJREF (obj) != CORBA_OBJECT_NIL) {
242     if (g_hash_table_remove (get_streams (), CSPI_OBJREF (obj)))
243       return TRUE;
244   }
245   return FALSE;
246 }
247
248 /**
249  * AccessibleStreamableContent_seek:
250  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
251  * @offset: a long int specifying the offset into the stream.
252  * @seek_type: an enum indicating the seek offset type, may be SEEK_SET,
253  *            SEEK_CUR, SEEK_END (as in the lseek() libc command).
254  *
255  * Cause the current streamable content connection (obtained via
256  *     #AccessibleStreamableContent_open()) to seek to a particular offset in the
257  *     stream.
258  *
259  * @Since: AT-SPI 1.4
260  *
261  * Returns: #TRUE if successful, #FALSE if unsuccessful.
262  *
263  **/
264 long int
265 AccessibleStreamableContent_seek (AccessibleStreamableContent *obj,
266                                   long int offset,
267                                   AccessibleStreamableContentSeekType seek_type)
268 {
269   Bonobo_Stream stream;
270   long int ret_offset = 0;
271   struct StreamCacheItem *cached; 
272   Bonobo_Stream_SeekType bonobo_seek_type;
273
274   cached = g_hash_table_lookup (get_streams (), CSPI_OBJREF (obj));
275   if (cached)
276     {
277       stream = cached->stream;
278       if (stream != CORBA_OBJECT_NIL)
279         {
280           switch (seek_type) {
281           case SPI_STREAM_SEEK_SET:
282             bonobo_seek_type = Bonobo_Stream_SeekSet; 
283             break;
284           case SPI_STREAM_SEEK_END:
285             bonobo_seek_type = Bonobo_Stream_SeekEnd; 
286             break;
287           case SPI_STREAM_SEEK_CUR:
288           default:
289             bonobo_seek_type = Bonobo_Stream_SeekCur; 
290             break;
291           }
292           /* bonobo-client doesn't wrap seek yet, so we have to. */
293           ret_offset = accessible_bonobo_stream_client_seek (stream, offset, 
294                                                              bonobo_seek_type, cspi_ev ());
295           cspi_return_val_if_ev ("seek", FALSE);
296         }
297     }
298   return ret_offset;
299 }
300
301 /**
302  * AccessibleStreamableContent_read:
303  * @obj: a pointer to the #AccessibleStreamableContent implementor on which to operate.
304  * @buff: a pointer to a buffer into which the resulting bytes read from the stream
305  *        are to be written.
306  * @nbytes: a long integer indicating the number of bytes to read/write.
307  * @read_type: currently unused, specifies behavior of reads for streamed content
308  *        if blocking is not allowed, etc.
309  *
310  * Copy (read) bytes from the currently open streamable content connection
311  *     to a buffer.  This is a blocking API, in the sense that it does not 
312  *     return until the bytes have been read, or an error condition is 
313  *     detected.
314  *
315  * @Since: AT-SPI 1.4
316  *
317  * Returns: an integer indicating the number of bytes read, or -1 on error.
318  *
319  **/
320 SPIBoolean
321 AccessibleStreamableContent_read (AccessibleStreamableContent *obj,
322                                   void *buff,
323                                   long int nbytes,
324                                   unsigned int read_type)
325 {
326   Bonobo_Stream stream;
327   struct StreamCacheItem *cached; 
328   cached = g_hash_table_lookup (get_streams (), CSPI_OBJREF (obj));
329   if (cached)
330     {
331       CORBA_long len_read;
332       stream = cached->stream;
333       if (stream != CORBA_OBJECT_NIL)
334         {
335           guint8 *mem;
336           mem = bonobo_stream_client_read (stream, (size_t) nbytes, &len_read, cspi_ev ());
337           cspi_return_val_if_ev ("read", FALSE);
338           if (mem)
339             {
340               memcpy (buff, mem, len_read);
341               g_free (mem);
342               if ((nbytes == -1) || (len_read == nbytes))
343                 return TRUE;
344             }
345         }
346     }
347   return FALSE;
348 }
349