|
Packit |
a4058c |
/* GdkPixbuf library
|
|
Packit |
a4058c |
* Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
|
|
Packit |
a4058c |
* 2005-2006 Eric Anholt <eric@anholt.net>
|
|
Packit |
a4058c |
* 2006-2007 Benjamin Otte <otte@gnome.org>
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* This library is free software; you can redistribute it and/or
|
|
Packit |
a4058c |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4058c |
* License as published by the Free Software Foundation; either
|
|
Packit |
a4058c |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
a4058c |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4058c |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4058c |
* Lesser General Public License for more details.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4058c |
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
a4058c |
*/
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
#include "config.h"
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
#include "gdk-pixbuf-buffer-queue-private.h"
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
#include <string.h>
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
struct _GdkPixbufBufferQueue
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
GSList * first_buffer; /* pointer to first buffer */
|
|
Packit |
a4058c |
GSList * last_buffer; /* pointer to last buffer (for fast appending) */
|
|
Packit |
a4058c |
gsize size; /* amount of bytes in the queue */
|
|
Packit |
a4058c |
gsize offset; /* amount of data already flushed out of the queue */
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
int ref_count;
|
|
Packit |
a4058c |
};
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* GdkPixbufBufferQueue:
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* A #GdkPixbufBufferQueue is a queue of continuous buffers that allows reading
|
|
Packit |
a4058c |
* its data in chunks of pre-defined sizes. It is used to transform a data
|
|
Packit |
a4058c |
* stream that was provided by buffers of random sizes to buffers of the right
|
|
Packit |
a4058c |
* size.
|
|
Packit |
a4058c |
*/
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_new:
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Creates a new empty buffer queue.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns: a new buffer queue. Use gdk_pixbuf_buffer_queue_unref () to free it.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
GdkPixbufBufferQueue *
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_new (void)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
GdkPixbufBufferQueue *buffer_queue;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
buffer_queue = g_new0 (GdkPixbufBufferQueue, 1);
|
|
Packit |
a4058c |
buffer_queue->ref_count = 1;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
return buffer_queue;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_get_size:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns the number of bytes currently in @queue.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns: amount of bytes in @queue.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
gsize
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_get_size (GdkPixbufBufferQueue *queue)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
g_return_val_if_fail (queue != NULL, 0);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
return queue->size;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_get_offset:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Queries the amount of bytes that has already been pulled out of
|
|
Packit |
a4058c |
* @queue using functions like gdk_pixbuf_buffer_queue_pull().
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns: Number of bytes that were already pulled from this queue.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
gsize
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_get_offset (GdkPixbufBufferQueue * queue)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
g_return_val_if_fail (queue != NULL, 0);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
return queue->offset;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_flush:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
* @n_bytes: amount of bytes to flush from the queue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Removes the first @n_bytes bytes from the queue.
|
|
Packit |
a4058c |
*/
|
|
Packit |
a4058c |
void
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_flush (GdkPixbufBufferQueue *queue, gsize n_bytes)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
g_return_if_fail (queue != NULL);
|
|
Packit |
a4058c |
g_return_if_fail (n_bytes <= queue->size);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
queue->size -= n_bytes;
|
|
Packit |
a4058c |
queue->offset += n_bytes;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
while (n_bytes > 0)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
GBytes *bytes;
|
|
Packit |
a4058c |
gsize size;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
bytes = queue->first_buffer->data;
|
|
Packit |
a4058c |
size = g_bytes_get_size (bytes);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
if (size <= n_bytes)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
n_bytes -= size;
|
|
Packit |
a4058c |
queue->first_buffer = g_slist_remove (queue->first_buffer, bytes);
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
else
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
queue->first_buffer->data = g_bytes_new_from_bytes (bytes,
|
|
Packit |
a4058c |
n_bytes,
|
|
Packit |
a4058c |
size - n_bytes);
|
|
Packit |
a4058c |
n_bytes = 0;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
g_bytes_unref (bytes);
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
if (queue->first_buffer == NULL)
|
|
Packit |
a4058c |
queue->last_buffer = NULL;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_clear:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Resets @queue into to initial state. All buffers it contains will be
|
|
Packit |
a4058c |
* released and the offset will be reset to 0.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
void
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_clear (GdkPixbufBufferQueue *queue)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
g_return_if_fail (queue != NULL);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
g_slist_free_full (queue->first_buffer, (GDestroyNotify) g_bytes_unref);
|
|
Packit |
a4058c |
queue->first_buffer = NULL;
|
|
Packit |
a4058c |
queue->last_buffer = NULL;
|
|
Packit |
a4058c |
queue->size = 0;
|
|
Packit |
a4058c |
queue->offset = 0;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_push:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
* @bytes: #GBytes to append to @queue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Appends the given @bytes to the buffers already in @queue. This function
|
|
Packit |
a4058c |
* will take ownership of the given @buffer. Use g_bytes_ref () before
|
|
Packit |
a4058c |
* calling this function to keep a reference.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
void
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_push (GdkPixbufBufferQueue *queue,
|
|
Packit |
a4058c |
GBytes *bytes)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
gsize size;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
g_return_if_fail (queue != NULL);
|
|
Packit |
a4058c |
g_return_if_fail (bytes != NULL);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
size = g_bytes_get_size (bytes);
|
|
Packit |
a4058c |
if (size == 0)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
g_bytes_unref (bytes);
|
|
Packit |
a4058c |
return;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
queue->last_buffer = g_slist_append (queue->last_buffer, bytes);
|
|
Packit |
a4058c |
if (queue->first_buffer == NULL)
|
|
Packit |
a4058c |
queue->first_buffer = queue->last_buffer;
|
|
Packit |
a4058c |
else
|
|
Packit |
a4058c |
queue->last_buffer = queue->last_buffer->next;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
queue->size += size;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_peek:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue to read from
|
|
Packit |
a4058c |
* @length: amount of bytes to peek
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Creates a new buffer with the first @length bytes from @queue, but unlike
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_pull(), does not remove them from @queue.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns: NULL if the requested amount of data wasn't available or a new
|
|
Packit |
a4058c |
* #GBytes. Use g_bytes_unref() after use.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
GBytes *
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_peek (GdkPixbufBufferQueue *queue,
|
|
Packit |
a4058c |
gsize length)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
GSList *g;
|
|
Packit |
a4058c |
GBytes *result, *bytes;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
g_return_val_if_fail (queue != NULL, NULL);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
if (queue->size < length)
|
|
Packit |
a4058c |
return NULL;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/* need to special case here, because the queue may be empty */
|
|
Packit |
a4058c |
if (length == 0)
|
|
Packit |
a4058c |
return g_bytes_new (NULL, 0);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
g = queue->first_buffer;
|
|
Packit |
a4058c |
bytes = g->data;
|
|
Packit |
a4058c |
if (g_bytes_get_size (bytes) == length)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
result = g_bytes_ref (bytes);
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
else if (g_bytes_get_size (bytes) > length)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
result = g_bytes_new_from_bytes (bytes, 0, length);
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
else
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
guchar *data;
|
|
Packit |
a4058c |
gsize amount, offset;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
data = g_malloc (length);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
for (offset = 0; offset < length; offset += amount)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
bytes = g->data;
|
|
Packit |
a4058c |
amount = MIN (length - offset, g_bytes_get_size (bytes));
|
|
Packit |
a4058c |
memcpy (data + offset, g_bytes_get_data (bytes, NULL), amount);
|
|
Packit |
a4058c |
g = g->next;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
result = g_bytes_new_take (data, length);
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
return result;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_pull:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
* @length: amount of bytes to pull
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* If enough data is still available in @queue, the first @length bytes are
|
|
Packit |
a4058c |
* put into a new buffer and that buffer is returned. The @length bytes are
|
|
Packit |
a4058c |
* removed from the head of the queue. If not enough data is available, %NULL
|
|
Packit |
a4058c |
* is returned.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns: a new #GBytes or %NULL
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
GBytes *
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_pull (GdkPixbufBufferQueue * queue, gsize length)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
GBytes *result;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
g_return_val_if_fail (queue != NULL, NULL);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
result = gdk_pixbuf_buffer_queue_peek (queue, length);
|
|
Packit |
a4058c |
if (result == NULL)
|
|
Packit |
a4058c |
return NULL;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_flush (queue, length);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
return result;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_peek_buffer:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Gets the first buffer out of @queue and returns it. This function is
|
|
Packit |
a4058c |
* equivalent to calling gdk_pixbuf_buffer_queue_peek() with the size of the
|
|
Packit |
a4058c |
* first buffer in it.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns: The first buffer in @queue or %NULL if @queue is empty. Use
|
|
Packit |
a4058c |
* g_bytes_unref() after use.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
GBytes *
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_peek_buffer (GdkPixbufBufferQueue * queue)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
GBytes *bytes;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
g_return_val_if_fail (queue != NULL, NULL);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
if (queue->first_buffer == NULL)
|
|
Packit |
a4058c |
return NULL;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
bytes = queue->first_buffer->data;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
return g_bytes_ref (bytes);
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_pull_buffer:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Pulls the first buffer out of @queue and returns it. This function is
|
|
Packit |
a4058c |
* equivalent to calling gdk_pixbuf_buffer_queue_pull() with the size of the
|
|
Packit |
a4058c |
* first buffer in it.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns: The first buffer in @queue or %NULL if @queue is empty.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
GBytes *
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_pull_buffer (GdkPixbufBufferQueue *queue)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
GBytes *bytes;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
g_return_val_if_fail (queue != NULL, NULL);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
bytes = gdk_pixbuf_buffer_queue_peek_buffer (queue);
|
|
Packit |
a4058c |
if (bytes)
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_flush (queue, g_bytes_get_size (bytes));
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
return bytes;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_ref:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* increases the reference count of @queue by one.
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Returns: The passed in @queue.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
GdkPixbufBufferQueue *
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_ref (GdkPixbufBufferQueue * queue)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
g_return_val_if_fail (queue != NULL, NULL);
|
|
Packit |
a4058c |
g_return_val_if_fail (queue->ref_count > 0, NULL);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
queue->ref_count++;
|
|
Packit |
a4058c |
return queue;
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
/**
|
|
Packit |
a4058c |
* gdk_pixbuf_buffer_queue_unref:
|
|
Packit |
a4058c |
* @queue: a #GdkPixbufBufferQueue
|
|
Packit |
a4058c |
*
|
|
Packit |
a4058c |
* Decreases the reference count of @queue by one. If no reference
|
|
Packit |
a4058c |
* to this buffer exists anymore, the buffer and the memory
|
|
Packit |
a4058c |
* it manages are freed.
|
|
Packit |
a4058c |
**/
|
|
Packit |
a4058c |
void
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_unref (GdkPixbufBufferQueue * queue)
|
|
Packit |
a4058c |
{
|
|
Packit |
a4058c |
g_return_if_fail (queue != NULL);
|
|
Packit |
a4058c |
g_return_if_fail (queue->ref_count > 0);
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
queue->ref_count--;
|
|
Packit |
a4058c |
if (queue->ref_count > 0)
|
|
Packit |
a4058c |
return;
|
|
Packit |
a4058c |
|
|
Packit |
a4058c |
gdk_pixbuf_buffer_queue_clear (queue);
|
|
Packit |
a4058c |
g_free (queue);
|
|
Packit |
a4058c |
}
|
|
Packit |
a4058c |
|