summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/kiro-sb.c171
-rw-r--r--src/kiro-sb.h163
2 files changed, 306 insertions, 28 deletions
diff --git a/src/kiro-sb.c b/src/kiro-sb.c
index 10a36b0..c0487e0 100644
--- a/src/kiro-sb.c
+++ b/src/kiro-sb.c
@@ -58,6 +58,9 @@ struct _KiroSbPrivate {
GThread *main_thread; // Main thread for the main_loop
GMainLoop *main_loop; // main_loop *duh*
guint close_signal; // Used to signal shutdown of the main_loop
+ gboolean freeze; // Allows to prevent auto-sync
+
+ GHookList callbacks; // List of registerd sync-callbacks
};
@@ -91,6 +94,8 @@ kiro_sb_init (KiroSb *self)
priv->trb = NULL;
priv->server = NULL;
priv->client = NULL;
+ priv->freeze = FALSE;
+ g_hook_list_init (&(priv->callbacks), sizeof (GHook));
}
@@ -99,22 +104,8 @@ kiro_sb_finalize (GObject *object)
{
g_return_if_fail (object != NULL);
KiroSb *self = KIRO_SB (object);
- KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
-
- if (priv->trb) {
- kiro_trb_purge (priv->trb, FALSE);
- kiro_trb_free (priv->trb);
- }
- if (priv->server)
- kiro_server_free (priv->server);
-
- if (priv->client)
- kiro_client_free (priv->client);
-
- priv->trb = NULL;
- priv->server = NULL;
- priv->client = NULL;
+ kiro_sb_stop (self);
G_OBJECT_CLASS (kiro_sb_parent_class)->finalize (object);
}
@@ -130,6 +121,44 @@ kiro_sb_class_init (KiroSbClass *klass)
}
+void
+kiro_sb_stop (KiroSb *self)
+{
+ g_return_if_fail (self != NULL);
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+
+ g_return_if_fail (priv->initialized != 0);
+
+ if (priv->initialized == 1) {
+ if (priv->server)
+ kiro_server_free (priv->server);
+ }
+
+ if (priv->initialized == 2) {
+ priv->close_signal = TRUE;
+ while (g_main_loop_is_running (priv->main_loop)) {}
+ g_thread_join (priv->main_thread);
+ g_thread_unref (priv->main_thread);
+ priv->main_thread = NULL;
+
+ if (priv->client)
+ kiro_client_free (priv->client);
+ }
+
+ g_hook_list_clear (&(priv->callbacks));
+
+ if (priv->trb) {
+ kiro_trb_purge (priv->trb, FALSE);
+ kiro_trb_free (priv->trb);
+ }
+
+ priv->trb = NULL;
+ priv->server = NULL;
+ priv->client = NULL;
+ priv->initialized = 0;
+}
+
+
gpointer
start_main_loop (GMainLoop *loop)
{
@@ -151,21 +180,43 @@ idle_func (KiroSbPrivate *priv)
return G_SOURCE_REMOVE;
}
+ if (TRUE == priv->freeze)
+ return G_SOURCE_CONTINUE;
+
struct KiroTrbInfo *header = (struct KiroTrbInfo *)kiro_trb_get_raw_buffer (priv->trb);
gulong old_offset = header->offset;
kiro_client_sync_partial (priv->client, 0, sizeof(struct KiroTrbInfo), 0);
kiro_trb_refresh (priv->trb);
- if (old_offset != header->offset) {
- g_debug ("Fetching new element");
- gulong offset = (gulong) (kiro_trb_get_element (priv->trb, -1) - kiro_trb_get_raw_buffer (priv->trb));
- kiro_client_sync_partial (priv->client, offset, kiro_trb_get_element_size (priv->trb), offset);
- /*INVOKE callback*/
+ if ((old_offset != header->offset) && 0 < header->offset) {
+ gulong offset = (gulong) (kiro_trb_get_element (priv->trb, 1) - kiro_trb_get_raw_buffer (priv->trb));
+ kiro_client_sync_partial (priv->client, offset, kiro_trb_get_element_size (priv->trb), offset);
+ g_hook_list_invoke_check (&(priv->callbacks), FALSE);
}
return G_SOURCE_CONTINUE;
}
+void
+kiro_sb_freeze (KiroSb *self)
+{
+ g_return_if_fail (self != NULL);
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+
+ priv->freeze = TRUE;
+}
+
+
+void
+kiro_sb_thaw (KiroSb *self)
+{
+ g_return_if_fail (self != NULL);
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+
+ priv->freeze = FALSE;
+}
+
+
gboolean
kiro_sb_serve (KiroSb *self, gulong size)
{
@@ -176,7 +227,7 @@ kiro_sb_serve (KiroSb *self, gulong size)
g_return_val_if_fail ((priv->trb = kiro_trb_new ()), FALSE);
- if (0 > kiro_trb_reshape (priv->trb, size, 3)) {
+ if (0 > kiro_trb_reshape (priv->trb, size, 2)) {
g_debug ("Failed to create KIRO ring buffer");
kiro_trb_free (priv->trb);
return FALSE;
@@ -200,6 +251,46 @@ kiro_sb_serve (KiroSb *self, gulong size)
}
+void *
+kiro_sb_get_data (KiroSb *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+ g_return_val_if_fail (priv->initialized != 2, NULL);
+
+ struct KiroTrbInfo *header = kiro_trb_get_raw_buffer (priv->trb);
+ if (header->offset > 1)
+ return kiro_trb_get_element (priv->trb, 1);
+ else
+ return kiro_trb_get_element (priv->trb, 0);
+}
+
+
+gboolean
+kiro_sb_push (KiroSb *self, void *data_in)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+ g_return_val_if_fail (priv->initialized != 1, FALSE);
+
+ return kiro_trb_push (priv->trb, data_in);
+}
+
+
+void *
+kiro_sb_push_dma (KiroSb *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+ g_return_val_if_fail (priv->initialized != 1, FALSE);
+
+ return kiro_trb_dma_push (priv->trb);
+}
+
+
gboolean
kiro_sb_clone (KiroSb *self, const gchar* address, const gchar* port)
{
@@ -225,11 +316,47 @@ kiro_sb_clone (KiroSb *self, const gchar* address, const gchar* port)
g_idle_add ((GSourceFunc)idle_func, priv);
priv->main_thread = g_thread_new ("KIRO SB Main Loop", (GThreadFunc)start_main_loop, priv->main_loop);
+ priv->initialized = 2;
return TRUE;
}
gulong
+kiro_sb_add_sync_callback (KiroSb *self, KiroSbSyncCallbackFunc func)
+{
+ g_return_val_if_fail (self != NULL, 0);
+
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+
+ GHook *new_hook = g_hook_alloc (&(priv->callbacks));
+ new_hook->data = self;
+ new_hook->func = (GHookCheckFunc)func;
+ g_hook_append (&(priv->callbacks), new_hook);
+ return new_hook->hook_id;
+}
+
+
+gboolean
+kiro_sb_remove_sync_callback (KiroSb *self, gulong hook_id)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+
+ return g_hook_destroy (&(priv->callbacks), hook_id);
+}
+
+
+void
+kiro_sb_clear_sync_callbacks (KiroSb *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ KiroSbPrivate *priv = KIRO_SB_GET_PRIVATE (self);
+
+ g_hook_list_clear (&(priv->callbacks));
+}
+
+
+gulong
kiro_sb_get_size (KiroSb *self)
{
g_return_val_if_fail (self != NULL, 0);
@@ -239,5 +366,3 @@ kiro_sb_get_size (KiroSb *self)
return kiro_trb_get_element_size (priv->trb);
}
-/* Privat functions */
-
diff --git a/src/kiro-sb.h b/src/kiro-sb.h
index 45fcf0c..a2f0148 100644
--- a/src/kiro-sb.h
+++ b/src/kiro-sb.h
@@ -74,7 +74,6 @@ struct _KiroSbClass {
*/
GType kiro_sb_get_type (void);
-
/**
* kiro_sb_new - Creates a new #KiroSb
* Returns: (transfer full): A pointer to a new #KiroSb
@@ -85,7 +84,6 @@ GType kiro_sb_get_type (void);
*/
KiroSb* kiro_sb_new (void);
-
/**
* kiro_sb_free - 'Destroys' the given #KiroSb
* @trb: (transfer none): The #KiroSb that is to be freed
@@ -101,6 +99,86 @@ KiroSb* kiro_sb_new (void);
*/
void kiro_sb_free (KiroSb *sb);
+/**
+ * kiro_sb_stop - Stops the #KiroSb and clears all internal memory
+ * @sb: (transfer none): The #KiroSb to stop
+ * Description:
+ * The given #KiroSb is stopped and all internal memory is cleared. It is put
+ * back into its initial state and it can be used as if it was just created
+ * See also:
+ * kiro_sb_new, kiro_sb_serve, kiro_sb_clone
+ */
+void kiro_sb_stop (KiroSb *sb);
+
+
+typedef gboolean KiroContinueFlag;
+#define KIRO_CALLBACK_CONTINUE TRUE
+#define KIRO_CALLBACK_REMOVE FALSE
+
+/**
+ * KiroSbSyncCallbackFunc - Function type for sync callbacks os a #KiroSb
+ * @sb: (transfer none): The #KiroSb which invoked this callback
+ * Returns: A #KiroContinueFlag
+ * Description:
+ * Defines the type of a callback function which will be invoked every time
+ * the #KiroSb syncs new data
+ * Note:
+ * Returning %FALSE or %KIRO_CALLBACK_REMOVE will automatically remove the callback
+ * from the internal callback list. Return %TRUE or %KIRO_CALLBACK_CONTINUE if you
+ * want to keep the callback active
+ * See also:
+ * kiro_sb_add_sync_callback, kiro_sb_remove_sync_callback, kiro_sb_clear_sync_callbacks
+ */
+typedef KiroContinueFlag (*KiroSbSyncCallbackFunc) (KiroSb *sb);
+
+/**
+ * kiro_sb_add_sync_callback - Add a sync callback to the #KiroSb
+ * @sb: (tranfer none): The #KiroSb to register this callback to
+ * @func: (transfer none): A function pointer to the callback function
+ * Returns: The internal id of the registerd callback
+ * Description:
+ * Adds a callback to the passed #KiroSbSyncCallbackFunc to this #KiroSb which
+ * will be invoked every time the #KiroSb syncs new data.
+ * Note:
+ * The sync callbacks will only be invoked on a 'clonig' #KiroSb. All
+ * registered callbacks will be invoked in the order they were added to the
+ * #KiroSb.
+ * See also:
+ * kiro_sb_remove_sync_callback, kiro_sb_clear_sync_callbacks
+ */
+gulong kiro_sb_add_sync_callback (KiroSb *sb, KiroSbSyncCallbackFunc callback);
+
+/**
+ * kiro_sb_remove_sync_callback - Remove a callback from the list
+ * @sb: (transfer none): The #KiroSb to remove the callback from
+ * @id: The id of the callback to be removed
+ * Returns: A #gboolean. %TRUE if the callback was found and removed. %FALSE
+ * otherwise
+ * Description:
+ * Removes the callback with the given @id from the internal list. If the
+ * callback with the given @id was not found %FALSE is returned. If the
+ * callback with the given @id was found, it will be removed from the callback
+ * list and %TRUE is returned
+ * Note:
+ * Any currently active callback will still finish before it is removed from
+ * the list.
+ * See also:
+ * kiro_sb_add_sync_callback, kiro_sb_clear_sync_callbacks
+ */
+gboolean kiro_sb_remove_sync_callback (KiroSb *sb, gulong id);
+
+/**
+ * kiro_sb_clear_sync_callbacks - Clear all sync callbacks
+ * @sb: (transfer none): The #KiroSb to perform this operation on
+ * Description:
+ * Removes all registerd callbacks from the internal list
+ * Note:
+ * Any currently active callbacks will still finish before they are removed
+ * from the list
+ * See also:
+ * kiro_sb_add_sync_callback, kiro_sb_remove_sync_callback
+ */
+void kiro_sb_clear_sync_callbacks (KiroSb *sb);
/**
* kiro_sb_serve - Allow remote KiroSbs to clone this buffers memory
@@ -109,16 +187,16 @@ void kiro_sb_free (KiroSb *sb);
* @size: Size in bytes of the content that will be served
* Description:
* Allows other remote #KiroSbs to connect to this #KiroSb and clone its
- * memory.
+ * memory. The internal memory is initially empty. Use the kiro_sb_push or
+ * kiro_sb_push_dma functions to update the served data.
* Note:
* A #KiroSb that already 'serves' its content can no longer clone
* other remote #KiroSbs.
* See also:
- *
+ * kiro_sb_push, kiro_sb_push_dma
*/
gboolean kiro_sb_serve (KiroSb *sb, gulong size);
-
/**
* kiro_sb_clone - Clone the content of a remote #KiroSb
* Returns: A gboolean. TRUE = connection successful. FALSE = connection failed.
@@ -152,6 +230,81 @@ gboolean kiro_sb_clone (KiroSb *sb, const gchar *address, const gchar *
*/
gulong kiro_sb_get_size (KiroSb *sb);
+/**
+ * kiro_sb_freeze - Stop auto syncing
+ * @sb: (transfer none): The #KiroSb to perform this operation on
+ * Description:
+ * Stops the given #KiroSb from automatically syncing.
+ * See also:
+ * kiro_sb_thaw
+ */
+void kiro_sb_freeze (KiroSb *sb);
+
+/**
+ * kiro_sb_thaw - Enable auto syncing
+ * @sb: (transfer none): The #KiroSb to perform this operation on
+ * Description:
+ * Enable the given #KiroSb automatic syncing.
+ * See also:
+ * kiro_sb_freeze
+ */
+void kiro_sb_thaw (KiroSb *sb);
+
+/**
+ * kiro_sb_get_data - Get a pointer to the stored data
+ * @sb: (transfer none) The #KiroSb to get the data from
+ * Returns: A void pointer the stored data
+ * Description:
+ * Returns a void pointer to the most current incarnation of the stored data.
+ * Data might either change by pushing (in case of a 'serving' #KiroSb) or
+ * after (automatic or manual) syncing (in case of a 'cloning' #KiroSb).
+ * Note:
+ * The returned pointer to the element might become invalid at any time by
+ * automatic or manual sync. Under no circumstances might the returned pointer
+ * be freed by the user. If you want to ensure access to the pointed-to data
+ * after a sync, you should use memcpy().
+ * See also:
+ * kiro_sb_freeze, kiro_sb_serve, kiro_sb_clone, kiro_sb_push,
+ * kiro_sb_push_dma
+ */
+void* kiro_sb_get_data (KiroSb *sb);
+
+/**
+ * kiro_sb_push - Push data into the memory
+ * @sb: (transfer none) The #KiroSb to get the data from
+ * @data: (transfer none) void pointer to copy data from
+ * Returns: %TRUE on success %FALSE in case of error
+ * Desciption:
+ * Updates the internal memory by memcopy()-ing the given element into it.
+ * This operation is only valid for 'serving' #KiroSb. Calling this function
+ * on a 'cloning' #KiroSb will allways return %FALSE.
+ * Note:
+ * The internal memcopy() will assume an element of the correct size (given
+ * with the initial call to kiro_sb_serve or returned by kiro_sb_get_size)
+ * See also:
+ * kiro_sb_get_size, kiro_sb_serve
+ */
+gboolean kiro_sb_push (KiroSb *sb, void *data);
+
+/**
+ * kiro_sb_push_dma - Push data into the memory using memory access
+ * @sb: (transfer none) The #KiroSb to get the data from
+ * Returns: A pointer to the memory where the new data should be stored
+ * Desciption:
+ * Returns a pointer where the new data should be stored.
+ * This operation is only valid for a 'serving' #KiroSb. Calling this
+ * function on a 'cloning' #KiroSb will allways return a %NULL pointer.
+ * Note:
+ * It is the users responsibility to ensure no more data is written to the
+ * pointed memory then was specified with the initial call to kiro_sb_serve or
+ * returned by kiro_sb_get_size. Under no circumstances might the returned
+ * pointer be freed by the user.
+ * See also:
+ * kiro_sb_get_size, kiro_sb_serve
+ */
+void* kiro_sb_push_dma (KiroSb *sb);
+
+
G_END_DECLS
#endif //__kiro_sb_H