/* $Id$ */ /* * Cantus Tag Editor * Copyright © 2002-2004 by Samuel Abels * Copyright © 2007 by Tim Huetz * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see **/ #ifdef HAVE_CONFIG_H # include #endif #include //#define _DEBUG_ /****************************************************************************** * Constructor/Destructor ******************************************************************************/ /* Constructor. */ EventBus::EventBus(void) { idpool = 0; listeners = NULL; } /* Destructor. */ EventBus::~EventBus(void) { // Destroy all listeners. GList *item = listeners; while (item) { EventBusListener *listener = (EventBusListener*)item->data; g_assert(listener != NULL); if (listener->closure) g_closure_unref(listener->closure); delete listener; item = item->next; } g_list_free(listeners); } /****************************************************************************** * Public ******************************************************************************/ /* Registers a listener for a specific event pattern; use the returned * id to unregister the listener. The function to be called is passed as a * GClosure. */ glong EventBus::add_listener(const gchar *event_pattern, GClosure *closure) { #ifdef _DEBUG_ std::cout << "EventBus::add_listener(): " << event_pattern << "\n"; #endif EventBusListener *listener = new EventBusListener; g_closure_ref(closure); g_assert(++idpool > 0); // Idpool exceeded? listener->id = idpool; listener->invalid = FALSE; listener->pattern = event_pattern; listener->type = EVENTBUS_SIG_GCLOSURE; listener->closure = closure; listeners = g_list_append(listeners, listener); return(idpool); } /* Registers a listener for a specific event pattern; use the returned * id to unregister the listener. The function to be called is a SigC slot. */ glong EventBus::add_listener_sigc(const gchar *event_pattern, sigc::slot1 slot) { #ifdef _DEBUG_ std::cout << "EventBus::add_listener_sigc(): " << event_pattern << "\n"; #endif EventBusListener *listener = new EventBusListener; g_assert(++idpool > 0); // Idpool exceeded? listener->id = idpool; listener->invalid = FALSE; listener->pattern = event_pattern; listener->type = EVENTBUS_SIG_SIGC; listener->closure = NULL; listener->sigcslot = slot; listeners = g_list_append(listeners, listener); #ifdef _DEBUG_ printf("EventBus::add_listener_sigc(): ID%i.\n", idpool); #endif return(idpool); } /* Invalidate the listener with the given id. */ void EventBus::remove_listener(glong id) { #ifdef _DEBUG_ printf("EventBus::remove_listener(): ID%i.\n", id); #endif GList *item = listeners; while (item) { EventBusListener *listener = (EventBusListener*)item->data; g_assert(listener != NULL); if (listener->id == id) { listener->invalid = TRUE; return; } item = item->next; } g_assert("Specified listener not found.\n"); } /* Unregister all invalid listeners. */ void EventBus::delete_invalid_listeners(void) { #ifdef _DEBUG_ printf("EventBus::delete_invalid_listeners(): Called.\n"); #endif GList *item = listeners; while (item) { EventBusListener *listener = (EventBusListener*)item->data; g_assert(listener != NULL); if (listener->invalid) { listeners = g_list_remove(listeners, listener); if (listener->closure) g_closure_unref(listener->closure); delete listener; return; } item = item->next; } g_assert("Specified listener not found.\n"); } /* Emits an event in the bus. */ void EventBus::emit_event(const gchar *event, const GValue *value) { #ifdef _DEBUG_ printf("EventBus::emit_event(): Called. (%s).\n", event); #endif GValue ret_val = {0, }; GList *item = listeners; g_value_init(&ret_val, G_TYPE_POINTER); while (item) { EventBusListener *listener = (EventBusListener*)item->data; g_assert(listener != NULL); // Check whether the listener is still valid. if (listener->invalid) { item = item->next; continue; } // Check whether the listener matches the pattern. if (!shellpattern_match(event, listener->pattern, TRUE)) { item = item->next; continue; } // Invoke the listener function. switch (listener->type) { case EVENTBUS_SIG_GCLOSURE: g_closure_invoke(listener->closure, &ret_val, 1, value, NULL); break; case EVENTBUS_SIG_SIGC: listener->sigcslot(g_value_peek_pointer(value)); break; default: g_assert_not_reached(); break; } item = item->next; } g_value_unset(&ret_val); } /* Emits an event in the bus, convenience wrapper. */ void EventBus::emit_event_with_pointer(const gchar *event, gpointer value) { GValue arg = {0, }; g_value_init(&arg, G_TYPE_POINTER); g_value_set_pointer(&arg, value); this->emit_event(event, &arg); g_value_unset(&arg); } /* Emits an event in the bus, convenience wrapper. */ void EventBus::emit_event_with_char(const gchar *event, const gchar *value) { GValue arg = {0, }; g_value_init(&arg, G_TYPE_POINTER); g_value_set_pointer(&arg, (gpointer)value); this->emit_event(event, &arg); g_value_unset(&arg); } /* Emits an event in the bus, convenience wrapper. */ void EventBus::emit_event_with_int(const gchar *event, gint value) { GValue arg = {0, }; g_value_init(&arg, G_TYPE_INT); g_value_set_int(&arg, value); this->emit_event(event, &arg); g_value_unset(&arg); }