#include <libbonobo.h>
#include <cspi/spi-private.h>
-
-/* 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;
};
static GHashTable *streams = NULL;
-GHashTable *
+static GHashTable *
get_streams (void)
{
if (streams == NULL)
}
static CORBA_long
-accessible_bonobo_stream_client_seek (const Bonobo_Stream stream,
+accessible_content_stream_client_seek (const Accessibility_ContentStream stream,
CORBA_long offset,
- Bonobo_Stream_SeekType seek_type,
+ Accessibility_ContentStream_SeekType seek_type,
CORBA_Environment *opt_ev)
{
- Bonobo_StorageInfo *info;
CORBA_Environment *ev, temp_ev;
CORBA_long ret_offset;
} else
ev = opt_ev;
- ret_offset = Bonobo_Stream_seek (stream, offset, seek_type, ev);
+ ret_offset = Accessibility_ContentStream_seek (stream, offset, seek_type, ev);
if (BONOBO_EX (ev))
ret_offset = -1;
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)
*
* Increment the reference count for an #AccessibleStreamableContent object.
*
+ * @Since: AT-SPI 1.4
**/
void
AccessibleStreamableContent_ref (AccessibleStreamableContent *obj)
*
* Decrement the reference count for an #AccessibleStreamableContent object.
*
+ * @Since: AT-SPI 1.4
**/
void
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 **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]);
+ 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)
* 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.
*
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;
* 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.
*
* #AccessibleStreamableContent_open()) to seek to a particular offset in the
* stream.
*
+ * @Since: AT-SPI 1.4
+ *
* Returns: #TRUE if successful, #FALSE if unsuccessful.
*
**/
long int offset,
AccessibleStreamableContentSeekType seek_type)
{
- Bonobo_Stream stream;
+ Accessibility_ContentStream stream;
long int ret_offset = 0;
struct StreamCacheItem *cached;
- Bonobo_Stream_SeekType bonobo_seek_type;
+ 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)
{
- guint8 *mem;
switch (seek_type) {
case SPI_STREAM_SEEK_SET:
- bonobo_seek_type = Bonobo_Stream_SeekSet;
+ content_seek_type = Accessibility_ContentStream_SEEK_SET;
break;
case SPI_STREAM_SEEK_END:
- bonobo_seek_type = Bonobo_Stream_SeekEnd;
+ content_seek_type = Accessibility_ContentStream_SEEK_END;
break;
case SPI_STREAM_SEEK_CUR:
default:
- bonobo_seek_type = Bonobo_Stream_SeekCur;
+ content_seek_type = Accessibility_ContentStream_SEEK_CURRENT;
break;
}
- /* bonobo-client doesn't wrap seek yet, so we have to. */
- ret_offset = accessible_bonobo_stream_client_seek (stream, offset,
- seek_type, cspi_ev ());
+ ret_offset = accessible_content_stream_client_seek (stream, offset,
+ content_seek_type, cspi_ev ());
cspi_return_val_if_ev ("seek", FALSE);
}
}
* 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.
*
**/
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)
if (stream != CORBA_OBJECT_NIL)
{
guint8 *mem;
- mem = bonobo_stream_client_read (stream, (size_t) nbytes, &len_read, cspi_ev ());
+
+ mem = accessible_content_stream_client_read (stream, (size_t) nbytes, &len_read, cspi_ev ());
cspi_return_val_if_ev ("read", FALSE);
if (mem)
{
}
}
}
+ else g_message ("no matching stream was opened...");
return FALSE;
}