summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2016-04-08 00:15:32 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2016-04-08 00:15:32 +0200
commit057ef1d83ba263fb2adf1aa86f8e281ab0065c43 (patch)
tree31c1f237e3a9df9fc241d87527f7dd4245665d43 /src
parentb530ac02af61e320e137a392decef1b3cc5af2c4 (diff)
Refactoring to finally get rid of MessageHandler/Receiver in favor of the new Settings mechanism.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/Makefile.am.drumgizmo2
-rw-r--r--src/atomic.h60
-rw-r--r--src/drumgizmo.cc149
-rw-r--r--src/drumgizmo.h14
-rw-r--r--src/drumkitloader.cc16
-rw-r--r--src/drumkitparser.cc2
-rw-r--r--src/instrument.cc19
-rw-r--r--src/message.h121
-rw-r--r--src/messagehandler.cc89
-rw-r--r--src/messagehandler.h66
-rw-r--r--src/messagereceiver.cc78
-rw-r--r--src/messagereceiver.h75
-rw-r--r--src/notifier.h163
-rw-r--r--src/settings.h123
15 files changed, 373 insertions, 610 deletions
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<std::mutex> lock{mutex};
+ return other == data;
+ }
+
+ bool operator!=(const T& other) const
+ {
+ std::lock_guard<std::mutex> lock{mutex};
+ return !(other == data);
+ }
+
+ bool operator==(const Atomic<T>& other) const
+ {
+ std::lock_guard<std::mutex> lock{mutex};
+ return other.load() == data;
+ }
+
+ bool operator!=(const Atomic<T>& other) const
+ {
+ std::lock_guard<std::mutex> lock{mutex};
+ return !(other.load() == data);
+ }
+
private:
T data;
mutable std::mutex mutex;
};
+
+//! Getter utility class.
+template <typename T> class SettingRef
+{
+public:
+ SettingRef(Atomic<T>& value)
+ : value(value)
+ {
+ // string isn't lock free either
+ assert((std::is_same<T, std::string>::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<T>& value;
+ Atomic<T> 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 <hugin.hpp>
#include <config.h>
+#include <memory>
#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<AudioInputEngineMidi*>(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<event_t> 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<AudioFile*>::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<Sample*> s = samples.get(level * mod);
if(s.size() == 0)
{
- return NULL;
+ return nullptr;
}
- //size_t idx = ::rand()%(s.size());
- sample = rand.choose<Sample*>(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 <string>
-
-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 <hugin.hpp>
-
-#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<message_receiver_id_t, MessageReceiver *>::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 <map>
-
-#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<message_receiver_id_t, MessageReceiver *> 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 <hugin.hpp>
-
-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 <list>
-
-#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 *> 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 <functional>
+#include <vector>
+#include <map>
+#include <set>
+#include <memory>
+
+namespace aux
+{
+ template<int>
+ struct placeholder
+ {
+ };
+}
+
+namespace std
+{
+ template<int N>
+ struct is_placeholder<aux::placeholder<N>>
+ : integral_constant<int, N+1>
+ {
+ };
+}
+
+namespace aux
+{
+ // std::integer_sequence introduced in C++14 so remove this once we start requiring that.
+
+ template<int... Ns>
+ struct int_sequence
+ {
+ };
+
+ template<int N, int... Ns>
+ struct gen_int_sequence
+ : gen_int_sequence<N-1, N-1, Ns...>
+ {
+ };
+
+ template<int... Ns>
+ struct gen_int_sequence<0, Ns...>
+ : int_sequence<Ns...>
+ {
+ };
+};
+
+
+//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<NotifierBase*> signals;
+};
+
+template<typename... Args>
+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<void(Args...)>;
+
+ //! \brief Connect object to this Notifier.
+ template<typename O, typename F>
+ void connect(O* p, const F& fn)
+ {
+ slots[p] = std::move(construct_mem_fn(fn, p, aux::gen_int_sequence<sizeof...(Args)>{}));
+ if(p && dynamic_cast<Listener*>(p))
+ {
+ dynamic_cast<Listener*>(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<int> foo; foo(42);
+ void operator()(Args... args)
+ {
+ for(auto& slot : slots)
+ {
+ slot.second(args...);
+ }
+ }
+
+private:
+ std::map<Listener*, callback_type> slots;
+
+ template<typename F, typename O, int... Ns>
+ callback_type construct_mem_fn(const F& fn, O* p, aux::int_sequence<Ns...>) const
+ {
+ return std::bind(fn, p, aux::placeholder<Ns>{}...);
+ }
+
+};
+
+//} // 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 <cassert>
#include "atomic.h"
+#include "notifier.h"
+
+enum class LoadStatus : unsigned int
+{
+ Idle,
+ Loading,
+ Done,
+ Error
+};
//! Engine settings
struct Settings
{
+ Atomic<std::string> drumkit_file;
+ Atomic<LoadStatus> drumkit_load_status{LoadStatus::Idle};
+
+ Atomic<std::string> midimap_file;
+ Atomic<LoadStatus> midimap_load_status{LoadStatus::Idle};
+
Atomic<bool> enable_velocity_modifier{true};
Atomic<float> velocity_modifier_falloff{0.5f};
Atomic<float> velocity_modifier_weight{0.25f};
@@ -51,45 +66,15 @@ struct Settings
Atomic<std::string> current_file;
};
-//! Getter utility class.
-template <typename T> class SettingRef
+//! Settings getter class.
+struct SettingsGetter
{
-public:
- SettingRef(Atomic<T>& value)
- : value(value)
- {
- // string isn't lock free either
- assert((std::is_same<T, std::string>::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<std::string> drumkit_file;
+ SettingRef<LoadStatus> drumkit_load_status;
-private:
- bool firstAccess{true};
- Atomic<T>& value;
- Atomic<T> cache;
-};
+ SettingRef<std::string> midimap_file;
+ SettingRef<LoadStatus> midimap_load_status;
-//! Combined getter class.
-struct SettingsGetter
-{
SettingRef<bool> enable_velocity_modifier;
SettingRef<float> velocity_modifier_falloff;
SettingRef<float> velocity_modifier_weight;
@@ -106,7 +91,11 @@ struct SettingsGetter
SettingRef<std::string> 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<std::string> drumkit_file;
+ Notifier<LoadStatus> drumkit_load_status;
+
+ Notifier<std::string> midimap_file;
+ Notifier<LoadStatus> midimap_load_status;
+
+ Notifier<bool> enable_velocity_modifier;
+ Notifier<float> velocity_modifier_falloff;
+ Notifier<float> velocity_modifier_weight;
+
+ Notifier<bool> enable_velocity_randomiser;
+ Notifier<float> velocity_randomiser_weight;
+
+ Notifier<double> samplerate;
+
+ Notifier<bool> enable_resampling;
+
+ Notifier<int> number_of_files;
+ Notifier<int> number_of_files_loaded;
+ Notifier<std::string> 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 {