From 057ef1d83ba263fb2adf1aa86f8e281ab0065c43 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 8 Apr 2016 00:15:32 +0200 Subject: Refactoring to finally get rid of MessageHandler/Receiver in favor of the new Settings mechanism. --- drumgizmo/drumgizmoc.cc | 76 +++++++------------ drumgizmo/drumgizmoc.h | 17 ----- plugin/Makefile.mingw32.in | 2 - plugin/drumgizmo_plugin.cc | 2 +- plugingui/Makefile.am | 5 +- plugingui/button.h | 3 +- plugingui/checkbox.h | 3 +- plugingui/dgwindow.cc | 113 ++++++++++++++++++---------- plugingui/dgwindow.h | 14 ++-- plugingui/eventhandler.h | 3 +- plugingui/filebrowser.h | 4 +- plugingui/knob.h | 3 +- plugingui/layout.h | 2 +- plugingui/listboxbasic.h | 3 +- plugingui/listboxthin.h | 3 +- plugingui/notifier.h | 163 ---------------------------------------- plugingui/plugingui.cc | 183 +++++++++------------------------------------ plugingui/plugingui.h | 36 ++------- plugingui/progressbar.cc | 26 ++++--- plugingui/progressbar.h | 9 ++- plugingui/testmain.cc | 12 ++- src/Makefile.am | 6 +- src/Makefile.am.drumgizmo | 2 - src/atomic.h | 60 +++++++++++++++ src/drumgizmo.cc | 149 ++++++++++++------------------------ src/drumgizmo.h | 14 +--- src/drumkitloader.cc | 16 ++-- src/drumkitparser.cc | 2 +- src/instrument.cc | 19 ++--- src/message.h | 121 ------------------------------ src/messagehandler.cc | 89 ---------------------- src/messagehandler.h | 66 ---------------- src/messagereceiver.cc | 78 ------------------- src/messagereceiver.h | 75 ------------------- src/notifier.h | 163 ++++++++++++++++++++++++++++++++++++++++ src/settings.h | 123 +++++++++++++++++++++--------- 36 files changed, 567 insertions(+), 1098 deletions(-) delete mode 100644 plugingui/notifier.h delete mode 100644 src/message.h delete mode 100644 src/messagehandler.cc delete mode 100644 src/messagehandler.h delete mode 100644 src/messagereceiver.cc delete mode 100644 src/messagereceiver.h create mode 100644 src/notifier.h diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 357877d..e993dc3 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -92,36 +92,7 @@ static const char usage_str[] = " dummy:\n" "\n"; -CliMain::CliMain() - : MessageReceiver(MSGRCV_UI) -{ - loading = true; // Block by default -} - -CliMain::~CliMain() -{ - hug_close(); -} - -void CliMain::handleMessage(Message* msg) -{ - switch(msg->type()) - { - case Message::LoadStatus: - { - auto ls = static_cast(msg); - if(ls->numer_of_files_loaded == ls->number_of_files) - { - loading = false; - } - } - break; - default: - break; - } -} - -int CliMain::run(int argc, char* argv[]) +int main(int argc, char* argv[]) { int c; @@ -383,21 +354,37 @@ int CliMain::run(int argc, char* argv[]) return 1; } - printf("Loading drumkit, this may take a while..."); - fflush(stdout); - loading = true; - while(async == false && loading) + printf("Loading drumkit, this may take a while:\n"); + + if(!async) { + while(settings.drumkit_load_status.load() != LoadStatus::Done) + { #ifdef WIN32 - SleepEx(500, FALSE); + SleepEx(10, FALSE); #else - usleep(500000); + usleep(10000); #endif /*WIN32*/ - handleMessages(); - printf("."); - fflush(stdout); + + int total = settings.number_of_files.load(); + int loaded = settings.number_of_files_loaded.load(); + + printf("\r%d of %d ", loaded, total); + fflush(stdout); + + if(settings.drumkit_load_status.load() == LoadStatus::Error) + { + printf("\nLoad error\n"); + return 1; + } + + if(loaded == total) + { + //break; + } + } + printf("\ndone\n"); } - printf("done.\n"); gizmo.setSamplerate(oe->getSamplerate()); @@ -412,14 +399,7 @@ int CliMain::run(int argc, char* argv[]) printf("Quit.\n"); fflush(stdout); - return 0; -} - -int main(int argc, char* argv[]) -{ - CliMain cli; - - cli.run(argc, argv); + hug_close(); return 0; } diff --git a/drumgizmo/drumgizmoc.h b/drumgizmo/drumgizmoc.h index 231aec6..cc2f96c 100644 --- a/drumgizmo/drumgizmoc.h +++ b/drumgizmo/drumgizmoc.h @@ -24,21 +24,4 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ - #pragma once - -#include "messagereceiver.h" - -class CliMain : public MessageReceiver -{ -public: - CliMain(); - virtual ~CliMain(); - - int run(int argc, char* argv[]); - void handleMessage(Message* msg); - -private: - bool loading; -}; - diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in index 779f54b..8b341c7 100644 --- a/plugin/Makefile.mingw32.in +++ b/plugin/Makefile.mingw32.in @@ -28,8 +28,6 @@ DG_SRC = \ @top_srcdir@/src/instrument.cc \ @top_srcdir@/src/instrumentparser.cc \ @top_srcdir@/src/memchecker.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/plugin/drumgizmo_plugin.cc b/plugin/drumgizmo_plugin.cc index 24cfb9a..06c2799 100644 --- a/plugin/drumgizmo_plugin.cc +++ b/plugin/drumgizmo_plugin.cc @@ -143,7 +143,7 @@ bool DrumGizmoPlugin::hasGUI() void DrumGizmoPlugin::createWindow(void *parent) { - plugin_gui = std::make_shared(parent); + plugin_gui = std::make_shared(settings, parent); resizeWindow(370, 330); onShowWindow(); } diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am index 3dee864..4176c07 100644 --- a/plugingui/Makefile.am +++ b/plugingui/Makefile.am @@ -16,9 +16,7 @@ plugingui_SOURCES = \ $(top_srcdir)/src/configfile.cc \ $(top_srcdir)/src/thread.cc \ $(top_srcdir)/src/semaphore.cc \ - $(top_srcdir)/src/mutex.cc \ - $(top_srcdir)/src/messagehandler.cc \ - $(top_srcdir)/src/messagereceiver.cc + $(top_srcdir)/src/mutex.cc rcgen_SOURCES = rcgen.cc @@ -46,7 +44,6 @@ EXTRA_DIST = \ nativewindow.h \ nativewindow_win32.h \ nativewindow_x11.h \ - notifier.h \ painter.h \ pixelbuffer.h \ pluginconfig.h \ diff --git a/plugingui/button.h b/plugingui/button.h index 7e3e168..1bfeb2d 100644 --- a/plugingui/button.h +++ b/plugingui/button.h @@ -28,9 +28,10 @@ #include +#include + #include "widget.h" #include "painter.h" -#include "notifier.h" #include "font.h" namespace GUI { diff --git a/plugingui/checkbox.h b/plugingui/checkbox.h index 3da5511..5c658a5 100644 --- a/plugingui/checkbox.h +++ b/plugingui/checkbox.h @@ -26,9 +26,10 @@ */ #pragma once +#include + #include "widget.h" #include "image.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/dgwindow.cc b/plugingui/dgwindow.cc index 25cbdf0..c325703 100644 --- a/plugingui/dgwindow.cc +++ b/plugingui/dgwindow.cc @@ -30,12 +30,12 @@ #include "verticalline.h" #include "../version.h" -#include "messagehandler.h" #include "pluginconfig.h" namespace GUI { -class LabeledControl : public Widget +class LabeledControl + : public Widget { public: LabeledControl(Widget* parent, const std::string& name) @@ -60,7 +60,8 @@ public: Label caption{this}; }; -class File : public Widget +class File + : public Widget { public: File(Widget* parent) @@ -83,7 +84,8 @@ public: Button browseButton{this}; }; -class HumanizeControls : public Widget +class HumanizeControls + : public Widget { public: HumanizeControls(Widget* parent) @@ -119,10 +121,8 @@ public: Knob falloffKnob{&falloff}; }; -DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, - Config& config, Settings& settings) +DGWindow::DGWindow(void* native_window, Config& config, Settings& settings) : Window(native_window) - , messageHandler(messageHandler) , config(config) , settings(settings) { @@ -180,6 +180,7 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, midimapFileProgress = new ProgressBar(this); midimapFileProgress->resize(width() - 40, 11); + midimapFileProgress->setTotal(2); layout.addItem(midimapFileProgress); VerticalLine *l2 = new VerticalLine(this); @@ -208,7 +209,7 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, layout.addItem(l3); Label *lbl_version = new Label(this); - lbl_version->setText(".::. v" VERSION " .::. http://www.drumgizmo.org .::. LGPLv3 .::."); + lbl_version->setText(".::. v" VERSION " .::. http://www.drumgizmo.org .::. LGPLv3 .::."); lbl_version->resize(width(), 20); lbl_version->setAlignment(TextAlignment::center); layout.addItem(lbl_version); @@ -220,6 +221,50 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, fileBrowser->hide(); } +void DGWindow::setDrumKitLoadStatus(LoadStatus load_status) +{ + ProgressBarState state = ProgressBarState::Blue; + switch(load_status) + { + case LoadStatus::Idle: + case LoadStatus::Loading: + state = ProgressBarState::Blue; + break; + case LoadStatus::Done: + state = ProgressBarState::Green; + break; + case LoadStatus::Error: + state = ProgressBarState::Red; + break; + } + drumkitFileProgress->setState(state); +} + +void DGWindow::setMidiMapLoadStatus(LoadStatus load_status) +{ + ProgressBarState state = ProgressBarState::Blue; + switch(load_status) + { + case LoadStatus::Idle: + midimapFileProgress->setValue(0); + break; + case LoadStatus::Loading: + midimapFileProgress->setValue(1); + state = ProgressBarState::Blue; + break; + case LoadStatus::Done: + midimapFileProgress->setValue(2); + state = ProgressBarState::Green; + break; + case LoadStatus::Error: + midimapFileProgress->setValue(2); + state = ProgressBarState::Red; + break; + } + + midimapFileProgress->setState(state); +} + void DGWindow::repaintEvent(RepaintEvent* repaintEvent) { if(!visible()) @@ -234,45 +279,41 @@ void DGWindow::repaintEvent(RepaintEvent* repaintEvent) void DGWindow::attackValueChanged(float value) { - //ChangeSettingMessage *msg = - // new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, - // value); - //messageHandler.sendMessage(MSGRCV_ENGINE, msg); - settings.velocity_modifier_weight.store(value); -#ifdef STANDALONE +#ifdef STANDALONE // For GUI debugging int i = value * 4; switch(i) { - case 0: drumkitFileProgress->setState(ProgressBarState::Off); break; - case 1: drumkitFileProgress->setState(ProgressBarState::Blue); break; - case 2: drumkitFileProgress->setState(ProgressBarState::Green); break; - case 3: drumkitFileProgress->setState(ProgressBarState::Red); break; - default: break; + case 0: + drumkitFileProgress->setState(ProgressBarState::Off); + break; + case 1: + drumkitFileProgress->setState(ProgressBarState::Blue); + break; + case 2: + drumkitFileProgress->setState(ProgressBarState::Green); + break; + case 3: + drumkitFileProgress->setState(ProgressBarState::Red); + break; + default: + break; } #endif } void DGWindow::falloffValueChanged(float value) { - //ChangeSettingMessage *msg = - // new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, - // value); - //messageHandler.sendMessage(MSGRCV_ENGINE, msg); - settings.velocity_modifier_falloff.store(value); -#ifdef STANDALONE - drumkitFileProgress->setProgress(value); +#ifdef STANDALONE // For GUI debugging + drumkitFileProgress->setTotal(100); + drumkitFileProgress->setValue(value * 100); #endif } void DGWindow::velocityCheckClick(bool checked) { -// ChangeSettingMessage *msg = -// new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, -// checked); -// messageHandler.sendMessage(MSGRCV_ENGINE, msg); settings.enable_velocity_modifier.store(checked); } @@ -323,13 +364,7 @@ void DGWindow::selectKitFile(const std::string& filename) config.lastkit = drumkit; config.save(); - drumkitFileProgress->setProgress(0); - drumkitFileProgress->setState(ProgressBarState::Blue); - - LoadDrumKitMessage *msg = new LoadDrumKitMessage(); - msg->drumkitfile = drumkit; - - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.drumkit_file.store(drumkit); } void DGWindow::selectMapFile(const std::string& filename) @@ -342,9 +377,7 @@ void DGWindow::selectMapFile(const std::string& filename) config.lastmidimap = midimap; config.save(); - LoadMidimapMessage *msg = new LoadMidimapMessage(); - msg->midimapfile = midimap; - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.midimap_file.store(midimap); } diff --git a/plugingui/dgwindow.h b/plugingui/dgwindow.h index c4fbeab..72e4679 100644 --- a/plugingui/dgwindow.h +++ b/plugingui/dgwindow.h @@ -26,8 +26,9 @@ */ #pragma once -#include "window.h" +#include +#include "window.h" #include "label.h" #include "lineedit.h" #include "checkbox.h" @@ -37,10 +38,6 @@ #include "filebrowser.h" #include "layout.h" -#include - -class MessageHandler; - namespace GUI { class Config; @@ -49,8 +46,7 @@ class File; class DGWindow : public Window { public: - DGWindow(void* native_window, MessageHandler& messageHandler, Config& config, - Settings& settings); + DGWindow(void* native_window, Config& config, Settings& settings); Header* header; @@ -68,6 +64,9 @@ public: Knob* falloffKnob; FileBrowser* fileBrowser; + void setDrumKitLoadStatus(LoadStatus load_status); + void setMidiMapLoadStatus(LoadStatus load_status); + protected: // From Widget: void repaintEvent(RepaintEvent* repaintEvent) override; @@ -81,7 +80,6 @@ private: void selectKitFile(const std::string& filename); void selectMapFile(const std::string& filename); - MessageHandler& messageHandler; Config& config; VBoxLayout layout{this}; diff --git a/plugingui/eventhandler.h b/plugingui/eventhandler.h index 1fdb1e8..490c515 100644 --- a/plugingui/eventhandler.h +++ b/plugingui/eventhandler.h @@ -26,9 +26,10 @@ */ #pragma once +#include + #include "guievent.h" #include "nativewindow.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/filebrowser.h b/plugingui/filebrowser.h index 04b34f6..bc2019f 100644 --- a/plugingui/filebrowser.h +++ b/plugingui/filebrowser.h @@ -26,15 +26,15 @@ */ #pragma once -#include "widget.h" +#include +#include "widget.h" #include "button.h" #include "listbox.h" #include "lineedit.h" #include "label.h" #include "image.h" #include "directory.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/knob.h b/plugingui/knob.h index 10d91d6..d144184 100644 --- a/plugingui/knob.h +++ b/plugingui/knob.h @@ -26,10 +26,11 @@ */ #pragma once +#include + #include "widget.h" #include "image.h" #include "font.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/layout.h b/plugingui/layout.h index 55cc93f..49bf75c 100644 --- a/plugingui/layout.h +++ b/plugingui/layout.h @@ -29,7 +29,7 @@ #include #include -#include "notifier.h" +#include namespace GUI { diff --git a/plugingui/listboxbasic.h b/plugingui/listboxbasic.h index 7953dc3..2ebe845 100644 --- a/plugingui/listboxbasic.h +++ b/plugingui/listboxbasic.h @@ -29,11 +29,12 @@ #include #include +#include + #include "widget.h" #include "font.h" #include "painter.h" #include "scrollbar.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/listboxthin.h b/plugingui/listboxthin.h index 3139ecc..1617234 100644 --- a/plugingui/listboxthin.h +++ b/plugingui/listboxthin.h @@ -29,10 +29,11 @@ #include #include +#include + #include "widget.h" #include "painter.h" #include "listboxbasic.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/notifier.h b/plugingui/notifier.h deleted file mode 100644 index 9e9f6eb..0000000 --- a/plugingui/notifier.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * notifier.h - * - * Thu Sep 3 15:48:39 CEST 2015 - * Copyright 2015 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 Lesser General Public License as published by - * the Free Software Foundation; either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ -#pragma once - -#include -#include -#include -#include -#include - -namespace aux -{ - template - struct placeholder - { - }; -} - -namespace std -{ - template - struct is_placeholder> - : integral_constant - { - }; -} - -namespace aux -{ - // std::integer_sequence introduced in C++14 so remove this once we start requiring that. - - template - struct int_sequence - { - }; - - template - struct gen_int_sequence - : gen_int_sequence - { - }; - - template - struct gen_int_sequence<0, Ns...> - : int_sequence - { - }; -}; - - -namespace GUI { - -class Listener; -class NotifierBase { -public: - virtual void disconnect(Listener* object) {} -}; - -class Listener { -public: - virtual ~Listener() - { - for(auto signal : signals) - { - signal->disconnect(this); - } - } - - void registerNotifier(NotifierBase* signal) - { - signals.insert(signal); - } - - void unregisterNotifier(NotifierBase* signal) - { - signals.erase(signal); - } - -private: - std::set signals; -}; - -template -class Notifier : public NotifierBase { -public: - Notifier() {} - - //! \brief When dtor is called it will automatically disconnect all its listeners. - ~Notifier() - { - for(auto& slot : slots) - { - slot.first->unregisterNotifier(this); - } - } - - using callback_type = std::function; - - //! \brief Connect object to this Notifier. - template - void connect(O* p, const F& fn) - { - slots[p] = std::move(construct_mem_fn(fn, p, aux::gen_int_sequence{})); - if(p && dynamic_cast(p)) - { - dynamic_cast(p)->registerNotifier(this); - } - } - - //! \brief Disconnect object from this Notifier. - void disconnect(Listener* object) - { - slots.erase(object); - } - - //! \brief Activate this notifier by pretending it is a function. - //! Example: Notifier foo; foo(42); - void operator()(Args... args) - { - for(auto& slot : slots) - { - slot.second(args...); - } - } - -private: - std::map slots; - - template - callback_type construct_mem_fn(const F& fn, O* p, aux::int_sequence) const - { - return std::bind(fn, p, aux::placeholder{}...); - } - -}; - -} // GUI:: - -#define CONNECT(SRC, SIG, TAR, SLO) (SRC)->SIG.connect(TAR, SLO) diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index 9bac007..2802c44 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -26,18 +26,17 @@ */ #include "plugingui.h" +#include + #include #include "pluginconfig.h" -#include "messagehandler.h" - -#include namespace GUI { -PluginGUI::PluginGUI(void* native_window) - : MessageReceiver(MSGRCV_UI) - , native_window(native_window) +PluginGUI::PluginGUI(Settings& settings, void* native_window) + : native_window(native_window) + , settings(settings) { init(); } @@ -46,70 +45,6 @@ PluginGUI::~PluginGUI() { } -void PluginGUI::handleMessage(Message *msg) -{ - Painter p(*window);// Make sure we only redraw buffer once (set refcount to 1) - - switch(msg->type()) { - case Message::LoadStatus: - { - LoadStatusMessage *ls = (LoadStatusMessage*)msg; - window->drumkitFileProgress->setProgress((float)ls->numer_of_files_loaded / - (float)ls->number_of_files); - if(ls->numer_of_files_loaded == ls->number_of_files) - { - window->drumkitFileProgress->setState(ProgressBarState::Green); - } - } - break; - case Message::LoadStatusMidimap: - { - LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg; - window->midimapFileProgress->setProgress(1); - if(ls->success) - { - window->midimapFileProgress->setState(ProgressBarState::Green); - } - else - { - window->midimapFileProgress->setState(ProgressBarState::Red); - } - } - break; - case Message::EngineSettingsMessage: - { - EngineSettingsMessage *settings = (EngineSettingsMessage *)msg; - window->lineedit->setText(settings->drumkitfile); - if(settings->drumkit_loaded) - { - window->drumkitFileProgress->setProgress(1); - window->drumkitFileProgress->setState(ProgressBarState::Green); - } - else - { - window->drumkitFileProgress->setProgress(0); - window->drumkitFileProgress->setState(ProgressBarState::Blue); - } - window->lineedit2->setText(settings->midimapfile); - if(settings->midimap_loaded) - { - window->midimapFileProgress->setProgress(1); - window->midimapFileProgress->setState(ProgressBarState::Green); - } - else - { - window->midimapFileProgress->setProgress(0); - window->midimapFileProgress->setState(ProgressBarState::Blue); - } - window->velocityCheck->setChecked(settings->enable_velocity_modifier); - window->attackKnob->setValue(settings->velocity_modifier_weight); - window->falloffKnob->setValue(settings->velocity_modifier_falloff); - } - default: - break; - } -} - bool PluginGUI::processEvents() { if(!initialised) @@ -118,69 +53,13 @@ bool PluginGUI::processEvents() } window->eventHandler()->processEvents(); - //handleMessages(); - - static bool foo = false; - static int t = 0; - if(t != time(nullptr)) - { - t = time(nullptr); - foo = !foo; - float v = settings.velocity_modifier_falloff.load(); - v += 0.1f; - settings.velocity_modifier_falloff.store(v); - } - - Painter p(*window); - - // Run through all settings one at a time propagate changes to the UI. - if(getter.enable_velocity_modifier.hasChanged()) - { - enable_velocity_modifier_notifier(getter.enable_velocity_modifier.getValue()); - } - if(getter.velocity_modifier_falloff.hasChanged()) { - velocity_modifier_falloff_notifier(getter.velocity_modifier_falloff.getValue()); - } + Painter p(*window); - if(getter.velocity_modifier_weight.hasChanged()) - { - velocity_modifier_weight_notifier(getter.velocity_modifier_weight.getValue()); - } - - if(getter.enable_velocity_randomiser.hasChanged()) - { - enable_velocity_randomiser_notifier(getter.enable_velocity_randomiser.getValue()); + settings_notifier.evaluate(); } - if(getter.velocity_randomiser_weight.hasChanged()) - { - velocity_randomiser_weight_notifier(getter.velocity_randomiser_weight.getValue()); - } - - if(getter.samplerate.hasChanged()) - { - samplerate_notifier(getter.samplerate.getValue()); - } - - if(getter.enable_resampling.hasChanged()) - { - enable_resampling_notifier(getter.enable_resampling.getValue()); - } - - if(getter.number_of_files.hasChanged() || - getter.number_of_files_loaded.hasChanged()) - { - drumkit_file_progress_notifier((float)getter.number_of_files_loaded.getValue() / - (float)getter.number_of_files.getValue()); - } - - //if(getter.current_file.hasChanged()) - //{ - // current_file_notifier(getter.current_file.getValue()); - //} - if(closing) { closeNotifier(); @@ -198,41 +77,51 @@ void PluginGUI::init() config = new Config(); config->load(); - window = new DGWindow(native_window, msghandler, *config, settings); + window = new DGWindow(native_window, *config, settings); + + + CONNECT(this, settings_notifier.drumkit_file, + window->lineedit, &LineEdit::setText); + CONNECT(this, settings_notifier.drumkit_load_status, + window, &DGWindow::setDrumKitLoadStatus); - CONNECT(this, enable_velocity_modifier_notifier, + CONNECT(this, settings_notifier.midimap_file, + window->lineedit2, &LineEdit::setText); + CONNECT(this, settings_notifier.midimap_load_status, + window, &DGWindow::setMidiMapLoadStatus); + + CONNECT(this, settings_notifier.enable_velocity_modifier, window->velocityCheck, &CheckBox::setChecked); - CONNECT(this, velocity_modifier_falloff_notifier, + CONNECT(this, settings_notifier.velocity_modifier_falloff, window->falloffKnob, &Knob::setValue); - CONNECT(this, velocity_modifier_weight_notifier, + CONNECT(this, settings_notifier.velocity_modifier_weight, window->attackKnob, &Knob::setValue); - //CONNECT(this, enable_velocity_randomiser_notifier, - // window->velocityCheck, &CheckBox::setChecked); - //CONNECT(this, velocity_randomiser_weight_notifier, - // window->velocityCheck, &CheckBox::setChecked); + // TODO: + //CONNECT(this, settings_notifier.enable_velocity_randomiser, + // window->, &CheckBox::setChecked); + //CONNECT(this, settings_notifier.velocity_randomiser_weight, + // window->, &Knob::setValue); + + //CONNECT(this, settings_notifier.samplerate, + // window->, &Knob::setValue); - //CONNECT(this, samplerate_notifier, - // window->velocityCheck, &CheckBox::setChecked); + //CONNECT(this, settings_notifier.enable_resampling, + // window->, &CheckBox::setChecked); - //CONNECT(this, enable_resampling_notifier, - // window->velocityCheck, &CheckBox::setChecked); + CONNECT(this, settings_notifier.number_of_files, + window->drumkitFileProgress, &ProgressBar::setTotal); - CONNECT(this, drumkit_file_progress_notifier, - window->drumkitFileProgress, &ProgressBar::setProgress); + CONNECT(this, settings_notifier.number_of_files_loaded, + window->drumkitFileProgress, &ProgressBar::setValue); auto eventHandler = window->eventHandler(); CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler); window->show(); - { // Request all engine settings - EngineSettingsMessage *msg = new EngineSettingsMessage(); - msghandler.sendMessage(MSGRCV_ENGINE, msg); - } - initialised = true; } diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index ca31c41..04b0a29 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -26,24 +26,20 @@ */ #pragma once +#include +#include + #include "dgwindow.h" #include "eventhandler.h" - #include "pluginconfig.h" -#include - -#include "messagereceiver.h" -#include "notifier.h" - namespace GUI { class PluginGUI - : public MessageReceiver - , public Listener + : public Listener { public: - PluginGUI(void* native_window = nullptr); + PluginGUI(Settings& settings, void* native_window = nullptr); virtual ~PluginGUI(); //! Process all events and messages in queue @@ -56,9 +52,6 @@ public: void show(); void hide(); - - void handleMessage(Message* msg); - DGWindow* window{nullptr}; EventHandler* eventhandler{nullptr}; @@ -66,21 +59,6 @@ public: Notifier<> closeNotifier; - // Setting notifiers: - Notifier enable_velocity_modifier_notifier; - Notifier velocity_modifier_falloff_notifier; - Notifier velocity_modifier_weight_notifier; - - Notifier enable_velocity_randomiser_notifier; - Notifier velocity_randomiser_weight_notifier; - - Notifier samplerate_notifier; - - Notifier enable_resampling_notifier; - - Notifier drumkit_file_progress_notifier; - //Notifier current_file_notifier; - // Support old interface a little while longer.. void setWindowClosedCallback(void (*handler)(void*), void* ptr); @@ -97,8 +75,8 @@ private: void (*windowClosedHandler)(void *){nullptr}; void *windowClosedPtr{nullptr}; - Settings settings; - SettingsGetter getter{settings}; + Settings& settings; + SettingsNotifier settings_notifier{settings}; }; } // GUI:: diff --git a/plugingui/progressbar.cc b/plugingui/progressbar.cc index 932f17c..f934664 100644 --- a/plugingui/progressbar.cc +++ b/plugingui/progressbar.cc @@ -26,6 +26,8 @@ */ #include "progressbar.h" +#include + namespace GUI { ProgressBar::ProgressBar(Widget *parent) @@ -46,9 +48,6 @@ ProgressBar::ProgressBar(Widget *parent) bar_green.left = new Image(":progress_front_green_l.png"); bar_green.right = new Image(":progress_front_green_r.png"); bar_green.center = new Image(":progress_front_green_c.png"); - - state = ProgressBarState::Blue; - _progress = .5; } ProgressBar::~ProgressBar() @@ -79,22 +78,31 @@ void ProgressBar::setState(ProgressBarState state) } } -float ProgressBar::progress() +void ProgressBar::setTotal(int total) { - return _progress; + if(this->total != total) + { + this->total = total; + repaintEvent(nullptr); + } } -void ProgressBar::setProgress(float progress) +void ProgressBar::setValue(int value) { - _progress = progress; - repaintEvent(nullptr); + if(this->value != value) + { + this->value = value; + repaintEvent(nullptr); + } } void ProgressBar::repaintEvent(RepaintEvent* repaintEvent) { Painter p(*this); - int max = width() * _progress; + float progress = (float)value / (float)total; + + int max = width() * progress; p.clear(); diff --git a/plugingui/progressbar.h b/plugingui/progressbar.h index d5f6c61..d48a8b5 100644 --- a/plugingui/progressbar.h +++ b/plugingui/progressbar.h @@ -46,8 +46,8 @@ public: ProgressBar(Widget *parent); ~ProgressBar(); - float progress(); - void setProgress(float progress); + void setTotal(int total); + void setValue(int value); void setState(ProgressBarState state); @@ -56,7 +56,7 @@ protected: virtual void repaintEvent(RepaintEvent* repaintEvent) override; private: - ProgressBarState state; + ProgressBarState state{ProgressBarState::Blue}; Painter::Bar bar_bg; @@ -64,7 +64,8 @@ private: Painter::Bar bar_blue; Painter::Bar bar_red; - float _progress; + int total{0}; + int value{0}; }; } // GUI:: diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc index b3a0d8d..84d813d 100644 --- a/plugingui/testmain.cc +++ b/plugingui/testmain.cc @@ -33,13 +33,10 @@ #include -// Dummy Engine class. -class Engine : public MessageHandler { -public: - void handleMessage(Message *msg) {} -}; +#include +#include -class TestMain : public GUI::Listener { +class TestMain : public Listener { public: TestMain() { @@ -67,7 +64,8 @@ public: bool running = true; - GUI::PluginGUI gui; + Settings settings; + GUI::PluginGUI gui{settings}; }; int main() diff --git a/src/Makefile.am b/src/Makefile.am index 9dd6c29..4d167af 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,13 +23,11 @@ EXTRA_DIST = \ instrument.h \ instrumentparser.h \ memchecker.h \ - message.h \ - messagehandler.h \ - messagereceiver.h \ midimapparser.h \ midimapper.h \ mutex.h \ nolocale.h \ + notifier.h \ path.h \ powerlist.h \ rangemap.h \ @@ -62,8 +60,6 @@ EXTRA_DIST = \ instrument.cc \ instrumentparser.cc \ memchecker.cc \ - messagehandler.cc \ - messagereceiver.cc \ midimapparser.cc \ midimapper.cc \ mutex.cc \ diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo index e707fe2..6fddded 100644 --- a/src/Makefile.am.drumgizmo +++ b/src/Makefile.am.drumgizmo @@ -20,8 +20,6 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/instrument.cc \ $(top_srcdir)/src/instrumentparser.cc \ $(top_srcdir)/src/memchecker.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/atomic.h b/src/atomic.h index e0b80b1..95a5e9d 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -116,7 +116,67 @@ public: return data; } + bool operator==(const T& other) const + { + std::lock_guard lock{mutex}; + return other == data; + } + + bool operator!=(const T& other) const + { + std::lock_guard lock{mutex}; + return !(other == data); + } + + bool operator==(const Atomic& other) const + { + std::lock_guard lock{mutex}; + return other.load() == data; + } + + bool operator!=(const Atomic& other) const + { + std::lock_guard lock{mutex}; + return !(other.load() == data); + } + private: T data; mutable std::mutex mutex; }; + +//! Getter utility class. +template class SettingRef +{ +public: + SettingRef(Atomic& value) + : value(value) + { + // string isn't lock free either + assert((std::is_same::value || value.is_lock_free())); + } + + bool hasChanged() + { + T tmp = cache; + cache.exchange(value); + + if(firstAccess) + { + firstAccess = false; + return true; + } + + return cache != tmp; + } + + T getValue() const + { + return cache; + } + +private: + bool firstAccess{true}; + Atomic& value; + Atomic cache; +}; diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index f769f4e..aa6be23 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -38,6 +38,7 @@ #include #include +#include #include "drumkitparser.h" #include "audioinputenginemidi.h" @@ -47,8 +48,7 @@ DrumGizmo::DrumGizmo(Settings& settings, AudioOutputEngine *o, AudioInputEngine *i) - : MessageReceiver(MSGRCV_ENGINE) - , loader(settings) + : loader(settings) , oe(o) , ie(i) , framesize(0) @@ -69,9 +69,12 @@ DrumGizmo::~DrumGizmo() bool DrumGizmo::loadkit(std::string file) { + settings.drumkit_load_status.store(LoadStatus::Idle); + if(file == "") { - return 1; + settings.drumkit_load_status.store(LoadStatus::Error); + return false; } DEBUG(drumgizmo, "loadkit(%s)\n", file.c_str()); @@ -82,20 +85,24 @@ bool DrumGizmo::loadkit(std::string file) // Delete all Channels, Instruments, Samples and AudioFiles. kit.clear(); + settings.drumkit_load_status.store(LoadStatus::Loading); + DrumKitParser parser(settings, kit); if(parser.parseFile(file)) { ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); + settings.drumkit_load_status.store(LoadStatus::Error); return false; } - // Check if there is enough free RAM to load the drumkit. - if(!memchecker.enoughFreeMemory(kit)) - { - printf("WARNING: " - "There doesn't seem to be enough RAM available to load the kit.\n" - "Trying to load it anyway...\n"); - } + // TODO: Re-introduce when the code has been moved to the loader thread. + //// Check if there is enough free RAM to load the drumkit. + //if(!memchecker.enoughFreeMemory(kit)) + //{ + // printf("WARNING: " + // "There doesn't seem to be enough RAM available to load the kit.\n" + // "Trying to load it anyway...\n"); + //} loader.loadKit(&kit); @@ -126,79 +133,6 @@ bool DrumGizmo::init() return true; } -void DrumGizmo::handleMessage(Message *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; - } - { - 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: - { - bool mmap_loaded = false; - std::string mmapfile; - if(ie->isMidiEngine()) - { - AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; - mmapfile = aim->getMidimapFile(); - mmap_loaded = aim->isValid(); - } - - EngineSettingsMessage *msg = new EngineSettingsMessage(); - msg->midimapfile = mmapfile; - msg->midimap_loaded = mmap_loaded; - msg->drumkitfile = kit.getFile(); - msg->drumkit_loaded = loader.isDone(); - msg->enable_velocity_modifier = settings.enable_velocity_modifier.load(); - msg->velocity_modifier_falloff = settings.velocity_modifier_falloff.load(); - msg->velocity_modifier_weight = settings.velocity_modifier_weight.load(); - msg->enable_velocity_randomiser = settings.enable_velocity_randomiser.load(); - msg->velocity_randomiser_weight = settings.velocity_randomiser_weight.load(); - msghandler.sendMessage(MSGRCV_UI, msg); - } - break; - case Message::ChangeSettingMessage: - { - ChangeSettingMessage *ch = (ChangeSettingMessage*)msg; - switch(ch->name) { - case ChangeSettingMessage::enable_velocity_modifier: - settings.enable_velocity_modifier.store(ch->value); - break; - case ChangeSettingMessage::velocity_modifier_weight: - settings.velocity_modifier_weight.store(ch->value); - break; - case ChangeSettingMessage::velocity_modifier_falloff: - settings.velocity_modifier_falloff.store(ch->value); - break; - } - } - break; - default: - break; - } -} - void DrumGizmo::setFrameSize(size_t framesize) { // If we are resampling override the frame size. @@ -260,8 +194,31 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) { setFrameSize(nsamples); - // Handle engine messages, at most one in each iteration: - handleMessages(1); + // TODO: Move this to DrumKitLoader thread. + if(getter.drumkit_file.hasChanged()) + { + loadkit(getter.drumkit_file.getValue()); + } + + // TODO: Move this to DrumKitLoader thread. + if(getter.midimap_file.hasChanged()) + { + auto ie_midi = dynamic_cast(ie); + if(ie_midi) + { + settings.midimap_load_status.store(LoadStatus::Loading); + bool ret = ie_midi->loadMidiMap(getter.midimap_file.getValue(), + kit.instruments); + if(ret) + { + settings.midimap_load_status.store(LoadStatus::Done); + } + else + { + settings.midimap_load_status.store(LoadStatus::Error); + } + } + } ie->pre(); oe->pre(nsamples); @@ -712,8 +669,8 @@ bool DrumGizmo::setConfigString(std::string cfg) ConfigParser p; if(p.parseString(cfg)) { - ERR(drumgizmo, "Config parse error.\n"); - return false; + ERR(drumgizmo, "Config parse error.\n"); + return false; } if(p.value("enable_velocity_modifier") != "") @@ -747,27 +704,15 @@ bool DrumGizmo::setConfigString(std::string cfg) } std::string newkit = p.value("drumkitfile"); - if(newkit != "" && kit.getFile() != newkit) + if(newkit != "") { - /* - if(!loadkit(p.values["drumkitfile"])) - { - return false; - } - init(true); - */ - LoadDrumKitMessage *msg = new LoadDrumKitMessage(); - msg->drumkitfile = newkit; - msghandler.sendMessage(MSGRCV_ENGINE, msg); + settings.drumkit_file.store(newkit); } std::string newmidimap = p.value("midimapfile"); if(newmidimap != "") { - //midimapfile = newmidimap; - LoadMidimapMessage *msg = new LoadMidimapMessage(); - msg->midimapfile = newmidimap; - msghandler.sendMessage(MSGRCV_ENGINE, msg); + settings.midimap_file.store(newmidimap); } return true; diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 63348da..7af5dbb 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -31,25 +31,15 @@ #include "audiooutputengine.h" #include "audioinputengine.h" - #include "events.h" #include "audiofile.h" #include "drumkit.h" #include "memchecker.h" - #include "drumkitloader.h" #include "audiocache.h" - #include "mutex.h" - -#include "message.h" - -#include "messagereceiver.h" - #include "chresampler.h" - #include "configfile.h" - #include "settings.h" #define MAX_NUM_CHANNELS 64 @@ -57,7 +47,6 @@ #define RESAMPLER_INPUT_BUFFER 64 class DrumGizmo - : public MessageReceiver { public: DrumGizmo(Settings& settings, @@ -77,8 +66,6 @@ public: std::string configString(); bool setConfigString(std::string cfg); - void handleMessage(Message *msg); - int samplerate(); void setSamplerate(int samplerate); @@ -112,4 +99,5 @@ protected: std::vector events; Settings& settings; + SettingsGetter getter{settings}; }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 3cb4b68..f9e45db 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -184,18 +184,14 @@ void DrumKitLoader::thread_main() audiofile->load(preload_size); } - loaded++; + ++loaded; - if(loaded % fraction == 0 || loaded == total_num_audiofiles) + settings.number_of_files.store(total_num_audiofiles); + settings.number_of_files_loaded.store(loaded); + + if(total_num_audiofiles == loaded) { - //LoadStatusMessage *ls = new LoadStatusMessage(); - //ls->number_of_files = total_num_audiofiles; - //ls->numer_of_files_loaded = loaded; - //ls->current_file = filename; - //msghandler.sendMessage(MSGRCV_UI, ls); - settings.number_of_files.store(total_num_audiofiles); - settings.number_of_files_loaded.store(loaded); - //settings.current_file.store(filename); + settings.drumkit_load_status.store(LoadStatus::Done); } } diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 221e921..048a05b 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -34,7 +34,7 @@ #include "path.h" #include "drumgizmo.h" -DrumKitParser::DrumKitParser(Settings& setting, DrumKit& k) +DrumKitParser::DrumKitParser(Settings& settings, DrumKit& k) : kit(k) , refs(REFSFILE) , settings(settings) diff --git a/src/instrument.cc b/src/instrument.cc index f187de0..cc052e9 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -42,7 +42,7 @@ Instrument::Instrument(Settings& settings) Instrument::~Instrument() { - magic = NULL; + magic = nullptr; DEBUG(instrument, "delete %p\n", this); std::vector::iterator i = audiofiles.begin(); @@ -60,8 +60,6 @@ bool Instrument::isValid() const Sample* Instrument::sample(level_t level, size_t pos) { - Sample *sample = NULL; - // Read out all values from settings. auto enable_velocity_randomiser = settings.enable_velocity_randomiser.load(); auto velocity_randomiser_weight = settings.velocity_randomiser_weight.load(); @@ -70,6 +68,8 @@ Sample* Instrument::sample(level_t level, size_t pos) auto enable_velocity_modifier = settings.enable_velocity_modifier.load(); auto velocity_modifier_weight = settings.velocity_modifier_weight.load(); + Sample *sample = nullptr; + if(enable_velocity_modifier == false) { mod = 1.0; @@ -78,14 +78,13 @@ Sample* Instrument::sample(level_t level, size_t pos) if(enable_velocity_randomiser) { - float r = rand.floatInRange(-0.5f, 0.5f); - r *= velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] + float r = rand.floatInRange(-1.0 * velocity_randomiser_weight, + velocity_randomiser_weight); level += r; if(level > 1.0) { level = 1.0; } - if(level < 0.0) { level = 0.0; @@ -94,8 +93,7 @@ Sample* Instrument::sample(level_t level, size_t pos) if(enable_velocity_modifier) { - mod += (pos - lastpos) / - (samplerate * velocity_modifier_falloff); + mod += (pos - lastpos) / (samplerate * velocity_modifier_falloff); if(mod > 1.0) { mod = 1.0; @@ -113,11 +111,10 @@ Sample* Instrument::sample(level_t level, size_t pos) std::vector s = samples.get(level * mod); if(s.size() == 0) { - return NULL; + return nullptr; } - //size_t idx = ::rand()%(s.size()); - sample = rand.choose(s); + sample = rand.choose(s); } if(enable_velocity_modifier) diff --git a/src/message.h b/src/message.h deleted file mode 100644 index 71d0da6..0000000 --- a/src/message.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * message.h - * - * Wed Mar 20 15:50:57 CET 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 Lesser General Public License as published by - * the Free Software Foundation; either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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_MESSAGE_H__ -#define __DRUMGIZMO_MESSAGE_H__ - -#include - -class MessageHandler; - -class Message { -public: - typedef enum { - // Engine -> GUI Messages: - LoadStatus, // Signal GUI the current load status. - LoadStatusMidimap, // Signal GUI the current load status of the midimap. - - // GUI -> Engine, Engine -> Engine Messages: - LoadDrumKit, // Signal engine to load drumkit. - LoadMidimap, // Signal engine to load midimap. - EngineSettingsMessage, // Request or receive engine settings. - ChangeSettingMessage, // Update named setting in engine. - } 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; -}; - -class LoadStatusMessageMidimap : public Message { -public: - type_t type() { return Message::LoadStatusMidimap; } - bool success; -}; - -class LoadDrumKitMessage : public Message { -public: - type_t type() { return Message::LoadDrumKit; } - std::string drumkitfile; -}; - -class LoadMidimapMessage : public Message { -public: - type_t type() { return Message::LoadMidimap; } - std::string midimapfile; -}; - -class EngineSettingsMessage : public Message { -public: - type_t type() { return Message::EngineSettingsMessage; } - std::string midimapfile; - bool midimap_loaded; - - std::string drumkitfile; - bool drumkit_loaded; - - float enable_velocity_modifier; - float velocity_modifier_falloff; - float velocity_modifier_weight; - float enable_velocity_randomiser; - float velocity_randomiser_weight; -}; - -class ChangeSettingMessage : public Message { -public: - typedef enum { - enable_velocity_modifier, - velocity_modifier_weight, - velocity_modifier_falloff, - } setting_name_t; - - ChangeSettingMessage(setting_name_t n, float v) { - name = n; - value = v; - } - - type_t type() { return Message::ChangeSettingMessage; } - - setting_name_t name; - float value; -}; - -#endif/*__DRUMGIZMO_MESSAGE_H__*/ diff --git a/src/messagehandler.cc b/src/messagehandler.cc deleted file mode 100644 index 7a0c7ea..0000000 --- a/src/messagehandler.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- 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 Lesser General Public License as published by - * the Free Software Foundation; either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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]; - /* // This code causes sporadic segfaults on windows. - if(msg->processing_mode() == Message::FilterMultiple) { - Message *pmsg; - MutexAutolock lock(receiver->message_mutex); // Make peek/receive atomic. - while( (pmsg = receiver->peekMessage()) != NULL) { - if(pmsg->type() != msg->type()) break; - // Remove all old messages with same type. - delete receiver->receiveMessage(); - } - } - */ - receiver->sendMessage(msg); - return true; -} diff --git a/src/messagehandler.h b/src/messagehandler.h deleted file mode 100644 index 2b6c40e..0000000 --- a/src/messagehandler.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- 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 Lesser General Public License as published by - * the Free Software Foundation; either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 deleted file mode 100644 index 590c98a..0000000 --- a/src/messagereceiver.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- 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 Lesser General Public License as published by - * the Free Software Foundation; either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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() -{ - Message *msg = NULL; - if(message_queue.size()) { - msg = message_queue.front(); - message_queue.pop_front(); - } - return msg; -} - -Message *MessageReceiver::peekMessage() -{ - Message *msg = NULL; - if(message_queue.size()) { - msg = message_queue.front(); - } - return msg; -} - -void MessageReceiver::handleMessages(size_t max) -{ - MutexAutolock l(message_mutex); - 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 deleted file mode 100644 index c1a8e60..0000000 --- a/src/messagereceiver.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- 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 Lesser General Public License as published by - * the Free Software Foundation; either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 { - friend class MessageHandler; -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__*/ diff --git a/src/notifier.h b/src/notifier.h new file mode 100644 index 0000000..ff59741 --- /dev/null +++ b/src/notifier.h @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * notifier.h + * + * Thu Sep 3 15:48:39 CEST 2015 + * Copyright 2015 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 Lesser General Public License as published by + * the Free Software Foundation; either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#pragma once + +#include +#include +#include +#include +#include + +namespace aux +{ + template + struct placeholder + { + }; +} + +namespace std +{ + template + struct is_placeholder> + : integral_constant + { + }; +} + +namespace aux +{ + // std::integer_sequence introduced in C++14 so remove this once we start requiring that. + + template + struct int_sequence + { + }; + + template + struct gen_int_sequence + : gen_int_sequence + { + }; + + template + struct gen_int_sequence<0, Ns...> + : int_sequence + { + }; +}; + + +//namespace GUI { + +class Listener; +class NotifierBase { +public: + virtual void disconnect(Listener* object) {} +}; + +class Listener { +public: + virtual ~Listener() + { + for(auto signal : signals) + { + signal->disconnect(this); + } + } + + void registerNotifier(NotifierBase* signal) + { + signals.insert(signal); + } + + void unregisterNotifier(NotifierBase* signal) + { + signals.erase(signal); + } + +private: + std::set signals; +}; + +template +class Notifier : public NotifierBase { +public: + Notifier() {} + + //! \brief When dtor is called it will automatically disconnect all its listeners. + ~Notifier() + { + for(auto& slot : slots) + { + slot.first->unregisterNotifier(this); + } + } + + using callback_type = std::function; + + //! \brief Connect object to this Notifier. + template + void connect(O* p, const F& fn) + { + slots[p] = std::move(construct_mem_fn(fn, p, aux::gen_int_sequence{})); + if(p && dynamic_cast(p)) + { + dynamic_cast(p)->registerNotifier(this); + } + } + + //! \brief Disconnect object from this Notifier. + void disconnect(Listener* object) + { + slots.erase(object); + } + + //! \brief Activate this notifier by pretending it is a function. + //! Example: Notifier foo; foo(42); + void operator()(Args... args) + { + for(auto& slot : slots) + { + slot.second(args...); + } + } + +private: + std::map slots; + + template + callback_type construct_mem_fn(const F& fn, O* p, aux::int_sequence) const + { + return std::bind(fn, p, aux::placeholder{}...); + } + +}; + +//} // GUI:: + +#define CONNECT(SRC, SIG, TAR, SLO) (SRC)->SIG.connect(TAR, SLO) diff --git a/src/settings.h b/src/settings.h index b132c1b..c79e4e5 100644 --- a/src/settings.h +++ b/src/settings.h @@ -31,10 +31,25 @@ #include #include "atomic.h" +#include "notifier.h" + +enum class LoadStatus : unsigned int +{ + Idle, + Loading, + Done, + Error +}; //! Engine settings struct Settings { + Atomic drumkit_file; + Atomic drumkit_load_status{LoadStatus::Idle}; + + Atomic midimap_file; + Atomic midimap_load_status{LoadStatus::Idle}; + Atomic enable_velocity_modifier{true}; Atomic velocity_modifier_falloff{0.5f}; Atomic velocity_modifier_weight{0.25f}; @@ -51,45 +66,15 @@ struct Settings Atomic current_file; }; -//! Getter utility class. -template class SettingRef +//! Settings getter class. +struct SettingsGetter { -public: - SettingRef(Atomic& value) - : value(value) - { - // string isn't lock free either - assert((std::is_same::value || value.is_lock_free())); - } - - bool hasChanged() - { - T tmp = cache; - cache.exchange(value); - - if(firstAccess) - { - firstAccess = false; - return true; - } - - return tmp != cache; - } - - T getValue() const - { - return cache; - } + SettingRef drumkit_file; + SettingRef drumkit_load_status; -private: - bool firstAccess{true}; - Atomic& value; - Atomic cache; -}; + SettingRef midimap_file; + SettingRef midimap_load_status; -//! Combined getter class. -struct SettingsGetter -{ SettingRef enable_velocity_modifier; SettingRef velocity_modifier_falloff; SettingRef velocity_modifier_weight; @@ -106,7 +91,11 @@ struct SettingsGetter SettingRef current_file; SettingsGetter(Settings& settings) - : enable_velocity_modifier{settings.enable_velocity_modifier} + : drumkit_file(settings.drumkit_file) + , drumkit_load_status(settings.drumkit_load_status) + , midimap_file(settings.midimap_file) + , midimap_load_status(settings.midimap_load_status) + , enable_velocity_modifier{settings.enable_velocity_modifier} , velocity_modifier_falloff{settings.velocity_modifier_falloff} , velocity_modifier_weight{settings.velocity_modifier_weight} , enable_velocity_randomiser{settings.enable_velocity_randomiser} @@ -120,6 +109,66 @@ struct SettingsGetter } }; +//! Settings change notifier class. +class SettingsNotifier +{ +public: + Notifier drumkit_file; + Notifier drumkit_load_status; + + Notifier midimap_file; + Notifier midimap_load_status; + + Notifier enable_velocity_modifier; + Notifier velocity_modifier_falloff; + Notifier velocity_modifier_weight; + + Notifier enable_velocity_randomiser; + Notifier velocity_randomiser_weight; + + Notifier samplerate; + + Notifier enable_resampling; + + Notifier number_of_files; + Notifier number_of_files_loaded; + Notifier current_file; + + void evaluate() + { +#define EVAL(x) if(settings.x.hasChanged()) { x(settings.x.getValue()); } + + EVAL(drumkit_file); + EVAL(drumkit_load_status); + + EVAL(midimap_file); + EVAL(midimap_load_status); + + EVAL(enable_velocity_modifier); + EVAL(velocity_modifier_falloff); + EVAL(velocity_modifier_weight); + + EVAL(enable_velocity_randomiser); + EVAL(velocity_randomiser_weight); + + EVAL(samplerate); + + EVAL(enable_resampling); + + EVAL(number_of_files); + EVAL(number_of_files_loaded); + EVAL(current_file); + } + + SettingsNotifier(Settings& settings) + : settings(settings) + { + } + +private: + SettingsGetter settings; +}; + // lovely reminder: NO, GLOCKE. NOOOO!! /* enum class IntParams { -- cgit v1.2.3