X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cspi%2Fspi_streamablecontent.c;h=d79aa6428f99e722bc46760f0ea1891a5df68220;hb=59568fcca2ea754f1ebb7133f29e1e0908e2af4a;hp=500b339d94e9df878e9b7bb99872e0f59e33f0d9;hpb=b7b8c5ec58a241e524435db41cbe798109f175dc;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/cspi/spi_streamablecontent.c b/cspi/spi_streamablecontent.c index 500b339..d79aa64 100644 --- a/cspi/spi_streamablecontent.c +++ b/cspi/spi_streamablecontent.c @@ -25,11 +25,10 @@ #include #include - -/* TODO: factor/wrap Bonobo_Stream dependency to cspi/bonobo */ +#define CORBA_BLOCK_SIZE 65536 /* see libbonobo, dunno where this is officially dictated */ struct StreamCacheItem { - Bonobo_Stream stream; + Accessibility_ContentStream stream; gchar *mimetype; }; @@ -41,37 +40,114 @@ streams_equal_func (gconstpointer a, gconstpointer b) } static void -stream_release (gpointer a) -{ - CORBA_Environment ev; - - bonobo_object_release_unref (a, &ev); -} - -static void stream_cache_item_free (gpointer a) { struct StreamCacheItem *cache_item = a; - CORBA_Environment ev; - if (cache_item) { - bonobo_object_release_unref (cache_item->stream, &ev); - SPI_freeString (cache_item->mimetype); - g_free (cache_item); - } + + cspi_release_unref (cache_item->stream); + SPI_freeString (cache_item->mimetype); + g_free (cache_item); } static GHashTable *streams = NULL; -GHashTable * +static GHashTable * get_streams (void) { - if (streams == NULL) { - streams = g_hash_table_new_full (g_direct_hash, streams_equal_func, - stream_release, stream_cache_item_free); - } + if (streams == NULL) + streams = g_hash_table_new_full (g_direct_hash, streams_equal_func, + NULL, stream_cache_item_free); return streams; } +static CORBA_long +accessible_content_stream_client_seek (const Accessibility_ContentStream stream, + CORBA_long offset, + Accessibility_ContentStream_SeekType seek_type, + CORBA_Environment *opt_ev) +{ + CORBA_Environment *ev, temp_ev; + CORBA_long ret_offset; + + if (!opt_ev) { + CORBA_exception_init (&temp_ev); + ev = &temp_ev; + } else + ev = opt_ev; + + ret_offset = Accessibility_ContentStream_seek (stream, offset, seek_type, ev); + if (BONOBO_EX (ev)) + ret_offset = -1; + + if (!opt_ev) + CORBA_exception_free (&temp_ev); + + return ret_offset; +} + +static guint8* +accessible_content_stream_client_read (const Accessibility_ContentStream stream, + const size_t size, + CORBA_long *length_read, + CORBA_Environment *ev) +{ + size_t pos; + guint8 *mem; + size_t length; + + g_return_val_if_fail (ev != NULL, NULL); + + if (length_read) + *length_read = size; + + length = size; + + if (length == 0) + return NULL; + + mem = g_try_malloc (length); + if (!mem) { + CORBA_exception_set_system (ev, ex_CORBA_NO_MEMORY, + CORBA_COMPLETED_NO); + return NULL; + } + + *length_read = 0; + + for (pos = 0; pos < length;) { + Accessibility_ContentStream_iobuf *buf; + CORBA_long len; + + len = (pos + CORBA_BLOCK_SIZE < length) ? + CORBA_BLOCK_SIZE : length - pos; + + Accessibility_ContentStream_read (stream, len, &buf, ev); + + if (BONOBO_EX (ev) || !buf) + goto io_error; + + if (buf->_length > 0) { + memcpy (mem + pos, buf->_buffer, buf->_length); + pos += buf->_length; + *length_read += buf->_length; + /* we assume a short read equals EOF ... is that right? */ + if (buf->_length < len || *length_read == size) + return mem; + } else { + g_warning ("Buffer length %d", buf->_length); + goto io_error; + } + *length_read += buf->_length; + + CORBA_free (buf); + } + + return mem; + + io_error: + return NULL; +} + /* internal use only, declared in cspi-private.h */ void cspi_streams_close_all (void) @@ -90,6 +166,7 @@ cspi_streams_close_all (void) * * Increment the reference count for an #AccessibleStreamableContent object. * + * @Since: AT-SPI 1.4 **/ void AccessibleStreamableContent_ref (AccessibleStreamableContent *obj) @@ -104,6 +181,7 @@ AccessibleStreamableContent_ref (AccessibleStreamableContent *obj) * * Decrement the reference count for an #AccessibleStreamableContent object. * + * @Since: AT-SPI 1.4 **/ void AccessibleStreamableContent_unref (AccessibleStreamableContent *obj) @@ -118,10 +196,13 @@ AccessibleStreamableContent_unref (AccessibleStreamableContent *obj) * Get a list of strings containing the content mimetypes available from an * #AccessibleStreamableContent implementor. * + * @Since: AT-SPI 1.4 + * * Returns: an array of strings, terminated by a NULL string, specifying the * mimetypes for which the streamed content is available. * **/ + char ** AccessibleStreamableContent_getContentTypes (AccessibleStreamableContent *obj) { @@ -129,18 +210,45 @@ AccessibleStreamableContent_getContentTypes (AccessibleStreamableContent *obj) char **content_types; int i; + g_return_val_if_fail (obj != NULL, NULL); + mimeseq = Accessibility_StreamableContent_getContentTypes (CSPI_OBJREF (obj), cspi_ev ()); - + cspi_return_val_if_ev ("getContentTypes", NULL); content_types = g_new0 (char *, mimeseq->_length + 1); - for (i = 0; i < mimeseq->_length; ++i) { - content_types[i] = CORBA_string_dup (mimeseq->_buffer[i]); - } + for (i = 0; i < mimeseq->_length; ++i) + content_types[i] = g_strdup (mimeseq->_buffer[i]); content_types [mimeseq->_length] = NULL; CORBA_free (mimeseq); - + return content_types; } +/** +* AccessibleStreamableContent_freeContentTypesList: +* @obj: the AccessibleStreamableContent implementor on which to operate. +* @content_types: a list of content types previously returned by +* #AccessibleStreamableContent_getContentTypes. +* +* Free the memory associated with a call to #AccessibleStreamableContent_getContentTypes, once +* the result has been used. +* +* Since: AT-SPI 1.4 +**/ +void +AccessibleStreamableContent_freeContentTypesList (AccessibleStreamableContent *obj, + char **content_types) +{ + if (content_types) + { + gint i = 0; + while (content_types[i]) + { + g_free (content_types[i]); + i++; + } + g_free (content_types); + } +} /** * AccessibleStreamableContent_open: @@ -149,7 +257,11 @@ AccessibleStreamableContent_getContentTypes (AccessibleStreamableContent *obj) * of the return strings from #AccessibleStreamableContent_getContentTypes ()). * * Open a streaming connection to an AccessibleStreamableContent implementor, - * of a particular content type + * of a particular content type. Note that a client may only have one + * open stream per streamable interface instance in the current + * implementation. + * + * @Since: AT-SPI 1.4 * * Returns: #TRUE if successful, #FALSE if unsuccessful. * @@ -158,16 +270,26 @@ SPIBoolean AccessibleStreamableContent_open (AccessibleStreamableContent *obj, const char *content_type) { - Bonobo_Stream stream; + Accessibility_ContentStream stream; struct StreamCacheItem *cache; - stream = Accessibility_StreamableContent_getContent (CSPI_OBJREF (obj), - content_type, - cspi_ev ()); + stream = Accessibility_StreamableContent_getStream (CSPI_OBJREF (obj), + content_type, + cspi_ev ()); + cspi_return_val_if_ev ("getContent", FALSE); + if (stream != CORBA_OBJECT_NIL) { cache = g_new0 (struct StreamCacheItem, 1); cache->stream = stream; cache->mimetype = CORBA_string_dup (content_type); - g_hash_table_replace (get_streams (), stream, cache); + + g_hash_table_replace (get_streams (), CSPI_OBJREF (obj), cache); + /* FIXME + * This limits us to one concurrent stream per streamable interface + * for a given client. + * It might be reasonable for a client to open more than one stream + * to content, in different mime-types, at the same time. + */ + return TRUE; } return FALSE; @@ -180,6 +302,8 @@ AccessibleStreamableContent_open (AccessibleStreamableContent *obj, * Close the current streaming connection to an AccessibleStreamableContent implementor. * This must be called before any subsequent AccessibleStreamableContent_open * calls on the same object. + * + * @Since: AT-SPI 1.4 * * Returns: #TRUE if successful, #FALSE if unsuccessful. * @@ -205,16 +329,45 @@ AccessibleStreamableContent_close (AccessibleStreamableContent *obj) * #AccessibleStreamableContent_open()) to seek to a particular offset in the * stream. * + * @Since: AT-SPI 1.4 + * * Returns: #TRUE if successful, #FALSE if unsuccessful. * **/ -SPIBoolean +long int AccessibleStreamableContent_seek (AccessibleStreamableContent *obj, long int offset, - unsigned int seek_type) + AccessibleStreamableContentSeekType seek_type) { - /* currently Bonobo_Stream does not appear to support seek operations */ - return FALSE; + Accessibility_ContentStream stream; + long int ret_offset = 0; + struct StreamCacheItem *cached; + Accessibility_ContentStream_SeekType content_seek_type; + + cached = g_hash_table_lookup (get_streams (), CSPI_OBJREF (obj)); + if (cached) + { + stream = cached->stream; + if (stream != CORBA_OBJECT_NIL) + { + switch (seek_type) { + case SPI_STREAM_SEEK_SET: + content_seek_type = Accessibility_ContentStream_SEEK_SET; + break; + case SPI_STREAM_SEEK_END: + content_seek_type = Accessibility_ContentStream_SEEK_END; + break; + case SPI_STREAM_SEEK_CUR: + default: + content_seek_type = Accessibility_ContentStream_SEEK_CURRENT; + break; + } + ret_offset = accessible_content_stream_client_seek (stream, offset, + content_seek_type, cspi_ev ()); + cspi_return_val_if_ev ("seek", FALSE); + } + } + return ret_offset; } /** @@ -227,7 +380,11 @@ AccessibleStreamableContent_seek (AccessibleStreamableContent *obj, * if blocking is not allowed, etc. * * Copy (read) bytes from the currently open streamable content connection - * to a buffer. + * to a buffer. This is a blocking API, in the sense that it does not + * return until the bytes have been read, or an error condition is + * detected. + * + * @Since: AT-SPI 1.4 * * Returns: an integer indicating the number of bytes read, or -1 on error. * @@ -238,20 +395,29 @@ AccessibleStreamableContent_read (AccessibleStreamableContent *obj, long int nbytes, unsigned int read_type) { - Bonobo_Stream stream; + Accessibility_ContentStream stream; struct StreamCacheItem *cached; cached = g_hash_table_lookup (get_streams (), CSPI_OBJREF (obj)); - if (cached) { - CORBA_long len_read; - stream = cached->stream; - if (stream != CORBA_OBJECT_NIL) { - guint8 *mem; - mem = bonobo_stream_client_read (stream, (size_t) nbytes, &len_read, cspi_ev ()); - if (mem) memcpy (buff, mem, len_read); - if (mem && ((nbytes == -1) || (len_read == nbytes))) - return TRUE; + if (cached) + { + CORBA_long len_read; + stream = cached->stream; + if (stream != CORBA_OBJECT_NIL) + { + guint8 *mem; + + mem = accessible_content_stream_client_read (stream, (size_t) nbytes, &len_read, cspi_ev ()); + cspi_return_val_if_ev ("read", FALSE); + if (mem) + { + memcpy (buff, mem, len_read); + g_free (mem); + if ((nbytes == -1) || (len_read == nbytes)) + return TRUE; + } + } } - } + else g_message ("no matching stream was opened..."); return FALSE; }