From 1827f1ab9bf44490cf24779e0eab8533845b4a77 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 29 Jun 2013 21:46:10 +0200 Subject: New inter-thread message system. --- lv2/lv2_gui.cc | 2 +- plugingui/Makefile.am | 4 +- plugingui/plugingui.cc | 179 ++++++++++++++++--------------------- plugingui/plugingui.h | 10 +-- src/Makefile.am | 4 + src/Makefile.am.drumgizmo | 2 + src/drumgizmo.cc | 219 ++++++++++++++++------------------------------ src/drumgizmo.h | 44 ++-------- src/drumkitloader.cc | 2 +- src/message.h | 19 ++++ src/messagehandler.cc | 88 +++++++++++++++++++ src/messagehandler.h | 66 ++++++++++++++ src/messagereceiver.cc | 79 +++++++++++++++++ src/messagereceiver.h | 74 ++++++++++++++++ 14 files changed, 496 insertions(+), 296 deletions(-) create mode 100644 src/messagehandler.cc create mode 100644 src/messagehandler.h create mode 100644 src/messagereceiver.cc create mode 100644 src/messagereceiver.h diff --git a/lv2/lv2_gui.cc b/lv2/lv2_gui.cc index 7d9cfbf..7b56c5b 100644 --- a/lv2/lv2_gui.cc +++ b/lv2/lv2_gui.cc @@ -190,7 +190,7 @@ static LV2UI_Handle ui_instantiate(const struct _LV2UI_Descriptor * descriptor, pt->virt.run = ui_run; pt->virt.show = ui_show; pt->virt.hide = ui_hide; - pt->gui = new PluginGUI(pt->instance); + pt->gui = new PluginGUI(); pt->gui->setWindowClosedCallback(closeHandler, pt); *widget = (LV2UI_Widget)pt; diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am index aee2de6..fed12fc 100644 --- a/plugingui/Makefile.am +++ b/plugingui/Makefile.am @@ -15,7 +15,9 @@ plugingui_CFLAGS = $(plugingui_CXXFLAGS) plugingui_SOURCES = \ $(PLUGIN_GUI_SOURCES) \ $(top_srcdir)/src/thread.cc \ - $(top_srcdir)/src/semaphore.cc + $(top_srcdir)/src/semaphore.cc \ + $(top_srcdir)/src/mutex.cc \ + $(top_srcdir)/src/messagehandler.cc rcgen_SOURCES = rcgen.cc diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index 9de7c94..a4f99d7 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -30,31 +30,10 @@ #include #include "knob.h" - #include "verticalline.h" +#include "../version.h" -#ifndef STANDALONE -#include -#include "../src/configuration.h" -#else -#include "../src/message.h" -class DrumGizmo { -public: - bool loadkit(std::string) { return true; } - bool init(bool) { return true; } - std::string drumkitfile() { return ""; } - std::string midimapfile; - Message *receiveGUIMessage() { return NULL; } - Message *peekGUIMessage() { return NULL; } - void sendEngineMessage(Message *msg) { delete msg; } -}; - -namespace Conf { - bool enable_velocity_modifier; - float velocity_modifier_weight; - float velocity_modifier_falloff; -}; -#endif +#include "messagehandler.h" static void checkClick(void *ptr) { @@ -63,7 +42,7 @@ static void checkClick(void *ptr) ChangeSettingMessage *msg = new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, gui->check->checked()); - gui->drumgizmo->sendEngineMessage(msg); + msghandler.sendMessage(MSGRCV_ENGINE, msg); } static void knobChange(void *ptr) @@ -73,7 +52,8 @@ static void knobChange(void *ptr) ChangeSettingMessage *msg = new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, gui->knob->value()); - gui->drumgizmo->sendEngineMessage(msg); + + msghandler.sendMessage(MSGRCV_ENGINE, msg); #ifdef STANDALONE int i = gui->knob->value() * 4; @@ -94,7 +74,7 @@ static void knobChange2(void *ptr) ChangeSettingMessage *msg = new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, gui->knob2->value()); - gui->drumgizmo->sendEngineMessage(msg); + msghandler.sendMessage(MSGRCV_ENGINE, msg); #ifdef STANDALONE gui->progress->setProgress(gui->knob2->value()); @@ -116,16 +96,8 @@ static void selectKitFile(void *ptr, std::string filename) LoadDrumKitMessage *msg = new LoadDrumKitMessage(); msg->drumkitfile = drumkit; - gui->drumgizmo->sendEngineMessage(msg); - /* - if(!gui->drumgizmo || - !gui->drumgizmo->loadkit(drumkit) || - !gui->drumgizmo->init(true)) { - gui->progress->setState(GUI::ProgressBar::red); - } else { - gui->progress->setState(GUI::ProgressBar::blue); - } - */ + + msghandler.sendMessage(MSGRCV_ENGINE, msg); } static void kitBrowseClick(void *ptr) @@ -151,7 +123,7 @@ static void selectMapFile(void *ptr, std::string filename) LoadMidimapMessage *msg = new LoadMidimapMessage(); msg->midimapfile = midimap; - gui->drumgizmo->sendEngineMessage(msg); + msghandler.sendMessage(MSGRCV_ENGINE, msg); /* if(gui->changeMidimapHandler) @@ -180,15 +152,12 @@ void closeClick(void *ptr) } */ -#include "../version.h" - -PluginGUI::PluginGUI(DrumGizmo *drumgizmo) +PluginGUI::PluginGUI() + : MessageReceiver(MSGRCV_UI) { windowClosedHandler = NULL; changeMidimapHandler = NULL; - this->drumgizmo = drumgizmo; - window = NULL; running = true; @@ -216,13 +185,67 @@ void PluginGUI::stopThread() } } + +void PluginGUI::handleMessage(Message *msg) +{ + switch(msg->type()) { + case Message::LoadStatus: + { + LoadStatusMessage *ls = (LoadStatusMessage*)msg; + progress->setProgress((float)ls->numer_of_files_loaded / + (float)ls->number_of_files); + if(ls->numer_of_files_loaded == ls->number_of_files) { + progress->setState(GUI::ProgressBar::green); + } + } + break; + case Message::LoadStatusMidimap: + { + LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg; + progress2->setProgress(1); + if(ls->success) { + progress2->setState(GUI::ProgressBar::green); + } else { + progress2->setState(GUI::ProgressBar::red); + } + } + break; + case Message::EngineSettingsMessage: + { + EngineSettingsMessage *settings = (EngineSettingsMessage *)msg; + lineedit->setText(settings->drumkitfile); + if(settings->drumkit_loaded) { + progress->setProgress(1); + progress->setState(GUI::ProgressBar::green); + } else { + progress->setProgress(0); + progress->setState(GUI::ProgressBar::blue); + } + lineedit2->setText(settings->midimapfile); + if(settings->midimap_loaded) { + progress2->setProgress(1); + progress2->setState(GUI::ProgressBar::green); + } else { + progress2->setProgress(0); + progress2->setState(GUI::ProgressBar::blue); + } + check->setChecked(settings->enable_velocity_modifier); + knob->setValue(settings->velocity_modifier_weight); + knob2->setValue(settings->velocity_modifier_falloff); + + } + default: + break; + } +} + void PluginGUI::thread_main() { init(); { // Request all engine settings EngineSettingsMessage *msg = new EngineSettingsMessage(); - drumgizmo->sendEngineMessage(msg); + msghandler.sendMessage(MSGRCV_ENGINE, msg); } while(1) { @@ -235,67 +258,7 @@ void PluginGUI::thread_main() if(!running) break; window->eventHandler()->processEvents(); - - Message *msg; - if((msg = drumgizmo->receiveGUIMessage()) != NULL) { - switch(msg->type()) { - case Message::LoadStatus: - { - Message *pmsg; - while( (pmsg = drumgizmo->peekGUIMessage()) != NULL) { - if(pmsg->type() != Message::LoadStatus) break; - delete msg; - msg = drumgizmo->receiveGUIMessage(); - } - LoadStatusMessage *ls = (LoadStatusMessage*)msg; - progress->setProgress((float)ls->numer_of_files_loaded / - (float)ls->number_of_files); - if(ls->numer_of_files_loaded == ls->number_of_files) { - progress->setState(GUI::ProgressBar::green); - } - } - break; - case Message::LoadStatusMidimap: - { - LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg; - progress2->setProgress(1); - if(ls->success) { - progress2->setState(GUI::ProgressBar::green); - } else { - progress2->setState(GUI::ProgressBar::red); - } - } - break; - case Message::EngineSettingsMessage: - { - EngineSettingsMessage *settings = (EngineSettingsMessage *)msg; - lineedit->setText(settings->drumkitfile); - if(settings->drumkit_loaded) { - progress->setProgress(1); - progress->setState(GUI::ProgressBar::green); - } else { - progress->setProgress(0); - progress->setState(GUI::ProgressBar::blue); - } - lineedit2->setText(settings->midimapfile); - if(settings->midimap_loaded) { - progress2->setProgress(1); - progress2->setState(GUI::ProgressBar::green); - } else { - progress2->setProgress(0); - progress2->setState(GUI::ProgressBar::blue); - } - check->setChecked(settings->enable_velocity_modifier); - knob->setValue(settings->velocity_modifier_weight); - knob2->setValue(settings->velocity_modifier_falloff); - - } - default: - break; - } - - delete msg; - } + handleMessages(); } deinit(); @@ -500,6 +463,12 @@ void PluginGUI::setWindowClosedCallback(void (*handler)(void *), void *ptr) #ifdef STANDALONE +class Engine : public MessageHandler { +public: + void handleMessage(Message *msg) {} +}; + + void stop(void *ptr) { DEBUG(stop, "Stopping...\n"); @@ -524,7 +493,7 @@ int main() bool running = true; - PluginGUI gui(NULL); + PluginGUI gui; gui.setWindowClosedCallback(stop, &running); // gui.show(); diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index 97e45b8..cd050de 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -42,11 +42,11 @@ #include "thread.h" #include "semaphore.h" -class DrumGizmo; +#include "messagereceiver.h" -class PluginGUI : public Thread { +class PluginGUI : public Thread, public MessageReceiver { public: - PluginGUI(DrumGizmo *drumgizmo); + PluginGUI(); ~PluginGUI(); void thread_main(); @@ -60,14 +60,14 @@ public: void processEvents(); void setWindowClosedCallback(void (*handler)(void *), void *ptr); + void handleMessage(Message *msg); + //private: GUI::Window *window; GUI::EventHandler *eventhandler; GUI::FileBrowser *filebrowser; - DrumGizmo *drumgizmo; - GUI::CheckBox *check; GUI::Knob *knob; GUI::Knob *knob2; diff --git a/src/Makefile.am b/src/Makefile.am index 35d052b..75c209c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,6 +16,8 @@ EXTRA_DIST = \ instrument.h \ instrumentparser.h \ message.h \ + messagehandler.h \ + messagereceiver.h \ midimapparser.h \ midimapper.h \ mutex.h \ @@ -42,6 +44,8 @@ EXTRA_DIST = \ events.cc \ instrument.cc \ instrumentparser.cc \ + messagehandler.cc \ + messagereceiver.cc \ midimapparser.cc \ midimapper.cc \ mutex.cc \ diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo index 428d2a7..b1ad862 100644 --- a/src/Makefile.am.drumgizmo +++ b/src/Makefile.am.drumgizmo @@ -11,6 +11,8 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/events.cc \ $(top_srcdir)/src/instrument.cc \ $(top_srcdir)/src/instrumentparser.cc \ + $(top_srcdir)/src/messagehandler.cc \ + $(top_srcdir)/src/messagereceiver.cc \ $(top_srcdir)/src/midimapparser.cc \ $(top_srcdir)/src/midimapper.cc \ $(top_srcdir)/src/mutex.cc \ diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index b6ac98f..135975d 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -41,7 +41,8 @@ #include "configuration.h" DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i) - : loader(this), oe(o), ie(i) + : MessageReceiver(MSGRCV_ENGINE), + loader(this), oe(o), ie(i) { loader.run(); // Start drumkit loader thread. } @@ -59,78 +60,6 @@ DrumGizmo::~DrumGizmo() loader.stop(); } -/* - * Add a message to the GUI message queue. - */ -void DrumGizmo::sendGUIMessage(Message *msg) -{ - MutexAutolock l(gui_message_mutex); - gui_message_queue.push_back(msg); -} - -/* - * Receive message from the engine. The caller takes over the memory. - */ -Message *DrumGizmo::receiveGUIMessage() -{ - MutexAutolock l(gui_message_mutex); - Message *msg = NULL; - if(gui_message_queue.size()) { - msg = gui_message_queue.front(); - gui_message_queue.pop_front(); - } - return msg; -} - -/* - * Receive message from the engine without removing it from the queue. - */ -Message *DrumGizmo::peekGUIMessage() -{ - MutexAutolock l(gui_message_mutex); - Message *msg = NULL; - if(gui_message_queue.size()) { - msg = gui_message_queue.front(); - } - return msg; -} - -/* - * Add a message to the GUI message queue. - */ -void DrumGizmo::sendEngineMessage(Message *msg) -{ - MutexAutolock l(engine_message_mutex); - engine_message_queue.push_back(msg); -} - -/* - * Receive message from the engine. The caller takes over the memory. - */ -Message *DrumGizmo::receiveEngineMessage() -{ - MutexAutolock l(engine_message_mutex); - Message *msg = NULL; - if(engine_message_queue.size()) { - msg = engine_message_queue.front(); - engine_message_queue.pop_front(); - } - return msg; -} - -/* - * Receive message from the engine without removing it from the queue. - */ -Message *DrumGizmo::peekEngineMessage() -{ - MutexAutolock l(engine_message_mutex); - Message *msg = NULL; - if(engine_message_queue.size()) { - msg = engine_message_queue.front(); - } - return msg; -} - std::string DrumGizmo::drumkitfile() { return kitfile; @@ -181,86 +110,88 @@ bool DrumGizmo::init(bool preload) return true; } -void DrumGizmo::handleEngineEvents() +void DrumGizmo::handleMessage(Message *msg) { - Message *msg = receiveEngineMessage(); - if(msg) { - DEBUG(msg, "got message."); - switch(msg->type()) { - case Message::LoadDrumKit: - { - DEBUG(msg, "got LoadDrumKitMessage message."); - LoadDrumKitMessage *m = (LoadDrumKitMessage*)msg; - loadkit(m->drumkitfile); - //init(true); - } - break; - case Message::LoadMidimap: - DEBUG(msg, "got LoadMidimapMessage message."); - if(!ie->isMidiEngine()) break; - { + DEBUG(msg, "got message."); + switch(msg->type()) { + case Message::RegisterUIMessage: + { + DEBUG(msg, "got RegisterUIMessage message."); + RegisterUIMessage *m = (RegisterUIMessage*)msg; + ui = m->messagehandler; + } + break; + case Message::LoadDrumKit: + { + DEBUG(msg, "got LoadDrumKitMessage message."); + LoadDrumKitMessage *m = (LoadDrumKitMessage*)msg; + loadkit(m->drumkitfile); + //init(true); + } + break; + case Message::LoadMidimap: + DEBUG(msg, "got LoadMidimapMessage message."); + if(!ie->isMidiEngine()) break; + { + AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; + LoadMidimapMessage *m = (LoadMidimapMessage*)msg; + bool ret = aim->loadMidiMap(m->midimapfile, kit.instruments); + + LoadStatusMessageMidimap *ls = new LoadStatusMessageMidimap(); + ls->success = ret; + msghandler.sendMessage(MSGRCV_UI, ls); + } + break; + case Message::EngineSettingsMessage: + { + DEBUG(msg, "--------------- Send: EngineSettingsMessage ------------ \n"); + + bool mmap_loaded = false; + std::string mmapfile; + if(ie->isMidiEngine()) { AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; - LoadMidimapMessage *m = (LoadMidimapMessage*)msg; - bool ret = aim->loadMidiMap(m->midimapfile, kit.instruments); - - LoadStatusMessageMidimap *ls = new LoadStatusMessageMidimap(); - ls->success = ret; - sendGUIMessage(ls); - } - break; - case Message::EngineSettingsMessage: - { - DEBUG(msg, "--------------- Send: EngineSettingsMessage --------------- \n"); - - bool mmap_loaded = false; - std::string mmapfile; - if(ie->isMidiEngine()) { - AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; - mmapfile = aim->midimapFile(); - mmap_loaded = aim->isValid(); - - } - - EngineSettingsMessage *msg = new EngineSettingsMessage(); - msg->midimapfile = mmapfile; - msg->midimap_loaded = mmap_loaded; - msg->drumkitfile = drumkitfile(); - msg->drumkit_loaded = loader.isDone(); - msg->enable_velocity_modifier = Conf::enable_velocity_modifier; - msg->velocity_modifier_falloff = Conf::velocity_modifier_falloff; - msg->velocity_modifier_weight = Conf::velocity_modifier_weight; - msg->enable_velocity_randomiser = Conf::enable_velocity_randomiser; - msg->velocity_randomiser_weight = Conf::velocity_randomiser_weight; - sendGUIMessage(msg); + mmapfile = aim->midimapFile(); + mmap_loaded = aim->isValid(); } - break; - case Message::ChangeSettingMessage: - { - ChangeSettingMessage *ch = (ChangeSettingMessage*)msg; - switch(ch->name) { - case ChangeSettingMessage::enable_velocity_modifier: - Conf::enable_velocity_modifier = ch->value; - break; - case ChangeSettingMessage::velocity_modifier_weight: - Conf::velocity_modifier_weight = ch->value; - break; - case ChangeSettingMessage::velocity_modifier_falloff: - Conf::velocity_modifier_falloff = ch->value; - break; - } + + EngineSettingsMessage *msg = new EngineSettingsMessage(); + msg->midimapfile = mmapfile; + msg->midimap_loaded = mmap_loaded; + msg->drumkitfile = drumkitfile(); + msg->drumkit_loaded = loader.isDone(); + msg->enable_velocity_modifier = Conf::enable_velocity_modifier; + msg->velocity_modifier_falloff = Conf::velocity_modifier_falloff; + msg->velocity_modifier_weight = Conf::velocity_modifier_weight; + msg->enable_velocity_randomiser = Conf::enable_velocity_randomiser; + msg->velocity_randomiser_weight = Conf::velocity_randomiser_weight; + msghandler.sendMessage(MSGRCV_UI, msg); + } + break; + case Message::ChangeSettingMessage: + { + ChangeSettingMessage *ch = (ChangeSettingMessage*)msg; + switch(ch->name) { + case ChangeSettingMessage::enable_velocity_modifier: + Conf::enable_velocity_modifier = ch->value; + break; + case ChangeSettingMessage::velocity_modifier_weight: + Conf::velocity_modifier_weight = ch->value; + break; + case ChangeSettingMessage::velocity_modifier_falloff: + Conf::velocity_modifier_falloff = ch->value; + break; } - break; - default: - break; } - delete msg; + break; + default: + break; } } bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) { // Handle engine messages, at most one in each iteration: - handleEngineEvents(); + handleMessages(1); ie->pre(); oe->pre(nsamples); @@ -609,7 +540,7 @@ bool DrumGizmo::setConfigString(std::string cfg) */ LoadDrumKitMessage *msg = new LoadDrumKitMessage(); msg->drumkitfile = newkit; - sendEngineMessage(msg); + msghandler.sendMessage(MSGRCV_ENGINE, msg); } std::string newmidimap = p.value("midimapfile"); @@ -617,7 +548,7 @@ bool DrumGizmo::setConfigString(std::string cfg) //midimapfile = newmidimap; LoadMidimapMessage *msg = new LoadMidimapMessage(); msg->midimapfile = newmidimap; - sendEngineMessage(msg); + msghandler.sendMessage(MSGRCV_ENGINE, msg); } return true; diff --git a/src/drumgizmo.h b/src/drumgizmo.h index ffb9b07..31c192c 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -43,9 +43,11 @@ #include "message.h" +#include "messagereceiver.h" + #define MAX_NUM_CHANNELS 512 -class DrumGizmo { +class DrumGizmo : public MessageReceiver { public: DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine); @@ -69,50 +71,14 @@ public: std::string kitfile; - /* - * Receive message from the engine. The caller takes over the memory. - */ - Message *receiveGUIMessage(); - - /* - * Receive message from the engine without removing it from the queue. - */ - Message *peekGUIMessage(); - - /* - * Add a message to the GUI message queue. - */ - void sendEngineMessage(Message *msg); - - /* - * Receive message from the engine. The caller takes over the memory. - */ - Message *receiveEngineMessage(); - - /* - * Receive message from the engine without removing it from the queue. - */ - Message *peekEngineMessage(); - - /* - * Add a message to the GUI message queue. - */ - void sendGUIMessage(Message *msg); + void handleMessage(Message *msg); private: - void handleEngineEvents(); - - Mutex gui_message_mutex; - std::list gui_message_queue; - - Mutex engine_message_mutex; - std::list engine_message_queue; - DrumKitLoader loader; Mutex mutex; bool is_running; - + AudioOutputEngine *oe; AudioInputEngine *ie; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 41b56a1..a7a8989 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -191,7 +191,7 @@ void DrumKitLoader::thread_main() ls->number_of_files = count; ls->numer_of_files_loaded = loaded; ls->current_file = af->filename; - drumgizmo->sendGUIMessage(ls); + msghandler.sendMessage(MSGRCV_UI, ls); a++; diff --git a/src/message.h b/src/message.h index 4ce65ef..d51c263 100644 --- a/src/message.h +++ b/src/message.h @@ -27,6 +27,10 @@ #ifndef __DRUMGIZMO_MESSAGE_H__ #define __DRUMGIZMO_MESSAGE_H__ +#include + +class MessageHandler; + class Message { public: typedef enum { @@ -39,15 +43,24 @@ public: LoadMidimap, // Signal engine to load midimap. EngineSettingsMessage, // Request or receive engine settings. ChangeSettingMessage, // Update named setting in engine. + RegisterUIMessage, // Register new UI message handler } type_t; + typedef enum { + NormalProcessing, // Just add to the queue + FilterMultiple, // Ignore top message if it has the same type. + // SyncWait, // Block the send call until the message has been handled by the receiver. + } processing_mode_t; + virtual ~Message() {} virtual type_t type() = 0; + virtual processing_mode_t processing_mode() { return NormalProcessing; } }; class LoadStatusMessage : public Message { public: type_t type() { return Message::LoadStatus; } + processing_mode_t processing_mode() { return FilterMultiple; } unsigned int number_of_files; unsigned int numer_of_files_loaded; std::string current_file; @@ -106,4 +119,10 @@ public: float value; }; +class RegisterUIMessage : public Message { +public: + type_t type() { return Message::RegisterUIMessage; } + MessageHandler *messagehandler; +}; + #endif/*__DRUMGIZMO_MESSAGE_H__*/ diff --git a/src/messagehandler.cc b/src/messagehandler.cc new file mode 100644 index 0000000..a5a71f1 --- /dev/null +++ b/src/messagehandler.cc @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * messagehandler.cc + * + * Fri Jun 14 20:30:43 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "messagehandler.h" + +#include + +#include "messagereceiver.h" + +// Global messagehandler: +MessageHandler msghandler; + +MessageHandler::MessageHandler() +{ +} + +void MessageHandler::addReceiver(message_receiver_id_t id, + MessageReceiver *receiver) +{ + MutexAutolock l(mutex); + + receivers[id] = receiver; +} + +void MessageHandler::removeReceiver(MessageReceiver *receiver) +{ + MutexAutolock l(mutex); + + std::map::iterator i = + receivers.begin(); + while(i != receivers.end()) { + if(i->second == receiver) { + receivers.erase(i); + break; + } + i++; + } +} + +bool MessageHandler::sendMessage(message_receiver_id_t id, Message* msg) +{ + MutexAutolock l(mutex); + + if(receivers.find(id) == receivers.end()) { + WARN(msghandler, "Could not find id %d\n", id); + delete msg; + return false; + } + + DEBUG(msghandler, "Sending message to id %d\n", id); + + MessageReceiver *receiver = receivers[id]; + + if(msg->processing_mode() == Message::FilterMultiple) { + Message *pmsg; + while( (pmsg = receiver->peekMessage()) != NULL) { + if(pmsg->type() != Message::LoadStatus) break; + delete msg; + msg = receiver->receiveMessage(); + } + } + + receiver->sendMessage(msg); + return true; +} diff --git a/src/messagehandler.h b/src/messagehandler.h new file mode 100644 index 0000000..9812777 --- /dev/null +++ b/src/messagehandler.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * messagehandler.h + * + * Fri Jun 14 20:30:43 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_MESSAGEHANDLER_H__ +#define __DRUMGIZMO_MESSAGEHANDLER_H__ + +#include + +#include "message.h" +#include "mutex.h" + +typedef enum { + MSGRCV_ENGINE = 1, + MSGRCV_UI = 2, + MSGRCV_LOADER = 3, +} message_receiver_id_t; + +class MessageReceiver; + +class MessageHandler { +public: + MessageHandler(); + + void addReceiver(message_receiver_id_t id, MessageReceiver *receiver); + void removeReceiver(MessageReceiver *receiver); + + /** + * Send Message to receiver with specified id. + * @return Return true if id is registered. Return false if id is not + * currently registered. + */ + bool sendMessage(message_receiver_id_t id, Message* msg); + +private: + std::map receivers; + + Mutex mutex; +}; + +// Global MessageHandler; +extern MessageHandler msghandler; + +#endif/*__DRUMGIZMO_MESSAGEHANDLER_H__*/ diff --git a/src/messagereceiver.cc b/src/messagereceiver.cc new file mode 100644 index 0000000..f391aad --- /dev/null +++ b/src/messagereceiver.cc @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * messagereceiver.cc + * + * Sun Jun 16 12:09:06 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "messagereceiver.h" + +#include + +MessageReceiver::MessageReceiver(message_receiver_id_t id) +{ + msghandler.addReceiver(id, this); +} + +MessageReceiver::~MessageReceiver() +{ + msghandler.removeReceiver(this); +} + +void MessageReceiver::sendMessage(Message *msg) +{ + MutexAutolock l(message_mutex); + + message_queue.push_back(msg); +} + +Message *MessageReceiver::receiveMessage() +{ + MutexAutolock l(message_mutex); + Message *msg = NULL; + if(message_queue.size()) { + msg = message_queue.front(); + message_queue.pop_front(); + } + return msg; +} + +Message *MessageReceiver::peekMessage() +{ + MutexAutolock l(message_mutex); + Message *msg = NULL; + if(message_queue.size()) { + msg = message_queue.front(); + } + return msg; +} + +void MessageReceiver::handleMessages(size_t max) +{ + bool process_all = false; + if(max == 0) process_all = true; + + while((process_all || max--) && peekMessage()) { + Message *msg = receiveMessage(); + handleMessage(msg); + delete msg; + } +} diff --git a/src/messagereceiver.h b/src/messagereceiver.h new file mode 100644 index 0000000..4185f29 --- /dev/null +++ b/src/messagereceiver.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * messagereceiver.h + * + * Sun Jun 16 12:09:06 CEST 2013 + * Copyright 2013 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo 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 2 of the License, or + * (at your option) any later version. + * + * DrumGizmo 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 DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __DRUMGIZMO_MESSAGERECEIVER_H__ +#define __DRUMGIZMO_MESSAGERECEIVER_H__ + +#include + +#include "mutex.h" +#include "message.h" +#include "messagehandler.h" + +class MessageReceiver { +public: + MessageReceiver(message_receiver_id_t id); + ~MessageReceiver(); + + /** + * Receive message from the message queue. + */ + Message *receiveMessage(); + + /** + * Receive message from the message queue without removing it. + */ + Message *peekMessage(); + + /** + * Add a message to the message queue. + */ + void sendMessage(Message *msg); + + /** + * Handle messages from the event queue. + * @param max_number_of_events the maximum number of events to be handled in + * this call. 0 means all. + */ + void handleMessages(size_t max_number_of_events = 0); + + /** + * Handler to be implemented in child classes. + * Handles a single event. + */ + virtual void handleMessage(Message *msg) = 0; + +private: + Mutex message_mutex; + std::list message_queue; +}; + +#endif/*__DRUMGIZMO_MESSAGERECEIVER_H__*/ -- cgit v1.2.3