Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
hook.c
Go to the documentation of this file.
00001 /*
00002  * hook.c
00003  * Copyright 2011 John Lindgren
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice,
00009  *    this list of conditions, and the following disclaimer.
00010  *
00011  * 2. Redistributions in binary form must reproduce the above copyright notice,
00012  *    this list of conditions, and the following disclaimer in the documentation
00013  *    provided with the distribution.
00014  *
00015  * This software is provided "as is" and without any warranty, express or
00016  * implied. In no event shall the authors be liable for any damages arising from
00017  * the use of this software.
00018  */
00019 
00020 #include <glib.h>
00021 #include <pthread.h>
00022 #include <string.h>
00023 
00024 #include "config.h"
00025 #include "core.h"
00026 #include "hook.h"
00027 
00028 typedef struct {
00029     HookFunction func;
00030     void * user;
00031 } HookItem;
00032 
00033 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
00034 static GHashTable * hooks;
00035 
00036 /* str_unref() may be a macro */
00037 static void str_unref_cb (void * str)
00038 {
00039     str_unref (str);
00040 }
00041 
00042 EXPORT void hook_associate (const char * name, HookFunction func, void * user)
00043 {
00044     pthread_mutex_lock (& mutex);
00045 
00046     if (! hooks)
00047         hooks = g_hash_table_new_full (g_str_hash, g_str_equal, str_unref_cb, NULL);
00048 
00049     HookItem * item = g_slice_new (HookItem);
00050     item->func = func;
00051     item->user = user;
00052 
00053     GList * items = g_hash_table_lookup (hooks, name);
00054     items = g_list_prepend (items, item);
00055     g_hash_table_insert (hooks, str_get (name), items);
00056 
00057     pthread_mutex_unlock (& mutex);
00058 }
00059 
00060 EXPORT void hook_dissociate_full (const char * name, HookFunction func, void * user)
00061 {
00062     pthread_mutex_lock (& mutex);
00063 
00064     if (! hooks)
00065         goto DONE;
00066 
00067     GList * items = g_hash_table_lookup (hooks, name);
00068 
00069     GList * node = items;
00070     while (node)
00071     {
00072         HookItem * item = node->data;
00073         GList * next = node->next;
00074 
00075         if (item->func == func && (! user || item->user == user))
00076         {
00077             items = g_list_delete_link (items, node);
00078             g_slice_free (HookItem, item);
00079         }
00080 
00081         node = next;
00082     }
00083 
00084     if (items)
00085         g_hash_table_insert (hooks, str_get (name), items);
00086     else
00087         g_hash_table_remove (hooks, name);
00088 
00089 DONE:
00090     pthread_mutex_unlock (& mutex);
00091 }
00092 
00093 EXPORT void hook_call (const char * name, void * data)
00094 {
00095     pthread_mutex_lock (& mutex);
00096 
00097     if (! hooks)
00098         goto DONE;
00099 
00100     GList * node = g_hash_table_lookup (hooks, name);
00101 
00102     for (; node; node = node->next)
00103     {
00104         HookItem * item = node->data;
00105         item->func (data, item->user);
00106     }
00107 
00108 DONE:
00109     pthread_mutex_unlock (& mutex);
00110 }