summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2016-04-16 13:33:53 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2016-04-16 13:33:53 +0200
commit4eb252df04ab237c8638d45bcbf028859dc6a110 (patch)
tree8bffddf62b4271336a6e0121fef8133327654000 /src
parentef68248bf70a027595803b08433a7a2c74e20fd0 (diff)
parent35e804b984c28131fe13d229c5a0867762c6e8cf (diff)
Merge branch 'settings'
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/Makefile.am.drumgizmo3
-rw-r--r--src/atomic.h182
-rw-r--r--src/audiofile.cc2
-rw-r--r--src/configuration.cc38
-rw-r--r--src/configuration.h44
-rw-r--r--src/drumgizmo.cc196
-rw-r--r--src/drumgizmo.h20
-rw-r--r--src/drumkit.cc24
-rw-r--r--src/drumkit.h2
-rw-r--r--src/drumkitloader.cc101
-rw-r--r--src/drumkitloader.h16
-rw-r--r--src/drumkitparser.cc45
-rw-r--r--src/drumkitparser.h3
-rw-r--r--src/instrument.cc82
-rw-r--r--src/instrument.h8
-rw-r--r--src/instrumentparser.cc62
-rw-r--r--src/instrumentparser.h2
-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/midimapparser.cc3
-rw-r--r--src/midimapparser.h2
-rw-r--r--src/notifier.h163
-rw-r--r--src/path.cc18
-rw-r--r--src/path.h1
-rw-r--r--src/sample.cc21
-rw-r--r--src/sample.h22
-rw-r--r--src/saxparser.cc66
-rw-r--r--src/saxparser.h19
-rw-r--r--src/semaphore.cc96
-rw-r--r--src/semaphore.h24
-rw-r--r--src/settings.h181
-rw-r--r--src/syncedsettings.h106
36 files changed, 942 insertions, 1047 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index a1b1615..4d167af 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,6 @@ EXTRA_DIST = \
channelmixer.h \
chresampler.h \
configfile.h \
- configuration.h \
configparser.h \
cpp11fix.h \
drumgizmo.h \
@@ -24,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 \
@@ -54,7 +51,6 @@ EXTRA_DIST = \
channelmixer.cc \
chresampler.cc \
configfile.cc \
- configuration.cc \
configparser.cc \
drumgizmo.cc \
drumkit.cc \
@@ -64,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 8f648d0..6fddded 100644
--- a/src/Makefile.am.drumgizmo
+++ b/src/Makefile.am.drumgizmo
@@ -11,7 +11,6 @@ DRUMGIZMO_SOURCES = \
$(top_srcdir)/src/channelmixer.cc \
$(top_srcdir)/src/chresampler.cc \
$(top_srcdir)/src/configfile.cc \
- $(top_srcdir)/src/configuration.cc \
$(top_srcdir)/src/configparser.cc \
$(top_srcdir)/src/drumgizmo.cc \
$(top_srcdir)/src/drumkit.cc \
@@ -21,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
new file mode 100644
index 0000000..95a5e9d
--- /dev/null
+++ b/src/atomic.h
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * atomic.h
+ *
+ * Wed Mar 23 09:15:05 CET 2016
+ * Copyright 2016 Christian Glöckner
+ * cgloeckner@freenet.de
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <type_traits>
+#include <atomic>
+
+#include <mutex>
+#include "mutex.h"
+
+template <typename T, typename = void>
+class Atomic;
+
+// use std::atomic if possible
+template <typename T>
+class Atomic<T, typename std::enable_if<std::is_pod<T>::value>::type>
+ : public std::atomic<T>
+{
+public:
+ // inherit methods
+ using std::atomic<T>::atomic;
+ using std::atomic<T>::operator=;
+};
+
+// else work around it using a mutex
+template <typename T>
+class Atomic<T, typename std::enable_if<!std::is_pod<T>::value>::type>
+{
+public:
+ using self_type =
+ Atomic<T, typename std::enable_if<!std::is_pod<T>::value>::type>;
+
+ Atomic()
+ : data{}
+ , mutex{}
+ {
+ }
+
+ Atomic(T data)
+ : data{std::move(data)}
+ , mutex{}
+ {
+ }
+
+ Atomic(self_type const & other)
+ : data{}
+ , mutex{}
+ {
+ std::lock_guard<std::mutex> lock{other.mutex};
+ data = other.data;
+ }
+
+ Atomic(self_type&& other)
+ : data{}
+ , mutex{}
+ {
+ std::lock_guard<std::mutex> lock{other.mutex};
+ std::swap(data, other.data);
+ }
+
+ T operator=(T data)
+ {
+ std::lock_guard<std::mutex> lock{mutex};
+ this->data = std::move(data);
+ return this->data;
+ }
+
+ operator T() const
+ {
+ return load();
+ }
+
+ bool is_lock_free() const
+ {
+ return false;
+ }
+
+ void store(T data)
+ {
+ std::lock_guard<std::mutex> lock{mutex};
+ this->data = std::move(data);
+ }
+
+ T load() const {
+ std::lock_guard<std::mutex> lock{mutex};
+ return data;
+ }
+
+ T exchange(T data){
+ std::lock_guard<std::mutex> lock{mutex};
+ std::swap(data, this->data);
+ 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/audiofile.cc b/src/audiofile.cc
index 58b248b..84329f8 100644
--- a/src/audiofile.cc
+++ b/src/audiofile.cc
@@ -36,8 +36,6 @@
#include <sndfile.h>
#include <hugin.hpp>
-#include "configuration.h"
-
AudioFile::AudioFile(const std::string& filename, int filechannel)
{
is_loaded = false;
diff --git a/src/configuration.cc b/src/configuration.cc
deleted file mode 100644
index 72f6e4a..0000000
--- a/src/configuration.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/***************************************************************************
- * configuration.cc
- *
- * Sat Oct 8 14:37:14 CEST 2011
- * Copyright 2011 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 "configuration.h"
-
-bool Conf::enable_velocity_modifier = true;
-float Conf::velocity_modifier_falloff = 0.5;
-float Conf::velocity_modifier_weight = 0.25;
-
-bool Conf::enable_velocity_randomiser = false;
-float Conf::velocity_randomiser_weight = 0.1;
-
-int Conf::samplerate = 44100;
-
-bool Conf::enable_resampling = true;
diff --git a/src/configuration.h b/src/configuration.h
deleted file mode 100644
index 3adf525..0000000
--- a/src/configuration.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/***************************************************************************
- * configuration.h
- *
- * Sat Oct 8 14:37:13 CEST 2011
- * Copyright 2011 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_CONFIGURATION_H__
-#define __DRUMGIZMO_CONFIGURATION_H__
-
-namespace Conf {
- extern bool enable_velocity_modifier;
- extern float velocity_modifier_falloff;
- extern float velocity_modifier_weight;
-
- extern bool enable_velocity_randomiser;
- extern float velocity_randomiser_weight;
-
- extern int samplerate;
-
- extern bool enable_resampling;
-};
-
-
-#endif/*__DRUMGIZMO_CONFIGURATION_H__*/
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index 853e93d..aa6be23 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -38,26 +38,27 @@
#include <hugin.hpp>
#include <config.h>
+#include <memory>
#include "drumkitparser.h"
#include "audioinputenginemidi.h"
-#include "configuration.h"
#include "configparser.h"
#include "nolocale.h"
-DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i)
- : MessageReceiver(MSGRCV_ENGINE)
- , loader()
+DrumGizmo::DrumGizmo(Settings& settings,
+ AudioOutputEngine *o, AudioInputEngine *i)
+ : loader(settings)
, oe(o)
, ie(i)
, framesize(0)
, freewheel(false)
, events{}
+ , settings(settings)
{
is_stopping = false;
audioCache.init(10000); // start thread
-
+
events.reserve(1000);
}
@@ -68,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());
@@ -81,27 +85,31 @@ bool DrumGizmo::loadkit(std::string file)
// Delete all Channels, Instruments, Samples and AudioFiles.
kit.clear();
- DrumKitParser parser(kit);
+ 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);
#ifdef WITH_RESAMPLER
for(int i = 0; i < MAX_NUM_CHANNELS; ++i)
{
- resampler[i].setup(kit.getSamplerate(), Conf::samplerate);
+ resampler[i].setup(kit.getSamplerate(), settings.samplerate.load());
}
#endif/*WITH_RESAMPLER*/
@@ -125,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 = Conf::enable_velocity_modifier;
- msg->velocity_modifier_falloff = Conf::velocity_modifier_falloff;
- msg->velocity_modifier_weight = Conf::velocity_modifier_weight;
- msg->enable_velocity_randomiser = Conf::enable_velocity_randomiser;
- msg->velocity_randomiser_weight = Conf::velocity_randomiser_weight;
- msghandler.sendMessage(MSGRCV_UI, msg);
- }
- break;
- case Message::ChangeSettingMessage:
- {
- ChangeSettingMessage *ch = (ChangeSettingMessage*)msg;
- switch(ch->name) {
- case ChangeSettingMessage::enable_velocity_modifier:
- Conf::enable_velocity_modifier = ch->value;
- break;
- case ChangeSettingMessage::velocity_modifier_weight:
- Conf::velocity_modifier_weight = ch->value;
- break;
- case ChangeSettingMessage::velocity_modifier_falloff:
- Conf::velocity_modifier_falloff = ch->value;
- break;
- }
- }
- break;
- default:
- break;
- }
-}
-
void DrumGizmo::setFrameSize(size_t framesize)
{
// If we are resampling override the frame size.
@@ -259,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);
@@ -398,7 +356,7 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)
// Write audio
//
#ifdef WITH_RESAMPLER
- if((Conf::enable_resampling == false) ||
+ if((settings.enable_resampling.load() == false) ||
(resampler[0].getRatio() == 1.0)) // No resampling needed
{
#endif
@@ -636,17 +594,17 @@ void DrumGizmo::stop()
int DrumGizmo::samplerate()
{
- return Conf::samplerate;
+ return settings.samplerate.load();
}
void DrumGizmo::setSamplerate(int samplerate)
{
DEBUG(dgeditor, "%s samplerate: %d\n", __PRETTY_FUNCTION__, samplerate);
- Conf::samplerate = samplerate;
+ settings.samplerate.store(samplerate);
#ifdef WITH_RESAMPLER
for(int i = 0; i < MAX_NUM_CHANNELS; ++i)
{
- resampler[i].setup(kit.getSamplerate(), Conf::samplerate);
+ resampler[i].setup(kit.getSamplerate(), settings.samplerate.load());
}
if(resampler[0].getRatio() != 1)
{
@@ -691,15 +649,15 @@ std::string DrumGizmo::configString()
" <value name=\"drumkitfile\">" + kit.getFile() + "</value>\n"
" <value name=\"midimapfile\">" + mmapfile + "</value>\n"
" <value name=\"enable_velocity_modifier\">" +
- bool2str(Conf::enable_velocity_modifier) + "</value>\n"
+ bool2str(settings.enable_velocity_modifier.load()) + "</value>\n"
" <value name=\"velocity_modifier_falloff\">" +
- float2str(Conf::velocity_modifier_falloff) + "</value>\n"
+ float2str(settings.velocity_modifier_falloff.load()) + "</value>\n"
" <value name=\"velocity_modifier_weight\">" +
- float2str(Conf::velocity_modifier_weight) + "</value>\n"
+ float2str(settings.velocity_modifier_weight.load()) + "</value>\n"
" <value name=\"enable_velocity_randomiser\">" +
- bool2str(Conf::enable_velocity_randomiser) + "</value>\n"
+ bool2str(settings.enable_velocity_randomiser.load()) + "</value>\n"
" <value name=\"velocity_randomiser_weight\">" +
- float2str(Conf::velocity_randomiser_weight) + "</value>\n"
+ float2str(settings.velocity_randomiser_weight.load()) + "</value>\n"
"</config>";
}
@@ -711,68 +669,50 @@ 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") != "")
{
- Conf::enable_velocity_modifier =
- p.value("enable_velocity_modifier") == "true";
+ settings.enable_velocity_modifier.store(p.value("enable_velocity_modifier") == "true");
}
if(p.value("velocity_modifier_falloff") != "")
{
- Conf::velocity_modifier_falloff =
- str2float(p.value("velocity_modifier_falloff"));
+ settings.velocity_modifier_falloff.store(str2float(p.value("velocity_modifier_falloff")));
}
if(p.value("velocity_modifier_weight") != "")
{
- Conf::velocity_modifier_weight =
- str2float(p.value("velocity_modifier_weight"));
+ settings.velocity_modifier_weight.store(str2float(p.value("velocity_modifier_weight")));
}
if(p.value("enable_velocity_randomiser") != "")
{
- Conf::enable_velocity_randomiser =
- p.value("enable_velocity_randomiser") == "true";
+ settings.enable_velocity_randomiser.store(p.value("enable_velocity_randomiser") == "true");
}
if(p.value("velocity_randomiser_weight") != "")
{
- Conf::velocity_randomiser_weight =
- str2float(p.value("velocity_randomiser_weight"));
+ settings.velocity_randomiser_weight.store(str2float(p.value("velocity_randomiser_weight")));
}
if(p.value("enable_resampling") != "")
{
- Conf::enable_resampling =
- p.value("enable_resampling") == "true";
+ settings.enable_resampling.store(p.value("enable_resampling") == "true");
}
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 632d5fc..7af5dbb 100644
--- a/src/drumgizmo.h
+++ b/src/drumgizmo.h
@@ -31,34 +31,26 @@
#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
#define REFSFILE "refs.conf"
#define RESAMPLER_INPUT_BUFFER 64
class DrumGizmo
- : public MessageReceiver
{
public:
- DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine);
+ DrumGizmo(Settings& settings,
+ AudioOutputEngine *outputengine, AudioInputEngine *inputengine);
virtual ~DrumGizmo();
bool loadkit(std::string kitfile);
@@ -74,8 +66,6 @@ public:
std::string configString();
bool setConfigString(std::string cfg);
- void handleMessage(Message *msg);
-
int samplerate();
void setSamplerate(int samplerate);
@@ -106,6 +96,8 @@ protected:
size_t framesize;
bool freewheel;
-
+
std::vector<event_t> events;
+ Settings& settings;
+ SettingsGetter getter{settings};
};
diff --git a/src/drumkit.cc b/src/drumkit.cc
index 1b95c87..f25a6ea 100644
--- a/src/drumkit.cc
+++ b/src/drumkit.cc
@@ -39,12 +39,11 @@ DrumKit::~DrumKit()
void DrumKit::clear()
{
- Instruments::iterator i = instruments.begin();
- while(i != instruments.end())
+ for(auto& instrument : instruments)
{
- delete *i;
- i++;
+ delete instrument;
}
+
instruments.clear();
channels.clear();
@@ -78,20 +77,3 @@ size_t DrumKit::getSamplerate() const
{
return _samplerate;
}
-
-#ifdef TEST_DRUMKIT
-// Additional dependency files
-// deps:
-// Required cflags (autoconf vars may be used)
-// cflags:
-// Required link options (autoconf vars may be used)
-// libs:
-#include "test.h"
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-
-TEST_END;
-
-#endif /*TEST_DRUMKIT*/
diff --git a/src/drumkit.h b/src/drumkit.h
index 1ceef3e..e3ae783 100644
--- a/src/drumkit.h
+++ b/src/drumkit.h
@@ -33,11 +33,9 @@
#include "instrument.h"
#include "versionstr.h"
-class DrumKitParser;
class DrumKit
{
friend class DrumKitParser;
-
public:
DrumKit();
~DrumKit();
diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc
index ff489ea..3a0e096 100644
--- a/src/drumkitloader.cc
+++ b/src/drumkitloader.cc
@@ -26,14 +26,17 @@
*/
#include "drumkitloader.h"
+#include <iostream>
+
#include <hugin.hpp>
#include "drumkitparser.h"
#include "drumgizmo.h"
-DrumKitLoader::DrumKitLoader()
- : semaphore("drumkitloader")
- , framesize(0)
+DrumKitLoader::DrumKitLoader(Settings& settings)
+ : framesize(0)
+ , settings(settings)
+ , getter(settings)
{
run();
run_semaphore.wait(); // Wait for the thread to actually start.
@@ -55,7 +58,7 @@ DrumKitLoader::~DrumKitLoader()
void DrumKitLoader::stop()
{
{
- MutexAutolock l(mutex);
+ std::lock_guard<std::mutex> guard(mutex);
load_queue.clear();
}
@@ -66,68 +69,48 @@ void DrumKitLoader::stop()
void DrumKitLoader::skip()
{
- MutexAutolock l(mutex);
+ std::lock_guard<std::mutex> guard(mutex);
load_queue.clear();
}
void DrumKitLoader::setFrameSize(size_t framesize)
{
- DEBUG(loader, "%s pre\n", __PRETTY_FUNCTION__);
-
- {
- MutexAutolock l(mutex);
- this->framesize = framesize;
- framesize_semaphore.post(); // Signal that the framesize has been set.
- }
-
- DEBUG(loader, "%s post\n", __PRETTY_FUNCTION__);
+ std::lock_guard<std::mutex> guard(mutex);
+ this->framesize = framesize;
+ framesize_semaphore.post(); // Signal that the framesize has been set.
}
bool DrumKitLoader::isDone()
{
- MutexAutolock l(mutex);
+ std::lock_guard<std::mutex> guard(mutex);
return load_queue.size() == 0;
}
void DrumKitLoader::loadKit(DrumKit *kit)
{
- MutexAutolock l(mutex);
+ std::lock_guard<std::mutex> guard(mutex);
DEBUG(loader, "Create AudioFile queue from DrumKit\n");
- total_num_audiofiles = 0;// For UI Progress Messages
-
- { // Count total number of files that need loading:
- Instruments::iterator i = kit->instruments.begin();
- while(i != kit->instruments.end())
- {
- Instrument *instr = *i;
- total_num_audiofiles += instr->audiofiles.size();
- ++i;
- }
- }
+ std::size_t total_num_audiofiles = 0;// For UI Progress Messages
- fraction = total_num_audiofiles / 200;
- if(fraction == 0)
+ // Count total number of files that need loading:
+ for(auto instr : kit->instruments)
{
- fraction = 1;
+ total_num_audiofiles += instr->audiofiles.size();
}
- { // Now actually queue them for loading:
- Instruments::iterator i = kit->instruments.begin();
- while(i != kit->instruments.end())
- {
- Instrument *instr = *i;
-
- std::vector<AudioFile*>::iterator af = instr->audiofiles.begin();
- while(af != instr->audiofiles.end())
- {
- AudioFile *audiofile = *af;
- load_queue.push_back(audiofile);
- af++;
- }
+ settings.number_of_files.store(total_num_audiofiles);
- ++i;
+ // Now actually queue them for loading:
+ for(auto instr : kit->instruments)
+ {
+ std::vector<AudioFile*>::iterator af = instr->audiofiles.begin();
+ while(af != instr->audiofiles.end())
+ {
+ AudioFile *audiofile = *af;
+ load_queue.push_back(audiofile);
+ af++;
}
}
@@ -151,23 +134,35 @@ void DrumKitLoader::thread_main()
{
size_t size;
{
- MutexAutolock l(mutex);
+ std::lock_guard<std::mutex> guard(mutex);
size = load_queue.size();
}
// Only sleep if queue is empty.
if(size == 0)
{
- semaphore.wait();
+ semaphore.wait(std::chrono::milliseconds(1000));
+ }
+
+ if(getter.drumkit_file.hasChanged())
+ {
+ //std::cout << "RELOAD DRUMKIT!" << std::endl;
+ }
+
+ if(getter.midimap_file.hasChanged())
+ {
+ //std::cout << "RELOAD MIDIMAP!" << std::endl;
}
std::string filename;
{
- MutexAutolock l(mutex);
+ std::lock_guard<std::mutex> guard(mutex);
+
if(load_queue.size() == 0)
{
continue;
}
+
AudioFile *audiofile = load_queue.front();
load_queue.pop_front();
filename = audiofile->filename;
@@ -183,15 +178,13 @@ void DrumKitLoader::thread_main()
audiofile->load(preload_size);
}
- loaded++;
+ ++loaded;
+
+ settings.number_of_files_loaded.store(loaded);
- if(loaded % fraction == 0 || loaded == total_num_audiofiles)
+ if(settings.number_of_files.load() == 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.drumkit_load_status.store(LoadStatus::Done);
}
}
diff --git a/src/drumkitloader.h b/src/drumkitloader.h
index 3656839..3fd7ec1 100644
--- a/src/drumkitloader.h
+++ b/src/drumkitloader.h
@@ -28,12 +28,14 @@
#include <string>
#include <list>
+#include <mutex>
+#include "mutex.h"
#include "thread.h"
#include "semaphore.h"
-#include "mutex.h"
#include "drumkit.h"
+#include "settings.h"
//! This class is responsible for loading the drumkits in its own thread.
//! All interaction calls are simply modifying queues and not doing any
@@ -45,7 +47,7 @@ class DrumKitLoader
{
public:
//! The constrcutor starts the loader thread.
- DrumKitLoader();
+ DrumKitLoader(Settings& settings);
//! The destructor signals the thread to stop and waits to merge before
//! returning (ie. deleting the object will garantuee that the thread has
@@ -75,11 +77,11 @@ protected:
Semaphore run_semaphore;
Semaphore semaphore;
Semaphore framesize_semaphore;
- Mutex mutex;
+ std::mutex mutex;
volatile bool running{false};
std::list<AudioFile*> load_queue;
- size_t total_num_audiofiles{0};
- size_t fraction{1};
- size_t loaded{0};
- size_t framesize{0};
+ std::size_t loaded{0};
+ std::size_t framesize{0};
+ Settings& settings;
+ SettingsGetter getter;
};
diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc
index 3ba69c8..048a05b 100644
--- a/src/drumkitparser.cc
+++ b/src/drumkitparser.cc
@@ -34,9 +34,10 @@
#include "path.h"
#include "drumgizmo.h"
-DrumKitParser::DrumKitParser(DrumKit& kit)
- : kit(kit)
- , refs(REFSFILE)
+DrumKitParser::DrumKitParser(Settings& settings, DrumKit& k)
+ : kit(k)
+ , refs(REFSFILE)
+ , settings(settings)
{
}
@@ -46,9 +47,9 @@ int DrumKitParser::parseFile(const std::string& filename)
if(refs.load())
{
- if(filename.size() > 1 && filename[0] == '@')
+ if((filename.size() > 1) && (filename[0] == '@'))
{
- edited_filename = refs.getValue(filename.substr(1));
+ edited_filename = refs.getValue(filename.substr(1));
}
}
else
@@ -57,9 +58,10 @@ int DrumKitParser::parseFile(const std::string& filename)
}
path = getPath(edited_filename);
- auto result = SAXParser::parseFile(filename);
+ auto result = SAXParser::parseFile(edited_filename);
- if (result == 0) {
+ if(result == 0)
+ {
kit._file = edited_filename;
}
@@ -101,7 +103,7 @@ void DrumKitParser::startTag(const std::string& name, const attr_t& attr)
{
ERR(kitparser, "Error parsing version number: %s, using 1.0\n", err);
kit._version = VersionStr(1,0,0);
- }
+ }
}
else
{
@@ -112,7 +114,7 @@ void DrumKitParser::startTag(const std::string& name, const attr_t& attr)
if(name == "channels")
{
-
+
}
if(name == "channel")
@@ -140,6 +142,7 @@ void DrumKitParser::startTag(const std::string& name, const attr_t& attr)
ERR(kitparser, "Missing name in instrument tag.\n");
return;
}
+
if(attr.find("file") == attr.end())
{
ERR(kitparser, "Missing file in instrument tag.\n");
@@ -180,12 +183,14 @@ void DrumKitParser::endTag(const std::string& name)
{
if(name == "instrument")
{
- Instrument* i = new Instrument();
- i->setGroup(instr_group);
- // Instrument &i = kit.instruments[kit.instruments.size() - 1];
- InstrumentParser parser(*i);
+ Instrument* instrument = new Instrument(settings);
+ instrument->setGroup(instr_group);
+
+ InstrumentParser parser(*instrument);
parser.parseFile(path + "/" + instr_file);
- kit.instruments.push_back(i);
+
+ // Transfer ownership to the DrumKit object.
+ kit.instruments.push_back(instrument);
// Assign kit channel numbers to instruments channels.
std::vector<InstrumentChannel*>::iterator ic = parser.channellist.begin();
@@ -206,16 +211,18 @@ void DrumKitParser::endTag(const std::string& name)
c->num = kit.channels[cnt].num;
}
}
+
if(c->num == NO_CHANNEL)
{
ERR(kitparser, "Missing channel '%s' in instrument '%s'\n",
- c->name.c_str(), i->getName().c_str());
+ c->name.c_str(), instrument->getName().c_str());
}
- else {
+ else
+ {
/*
- DEBUG(kitparser, "Assigned channel '%s' to number %d in instrument '%s'\n",
- c->name.c_str(), c->num, i.name().c_str());
- */
+ DEBUG(kitparser, "Assigned channel '%s' to number %d in instrument '%s'\n",
+ c->name.c_str(), c->num, i.name().c_str());
+ */
}
ic++;
}
diff --git a/src/drumkitparser.h b/src/drumkitparser.h
index b0c8d8f..0adccb9 100644
--- a/src/drumkitparser.h
+++ b/src/drumkitparser.h
@@ -34,7 +34,7 @@ class DrumKitParser
: public SAXParser
{
public:
- DrumKitParser(DrumKit& kit);
+ DrumKitParser(Settings& setting, DrumKit& kit);
virtual int parseFile(const std::string& filename) override;
@@ -52,4 +52,5 @@ private:
std::string instr_group;
ConfigFile refs;
+ Settings& settings;
};
diff --git a/src/instrument.cc b/src/instrument.cc
index 9f18233..cc052e9 100644
--- a/src/instrument.cc
+++ b/src/instrument.cc
@@ -26,15 +26,12 @@
*/
#include "instrument.h"
-#include <stdlib.h>
-#include <stdio.h>
-
#include <hugin.hpp>
#include "sample.h"
-#include "configuration.h"
-Instrument::Instrument()
+Instrument::Instrument(Settings& settings)
+ : settings(settings)
{
DEBUG(instrument, "new %p\n", this);
mod = 1.0;
@@ -45,7 +42,7 @@ Instrument::Instrument()
Instrument::~Instrument()
{
- magic = NULL;
+ magic = nullptr;
DEBUG(instrument, "delete %p\n", this);
std::vector<AudioFile*>::iterator i = audiofiles.begin();
@@ -63,16 +60,26 @@ 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();
+ auto samplerate = settings.samplerate.load();
+ auto velocity_modifier_falloff = settings.velocity_modifier_falloff.load();
+ auto enable_velocity_modifier = settings.enable_velocity_modifier.load();
+ auto velocity_modifier_weight = settings.velocity_modifier_weight.load();
+
+ Sample *sample = nullptr;
- if(Conf::enable_velocity_modifier == false) {
+ if(enable_velocity_modifier == false)
+ {
mod = 1.0;
lastpos = 0;
}
- if(Conf::enable_velocity_randomiser) {
- float r = rand.floatInRange(-1.0*Conf::velocity_randomiser_weight,
- Conf::velocity_randomiser_weight);
+ if(enable_velocity_randomiser)
+ {
+ float r = rand.floatInRange(-1.0 * velocity_randomiser_weight,
+ velocity_randomiser_weight);
level += r;
if(level > 1.0)
{
@@ -84,9 +91,9 @@ Sample* Instrument::sample(level_t level, size_t pos)
}
}
- if(Conf::enable_velocity_modifier) {
- mod += (pos - lastpos) /
- (Conf::samplerate * Conf::velocity_modifier_falloff);
+ if(enable_velocity_modifier)
+ {
+ mod += (pos - lastpos) / (samplerate * velocity_modifier_falloff);
if(mod > 1.0)
{
mod = 1.0;
@@ -98,21 +105,22 @@ Sample* Instrument::sample(level_t level, size_t pos)
// Version 2.0
sample = powerlist.get(level * mod);
}
- else {
+ else
+ {
// Version 1.0
std::vector<Sample*> s = samples.get(level * mod);
if(s.size() == 0)
{
- return NULL;
+ return nullptr;
}
sample = rand.choose(s);
}
- if(Conf::enable_velocity_modifier)
+ if(enable_velocity_modifier)
{
lastpos = pos;
- mod *= Conf::velocity_modifier_weight;
+ mod *= velocity_modifier_weight;
}
return sample;
@@ -157,41 +165,3 @@ void Instrument::setGroup(const std::string& g)
{
_group = g;
}
-
-#ifdef TEST_INSTRUMENT
-// deps: channel.cc sample.cc audiofile.cc
-// cflags: $(SNDFILE_CFLAGS)
-// libs: $(SNDFILE_LIBS)
-#include "test.h"
-
-TEST_BEGIN;
-
-Instrument i("test");
-
-Sample* a = new Sample();
-i.addSample(0.0, 1.0, a);
-
-Sample* b = new Sample();
-i.addSample(0.0, 1.0, b);
-
-Sample* c = new Sample();
-i.addSample(1.5, 1.7, c);
-
-TEST_EQUAL(i.sample(0.0), b, "?");
-TEST_EQUAL(i.sample(0.0), a, "?");
-TEST_EQUAL(i.sample(0.0), b, "?");
-TEST_EQUAL(i.sample(0.0), b, "?");
-TEST_EQUAL(i.sample(0.0), b, "?");
-TEST_EQUAL(i.sample(0.0), b, "?");
-TEST_EQUAL(i.sample(0.0), a, "?");
-TEST_EQUAL(i.sample(0.0), a, "?");
-
-TEST_EQUAL(i.sample(2.0), NULL, "?");
-
-TEST_EQUAL(i.sample(1.6), c, "?");
-TEST_EQUAL(i.sample(1.6), c, "?");
-TEST_EQUAL(i.sample(1.6), c, "?");
-
-TEST_END;
-
-#endif /*TEST_INSTRUMENT*/
diff --git a/src/instrument.h b/src/instrument.h
index de5546b..a531aec 100644
--- a/src/instrument.h
+++ b/src/instrument.h
@@ -36,13 +36,13 @@
#include "versionstr.h"
#include "random.h"
-class InstrumentParser;
+#include "settings.h"
+
class Instrument
{
friend class InstrumentParser;
-
public:
- Instrument();
+ Instrument(Settings& settings);
~Instrument();
Sample* sample(level_t level, size_t pos);
@@ -78,7 +78,7 @@ private:
size_t lastpos;
float mod;
-
+ Settings& settings;
Random rand;
};
diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc
index 268f8f3..1e42cc3 100644
--- a/src/instrumentparser.cc
+++ b/src/instrumentparser.cc
@@ -35,8 +35,8 @@
#include "nolocale.h"
-InstrumentParser::InstrumentParser(Instrument& i)
- : instrument(i)
+InstrumentParser::InstrumentParser(Instrument& instrument)
+ : instrument(instrument)
{
}
@@ -64,14 +64,15 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr)
if(attr.find("version") != attr.end())
{
- try {
+ try
+ {
instrument.version = VersionStr(attr.at("version"));
}
- catch(const char *err)
+ catch(const char* err)
{
ERR(instrparser, "Error parsing version number: %s, using 1.0\n", err);
instrument.version = VersionStr(1,0,0);
- }
+ }
}
else
{
@@ -82,7 +83,6 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr)
if(name == "samples")
{
-
}
if(name == "sample")
@@ -93,10 +93,10 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr)
return;
}
- float power;
+ float power;
if(attr.find("power") == attr.end())
{
- power = -1;
+ power = -1;
}
else
{
@@ -105,12 +105,12 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr)
}
// TODO get rid of new or delete it properly
- s = new Sample(attr.at("name"), power);
+ sample = new Sample(attr.at("name"), power);
}
if(name == "audiofile")
{
- if(s == nullptr)
+ if(sample == nullptr)
{
ERR(instrparser,"Missing Sample!\n");
return;
@@ -139,18 +139,24 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr)
}
}
- filechannel = filechannel - 1; // 1-based in file, but zero-based internally
- // TODO do those next two lines correspond with proper deletes? If not fix it.
- AudioFile *af = new AudioFile(path + "/" + attr.at("file"), filechannel);
- InstrumentChannel *ch = new InstrumentChannel(attr.at("channel"));
- channellist.push_back(ch);
- s->addAudioFile(ch, af);
- instrument.audiofiles.push_back(af);
+ filechannel = filechannel - 1; // 1-based in file but zero-based internally.
+
+ AudioFile *audio_file =
+ new AudioFile(path + "/" + attr.at("file"), filechannel);
+
+ // TODO: This is not deleted anywhere...
+ InstrumentChannel *instrument_channel =
+ new InstrumentChannel(attr.at("channel"));
+
+ channellist.push_back(instrument_channel);
+ sample->addAudioFile(instrument_channel, audio_file);
+
+ // Transfer audio_file ownership to the instrument.
+ instrument.audiofiles.push_back(audio_file);
}
if(name == "velocities")
{
-
}
if(name == "velocity")
@@ -179,19 +185,17 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr)
return;
}
- Sample* sample = nullptr;
- std::vector<Sample *>::iterator i = instrument.samplelist.begin();
- while(i != instrument.samplelist.end())
+ Sample* sample_ref = nullptr;
+ for(auto& sample : instrument.samplelist)
{
- if((*i)->name == attr.at("name"))
+ if(sample->name == attr.at("name"))
{
- sample = *i;
+ sample_ref = sample;
break;
}
- i++;
}
- if(sample == nullptr)
+ if(sample_ref == nullptr)
{
ERR(instrparser,"Samplref pointed at non-existing sample.\n");
return;
@@ -200,7 +204,7 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr)
if(instrument.version == VersionStr("1.0"))
{
// Old "velocity group" algorithm needs this
- instrument.addSample(lower, upper, sample);
+ instrument.addSample(lower, upper, sample_ref);
}
}
}
@@ -209,15 +213,15 @@ void InstrumentParser::endTag(const std::string& name)
{
if(name == "sample")
{
- if(s == nullptr)
+ if(sample == nullptr)
{
ERR(instrparser,"Missing Sample.\n");
return;
}
- instrument.samplelist.push_back(s);
+ instrument.samplelist.push_back(sample);
- s = nullptr;
+ sample = nullptr;
}
if(name == "instrument") {
diff --git a/src/instrumentparser.h b/src/instrumentparser.h
index 965694a..6cbaf8a 100644
--- a/src/instrumentparser.h
+++ b/src/instrumentparser.h
@@ -47,7 +47,7 @@ protected:
private:
Instrument& instrument;
- Sample* s{nullptr};
+ Sample* sample{nullptr};
std::string path;
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/midimapparser.cc b/src/midimapparser.cc
index ec4c10d..cc97280 100644
--- a/src/midimapparser.cc
+++ b/src/midimapparser.cc
@@ -30,7 +30,8 @@ void MidiMapParser::startTag(const std::string& name, const attr_t& attr)
{
if(name == "map")
{
- if(attr.find("note") != attr.end() && attr.find("instr") != attr.end())
+ if((attr.find("note") != attr.end()) &&
+ (attr.find("instr") != attr.end()))
{
midimap[std::stoi(attr.at("note"))] = attr.at("instr");
}
diff --git a/src/midimapparser.h b/src/midimapparser.h
index 740cb60..8ec76c0 100644
--- a/src/midimapparser.h
+++ b/src/midimapparser.h
@@ -26,8 +26,6 @@
*/
#pragma once
-#include <stdio.h>
-
#include "saxparser.h"
#include "midimapper.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/path.cc b/src/path.cc
index 43c64f0..c2e7910 100644
--- a/src/path.cc
+++ b/src/path.cc
@@ -35,17 +35,19 @@
std::string getPath(const std::string& file)
{
- std::string p;
-#ifndef __MINGW32__
- char *b = strdup(file.c_str());
- p = dirname(b);
- free(b);
-#else
+ std::string path;
+
+#ifdef __MINGW32__
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
_splitpath(file.c_str(), drive, dir, NULL, NULL);
- p = std::string(drive) + dir;
+ path = std::string(drive) + dir;
+#else
+ // POSIX
+ char* buffer = strdup(file.c_str());
+ path = dirname(buffer);
+ free(buffer);
#endif
- return p;
+ return path;
}
diff --git a/src/path.h b/src/path.h
index 7189cea..50ff842 100644
--- a/src/path.h
+++ b/src/path.h
@@ -28,4 +28,5 @@
#include <string>
+//! \returns path component of full filename with path.
std::string getPath(const std::string& file);
diff --git a/src/sample.cc b/src/sample.cc
index 66fe3c5..ced8a47 100644
--- a/src/sample.cc
+++ b/src/sample.cc
@@ -65,24 +65,3 @@ AudioFile* Sample::getAudioFile(Channel* c)
return nullptr;
}
-
-#ifdef TEST_SAMPLE
-// deps: channel.cc audiofile.cc
-// cflags: $(SNDFILE_CFLAGS)
-// libs: $(SNDFILE_LIBS)
-#include "test.h"
-
-TEST_BEGIN;
-
-Sample s;
-InstrumentChannel c;
-InstrumentChannel c2;
-AudioFile a("test");
-
-s.addAudioFile(&c, &a);
-TEST_EQUAL(s.getAudioFile(&c), &a, "?");
-TEST_EQUAL(s.getAudioFile(&c2), nullptr, "?");
-
-TEST_END;
-
-#endif /*TEST_SAMPLE*/
diff --git a/src/sample.h b/src/sample.h
index 5b4f3b5..f00db13 100644
--- a/src/sample.h
+++ b/src/sample.h
@@ -32,34 +32,22 @@
#include "channel.h"
#include "audiofile.h"
-typedef std::map<Channel*, AudioFile*> AudioFiles;
+using AudioFiles = std::map<Channel*, AudioFile*>;
-class InstrumentParser;
-class Sample
-{
+class Sample {
friend class InstrumentParser;
friend class PowerList;
-
public:
Sample(const std::string& name, float power);
~Sample();
- AudioFile* getAudioFile(InstrumentChannel* c);
+ AudioFile* getAudioFile(InstrumentChannel *instrument_channel);
private:
- void addAudioFile(InstrumentChannel* c, AudioFile* a);
+ void addAudioFile(InstrumentChannel* instrument_channel,
+ AudioFile* audio_file);
std::string name;
float power;
AudioFiles audiofiles;
};
-
-/*
- * <sample name="kick-r-1">
- * <audiofile channel="Alesis-3" file="samples/1-kick-r-Alesis-3.wav"/>
- * <audiofile channel="Amb L-3" file="samples/1-kick-r-Amb L-3.wav"/>
- * <audiofile channel="Amb R-3" file="samples/1-kick-r-Amb R-3.wav"/>
- * <audiofile channel="Kick L-3" file="samples/1-kick-r-Kick L-3.wav"/>
- * <audiofile channel="Kick R-3" file="samples/1-kick-r-Kick R-3.wav"/>
- * </sample>
- */
diff --git a/src/saxparser.cc b/src/saxparser.cc
index e32143d..280e608 100644
--- a/src/saxparser.cc
+++ b/src/saxparser.cc
@@ -26,29 +26,30 @@
*/
#include "saxparser.h"
-#include <string.h>
-#include <hugin.hpp>
#include <sstream>
#include <iostream>
+#include <hugin.hpp>
+
SAXParser::SAXParser()
{
- p = XML_ParserCreate(nullptr);
- if(!p) {
+ parser = XML_ParserCreate(nullptr);
+ if(!parser)
+ {
ERR(sax, "Couldn't allocate memory for parser\n");
// throw Exception(...); TODO
return;
}
- XML_SetUserData(p, this);
- XML_UseParserAsHandlerArg(p);
- XML_SetElementHandler(p, start_hndl, end_hndl);
- XML_SetCharacterDataHandler(p, character_hndl);
+ XML_SetUserData(parser, this);
+ XML_UseParserAsHandlerArg(parser);
+ XML_SetElementHandler(parser, SAXParser::startHandler, SAXParser::endHandler);
+ XML_SetCharacterDataHandler(parser, SAXParser::characterHandler);
}
SAXParser::~SAXParser()
{
- XML_ParserFree(p);
+ XML_ParserFree(parser);
}
int SAXParser::parseFile(const std::string& filename)
@@ -60,7 +61,8 @@ int SAXParser::parseFile(const std::string& filename)
std::ifstream file(filename, std::ifstream::in);
- if(!file.is_open()) {
+ if(!file.is_open())
+ {
return 1;
}
@@ -68,59 +70,63 @@ int SAXParser::parseFile(const std::string& filename)
ss << file.rdbuf();
std::string str = ss.str();
- parseString(str, filename);
-
- return 0;
+ return parseString(str, filename);
}
-int SAXParser::parseString(const std::string& str, const std::string& xml_source_name)
+int SAXParser::parseString(const std::string& str,
+ const std::string& xml_source_name)
{
DEBUG(sax, "parse(buffer %d bytes)\n", (int)str.length());
- if(!XML_Parse(p, str.c_str(), str.length(), true)) {
- parseError(str, XML_ErrorString(XML_GetErrorCode(p)),
- xml_source_name, (int)XML_GetCurrentLineNumber(p));
+ if(!XML_Parse(parser, str.c_str(), str.length(), true))
+ {
+ parseError(str, XML_ErrorString(XML_GetErrorCode(parser)),
+ xml_source_name, (int)XML_GetCurrentLineNumber(parser));
return 1;
}
return 0;
}
-void SAXParser::parseError(const std::string& buf, const std::string& error, const std::string& xml_source_name, std::size_t lineno)
+void SAXParser::parseError(const std::string& buf, const std::string& error,
+ const std::string& xml_source_name,
+ std::size_t lineno)
{
- std::cerr << "SAXParser error trying to parse from source: " << xml_source_name << "\n";
+ std::cerr << "SAXParser error trying to parse from source: " <<
+ xml_source_name << "\n";
std::cerr << "At line " << lineno << ": " << error << "\n";
std::cerr << "Buffer " << buf.size() << " bytes: \n[\n";
std::cerr << buf;
std::cerr << "\n]" << std::endl;
}
-void SAXParser::character_hndl(void* p, const XML_Char* s, int len)
+void SAXParser::characterHandler(void* parser, const XML_Char* cData, int len)
{
- SAXParser* parser = (SAXParser*)XML_GetUserData(p);
- std::string chars(s, len);
- parser->characterData(chars);
+ SAXParser* sax_parser = (SAXParser*)XML_GetUserData(parser);
+ std::string chars(cData, len);
+ sax_parser->characterData(chars);
}
-void SAXParser::start_hndl(void* p, const char* el, const char** attr)
+void SAXParser::startHandler(void* parser, const char* el, const char** attr)
{
- SAXParser* parser = (SAXParser*)XML_GetUserData(p);
+ SAXParser* sax_parser = (SAXParser*)XML_GetUserData(parser);
// Convert to comfy C++ values...
attr_t attributes;
- while(*attr) {
+ while(*attr)
+ {
std::string at_name = *attr++;
std::string at_value = *attr++;
attributes.emplace(at_name, at_value);
}
- parser->startTag(std::string(el), attributes);
+ sax_parser->startTag(std::string(el), attributes);
}
-void SAXParser::end_hndl(void* p, const char* el)
+void SAXParser::endHandler(void* parser, const char* el)
{
- SAXParser* parser = (SAXParser*)XML_GetUserData(p);
- parser->endTag(std::string(el));
+ SAXParser* sax_parser = (SAXParser*)XML_GetUserData(parser);
+ sax_parser->endTag(std::string(el));
}
diff --git a/src/saxparser.h b/src/saxparser.h
index 92197d1..4b1a273 100644
--- a/src/saxparser.h
+++ b/src/saxparser.h
@@ -31,7 +31,8 @@
#include <expat.h>
#include <fstream>
-class SAXParser {
+class SAXParser
+{
public:
SAXParser();
virtual ~SAXParser();
@@ -40,7 +41,8 @@ public:
virtual int parseFile(const std::string& filename);
//! Parses all the data in the buffer.
- virtual int parseString(const std::string& str, const std::string& xml_source_name = "");
+ virtual int parseString(const std::string& str,
+ const std::string& xml_source_name = "");
protected:
using attr_t = std::unordered_map<std::string, std::string>;
@@ -48,13 +50,16 @@ protected:
virtual void characterData(const std::string& data) {}
virtual void startTag(const std::string& name, const attr_t& attr) {}
virtual void endTag(const std::string& name) {}
- virtual void parseError(const std::string& buf, const std::string& error, const std::string& xml_source_name, std::size_t lineno);
+ virtual void parseError(const std::string& buf,
+ const std::string& error,
+ const std::string& xml_source_name,
+ std::size_t lineno);
private:
- XML_Parser p;
+ XML_Parser parser;
std::string filename;
- static void character_hndl(void* p, const XML_Char* s, int len);
- static void start_hndl(void* p, const char* el, const char** attr);
- static void end_hndl(void* p, const char* el);
+ static void characterHandler(void* parser, const XML_Char* cData, int len);
+ static void startHandler(void* parser, const char* el, const char** attr);
+ static void endHandler(void* parser, const char* el);
};
diff --git a/src/semaphore.cc b/src/semaphore.cc
index cd29bbf..6172251 100644
--- a/src/semaphore.cc
+++ b/src/semaphore.cc
@@ -27,87 +27,101 @@
#include "semaphore.h"
#include <hugin.hpp>
-
#include <limits>
+#include <assert.h>
#ifdef WIN32
#include <windows.h>
#else
-// Make sure we don't include /this/ file...
+// Make sure we don't include /this/ files header...
#include <../include/semaphore.h>
+#include <errno.h>
+#include <stdio.h>
#endif
struct semaphore_private_t {
#ifdef WIN32
- HANDLE semaphore;
+ HANDLE semaphore;
#else
- sem_t semaphore;
+ sem_t semaphore;
#endif
};
-Semaphore::Semaphore(const char *name)
+Semaphore::Semaphore(std::size_t initial_count)
{
- this->name = name;
- // DEBUG(semaphore, "Create [%s]\n", name);
-
- prv = new struct semaphore_private_t();
+ prv = new struct semaphore_private_t();
#ifdef WIN32
- prv->semaphore = CreateSemaphore(NULL, // default security attributes
- 0, // initial count
- std::numeric_limits<LONG>::max(),
- NULL); // unnamed semaphore
+ prv->semaphore = CreateSemaphore(nullptr, // default security attributes
+ initial_count,
+ std::numeric_limits<LONG>::max(),
+ nullptr); // unnamed semaphore
#else
- sem_init(&prv->semaphore, 0, 0);
+ const int pshared = 0;
+ sem_init(&prv->semaphore, pshared, initial_count);
#endif
}
Semaphore::~Semaphore()
{
- // DEBUG(semaphore, "Delete [%s]\n", name);
-
#ifdef WIN32
- CloseHandle(prv->semaphore);
+ CloseHandle(prv->semaphore);
#else
- sem_destroy(&prv->semaphore);
+ sem_destroy(&prv->semaphore);
#endif
- delete prv;
+ delete prv;
}
void Semaphore::post()
{
- // DEBUG(semaphore, "Post [%s]\n", name);
+#ifdef WIN32
+ ReleaseSemaphore(prv->semaphore, 1, NULL);
+#else
+ sem_post(&prv->semaphore);
+#endif
+}
+bool Semaphore::wait(const std::chrono::milliseconds& timeout)
+{
#ifdef WIN32
- ReleaseSemaphore(prv->semaphore, 1, NULL);
+ DWORD ret = WaitForSingleObject(prv->semaphore, timeout.count());
+ if(ret == WAIT_TIMEOUT)
+ {
+ return false;
+ }
+
+ assert(ret == WAIT_OBJECT_0);
#else
- sem_post(&prv->semaphore);
+ struct timespec t = {
+ // Whole seconds:
+ (time_t)(timeout.count() / 1000),
+
+ // Remainder as nanoseconds:
+ (long)((timeout.count() - ((timeout.count() / 1000) * 1000)) * 1000000)
+ };
+
+ int ret = sem_timedwait(&prv->semaphore, &t);
+ if(ret < 0)
+ {
+ if(errno == ETIMEDOUT)
+ {
+ return false;
+ }
+
+ perror("sem_timedwait()");
+ assert(false);
+ }
#endif
+
+ return true;
}
void Semaphore::wait()
{
- // DEBUG(semaphore, "Wait [%s]\n", name);
-
#ifdef WIN32
- WaitForSingleObject(prv->semaphore, INFINITE);
+ WaitForSingleObject(prv->semaphore, INFINITE);
#else
- sem_wait(&prv->semaphore);
+ sem_wait(&prv->semaphore);
#endif
}
-
-#ifdef TEST_SEMAPHORE
-//deps:
-//cflags: -I.. $(PTHREAD_CFLAGS)
-//libs: $(PTHREAD_LIBS)
-#include <test.h>
-
-TEST_BEGIN;
-
-// TODO: Put some testcode here (see test.h for usable macros).
-TEST_TRUE(false, "No tests yet!");
-
-TEST_END;
-
-#endif/*TEST_SEMAPHORE*/
diff --git a/src/semaphore.h b/src/semaphore.h
index 4464898..d5995cb 100644
--- a/src/semaphore.h
+++ b/src/semaphore.h
@@ -24,22 +24,26 @@
* along with DrumGizmo; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-#ifndef __PRACRO_SEMAPHORE_H__
-#define __PRACRO_SEMAPHORE_H__
+#pragma once
+
+#include <chrono>
struct semaphore_private_t;
-class Semaphore {
+class Semaphore
+{
public:
- Semaphore(const char *name = "");
- ~Semaphore();
+ Semaphore(std::size_t initial_count = 0);
+ ~Semaphore();
+
+ void post();
- void post();
- void wait();
+ //! Lock semaphore with timeout.
+ //! \returns true if the semaphore was locked, false on timeout.
+ bool wait(const std::chrono::milliseconds& timeout);
+
+ void wait();
private:
struct semaphore_private_t *prv{nullptr};
- const char *name{nullptr};
};
-
-#endif/*__PRACRO_SEMAPHORE_H__*/
diff --git a/src/settings.h b/src/settings.h
index 74c432d..6b4e882 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -27,52 +27,54 @@
#pragma once
#include <atomic>
+#include <string>
#include <cassert>
-template <typename T> class SettingRef
-{
-public:
- SettingRef(std::atomic<T>& value)
- : value{value}
- , cache{}
- {
- // 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);
- return tmp == cache;
- }
+#include "atomic.h"
+#include "notifier.h"
- T getValue() const
- {
- return cache;
- }
-
-private:
- std::atomic<T>& value;
- std::atomic<T> cache;
+enum class LoadStatus : unsigned int
+{
+ Idle,
+ Loading,
+ Done,
+ Error
};
+//! Engine settings
struct Settings
{
- std::atomic<bool> enable_velocity_modifier;
- std::atomic<float> velocity_modifier_falloff;
- std::atomic<float> velocity_modifier_weight;
+ 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};
- std::atomic<bool> enable_velocity_randomiser;
- std::atomic<float> velocity_randomiser_weight;
+ Atomic<bool> enable_velocity_randomiser{false};
+ Atomic<float> velocity_randomiser_weight{0.1f};
- std::atomic<int> samplerate;
+ Atomic<double> samplerate{44100.0};
- std::atomic<bool> enable_resampling;
+ Atomic<bool> enable_resampling{true};
+
+ Atomic<std::size_t> number_of_files;
+ Atomic<std::size_t> number_of_files_loaded;
+ Atomic<std::string> current_file;
};
+//! Settings getter class.
struct SettingsGetter
{
+ SettingRef<std::string> drumkit_file;
+ SettingRef<LoadStatus> drumkit_load_status;
+
+ SettingRef<std::string> midimap_file;
+ SettingRef<LoadStatus> midimap_load_status;
+
SettingRef<bool> enable_velocity_modifier;
SettingRef<float> velocity_modifier_falloff;
SettingRef<float> velocity_modifier_weight;
@@ -80,48 +82,125 @@ struct SettingsGetter
SettingRef<bool> enable_velocity_randomiser;
SettingRef<float> velocity_randomiser_weight;
- SettingRef<int> samplerate;
+ SettingRef<double> samplerate;
SettingRef<bool> enable_resampling;
+ SettingRef<std::size_t> number_of_files;
+ SettingRef<std::size_t> number_of_files_loaded;
+ 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}
, velocity_randomiser_weight{settings.velocity_randomiser_weight}
, samplerate{settings.samplerate}
, enable_resampling{settings.enable_resampling}
+ , number_of_files{settings.number_of_files}
+ , number_of_files_loaded{settings.number_of_files_loaded}
+ , current_file{settings.current_file}
{
}
};
+//! 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<std::size_t> number_of_files;
+ Notifier<std::size_t> 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 {
- Foo = 0
+ Foo = 0
};
-struct Settings {
- std::array<std::atomic<int>, 5> ints;
+struct Settings
+{
+ std::array<std::atomic<int>, 5> ints;
- Settings()
- : ints{} {
- //get(IntParams::Foo).store(3);
- }
+ Settings()
+ : ints{}
+ {
+ //get(IntParams::Foo).store(3);
+ }
- std::atomic<int>& get(IntParams param) {
- return ints[(size_t)param];
- }
+ std::atomic<int>& get(IntParams param)
+ {
+ return ints[(size_t)param];
+ }
};
-struct SettingsGetter {
- std::vector<SettingRef<int>> ints;
+struct SettingsGetter
+{
+ std::vector<SettingRef<int>> ints;
- SettingsGetter(Settings& parent) {
- for (auto& atomic: parent.ints) {
- ints.emplace_back(atomic);
- }
- }
+ SettingsGetter(Settings& parent)
+ {
+ for(auto& atomic: parent.ints)
+ {
+ ints.emplace_back(atomic);
+ }
+ }
};
*/
diff --git a/src/syncedsettings.h b/src/syncedsettings.h
new file mode 100644
index 0000000..0fe5efd
--- /dev/null
+++ b/src/syncedsettings.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * syncedsettings.h
+ *
+ * Thu Mar 31 09:23:27 CEST 2016
+ * Copyright 2016 Christian Glöckner
+ * cgloeckner@freenet.de
+ ****************************************************************************/
+
+/*
+ * 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 <mutex>
+
+template <typename T> class Group;
+
+template <typename T> class Accessor
+{
+private:
+ std::lock_guard<std::mutex> lock;
+
+public:
+ Accessor(Group<T>& parent)
+ : lock{parent.mutex}
+ , data(parent.data)
+ {
+ }
+
+ T& data;
+};
+
+template <typename T> class Group
+{
+private:
+ friend class Accessor<T>;
+
+ mutable std::mutex mutex;
+ T data;
+
+public:
+ Group()
+ : mutex{}
+ , data{}
+ {
+ }
+
+ Group(Group<T> const& other)
+ : mutex{}
+ , data{}
+ {
+ std::lock_guard<std::mutex> lock{other.mutex};
+ data = other.data;
+ }
+
+ Group(Group<T>&& other)
+ : mutex{}
+ , data{}
+ {
+ std::lock_guard<std::mutex> lock{other.mutex};
+ std::swap(data, other.data);
+ }
+
+ Group<T>& operator=(const Group<T>& other)
+ {
+ if (*this != &other)
+ {
+ std::lock_guard<std::mutex> lock{mutex};
+ std::lock_guard<std::mutex> lock2{other.mutex};
+ data = other.data;
+ }
+ return *this;
+ }
+
+ Group<T>& operator=(Group<T>&& other)
+ {
+ if (*this != &other)
+ {
+ std::lock_guard<std::mutex> lock{mutex};
+ std::lock_guard<std::mutex> lock2{other.mutex};
+ std::swap(data, other.data);
+ }
+ return *this;
+ }
+
+ operator T() const
+ {
+ std::lock_guard<std::mutex> lock{mutex};
+ return data;
+ }
+};