diff options
65 files changed, 1371 insertions, 1300 deletions
| @@ -1,3 +1,11 @@ +Version 0.9.10 +============== +Release date: March 30th 2016 +Contributors: deva, suhr + - Fix the 'no sound from plugin when resampler active' bug. + - Fix the 'freeze on tempo change' bug. + - Fix backspace in lineedits. +  Version 0.9.9  =============  Release date: March 24th 2016 diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 24d16e8..e993dc3 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -92,36 +92,7 @@ static const char usage_str[] =      "  dummy:\n"      "\n"; -CliMain::CliMain() -	: MessageReceiver(MSGRCV_UI) -{ -	loading = true; // Block by default -} - -CliMain::~CliMain() -{ -	hug_close(); -} - -void CliMain::handleMessage(Message* msg) -{ -	switch(msg->type()) -	{ -	case Message::LoadStatus: -		{ -			auto ls = static_cast<LoadStatusMessage*>(msg); -			if(ls->numer_of_files_loaded == ls->number_of_files) -			{ -				loading = false; -			} -		} -		break; -	default: -		break; -	} -} - -int CliMain::run(int argc, char* argv[]) +int main(int argc, char* argv[])  {  	int c; @@ -372,7 +343,8 @@ int CliMain::run(int argc, char* argv[])  	printf("Using kitfile: %s\n", kitfile.c_str()); -	DrumGizmo gizmo(oe.get(), ie.get()); +	Settings settings; +	DrumGizmo gizmo(settings, oe.get(), ie.get());  	gizmo.setFrameSize(oe->getBufferSize()); @@ -382,21 +354,37 @@ int CliMain::run(int argc, char* argv[])  		return 1;  	} -	printf("Loading drumkit, this may take a while..."); -	fflush(stdout); -	loading = true; -	while(async == false && loading) +	printf("Loading drumkit, this may take a while:\n"); + +	if(!async)  	{ +		while(settings.drumkit_load_status.load() != LoadStatus::Done) +		{  #ifdef WIN32 -		SleepEx(500, FALSE); +			SleepEx(10, FALSE);  #else -		usleep(500000); +			usleep(10000);  #endif /*WIN32*/ -		handleMessages(); -		printf("."); -		fflush(stdout); + +			int total = settings.number_of_files.load(); +			int loaded =  settings.number_of_files_loaded.load(); + +			printf("\r%d of %d     ", loaded, total); +			fflush(stdout); + +			if(settings.drumkit_load_status.load() == LoadStatus::Error) +			{ +				printf("\nLoad error\n"); +				return 1; +			} + +			if(loaded == total) +			{ +				//break; +			} +		} +		printf("\ndone\n");  	} -	printf("done.\n");  	gizmo.setSamplerate(oe->getSamplerate()); @@ -411,14 +399,7 @@ int CliMain::run(int argc, char* argv[])  	printf("Quit.\n");  	fflush(stdout); -	return 0; -} - -int main(int argc, char* argv[]) -{ -	CliMain cli; - -	cli.run(argc, argv); +	hug_close();  	return 0;  } diff --git a/drumgizmo/drumgizmoc.h b/drumgizmo/drumgizmoc.h index 231aec6..cc2f96c 100644 --- a/drumgizmo/drumgizmoc.h +++ b/drumgizmo/drumgizmoc.h @@ -24,21 +24,4 @@   *  along with DrumGizmo; if not, write to the Free Software   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.   */ -  #pragma once - -#include "messagereceiver.h" - -class CliMain : public MessageReceiver -{ -public: -	CliMain(); -	virtual ~CliMain(); - -	int run(int argc, char* argv[]); -	void handleMessage(Message* msg); - -private: -	bool loading; -}; - diff --git a/drumgizmo/output/jackaudio.cc b/drumgizmo/output/jackaudio.cc index 7710e14..abd7d4f 100644 --- a/drumgizmo/output/jackaudio.cc +++ b/drumgizmo/output/jackaudio.cc @@ -33,7 +33,6 @@ JackAudioOutputEngine::JackAudioOutputEngine(JackClient& client)  	: AudioOutputEngine{}  	, client(client)  	, channels{} -	, sema{"jackaudio"}  {  	client.add(*this);  } diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in index 40233b4..8b341c7 100644 --- a/plugin/Makefile.mingw32.in +++ b/plugin/Makefile.mingw32.in @@ -19,7 +19,6 @@ DG_SRC = \  	@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 \ @@ -29,8 +28,6 @@ DG_SRC = \  	@top_srcdir@/src/instrument.cc \  	@top_srcdir@/src/instrumentparser.cc \  	@top_srcdir@/src/memchecker.cc \ -	@top_srcdir@/src/messagehandler.cc \ -	@top_srcdir@/src/messagereceiver.cc \  	@top_srcdir@/src/midimapparser.cc \  	@top_srcdir@/src/midimapper.cc \  	@top_srcdir@/src/mutex.cc \ diff --git a/plugin/drumgizmo_plugin.cc b/plugin/drumgizmo_plugin.cc index b8f8822..06c2799 100644 --- a/plugin/drumgizmo_plugin.cc +++ b/plugin/drumgizmo_plugin.cc @@ -59,7 +59,7 @@ DrumGizmoPlugin::DrumGizmoPlugin()  {  	init(); -	drumgizmo = std::make_shared<DrumGizmo>(&output, &input); +	drumgizmo = std::make_shared<DrumGizmo>(settings, &output, &input);  	resizeWindow(370, 330);  	drumgizmo->setFreeWheel(true);  	drumgizmo->setSamplerate(44100); @@ -143,7 +143,7 @@ bool DrumGizmoPlugin::hasGUI()  void DrumGizmoPlugin::createWindow(void *parent)  { -	plugin_gui = std::make_shared<GUI::PluginGUI>(parent); +	plugin_gui = std::make_shared<GUI::PluginGUI>(settings, parent);  	resizeWindow(370, 330);  	onShowWindow();  } diff --git a/plugin/drumgizmo_plugin.h b/plugin/drumgizmo_plugin.h index 28a1b8f..3508c3e 100644 --- a/plugin/drumgizmo_plugin.h +++ b/plugin/drumgizmo_plugin.h @@ -154,6 +154,8 @@ private:  	Output output{*this};  	const std::vector<float*>* output_samples{nullptr}; +	Settings settings; +  	std::shared_ptr<GUI::PluginGUI> plugin_gui;  	std::shared_ptr<DrumGizmo> drumgizmo;  }; diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am index 3dee864..4176c07 100644 --- a/plugingui/Makefile.am +++ b/plugingui/Makefile.am @@ -16,9 +16,7 @@ plugingui_SOURCES = \  	$(top_srcdir)/src/configfile.cc \  	$(top_srcdir)/src/thread.cc \  	$(top_srcdir)/src/semaphore.cc \ -	$(top_srcdir)/src/mutex.cc \ -	$(top_srcdir)/src/messagehandler.cc \ -	$(top_srcdir)/src/messagereceiver.cc +	$(top_srcdir)/src/mutex.cc  rcgen_SOURCES = rcgen.cc @@ -46,7 +44,6 @@ EXTRA_DIST = \  	nativewindow.h \  	nativewindow_win32.h \  	nativewindow_x11.h \ -	notifier.h \  	painter.h \  	pixelbuffer.h \  	pluginconfig.h \ diff --git a/plugingui/Makefile.mingw32 b/plugingui/Makefile.mingw32 index 3f52e8a..9820d1a 100644 --- a/plugingui/Makefile.mingw32 +++ b/plugingui/Makefile.mingw32 @@ -2,9 +2,7 @@ DG_SRC = \  	../src/configfile.cc \  	../src/thread.cc \  	../src/semaphore.cc \ -	../src/mutex.cc \ -	../src/messagehandler.cc \ -	../src/messagereceiver.cc +	../src/mutex.cc  DG_CFLAGS = -I.. -I../include -I../src -DSSE -msse -msse2 -DDISABLE_HUGIN diff --git a/plugingui/button.h b/plugingui/button.h index 7e3e168..1bfeb2d 100644 --- a/plugingui/button.h +++ b/plugingui/button.h @@ -28,9 +28,10 @@  #include <string> +#include <notifier.h> +  #include "widget.h"  #include "painter.h" -#include "notifier.h"  #include "font.h"  namespace GUI { diff --git a/plugingui/checkbox.h b/plugingui/checkbox.h index 3da5511..5c658a5 100644 --- a/plugingui/checkbox.h +++ b/plugingui/checkbox.h @@ -26,9 +26,10 @@   */  #pragma once +#include <notifier.h> +  #include "widget.h"  #include "image.h" -#include "notifier.h"  namespace GUI { diff --git a/plugingui/dgwindow.cc b/plugingui/dgwindow.cc index 86a985d..c325703 100644 --- a/plugingui/dgwindow.cc +++ b/plugingui/dgwindow.cc @@ -30,12 +30,12 @@  #include "verticalline.h"  #include "../version.h" -#include "messagehandler.h"  #include "pluginconfig.h"  namespace GUI { -class LabeledControl : public Widget +class LabeledControl +	: public Widget  {  public:  	LabeledControl(Widget* parent, const std::string& name) @@ -60,7 +60,8 @@ public:  	Label caption{this};  }; -class File : public Widget +class File +	: public Widget  {  public:  	File(Widget* parent) @@ -83,7 +84,8 @@ public:  	Button browseButton{this};  }; -class HumanizeControls : public Widget +class HumanizeControls +	: public Widget  {  public:  	HumanizeControls(Widget* parent) @@ -119,11 +121,10 @@ public:  	Knob falloffKnob{&falloff};  }; -DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, -                   Config& config) +DGWindow::DGWindow(void* native_window, Config& config, Settings& settings)  	: Window(native_window) -	, messageHandler(messageHandler)  	, config(config) +	, settings(settings)  {  	int vlineSpacing = 16; @@ -179,6 +180,7 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler,  	midimapFileProgress = new ProgressBar(this);  	midimapFileProgress->resize(width() - 40, 11); +	midimapFileProgress->setTotal(2);  	layout.addItem(midimapFileProgress);  	VerticalLine *l2 = new VerticalLine(this); @@ -207,7 +209,7 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler,  	layout.addItem(l3);  	Label *lbl_version = new Label(this); -	lbl_version->setText(".::. v" VERSION "  .::.  http://www.drumgizmo.org  .::.  LGPLv3 .::."); +	lbl_version->setText(".::.  v" VERSION "  .::.  http://www.drumgizmo.org  .::.  LGPLv3 .::.");  	lbl_version->resize(width(), 20);  	lbl_version->setAlignment(TextAlignment::center);  	layout.addItem(lbl_version); @@ -219,6 +221,50 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler,  	fileBrowser->hide();  } +void DGWindow::setDrumKitLoadStatus(LoadStatus load_status) +{ +	ProgressBarState state = ProgressBarState::Blue; +	switch(load_status) +	{ +	case LoadStatus::Idle: +	case LoadStatus::Loading: +		state = ProgressBarState::Blue; +		break; +	case LoadStatus::Done: +		state = ProgressBarState::Green; +		break; +	case LoadStatus::Error: +		state = ProgressBarState::Red; +		break; +	} +	drumkitFileProgress->setState(state); +} + +void DGWindow::setMidiMapLoadStatus(LoadStatus load_status) +{ +	ProgressBarState state = ProgressBarState::Blue; +	switch(load_status) +	{ +	case LoadStatus::Idle: +		midimapFileProgress->setValue(0); +		break; +	case LoadStatus::Loading: +		midimapFileProgress->setValue(1); +		state = ProgressBarState::Blue; +		break; +	case LoadStatus::Done: +		midimapFileProgress->setValue(2); +		state = ProgressBarState::Green; +		break; +	case LoadStatus::Error: +		midimapFileProgress->setValue(2); +		state = ProgressBarState::Red; +		break; +	} + +	midimapFileProgress->setState(state); +} +  void DGWindow::repaintEvent(RepaintEvent* repaintEvent)  {  	if(!visible()) @@ -233,42 +279,42 @@ void DGWindow::repaintEvent(RepaintEvent* repaintEvent)  void DGWindow::attackValueChanged(float value)  { -	ChangeSettingMessage *msg = -		new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, -														 value); +	settings.velocity_modifier_weight.store(value); -	messageHandler.sendMessage(MSGRCV_ENGINE, msg); - -#ifdef STANDALONE +#ifdef STANDALONE // For GUI debugging  	int i = value * 4;  	switch(i) { -	case 0: drumkitFileProgress->setState(ProgressBarState::Off); break; -	case 1: drumkitFileProgress->setState(ProgressBarState::Blue); break; -	case 2: drumkitFileProgress->setState(ProgressBarState::Green); break; -	case 3: drumkitFileProgress->setState(ProgressBarState::Red); break; -	default: break; +	case 0: +		drumkitFileProgress->setState(ProgressBarState::Off); +		break; +	case 1: +		drumkitFileProgress->setState(ProgressBarState::Blue); +		break; +	case 2: +		drumkitFileProgress->setState(ProgressBarState::Green); +		break; +	case 3: +		drumkitFileProgress->setState(ProgressBarState::Red); +		break; +	default: +		break;  	}  #endif  }  void DGWindow::falloffValueChanged(float value)  { -	ChangeSettingMessage *msg = -		new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, -		                         value); -	messageHandler.sendMessage(MSGRCV_ENGINE, msg); +	settings.velocity_modifier_falloff.store(value); -#ifdef STANDALONE -	drumkitFileProgress->setProgress(value); +#ifdef STANDALONE // For GUI debugging +	drumkitFileProgress->setTotal(100); +	drumkitFileProgress->setValue(value * 100);  #endif  }  void DGWindow::velocityCheckClick(bool checked)  { -	ChangeSettingMessage *msg = -		new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, -		                         checked); -	messageHandler.sendMessage(MSGRCV_ENGINE, msg); +	settings.enable_velocity_modifier.store(checked);  }  void DGWindow::kitBrowseClick() @@ -318,13 +364,7 @@ void DGWindow::selectKitFile(const std::string& filename)  	config.lastkit = drumkit;  	config.save(); -	drumkitFileProgress->setProgress(0); -	drumkitFileProgress->setState(ProgressBarState::Blue); - -	LoadDrumKitMessage *msg = new LoadDrumKitMessage(); -	msg->drumkitfile = drumkit; - -	messageHandler.sendMessage(MSGRCV_ENGINE, msg); +	settings.drumkit_file.store(drumkit);  }  void DGWindow::selectMapFile(const std::string& filename) @@ -337,9 +377,7 @@ void DGWindow::selectMapFile(const std::string& filename)  	config.lastmidimap = midimap;  	config.save(); -	LoadMidimapMessage *msg = new LoadMidimapMessage(); -	msg->midimapfile = midimap; -	messageHandler.sendMessage(MSGRCV_ENGINE, msg); +	settings.midimap_file.store(midimap);  } diff --git a/plugingui/dgwindow.h b/plugingui/dgwindow.h index 605e87a..72e4679 100644 --- a/plugingui/dgwindow.h +++ b/plugingui/dgwindow.h @@ -26,8 +26,9 @@   */  #pragma once -#include "window.h" +#include <settings.h> +#include "window.h"  #include "label.h"  #include "lineedit.h"  #include "checkbox.h" @@ -37,8 +38,6 @@  #include "filebrowser.h"  #include "layout.h" -class MessageHandler; -  namespace GUI {  class Config; @@ -47,7 +46,7 @@ class File;  class DGWindow : public Window {  public: -	DGWindow(void* native_window, MessageHandler& messageHandler, Config& config); +	DGWindow(void* native_window, Config& config, Settings& settings);  	Header* header; @@ -65,6 +64,9 @@ public:  	Knob* falloffKnob;  	FileBrowser* fileBrowser; +	void setDrumKitLoadStatus(LoadStatus load_status); +	void setMidiMapLoadStatus(LoadStatus load_status); +  protected:  	// From Widget:  	void repaintEvent(RepaintEvent* repaintEvent) override; @@ -78,13 +80,14 @@ private:  	void selectKitFile(const std::string& filename);  	void selectMapFile(const std::string& filename); -	MessageHandler& messageHandler;  	Config& config;  	VBoxLayout layout{this};  	Image back{":bg.png"};  	Image logo{":logo.png"}; + +	Settings& settings;  };  } // GUI:: diff --git a/plugingui/eventhandler.h b/plugingui/eventhandler.h index 1fdb1e8..490c515 100644 --- a/plugingui/eventhandler.h +++ b/plugingui/eventhandler.h @@ -26,9 +26,10 @@   */  #pragma once +#include <notifier.h> +  #include "guievent.h"  #include "nativewindow.h" -#include "notifier.h"  namespace GUI { diff --git a/plugingui/filebrowser.h b/plugingui/filebrowser.h index 04b34f6..bc2019f 100644 --- a/plugingui/filebrowser.h +++ b/plugingui/filebrowser.h @@ -26,15 +26,15 @@   */  #pragma once -#include "widget.h" +#include <notifier.h> +#include "widget.h"  #include "button.h"  #include "listbox.h"  #include "lineedit.h"  #include "label.h"  #include "image.h"  #include "directory.h" -#include "notifier.h"  namespace GUI { diff --git a/plugingui/knob.h b/plugingui/knob.h index 10d91d6..d144184 100644 --- a/plugingui/knob.h +++ b/plugingui/knob.h @@ -26,10 +26,11 @@   */  #pragma once +#include <notifier.h> +  #include "widget.h"  #include "image.h"  #include "font.h" -#include "notifier.h"  namespace GUI { diff --git a/plugingui/layout.h b/plugingui/layout.h index 55cc93f..49bf75c 100644 --- a/plugingui/layout.h +++ b/plugingui/layout.h @@ -29,7 +29,7 @@  #include <list>  #include <cstdlib> -#include "notifier.h" +#include <notifier.h>  namespace GUI { diff --git a/plugingui/listboxbasic.h b/plugingui/listboxbasic.h index 7953dc3..2ebe845 100644 --- a/plugingui/listboxbasic.h +++ b/plugingui/listboxbasic.h @@ -29,11 +29,12 @@  #include <string.h>  #include <vector> +#include <notifier.h> +  #include "widget.h"  #include "font.h"  #include "painter.h"  #include "scrollbar.h" -#include "notifier.h"  namespace GUI { diff --git a/plugingui/listboxthin.h b/plugingui/listboxthin.h index 3139ecc..1617234 100644 --- a/plugingui/listboxthin.h +++ b/plugingui/listboxthin.h @@ -29,10 +29,11 @@  #include <string.h>  #include <vector> +#include <notifier.h> +  #include "widget.h"  #include "painter.h"  #include "listboxbasic.h" -#include "notifier.h"  namespace GUI { diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index e34c471..2802c44 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -26,16 +26,17 @@   */  #include "plugingui.h" +#include <iostream> +  #include <hugin.hpp>  #include "pluginconfig.h" -#include "messagehandler.h"  namespace GUI { -PluginGUI::PluginGUI(void* native_window) -	: MessageReceiver(MSGRCV_UI) -	, native_window(native_window) +PluginGUI::PluginGUI(Settings& settings, void* native_window) +	: native_window(native_window) +	, settings(settings)  {  	init();  } @@ -44,70 +45,6 @@ PluginGUI::~PluginGUI()  {  } -void PluginGUI::handleMessage(Message *msg) -{ -	Painter p(*window);// Make sure we only redraw buffer once (set refcount to 1) - -	switch(msg->type()) { -	case Message::LoadStatus: -		{ -			LoadStatusMessage *ls = (LoadStatusMessage*)msg; -			window->drumkitFileProgress->setProgress((float)ls->numer_of_files_loaded / -			                              (float)ls->number_of_files); -			if(ls->numer_of_files_loaded == ls->number_of_files) -			{ -				window->drumkitFileProgress->setState(ProgressBarState::Green); -			} -		} -		break; -	case Message::LoadStatusMidimap: -		{ -			LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg; -			window->midimapFileProgress->setProgress(1); -			if(ls->success) -			{ -				window->midimapFileProgress->setState(ProgressBarState::Green); -			} -			else -			{ -				window->midimapFileProgress->setState(ProgressBarState::Red); -			} -		} -		break; -	case Message::EngineSettingsMessage: -		{ -			EngineSettingsMessage *settings = (EngineSettingsMessage *)msg; -			window->lineedit->setText(settings->drumkitfile); -			if(settings->drumkit_loaded) -			{ -				window->drumkitFileProgress->setProgress(1); -				window->drumkitFileProgress->setState(ProgressBarState::Green); -			} -			else -			{ -				window->drumkitFileProgress->setProgress(0); -				window->drumkitFileProgress->setState(ProgressBarState::Blue); -			} -			window->lineedit2->setText(settings->midimapfile); -			if(settings->midimap_loaded) -			{ -				window->midimapFileProgress->setProgress(1); -				window->midimapFileProgress->setState(ProgressBarState::Green); -			} -			else -			{ -				window->midimapFileProgress->setProgress(0); -				window->midimapFileProgress->setState(ProgressBarState::Blue); -			} -			window->velocityCheck->setChecked(settings->enable_velocity_modifier); -			window->attackKnob->setValue(settings->velocity_modifier_weight); -			window->falloffKnob->setValue(settings->velocity_modifier_falloff); -		} -	default: -		break; -	} -} -  bool PluginGUI::processEvents()  {  	if(!initialised) @@ -116,7 +53,12 @@ bool PluginGUI::processEvents()  	}  	window->eventHandler()->processEvents(); -	handleMessages(); + +	{ +		Painter p(*window); + +		settings_notifier.evaluate(); +	}  	if(closing)  	{ @@ -135,18 +77,51 @@ void PluginGUI::init()  	config = new Config();  	config->load(); -	window = new DGWindow(native_window, msghandler, *config); +	window = new DGWindow(native_window, *config, settings); + + +	CONNECT(this, settings_notifier.drumkit_file, +	        window->lineedit, &LineEdit::setText); +	CONNECT(this, settings_notifier.drumkit_load_status, +	        window, &DGWindow::setDrumKitLoadStatus); + +	CONNECT(this, settings_notifier.midimap_file, +	        window->lineedit2, &LineEdit::setText); +	CONNECT(this, settings_notifier.midimap_load_status, +	        window, &DGWindow::setMidiMapLoadStatus); + +	CONNECT(this, settings_notifier.enable_velocity_modifier, +	        window->velocityCheck, &CheckBox::setChecked); + +	CONNECT(this, settings_notifier.velocity_modifier_falloff, +	        window->falloffKnob, &Knob::setValue); +	CONNECT(this, settings_notifier.velocity_modifier_weight, +	        window->attackKnob, &Knob::setValue); + + +	// TODO: +	//CONNECT(this, settings_notifier.enable_velocity_randomiser, +	//        window->, &CheckBox::setChecked); +	//CONNECT(this, settings_notifier.velocity_randomiser_weight, +	//        window->, &Knob::setValue); + +	//CONNECT(this, settings_notifier.samplerate, +	//        window->, &Knob::setValue); + +	//CONNECT(this, settings_notifier.enable_resampling, +	//        window->, &CheckBox::setChecked); + +	CONNECT(this, settings_notifier.number_of_files, +	        window->drumkitFileProgress, &ProgressBar::setTotal); + +	CONNECT(this, settings_notifier.number_of_files_loaded, +	        window->drumkitFileProgress, &ProgressBar::setValue);  	auto eventHandler = window->eventHandler();  	CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler);  	window->show(); -	{ // Request all engine settings -		EngineSettingsMessage *msg = new EngineSettingsMessage(); -		msghandler.sendMessage(MSGRCV_ENGINE, msg); -	} -  	initialised = true;  } diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index f441696..04b0a29 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -26,26 +26,20 @@   */  #pragma once +#include <settings.h> +#include <notifier.h> +  #include "dgwindow.h"  #include "eventhandler.h" -  #include "pluginconfig.h" - -#include "thread.h" -#include "semaphore.h" - -#include "messagereceiver.h" -#include "notifier.h" -  namespace GUI {  class PluginGUI -	: public MessageReceiver -	, public Listener +	: public Listener  {  public: -	PluginGUI(void* native_window = nullptr); +	PluginGUI(Settings& settings, void* native_window = nullptr);  	virtual ~PluginGUI();  	//! Process all events and messages in queue @@ -58,9 +52,6 @@ public:  	void show();  	void hide(); - -	void handleMessage(Message* msg); -  	DGWindow* window{nullptr};  	EventHandler* eventhandler{nullptr}; @@ -80,11 +71,12 @@ private:  	volatile bool closing{false};  	volatile bool initialised{false}; -	Semaphore sem{"plugingui"}; -  	// For the old-style notifier.  	void (*windowClosedHandler)(void *){nullptr};  	void *windowClosedPtr{nullptr}; + +	Settings& settings; +	SettingsNotifier settings_notifier{settings};  };  } // GUI:: diff --git a/plugingui/progressbar.cc b/plugingui/progressbar.cc index 932f17c..8a382f5 100644 --- a/plugingui/progressbar.cc +++ b/plugingui/progressbar.cc @@ -26,6 +26,8 @@   */  #include "progressbar.h" +#include <iostream> +  namespace GUI {  ProgressBar::ProgressBar(Widget *parent) @@ -46,9 +48,6 @@ ProgressBar::ProgressBar(Widget *parent)  	bar_green.left    = new Image(":progress_front_green_l.png");  	bar_green.right   = new Image(":progress_front_green_r.png");  	bar_green.center  = new Image(":progress_front_green_c.png"); - -	state = ProgressBarState::Blue; -	_progress = .5;  }  ProgressBar::~ProgressBar() @@ -79,22 +78,31 @@ void ProgressBar::setState(ProgressBarState state)  	}  } -float ProgressBar::progress() +void ProgressBar::setTotal(std::size_t total)  { -	return _progress; +	if(this->total != total) +	{ +		this->total = total; +		repaintEvent(nullptr); +	}  } -void ProgressBar::setProgress(float progress) +void ProgressBar::setValue(std::size_t value)  { -	_progress = progress; -	repaintEvent(nullptr); +	if(this->value != value) +	{ +		this->value = value; +		repaintEvent(nullptr); +	}  }  void ProgressBar::repaintEvent(RepaintEvent* repaintEvent)  {  	Painter p(*this); -	int max = width() * _progress; +	float progress = (float)value / (float)total; + +	int max = width() * progress;  	p.clear(); diff --git a/plugingui/progressbar.h b/plugingui/progressbar.h index d5f6c61..7485e40 100644 --- a/plugingui/progressbar.h +++ b/plugingui/progressbar.h @@ -43,11 +43,11 @@ enum class ProgressBarState  class ProgressBar : public Widget {  public: -	ProgressBar(Widget *parent); +	ProgressBar(Widget* parent);  	~ProgressBar(); -	float progress(); -	void setProgress(float progress); +	void setTotal(std::size_t total); +	void setValue(std::size_t value);  	void setState(ProgressBarState state); @@ -56,7 +56,7 @@ protected:  	virtual void repaintEvent(RepaintEvent* repaintEvent) override;  private: -	ProgressBarState state; +	ProgressBarState state{ProgressBarState::Blue};  	Painter::Bar bar_bg; @@ -64,7 +64,8 @@ private:  	Painter::Bar bar_blue;  	Painter::Bar bar_red; -	float _progress; +	std::size_t total{0}; +	std::size_t value{0};  };  } // GUI:: diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc index 8282bc8..84d813d 100644 --- a/plugingui/testmain.cc +++ b/plugingui/testmain.cc @@ -26,15 +26,17 @@   */  #include "plugingui.h" +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif +  #include <hugin.hpp> -// Dummy Engine class. -class Engine : public MessageHandler { -public: -	void handleMessage(Message *msg) {} -}; +#include <notifier.h> +#include <settings.h> -class TestMain : public GUI::Listener { +class TestMain : public Listener {  public:  	TestMain()  	{ @@ -62,7 +64,8 @@ public:  	bool running = true; -	GUI::PluginGUI gui; +	Settings settings; +	GUI::PluginGUI gui{settings};  };  int main() diff --git a/src/Makefile.am b/src/Makefile.am index 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/plugingui/notifier.h b/src/notifier.h index 9e9f6eb..ff59741 100644 --- a/plugingui/notifier.h +++ b/src/notifier.h @@ -72,7 +72,7 @@ namespace aux  }; -namespace GUI { +//namespace GUI {  class Listener;  class NotifierBase { @@ -158,6 +158,6 @@ private:  }; -} // GUI:: +//} // 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;  } @@ -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; +	} +}; diff --git a/test/Makefile.am b/test/Makefile.am index ccb21e6..3633ad8 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,7 +3,7 @@ include $(top_srcdir)/src/Makefile.am.drumgizmo  TESTS = resource engine gui resampler lv2 configfile audiocache \  	audiocachefile audiocacheidmanager audiocacheeventhandler \ -	memchecker random +	memchecker random atomictest syncedsettingstest  check_PROGRAMS = $(TESTS) @@ -29,7 +29,6 @@ audiocache_SOURCES = \  	$(top_srcdir)/src/thread.cc \  	$(top_srcdir)/src/mutex.cc \  	$(top_srcdir)/src/semaphore.cc \ -	$(top_srcdir)/src/configuration.cc \  	$(top_srcdir)/src/audiofile.cc \  	test.cc \  	audiocachetest.cc @@ -43,7 +42,6 @@ audiocachefile_SOURCES = \  	$(top_srcdir)/src/thread.cc \  	$(top_srcdir)/src/mutex.cc \  	$(top_srcdir)/src/semaphore.cc \ -	$(top_srcdir)/src/configuration.cc \  	$(top_srcdir)/src/audiofile.cc \  	test.cc \  	audiocachefiletest.cc @@ -138,5 +136,15 @@ random_SOURCES = \  	test.cc \  	randomtest.cc +atomictest_CXXFLAGS = -DOUTPUT=\"atomictest\" $(CPPUNIT_CFLAGS) \ +	-I$(top_srcdir)/src -I$(top_srcdir)/hugin +atomictest_LDFLAGS = $(CPPUNIT_LIBS) +atomictest_SOURCES = atomictest.cc test.cc + +syncedsettingstest_CXXFLAGS = -DOUTPUT=\"syncedsettingstest\" $(CPPUNIT_CFLAGS) \ +	-I$(top_srcdir)/src -I$(top_srcdir)/hugin +syncedsettingstest_LDFLAGS = $(CPPUNIT_LIBS) +syncedsettingstest_SOURCES = syncedsettings.cc test.cc +  EXTRA_DIST = \  	lv2_test_host.h diff --git a/test/atomictest.cc b/test/atomictest.cc new file mode 100644 index 0000000..1718b33 --- /dev/null +++ b/test/atomictest.cc @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            atomic.cc + * + *  Wed Mar 23 09:17:12 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. + */ +#include <cppunit/extensions/HelperMacros.h> + +#include <atomic.h> + +class AtomicTest +	: public CppUnit::TestFixture { +		 +	CPPUNIT_TEST_SUITE(AtomicTest); +	CPPUNIT_TEST(podAtomicsUseStandardImpl); +	CPPUNIT_TEST(nonPodAtomicsUseOwnImpl); +	CPPUNIT_TEST(podAtomicCanBeDefaultInitialized); +	CPPUNIT_TEST(nonPodAtomicCanBeDefaultInitialized); +	CPPUNIT_TEST(podAtomicCanBeValueInitialized); +	CPPUNIT_TEST(nonPodAtomicCanBeValueInitialized); +	CPPUNIT_TEST(podAtomicCanBeValueAssigned); +	CPPUNIT_TEST(nonPodAtomicCanBeValueAssigned); +	CPPUNIT_TEST(podAtomicsAreLockFree); +	CPPUNIT_TEST_SUITE_END(); +	 +	public: +		void setUp() {} +		void tearDown() {} +		 +		void podAtomicsUseStandardImpl() { +			CPPUNIT_ASSERT(isUsingStandardImpl<bool>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<unsigned short int>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<short int>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<unsigned int>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<int>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<unsigned long int>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<long int>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<unsigned long long int>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<long long int>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<float>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<double>()); +			CPPUNIT_ASSERT(isUsingStandardImpl<long double>()); +		} +		 +		void nonPodAtomicsUseOwnImpl() { +			CPPUNIT_ASSERT(!isUsingStandardImpl<std::string>()); +		} +		 +		void podAtomicCanBeDefaultInitialized() { +			Atomic<int> i; +			// note: i is initialized with garbage +		} +		 +		void nonPodAtomicCanBeDefaultInitialized() { +			Atomic<std::string> s; +			CPPUNIT_ASSERT_EQUAL(s.load(), std::string{}); +		} +		 +		void podAtomicCanBeValueInitialized() { +			Atomic<int> i{5}; +			CPPUNIT_ASSERT_EQUAL(i.load(), 5); +		} +		 +		void nonPodAtomicCanBeValueInitialized() { +			Atomic<std::string> s{"hello world"}; +			CPPUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"}); +		} +		 +		void podAtomicCanBeValueAssigned() { +			Atomic<int> i; +			i = 5; +			CPPUNIT_ASSERT_EQUAL(i.load(), 5); +		} +		 +		void nonPodAtomicCanBeValueAssigned() { +			Atomic<std::string> s; +			s = "hello world"; +			CPPUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"}); +		} +		 +		void podAtomicsAreLockFree() { +			CPPUNIT_ASSERT(isLockFree<bool>()); +			CPPUNIT_ASSERT(isLockFree<unsigned short int>()); +			CPPUNIT_ASSERT(isLockFree<short int>()); +			CPPUNIT_ASSERT(isLockFree<unsigned int>()); +			CPPUNIT_ASSERT(isLockFree<int>()); +			CPPUNIT_ASSERT(isLockFree<unsigned long int>()); +			CPPUNIT_ASSERT(isLockFree<long int>()); +			CPPUNIT_ASSERT(isLockFree<unsigned long long int>()); +			CPPUNIT_ASSERT(isLockFree<long long int>()); +			CPPUNIT_ASSERT(isLockFree<float>()); +			CPPUNIT_ASSERT(isLockFree<double>()); +			 +			// compile error: undefined reference to `__atomic_is_lock_free' +			//CPPUNIT_ASSERT(isLockFree<long double>()); +		} +		 +		// todo: further testing +		 +	private: +		template <typename T> +		bool isUsingStandardImpl() { +			return std::is_base_of<std::atomic<T>, Atomic<T>>::value; +		} +		 +		template <typename T> +		bool isLockFree() { +			Atomic<T> a; +			return a.is_lock_free(); +		} +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AtomicTest); + diff --git a/test/engine.cc b/test/engine.cc index 86f4f4d..89c0158 100644 --- a/test/engine.cc +++ b/test/engine.cc @@ -40,9 +40,10 @@ public:  	void tearDown() {}    void loading() { +	  Settings settings;      AudioOutputEngine *oe = NULL;      AudioInputEngine *ie = NULL; -    DrumGizmo dg(oe, ie); +    DrumGizmo dg(settings, oe, ie);      dg.setFrameSize(100);      // Switch kits emmidiately with giving the loader time to work: diff --git a/test/memcheckertest.cc b/test/memcheckertest.cc index 90bd254..e312ca7 100644 --- a/test/memcheckertest.cc +++ b/test/memcheckertest.cc @@ -52,6 +52,7 @@ class MemCheckerTest  	CPPUNIT_TEST(check_free_ram);  	CPPUNIT_TEST_SUITE_END();  private: +	Settings settings;  	DrumKit kit;  	const std::string small_kit_path = "kit/small_kit.xml"; @@ -70,7 +71,7 @@ public:  	void small_drumkit()  	{  		// load the small kit -		DrumKitParser parser(kit); +		DrumKitParser parser(settings, kit);  		CPPUNIT_ASSERT(!parser.parseFile(small_kit_path));  		// check if the memchecker thinks it fits into memory @@ -80,7 +81,7 @@ public:  	void huge_drumkit()  	{  		// load the huge kit -		DrumKitParser parser(kit); +		DrumKitParser parser(settings, kit);  		CPPUNIT_ASSERT(!parser.parseFile(huge_kit_path));  		// check if the memchecker thinks it doesn't fit into memory @@ -94,7 +95,7 @@ public:  		CPPUNIT_ASSERT_EQUAL(bytes_per_channel, calcBytesPerChannel(audiofile));  		// load the huge kit -		DrumKitParser parser(kit); +		DrumKitParser parser(settings, kit);  		CPPUNIT_ASSERT(!parser.parseFile(huge_kit_path));  		// check if the protected method of the memchecker reports the correct size diff --git a/test/syncedsettings.cc b/test/syncedsettings.cc new file mode 100644 index 0000000..62bd8c6 --- /dev/null +++ b/test/syncedsettings.cc @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            syncedsettings.cc + * + *  Wed Mar 31 09:32:12 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. + */ +#include <cppunit/extensions/HelperMacros.h> + +#include <syncedsettings.h> + +class SyncedSettingsTest +	: public CppUnit::TestFixture { +		 +	CPPUNIT_TEST_SUITE(SyncedSettingsTest); +	CPPUNIT_TEST(groupCanBeDefaultInitialized); +	CPPUNIT_TEST(groupDataCanBeCopied); +	 +	CPPUNIT_TEST(accessorCanGetFields); +	CPPUNIT_TEST(accessorCanSetFields); +	 +	CPPUNIT_TEST(groupHasCopyCtor); +	CPPUNIT_TEST(groupHasMoveCtor); +	CPPUNIT_TEST(groupHasCopyAssignOp); +	CPPUNIT_TEST(groupHasMoveAssignOp); +	 +	CPPUNIT_TEST(mimicRealUse); +	CPPUNIT_TEST_SUITE_END(); +	 +	private: +		struct TestData { +			float foo; +			bool bar; +			std::string msg; +		}; +	 +	public: +		void setUp() {} +		void tearDown() {} +		 +		void groupCanBeDefaultInitialized() { +			Group<TestData> data; +		} +		 +		void groupDataCanBeCopied() { +			Group<TestData> data; +			(TestData)data; // copies +		} +		 +		void accessorCanSetFields() { +			Group<TestData> data; +			{ +				Accessor<TestData> a{data}; +				a.data.foo = 3.f; +				a.data.bar = false; +				a.data.msg = "hello"; +			} +			TestData copy = data; +			CPPUNIT_ASSERT_EQUAL(copy.foo, 3.f); +			CPPUNIT_ASSERT_EQUAL(copy.bar, false); +			CPPUNIT_ASSERT_EQUAL(copy.msg, std::string{"hello"}); +		} +		 +		void accessorCanGetFields() { +			Group<TestData> data; +			{ +				Accessor<TestData> a{data}; +				a.data.foo = 3.f; +				a.data.bar = false; +				a.data.msg = "hello"; +			} +			// now read +			{ +				Accessor<TestData> a{data}; +				CPPUNIT_ASSERT_EQUAL(a.data.foo, 3.f); +				CPPUNIT_ASSERT_EQUAL(a.data.bar, false); +				CPPUNIT_ASSERT_EQUAL(a.data.msg, std::string{"hello"}); +			} +		} +		 +		void groupHasCopyCtor() { +			Group<TestData> tmp; +			{ +				Accessor<TestData> a{tmp}; +				a.data.foo = 3.f; +				a.data.bar = false; +				a.data.msg = "hello"; +			} +			Group<TestData> data{tmp}; +			TestData copy = data; +			CPPUNIT_ASSERT_EQUAL(copy.foo, 3.f); +			CPPUNIT_ASSERT_EQUAL(copy.bar, false); +			CPPUNIT_ASSERT_EQUAL(copy.msg, std::string{"hello"}); +		} +		 +		void groupHasMoveCtor() { +			Group<TestData> tmp; +			{ +				Accessor<TestData> a{tmp}; +				a.data.foo = 3.f; +				a.data.bar = false; +				a.data.msg = "hello"; +			} +			Group<TestData> data{std::move(tmp)}; +			TestData copy = data; +			CPPUNIT_ASSERT_EQUAL(copy.foo, 3.f); +			CPPUNIT_ASSERT_EQUAL(copy.bar, false); +			CPPUNIT_ASSERT_EQUAL(copy.msg, std::string{"hello"}); +		} +		 +		void groupHasCopyAssignOp() { +			Group<TestData> tmp; +			{ +				Accessor<TestData> a{tmp}; +				a.data.foo = 3.f; +				a.data.bar = false; +				a.data.msg = "hello"; +			} +			Group<TestData> data = tmp; +			TestData copy = data; +			CPPUNIT_ASSERT_EQUAL(copy.foo, 3.f); +			CPPUNIT_ASSERT_EQUAL(copy.bar, false); +			CPPUNIT_ASSERT_EQUAL(copy.msg, std::string{"hello"}); +		} +		 +		void groupHasMoveAssignOp() { +			Group<TestData> tmp; +			{ +				Accessor<TestData> a{tmp}; +				a.data.foo = 3.f; +				a.data.bar = false; +				a.data.msg = "hello"; +			} +			Group<TestData> data = std::move(tmp); +			TestData copy = data; +			CPPUNIT_ASSERT_EQUAL(copy.foo, 3.f); +			CPPUNIT_ASSERT_EQUAL(copy.bar, false); +			CPPUNIT_ASSERT_EQUAL(copy.msg, std::string{"hello"}); +		} +		 +		void mimicRealUse() { +			struct Settings { +				struct Foo { +					float a{5}; +					float b{3}; +					bool enabled{true}; +				}; +				struct Bar { +					std::string label{"empty"}; +					float bla{0.f}; +				}; +				 +				Group<Foo> foo; +				Group<Bar> bar; +			}; +			 +			Settings s; +			 +			// set bar settings +			{ +				Accessor<Settings::Bar> tmp{s.bar}; +				tmp.data.label = "hello world"; +				tmp.data.bla = 3.14f; +			} +			 +			// read foo settings +			{ +				Accessor<Settings::Foo> tmp{s.foo}; +				if (tmp.data.enabled) { +					// do some while locked +				} +			} +			// or: +			Settings::Foo copy = s.foo; +			if (copy.enabled) { +				// do some stuff without locking +			} +			CPPUNIT_ASSERT(copy.enabled); +		} +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(SyncedSettingsTest); + | 
