From 0728a11284f15100a8f8e0d9da0192019a056d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Tue, 22 Mar 2016 00:40:15 +0100 Subject: Parser refactoring. * Use new style * Update to C++11 * Use more std::string than char* --- src/configparser.cc | 45 +++--- src/configparser.h | 24 ++- src/drumkitparser.cc | 409 ++++++++++++++++++++++-------------------------- src/drumkitparser.h | 39 +++-- src/instrumentparser.cc | 399 ++++++++++++++++++++++------------------------ src/instrumentparser.h | 32 ++-- src/midimapparser.cc | 33 ++-- src/midimapparser.h | 22 ++- src/saxparser.cc | 150 +++++++++--------- src/saxparser.h | 37 +++-- 10 files changed, 569 insertions(+), 621 deletions(-) diff --git a/src/configparser.cc b/src/configparser.cc index 86219dd..e8a6d12 100644 --- a/src/configparser.cc +++ b/src/configparser.cc @@ -32,39 +32,40 @@ ConfigParser::ConfigParser() { - str = NULL; + str = nullptr; } -void ConfigParser::characterData(std::string &data) +void ConfigParser::characterData(const std::string& data) { - if(str) str->append(data); + if(str) + { + str->append(data); + } } -void ConfigParser::startTag(std::string name, attr_t attr) +void ConfigParser::startTag(const std::string& name, attr_t& attr) { - if(name == "value" && attr.find("name") != attr.end()) { - values[attr["name"]] = ""; - str = &values[attr["name"]]; - } + if(name == "value" && attr.find("name") != attr.end()) + { + values[attr["name"]] = ""; + str = &values[attr["name"]]; + } } -void ConfigParser::endTag(std::string name) +void ConfigParser::endTag(const std::string& name) { - if(name == "value") str = NULL; + if(name == "value") + { + str = nullptr; + } } -std::string ConfigParser::value(std::string name, std::string def) +std::string ConfigParser::value(const std::string& name, const std::string& def) { - if(values.find(name) == values.end()) return def; - return values[name]; -} + if(values.find(name) == values.end()) + { + return def; + } -void ConfigParser::parseError(char *buf, size_t len, std::string error, - int lineno) -{ - std::string buffer; - buffer.append(buf, len); - ERR(configparser, "sax parser error '%s' at line %d. " - "Buffer: [%d bytes]<%s>\n", - error.c_str(), lineno, (int)len, buffer.c_str()); + return values[name]; } diff --git a/src/configparser.h b/src/configparser.h index 9aba284..b33af85 100644 --- a/src/configparser.h +++ b/src/configparser.h @@ -24,26 +24,24 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_CONFIGPARSER_H__ -#define __DRUMGIZMO_CONFIGPARSER_H__ +#pragma once #include #include "saxparser.h" -class ConfigParser : public SAXParser { +class ConfigParser : + public SAXParser +{ public: - ConfigParser(); + ConfigParser(); - void characterData(std::string &data); - void startTag(std::string name, attr_t attr); - void endTag(std::string name); - std::string value(std::string name, std::string def = ""); - void parseError(char *buf, size_t len, std::string error, int lineno); + void characterData(const std::string& data) override; + void startTag(const std::string& name, attr_t& attr) override; + void endTag(const std::string& name) override; + std::string value(const std::string& name, const std::string& def = ""); private: - std::map values; - std::string *str; + std::map values; + std::string* str; }; - -#endif/*__DRUMGIZMO_CONFIGPARSER_H__*/ diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index e67d65e..eb0913a 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -34,244 +34,213 @@ #include "path.h" #include "drumgizmo.h" -DrumKitParser::DrumKitParser(const std::string &file, DrumKit &k) - : kit(k) - , refs(REFSFILE) +DrumKitParser::DrumKitParser(const std::string& file, DrumKit& k) + : kit(k) + , refs(REFSFILE) { - std::string kitfile = file; + std::string kitfile = file; - if(refs.load()) { - if(file.size() > 1 && file[0] == '@') { - kitfile = refs.getValue(file.substr(1)); - } - } else { - ERR(drumkitparser, "Error reading refs.conf"); - } + if(refs.load()) + { + if(file.size() > 1 && file[0] == '@') + { + kitfile = refs.getValue(file.substr(1)); + } + } + else + { + ERR(drumkitparser, "Error reading refs.conf"); + } - // instr = NULL; - path = getPath(kitfile); + // instr = NULL; + path = getPath(kitfile); - fd = fopen(kitfile.c_str(), "r"); + fd = fopen(kitfile.c_str(), "r"); - // DEBUG(kitparser, "Parsing drumkit in %s\n", kitfile.c_str()); + // DEBUG(kitparser, "Parsing drumkit in %s\n", kitfile.c_str()); - if(!fd) return; + if(!fd) + { + return; + } - kit._file = file; + kit._file = file; } DrumKitParser::~DrumKitParser() { - if(fd) fclose(fd); + if(fd) + { + fclose(fd); + } + } -void DrumKitParser::startTag(std::string name, - std::map attr) +void DrumKitParser::startTag(const std::string& name, + attr_t& attr) { - if(name == "drumkit") { - if(attr.find("name") != attr.end()) - kit._name = attr["name"]; - - if(attr.find("samplerate") != attr.end()) { - kit._samplerate = atoi(attr["samplerate"].c_str()); - } else { - // If 'samplerate' attribute is missing, assume 44k1Hz - // TODO: Ask instrument what samplerate is in the audiofiles... - kit._samplerate = 44100; - } - - if(attr.find("description") != attr.end()) - kit._description = attr["description"]; - - if(attr.find("version") != attr.end()) { - try { - kit._version = VersionStr(attr["version"]); - } catch(const char *err) { - ERR(kitparser, "Error parsing version number: %s, using 1.0\n", err); - kit._version = VersionStr(1,0,0); - } - } else { - WARN(kitparser, "Missing version number, assuming 1.0\n"); - kit._version = VersionStr(1,0,0); - } - } - - if(name == "channels") {} - - if(name == "channel") { - if(attr.find("name") == attr.end()) { - DEBUG(kitparser, "Missing channel name.\n"); - return; - } - Channel c(attr["name"]); - c.num = kit.channels.size(); - kit.channels.push_back(c); - } - - if(name == "instruments") { - } - - if(name == "instrument") { - if(attr.find("name") == attr.end()) { - DEBUG(kitparser, "Missing name in instrument tag.\n"); - return; - } - if(attr.find("file") == attr.end()) { - DEBUG(kitparser, "Missing file in instrument tag.\n"); - return; - } - - instr_name = attr["name"]; - instr_file = attr["file"]; - if(attr.find("group") != attr.end()) instr_group = attr["group"]; - else instr_group = ""; - } - - if(name == "channelmap") { - if(attr.find("in") == attr.end()) { - DEBUG(kitparser, "Missing 'in' in channelmap tag.\n"); - return; - } - - if(attr.find("out") == attr.end()) { - DEBUG(kitparser, "Missing 'out' in channelmap tag.\n"); - return; - } - - channelmap[attr["in"]] = attr["out"]; - } + if(name == "drumkit") + { + if(attr.find("name") != attr.end()) + { + kit._name = attr["name"]; + } + + if(attr.find("samplerate") != attr.end()) + { + kit._samplerate = std::stoi(attr["samplerate"]); + } + else + { + // If 'samplerate' attribute is missing, assume 44k1Hz + // TODO: Ask instrument what samplerate is in the audiofiles... + kit._samplerate = 44100; + } + + if(attr.find("description") != attr.end()) + { + kit._description = attr["description"]; + } + + if(attr.find("version") != attr.end()) + { + try + { + kit._version = VersionStr(attr["version"]); + } + catch(const char *err) + { + ERR(kitparser, "Error parsing version number: %s, using 1.0\n", err); + kit._version = VersionStr(1,0,0); + } + } + else + { + WARN(kitparser, "Missing version number, assuming 1.0\n"); + kit._version = VersionStr(1,0,0); + } + } + + if(name == "channels") + { + + } + + if(name == "channel") + { + if(attr.find("name") == attr.end()) + { + ERR(kitparser, "Missing channel name.\n"); + return; + } + + Channel c(attr["name"]); + c.num = kit.channels.size(); + kit.channels.push_back(c); + } + + if(name == "instruments") + { + + } + + if(name == "instrument") + { + if(attr.find("name") == attr.end()) + { + ERR(kitparser, "Missing name in instrument tag.\n"); + return; + } + if(attr.find("file") == attr.end()) + { + ERR(kitparser, "Missing file in instrument tag.\n"); + return; + } + + instr_name = attr["name"]; + instr_file = attr["file"]; + if(attr.find("group") != attr.end()) + { + instr_group = attr["group"]; + } + else + { + instr_group = ""; + } + } + + if(name == "channelmap") + { + if(attr.find("in") == attr.end()) + { + ERR(kitparser, "Missing 'in' in channelmap tag.\n"); + return; + } + + if(attr.find("out") == attr.end()) + { + ERR(kitparser, "Missing 'out' in channelmap tag.\n"); + return; + } + + channelmap[attr["in"]] = attr["out"]; + } } -void DrumKitParser::endTag(std::string name) +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(path + "/" + instr_file, *i); - parser.parse(); - kit.instruments.push_back(i); - - // Assign kit channel numbers to instruments channels. - std::vector::iterator ic = parser.channellist.begin(); - while(ic != parser.channellist.end()) { - InstrumentChannel *c = *ic; - - std::string cname = c->name; - if(channelmap.find(cname) != channelmap.end()) cname = channelmap[cname]; - - for(size_t cnt = 0; cnt < kit.channels.size(); cnt++) { - if(kit.channels[cnt].name == cname) c->num = kit.channels[cnt].num; - } - if(c->num == NO_CHANNEL) { - DEBUG(kitparser, "Missing channel '%s' in instrument '%s'\n", - c->name.c_str(), i->name().c_str()); - } else { - /* - DEBUG(kitparser, "Assigned channel '%s' to number %d in instrument '%s'\n", - c->name.c_str(), c->num, i.name().c_str()); - */ - } - ic++; - } - - channelmap.clear(); - - } + if(name == "instrument") + { + Instrument* i = new Instrument(); + i->setGroup(instr_group); + // Instrument &i = kit.instruments[kit.instruments.size() - 1]; + InstrumentParser parser(path + "/" + instr_file, *i); + parser.parse(); + kit.instruments.push_back(i); + + // Assign kit channel numbers to instruments channels. + std::vector::iterator ic = parser.channellist.begin(); + while(ic != parser.channellist.end()) + { + InstrumentChannel* c = *ic; + + std::string cname = c->name; + if(channelmap.find(cname) != channelmap.end()) + { + cname = channelmap[cname]; + } + + for(std::size_t cnt = 0; cnt < kit.channels.size(); cnt++) + { + if(kit.channels[cnt].name == cname) + { + 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->name().c_str()); + } + else { + /* + DEBUG(kitparser, "Assigned channel '%s' to number %d in instrument '%s'\n", + c->name.c_str(), c->num, i.name().c_str()); + */ + } + ic++; + } + + channelmap.clear(); + } } -int DrumKitParser::readData(char *data, size_t size) +int DrumKitParser::readData(std::string& data, std::size_t size) { - if(!fd) return -1; - return fread(data, 1, size, fd); -} + if(!fd) + { + return -1; + } -#ifdef TEST_DRUMKITPARSER -//deps: drumkit.cc saxparser.cc instrument.cc sample.cc audiofile.cc channel.cc -//cflags: $(EXPAT_CFLAGS) $(SNDFILE_CFLAGS) -//libs: $(EXPAT_LIBS) $(SNDFILE_LIBS) -#include "test.h" - -const char xml[] = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" - ; - -#define FNAME "/tmp/drumkittest.xml" - -TEST_BEGIN; - -FILE *fp = fopen(FNAME, "w"); -fprintf(fp, "%s", xml); -fclose(fp); - -DrumKit kit; -DrumKitParser p(FNAME, kit); -TEST_EQUAL_INT(p.parse(), 0, "Parsing went well?"); - -TEST_EQUAL_STR(kit.name(), "The Aasimonster", "Compare name"); -TEST_EQUAL_INT(kit.instruments.size(), 2, "How many instruments?"); - -unlink(FNAME); - -TEST_END; - -#endif/*TEST_DRUMKITPARSER*/ + return fread((char*)data.c_str(), 1, size, fd); +} diff --git a/src/drumkitparser.h b/src/drumkitparser.h index d9ec4fe..5c97b4e 100644 --- a/src/drumkitparser.h +++ b/src/drumkitparser.h @@ -24,37 +24,34 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_DRUMKITPARSER_H__ -#define __DRUMGIZMO_DRUMKITPARSER_H__ +#pragma once #include "saxparser.h" #include "drumkit.h" #include "configfile.h" -class DrumKitParser : public SAXParser { +class DrumKitParser + : public SAXParser +{ public: - DrumKitParser(const std::string &kitfile, DrumKit &kit); - ~DrumKitParser(); - - void startTag(std::string name, - std::map< std::string, std::string> attributes); - void endTag(std::string name); + DrumKitParser(const std::string& kitfile, DrumKit& kit); + ~DrumKitParser(); protected: - int readData(char *data, size_t size); + void startTag(const std::string& name, attr_t& attributes) override; + void endTag(const std::string& name) override; + + int readData(std::string& data, std::size_t size) override; private: - FILE *fd; - DrumKit &kit; - // Instrument *instr; - std::string path; + FILE* fd; + DrumKit& kit; + std::string path; - std::map channelmap; - std::string instr_file; - std::string instr_name; - std::string instr_group; + std::map channelmap; + std::string instr_file; + std::string instr_name; + std::string instr_group; - ConfigFile refs; + ConfigFile refs; }; - -#endif/*__DRUMGIZMO_DRUMKITPARSER_H__*/ diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index 5d6acef..c04aee3 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -35,228 +35,207 @@ #include "nolocale.h" -InstrumentParser::InstrumentParser(const std::string &file, Instrument &i) - : instrument(i) +InstrumentParser::InstrumentParser(const std::string& file, Instrument& i) + : instrument(i) { - s = NULL; - // DEBUG(instrparser,"Parsing instrument in %s\n", file.c_str()); - path = getPath(file); - fd = fopen(file.c_str(), "r"); - if(!fd) return; + // DEBUG(instrparser,"Parsing instrument in %s\n", file.c_str()); + path = getPath(file); + fd = fopen(file.c_str(), "r"); + + if(!fd) + { + ERR(instrparser, "The following instrument file could not be opened: %s\n", file.c_str()); + return; + } } InstrumentParser::~InstrumentParser() { - if(fd) fclose(fd); + if(fd) + { + fclose(fd); + } } -void InstrumentParser::startTag(std::string name, - std::map attr) +void InstrumentParser::startTag(const std::string& name, attr_t& attr) { - if(name == "instrument") { - if(attr.find("name") != attr.end()) - instrument._name = attr["name"]; - - if(attr.find("description") != attr.end()) - instrument._description = attr["description"]; - - if(attr.find("version") != attr.end()) { - try { - instrument.version = VersionStr(attr["version"]); - } catch(const char *err) { - ERR(instrparser, "Error parsing version number: %s, using 1.0\n", err); - instrument.version = VersionStr(1,0,0); - } - } else { - WARN(instrparser, "Missing version number, assuming 1.0\n"); - instrument.version = VersionStr(1,0,0); - } - } - - if(name == "samples") { - } - - if(name == "sample") { - if(attr.find("name") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'name'.\n"); - return; - } - - float power; - if(attr.find("power") == attr.end()) { - power = -1; - } else { - power = atof_nol(attr["power"].c_str()); - DEBUG(instrparser, "Instrument power set to %f\n", power); - } - - // TODO get rid of new or delete it properly - s = new Sample(attr["name"], power); - } - - if(name == "audiofile") { - if(s == NULL) { - DEBUG(instrparser,"Missing Sample!\n"); - return; - } - - if(attr.find("file") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'file'.\n"); - return; - } - - if(attr.find("channel") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'channel'.\n"); - return; - } - int filechannel = 1; // default, override with optional attribute - if(attr.find("filechannel") != attr.end()) { - filechannel = atoi(attr["filechannel"].c_str()); - if(filechannel < 1) { - DEBUG(instrparser,"Invalid value for attribute 'filechannel'.\n"); - filechannel = 1; - } - } - 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["file"], filechannel); - InstrumentChannel *ch = new InstrumentChannel(attr["channel"]); - channellist.push_back(ch); - s->addAudioFile(ch, af); - instrument.audiofiles.push_back(af); - } - - if(name == "velocities") { - } - - if(name == "velocity") { - if(attr.find("lower") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'lower'.\n"); - return; - } - - if(attr.find("upper") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'upper'.\n"); - return; - } - - lower = atof_nol(attr["lower"].c_str()); - upper = atof_nol(attr["upper"].c_str()); - } - - if(name == "sampleref") { - if(attr.find("name") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'name'.\n"); - return; - } - - Sample *sample = NULL; - std::vector::iterator i = instrument.samplelist.begin(); - while(i != instrument.samplelist.end()) { - if((*i)->name == attr["name"]) { - sample = *i; - break; - } - i++; - } - - if(sample == NULL) { - DEBUG(instrparser,"Samplref pointed at non-existing sample.\n"); - return; - } - - if(instrument.version == VersionStr("1.0")) { - // Old "velocity group" algorithm needs this - instrument.addSample(lower, upper, sample); - } - } + if(name == "instrument") + { + if(attr.find("name") != attr.end()) + { + instrument._name = attr["name"]; + } + + if(attr.find("description") != attr.end()) + { + instrument._description = attr["description"]; + } + + if(attr.find("version") != attr.end()) + { + try { + instrument.version = VersionStr(attr["version"]); + } + catch(const char *err) + { + ERR(instrparser, "Error parsing version number: %s, using 1.0\n", err); + instrument.version = VersionStr(1,0,0); + } + } + else + { + WARN(instrparser, "Missing version number, assuming 1.0\n"); + instrument.version = VersionStr(1,0,0); + } + } + + if(name == "samples") + { + + } + + if(name == "sample") + { + if(attr.find("name") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'name'.\n"); + return; + } + + float power; + if(attr.find("power") == attr.end()) + { + power = -1; + } + else + { + power = atof_nol(attr["power"].c_str()); + DEBUG(instrparser, "Instrument power set to %f\n", power); + } + + // TODO get rid of new or delete it properly + s = new Sample(attr["name"], power); + } + + if(name == "audiofile") + { + if(s == nullptr) + { + ERR(instrparser,"Missing Sample!\n"); + return; + } + + if(attr.find("file") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'file'.\n"); + return; + } + + if(attr.find("channel") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'channel'.\n"); + return; + } + + int filechannel = 1; // default, override with optional attribute + if(attr.find("filechannel") != attr.end()) + { + filechannel = std::stoi(attr["filechannel"]); + if(filechannel < 1) + { + ERR(instrparser,"Invalid value for attribute 'filechannel'.\n"); + filechannel = 1; + } + } + + 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["file"], filechannel); + InstrumentChannel *ch = new InstrumentChannel(attr["channel"]); + channellist.push_back(ch); + s->addAudioFile(ch, af); + instrument.audiofiles.push_back(af); + } + + if(name == "velocities") + { + + } + + if(name == "velocity") + { + if(attr.find("lower") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'lower'.\n"); + return; + } + + if(attr.find("upper") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'upper'.\n"); + return; + } + + lower = atof_nol(attr["lower"].c_str()); + upper = atof_nol(attr["upper"].c_str()); + } + + if(name == "sampleref") + { + if(attr.find("name") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'name'.\n"); + return; + } + + Sample* sample = nullptr; + std::vector::iterator i = instrument.samplelist.begin(); + while(i != instrument.samplelist.end()) + { + if((*i)->name == attr["name"]) + { + sample = *i; + break; + } + i++; + } + + if(sample == nullptr) + { + ERR(instrparser,"Samplref pointed at non-existing sample.\n"); + return; + } + + if(instrument.version == VersionStr("1.0")) + { + // Old "velocity group" algorithm needs this + instrument.addSample(lower, upper, sample); + } + } } -void InstrumentParser::endTag(std::string name) +void InstrumentParser::endTag(const std::string& name) { - if(name == "sample") { - if(s == NULL) { - DEBUG(instrparser,"Missing Sample.\n"); - return; - } - - instrument.samplelist.push_back(s); - - s = NULL; - } - - if(name == "instrument") { - instrument.finalise(); - } + if(name == "sample") + { + if(s == nullptr) + { + ERR(instrparser,"Missing Sample.\n"); + return; + } + + instrument.samplelist.push_back(s); + + s = nullptr; + } + + if(name == "instrument") { + instrument.finalise(); + } } -int InstrumentParser::readData(char *data, size_t size) +int InstrumentParser::readData(std::string& data, std::size_t size) { - if(!fd) return -1; - return fread(data, 1, size, fd); + if(!fd) return -1; + return fread((char*)data.c_str(), 1, size, fd); } - - -#ifdef TEST_INSTRUMENTPARSER -//deps: saxparser.cc instrument.cc sample.cc audiofile.cc channel.cc -//cflags: $(EXPAT_CFLAGS) $(SNDFILE_CFLAGS) -//libs: $(EXPAT_LIBS) $(SNDFILE_LIBS) -#include "test.h" - -const char xml[] = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" - ; - -#define FNAME "/tmp/instrtest.xml" - -TEST_BEGIN; - -FILE *fp = fopen(FNAME, "w"); -fprintf(fp, "%s", xml); -fclose(fp); - -Instrument instr; -InstrumentParser p(FNAME, instr); -TEST_EQUAL_INT(p.parse(), 0, "Parsing went well?"); - -TEST_EQUAL_STR(instr.name(), "kick-r", "Compare name"); - -unlink(FNAME); - -TEST_END; - -#endif/*TEST_INSTRUMENTPARSER*/ diff --git a/src/instrumentparser.h b/src/instrumentparser.h index 4971922..15fadef 100644 --- a/src/instrumentparser.h +++ b/src/instrumentparser.h @@ -24,37 +24,35 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_INSTRUMENTPARSER_H__ -#define __DRUMGIZMO_INSTRUMENTPARSER_H__ +#pragma once #include "saxparser.h" #include "instrument.h" #include -class InstrumentParser : public SAXParser { +class InstrumentParser + : public SAXParser +{ public: - InstrumentParser(const std::string &instrfile, Instrument &instrument); - ~InstrumentParser(); + InstrumentParser(const std::string& instrfile, Instrument &instrument); + ~InstrumentParser(); - void startTag(std::string name, - std::map< std::string, std::string> attributes); - void endTag(std::string name); - - std::vector channellist; + std::vector channellist; protected: - int readData(char *data, size_t size); + int readData(std::string& data, std::size_t size) override; + + virtual void startTag(const std::string& name, attr_t& attr) override; + virtual void endTag(const std::string& name) override; private: - FILE *fd{nullptr}; - Instrument &instrument; - Sample *s{nullptr}; + FILE* fd{nullptr}; + Instrument& instrument; + Sample* s{nullptr}; - std::string path; + std::string path; level_t lower{0}; level_t upper{0}; }; - -#endif/*__DRUMGIZMO_INSTRUMENTPARSER_H__*/ diff --git a/src/midimapparser.cc b/src/midimapparser.cc index e81b871..3c8eed4 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -26,27 +26,36 @@ */ #include "midimapparser.h" -MidiMapParser::MidiMapParser(std::string file) +MidiMapParser::MidiMapParser(const std::string& file) { - fd = fopen(file.c_str(), "r"); + fd = fopen(file.c_str(), "r"); } MidiMapParser::~MidiMapParser() { - if(fd) fclose(fd); + if(fd) + { + fclose(fd); + } } -void MidiMapParser::startTag(std::string name, attr_t attr) +void MidiMapParser::startTag(const std::string& name, attr_t& attr) { - if(name == "map") { - if(attr.find("note") != attr.end() && attr.find("instr") != attr.end()) { - midimap[atoi(attr["note"].c_str())] = attr["instr"]; - } - } + if(name == "map") + { + if(attr.find("note") != attr.end() && attr.find("instr") != attr.end()) + { + midimap[std::stoi(attr["note"])] = attr["instr"]; + } + } } -int MidiMapParser::readData(char *data, size_t size) +int MidiMapParser::readData(std::string& data, std::size_t size) { - if(!fd) return -1; - return fread(data, 1, size, fd); + if(!fd) + { + return -1; + } + + return fread((char*)data.c_str(), 1, size, fd); } diff --git a/src/midimapparser.h b/src/midimapparser.h index 32cd9e8..67a0b4a 100644 --- a/src/midimapparser.h +++ b/src/midimapparser.h @@ -24,29 +24,27 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_MIDIMAPPARSER_H__ -#define __DRUMGIZMO_MIDIMAPPARSER_H__ +#pragma once #include #include "saxparser.h" - #include "midimapper.h" -class MidiMapParser : public SAXParser { +class MidiMapParser + : public SAXParser +{ public: - MidiMapParser(std::string file); - ~MidiMapParser(); + MidiMapParser(const std::string& file); + ~MidiMapParser(); - void startTag(std::string name, attr_t attr); + void startTag(const std::string& name, attr_t& attr) override; - midimap_t midimap; + midimap_t midimap; protected: - int readData(char *data, size_t size); + int readData(std::string& data, size_t size) override; private: - FILE *fd; + FILE* fd; }; - -#endif/*__DRUMGIZMO_MIDIMAPPARSER_H__*/ diff --git a/src/saxparser.cc b/src/saxparser.cc index f163dfc..5c28962 100644 --- a/src/saxparser.cc +++ b/src/saxparser.cc @@ -30,106 +30,102 @@ #include #include -static void character_hndl(void *p, const XML_Char *s, int len) +SAXParser::SAXParser() { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); - std::string chars; - chars.append(s, len); - parser->characterData(chars); + p = XML_ParserCreate(nullptr); + if(!p) { + 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); } -static void start_hndl(void *p, const char *el, const char **attr) +SAXParser::~SAXParser() { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); + XML_ParserFree(p); +} - // Convert to comfy C++ values... - std::string name = el; - std::map< std::string, std::string > attributes; +int SAXParser::parse() +{ + DEBUG(sax, "parse()\n"); + + std::string buf; + int len; + + do { + len = readData(buf, 32); + if(len <= -1) { + parseError("", 0, "Could not read data", 0); + return 1; + } + if(!XML_Parse(p, (char*)buf.c_str(), len, len == 0)) { + parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), + (int)XML_GetCurrentLineNumber(p)); + return 1; + } + + buf.clear(); + } while(len); + + return 0; +} - while(*attr) { - std::string at_name = *attr; - attr++; - std::string at_value = *attr; - attr++; +int SAXParser::parse(const std::string& buffer) +{ + DEBUG(sax, "parse(buffer %d bytes)\n", (int)buffer.length()); - attributes.insert(make_pair(at_name, at_value)); - } + if(!XML_Parse(p, buffer.c_str(), buffer.length(), true)) { + parseError(buffer, buffer.length(), + XML_ErrorString(XML_GetErrorCode(p)), + (int)XML_GetCurrentLineNumber(p)); + return 1; + } - parser->startTag(name, attributes); + return 0; } -static void end_hndl(void *p, const char *el) +void SAXParser::parseError(const std::string& buf, std::size_t len, const std::string& error, std::size_t lineno) { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); - std::string name = el; - parser->endTag(name); -} + fprintf(stderr, "SAXParser error at line %d: %s\n", (int)lineno, error.c_str()); + fprintf(stderr, "Buffer %u bytes: \n[\n", (int)len); + fwrite((char*)buf.c_str(), len, 1, stderr); -SAXParser::SAXParser() -{ - p = XML_ParserCreate(NULL); - if(!p) { - fprintf(stderr, "Couldn't allocate memory for parser\n"); - // throw Exception(...); - return; - } - - XML_SetUserData(p, this); - XML_UseParserAsHandlerArg(p); - XML_SetElementHandler(p, start_hndl, end_hndl); - XML_SetCharacterDataHandler(p, character_hndl); + fprintf(stderr, "\n]\n"); + fflush(stderr); } -SAXParser::~SAXParser() +void SAXParser::character_hndl(void* p, const XML_Char* s, int len) { - XML_ParserFree(p); + SAXParser* parser = (SAXParser*)XML_GetUserData(p); + std::string chars(s, len); + parser->characterData(chars); } -int SAXParser::parse() +void SAXParser::start_hndl(void* p, const char* el, const char** attr) { - DEBUG(sax, "parse()\n"); - - char buf[32]; - int len; - - do { - len = readData(buf, sizeof(buf) - 1); - if(len == -1) { - parseError((char*)"", 0, "Could not read data", 0); - return 1; - } - if(!XML_Parse(p, buf, len, len == 0)) { - parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return 1; - } - - memset(buf, 0, sizeof(buf)); - } while(len); - - return 0; -} + SAXParser* parser = (SAXParser*)XML_GetUserData(p); -int SAXParser::parse(std::string buffer) -{ - DEBUG(sax, "parse(buffer %d bytes)\n", (int)buffer.length()); + // Convert to comfy C++ values... + attr_t attributes; + + while(*attr) { + std::string at_name = *attr++; + std::string at_value = *attr++; - if(!XML_Parse(p, buffer.c_str(), buffer.length(), true)) { - parseError((char*)buffer.c_str(), buffer.length(), - XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return 1; - } + attributes.emplace(at_name, at_value); + } - return 0; + parser->startTag(std::string(el), attributes); } -void SAXParser::parseError(char *buf, size_t len, std::string error, int lineno) +void SAXParser::end_hndl(void* p, const char* el) { - fprintf(stderr, "SAXParser error at line %d: %s\n", lineno, error.c_str()); - fprintf(stderr, "\tBuffer %u bytes: [", (int)len); - if(fwrite(buf, len, 1, stderr) != len) {} - fprintf(stderr, "]\n"); - fflush(stderr); + SAXParser* parser = (SAXParser*)XML_GetUserData(p); + parser->endTag(std::string(el)); } diff --git a/src/saxparser.h b/src/saxparser.h index 6acbcdc..680df1d 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -24,34 +24,37 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_SAXPARSER_H__ -#define __DRUMGIZMO_SAXPARSER_H__ +#pragma once #include #include #include -typedef std::map< std::string, std::string> attr_t; - class SAXParser { public: - SAXParser(); - virtual ~SAXParser(); + SAXParser(); + virtual ~SAXParser(); - int parse(); - int parse(std::string buffer); - - virtual void characterData(std::string &data) {} - virtual void startTag(std::string name, attr_t attr) {} - virtual void endTag(std::string name) {} + //! Parses the data obtained by readData in chunks. + int parse(); - virtual void parseError(char *buf, size_t len, std::string error, int lineno); + //! Parses all the data in the buffer. + int parse(const std::string& buffer); protected: - virtual int readData(char *data, size_t size) { return 0; } + using attr_t = std::map; + + virtual void characterData(const std::string& data) {} + virtual void startTag(const std::string& name, attr_t& attr) {} + virtual void endTag(const std::string& name) {} + virtual void parseError(const std::string& buf, std::size_t len, const std::string& error, std::size_t lineno); + + virtual int readData(std::string& data, std::size_t size) { return 0; } private: - XML_Parser p; -}; + XML_Parser p; -#endif/*__DRUMGIZMO_SAXPARSER_H__*/ + 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); +}; -- cgit v1.2.3 From 04e088e65942b7f6fdd80c4e54768dca987ff9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Wed, 23 Mar 2016 15:07:17 +0100 Subject: Fix horribly stupid bug. --- src/drumkitparser.cc | 4 ++++ src/instrumentparser.cc | 11 +++++++++-- src/midimapparser.cc | 5 ++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index eb0913a..7f798a8 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -242,5 +242,9 @@ int DrumKitParser::readData(std::string& data, std::size_t size) return -1; } + data.resize(size); + auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); + data.resize(nr_of_bytes_read); + return nr_of_bytes_read; return fread((char*)data.c_str(), 1, size, fd); } diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index c04aee3..3b849e1 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -236,6 +236,13 @@ void InstrumentParser::endTag(const std::string& name) int InstrumentParser::readData(std::string& data, std::size_t size) { - if(!fd) return -1; - return fread((char*)data.c_str(), 1, size, fd); + if(!fd) + { + return -1; + } + + data.resize(size); + auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); + data.resize(nr_of_bytes_read); + return nr_of_bytes_read; } diff --git a/src/midimapparser.cc b/src/midimapparser.cc index 3c8eed4..f66d063 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -57,5 +57,8 @@ int MidiMapParser::readData(std::string& data, std::size_t size) return -1; } - return fread((char*)data.c_str(), 1, size, fd); + data.resize(size); + auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); + data.resize(nr_of_bytes_read); + return nr_of_bytes_read; } -- cgit v1.2.3 From e8fcde7654f2d7dce494ebe1ca27abbebc3908b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Wed, 23 Mar 2016 15:59:41 +0100 Subject: Make attr a const ref. --- src/configparser.cc | 6 +++--- src/configparser.h | 2 +- src/drumkitparser.cc | 21 ++++++++++----------- src/drumkitparser.h | 2 +- src/instrumentparser.cc | 24 ++++++++++++------------ src/instrumentparser.h | 2 +- src/midimapparser.cc | 4 ++-- src/midimapparser.h | 2 +- src/saxparser.h | 2 +- 9 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/configparser.cc b/src/configparser.cc index e8a6d12..4bb5c45 100644 --- a/src/configparser.cc +++ b/src/configparser.cc @@ -43,12 +43,12 @@ void ConfigParser::characterData(const std::string& data) } } -void ConfigParser::startTag(const std::string& name, attr_t& attr) +void ConfigParser::startTag(const std::string& name, const attr_t& attr) { if(name == "value" && attr.find("name") != attr.end()) { - values[attr["name"]] = ""; - str = &values[attr["name"]]; + values[attr.at("name")] = ""; + str = &values[attr.at("name")]; } } diff --git a/src/configparser.h b/src/configparser.h index b33af85..ac1b5bb 100644 --- a/src/configparser.h +++ b/src/configparser.h @@ -37,7 +37,7 @@ public: ConfigParser(); void characterData(const std::string& data) override; - void startTag(const std::string& name, attr_t& attr) override; + void startTag(const std::string& name, const attr_t& attr) override; void endTag(const std::string& name) override; std::string value(const std::string& name, const std::string& def = ""); diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 7f798a8..510bb53 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -76,19 +76,18 @@ DrumKitParser::~DrumKitParser() } -void DrumKitParser::startTag(const std::string& name, - attr_t& attr) +void DrumKitParser::startTag(const std::string& name, const attr_t& attr) { if(name == "drumkit") { if(attr.find("name") != attr.end()) { - kit._name = attr["name"]; + kit._name = attr.at("name"); } if(attr.find("samplerate") != attr.end()) { - kit._samplerate = std::stoi(attr["samplerate"]); + kit._samplerate = std::stoi(attr.at("samplerate")); } else { @@ -99,14 +98,14 @@ void DrumKitParser::startTag(const std::string& name, if(attr.find("description") != attr.end()) { - kit._description = attr["description"]; + kit._description = attr.at("description"); } if(attr.find("version") != attr.end()) { try { - kit._version = VersionStr(attr["version"]); + kit._version = VersionStr(attr.at("version")); } catch(const char *err) { @@ -134,7 +133,7 @@ void DrumKitParser::startTag(const std::string& name, return; } - Channel c(attr["name"]); + Channel c(attr.at("name")); c.num = kit.channels.size(); kit.channels.push_back(c); } @@ -157,11 +156,11 @@ void DrumKitParser::startTag(const std::string& name, return; } - instr_name = attr["name"]; - instr_file = attr["file"]; + instr_name = attr.at("name"); + instr_file = attr.at("file"); if(attr.find("group") != attr.end()) { - instr_group = attr["group"]; + instr_group = attr.at("group"); } else { @@ -183,7 +182,7 @@ void DrumKitParser::startTag(const std::string& name, return; } - channelmap[attr["in"]] = attr["out"]; + channelmap[attr.at("in")] = attr.at("out"); } } diff --git a/src/drumkitparser.h b/src/drumkitparser.h index 5c97b4e..2344261 100644 --- a/src/drumkitparser.h +++ b/src/drumkitparser.h @@ -38,7 +38,7 @@ public: ~DrumKitParser(); protected: - void startTag(const std::string& name, attr_t& attributes) override; + void startTag(const std::string& name, const attr_t& attributes) override; void endTag(const std::string& name) override; int readData(std::string& data, std::size_t size) override; diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index 3b849e1..3c34b9f 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -57,24 +57,24 @@ InstrumentParser::~InstrumentParser() } } -void InstrumentParser::startTag(const std::string& name, attr_t& attr) +void InstrumentParser::startTag(const std::string& name, const attr_t& attr) { if(name == "instrument") { if(attr.find("name") != attr.end()) { - instrument._name = attr["name"]; + instrument._name = attr.at("name"); } if(attr.find("description") != attr.end()) { - instrument._description = attr["description"]; + instrument._description = attr.at("description"); } if(attr.find("version") != attr.end()) { try { - instrument.version = VersionStr(attr["version"]); + instrument.version = VersionStr(attr.at("version")); } catch(const char *err) { @@ -109,12 +109,12 @@ void InstrumentParser::startTag(const std::string& name, attr_t& attr) } else { - power = atof_nol(attr["power"].c_str()); + power = atof_nol(attr.at("power").c_str()); DEBUG(instrparser, "Instrument power set to %f\n", power); } // TODO get rid of new or delete it properly - s = new Sample(attr["name"], power); + s = new Sample(attr.at("name"), power); } if(name == "audiofile") @@ -140,7 +140,7 @@ void InstrumentParser::startTag(const std::string& name, attr_t& attr) int filechannel = 1; // default, override with optional attribute if(attr.find("filechannel") != attr.end()) { - filechannel = std::stoi(attr["filechannel"]); + filechannel = std::stoi(attr.at("filechannel")); if(filechannel < 1) { ERR(instrparser,"Invalid value for attribute 'filechannel'.\n"); @@ -150,8 +150,8 @@ void InstrumentParser::startTag(const std::string& name, 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["file"], filechannel); - InstrumentChannel *ch = new InstrumentChannel(attr["channel"]); + 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); @@ -176,8 +176,8 @@ void InstrumentParser::startTag(const std::string& name, attr_t& attr) return; } - lower = atof_nol(attr["lower"].c_str()); - upper = atof_nol(attr["upper"].c_str()); + lower = atof_nol(attr.at("lower").c_str()); + upper = atof_nol(attr.at("upper").c_str()); } if(name == "sampleref") @@ -192,7 +192,7 @@ void InstrumentParser::startTag(const std::string& name, attr_t& attr) std::vector::iterator i = instrument.samplelist.begin(); while(i != instrument.samplelist.end()) { - if((*i)->name == attr["name"]) + if((*i)->name == attr.at("name")) { sample = *i; break; diff --git a/src/instrumentparser.h b/src/instrumentparser.h index 15fadef..50e05ef 100644 --- a/src/instrumentparser.h +++ b/src/instrumentparser.h @@ -43,7 +43,7 @@ public: protected: int readData(std::string& data, std::size_t size) override; - virtual void startTag(const std::string& name, attr_t& attr) override; + virtual void startTag(const std::string& name, const attr_t& attr) override; virtual void endTag(const std::string& name) override; private: diff --git a/src/midimapparser.cc b/src/midimapparser.cc index f66d063..e847c58 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -39,13 +39,13 @@ MidiMapParser::~MidiMapParser() } } -void MidiMapParser::startTag(const std::string& name, attr_t& attr) +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()) { - midimap[std::stoi(attr["note"])] = attr["instr"]; + midimap[std::stoi(attr.at("note"))] = attr.at("instr"); } } } diff --git a/src/midimapparser.h b/src/midimapparser.h index 67a0b4a..1a3dde0 100644 --- a/src/midimapparser.h +++ b/src/midimapparser.h @@ -38,7 +38,7 @@ public: MidiMapParser(const std::string& file); ~MidiMapParser(); - void startTag(const std::string& name, attr_t& attr) override; + void startTag(const std::string& name, const attr_t& attr) override; midimap_t midimap; diff --git a/src/saxparser.h b/src/saxparser.h index 680df1d..8664cb0 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -45,7 +45,7 @@ protected: using attr_t = std::map; virtual void characterData(const std::string& data) {} - virtual void startTag(const std::string& name, attr_t& attr) {} + 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, std::size_t len, const std::string& error, std::size_t lineno); -- cgit v1.2.3 From 5c04b951ffe53e1a31182bb0814908af8d7f0a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Wed, 23 Mar 2016 18:24:29 +0100 Subject: Do the file related actions in SAXParser. --- src/audioinputenginemidi.cc | 4 +-- src/configparser.h | 4 +-- src/drumgizmo.cc | 6 ++--- src/drumkitparser.cc | 56 +++++++++++--------------------------- src/drumkitparser.h | 8 +++--- src/instrumentparser.cc | 32 ++++------------------ src/instrumentparser.h | 8 +++--- src/midimapparser.cc | 26 ------------------ src/midimapparser.h | 9 ------- src/saxparser.cc | 65 +++++++++++++++++++++------------------------ src/saxparser.h | 12 ++++----- 11 files changed, 70 insertions(+), 160 deletions(-) diff --git a/src/audioinputenginemidi.cc b/src/audioinputenginemidi.cc index 052c5f0..5c87c3a 100644 --- a/src/audioinputenginemidi.cc +++ b/src/audioinputenginemidi.cc @@ -58,8 +58,8 @@ bool AudioInputEngineMidi::loadMidiMap(std::string file, Instruments &instrument if(f == "") return false; - MidiMapParser p(f); - if(p.parse()) { + MidiMapParser p; + if(p.parseFile(f)) { return false; } diff --git a/src/configparser.h b/src/configparser.h index ac1b5bb..90b0ebf 100644 --- a/src/configparser.h +++ b/src/configparser.h @@ -30,8 +30,8 @@ #include "saxparser.h" -class ConfigParser : - public SAXParser +class ConfigParser + : public SAXParser { public: ConfigParser(); diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 6906fb1..2599f9f 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -81,8 +81,8 @@ bool DrumGizmo::loadkit(std::string file) // Delete all Channels, Instruments, Samples and AudioFiles. kit.clear(); - DrumKitParser parser(file, kit); - if(parser.parse()) + DrumKitParser parser(kit); + if(parser.parseFile(file)) { ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); return false; @@ -709,7 +709,7 @@ bool DrumGizmo::setConfigString(std::string cfg) std::string dkf; ConfigParser p; - if(p.parse(cfg)) + if(p.parseString(cfg)) { ERR(drumgizmo, "Config parse error.\n"); return false; diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 510bb53..b935353 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -34,17 +34,21 @@ #include "path.h" #include "drumgizmo.h" -DrumKitParser::DrumKitParser(const std::string& file, DrumKit& k) - : kit(k) +DrumKitParser::DrumKitParser(DrumKit& kit) + : kit(kit) , refs(REFSFILE) { - std::string kitfile = file; +} + +int DrumKitParser::parseFile(const std::string& filename) +{ + auto edited_filename(filename); if(refs.load()) { - if(file.size() > 1 && file[0] == '@') + if(filename.size() > 1 && filename[0] == '@') { - kitfile = refs.getValue(file.substr(1)); + edited_filename = refs.getValue(filename.substr(1)); } } else @@ -52,28 +56,14 @@ DrumKitParser::DrumKitParser(const std::string& file, DrumKit& k) ERR(drumkitparser, "Error reading refs.conf"); } - // instr = NULL; - path = getPath(kitfile); - - fd = fopen(kitfile.c_str(), "r"); - - // DEBUG(kitparser, "Parsing drumkit in %s\n", kitfile.c_str()); - - if(!fd) - { - return; - } - - kit._file = file; -} + path = getPath(edited_filename); + auto result = SAXParser::parseFile(filename); -DrumKitParser::~DrumKitParser() -{ - if(fd) - { - fclose(fd); + if (result == 0) { + kit._file = edited_filename; } + return result; } void DrumKitParser::startTag(const std::string& name, const attr_t& attr) @@ -193,8 +183,8 @@ void DrumKitParser::endTag(const std::string& name) Instrument* i = new Instrument(); i->setGroup(instr_group); // Instrument &i = kit.instruments[kit.instruments.size() - 1]; - InstrumentParser parser(path + "/" + instr_file, *i); - parser.parse(); + InstrumentParser parser(*i); + parser.parseFile(path + "/" + instr_file); kit.instruments.push_back(i); // Assign kit channel numbers to instruments channels. @@ -233,17 +223,3 @@ void DrumKitParser::endTag(const std::string& name) channelmap.clear(); } } - -int DrumKitParser::readData(std::string& data, std::size_t size) -{ - if(!fd) - { - return -1; - } - - data.resize(size); - auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); - data.resize(nr_of_bytes_read); - return nr_of_bytes_read; - return fread((char*)data.c_str(), 1, size, fd); -} diff --git a/src/drumkitparser.h b/src/drumkitparser.h index 2344261..98ea875 100644 --- a/src/drumkitparser.h +++ b/src/drumkitparser.h @@ -34,17 +34,15 @@ class DrumKitParser : public SAXParser { public: - DrumKitParser(const std::string& kitfile, DrumKit& kit); - ~DrumKitParser(); + DrumKitParser(DrumKit& kit); + + virtual int parseFile(const std::string& filename) override; protected: void startTag(const std::string& name, const attr_t& attributes) override; void endTag(const std::string& name) override; - int readData(std::string& data, std::size_t size) override; - private: - FILE* fd; DrumKit& kit; std::string path; diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index 3c34b9f..bd356a9 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -35,26 +35,17 @@ #include "nolocale.h" -InstrumentParser::InstrumentParser(const std::string& file, Instrument& i) +InstrumentParser::InstrumentParser(Instrument& i) : instrument(i) { - // DEBUG(instrparser,"Parsing instrument in %s\n", file.c_str()); - path = getPath(file); - fd = fopen(file.c_str(), "r"); - if(!fd) - { - ERR(instrparser, "The following instrument file could not be opened: %s\n", file.c_str()); - return; - } } -InstrumentParser::~InstrumentParser() +int InstrumentParser::parseFile(const std::string& filename) { - if(fd) - { - fclose(fd); - } + path = getPath(filename); + + return SAXParser::parseFile(filename); } void InstrumentParser::startTag(const std::string& name, const attr_t& attr) @@ -233,16 +224,3 @@ void InstrumentParser::endTag(const std::string& name) instrument.finalise(); } } - -int InstrumentParser::readData(std::string& data, std::size_t size) -{ - if(!fd) - { - return -1; - } - - data.resize(size); - auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); - data.resize(nr_of_bytes_read); - return nr_of_bytes_read; -} diff --git a/src/instrumentparser.h b/src/instrumentparser.h index 50e05ef..951b8ed 100644 --- a/src/instrumentparser.h +++ b/src/instrumentparser.h @@ -35,19 +35,17 @@ class InstrumentParser : public SAXParser { public: - InstrumentParser(const std::string& instrfile, Instrument &instrument); - ~InstrumentParser(); + InstrumentParser(Instrument &instrument); + + virtual int parseFile(const std::string& filename) override; std::vector channellist; protected: - int readData(std::string& data, std::size_t size) override; - virtual void startTag(const std::string& name, const attr_t& attr) override; virtual void endTag(const std::string& name) override; private: - FILE* fd{nullptr}; Instrument& instrument; Sample* s{nullptr}; diff --git a/src/midimapparser.cc b/src/midimapparser.cc index e847c58..8d0e6ad 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -26,19 +26,6 @@ */ #include "midimapparser.h" -MidiMapParser::MidiMapParser(const std::string& file) -{ - fd = fopen(file.c_str(), "r"); -} - -MidiMapParser::~MidiMapParser() -{ - if(fd) - { - fclose(fd); - } -} - void MidiMapParser::startTag(const std::string& name, const attr_t& attr) { if(name == "map") @@ -49,16 +36,3 @@ void MidiMapParser::startTag(const std::string& name, const attr_t& attr) } } } - -int MidiMapParser::readData(std::string& data, std::size_t size) -{ - if(!fd) - { - return -1; - } - - data.resize(size); - auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); - data.resize(nr_of_bytes_read); - return nr_of_bytes_read; -} diff --git a/src/midimapparser.h b/src/midimapparser.h index 1a3dde0..35c64d5 100644 --- a/src/midimapparser.h +++ b/src/midimapparser.h @@ -35,16 +35,7 @@ class MidiMapParser : public SAXParser { public: - MidiMapParser(const std::string& file); - ~MidiMapParser(); - void startTag(const std::string& name, const attr_t& attr) override; midimap_t midimap; - -protected: - int readData(std::string& data, size_t size) override; - -private: - FILE* fd; }; diff --git a/src/saxparser.cc b/src/saxparser.cc index 5c28962..fcf7b2d 100644 --- a/src/saxparser.cc +++ b/src/saxparser.cc @@ -26,9 +26,10 @@ */ #include "saxparser.h" -#include #include #include +#include +#include SAXParser::SAXParser() { @@ -50,54 +51,48 @@ SAXParser::~SAXParser() XML_ParserFree(p); } -int SAXParser::parse() +int SAXParser::parseFile(const std::string& filename) { - DEBUG(sax, "parse()\n"); - - std::string buf; - int len; - - do { - len = readData(buf, 32); - if(len <= -1) { - parseError("", 0, "Could not read data", 0); - return 1; - } - if(!XML_Parse(p, (char*)buf.c_str(), len, len == 0)) { - parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return 1; - } - - buf.clear(); - } while(len); + if(filename.empty()) + { + return 0; + } + + std::ifstream file(filename, std::ifstream::in); + + if(!file.is_open()) { + return 1; + } + + std::stringstream ss; + ss << file.rdbuf(); + std::string str = ss.str(); + + parseString(str, filename); return 0; } -int SAXParser::parse(const std::string& buffer) +int SAXParser::parseString(const std::string& str, const std::string& xml_source_name) { - DEBUG(sax, "parse(buffer %d bytes)\n", (int)buffer.length()); + DEBUG(sax, "parse(buffer %d bytes)\n", (int)str.length()); - if(!XML_Parse(p, buffer.c_str(), buffer.length(), true)) { - parseError(buffer, buffer.length(), - XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); + if(!XML_Parse(p, str.c_str(), str.length(), true)) { + parseError(str, XML_ErrorString(XML_GetErrorCode(p)), + xml_source_name, (int)XML_GetCurrentLineNumber(p)); return 1; } return 0; } -void SAXParser::parseError(const std::string& buf, std::size_t len, const std::string& error, 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) { - fprintf(stderr, "SAXParser error at line %d: %s\n", (int)lineno, error.c_str()); - fprintf(stderr, "Buffer %u bytes: \n[\n", (int)len); - - fwrite((char*)buf.c_str(), len, 1, stderr); - - fprintf(stderr, "\n]\n"); - fflush(stderr); + 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) diff --git a/src/saxparser.h b/src/saxparser.h index 8664cb0..b688e32 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -29,17 +29,18 @@ #include #include #include +#include class SAXParser { public: SAXParser(); virtual ~SAXParser(); - //! Parses the data obtained by readData in chunks. - int parse(); + //! Parses the data from the file. + virtual int parseFile(const std::string& filename); //! Parses all the data in the buffer. - int parse(const std::string& buffer); + virtual int parseString(const std::string& str, const std::string& xml_source_name = ""); protected: using attr_t = std::map; @@ -47,12 +48,11 @@ 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, std::size_t len, const std::string& error, std::size_t lineno); - - virtual int readData(std::string& data, std::size_t size) { return 0; } + 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; + 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); -- cgit v1.2.3 From 91b3683ad0b6228bf85eefdb32e2ac3f717bd41c Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 21:57:41 +0100 Subject: More cleanup. --- src/drumkit.cc | 53 +++++++++++++------------------------- src/drumkit.h | 43 +++++++++++++++---------------- src/drumkitparser.cc | 38 ++++++++++++++++------------ src/instrumentparser.cc | 62 ++++++++++++++++++++++++--------------------- src/instrumentparser.h | 2 +- src/midimapparser.cc | 3 ++- src/midimapparser.h | 2 -- src/path.cc | 24 ++++++++++-------- src/path.h | 8 +++--- src/sample.cc | 67 ++++++++++++++++--------------------------------- src/sample.h | 36 +++++++++----------------- src/saxparser.cc | 66 ++++++++++++++++++++++++++---------------------- src/saxparser.h | 19 ++++++++------ 13 files changed, 194 insertions(+), 229 deletions(-) diff --git a/src/drumkit.cc b/src/drumkit.cc index 9590930..b088cb6 100644 --- a/src/drumkit.cc +++ b/src/drumkit.cc @@ -28,69 +28,52 @@ DrumKit::DrumKit() { - magic = this; + magic = this; } DrumKit::~DrumKit() { - magic = NULL; - clear(); + magic = NULL; + clear(); } void DrumKit::clear() { - Instruments::iterator i = instruments.begin(); - while(i != instruments.end()) { - delete *i; - i++; - } - instruments.clear(); + for(auto& instrument : instruments) + { + delete instrument; + } - channels.clear(); + instruments.clear(); - _name = ""; - _description = ""; - _samplerate = 44100; + channels.clear(); + + _name = ""; + _description = ""; + _samplerate = 44100; } bool DrumKit::isValid() { - return this == magic; + return this == magic; } std::string DrumKit::file() { - return _file; + return _file; } std::string DrumKit::name() { - return _name; + return _name; } std::string DrumKit::description() { - return _description; + return _description; } size_t DrumKit::samplerate() { - return _samplerate; + 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 aa06969..2b1886a 100644 --- a/src/drumkit.h +++ b/src/drumkit.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_DRUMKIT_H__ -#define __DRUMGIZMO_DRUMKIT_H__ +#pragma once #include #include @@ -34,37 +33,35 @@ #include "instrument.h" #include "versionstr.h" -class DrumKitParser; -class DrumKit { - friend class DrumKitParser; +class DrumKit +{ + friend class DrumKitParser; public: - DrumKit(); - ~DrumKit(); + DrumKit(); + ~DrumKit(); - std::string file(); + std::string file(); - std::string name(); - std::string description(); - - Instruments instruments; - Channels channels; - - void clear(); + std::string name(); + std::string description(); - bool isValid(); + Instruments instruments; + Channels channels; - size_t samplerate(); + void clear(); + + bool isValid(); + + size_t samplerate(); private: void *magic{nullptr}; - std::string _file; + std::string _file; - std::string _name; - std::string _description; + std::string _name; + std::string _description; size_t _samplerate{0}; - VersionStr _version; + VersionStr _version; }; - -#endif/*__DRUMGIZMO_DRUMKIT_H__*/ diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index b935353..8785ef5 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -36,7 +36,7 @@ DrumKitParser::DrumKitParser(DrumKit& kit) : kit(kit) - , refs(REFSFILE) + , refs(REFSFILE) { } @@ -46,9 +46,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 @@ -59,7 +59,8 @@ int DrumKitParser::parseFile(const std::string& filename) path = getPath(edited_filename); auto result = SAXParser::parseFile(filename); - if (result == 0) { + if(result == 0) + { kit._file = edited_filename; } @@ -101,7 +102,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 +113,7 @@ void DrumKitParser::startTag(const std::string& name, const attr_t& attr) if(name == "channels") { - + } if(name == "channel") @@ -140,6 +141,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 +182,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(); + 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::iterator ic = parser.channellist.begin(); @@ -206,16 +210,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->name().c_str()); + c->name.c_str(), instrument->name().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/instrumentparser.cc b/src/instrumentparser.cc index bd356a9..c3aeb11 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::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 951b8ed..ce970b3 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/midimapparser.cc b/src/midimapparser.cc index 8d0e6ad..a2b7f51 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 35c64d5..55ed5e4 100644 --- a/src/midimapparser.h +++ b/src/midimapparser.h @@ -26,8 +26,6 @@ */ #pragma once -#include - #include "saxparser.h" #include "midimapper.h" diff --git a/src/path.cc b/src/path.cc index 080bd12..21a8f89 100644 --- a/src/path.cc +++ b/src/path.cc @@ -33,19 +33,21 @@ #include #include -std::string getPath(std::string file) +std::string getPath(const std::string& file) { - std::string p; -#ifndef __MINGW32__ - char *b = strdup(file.c_str()); - p = dirname(b); - free(b); + std::string path; + +#ifdef __MINGW32__ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + _splitpath(file.c_str(), drive, dir, NULL, NULL); + path = std::string(drive) + dir; #else - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - _splitpath(file.c_str(), drive, dir, NULL, NULL); - p = std::string(drive) + dir; + // POSIX + char* buffer = strdup(file.c_str()); + path = dirname(buffer); + free(buffer); #endif - return p; + return path; } diff --git a/src/path.h b/src/path.h index dc6f78d..68e56bf 100644 --- a/src/path.h +++ b/src/path.h @@ -24,11 +24,9 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_PATH_H__ -#define __DRUMGIZMO_PATH_H__ +#pragma once #include -std::string getPath(std::string file); - -#endif/*__DRUMGIZMO_PATH_H__*/ +//! \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 45dc415..10fa6b1 100644 --- a/src/sample.cc +++ b/src/sample.cc @@ -26,60 +26,37 @@ */ #include "sample.h" -#include -#include - -#include - -Sample::Sample(std::string name, float power) +Sample::Sample(const std::string& name, float power) + : name(name) + , power(power) { - this->name = name; - this->power = power; } Sample::~Sample() { } -void Sample::addAudioFile(Channel *c, AudioFile *a) +void Sample::addAudioFile(InstrumentChannel* instrument_channel, + AudioFile* audio_file) { - audiofiles[c] = a; + audiofiles[instrument_channel] = audio_file; } -AudioFile *Sample::getAudioFile(Channel *c) +AudioFile *Sample::getAudioFile(InstrumentChannel* instrument_channel) { - /* - if(audiofiles.find(c) == audiofiles.end()) return NULL; - return audiofiles[c]; - */ - - AudioFiles::iterator i = audiofiles.begin(); - while(i != audiofiles.end()) { - Channel *ch = i->first; - if(c->num == ch->num) return i->second; - i++; - } - - return NULL; + /* + if(audiofiles.find(c) == audiofiles.end()) return NULL; + return audiofiles[c]; + */ + + for(auto& audio_file : audiofiles) + { + InstrumentChannel *ch = audio_file.first; + if(instrument_channel->num == ch->num) + { + return audio_file.second; + } + } + + 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), NULL, "?"); - -TEST_END; - -#endif/*TEST_SAMPLE*/ diff --git a/src/sample.h b/src/sample.h index be0d121..034b9aa 100644 --- a/src/sample.h +++ b/src/sample.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_SAMPLE_H__ -#define __DRUMGIZMO_SAMPLE_H__ +#pragma once #include #include @@ -33,33 +32,22 @@ #include "channel.h" #include "audiofile.h" -typedef std::map< Channel*, AudioFile* > AudioFiles; +using AudioFiles = std::map; -class InstrumentParser; class Sample { - friend class InstrumentParser; - friend class PowerList; + friend class InstrumentParser; + friend class PowerList; public: - Sample(std::string name, float power); - ~Sample(); + 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; + std::string name; + float power; + AudioFiles audiofiles; }; - -/* - * - * - * - * - * - * - * - */ -#endif/*__DRUMGIZMO_SAMPLE_H__*/ diff --git a/src/saxparser.cc b/src/saxparser.cc index fcf7b2d..cd252c0 100644 --- a/src/saxparser.cc +++ b/src/saxparser.cc @@ -26,29 +26,30 @@ */ #include "saxparser.h" -#include -#include #include #include +#include + 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 b688e32..f4999af 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -31,7 +31,8 @@ #include #include -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::map; @@ -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); }; -- cgit v1.2.3 From 571e5a5feab478f6481db96343dfaf566bd2ab6d Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 22:16:20 +0100 Subject: Fix drumkit file by reference. --- src/drumkitparser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 8785ef5..f6dd553 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -57,7 +57,7 @@ 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) { -- cgit v1.2.3 From 569636bbd766710f5ac60a66c402acc70cdf77a8 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 22:38:44 +0100 Subject: Settings. --- drumgizmo/drumgizmoc.cc | 3 +- plugin/drumgizmo_plugin.cc | 2 +- plugin/drumgizmo_plugin.h | 2 + plugingui/dgwindow.cc | 31 ++++--- plugingui/dgwindow.h | 7 +- plugingui/plugingui.cc | 90 +++++++++++++++++++- plugingui/plugingui.h | 24 ++++-- src/drumgizmo.cc | 10 ++- src/drumgizmo.h | 8 +- src/drumkitloader.cc | 16 ++-- src/drumkitloader.h | 4 +- src/drumkitparser.cc | 7 +- src/drumkitparser.h | 3 +- src/instrument.cc | 205 ++++++++++++++++++++++----------------------- src/instrument.h | 50 ++++++----- src/settings.h | 94 +++++++++++++-------- 16 files changed, 354 insertions(+), 202 deletions(-) diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index fd3576c..49844d5 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -372,7 +372,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()); diff --git a/plugin/drumgizmo_plugin.cc b/plugin/drumgizmo_plugin.cc index 61c0b17..be11753 100644 --- a/plugin/drumgizmo_plugin.cc +++ b/plugin/drumgizmo_plugin.cc @@ -59,7 +59,7 @@ DrumGizmoPlugin::DrumGizmoPlugin() { init(); - drumgizmo = std::make_shared(&output, &input); + drumgizmo = std::make_shared(settings, &output, &input); resizeWindow(370, 330); drumgizmo->setFreeWheel(true); drumgizmo->setSamplerate(44100); diff --git a/plugin/drumgizmo_plugin.h b/plugin/drumgizmo_plugin.h index a0ce8b9..5d14955 100644 --- a/plugin/drumgizmo_plugin.h +++ b/plugin/drumgizmo_plugin.h @@ -154,6 +154,8 @@ private: Output output{*this}; const std::vector* output_samples{nullptr}; + Settings settings; + std::shared_ptr plugin_gui; std::shared_ptr drumgizmo; }; diff --git a/plugingui/dgwindow.cc b/plugingui/dgwindow.cc index 8d9e789..e8dbcfc 100644 --- a/plugingui/dgwindow.cc +++ b/plugingui/dgwindow.cc @@ -120,10 +120,11 @@ public: }; DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, - Config& config) + Config& config, Settings& settings) : Window(native_window) , messageHandler(messageHandler) , config(config) + , settings(settings) { int vlineSpacing = 16; @@ -233,11 +234,12 @@ void DGWindow::repaintEvent(RepaintEvent* repaintEvent) void DGWindow::attackValueChanged(float value) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, - value); + //ChangeSettingMessage *msg = + // new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, + // value); + //messageHandler.sendMessage(MSGRCV_ENGINE, msg); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.velocity_modifier_weight.store(value); #ifdef STANDALONE int i = value * 4; @@ -253,10 +255,12 @@ void DGWindow::attackValueChanged(float value) void DGWindow::falloffValueChanged(float value) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, - value); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + //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); @@ -265,10 +269,11 @@ void DGWindow::falloffValueChanged(float value) void DGWindow::velocityCheckClick(bool checked) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, - checked); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); +// ChangeSettingMessage *msg = +// new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, +// checked); +// messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.enable_velocity_modifier.store(checked); } void DGWindow::kitBrowseClick() diff --git a/plugingui/dgwindow.h b/plugingui/dgwindow.h index 07e23df..7adedc2 100644 --- a/plugingui/dgwindow.h +++ b/plugingui/dgwindow.h @@ -37,6 +37,8 @@ #include "filebrowser.h" #include "layout.h" +#include + class MessageHandler; namespace GUI { @@ -47,7 +49,8 @@ class File; class DGWindow : public Window { public: - DGWindow(void* native_window, MessageHandler& messageHandler, Config& config); + DGWindow(void* native_window, MessageHandler& messageHandler, Config& config, + Settings& settings); Header* header; @@ -85,6 +88,8 @@ private: Image back{":bg.png"}; Image logo{":logo.png"}; + + Settings& settings; }; } // GUI:: diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index 3375817..ff9ec58 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -31,6 +31,8 @@ #include "pluginconfig.h" #include "messagehandler.h" +#include + namespace GUI { PluginGUI::PluginGUI(void* native_window) @@ -116,7 +118,68 @@ bool PluginGUI::processEvents() } window->eventHandler()->processEvents(); - handleMessages(); + //handleMessages(); + + static bool foo = false; + static int t = 0; + if(t != time(nullptr)) + { + t = time(nullptr); + foo = !foo; + float v = settings.velocity_modifier_falloff.load(); + v += 0.1f; + settings.velocity_modifier_falloff.store(v); + } + + Painter p(*window); + + // Run through all settings one at a time propagate changes to the UI. + if(getter.enable_velocity_modifier.hasChanged()) + { + enable_velocity_modifier_notifier(getter.enable_velocity_modifier.getValue()); + } + + if(getter.velocity_modifier_falloff.hasChanged()) + { + velocity_modifier_falloff_notifier(getter.velocity_modifier_falloff.getValue()); + } + + if(getter.velocity_modifier_weight.hasChanged()) + { + velocity_modifier_weight_notifier(getter.velocity_modifier_weight.getValue()); + } + + if(getter.enable_velocity_randomiser.hasChanged()) + { + enable_velocity_randomiser_notifier(getter.enable_velocity_randomiser.getValue()); + } + + if(getter.velocity_randomiser_weight.hasChanged()) + { + velocity_randomiser_weight_notifier(getter.velocity_randomiser_weight.getValue()); + } + + if(getter.samplerate.hasChanged()) + { + samplerate_notifier(getter.samplerate.getValue()); + } + + if(getter.enable_resampling.hasChanged()) + { + enable_resampling_notifier(getter.enable_resampling.getValue()); + } + + if(getter.number_of_files.hasChanged() || + getter.number_of_files_loaded.hasChanged()) + { + drumkit_file_progress_notifier((float)getter.number_of_files_loaded.getValue() / + (float)getter.number_of_files.getValue()); + } + + //if(getter.current_file.hasChanged()) + //{ + // current_file_notifier(getter.current_file.getValue()); + //} if(closing) { @@ -135,7 +198,30 @@ void PluginGUI::init() config = new Config(); config->load(); - window = new DGWindow(native_window, msghandler, *config); + window = new DGWindow(native_window, msghandler, *config, settings); + + CONNECT(this, enable_velocity_modifier_notifier, + window->velocityCheck, &CheckBox::setChecked); + + CONNECT(this, velocity_modifier_falloff_notifier, + window->falloffKnob, &Knob::setValue); + CONNECT(this, velocity_modifier_weight_notifier, + window->attackKnob, &Knob::setValue); + + + //CONNECT(this, enable_velocity_randomiser_notifier, + // window->velocityCheck, &CheckBox::setChecked); + //CONNECT(this, velocity_randomiser_weight_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + //CONNECT(this, samplerate_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + //CONNECT(this, enable_resampling_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + CONNECT(this, drumkit_file_progress_notifier, + window->drumkitFileProgress, &ProgressBar::setProgress); auto eventHandler = window->eventHandler(); CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler); diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index af05478..d313f1b 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -31,9 +31,7 @@ #include "pluginconfig.h" - -#include "thread.h" -#include "semaphore.h" +#include #include "messagereceiver.h" #include "notifier.h" @@ -68,6 +66,21 @@ public: Notifier<> closeNotifier; + // Setting notifiers: + Notifier enable_velocity_modifier_notifier; + Notifier velocity_modifier_falloff_notifier; + Notifier velocity_modifier_weight_notifier; + + Notifier enable_velocity_randomiser_notifier; + Notifier velocity_randomiser_weight_notifier; + + Notifier samplerate_notifier; + + Notifier enable_resampling_notifier; + + Notifier drumkit_file_progress_notifier; + //Notifier current_file_notifier; + // Support old interface a little while longer.. void setWindowClosedCallback(void (*handler)(void*), void* ptr); @@ -80,11 +93,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; + SettingsGetter getter{settings}; }; } // GUI:: diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 2599f9f..6ca3dc8 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -46,18 +46,20 @@ #include "nolocale.h" -DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i) +DrumGizmo::DrumGizmo(Settings& settings, + AudioOutputEngine *o, AudioInputEngine *i) : MessageReceiver(MSGRCV_ENGINE) - , loader() + , loader(settings) , oe(o) , ie(i) , framesize(0) , freewheel(false) , events{} + , settings(settings) { is_stopping = false; audioCache.init(10000); // start thread - + events.reserve(1000); } @@ -81,7 +83,7 @@ bool DrumGizmo::loadkit(std::string file) // Delete all Channels, Instruments, Samples and AudioFiles. kit.clear(); - DrumKitParser parser(kit); + DrumKitParser parser(settings, kit); if(parser.parseFile(file)) { ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 55f4590..5d40917 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -50,6 +50,8 @@ #include "configfile.h" +#include "settings.h" + #define MAX_NUM_CHANNELS 64 #define REFSFILE "refs.conf" #define RESAMPLER_INPUT_BUFFER 64 @@ -58,7 +60,8 @@ class DrumGizmo : public MessageReceiver { public: - DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine); + DrumGizmo(Settings& settings, + AudioOutputEngine *outputengine, AudioInputEngine *inputengine); virtual ~DrumGizmo(); bool loadkit(std::string kitfile); @@ -106,6 +109,7 @@ protected: size_t framesize; bool freewheel; - + std::vector events; + Settings& settings; }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 82b177b..33ddd05 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -31,9 +31,10 @@ #include "drumkitparser.h" #include "drumgizmo.h" -DrumKitLoader::DrumKitLoader() +DrumKitLoader::DrumKitLoader(Settings& settings) : semaphore("drumkitloader") , framesize(0) + , settings(settings) { run(); run_semaphore.wait(); // Wait for the thread to actually start. @@ -187,11 +188,14 @@ void DrumKitLoader::thread_main() if(loaded % fraction == 0 || loaded == total_num_audiofiles) { - 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); + //LoadStatusMessage *ls = new LoadStatusMessage(); + //ls->number_of_files = total_num_audiofiles; + //ls->numer_of_files_loaded = loaded; + //ls->current_file = filename; + //msghandler.sendMessage(MSGRCV_UI, ls); + settings.number_of_files.store(total_num_audiofiles); + settings.number_of_files_loaded.store(loaded); + //settings.current_file.store(filename); } } diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 8819d71..320677a 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -34,6 +34,7 @@ #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 +46,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 @@ -82,4 +83,5 @@ protected: size_t fraction{1}; size_t loaded{0}; size_t framesize{0}; + Settings& settings; }; diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index f6dd553..f7737a0 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) +DrumKitParser::DrumKitParser(Settings& setting, DrumKit& k) + : kit(k) , refs(REFSFILE) + , settings(settings) { } @@ -182,7 +183,7 @@ void DrumKitParser::endTag(const std::string& name) { if(name == "instrument") { - Instrument* instrument = new Instrument(); + Instrument* instrument = new Instrument(settings); instrument->setGroup(instr_group); InstrumentParser parser(*instrument); diff --git a/src/drumkitparser.h b/src/drumkitparser.h index 98ea875..6b9a470 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 463f10d..a6015f7 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -34,147 +34,142 @@ #include "sample.h" #include "configuration.h" -Instrument::Instrument() +Instrument::Instrument(Settings& settings) + : settings(settings) { - DEBUG(instrument, "new %p\n", this); - mod = 1.0; - lastpos = 0; + DEBUG(instrument, "new %p\n", this); + mod = 1.0; + lastpos = 0; - magic = this; + magic = this; } Instrument::~Instrument() { - magic = NULL; - - DEBUG(instrument, "delete %p\n", this); - std::vector::iterator i = audiofiles.begin(); - while(i != audiofiles.end()) { - delete *i; - i++; - } + magic = NULL; + + DEBUG(instrument, "delete %p\n", this); + std::vector::iterator i = audiofiles.begin(); + while(i != audiofiles.end()) + { + delete *i; + i++; + } } bool Instrument::isValid() { - return this == magic; + return this == magic; } Sample *Instrument::sample(level_t level, size_t pos) { - Sample *sample = NULL; - - if(Conf::enable_velocity_modifier == false) { - mod = 1.0; - lastpos = 0; - } - - if(Conf::enable_velocity_randomiser) { - float r = (float)rand() / (float)RAND_MAX; // random number: [0;1] - r -= 0.5; // random number [-0.5;0.5] - r *= Conf::velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] - level += r; - if(level > 1.0) level = 1.0; - if(level < 0.0) level = 0.0; - } - - if(Conf::enable_velocity_modifier) { - mod += (pos - lastpos) / - (Conf::samplerate * Conf::velocity_modifier_falloff); - if(mod > 1.0) mod = 1.0; - } - - if(version >= VersionStr("2.0")) { - // Version 2.0 - sample = powerlist.get(level * mod); - } else { - // Version 1.0 - std::vector s = samples.get(level * mod); - if(s.size() == 0) return NULL; - size_t idx = rand()%(s.size()); - sample = s[idx]; - } - - if(Conf::enable_velocity_modifier) { - lastpos = pos; - mod *= Conf::velocity_modifier_weight; - } - - return sample; + 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(); + + if(enable_velocity_modifier == false) + { + mod = 1.0; + lastpos = 0; + } + + if(enable_velocity_randomiser) + { + float r = (float)rand() / (float)RAND_MAX; // random number: [0;1] + r -= 0.5; // random number [-0.5;0.5] + r *= velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] + level += r; + if(level > 1.0) + { + level = 1.0; + } + + if(level < 0.0) + { + level = 0.0; + } + } + + if(enable_velocity_modifier) + { + mod += (pos - lastpos) / + (samplerate * velocity_modifier_falloff); + if(mod > 1.0) + { + mod = 1.0; + } + } + + if(version >= VersionStr("2.0")) + { + // Version 2.0 + sample = powerlist.get(level * mod); + } + else + { + // Version 1.0 + std::vector s = samples.get(level * mod); + if(s.size() == 0) + { + return NULL; + } + + size_t idx = rand()%(s.size()); + sample = s[idx]; + } + + if(enable_velocity_modifier) + { + lastpos = pos; + mod *= velocity_modifier_weight; + } + + return sample; } void Instrument::addSample(level_t a, level_t b, Sample *s) { - samples.insert(a, b, s); + samples.insert(a, b, s); } void Instrument::finalise() { - if(version >= VersionStr("2.0")) { - std::vector::iterator s = samplelist.begin(); - while(s != samplelist.end()) { - powerlist.add(*s); - s++; - } - - powerlist.finalise(); - } + if(version >= VersionStr("2.0")) + { + std::vector::iterator s = samplelist.begin(); + while(s != samplelist.end()) + { + powerlist.add(*s); + s++; + } + + powerlist.finalise(); + } } std::string Instrument::name() { - return _name; + return _name; } std::string Instrument::description() { - return _description; + return _description; } std::string Instrument::group() { - return _group; + return _group; } void Instrument::setGroup(std::string g) { - _group = 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 07aba9c..2a70a95 100644 --- a/src/instrument.h +++ b/src/instrument.h @@ -36,46 +36,50 @@ #include "sample.h" #include "versionstr.h" +#include "settings.h" + class InstrumentParser; class Instrument { - friend class InstrumentParser; + friend class InstrumentParser; public: - Instrument(); - ~Instrument(); + Instrument(Settings& settings); + ~Instrument(); - Sample *sample(level_t level, size_t pos); + Sample *sample(level_t level, size_t pos); - std::string name(); - std::string description(); - std::string group(); + std::string name(); + std::string description(); + std::string group(); - void setGroup(std::string group); + void setGroup(std::string group); - // std::map channelmap; + // std::map channelmap; - std::vector audiofiles; + std::vector audiofiles; - bool isValid(); + bool isValid(); private: - void *magic; + void *magic; + + std::string _group; + std::string _name; + std::string _description; - std::string _group; - std::string _name; - std::string _description; + VersionStr version; - VersionStr version; + RangeMap samples; + PowerList powerlist; - RangeMap samples; - PowerList powerlist; + void addSample(level_t a, level_t b, Sample *s); + void finalise(); ///< Signal instrument that no more samples will be added. - void addSample(level_t a, level_t b, Sample *s); - void finalise(); ///< Signal instrument that no more samples will be added. + std::vector samplelist; - std::vector samplelist; + size_t lastpos; + float mod; - size_t lastpos; - float mod; + Settings& settings; }; //typedef std::map< std::string, Instrument > Instruments; diff --git a/src/settings.h b/src/settings.h index 6396fc4..7cf5282 100644 --- a/src/settings.h +++ b/src/settings.h @@ -27,14 +27,40 @@ #pragma once #include +#include #include +class MyString { +public: + std::string value; +}; + +//! Engine settings +struct Settings +{ + std::atomic enable_velocity_modifier; + std::atomic velocity_modifier_falloff; + std::atomic velocity_modifier_weight; + + std::atomic enable_velocity_randomiser; + std::atomic velocity_randomiser_weight; + + std::atomic samplerate; + + std::atomic enable_resampling; + + std::atomic number_of_files; + std::atomic number_of_files_loaded; + //std::atomic current_file; + +}; + +//! Getter utility class. template class SettingRef { public: SettingRef(std::atomic& value) - : value{value} - , cache{} + : value(value) { // string isn't lock free either assert((std::is_same::value || value.is_lock_free())); @@ -57,20 +83,7 @@ private: std::atomic cache; }; -struct Settings -{ - std::atomic enable_velocity_modifier; - std::atomic velocity_modifier_falloff; - std::atomic velocity_modifier_weight; - - std::atomic enable_velocity_randomiser; - std::atomic velocity_randomiser_weight; - - std::atomic samplerate; - - std::atomic enable_resampling; -}; - +//! Combined getter class. struct SettingsGetter { SettingRef enable_velocity_modifier; @@ -80,10 +93,14 @@ struct SettingsGetter SettingRef enable_velocity_randomiser; SettingRef velocity_randomiser_weight; - SettingRef samplerate; + SettingRef samplerate; SettingRef enable_resampling; + SettingRef number_of_files; + SettingRef number_of_files_loaded; + //SettingRef current_file; + SettingsGetter(Settings& settings) : enable_velocity_modifier{settings.enable_velocity_modifier} , velocity_modifier_falloff{settings.velocity_modifier_falloff} @@ -92,6 +109,9 @@ struct SettingsGetter , 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} { } }; @@ -99,29 +119,35 @@ struct SettingsGetter // lovely reminder: NO, GLOCKE. NOOOO!! /* enum class IntParams { - Foo = 0 + Foo = 0 }; -struct Settings { - std::array, 5> ints; +struct Settings +{ + std::array, 5> ints; - Settings() - : ints{} { - //get(IntParams::Foo).store(3); - } + Settings() + : ints{} + { + //get(IntParams::Foo).store(3); + } - std::atomic& get(IntParams param) { - return ints[(size_t)param]; - } + std::atomic& get(IntParams param) + { + return ints[(size_t)param]; + } }; -struct SettingsGetter { - std::vector> ints; +struct SettingsGetter +{ + std::vector> 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); + } + } }; */ -- cgit v1.2.3 From fcdef40659077e56256cff4f3bd8b9d9520ad087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Wed, 23 Mar 2016 22:40:27 +0100 Subject: atomic workaround --- src/atomic.h | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ test/Makefile.am | 7 +++- test/atomictest.cc | 77 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 src/atomic.h create mode 100644 test/atomictest.cc diff --git a/src/atomic.h b/src/atomic.h new file mode 100644 index 0000000..11c87fc --- /dev/null +++ b/src/atomic.h @@ -0,0 +1,105 @@ +/* -*- 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 +#include +#include + +template +class Atomic; + +// use std::atomic if possible +template +class Atomic::value>::type> + : public std::atomic { +}; + +// else work around it using a mutex +template +class Atomic::value>::type> { + public: + using self_type = Atomic::value>::type>; + + Atomic() + : data{} + , mutex{} { + } + + Atomic(T data) + : data{std::move(data)} + , mutex{} { + } + + Atomic(self_type const & other) + : data{} + , mutex{} { + std::lock_guard lock{other.mutex}; + data = other.data; + } + + Atomic(self_type&& other) + : data{} + , mutex{} { + std::lock_guard lock{other.mutex}; + std::swap(data, other.data); + } + + T operator=(T data) { + std::lock_guard 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 lock{mutex}; + this->data = std::move(data); + } + + T load() const { + std::lock_guard lock{mutex}; + return data; + } + + T exchange(T data){ + std::lock_guard lock{mutex}; + std::swap(data, this->data); + return data; + } + + private: + T data; + mutable std::mutex mutex; +}; diff --git a/test/Makefile.am b/test/Makefile.am index 6e56043..4209991 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 + memchecker atomictest check_PROGRAMS = $(TESTS) @@ -128,5 +128,10 @@ memchecker_SOURCES = \ test.cc \ memcheckertest.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 + EXTRA_DIST = \ lv2_test_host.h diff --git a/test/atomictest.cc b/test/atomictest.cc new file mode 100644 index 0000000..d4cacf0 --- /dev/null +++ b/test/atomictest.cc @@ -0,0 +1,77 @@ +/* -*- 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 + +#include + +class AtomicTest + : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(AtomicTest); + CPPUNIT_TEST(atomicIntUsesStandardImpl); + CPPUNIT_TEST(atomicFloatUsesStandardImpl); + CPPUNIT_TEST(atomicBoolUsesStandardImpl); + CPPUNIT_TEST(atomicStringCanBeUsed); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() {} + void tearDown() {} + + void atomicIntUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicFloatUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicBoolUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicDoubleUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicStringCanBeUsed() { + // note: if it couldn't be used, the compiler would complain + Atomic tmp; + } + + // todo: further testing + + private: + template + bool isUsingStandardImpl() { + return std::is_base_of, Atomic>::value; + } +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AtomicTest); + -- cgit v1.2.3 From a06ac0793379358eb8095a859b617c85f166c15e Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 23:02:09 +0100 Subject: Fix tests. --- test/engine.cc | 3 ++- test/memcheckertest.cc | 13 +++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/test/engine.cc b/test/engine.cc index d27569c..7bdb1f6 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 d43a2e7..df5ca99 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,8 +71,8 @@ public: void small_drumkit() { // load the small kit - DrumKitParser parser(small_kit_path, kit); - CPPUNIT_ASSERT(!parser.parse()); + DrumKitParser parser(settings, kit); + CPPUNIT_ASSERT(!parser.parseFile(small_kit_path)); // check if the memchecker thinks it fits into memory CPPUNIT_ASSERT(enoughFreeMemory(kit)); @@ -80,8 +81,8 @@ public: void huge_drumkit() { // load the huge kit - DrumKitParser parser(huge_kit_path, kit); - CPPUNIT_ASSERT(!parser.parse()); + DrumKitParser parser(settings, kit); + CPPUNIT_ASSERT(!parser.parseFile(huge_kit_path)); // check if the memchecker thinks it doesn't fit into memory CPPUNIT_ASSERT(!enoughFreeMemory(kit)); @@ -94,8 +95,8 @@ public: CPPUNIT_ASSERT_EQUAL(bytes_per_channel, calcBytesPerChannel(audiofile)); // load the huge kit - DrumKitParser parser(huge_kit_path, kit); - CPPUNIT_ASSERT(!parser.parse()); + DrumKitParser parser(settings, kit); + CPPUNIT_ASSERT(!parser.parseFile(huge_kit_path)); // check if the protected method of the memchecker reports the correct size uint64_t needed_memory = 71478290000; -- cgit v1.2.3 From 7e8e8b372ebce367ee6393a7666916bf813b8fdf Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 23:02:35 +0100 Subject: Use new Atomic class. --- src/atomic.h | 6 +++--- src/settings.h | 35 ++++++++++++++++------------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/atomic.h b/src/atomic.h index 11c87fc..f800f68 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -35,15 +35,15 @@ class Atomic; // use std::atomic if possible template -class Atomic::value>::type> +class Atomic::value>::type> : public std::atomic { }; // else work around it using a mutex template -class Atomic::value>::type> { +class Atomic::value>::type> { public: - using self_type = Atomic::value>::type>; + using self_type = Atomic::value>::type>; Atomic() : data{} diff --git a/src/settings.h b/src/settings.h index 7cf5282..d899f0f 100644 --- a/src/settings.h +++ b/src/settings.h @@ -30,28 +30,25 @@ #include #include -class MyString { -public: - std::string value; -}; +#include "atomic.h" //! Engine settings struct Settings { - std::atomic enable_velocity_modifier; - std::atomic velocity_modifier_falloff; - std::atomic velocity_modifier_weight; + Atomic enable_velocity_modifier; + Atomic velocity_modifier_falloff; + Atomic velocity_modifier_weight; - std::atomic enable_velocity_randomiser; - std::atomic velocity_randomiser_weight; + Atomic enable_velocity_randomiser; + Atomic velocity_randomiser_weight; - std::atomic samplerate; + Atomic samplerate; - std::atomic enable_resampling; + Atomic enable_resampling; - std::atomic number_of_files; - std::atomic number_of_files_loaded; - //std::atomic current_file; + Atomic number_of_files; + Atomic number_of_files_loaded; + Atomic current_file; }; @@ -59,7 +56,7 @@ struct Settings template class SettingRef { public: - SettingRef(std::atomic& value) + SettingRef(Atomic& value) : value(value) { // string isn't lock free either @@ -79,8 +76,8 @@ public: } private: - std::atomic& value; - std::atomic cache; + Atomic& value; + Atomic cache; }; //! Combined getter class. @@ -99,7 +96,7 @@ struct SettingsGetter SettingRef number_of_files; SettingRef number_of_files_loaded; - //SettingRef current_file; + SettingRef current_file; SettingsGetter(Settings& settings) : enable_velocity_modifier{settings.enable_velocity_modifier} @@ -111,7 +108,7 @@ struct SettingsGetter , 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} + , current_file{settings.current_file} { } }; -- cgit v1.2.3 From 31ac3fd56ce77cfb2e9caddd0bdac0614971d98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Tue, 22 Mar 2016 00:40:15 +0100 Subject: Parser refactoring. * Use new style * Update to C++11 * Use more std::string than char* --- src/configparser.cc | 45 +++--- src/configparser.h | 24 ++- src/drumkitparser.cc | 409 ++++++++++++++++++++++-------------------------- src/drumkitparser.h | 39 +++-- src/instrumentparser.cc | 399 ++++++++++++++++++++++------------------------ src/instrumentparser.h | 32 ++-- src/midimapparser.cc | 33 ++-- src/midimapparser.h | 22 ++- src/saxparser.cc | 150 +++++++++--------- src/saxparser.h | 37 +++-- 10 files changed, 569 insertions(+), 621 deletions(-) diff --git a/src/configparser.cc b/src/configparser.cc index ac8b876..1ada879 100644 --- a/src/configparser.cc +++ b/src/configparser.cc @@ -32,39 +32,40 @@ ConfigParser::ConfigParser() { - str = NULL; + str = nullptr; } -void ConfigParser::characterData(std::string &data) +void ConfigParser::characterData(const std::string& data) { - if(str) str->append(data); + if(str) + { + str->append(data); + } } -void ConfigParser::startTag(std::string name, attr_t attr) +void ConfigParser::startTag(const std::string& name, attr_t& attr) { - if(name == "value" && attr.find("name") != attr.end()) { - values[attr["name"]] = ""; - str = &values[attr["name"]]; - } + if(name == "value" && attr.find("name") != attr.end()) + { + values[attr["name"]] = ""; + str = &values[attr["name"]]; + } } -void ConfigParser::endTag(std::string name) +void ConfigParser::endTag(const std::string& name) { - if(name == "value") str = NULL; + if(name == "value") + { + str = nullptr; + } } -std::string ConfigParser::value(std::string name, std::string def) +std::string ConfigParser::value(const std::string& name, const std::string& def) { - if(values.find(name) == values.end()) return def; - return values[name]; -} + if(values.find(name) == values.end()) + { + return def; + } -void ConfigParser::parseError(char *buf, size_t len, std::string error, - int lineno) -{ - std::string buffer; - buffer.append(buf, len); - ERR(configparser, "sax parser error '%s' at line %d. " - "Buffer: [%d bytes]<%s>\n", - error.c_str(), lineno, (int)len, buffer.c_str()); + return values[name]; } diff --git a/src/configparser.h b/src/configparser.h index b5f4d74..1e8aa56 100644 --- a/src/configparser.h +++ b/src/configparser.h @@ -24,26 +24,24 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_CONFIGPARSER_H__ -#define __DRUMGIZMO_CONFIGPARSER_H__ +#pragma once #include #include "saxparser.h" -class ConfigParser : public SAXParser { +class ConfigParser : + public SAXParser +{ public: - ConfigParser(); + ConfigParser(); - void characterData(std::string &data); - void startTag(std::string name, attr_t attr); - void endTag(std::string name); - std::string value(std::string name, std::string def = ""); - void parseError(char *buf, size_t len, std::string error, int lineno); + void characterData(const std::string& data) override; + void startTag(const std::string& name, attr_t& attr) override; + void endTag(const std::string& name) override; + std::string value(const std::string& name, const std::string& def = ""); private: - std::map values; - std::string *str; + std::map values; + std::string* str; }; - -#endif/*__DRUMGIZMO_CONFIGPARSER_H__*/ diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index f0fddf8..8746ae0 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -34,244 +34,213 @@ #include "path.h" #include "drumgizmo.h" -DrumKitParser::DrumKitParser(const std::string &file, DrumKit &k) - : kit(k) - , refs(REFSFILE) +DrumKitParser::DrumKitParser(const std::string& file, DrumKit& k) + : kit(k) + , refs(REFSFILE) { - std::string kitfile = file; + std::string kitfile = file; - if(refs.load()) { - if(file.size() > 1 && file[0] == '@') { - kitfile = refs.getValue(file.substr(1)); - } - } else { - ERR(drumkitparser, "Error reading refs.conf"); - } + if(refs.load()) + { + if(file.size() > 1 && file[0] == '@') + { + kitfile = refs.getValue(file.substr(1)); + } + } + else + { + ERR(drumkitparser, "Error reading refs.conf"); + } - // instr = NULL; - path = getPath(kitfile); + // instr = NULL; + path = getPath(kitfile); - fd = fopen(kitfile.c_str(), "r"); + fd = fopen(kitfile.c_str(), "r"); - // DEBUG(kitparser, "Parsing drumkit in %s\n", kitfile.c_str()); + // DEBUG(kitparser, "Parsing drumkit in %s\n", kitfile.c_str()); - if(!fd) return; + if(!fd) + { + return; + } - kit._file = file; + kit._file = file; } DrumKitParser::~DrumKitParser() { - if(fd) fclose(fd); + if(fd) + { + fclose(fd); + } + } -void DrumKitParser::startTag(std::string name, - std::map attr) +void DrumKitParser::startTag(const std::string& name, + attr_t& attr) { - if(name == "drumkit") { - if(attr.find("name") != attr.end()) - kit._name = attr["name"]; - - if(attr.find("samplerate") != attr.end()) { - kit._samplerate = atoi(attr["samplerate"].c_str()); - } else { - // If 'samplerate' attribute is missing, assume 44k1Hz - // TODO: Ask instrument what samplerate is in the audiofiles... - kit._samplerate = 44100; - } - - if(attr.find("description") != attr.end()) - kit._description = attr["description"]; - - if(attr.find("version") != attr.end()) { - try { - kit._version = VersionStr(attr["version"]); - } catch(const char *err) { - ERR(kitparser, "Error parsing version number: %s, using 1.0\n", err); - kit._version = VersionStr(1,0,0); - } - } else { - WARN(kitparser, "Missing version number, assuming 1.0\n"); - kit._version = VersionStr(1,0,0); - } - } - - if(name == "channels") {} - - if(name == "channel") { - if(attr.find("name") == attr.end()) { - DEBUG(kitparser, "Missing channel name.\n"); - return; - } - Channel c(attr["name"]); - c.num = kit.channels.size(); - kit.channels.push_back(c); - } - - if(name == "instruments") { - } - - if(name == "instrument") { - if(attr.find("name") == attr.end()) { - DEBUG(kitparser, "Missing name in instrument tag.\n"); - return; - } - if(attr.find("file") == attr.end()) { - DEBUG(kitparser, "Missing file in instrument tag.\n"); - return; - } - - instr_name = attr["name"]; - instr_file = attr["file"]; - if(attr.find("group") != attr.end()) instr_group = attr["group"]; - else instr_group = ""; - } - - if(name == "channelmap") { - if(attr.find("in") == attr.end()) { - DEBUG(kitparser, "Missing 'in' in channelmap tag.\n"); - return; - } - - if(attr.find("out") == attr.end()) { - DEBUG(kitparser, "Missing 'out' in channelmap tag.\n"); - return; - } - - channelmap[attr["in"]] = attr["out"]; - } + if(name == "drumkit") + { + if(attr.find("name") != attr.end()) + { + kit._name = attr["name"]; + } + + if(attr.find("samplerate") != attr.end()) + { + kit._samplerate = std::stoi(attr["samplerate"]); + } + else + { + // If 'samplerate' attribute is missing, assume 44k1Hz + // TODO: Ask instrument what samplerate is in the audiofiles... + kit._samplerate = 44100; + } + + if(attr.find("description") != attr.end()) + { + kit._description = attr["description"]; + } + + if(attr.find("version") != attr.end()) + { + try + { + kit._version = VersionStr(attr["version"]); + } + catch(const char *err) + { + ERR(kitparser, "Error parsing version number: %s, using 1.0\n", err); + kit._version = VersionStr(1,0,0); + } + } + else + { + WARN(kitparser, "Missing version number, assuming 1.0\n"); + kit._version = VersionStr(1,0,0); + } + } + + if(name == "channels") + { + + } + + if(name == "channel") + { + if(attr.find("name") == attr.end()) + { + ERR(kitparser, "Missing channel name.\n"); + return; + } + + Channel c(attr["name"]); + c.num = kit.channels.size(); + kit.channels.push_back(c); + } + + if(name == "instruments") + { + + } + + if(name == "instrument") + { + if(attr.find("name") == attr.end()) + { + ERR(kitparser, "Missing name in instrument tag.\n"); + return; + } + if(attr.find("file") == attr.end()) + { + ERR(kitparser, "Missing file in instrument tag.\n"); + return; + } + + instr_name = attr["name"]; + instr_file = attr["file"]; + if(attr.find("group") != attr.end()) + { + instr_group = attr["group"]; + } + else + { + instr_group = ""; + } + } + + if(name == "channelmap") + { + if(attr.find("in") == attr.end()) + { + ERR(kitparser, "Missing 'in' in channelmap tag.\n"); + return; + } + + if(attr.find("out") == attr.end()) + { + ERR(kitparser, "Missing 'out' in channelmap tag.\n"); + return; + } + + channelmap[attr["in"]] = attr["out"]; + } } -void DrumKitParser::endTag(std::string name) +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(path + "/" + instr_file, *i); - parser.parse(); - kit.instruments.push_back(i); - - // Assign kit channel numbers to instruments channels. - std::vector::iterator ic = parser.channellist.begin(); - while(ic != parser.channellist.end()) { - InstrumentChannel *c = *ic; - - std::string cname = c->name; - if(channelmap.find(cname) != channelmap.end()) cname = channelmap[cname]; - - for(size_t cnt = 0; cnt < kit.channels.size(); cnt++) { - if(kit.channels[cnt].name == cname) c->num = kit.channels[cnt].num; - } - if(c->num == NO_CHANNEL) { - DEBUG(kitparser, "Missing channel '%s' in instrument '%s'\n", - c->name.c_str(), i->name().c_str()); - } else { - /* - DEBUG(kitparser, "Assigned channel '%s' to number %d in instrument '%s'\n", - c->name.c_str(), c->num, i.name().c_str()); - */ - } - ic++; - } - - channelmap.clear(); - - } + if(name == "instrument") + { + Instrument* i = new Instrument(); + i->setGroup(instr_group); + // Instrument &i = kit.instruments[kit.instruments.size() - 1]; + InstrumentParser parser(path + "/" + instr_file, *i); + parser.parse(); + kit.instruments.push_back(i); + + // Assign kit channel numbers to instruments channels. + std::vector::iterator ic = parser.channellist.begin(); + while(ic != parser.channellist.end()) + { + InstrumentChannel* c = *ic; + + std::string cname = c->name; + if(channelmap.find(cname) != channelmap.end()) + { + cname = channelmap[cname]; + } + + for(std::size_t cnt = 0; cnt < kit.channels.size(); cnt++) + { + if(kit.channels[cnt].name == cname) + { + 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->name().c_str()); + } + else { + /* + DEBUG(kitparser, "Assigned channel '%s' to number %d in instrument '%s'\n", + c->name.c_str(), c->num, i.name().c_str()); + */ + } + ic++; + } + + channelmap.clear(); + } } -int DrumKitParser::readData(char *data, size_t size) +int DrumKitParser::readData(std::string& data, std::size_t size) { - if(!fd) return -1; - return fread(data, 1, size, fd); -} + if(!fd) + { + return -1; + } -#ifdef TEST_DRUMKITPARSER -//deps: drumkit.cc saxparser.cc instrument.cc sample.cc audiofile.cc channel.cc -//cflags: $(EXPAT_CFLAGS) $(SNDFILE_CFLAGS) -//libs: $(EXPAT_LIBS) $(SNDFILE_LIBS) -#include "test.h" - -const char xml[] = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" - ; - -#define FNAME "/tmp/drumkittest.xml" - -TEST_BEGIN; - -FILE *fp = fopen(FNAME, "w"); -fprintf(fp, "%s", xml); -fclose(fp); - -DrumKit kit; -DrumKitParser p(FNAME, kit); -TEST_EQUAL_INT(p.parse(), 0, "Parsing went well?"); - -TEST_EQUAL_STR(kit.name(), "The Aasimonster", "Compare name"); -TEST_EQUAL_INT(kit.instruments.size(), 2, "How many instruments?"); - -unlink(FNAME); - -TEST_END; - -#endif/*TEST_DRUMKITPARSER*/ + return fread((char*)data.c_str(), 1, size, fd); +} diff --git a/src/drumkitparser.h b/src/drumkitparser.h index b59e81b..91456d4 100644 --- a/src/drumkitparser.h +++ b/src/drumkitparser.h @@ -24,37 +24,34 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_DRUMKITPARSER_H__ -#define __DRUMGIZMO_DRUMKITPARSER_H__ +#pragma once #include "saxparser.h" #include "drumkit.h" #include "configfile.h" -class DrumKitParser : public SAXParser { +class DrumKitParser + : public SAXParser +{ public: - DrumKitParser(const std::string &kitfile, DrumKit &kit); - ~DrumKitParser(); - - void startTag(std::string name, - std::map< std::string, std::string> attributes); - void endTag(std::string name); + DrumKitParser(const std::string& kitfile, DrumKit& kit); + ~DrumKitParser(); protected: - int readData(char *data, size_t size); + void startTag(const std::string& name, attr_t& attributes) override; + void endTag(const std::string& name) override; + + int readData(std::string& data, std::size_t size) override; private: - FILE *fd; - DrumKit &kit; - // Instrument *instr; - std::string path; + FILE* fd; + DrumKit& kit; + std::string path; - std::map channelmap; - std::string instr_file; - std::string instr_name; - std::string instr_group; + std::map channelmap; + std::string instr_file; + std::string instr_name; + std::string instr_group; - ConfigFile refs; + ConfigFile refs; }; - -#endif/*__DRUMGIZMO_DRUMKITPARSER_H__*/ diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index b097c8c..3ebc585 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -35,228 +35,207 @@ #include "nolocale.h" -InstrumentParser::InstrumentParser(const std::string &file, Instrument &i) - : instrument(i) +InstrumentParser::InstrumentParser(const std::string& file, Instrument& i) + : instrument(i) { - s = NULL; - // DEBUG(instrparser,"Parsing instrument in %s\n", file.c_str()); - path = getPath(file); - fd = fopen(file.c_str(), "r"); - if(!fd) return; + // DEBUG(instrparser,"Parsing instrument in %s\n", file.c_str()); + path = getPath(file); + fd = fopen(file.c_str(), "r"); + + if(!fd) + { + ERR(instrparser, "The following instrument file could not be opened: %s\n", file.c_str()); + return; + } } InstrumentParser::~InstrumentParser() { - if(fd) fclose(fd); + if(fd) + { + fclose(fd); + } } -void InstrumentParser::startTag(std::string name, - std::map attr) +void InstrumentParser::startTag(const std::string& name, attr_t& attr) { - if(name == "instrument") { - if(attr.find("name") != attr.end()) - instrument._name = attr["name"]; - - if(attr.find("description") != attr.end()) - instrument._description = attr["description"]; - - if(attr.find("version") != attr.end()) { - try { - instrument.version = VersionStr(attr["version"]); - } catch(const char *err) { - ERR(instrparser, "Error parsing version number: %s, using 1.0\n", err); - instrument.version = VersionStr(1,0,0); - } - } else { - WARN(instrparser, "Missing version number, assuming 1.0\n"); - instrument.version = VersionStr(1,0,0); - } - } - - if(name == "samples") { - } - - if(name == "sample") { - if(attr.find("name") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'name'.\n"); - return; - } - - float power; - if(attr.find("power") == attr.end()) { - power = -1; - } else { - power = atof_nol(attr["power"].c_str()); - DEBUG(instrparser, "Instrument power set to %f\n", power); - } - - // TODO get rid of new or delete it properly - s = new Sample(attr["name"], power); - } - - if(name == "audiofile") { - if(s == NULL) { - DEBUG(instrparser,"Missing Sample!\n"); - return; - } - - if(attr.find("file") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'file'.\n"); - return; - } - - if(attr.find("channel") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'channel'.\n"); - return; - } - int filechannel = 1; // default, override with optional attribute - if(attr.find("filechannel") != attr.end()) { - filechannel = atoi(attr["filechannel"].c_str()); - if(filechannel < 1) { - DEBUG(instrparser,"Invalid value for attribute 'filechannel'.\n"); - filechannel = 1; - } - } - 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["file"], filechannel); - InstrumentChannel *ch = new InstrumentChannel(attr["channel"]); - channellist.push_back(ch); - s->addAudioFile(ch, af); - instrument.audiofiles.push_back(af); - } - - if(name == "velocities") { - } - - if(name == "velocity") { - if(attr.find("lower") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'lower'.\n"); - return; - } - - if(attr.find("upper") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'upper'.\n"); - return; - } - - lower = atof_nol(attr["lower"].c_str()); - upper = atof_nol(attr["upper"].c_str()); - } - - if(name == "sampleref") { - if(attr.find("name") == attr.end()) { - DEBUG(instrparser,"Missing required attribute 'name'.\n"); - return; - } - - Sample *sample = NULL; - std::vector::iterator i = instrument.samplelist.begin(); - while(i != instrument.samplelist.end()) { - if((*i)->name == attr["name"]) { - sample = *i; - break; - } - i++; - } - - if(sample == NULL) { - DEBUG(instrparser,"Samplref pointed at non-existing sample.\n"); - return; - } - - if(instrument.version == VersionStr("1.0")) { - // Old "velocity group" algorithm needs this - instrument.addSample(lower, upper, sample); - } - } + if(name == "instrument") + { + if(attr.find("name") != attr.end()) + { + instrument._name = attr["name"]; + } + + if(attr.find("description") != attr.end()) + { + instrument._description = attr["description"]; + } + + if(attr.find("version") != attr.end()) + { + try { + instrument.version = VersionStr(attr["version"]); + } + catch(const char *err) + { + ERR(instrparser, "Error parsing version number: %s, using 1.0\n", err); + instrument.version = VersionStr(1,0,0); + } + } + else + { + WARN(instrparser, "Missing version number, assuming 1.0\n"); + instrument.version = VersionStr(1,0,0); + } + } + + if(name == "samples") + { + + } + + if(name == "sample") + { + if(attr.find("name") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'name'.\n"); + return; + } + + float power; + if(attr.find("power") == attr.end()) + { + power = -1; + } + else + { + power = atof_nol(attr["power"].c_str()); + DEBUG(instrparser, "Instrument power set to %f\n", power); + } + + // TODO get rid of new or delete it properly + s = new Sample(attr["name"], power); + } + + if(name == "audiofile") + { + if(s == nullptr) + { + ERR(instrparser,"Missing Sample!\n"); + return; + } + + if(attr.find("file") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'file'.\n"); + return; + } + + if(attr.find("channel") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'channel'.\n"); + return; + } + + int filechannel = 1; // default, override with optional attribute + if(attr.find("filechannel") != attr.end()) + { + filechannel = std::stoi(attr["filechannel"]); + if(filechannel < 1) + { + ERR(instrparser,"Invalid value for attribute 'filechannel'.\n"); + filechannel = 1; + } + } + + 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["file"], filechannel); + InstrumentChannel *ch = new InstrumentChannel(attr["channel"]); + channellist.push_back(ch); + s->addAudioFile(ch, af); + instrument.audiofiles.push_back(af); + } + + if(name == "velocities") + { + + } + + if(name == "velocity") + { + if(attr.find("lower") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'lower'.\n"); + return; + } + + if(attr.find("upper") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'upper'.\n"); + return; + } + + lower = atof_nol(attr["lower"].c_str()); + upper = atof_nol(attr["upper"].c_str()); + } + + if(name == "sampleref") + { + if(attr.find("name") == attr.end()) + { + ERR(instrparser,"Missing required attribute 'name'.\n"); + return; + } + + Sample* sample = nullptr; + std::vector::iterator i = instrument.samplelist.begin(); + while(i != instrument.samplelist.end()) + { + if((*i)->name == attr["name"]) + { + sample = *i; + break; + } + i++; + } + + if(sample == nullptr) + { + ERR(instrparser,"Samplref pointed at non-existing sample.\n"); + return; + } + + if(instrument.version == VersionStr("1.0")) + { + // Old "velocity group" algorithm needs this + instrument.addSample(lower, upper, sample); + } + } } -void InstrumentParser::endTag(std::string name) +void InstrumentParser::endTag(const std::string& name) { - if(name == "sample") { - if(s == NULL) { - DEBUG(instrparser,"Missing Sample.\n"); - return; - } - - instrument.samplelist.push_back(s); - - s = NULL; - } - - if(name == "instrument") { - instrument.finalise(); - } + if(name == "sample") + { + if(s == nullptr) + { + ERR(instrparser,"Missing Sample.\n"); + return; + } + + instrument.samplelist.push_back(s); + + s = nullptr; + } + + if(name == "instrument") { + instrument.finalise(); + } } -int InstrumentParser::readData(char *data, size_t size) +int InstrumentParser::readData(std::string& data, std::size_t size) { - if(!fd) return -1; - return fread(data, 1, size, fd); + if(!fd) return -1; + return fread((char*)data.c_str(), 1, size, fd); } - - -#ifdef TEST_INSTRUMENTPARSER -//deps: saxparser.cc instrument.cc sample.cc audiofile.cc channel.cc -//cflags: $(EXPAT_CFLAGS) $(SNDFILE_CFLAGS) -//libs: $(EXPAT_LIBS) $(SNDFILE_LIBS) -#include "test.h" - -const char xml[] = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" - ; - -#define FNAME "/tmp/instrtest.xml" - -TEST_BEGIN; - -FILE *fp = fopen(FNAME, "w"); -fprintf(fp, "%s", xml); -fclose(fp); - -Instrument instr; -InstrumentParser p(FNAME, instr); -TEST_EQUAL_INT(p.parse(), 0, "Parsing went well?"); - -TEST_EQUAL_STR(instr.name(), "kick-r", "Compare name"); - -unlink(FNAME); - -TEST_END; - -#endif/*TEST_INSTRUMENTPARSER*/ diff --git a/src/instrumentparser.h b/src/instrumentparser.h index e08b54c..3fee916 100644 --- a/src/instrumentparser.h +++ b/src/instrumentparser.h @@ -24,37 +24,35 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_INSTRUMENTPARSER_H__ -#define __DRUMGIZMO_INSTRUMENTPARSER_H__ +#pragma once #include "saxparser.h" #include "instrument.h" #include -class InstrumentParser : public SAXParser { +class InstrumentParser + : public SAXParser +{ public: - InstrumentParser(const std::string &instrfile, Instrument &instrument); - ~InstrumentParser(); + InstrumentParser(const std::string& instrfile, Instrument &instrument); + ~InstrumentParser(); - void startTag(std::string name, - std::map< std::string, std::string> attributes); - void endTag(std::string name); - - std::vector channellist; + std::vector channellist; protected: - int readData(char *data, size_t size); + int readData(std::string& data, std::size_t size) override; + + virtual void startTag(const std::string& name, attr_t& attr) override; + virtual void endTag(const std::string& name) override; private: - FILE *fd{nullptr}; - Instrument &instrument; - Sample *s{nullptr}; + FILE* fd{nullptr}; + Instrument& instrument; + Sample* s{nullptr}; - std::string path; + std::string path; level_t lower{0}; level_t upper{0}; }; - -#endif/*__DRUMGIZMO_INSTRUMENTPARSER_H__*/ diff --git a/src/midimapparser.cc b/src/midimapparser.cc index 8dabb05..3c0e82b 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -26,27 +26,36 @@ */ #include "midimapparser.h" -MidiMapParser::MidiMapParser(std::string file) +MidiMapParser::MidiMapParser(const std::string& file) { - fd = fopen(file.c_str(), "r"); + fd = fopen(file.c_str(), "r"); } MidiMapParser::~MidiMapParser() { - if(fd) fclose(fd); + if(fd) + { + fclose(fd); + } } -void MidiMapParser::startTag(std::string name, attr_t attr) +void MidiMapParser::startTag(const std::string& name, attr_t& attr) { - if(name == "map") { - if(attr.find("note") != attr.end() && attr.find("instr") != attr.end()) { - midimap[atoi(attr["note"].c_str())] = attr["instr"]; - } - } + if(name == "map") + { + if(attr.find("note") != attr.end() && attr.find("instr") != attr.end()) + { + midimap[std::stoi(attr["note"])] = attr["instr"]; + } + } } -int MidiMapParser::readData(char *data, size_t size) +int MidiMapParser::readData(std::string& data, std::size_t size) { - if(!fd) return -1; - return fread(data, 1, size, fd); + if(!fd) + { + return -1; + } + + return fread((char*)data.c_str(), 1, size, fd); } diff --git a/src/midimapparser.h b/src/midimapparser.h index b9ef3e7..80b7507 100644 --- a/src/midimapparser.h +++ b/src/midimapparser.h @@ -24,29 +24,27 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_MIDIMAPPARSER_H__ -#define __DRUMGIZMO_MIDIMAPPARSER_H__ +#pragma once #include #include "saxparser.h" - #include "midimapper.h" -class MidiMapParser : public SAXParser { +class MidiMapParser + : public SAXParser +{ public: - MidiMapParser(std::string file); - ~MidiMapParser(); + MidiMapParser(const std::string& file); + ~MidiMapParser(); - void startTag(std::string name, attr_t attr); + void startTag(const std::string& name, attr_t& attr) override; - midimap_t midimap; + midimap_t midimap; protected: - int readData(char *data, size_t size); + int readData(std::string& data, size_t size) override; private: - FILE *fd; + FILE* fd; }; - -#endif/*__DRUMGIZMO_MIDIMAPPARSER_H__*/ diff --git a/src/saxparser.cc b/src/saxparser.cc index 1ed3050..e59a1fe 100644 --- a/src/saxparser.cc +++ b/src/saxparser.cc @@ -30,106 +30,102 @@ #include #include -static void character_hndl(void *p, const XML_Char *s, int len) +SAXParser::SAXParser() { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); - std::string chars; - chars.append(s, len); - parser->characterData(chars); + p = XML_ParserCreate(nullptr); + if(!p) { + 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); } -static void start_hndl(void *p, const char *el, const char **attr) +SAXParser::~SAXParser() { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); + XML_ParserFree(p); +} - // Convert to comfy C++ values... - std::string name = el; - std::map< std::string, std::string > attributes; +int SAXParser::parse() +{ + DEBUG(sax, "parse()\n"); + + std::string buf; + int len; + + do { + len = readData(buf, 32); + if(len <= -1) { + parseError("", 0, "Could not read data", 0); + return 1; + } + if(!XML_Parse(p, (char*)buf.c_str(), len, len == 0)) { + parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), + (int)XML_GetCurrentLineNumber(p)); + return 1; + } + + buf.clear(); + } while(len); + + return 0; +} - while(*attr) { - std::string at_name = *attr; - attr++; - std::string at_value = *attr; - attr++; +int SAXParser::parse(const std::string& buffer) +{ + DEBUG(sax, "parse(buffer %d bytes)\n", (int)buffer.length()); - attributes.insert(make_pair(at_name, at_value)); - } + if(!XML_Parse(p, buffer.c_str(), buffer.length(), true)) { + parseError(buffer, buffer.length(), + XML_ErrorString(XML_GetErrorCode(p)), + (int)XML_GetCurrentLineNumber(p)); + return 1; + } - parser->startTag(name, attributes); + return 0; } -static void end_hndl(void *p, const char *el) +void SAXParser::parseError(const std::string& buf, std::size_t len, const std::string& error, std::size_t lineno) { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); - std::string name = el; - parser->endTag(name); -} + fprintf(stderr, "SAXParser error at line %d: %s\n", (int)lineno, error.c_str()); + fprintf(stderr, "Buffer %u bytes: \n[\n", (int)len); + fwrite((char*)buf.c_str(), len, 1, stderr); -SAXParser::SAXParser() -{ - p = XML_ParserCreate(NULL); - if(!p) { - fprintf(stderr, "Couldn't allocate memory for parser\n"); - // throw Exception(...); - return; - } - - XML_SetUserData(p, this); - XML_UseParserAsHandlerArg(p); - XML_SetElementHandler(p, start_hndl, end_hndl); - XML_SetCharacterDataHandler(p, character_hndl); + fprintf(stderr, "\n]\n"); + fflush(stderr); } -SAXParser::~SAXParser() +void SAXParser::character_hndl(void* p, const XML_Char* s, int len) { - XML_ParserFree(p); + SAXParser* parser = (SAXParser*)XML_GetUserData(p); + std::string chars(s, len); + parser->characterData(chars); } -int SAXParser::parse() +void SAXParser::start_hndl(void* p, const char* el, const char** attr) { - DEBUG(sax, "parse()\n"); - - char buf[32]; - int len; - - do { - len = readData(buf, sizeof(buf) - 1); - if(len == -1) { - parseError((char*)"", 0, "Could not read data", 0); - return 1; - } - if(!XML_Parse(p, buf, len, len == 0)) { - parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return 1; - } - - memset(buf, 0, sizeof(buf)); - } while(len); - - return 0; -} + SAXParser* parser = (SAXParser*)XML_GetUserData(p); -int SAXParser::parse(std::string buffer) -{ - DEBUG(sax, "parse(buffer %d bytes)\n", (int)buffer.length()); + // Convert to comfy C++ values... + attr_t attributes; + + while(*attr) { + std::string at_name = *attr++; + std::string at_value = *attr++; - if(!XML_Parse(p, buffer.c_str(), buffer.length(), true)) { - parseError((char*)buffer.c_str(), buffer.length(), - XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return 1; - } + attributes.emplace(at_name, at_value); + } - return 0; + parser->startTag(std::string(el), attributes); } -void SAXParser::parseError(char *buf, size_t len, std::string error, int lineno) +void SAXParser::end_hndl(void* p, const char* el) { - fprintf(stderr, "SAXParser error at line %d: %s\n", lineno, error.c_str()); - fprintf(stderr, "\tBuffer %u bytes: [", (int)len); - if(fwrite(buf, len, 1, stderr) != len) {} - fprintf(stderr, "]\n"); - fflush(stderr); + SAXParser* parser = (SAXParser*)XML_GetUserData(p); + parser->endTag(std::string(el)); } diff --git a/src/saxparser.h b/src/saxparser.h index cc1800e..3222b4e 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -24,34 +24,37 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_SAXPARSER_H__ -#define __DRUMGIZMO_SAXPARSER_H__ +#pragma once #include #include #include -typedef std::map< std::string, std::string> attr_t; - class SAXParser { public: - SAXParser(); - virtual ~SAXParser(); + SAXParser(); + virtual ~SAXParser(); - int parse(); - int parse(std::string buffer); - - virtual void characterData(std::string &data) {} - virtual void startTag(std::string name, attr_t attr) {} - virtual void endTag(std::string name) {} + //! Parses the data obtained by readData in chunks. + int parse(); - virtual void parseError(char *buf, size_t len, std::string error, int lineno); + //! Parses all the data in the buffer. + int parse(const std::string& buffer); protected: - virtual int readData(char *data, size_t size) { return 0; } + using attr_t = std::map; + + virtual void characterData(const std::string& data) {} + virtual void startTag(const std::string& name, attr_t& attr) {} + virtual void endTag(const std::string& name) {} + virtual void parseError(const std::string& buf, std::size_t len, const std::string& error, std::size_t lineno); + + virtual int readData(std::string& data, std::size_t size) { return 0; } private: - XML_Parser p; -}; + XML_Parser p; -#endif/*__DRUMGIZMO_SAXPARSER_H__*/ + 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); +}; -- cgit v1.2.3 From eaf8c01ac99f9561870528ff608a073166be2163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Wed, 23 Mar 2016 15:07:17 +0100 Subject: Fix horribly stupid bug. --- src/drumkitparser.cc | 4 ++++ src/instrumentparser.cc | 11 +++++++++-- src/midimapparser.cc | 5 ++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 8746ae0..b3f3b99 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -242,5 +242,9 @@ int DrumKitParser::readData(std::string& data, std::size_t size) return -1; } + data.resize(size); + auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); + data.resize(nr_of_bytes_read); + return nr_of_bytes_read; return fread((char*)data.c_str(), 1, size, fd); } diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index 3ebc585..eed179d 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -236,6 +236,13 @@ void InstrumentParser::endTag(const std::string& name) int InstrumentParser::readData(std::string& data, std::size_t size) { - if(!fd) return -1; - return fread((char*)data.c_str(), 1, size, fd); + if(!fd) + { + return -1; + } + + data.resize(size); + auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); + data.resize(nr_of_bytes_read); + return nr_of_bytes_read; } diff --git a/src/midimapparser.cc b/src/midimapparser.cc index 3c0e82b..2d4563a 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -57,5 +57,8 @@ int MidiMapParser::readData(std::string& data, std::size_t size) return -1; } - return fread((char*)data.c_str(), 1, size, fd); + data.resize(size); + auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); + data.resize(nr_of_bytes_read); + return nr_of_bytes_read; } -- cgit v1.2.3 From 390f6f094d43f0d8cfca4efff13d002eb4cf6f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Wed, 23 Mar 2016 15:59:41 +0100 Subject: Make attr a const ref. --- src/configparser.cc | 6 +++--- src/configparser.h | 2 +- src/drumkitparser.cc | 21 ++++++++++----------- src/drumkitparser.h | 2 +- src/instrumentparser.cc | 24 ++++++++++++------------ src/instrumentparser.h | 2 +- src/midimapparser.cc | 4 ++-- src/midimapparser.h | 2 +- src/saxparser.h | 2 +- 9 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/configparser.cc b/src/configparser.cc index 1ada879..ef657b0 100644 --- a/src/configparser.cc +++ b/src/configparser.cc @@ -43,12 +43,12 @@ void ConfigParser::characterData(const std::string& data) } } -void ConfigParser::startTag(const std::string& name, attr_t& attr) +void ConfigParser::startTag(const std::string& name, const attr_t& attr) { if(name == "value" && attr.find("name") != attr.end()) { - values[attr["name"]] = ""; - str = &values[attr["name"]]; + values[attr.at("name")] = ""; + str = &values[attr.at("name")]; } } diff --git a/src/configparser.h b/src/configparser.h index 1e8aa56..b8bde05 100644 --- a/src/configparser.h +++ b/src/configparser.h @@ -37,7 +37,7 @@ public: ConfigParser(); void characterData(const std::string& data) override; - void startTag(const std::string& name, attr_t& attr) override; + void startTag(const std::string& name, const attr_t& attr) override; void endTag(const std::string& name) override; std::string value(const std::string& name, const std::string& def = ""); diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index b3f3b99..2d0262d 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -76,19 +76,18 @@ DrumKitParser::~DrumKitParser() } -void DrumKitParser::startTag(const std::string& name, - attr_t& attr) +void DrumKitParser::startTag(const std::string& name, const attr_t& attr) { if(name == "drumkit") { if(attr.find("name") != attr.end()) { - kit._name = attr["name"]; + kit._name = attr.at("name"); } if(attr.find("samplerate") != attr.end()) { - kit._samplerate = std::stoi(attr["samplerate"]); + kit._samplerate = std::stoi(attr.at("samplerate")); } else { @@ -99,14 +98,14 @@ void DrumKitParser::startTag(const std::string& name, if(attr.find("description") != attr.end()) { - kit._description = attr["description"]; + kit._description = attr.at("description"); } if(attr.find("version") != attr.end()) { try { - kit._version = VersionStr(attr["version"]); + kit._version = VersionStr(attr.at("version")); } catch(const char *err) { @@ -134,7 +133,7 @@ void DrumKitParser::startTag(const std::string& name, return; } - Channel c(attr["name"]); + Channel c(attr.at("name")); c.num = kit.channels.size(); kit.channels.push_back(c); } @@ -157,11 +156,11 @@ void DrumKitParser::startTag(const std::string& name, return; } - instr_name = attr["name"]; - instr_file = attr["file"]; + instr_name = attr.at("name"); + instr_file = attr.at("file"); if(attr.find("group") != attr.end()) { - instr_group = attr["group"]; + instr_group = attr.at("group"); } else { @@ -183,7 +182,7 @@ void DrumKitParser::startTag(const std::string& name, return; } - channelmap[attr["in"]] = attr["out"]; + channelmap[attr.at("in")] = attr.at("out"); } } diff --git a/src/drumkitparser.h b/src/drumkitparser.h index 91456d4..1c49ed8 100644 --- a/src/drumkitparser.h +++ b/src/drumkitparser.h @@ -38,7 +38,7 @@ public: ~DrumKitParser(); protected: - void startTag(const std::string& name, attr_t& attributes) override; + void startTag(const std::string& name, const attr_t& attributes) override; void endTag(const std::string& name) override; int readData(std::string& data, std::size_t size) override; diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index eed179d..8c3c737 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -57,24 +57,24 @@ InstrumentParser::~InstrumentParser() } } -void InstrumentParser::startTag(const std::string& name, attr_t& attr) +void InstrumentParser::startTag(const std::string& name, const attr_t& attr) { if(name == "instrument") { if(attr.find("name") != attr.end()) { - instrument._name = attr["name"]; + instrument._name = attr.at("name"); } if(attr.find("description") != attr.end()) { - instrument._description = attr["description"]; + instrument._description = attr.at("description"); } if(attr.find("version") != attr.end()) { try { - instrument.version = VersionStr(attr["version"]); + instrument.version = VersionStr(attr.at("version")); } catch(const char *err) { @@ -109,12 +109,12 @@ void InstrumentParser::startTag(const std::string& name, attr_t& attr) } else { - power = atof_nol(attr["power"].c_str()); + power = atof_nol(attr.at("power").c_str()); DEBUG(instrparser, "Instrument power set to %f\n", power); } // TODO get rid of new or delete it properly - s = new Sample(attr["name"], power); + s = new Sample(attr.at("name"), power); } if(name == "audiofile") @@ -140,7 +140,7 @@ void InstrumentParser::startTag(const std::string& name, attr_t& attr) int filechannel = 1; // default, override with optional attribute if(attr.find("filechannel") != attr.end()) { - filechannel = std::stoi(attr["filechannel"]); + filechannel = std::stoi(attr.at("filechannel")); if(filechannel < 1) { ERR(instrparser,"Invalid value for attribute 'filechannel'.\n"); @@ -150,8 +150,8 @@ void InstrumentParser::startTag(const std::string& name, 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["file"], filechannel); - InstrumentChannel *ch = new InstrumentChannel(attr["channel"]); + 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); @@ -176,8 +176,8 @@ void InstrumentParser::startTag(const std::string& name, attr_t& attr) return; } - lower = atof_nol(attr["lower"].c_str()); - upper = atof_nol(attr["upper"].c_str()); + lower = atof_nol(attr.at("lower").c_str()); + upper = atof_nol(attr.at("upper").c_str()); } if(name == "sampleref") @@ -192,7 +192,7 @@ void InstrumentParser::startTag(const std::string& name, attr_t& attr) std::vector::iterator i = instrument.samplelist.begin(); while(i != instrument.samplelist.end()) { - if((*i)->name == attr["name"]) + if((*i)->name == attr.at("name")) { sample = *i; break; diff --git a/src/instrumentparser.h b/src/instrumentparser.h index 3fee916..a203444 100644 --- a/src/instrumentparser.h +++ b/src/instrumentparser.h @@ -43,7 +43,7 @@ public: protected: int readData(std::string& data, std::size_t size) override; - virtual void startTag(const std::string& name, attr_t& attr) override; + virtual void startTag(const std::string& name, const attr_t& attr) override; virtual void endTag(const std::string& name) override; private: diff --git a/src/midimapparser.cc b/src/midimapparser.cc index 2d4563a..38a4124 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -39,13 +39,13 @@ MidiMapParser::~MidiMapParser() } } -void MidiMapParser::startTag(const std::string& name, attr_t& attr) +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()) { - midimap[std::stoi(attr["note"])] = attr["instr"]; + midimap[std::stoi(attr.at("note"))] = attr.at("instr"); } } } diff --git a/src/midimapparser.h b/src/midimapparser.h index 80b7507..02e79df 100644 --- a/src/midimapparser.h +++ b/src/midimapparser.h @@ -38,7 +38,7 @@ public: MidiMapParser(const std::string& file); ~MidiMapParser(); - void startTag(const std::string& name, attr_t& attr) override; + void startTag(const std::string& name, const attr_t& attr) override; midimap_t midimap; diff --git a/src/saxparser.h b/src/saxparser.h index 3222b4e..c43f00a 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -45,7 +45,7 @@ protected: using attr_t = std::map; virtual void characterData(const std::string& data) {} - virtual void startTag(const std::string& name, attr_t& attr) {} + 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, std::size_t len, const std::string& error, std::size_t lineno); -- cgit v1.2.3 From ef1d7e4478649296ccb17900acc949a604097d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Wed, 23 Mar 2016 18:24:29 +0100 Subject: Do the file related actions in SAXParser. --- src/audioinputenginemidi.cc | 4 +-- src/configparser.h | 4 +-- src/drumgizmo.cc | 6 ++--- src/drumkitparser.cc | 56 +++++++++++--------------------------- src/drumkitparser.h | 8 +++--- src/instrumentparser.cc | 32 ++++------------------ src/instrumentparser.h | 8 +++--- src/midimapparser.cc | 26 ------------------ src/midimapparser.h | 9 ------- src/saxparser.cc | 65 +++++++++++++++++++++------------------------ src/saxparser.h | 12 ++++----- 11 files changed, 70 insertions(+), 160 deletions(-) diff --git a/src/audioinputenginemidi.cc b/src/audioinputenginemidi.cc index d81a49b..e3cb796 100644 --- a/src/audioinputenginemidi.cc +++ b/src/audioinputenginemidi.cc @@ -58,8 +58,8 @@ bool AudioInputEngineMidi::loadMidiMap(std::string file, Instruments &instrument if(f == "") return false; - MidiMapParser p(f); - if(p.parse()) { + MidiMapParser p; + if(p.parseFile(f)) { return false; } diff --git a/src/configparser.h b/src/configparser.h index b8bde05..79f0cb1 100644 --- a/src/configparser.h +++ b/src/configparser.h @@ -30,8 +30,8 @@ #include "saxparser.h" -class ConfigParser : - public SAXParser +class ConfigParser + : public SAXParser { public: ConfigParser(); diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 159b01b..51cee18 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -81,8 +81,8 @@ bool DrumGizmo::loadkit(std::string file) // Delete all Channels, Instruments, Samples and AudioFiles. kit.clear(); - DrumKitParser parser(file, kit); - if(parser.parse()) + DrumKitParser parser(kit); + if(parser.parseFile(file)) { ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); return false; @@ -709,7 +709,7 @@ bool DrumGizmo::setConfigString(std::string cfg) std::string dkf; ConfigParser p; - if(p.parse(cfg)) + if(p.parseString(cfg)) { ERR(drumgizmo, "Config parse error.\n"); return false; diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 2d0262d..595cd41 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -34,17 +34,21 @@ #include "path.h" #include "drumgizmo.h" -DrumKitParser::DrumKitParser(const std::string& file, DrumKit& k) - : kit(k) +DrumKitParser::DrumKitParser(DrumKit& kit) + : kit(kit) , refs(REFSFILE) { - std::string kitfile = file; +} + +int DrumKitParser::parseFile(const std::string& filename) +{ + auto edited_filename(filename); if(refs.load()) { - if(file.size() > 1 && file[0] == '@') + if(filename.size() > 1 && filename[0] == '@') { - kitfile = refs.getValue(file.substr(1)); + edited_filename = refs.getValue(filename.substr(1)); } } else @@ -52,28 +56,14 @@ DrumKitParser::DrumKitParser(const std::string& file, DrumKit& k) ERR(drumkitparser, "Error reading refs.conf"); } - // instr = NULL; - path = getPath(kitfile); - - fd = fopen(kitfile.c_str(), "r"); - - // DEBUG(kitparser, "Parsing drumkit in %s\n", kitfile.c_str()); - - if(!fd) - { - return; - } - - kit._file = file; -} + path = getPath(edited_filename); + auto result = SAXParser::parseFile(filename); -DrumKitParser::~DrumKitParser() -{ - if(fd) - { - fclose(fd); + if (result == 0) { + kit._file = edited_filename; } + return result; } void DrumKitParser::startTag(const std::string& name, const attr_t& attr) @@ -193,8 +183,8 @@ void DrumKitParser::endTag(const std::string& name) Instrument* i = new Instrument(); i->setGroup(instr_group); // Instrument &i = kit.instruments[kit.instruments.size() - 1]; - InstrumentParser parser(path + "/" + instr_file, *i); - parser.parse(); + InstrumentParser parser(*i); + parser.parseFile(path + "/" + instr_file); kit.instruments.push_back(i); // Assign kit channel numbers to instruments channels. @@ -233,17 +223,3 @@ void DrumKitParser::endTag(const std::string& name) channelmap.clear(); } } - -int DrumKitParser::readData(std::string& data, std::size_t size) -{ - if(!fd) - { - return -1; - } - - data.resize(size); - auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); - data.resize(nr_of_bytes_read); - return nr_of_bytes_read; - return fread((char*)data.c_str(), 1, size, fd); -} diff --git a/src/drumkitparser.h b/src/drumkitparser.h index 1c49ed8..f857590 100644 --- a/src/drumkitparser.h +++ b/src/drumkitparser.h @@ -34,17 +34,15 @@ class DrumKitParser : public SAXParser { public: - DrumKitParser(const std::string& kitfile, DrumKit& kit); - ~DrumKitParser(); + DrumKitParser(DrumKit& kit); + + virtual int parseFile(const std::string& filename) override; protected: void startTag(const std::string& name, const attr_t& attributes) override; void endTag(const std::string& name) override; - int readData(std::string& data, std::size_t size) override; - private: - FILE* fd; DrumKit& kit; std::string path; diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index 8c3c737..268f8f3 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -35,26 +35,17 @@ #include "nolocale.h" -InstrumentParser::InstrumentParser(const std::string& file, Instrument& i) +InstrumentParser::InstrumentParser(Instrument& i) : instrument(i) { - // DEBUG(instrparser,"Parsing instrument in %s\n", file.c_str()); - path = getPath(file); - fd = fopen(file.c_str(), "r"); - if(!fd) - { - ERR(instrparser, "The following instrument file could not be opened: %s\n", file.c_str()); - return; - } } -InstrumentParser::~InstrumentParser() +int InstrumentParser::parseFile(const std::string& filename) { - if(fd) - { - fclose(fd); - } + path = getPath(filename); + + return SAXParser::parseFile(filename); } void InstrumentParser::startTag(const std::string& name, const attr_t& attr) @@ -233,16 +224,3 @@ void InstrumentParser::endTag(const std::string& name) instrument.finalise(); } } - -int InstrumentParser::readData(std::string& data, std::size_t size) -{ - if(!fd) - { - return -1; - } - - data.resize(size); - auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); - data.resize(nr_of_bytes_read); - return nr_of_bytes_read; -} diff --git a/src/instrumentparser.h b/src/instrumentparser.h index a203444..965694a 100644 --- a/src/instrumentparser.h +++ b/src/instrumentparser.h @@ -35,19 +35,17 @@ class InstrumentParser : public SAXParser { public: - InstrumentParser(const std::string& instrfile, Instrument &instrument); - ~InstrumentParser(); + InstrumentParser(Instrument &instrument); + + virtual int parseFile(const std::string& filename) override; std::vector channellist; protected: - int readData(std::string& data, std::size_t size) override; - virtual void startTag(const std::string& name, const attr_t& attr) override; virtual void endTag(const std::string& name) override; private: - FILE* fd{nullptr}; Instrument& instrument; Sample* s{nullptr}; diff --git a/src/midimapparser.cc b/src/midimapparser.cc index 38a4124..ec4c10d 100644 --- a/src/midimapparser.cc +++ b/src/midimapparser.cc @@ -26,19 +26,6 @@ */ #include "midimapparser.h" -MidiMapParser::MidiMapParser(const std::string& file) -{ - fd = fopen(file.c_str(), "r"); -} - -MidiMapParser::~MidiMapParser() -{ - if(fd) - { - fclose(fd); - } -} - void MidiMapParser::startTag(const std::string& name, const attr_t& attr) { if(name == "map") @@ -49,16 +36,3 @@ void MidiMapParser::startTag(const std::string& name, const attr_t& attr) } } } - -int MidiMapParser::readData(std::string& data, std::size_t size) -{ - if(!fd) - { - return -1; - } - - data.resize(size); - auto nr_of_bytes_read = fread((void*)data.data(), 1, size, fd); - data.resize(nr_of_bytes_read); - return nr_of_bytes_read; -} diff --git a/src/midimapparser.h b/src/midimapparser.h index 02e79df..740cb60 100644 --- a/src/midimapparser.h +++ b/src/midimapparser.h @@ -35,16 +35,7 @@ class MidiMapParser : public SAXParser { public: - MidiMapParser(const std::string& file); - ~MidiMapParser(); - void startTag(const std::string& name, const attr_t& attr) override; midimap_t midimap; - -protected: - int readData(std::string& data, size_t size) override; - -private: - FILE* fd; }; diff --git a/src/saxparser.cc b/src/saxparser.cc index e59a1fe..e32143d 100644 --- a/src/saxparser.cc +++ b/src/saxparser.cc @@ -26,9 +26,10 @@ */ #include "saxparser.h" -#include #include #include +#include +#include SAXParser::SAXParser() { @@ -50,54 +51,48 @@ SAXParser::~SAXParser() XML_ParserFree(p); } -int SAXParser::parse() +int SAXParser::parseFile(const std::string& filename) { - DEBUG(sax, "parse()\n"); - - std::string buf; - int len; - - do { - len = readData(buf, 32); - if(len <= -1) { - parseError("", 0, "Could not read data", 0); - return 1; - } - if(!XML_Parse(p, (char*)buf.c_str(), len, len == 0)) { - parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return 1; - } - - buf.clear(); - } while(len); + if(filename.empty()) + { + return 0; + } + + std::ifstream file(filename, std::ifstream::in); + + if(!file.is_open()) { + return 1; + } + + std::stringstream ss; + ss << file.rdbuf(); + std::string str = ss.str(); + + parseString(str, filename); return 0; } -int SAXParser::parse(const std::string& buffer) +int SAXParser::parseString(const std::string& str, const std::string& xml_source_name) { - DEBUG(sax, "parse(buffer %d bytes)\n", (int)buffer.length()); + DEBUG(sax, "parse(buffer %d bytes)\n", (int)str.length()); - if(!XML_Parse(p, buffer.c_str(), buffer.length(), true)) { - parseError(buffer, buffer.length(), - XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); + if(!XML_Parse(p, str.c_str(), str.length(), true)) { + parseError(str, XML_ErrorString(XML_GetErrorCode(p)), + xml_source_name, (int)XML_GetCurrentLineNumber(p)); return 1; } return 0; } -void SAXParser::parseError(const std::string& buf, std::size_t len, const std::string& error, 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) { - fprintf(stderr, "SAXParser error at line %d: %s\n", (int)lineno, error.c_str()); - fprintf(stderr, "Buffer %u bytes: \n[\n", (int)len); - - fwrite((char*)buf.c_str(), len, 1, stderr); - - fprintf(stderr, "\n]\n"); - fflush(stderr); + 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) diff --git a/src/saxparser.h b/src/saxparser.h index c43f00a..b4d9823 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -29,17 +29,18 @@ #include #include #include +#include class SAXParser { public: SAXParser(); virtual ~SAXParser(); - //! Parses the data obtained by readData in chunks. - int parse(); + //! Parses the data from the file. + virtual int parseFile(const std::string& filename); //! Parses all the data in the buffer. - int parse(const std::string& buffer); + virtual int parseString(const std::string& str, const std::string& xml_source_name = ""); protected: using attr_t = std::map; @@ -47,12 +48,11 @@ 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, std::size_t len, const std::string& error, std::size_t lineno); - - virtual int readData(std::string& data, std::size_t size) { return 0; } + 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; + 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); -- cgit v1.2.3 From 6ac5946767ba41d7eff9eb8521519007fdc58750 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 21:57:41 +0100 Subject: More cleanup. --- src/drumkit.cc | 53 +++++++++++++------------------------- src/drumkit.h | 43 +++++++++++++++---------------- src/drumkitparser.cc | 38 ++++++++++++++++------------ src/instrumentparser.cc | 62 ++++++++++++++++++++++++--------------------- src/instrumentparser.h | 2 +- src/midimapparser.cc | 3 ++- src/midimapparser.h | 2 -- src/path.cc | 24 ++++++++++-------- src/path.h | 8 +++--- src/sample.cc | 67 ++++++++++++++++--------------------------------- src/sample.h | 36 +++++++++----------------- src/saxparser.cc | 66 ++++++++++++++++++++++++++---------------------- src/saxparser.h | 19 ++++++++------ 13 files changed, 194 insertions(+), 229 deletions(-) diff --git a/src/drumkit.cc b/src/drumkit.cc index d8596c7..e41bd49 100644 --- a/src/drumkit.cc +++ b/src/drumkit.cc @@ -28,69 +28,52 @@ DrumKit::DrumKit() { - magic = this; + magic = this; } DrumKit::~DrumKit() { - magic = NULL; - clear(); + magic = NULL; + clear(); } void DrumKit::clear() { - Instruments::iterator i = instruments.begin(); - while(i != instruments.end()) { - delete *i; - i++; - } - instruments.clear(); + for(auto& instrument : instruments) + { + delete instrument; + } - channels.clear(); + instruments.clear(); - _name = ""; - _description = ""; - _samplerate = 44100; + channels.clear(); + + _name = ""; + _description = ""; + _samplerate = 44100; } bool DrumKit::isValid() { - return this == magic; + return this == magic; } std::string DrumKit::file() { - return _file; + return _file; } std::string DrumKit::name() { - return _name; + return _name; } std::string DrumKit::description() { - return _description; + return _description; } size_t DrumKit::samplerate() { - return _samplerate; + 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 24fce99..26f2945 100644 --- a/src/drumkit.h +++ b/src/drumkit.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_DRUMKIT_H__ -#define __DRUMGIZMO_DRUMKIT_H__ +#pragma once #include #include @@ -34,37 +33,35 @@ #include "instrument.h" #include "versionstr.h" -class DrumKitParser; -class DrumKit { - friend class DrumKitParser; +class DrumKit +{ + friend class DrumKitParser; public: - DrumKit(); - ~DrumKit(); + DrumKit(); + ~DrumKit(); - std::string file(); + std::string file(); - std::string name(); - std::string description(); - - Instruments instruments; - Channels channels; - - void clear(); + std::string name(); + std::string description(); - bool isValid(); + Instruments instruments; + Channels channels; - size_t samplerate(); + void clear(); + + bool isValid(); + + size_t samplerate(); private: void *magic{nullptr}; - std::string _file; + std::string _file; - std::string _name; - std::string _description; + std::string _name; + std::string _description; size_t _samplerate{0}; - VersionStr _version; + VersionStr _version; }; - -#endif/*__DRUMGIZMO_DRUMKIT_H__*/ diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 595cd41..bb51a75 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -36,7 +36,7 @@ DrumKitParser::DrumKitParser(DrumKit& kit) : kit(kit) - , refs(REFSFILE) + , refs(REFSFILE) { } @@ -46,9 +46,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 @@ -59,7 +59,8 @@ int DrumKitParser::parseFile(const std::string& filename) path = getPath(edited_filename); auto result = SAXParser::parseFile(filename); - if (result == 0) { + if(result == 0) + { kit._file = edited_filename; } @@ -101,7 +102,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 +113,7 @@ void DrumKitParser::startTag(const std::string& name, const attr_t& attr) if(name == "channels") { - + } if(name == "channel") @@ -140,6 +141,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 +182,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(); + 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::iterator ic = parser.channellist.begin(); @@ -206,16 +210,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->name().c_str()); + c->name.c_str(), instrument->name().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/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::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/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 - #include "saxparser.h" #include "midimapper.h" diff --git a/src/path.cc b/src/path.cc index 5c899f2..c2e7910 100644 --- a/src/path.cc +++ b/src/path.cc @@ -33,19 +33,21 @@ #include #include -std::string getPath(std::string file) +std::string getPath(const std::string& file) { - std::string p; -#ifndef __MINGW32__ - char *b = strdup(file.c_str()); - p = dirname(b); - free(b); + std::string path; + +#ifdef __MINGW32__ + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + _splitpath(file.c_str(), drive, dir, NULL, NULL); + path = std::string(drive) + dir; #else - char drive[_MAX_DRIVE]; - char dir[_MAX_DIR]; - _splitpath(file.c_str(), drive, dir, NULL, NULL); - p = std::string(drive) + dir; + // POSIX + char* buffer = strdup(file.c_str()); + path = dirname(buffer); + free(buffer); #endif - return p; + return path; } diff --git a/src/path.h b/src/path.h index 17b63d9..50ff842 100644 --- a/src/path.h +++ b/src/path.h @@ -24,11 +24,9 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_PATH_H__ -#define __DRUMGIZMO_PATH_H__ +#pragma once #include -std::string getPath(std::string file); - -#endif/*__DRUMGIZMO_PATH_H__*/ +//! \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 27382af..22bee14 100644 --- a/src/sample.cc +++ b/src/sample.cc @@ -26,60 +26,37 @@ */ #include "sample.h" -#include -#include - -#include - -Sample::Sample(std::string name, float power) +Sample::Sample(const std::string& name, float power) + : name(name) + , power(power) { - this->name = name; - this->power = power; } Sample::~Sample() { } -void Sample::addAudioFile(Channel *c, AudioFile *a) +void Sample::addAudioFile(InstrumentChannel* instrument_channel, + AudioFile* audio_file) { - audiofiles[c] = a; + audiofiles[instrument_channel] = audio_file; } -AudioFile *Sample::getAudioFile(Channel *c) +AudioFile *Sample::getAudioFile(InstrumentChannel* instrument_channel) { - /* - if(audiofiles.find(c) == audiofiles.end()) return NULL; - return audiofiles[c]; - */ - - AudioFiles::iterator i = audiofiles.begin(); - while(i != audiofiles.end()) { - Channel *ch = i->first; - if(c->num == ch->num) return i->second; - i++; - } - - return NULL; + /* + if(audiofiles.find(c) == audiofiles.end()) return NULL; + return audiofiles[c]; + */ + + for(auto& audio_file : audiofiles) + { + InstrumentChannel *ch = audio_file.first; + if(instrument_channel->num == ch->num) + { + return audio_file.second; + } + } + + 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), NULL, "?"); - -TEST_END; - -#endif/*TEST_SAMPLE*/ diff --git a/src/sample.h b/src/sample.h index 26c7be2..f00db13 100644 --- a/src/sample.h +++ b/src/sample.h @@ -24,8 +24,7 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __DRUMGIZMO_SAMPLE_H__ -#define __DRUMGIZMO_SAMPLE_H__ +#pragma once #include #include @@ -33,33 +32,22 @@ #include "channel.h" #include "audiofile.h" -typedef std::map< Channel*, AudioFile* > AudioFiles; +using AudioFiles = std::map; -class InstrumentParser; class Sample { - friend class InstrumentParser; - friend class PowerList; + friend class InstrumentParser; + friend class PowerList; public: - Sample(std::string name, float power); - ~Sample(); + 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; + std::string name; + float power; + AudioFiles audiofiles; }; - -/* - * - * - * - * - * - * - * - */ -#endif/*__DRUMGIZMO_SAMPLE_H__*/ 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 -#include #include #include +#include + 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 b4d9823..8cfbdda 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -31,7 +31,8 @@ #include #include -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::map; @@ -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); }; -- cgit v1.2.3 From 253a7fbc4a13d459cb2bd19f51ad578c0e1814f2 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 22:16:20 +0100 Subject: Fix drumkit file by reference. --- src/drumkitparser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index bb51a75..92230cc 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -57,7 +57,7 @@ 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) { -- cgit v1.2.3 From 324502145b2a5fec38928509c8b3d9f8eb8bf47d Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 22:38:44 +0100 Subject: Settings. --- drumgizmo/drumgizmoc.cc | 3 +- plugin/drumgizmo_plugin.cc | 2 +- plugin/drumgizmo_plugin.h | 2 + plugingui/dgwindow.cc | 31 ++++--- plugingui/dgwindow.h | 7 +- plugingui/plugingui.cc | 90 +++++++++++++++++++- plugingui/plugingui.h | 24 ++++-- src/drumgizmo.cc | 10 ++- src/drumgizmo.h | 8 +- src/drumkitloader.cc | 16 ++-- src/drumkitloader.h | 4 +- src/drumkitparser.cc | 7 +- src/drumkitparser.h | 3 +- src/instrument.cc | 205 ++++++++++++++++++++++----------------------- src/instrument.h | 50 ++++++----- src/settings.h | 94 +++++++++++++-------- 16 files changed, 354 insertions(+), 202 deletions(-) diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 14a71b3..3164c2e 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -372,7 +372,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()); diff --git a/plugin/drumgizmo_plugin.cc b/plugin/drumgizmo_plugin.cc index 2a7e556..6563dcc 100644 --- a/plugin/drumgizmo_plugin.cc +++ b/plugin/drumgizmo_plugin.cc @@ -59,7 +59,7 @@ DrumGizmoPlugin::DrumGizmoPlugin() { init(); - drumgizmo = std::make_shared(&output, &input); + drumgizmo = std::make_shared(settings, &output, &input); resizeWindow(370, 330); drumgizmo->setFreeWheel(true); drumgizmo->setSamplerate(44100); diff --git a/plugin/drumgizmo_plugin.h b/plugin/drumgizmo_plugin.h index 4a4ec13..5d4a648 100644 --- a/plugin/drumgizmo_plugin.h +++ b/plugin/drumgizmo_plugin.h @@ -154,6 +154,8 @@ private: Output output{*this}; const std::vector* output_samples{nullptr}; + Settings settings; + std::shared_ptr plugin_gui; std::shared_ptr drumgizmo; }; diff --git a/plugingui/dgwindow.cc b/plugingui/dgwindow.cc index 86a985d..25cbdf0 100644 --- a/plugingui/dgwindow.cc +++ b/plugingui/dgwindow.cc @@ -120,10 +120,11 @@ public: }; DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, - Config& config) + Config& config, Settings& settings) : Window(native_window) , messageHandler(messageHandler) , config(config) + , settings(settings) { int vlineSpacing = 16; @@ -233,11 +234,12 @@ void DGWindow::repaintEvent(RepaintEvent* repaintEvent) void DGWindow::attackValueChanged(float value) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, - value); + //ChangeSettingMessage *msg = + // new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, + // value); + //messageHandler.sendMessage(MSGRCV_ENGINE, msg); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.velocity_modifier_weight.store(value); #ifdef STANDALONE int i = value * 4; @@ -253,10 +255,12 @@ void DGWindow::attackValueChanged(float value) void DGWindow::falloffValueChanged(float value) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, - value); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + //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); @@ -265,10 +269,11 @@ void DGWindow::falloffValueChanged(float value) void DGWindow::velocityCheckClick(bool checked) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, - checked); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); +// ChangeSettingMessage *msg = +// new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, +// checked); +// messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.enable_velocity_modifier.store(checked); } void DGWindow::kitBrowseClick() diff --git a/plugingui/dgwindow.h b/plugingui/dgwindow.h index 605e87a..c4fbeab 100644 --- a/plugingui/dgwindow.h +++ b/plugingui/dgwindow.h @@ -37,6 +37,8 @@ #include "filebrowser.h" #include "layout.h" +#include + class MessageHandler; namespace GUI { @@ -47,7 +49,8 @@ class File; class DGWindow : public Window { public: - DGWindow(void* native_window, MessageHandler& messageHandler, Config& config); + DGWindow(void* native_window, MessageHandler& messageHandler, Config& config, + Settings& settings); Header* header; @@ -85,6 +88,8 @@ private: Image back{":bg.png"}; Image logo{":logo.png"}; + + Settings& settings; }; } // GUI:: diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index e34c471..9bac007 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -31,6 +31,8 @@ #include "pluginconfig.h" #include "messagehandler.h" +#include + namespace GUI { PluginGUI::PluginGUI(void* native_window) @@ -116,7 +118,68 @@ bool PluginGUI::processEvents() } window->eventHandler()->processEvents(); - handleMessages(); + //handleMessages(); + + static bool foo = false; + static int t = 0; + if(t != time(nullptr)) + { + t = time(nullptr); + foo = !foo; + float v = settings.velocity_modifier_falloff.load(); + v += 0.1f; + settings.velocity_modifier_falloff.store(v); + } + + Painter p(*window); + + // Run through all settings one at a time propagate changes to the UI. + if(getter.enable_velocity_modifier.hasChanged()) + { + enable_velocity_modifier_notifier(getter.enable_velocity_modifier.getValue()); + } + + if(getter.velocity_modifier_falloff.hasChanged()) + { + velocity_modifier_falloff_notifier(getter.velocity_modifier_falloff.getValue()); + } + + if(getter.velocity_modifier_weight.hasChanged()) + { + velocity_modifier_weight_notifier(getter.velocity_modifier_weight.getValue()); + } + + if(getter.enable_velocity_randomiser.hasChanged()) + { + enable_velocity_randomiser_notifier(getter.enable_velocity_randomiser.getValue()); + } + + if(getter.velocity_randomiser_weight.hasChanged()) + { + velocity_randomiser_weight_notifier(getter.velocity_randomiser_weight.getValue()); + } + + if(getter.samplerate.hasChanged()) + { + samplerate_notifier(getter.samplerate.getValue()); + } + + if(getter.enable_resampling.hasChanged()) + { + enable_resampling_notifier(getter.enable_resampling.getValue()); + } + + if(getter.number_of_files.hasChanged() || + getter.number_of_files_loaded.hasChanged()) + { + drumkit_file_progress_notifier((float)getter.number_of_files_loaded.getValue() / + (float)getter.number_of_files.getValue()); + } + + //if(getter.current_file.hasChanged()) + //{ + // current_file_notifier(getter.current_file.getValue()); + //} if(closing) { @@ -135,7 +198,30 @@ void PluginGUI::init() config = new Config(); config->load(); - window = new DGWindow(native_window, msghandler, *config); + window = new DGWindow(native_window, msghandler, *config, settings); + + CONNECT(this, enable_velocity_modifier_notifier, + window->velocityCheck, &CheckBox::setChecked); + + CONNECT(this, velocity_modifier_falloff_notifier, + window->falloffKnob, &Knob::setValue); + CONNECT(this, velocity_modifier_weight_notifier, + window->attackKnob, &Knob::setValue); + + + //CONNECT(this, enable_velocity_randomiser_notifier, + // window->velocityCheck, &CheckBox::setChecked); + //CONNECT(this, velocity_randomiser_weight_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + //CONNECT(this, samplerate_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + //CONNECT(this, enable_resampling_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + CONNECT(this, drumkit_file_progress_notifier, + window->drumkitFileProgress, &ProgressBar::setProgress); auto eventHandler = window->eventHandler(); CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler); diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index f441696..ca31c41 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -31,9 +31,7 @@ #include "pluginconfig.h" - -#include "thread.h" -#include "semaphore.h" +#include #include "messagereceiver.h" #include "notifier.h" @@ -68,6 +66,21 @@ public: Notifier<> closeNotifier; + // Setting notifiers: + Notifier enable_velocity_modifier_notifier; + Notifier velocity_modifier_falloff_notifier; + Notifier velocity_modifier_weight_notifier; + + Notifier enable_velocity_randomiser_notifier; + Notifier velocity_randomiser_weight_notifier; + + Notifier samplerate_notifier; + + Notifier enable_resampling_notifier; + + Notifier drumkit_file_progress_notifier; + //Notifier current_file_notifier; + // Support old interface a little while longer.. void setWindowClosedCallback(void (*handler)(void*), void* ptr); @@ -80,11 +93,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; + SettingsGetter getter{settings}; }; } // GUI:: diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 51cee18..2658754 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -46,18 +46,20 @@ #include "nolocale.h" -DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i) +DrumGizmo::DrumGizmo(Settings& settings, + AudioOutputEngine *o, AudioInputEngine *i) : MessageReceiver(MSGRCV_ENGINE) - , loader() + , loader(settings) , oe(o) , ie(i) , framesize(0) , freewheel(false) , events{} + , settings(settings) { is_stopping = false; audioCache.init(10000); // start thread - + events.reserve(1000); } @@ -81,7 +83,7 @@ bool DrumGizmo::loadkit(std::string file) // Delete all Channels, Instruments, Samples and AudioFiles. kit.clear(); - DrumKitParser parser(kit); + DrumKitParser parser(settings, kit); if(parser.parseFile(file)) { ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 632d5fc..63348da 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -50,6 +50,8 @@ #include "configfile.h" +#include "settings.h" + #define MAX_NUM_CHANNELS 64 #define REFSFILE "refs.conf" #define RESAMPLER_INPUT_BUFFER 64 @@ -58,7 +60,8 @@ class DrumGizmo : public MessageReceiver { public: - DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine); + DrumGizmo(Settings& settings, + AudioOutputEngine *outputengine, AudioInputEngine *inputengine); virtual ~DrumGizmo(); bool loadkit(std::string kitfile); @@ -106,6 +109,7 @@ protected: size_t framesize; bool freewheel; - + std::vector events; + Settings& settings; }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index ff489ea..3cb4b68 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -31,9 +31,10 @@ #include "drumkitparser.h" #include "drumgizmo.h" -DrumKitLoader::DrumKitLoader() +DrumKitLoader::DrumKitLoader(Settings& settings) : semaphore("drumkitloader") , framesize(0) + , settings(settings) { run(); run_semaphore.wait(); // Wait for the thread to actually start. @@ -187,11 +188,14 @@ void DrumKitLoader::thread_main() if(loaded % fraction == 0 || loaded == total_num_audiofiles) { - 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); + //LoadStatusMessage *ls = new LoadStatusMessage(); + //ls->number_of_files = total_num_audiofiles; + //ls->numer_of_files_loaded = loaded; + //ls->current_file = filename; + //msghandler.sendMessage(MSGRCV_UI, ls); + settings.number_of_files.store(total_num_audiofiles); + settings.number_of_files_loaded.store(loaded); + //settings.current_file.store(filename); } } diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 3656839..2410074 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -34,6 +34,7 @@ #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 +46,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 @@ -82,4 +83,5 @@ protected: size_t fraction{1}; size_t loaded{0}; size_t framesize{0}; + Settings& settings; }; diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 92230cc..1210611 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) +DrumKitParser::DrumKitParser(Settings& setting, DrumKit& k) + : kit(k) , refs(REFSFILE) + , settings(settings) { } @@ -182,7 +183,7 @@ void DrumKitParser::endTag(const std::string& name) { if(name == "instrument") { - Instrument* instrument = new Instrument(); + Instrument* instrument = new Instrument(settings); instrument->setGroup(instr_group); InstrumentParser parser(*instrument); diff --git a/src/drumkitparser.h b/src/drumkitparser.h index f857590..b3cf0a6 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 96a6bfd..eeaa956 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -34,147 +34,142 @@ #include "sample.h" #include "configuration.h" -Instrument::Instrument() +Instrument::Instrument(Settings& settings) + : settings(settings) { - DEBUG(instrument, "new %p\n", this); - mod = 1.0; - lastpos = 0; + DEBUG(instrument, "new %p\n", this); + mod = 1.0; + lastpos = 0; - magic = this; + magic = this; } Instrument::~Instrument() { - magic = NULL; - - DEBUG(instrument, "delete %p\n", this); - std::vector::iterator i = audiofiles.begin(); - while(i != audiofiles.end()) { - delete *i; - i++; - } + magic = NULL; + + DEBUG(instrument, "delete %p\n", this); + std::vector::iterator i = audiofiles.begin(); + while(i != audiofiles.end()) + { + delete *i; + i++; + } } bool Instrument::isValid() { - return this == magic; + return this == magic; } Sample *Instrument::sample(level_t level, size_t pos) { - Sample *sample = NULL; - - if(Conf::enable_velocity_modifier == false) { - mod = 1.0; - lastpos = 0; - } - - if(Conf::enable_velocity_randomiser) { - float r = (float)rand() / (float)RAND_MAX; // random number: [0;1] - r -= 0.5; // random number [-0.5;0.5] - r *= Conf::velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] - level += r; - if(level > 1.0) level = 1.0; - if(level < 0.0) level = 0.0; - } - - if(Conf::enable_velocity_modifier) { - mod += (pos - lastpos) / - (Conf::samplerate * Conf::velocity_modifier_falloff); - if(mod > 1.0) mod = 1.0; - } - - if(version >= VersionStr("2.0")) { - // Version 2.0 - sample = powerlist.get(level * mod); - } else { - // Version 1.0 - std::vector s = samples.get(level * mod); - if(s.size() == 0) return NULL; - size_t idx = rand()%(s.size()); - sample = s[idx]; - } - - if(Conf::enable_velocity_modifier) { - lastpos = pos; - mod *= Conf::velocity_modifier_weight; - } - - return sample; + 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(); + + if(enable_velocity_modifier == false) + { + mod = 1.0; + lastpos = 0; + } + + if(enable_velocity_randomiser) + { + float r = (float)rand() / (float)RAND_MAX; // random number: [0;1] + r -= 0.5; // random number [-0.5;0.5] + r *= velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] + level += r; + if(level > 1.0) + { + level = 1.0; + } + + if(level < 0.0) + { + level = 0.0; + } + } + + if(enable_velocity_modifier) + { + mod += (pos - lastpos) / + (samplerate * velocity_modifier_falloff); + if(mod > 1.0) + { + mod = 1.0; + } + } + + if(version >= VersionStr("2.0")) + { + // Version 2.0 + sample = powerlist.get(level * mod); + } + else + { + // Version 1.0 + std::vector s = samples.get(level * mod); + if(s.size() == 0) + { + return NULL; + } + + size_t idx = rand()%(s.size()); + sample = s[idx]; + } + + if(enable_velocity_modifier) + { + lastpos = pos; + mod *= velocity_modifier_weight; + } + + return sample; } void Instrument::addSample(level_t a, level_t b, Sample *s) { - samples.insert(a, b, s); + samples.insert(a, b, s); } void Instrument::finalise() { - if(version >= VersionStr("2.0")) { - std::vector::iterator s = samplelist.begin(); - while(s != samplelist.end()) { - powerlist.add(*s); - s++; - } - - powerlist.finalise(); - } + if(version >= VersionStr("2.0")) + { + std::vector::iterator s = samplelist.begin(); + while(s != samplelist.end()) + { + powerlist.add(*s); + s++; + } + + powerlist.finalise(); + } } std::string Instrument::name() { - return _name; + return _name; } std::string Instrument::description() { - return _description; + return _description; } std::string Instrument::group() { - return _group; + return _group; } void Instrument::setGroup(std::string g) { - _group = 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 e880d8d..549a5a4 100644 --- a/src/instrument.h +++ b/src/instrument.h @@ -36,46 +36,50 @@ #include "sample.h" #include "versionstr.h" +#include "settings.h" + class InstrumentParser; class Instrument { - friend class InstrumentParser; + friend class InstrumentParser; public: - Instrument(); - ~Instrument(); + Instrument(Settings& settings); + ~Instrument(); - Sample *sample(level_t level, size_t pos); + Sample *sample(level_t level, size_t pos); - std::string name(); - std::string description(); - std::string group(); + std::string name(); + std::string description(); + std::string group(); - void setGroup(std::string group); + void setGroup(std::string group); - // std::map channelmap; + // std::map channelmap; - std::vector audiofiles; + std::vector audiofiles; - bool isValid(); + bool isValid(); private: - void *magic; + void *magic; + + std::string _group; + std::string _name; + std::string _description; - std::string _group; - std::string _name; - std::string _description; + VersionStr version; - VersionStr version; + RangeMap samples; + PowerList powerlist; - RangeMap samples; - PowerList powerlist; + void addSample(level_t a, level_t b, Sample *s); + void finalise(); ///< Signal instrument that no more samples will be added. - void addSample(level_t a, level_t b, Sample *s); - void finalise(); ///< Signal instrument that no more samples will be added. + std::vector samplelist; - std::vector samplelist; + size_t lastpos; + float mod; - size_t lastpos; - float mod; + Settings& settings; }; //typedef std::map< std::string, Instrument > Instruments; diff --git a/src/settings.h b/src/settings.h index 74c432d..4eb7dba 100644 --- a/src/settings.h +++ b/src/settings.h @@ -27,14 +27,40 @@ #pragma once #include +#include #include +class MyString { +public: + std::string value; +}; + +//! Engine settings +struct Settings +{ + std::atomic enable_velocity_modifier; + std::atomic velocity_modifier_falloff; + std::atomic velocity_modifier_weight; + + std::atomic enable_velocity_randomiser; + std::atomic velocity_randomiser_weight; + + std::atomic samplerate; + + std::atomic enable_resampling; + + std::atomic number_of_files; + std::atomic number_of_files_loaded; + //std::atomic current_file; + +}; + +//! Getter utility class. template class SettingRef { public: SettingRef(std::atomic& value) - : value{value} - , cache{} + : value(value) { // string isn't lock free either assert((std::is_same::value || value.is_lock_free())); @@ -57,20 +83,7 @@ private: std::atomic cache; }; -struct Settings -{ - std::atomic enable_velocity_modifier; - std::atomic velocity_modifier_falloff; - std::atomic velocity_modifier_weight; - - std::atomic enable_velocity_randomiser; - std::atomic velocity_randomiser_weight; - - std::atomic samplerate; - - std::atomic enable_resampling; -}; - +//! Combined getter class. struct SettingsGetter { SettingRef enable_velocity_modifier; @@ -80,10 +93,14 @@ struct SettingsGetter SettingRef enable_velocity_randomiser; SettingRef velocity_randomiser_weight; - SettingRef samplerate; + SettingRef samplerate; SettingRef enable_resampling; + SettingRef number_of_files; + SettingRef number_of_files_loaded; + //SettingRef current_file; + SettingsGetter(Settings& settings) : enable_velocity_modifier{settings.enable_velocity_modifier} , velocity_modifier_falloff{settings.velocity_modifier_falloff} @@ -92,6 +109,9 @@ struct SettingsGetter , 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} { } }; @@ -99,29 +119,35 @@ struct SettingsGetter // lovely reminder: NO, GLOCKE. NOOOO!! /* enum class IntParams { - Foo = 0 + Foo = 0 }; -struct Settings { - std::array, 5> ints; +struct Settings +{ + std::array, 5> ints; - Settings() - : ints{} { - //get(IntParams::Foo).store(3); - } + Settings() + : ints{} + { + //get(IntParams::Foo).store(3); + } - std::atomic& get(IntParams param) { - return ints[(size_t)param]; - } + std::atomic& get(IntParams param) + { + return ints[(size_t)param]; + } }; -struct SettingsGetter { - std::vector> ints; +struct SettingsGetter +{ + std::vector> 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); + } + } }; */ -- cgit v1.2.3 From 9d49d51a85f86f516427e337e77a60bf8bd8edf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Wed, 23 Mar 2016 22:40:27 +0100 Subject: atomic workaround --- src/atomic.h | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ test/Makefile.am | 7 +++- test/atomictest.cc | 77 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 src/atomic.h create mode 100644 test/atomictest.cc diff --git a/src/atomic.h b/src/atomic.h new file mode 100644 index 0000000..11c87fc --- /dev/null +++ b/src/atomic.h @@ -0,0 +1,105 @@ +/* -*- 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 +#include +#include + +template +class Atomic; + +// use std::atomic if possible +template +class Atomic::value>::type> + : public std::atomic { +}; + +// else work around it using a mutex +template +class Atomic::value>::type> { + public: + using self_type = Atomic::value>::type>; + + Atomic() + : data{} + , mutex{} { + } + + Atomic(T data) + : data{std::move(data)} + , mutex{} { + } + + Atomic(self_type const & other) + : data{} + , mutex{} { + std::lock_guard lock{other.mutex}; + data = other.data; + } + + Atomic(self_type&& other) + : data{} + , mutex{} { + std::lock_guard lock{other.mutex}; + std::swap(data, other.data); + } + + T operator=(T data) { + std::lock_guard 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 lock{mutex}; + this->data = std::move(data); + } + + T load() const { + std::lock_guard lock{mutex}; + return data; + } + + T exchange(T data){ + std::lock_guard lock{mutex}; + std::swap(data, this->data); + return data; + } + + private: + T data; + mutable std::mutex mutex; +}; diff --git a/test/Makefile.am b/test/Makefile.am index 6e56043..4209991 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 + memchecker atomictest check_PROGRAMS = $(TESTS) @@ -128,5 +128,10 @@ memchecker_SOURCES = \ test.cc \ memcheckertest.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 + EXTRA_DIST = \ lv2_test_host.h diff --git a/test/atomictest.cc b/test/atomictest.cc new file mode 100644 index 0000000..d4cacf0 --- /dev/null +++ b/test/atomictest.cc @@ -0,0 +1,77 @@ +/* -*- 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 + +#include + +class AtomicTest + : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(AtomicTest); + CPPUNIT_TEST(atomicIntUsesStandardImpl); + CPPUNIT_TEST(atomicFloatUsesStandardImpl); + CPPUNIT_TEST(atomicBoolUsesStandardImpl); + CPPUNIT_TEST(atomicStringCanBeUsed); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() {} + void tearDown() {} + + void atomicIntUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicFloatUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicBoolUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicDoubleUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicStringCanBeUsed() { + // note: if it couldn't be used, the compiler would complain + Atomic tmp; + } + + // todo: further testing + + private: + template + bool isUsingStandardImpl() { + return std::is_base_of, Atomic>::value; + } +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AtomicTest); + -- cgit v1.2.3 From e584e1b0343542e08ba834307dab8aa3a745d0cf Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 23:02:09 +0100 Subject: Fix tests. --- test/engine.cc | 3 ++- test/memcheckertest.cc | 13 +++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) 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 3a02372..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,8 +71,8 @@ public: void small_drumkit() { // load the small kit - DrumKitParser parser(small_kit_path, kit); - CPPUNIT_ASSERT(!parser.parse()); + DrumKitParser parser(settings, kit); + CPPUNIT_ASSERT(!parser.parseFile(small_kit_path)); // check if the memchecker thinks it fits into memory CPPUNIT_ASSERT(enoughFreeMemory(kit)); @@ -80,8 +81,8 @@ public: void huge_drumkit() { // load the huge kit - DrumKitParser parser(huge_kit_path, kit); - CPPUNIT_ASSERT(!parser.parse()); + DrumKitParser parser(settings, kit); + CPPUNIT_ASSERT(!parser.parseFile(huge_kit_path)); // check if the memchecker thinks it doesn't fit into memory CPPUNIT_ASSERT(!enoughFreeMemory(kit)); @@ -94,8 +95,8 @@ public: CPPUNIT_ASSERT_EQUAL(bytes_per_channel, calcBytesPerChannel(audiofile)); // load the huge kit - DrumKitParser parser(huge_kit_path, kit); - CPPUNIT_ASSERT(!parser.parse()); + DrumKitParser parser(settings, kit); + CPPUNIT_ASSERT(!parser.parseFile(huge_kit_path)); // check if the protected method of the memchecker reports the correct size uint64_t needed_memory = 71478290000; -- cgit v1.2.3 From 8d2dd0685e130b1e6ad479b30fd3e96581763e60 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 23:02:35 +0100 Subject: Use new Atomic class. --- src/atomic.h | 6 +++--- src/settings.h | 35 ++++++++++++++++------------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/atomic.h b/src/atomic.h index 11c87fc..f800f68 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -35,15 +35,15 @@ class Atomic; // use std::atomic if possible template -class Atomic::value>::type> +class Atomic::value>::type> : public std::atomic { }; // else work around it using a mutex template -class Atomic::value>::type> { +class Atomic::value>::type> { public: - using self_type = Atomic::value>::type>; + using self_type = Atomic::value>::type>; Atomic() : data{} diff --git a/src/settings.h b/src/settings.h index 4eb7dba..eb18909 100644 --- a/src/settings.h +++ b/src/settings.h @@ -30,28 +30,25 @@ #include #include -class MyString { -public: - std::string value; -}; +#include "atomic.h" //! Engine settings struct Settings { - std::atomic enable_velocity_modifier; - std::atomic velocity_modifier_falloff; - std::atomic velocity_modifier_weight; + Atomic enable_velocity_modifier; + Atomic velocity_modifier_falloff; + Atomic velocity_modifier_weight; - std::atomic enable_velocity_randomiser; - std::atomic velocity_randomiser_weight; + Atomic enable_velocity_randomiser; + Atomic velocity_randomiser_weight; - std::atomic samplerate; + Atomic samplerate; - std::atomic enable_resampling; + Atomic enable_resampling; - std::atomic number_of_files; - std::atomic number_of_files_loaded; - //std::atomic current_file; + Atomic number_of_files; + Atomic number_of_files_loaded; + Atomic current_file; }; @@ -59,7 +56,7 @@ struct Settings template class SettingRef { public: - SettingRef(std::atomic& value) + SettingRef(Atomic& value) : value(value) { // string isn't lock free either @@ -79,8 +76,8 @@ public: } private: - std::atomic& value; - std::atomic cache; + Atomic& value; + Atomic cache; }; //! Combined getter class. @@ -99,7 +96,7 @@ struct SettingsGetter SettingRef number_of_files; SettingRef number_of_files_loaded; - //SettingRef current_file; + SettingRef current_file; SettingsGetter(Settings& settings) : enable_velocity_modifier{settings.enable_velocity_modifier} @@ -111,7 +108,7 @@ struct SettingsGetter , 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} + , current_file{settings.current_file} { } }; -- cgit v1.2.3 From bd6bee9faac81dc9d0ed44a7d6329d4acdfdfc00 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 30 Mar 2016 10:09:34 +0200 Subject: Update ChangeLog with 0.9.10 release --- ChangeLog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8e8afe5..10a2b28 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 -- cgit v1.2.3 From 357bfe71e62970752bf32029f506b2e96967b1d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 08:10:44 +0200 Subject: Fixed API of class Atomic for POD --- src/atomic.h | 5 +++++ test/atomictest.cc | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/atomic.h b/src/atomic.h index f800f68..1b92257 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -37,6 +37,11 @@ class Atomic; template class Atomic::value>::type> : public std::atomic { + + public: + // inherit methods + using std::atomic::atomic; + using std::atomic::operator=; }; // else work around it using a mutex diff --git a/test/atomictest.cc b/test/atomictest.cc index d4cacf0..d73695e 100644 --- a/test/atomictest.cc +++ b/test/atomictest.cc @@ -36,6 +36,12 @@ class AtomicTest CPPUNIT_TEST(atomicFloatUsesStandardImpl); CPPUNIT_TEST(atomicBoolUsesStandardImpl); CPPUNIT_TEST(atomicStringCanBeUsed); + CPPUNIT_TEST(podAtomicCanBeDefaultInitialized); + CPPUNIT_TEST(nonPodAtomicCanBeDefaultInitialized); + CPPUNIT_TEST(podAtomicCanBeValueInitialized); + CPPUNIT_TEST(nonPodAtomicCanBeValueInitialized); + CPPUNIT_TEST(podAtomicCanBeValueAssigned); + CPPUNIT_TEST(nonPodAtomicCanBeValueAssigned); CPPUNIT_TEST_SUITE_END(); public: @@ -63,6 +69,38 @@ class AtomicTest Atomic tmp; } + void podAtomicCanBeDefaultInitialized() { + Atomic i; + // note: i is initialized with garbage + } + + void nonPodAtomicCanBeDefaultInitialized() { + Atomic s; + CPPUNIT_ASSERT_EQUAL(s.load(), std::string{}); + } + + void podAtomicCanBeValueInitialized() { + Atomic i{5}; + CPPUNIT_ASSERT_EQUAL(i.load(), 5); + } + + void nonPodAtomicCanBeValueInitialized() { + Atomic s{"hello world"}; + CPPUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"}); + } + + void podAtomicCanBeValueAssigned() { + Atomic i; + i = 5; + CPPUNIT_ASSERT_EQUAL(i.load(), 5); + } + + void nonPodAtomicCanBeValueAssigned() { + Atomic s; + s = "hello world"; + CPPUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"}); + } + // todo: further testing private: -- cgit v1.2.3 From 7cbf182eb1f99997915fe203a24b97aa22e5be70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 08:29:09 +0200 Subject: Added Atomic Tests about being lock free --- test/atomictest.cc | 56 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/test/atomictest.cc b/test/atomictest.cc index d73695e..1718b33 100644 --- a/test/atomictest.cc +++ b/test/atomictest.cc @@ -32,41 +32,38 @@ class AtomicTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(AtomicTest); - CPPUNIT_TEST(atomicIntUsesStandardImpl); - CPPUNIT_TEST(atomicFloatUsesStandardImpl); - CPPUNIT_TEST(atomicBoolUsesStandardImpl); - CPPUNIT_TEST(atomicStringCanBeUsed); + 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 atomicIntUsesStandardImpl() { + void podAtomicsUseStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); CPPUNIT_ASSERT(isUsingStandardImpl()); - } - - void atomicFloatUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); CPPUNIT_ASSERT(isUsingStandardImpl()); - } - - void atomicBoolUsesStandardImpl() { - CPPUNIT_ASSERT(isUsingStandardImpl()); - } - - void atomicDoubleUsesStandardImpl() { CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); } - void atomicStringCanBeUsed() { - // note: if it couldn't be used, the compiler would complain - Atomic tmp; + void nonPodAtomicsUseOwnImpl() { + CPPUNIT_ASSERT(!isUsingStandardImpl()); } void podAtomicCanBeDefaultInitialized() { @@ -101,6 +98,23 @@ class AtomicTest CPPUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"}); } + void podAtomicsAreLockFree() { + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + + // compile error: undefined reference to `__atomic_is_lock_free' + //CPPUNIT_ASSERT(isLockFree()); + } + // todo: further testing private: @@ -108,6 +122,12 @@ class AtomicTest bool isUsingStandardImpl() { return std::is_base_of, Atomic>::value; } + + template + bool isLockFree() { + Atomic a; + return a.is_lock_free(); + } }; // Registers the fixture into the 'registry' -- cgit v1.2.3 From e526594e983659858ce55027cdd06489cdf8af57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:09:40 +0200 Subject: Added API for accessing structs in a thread-safe way --- src/syncedsettings.h | 112 ++++++++++++++++++++++++++++++++ test/Makefile.am | 7 +- test/syncedsettings.cc | 173 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 src/syncedsettings.h create mode 100644 test/syncedsettings.cc diff --git a/src/syncedsettings.h b/src/syncedsettings.h new file mode 100644 index 0000000..f83847c --- /dev/null +++ b/src/syncedsettings.h @@ -0,0 +1,112 @@ +/* -*- 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 + +// type trait helper + +template +struct pack_contains; + +template +struct pack_contains + : std::true_type { +}; + +template +struct pack_contains + : pack_contains { +}; + +template +struct pack_contains + : std::false_type { +}; + +// -------------------------------------------------------------------- + +template +class Group; + +template +class Accessor { + private: + std::lock_guard lock; + + public: + Accessor(Group& parent) + : lock{parent.mutex} + , data{parent.data} { + } + + T& data; +}; + +template +class Group { + private: + friend class Accessor; + + mutable std::mutex mutex; + T data; + + public: + Group() + : mutex{} + , data{} { + } + + Group(T const & data) + : mutex{} + , data{data} { + } + + Group(T&& data) + : mutex{} + , data{std::move(data)} { + } + + Group(Group const & other) + : mutex{} + , data{} { + std::lock_guard lock{other.mutex}; + data = other.data; + } + + Group(Group&& other) + : mutex{} + , data{} { + std::lock_guard lock{other.mutex}; + std::swap(data, other.data); + } + + operator T() const { + std::lock_guard lock{mutex}; + return data; + } +}; diff --git a/test/Makefile.am b/test/Makefile.am index 4209991..47fa026 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 atomictest + memchecker atomictest syncedsettingstest check_PROGRAMS = $(TESTS) @@ -133,5 +133,10 @@ atomictest_CXXFLAGS = -DOUTPUT=\"atomictest\" $(CPPUNIT_CFLAGS) \ 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/syncedsettings.cc b/test/syncedsettings.cc new file mode 100644 index 0000000..a04c870 --- /dev/null +++ b/test/syncedsettings.cc @@ -0,0 +1,173 @@ +/* -*- 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 + +#include + +class SyncedSettingsTest + : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(SyncedSettingsTest); + CPPUNIT_TEST(groupCanBeDefaultInitialized); + CPPUNIT_TEST(groupDataCanBeCopied); + CPPUNIT_TEST(groupCanBeCreatedByReference); + CPPUNIT_TEST(groupCanBeCreatedByRvalueReference); + + CPPUNIT_TEST(accessorCanGetFields); + CPPUNIT_TEST(accessorCanSetFields); + + CPPUNIT_TEST(groupHasCopyCtor); + CPPUNIT_TEST(groupHasMoveCtor); + CPPUNIT_TEST(groupHasCopyAssignOp); + CPPUNIT_TEST(groupHasMoveAssignOp); + CPPUNIT_TEST_SUITE_END(); + + private: + struct TestData { + float foo; + bool bar; + std::string msg; + }; + + public: + void setUp() {} + void tearDown() {} + + void groupCanBeDefaultInitialized() { + Group data; + } + + void groupDataCanBeCopied() { + Group data; + (TestData)data; // copies + } + + void groupCanBeCreatedByReference() { + TestData tmp{3.f, false, "hello"}; + Group 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 groupCanBeCreatedByRvalueReference() { + TestData tmp{3.f, false, "hello"}; + Group 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 accessorCanGetFields() { + TestData tmp{3.f, false, "hello"}; + Group data{tmp}; + Accessor 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 accessorCanSetFields() { + Group data; + Accessor 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 groupHasCopyCtor() { + Group tmp; + { + Accessor a{tmp}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + Group 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 tmp; + { + Accessor a{tmp}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + Group 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 tmp; + { + Accessor a{tmp}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + Group 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 tmp; + { + Accessor a{tmp}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + Group 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"}); + } + + // todo: further testing +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(SyncedSettingsTest); + -- cgit v1.2.3 From fb944022b0e727007420d30ff84d28974fb5f38e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:12:20 +0200 Subject: Cleanup on Synced Settings Header --- src/syncedsettings.h | 128 ++++++++++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 72 deletions(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index f83847c..eb8e66e 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -28,85 +28,69 @@ #include -// type trait helper +template class Group; -template -struct pack_contains; +template class Accessor +{ +private: + std::lock_guard lock; -template -struct pack_contains - : std::true_type { -}; +public: + Accessor(Group& parent) + : lock{parent.mutex} + , data{parent.data} + { + } -template -struct pack_contains - : pack_contains { + T& data; }; -template -struct pack_contains - : std::false_type { -}; +template class Group +{ +private: + friend class Accessor; -// -------------------------------------------------------------------- + mutable std::mutex mutex; + T data; -template -class Group; +public: + Group() + : mutex{} + , data{} + { + } -template -class Accessor { - private: - std::lock_guard lock; - - public: - Accessor(Group& parent) - : lock{parent.mutex} - , data{parent.data} { - } - - T& data; -}; + Group(T const& data) + : mutex{} + , data{data} + { + } + + Group(T&& data) + : mutex{} + , data{std::move(data)} + { + } + + Group(Group const& other) + : mutex{} + , data{} + { + std::lock_guard lock{other.mutex}; + data = other.data; + } + + Group(Group&& other) + : mutex{} + , data{} + { + std::lock_guard lock{other.mutex}; + std::swap(data, other.data); + } -template -class Group { - private: - friend class Accessor; - - mutable std::mutex mutex; - T data; - - public: - Group() - : mutex{} - , data{} { - } - - Group(T const & data) - : mutex{} - , data{data} { - } - - Group(T&& data) - : mutex{} - , data{std::move(data)} { - } - - Group(Group const & other) - : mutex{} - , data{} { - std::lock_guard lock{other.mutex}; - data = other.data; - } - - Group(Group&& other) - : mutex{} - , data{} { - std::lock_guard lock{other.mutex}; - std::swap(data, other.data); - } - - operator T() const { - std::lock_guard lock{mutex}; - return data; - } + operator T() const + { + std::lock_guard lock{mutex}; + return data; + } }; -- cgit v1.2.3 From 94961f8134c85981df467c70ee65a599f87a0bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:15:37 +0200 Subject: Added thread-safety to implicit cpy/mv assign op for synced group settings --- src/syncedsettings.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index eb8e66e..e60eb78 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -76,6 +76,7 @@ public: : mutex{} , data{} { + std::lock_guard lock{mutex}; std::lock_guard lock{other.mutex}; data = other.data; } @@ -84,6 +85,7 @@ public: : mutex{} , data{} { + std::lock_guard lock{mutex}; std::lock_guard lock{other.mutex}; std::swap(data, other.data); } -- cgit v1.2.3 From 6489719f4bf6f1f65af706986d3878c6fb3080b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:21:18 +0200 Subject: Added explicit cpy/mv assign operators to be sure about thread-safety of Group --- src/syncedsettings.h | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index e60eb78..4991627 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -76,7 +76,6 @@ public: : mutex{} , data{} { - std::lock_guard lock{mutex}; std::lock_guard lock{other.mutex}; data = other.data; } @@ -85,11 +84,32 @@ public: : mutex{} , data{} { - std::lock_guard lock{mutex}; std::lock_guard lock{other.mutex}; std::swap(data, other.data); } + Group& operator=(const Group& other) + { + if (*this != &other) + { + std::lock_guard lock{mutex}; + std::lock_guard lock{other.mutex}; + data = other.data; + } + return *this; + } + + Group& operator=(Group&& other) + { + if (*this != &other) + { + std::lock_guard lock{mutex}; + std::lock_guard lock{other.mutex}; + std::swap(data, tmp.data); + } + return *this; + } + operator T() const { std::lock_guard lock{mutex}; -- cgit v1.2.3 From 3539ba7cb47aedf8433d91890dbbc59a9ca1a201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:22:19 +0200 Subject: Fixed my dumb fail --- src/syncedsettings.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index 4991627..b72229e 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -93,7 +93,7 @@ public: if (*this != &other) { std::lock_guard lock{mutex}; - std::lock_guard lock{other.mutex}; + std::lock_guard lock2{other.mutex}; data = other.data; } return *this; @@ -104,8 +104,8 @@ public: if (*this != &other) { std::lock_guard lock{mutex}; - std::lock_guard lock{other.mutex}; - std::swap(data, tmp.data); + std::lock_guard lock2{other.mutex}; + std::swap(data, other.data); } return *this; } -- cgit v1.2.3 From ad3e2c966872d14ce3d4add2fc8588cfc1ca1e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:40:02 +0200 Subject: Removed unused features and fixed tests --- src/syncedsettings.h | 12 ------ test/syncedsettings.cc | 109 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 76 insertions(+), 45 deletions(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index b72229e..aa43cc0 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -60,18 +60,6 @@ public: { } - Group(T const& data) - : mutex{} - , data{data} - { - } - - Group(T&& data) - : mutex{} - , data{std::move(data)} - { - } - Group(Group const& other) : mutex{} , data{} diff --git a/test/syncedsettings.cc b/test/syncedsettings.cc index a04c870..7de7c42 100644 --- a/test/syncedsettings.cc +++ b/test/syncedsettings.cc @@ -34,8 +34,6 @@ class SyncedSettingsTest CPPUNIT_TEST_SUITE(SyncedSettingsTest); CPPUNIT_TEST(groupCanBeDefaultInitialized); CPPUNIT_TEST(groupDataCanBeCopied); - CPPUNIT_TEST(groupCanBeCreatedByReference); - CPPUNIT_TEST(groupCanBeCreatedByRvalueReference); CPPUNIT_TEST(accessorCanGetFields); CPPUNIT_TEST(accessorCanSetFields); @@ -44,6 +42,8 @@ class SyncedSettingsTest CPPUNIT_TEST(groupHasMoveCtor); CPPUNIT_TEST(groupHasCopyAssignOp); CPPUNIT_TEST(groupHasMoveAssignOp); + + CPPUNIT_TEST(mimicRealUse); CPPUNIT_TEST_SUITE_END(); private: @@ -66,18 +66,14 @@ class SyncedSettingsTest (TestData)data; // copies } - void groupCanBeCreatedByReference() { - TestData tmp{3.f, false, "hello"}; - Group 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 groupCanBeCreatedByRvalueReference() { - TestData tmp{3.f, false, "hello"}; - Group data{std::move(tmp)}; + void accessorCanSetFields() { + Group data; + { + Accessor 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); @@ -85,26 +81,22 @@ class SyncedSettingsTest } void accessorCanGetFields() { - TestData tmp{3.f, false, "hello"}; - Group data{tmp}; - Accessor 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 accessorCanSetFields() { Group data; - Accessor 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"}); + { + Accessor a{data}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + // now read + { + Accessor 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 tmp; { @@ -165,7 +157,58 @@ class SyncedSettingsTest CPPUNIT_ASSERT_EQUAL(copy.msg, std::string{"hello"}); } - // todo: further testing + void mimicRealUse() { + struct Settings { + struct Foo { + int a, b; + bool enabled; + }; + struct Bar { + float a, b; + bool enabled; + }; + struct Idk { + std::string label; + float bla; + }; + + Group foo; + Group bar; + Group idk; + }; + + Settings s; + + // set some settings + { + Accessor tmp{s.foo}; + tmp.data.enabled = true; + tmp.data.a = 3; + } + { + Accessor tmp{s.bar}; + tmp.data.enabled = false; + tmp.data.a = 0.f; + tmp.data.b = 0.f; + } + { + Accessor tmp{s.idk}; + tmp.data.label = "hello world"; + tmp.data.bla = 3.14f; + } + + // read some settings + { + Accessor tmp{s.foo}; + if (tmp.data.enabled) { + // do some while locked + } + } + Settings::Bar copy = s.bar; + if (copy.enabled) { + // do some stuff without locking + } + } }; // Registers the fixture into the 'registry' -- cgit v1.2.3 From 2b45e54322086d97b26e1443d34b8a59dc76f8f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:44:08 +0200 Subject: Improved mimicRealUse() test case --- test/syncedsettings.cc | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/test/syncedsettings.cc b/test/syncedsettings.cc index 7de7c42..62bd8c6 100644 --- a/test/syncedsettings.cc +++ b/test/syncedsettings.cc @@ -160,54 +160,41 @@ class SyncedSettingsTest void mimicRealUse() { struct Settings { struct Foo { - int a, b; - bool enabled; + float a{5}; + float b{3}; + bool enabled{true}; }; struct Bar { - float a, b; - bool enabled; - }; - struct Idk { - std::string label; - float bla; + std::string label{"empty"}; + float bla{0.f}; }; Group foo; Group bar; - Group idk; }; Settings s; - // set some settings - { - Accessor tmp{s.foo}; - tmp.data.enabled = true; - tmp.data.a = 3; - } + // set bar settings { Accessor tmp{s.bar}; - tmp.data.enabled = false; - tmp.data.a = 0.f; - tmp.data.b = 0.f; - } - { - Accessor tmp{s.idk}; tmp.data.label = "hello world"; tmp.data.bla = 3.14f; } - // read some settings + // read foo settings { Accessor tmp{s.foo}; if (tmp.data.enabled) { // do some while locked } } - Settings::Bar copy = s.bar; + // or: + Settings::Foo copy = s.foo; if (copy.enabled) { // do some stuff without locking } + CPPUNIT_ASSERT(copy.enabled); } }; -- cgit v1.2.3 From dcc4cb2be50b6f740d25323ae45b3a462e8445da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:53:04 +0200 Subject: Workaround outdated compiler version --- src/syncedsettings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index aa43cc0..0fe5efd 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -38,7 +38,7 @@ private: public: Accessor(Group& parent) : lock{parent.mutex} - , data{parent.data} + , data(parent.data) { } -- cgit v1.2.3 From 2cf2ec7150615148e9955c80661e2aed4d0bd2ad Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 14:51:36 +0200 Subject: Fix compilation on windows. --- src/atomic.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/atomic.h b/src/atomic.h index 1b92257..ed6fa39 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -28,7 +28,8 @@ #include #include -#include + +#include "mutex.h" template class Atomic; -- cgit v1.2.3 From dc0ebec8d3f83f06ba0351de061ef22b1393de70 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 15:12:37 +0200 Subject: Fix mutex include issue. --- src/atomic.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/atomic.h b/src/atomic.h index ed6fa39..84ef949 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -29,6 +29,7 @@ #include #include +#include #include "mutex.h" template -- cgit v1.2.3 From 3b239bdd5362b2a9db73f5f7254e14b6fe7ed858 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 15:21:28 +0200 Subject: Fix missing include on windows. --- plugingui/testmain.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc index 8282bc8..b3a0d8d 100644 --- a/plugingui/testmain.cc +++ b/plugingui/testmain.cc @@ -26,6 +26,11 @@ */ #include "plugingui.h" +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + #include // Dummy Engine class. -- cgit v1.2.3 From d172d756cfcdfbde5c6b8c6d25a51f58624739e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Tue, 22 Mar 2016 00:40:15 +0100 Subject: Parser refactoring. * Use new style * Update to C++11 * Use more std::string than char* --- src/drumkitparser.cc | 6 +++--- src/instrumentparser.cc | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 3ba69c8..a538996 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -36,7 +36,7 @@ DrumKitParser::DrumKitParser(DrumKit& kit) : kit(kit) - , refs(REFSFILE) + , refs(REFSFILE) { } @@ -101,7 +101,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 +112,7 @@ void DrumKitParser::startTag(const std::string& name, const attr_t& attr) if(name == "channels") { - + } if(name == "channel") diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc index 268f8f3..8bcb7a0 100644 --- a/src/instrumentparser.cc +++ b/src/instrumentparser.cc @@ -71,7 +71,7 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr) { ERR(instrparser, "Error parsing version number: %s, using 1.0\n", err); instrument.version = VersionStr(1,0,0); - } + } } else { @@ -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 { -- cgit v1.2.3 From 45521d593560b120d406acfb9926697e7ad5e423 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 21:57:41 +0100 Subject: More cleanup. --- src/drumkit.cc | 24 +++--------------- src/drumkit.h | 1 - src/drumkitparser.cc | 30 +++++++++++++--------- src/instrumentparser.cc | 56 ++++++++++++++++++++++------------------- src/instrumentparser.h | 2 +- src/midimapparser.cc | 3 ++- src/midimapparser.h | 2 -- src/path.cc | 18 ++++++++------ src/path.h | 1 + src/sample.cc | 21 ---------------- src/sample.h | 11 --------- src/saxparser.cc | 66 +++++++++++++++++++++++++++---------------------- src/saxparser.h | 19 ++++++++------ 13 files changed, 113 insertions(+), 141 deletions(-) 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..a6913c0 100644 --- a/src/drumkit.h +++ b/src/drumkit.h @@ -33,7 +33,6 @@ #include "instrument.h" #include "versionstr.h" -class DrumKitParser; class DrumKit { friend class DrumKitParser; diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index a538996..c727590 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -46,9 +46,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 @@ -59,7 +59,8 @@ int DrumKitParser::parseFile(const std::string& filename) path = getPath(edited_filename); auto result = SAXParser::parseFile(filename); - if (result == 0) { + if(result == 0) + { kit._file = edited_filename; } @@ -140,6 +141,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 +182,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(); + 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::iterator ic = parser.channellist.begin(); @@ -206,16 +210,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()); } - 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/instrumentparser.cc b/src/instrumentparser.cc index 8bcb7a0..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,10 +64,11 @@ 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); @@ -82,7 +83,6 @@ void InstrumentParser::startTag(const std::string& name, const attr_t& attr) if(name == "samples") { - } if(name == "sample") @@ -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::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/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 - #include "saxparser.h" #include "midimapper.h" diff --git a/src/path.cc b/src/path.cc index 43c64f0..c2e7910 100644 --- a/src/path.cc +++ b/src/path.cc @@ -35,17 +35,19 @@ std::string getPath(const std::string& file) { - std::string p; -#ifndef __MINGW32__ - char *b = strdup(file.c_str()); - p = dirname(b); - free(b); -#else + std::string path; + +#ifdef __MINGW32__ char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; _splitpath(file.c_str(), drive, dir, NULL, NULL); - p = std::string(drive) + dir; + path = std::string(drive) + dir; +#else + // POSIX + char* buffer = strdup(file.c_str()); + path = dirname(buffer); + free(buffer); #endif - return p; + return path; } diff --git a/src/path.h b/src/path.h index 7189cea..50ff842 100644 --- a/src/path.h +++ b/src/path.h @@ -28,4 +28,5 @@ #include +//! \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..a3400a4 100644 --- a/src/sample.h +++ b/src/sample.h @@ -34,7 +34,6 @@ typedef std::map AudioFiles; -class InstrumentParser; class Sample { friend class InstrumentParser; @@ -53,13 +52,3 @@ private: float power; AudioFiles audiofiles; }; - -/* - * - * - * - * - * - * - * - */ 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 -#include #include #include +#include + 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 #include -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; @@ -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); }; -- cgit v1.2.3 From 87e14b57d197a7e917ad55250f132fd50df3ccdc Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 22:16:20 +0100 Subject: Fix drumkit file by reference. --- src/drumkitparser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index c727590..ab2cb45 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -57,7 +57,7 @@ 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) { -- cgit v1.2.3 From c2997b9b1a5b831e76b1779aa957f2312a6e5089 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 22:38:44 +0100 Subject: Settings. --- drumgizmo/drumgizmoc.cc | 3 +- plugin/drumgizmo_plugin.cc | 2 +- plugin/drumgizmo_plugin.h | 2 + plugingui/dgwindow.cc | 31 ++++++++------- plugingui/dgwindow.h | 7 +++- plugingui/plugingui.cc | 90 +++++++++++++++++++++++++++++++++++++++++++- plugingui/plugingui.h | 24 +++++++++--- src/drumgizmo.cc | 10 +++-- src/drumgizmo.h | 8 +++- src/drumkitloader.cc | 16 +++++--- src/drumkitloader.h | 4 +- src/drumkitparser.cc | 7 ++-- src/drumkitparser.h | 3 +- src/instrument.cc | 76 +++++++++++++------------------------ src/instrument.h | 7 +++- src/settings.h | 94 +++++++++++++++++++++++++++++----------------- 16 files changed, 259 insertions(+), 125 deletions(-) diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 24d16e8..357877d 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -372,7 +372,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()); diff --git a/plugin/drumgizmo_plugin.cc b/plugin/drumgizmo_plugin.cc index b8f8822..24cfb9a 100644 --- a/plugin/drumgizmo_plugin.cc +++ b/plugin/drumgizmo_plugin.cc @@ -59,7 +59,7 @@ DrumGizmoPlugin::DrumGizmoPlugin() { init(); - drumgizmo = std::make_shared(&output, &input); + drumgizmo = std::make_shared(settings, &output, &input); resizeWindow(370, 330); drumgizmo->setFreeWheel(true); drumgizmo->setSamplerate(44100); 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* output_samples{nullptr}; + Settings settings; + std::shared_ptr plugin_gui; std::shared_ptr drumgizmo; }; diff --git a/plugingui/dgwindow.cc b/plugingui/dgwindow.cc index 86a985d..25cbdf0 100644 --- a/plugingui/dgwindow.cc +++ b/plugingui/dgwindow.cc @@ -120,10 +120,11 @@ public: }; DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, - Config& config) + Config& config, Settings& settings) : Window(native_window) , messageHandler(messageHandler) , config(config) + , settings(settings) { int vlineSpacing = 16; @@ -233,11 +234,12 @@ void DGWindow::repaintEvent(RepaintEvent* repaintEvent) void DGWindow::attackValueChanged(float value) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, - value); + //ChangeSettingMessage *msg = + // new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, + // value); + //messageHandler.sendMessage(MSGRCV_ENGINE, msg); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.velocity_modifier_weight.store(value); #ifdef STANDALONE int i = value * 4; @@ -253,10 +255,12 @@ void DGWindow::attackValueChanged(float value) void DGWindow::falloffValueChanged(float value) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, - value); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + //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); @@ -265,10 +269,11 @@ void DGWindow::falloffValueChanged(float value) void DGWindow::velocityCheckClick(bool checked) { - ChangeSettingMessage *msg = - new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, - checked); - messageHandler.sendMessage(MSGRCV_ENGINE, msg); +// ChangeSettingMessage *msg = +// new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, +// checked); +// messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.enable_velocity_modifier.store(checked); } void DGWindow::kitBrowseClick() diff --git a/plugingui/dgwindow.h b/plugingui/dgwindow.h index 605e87a..c4fbeab 100644 --- a/plugingui/dgwindow.h +++ b/plugingui/dgwindow.h @@ -37,6 +37,8 @@ #include "filebrowser.h" #include "layout.h" +#include + class MessageHandler; namespace GUI { @@ -47,7 +49,8 @@ class File; class DGWindow : public Window { public: - DGWindow(void* native_window, MessageHandler& messageHandler, Config& config); + DGWindow(void* native_window, MessageHandler& messageHandler, Config& config, + Settings& settings); Header* header; @@ -85,6 +88,8 @@ private: Image back{":bg.png"}; Image logo{":logo.png"}; + + Settings& settings; }; } // GUI:: diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index e34c471..9bac007 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -31,6 +31,8 @@ #include "pluginconfig.h" #include "messagehandler.h" +#include + namespace GUI { PluginGUI::PluginGUI(void* native_window) @@ -116,7 +118,68 @@ bool PluginGUI::processEvents() } window->eventHandler()->processEvents(); - handleMessages(); + //handleMessages(); + + static bool foo = false; + static int t = 0; + if(t != time(nullptr)) + { + t = time(nullptr); + foo = !foo; + float v = settings.velocity_modifier_falloff.load(); + v += 0.1f; + settings.velocity_modifier_falloff.store(v); + } + + Painter p(*window); + + // Run through all settings one at a time propagate changes to the UI. + if(getter.enable_velocity_modifier.hasChanged()) + { + enable_velocity_modifier_notifier(getter.enable_velocity_modifier.getValue()); + } + + if(getter.velocity_modifier_falloff.hasChanged()) + { + velocity_modifier_falloff_notifier(getter.velocity_modifier_falloff.getValue()); + } + + if(getter.velocity_modifier_weight.hasChanged()) + { + velocity_modifier_weight_notifier(getter.velocity_modifier_weight.getValue()); + } + + if(getter.enable_velocity_randomiser.hasChanged()) + { + enable_velocity_randomiser_notifier(getter.enable_velocity_randomiser.getValue()); + } + + if(getter.velocity_randomiser_weight.hasChanged()) + { + velocity_randomiser_weight_notifier(getter.velocity_randomiser_weight.getValue()); + } + + if(getter.samplerate.hasChanged()) + { + samplerate_notifier(getter.samplerate.getValue()); + } + + if(getter.enable_resampling.hasChanged()) + { + enable_resampling_notifier(getter.enable_resampling.getValue()); + } + + if(getter.number_of_files.hasChanged() || + getter.number_of_files_loaded.hasChanged()) + { + drumkit_file_progress_notifier((float)getter.number_of_files_loaded.getValue() / + (float)getter.number_of_files.getValue()); + } + + //if(getter.current_file.hasChanged()) + //{ + // current_file_notifier(getter.current_file.getValue()); + //} if(closing) { @@ -135,7 +198,30 @@ void PluginGUI::init() config = new Config(); config->load(); - window = new DGWindow(native_window, msghandler, *config); + window = new DGWindow(native_window, msghandler, *config, settings); + + CONNECT(this, enable_velocity_modifier_notifier, + window->velocityCheck, &CheckBox::setChecked); + + CONNECT(this, velocity_modifier_falloff_notifier, + window->falloffKnob, &Knob::setValue); + CONNECT(this, velocity_modifier_weight_notifier, + window->attackKnob, &Knob::setValue); + + + //CONNECT(this, enable_velocity_randomiser_notifier, + // window->velocityCheck, &CheckBox::setChecked); + //CONNECT(this, velocity_randomiser_weight_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + //CONNECT(this, samplerate_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + //CONNECT(this, enable_resampling_notifier, + // window->velocityCheck, &CheckBox::setChecked); + + CONNECT(this, drumkit_file_progress_notifier, + window->drumkitFileProgress, &ProgressBar::setProgress); auto eventHandler = window->eventHandler(); CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler); diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index f441696..ca31c41 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -31,9 +31,7 @@ #include "pluginconfig.h" - -#include "thread.h" -#include "semaphore.h" +#include #include "messagereceiver.h" #include "notifier.h" @@ -68,6 +66,21 @@ public: Notifier<> closeNotifier; + // Setting notifiers: + Notifier enable_velocity_modifier_notifier; + Notifier velocity_modifier_falloff_notifier; + Notifier velocity_modifier_weight_notifier; + + Notifier enable_velocity_randomiser_notifier; + Notifier velocity_randomiser_weight_notifier; + + Notifier samplerate_notifier; + + Notifier enable_resampling_notifier; + + Notifier drumkit_file_progress_notifier; + //Notifier current_file_notifier; + // Support old interface a little while longer.. void setWindowClosedCallback(void (*handler)(void*), void* ptr); @@ -80,11 +93,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; + SettingsGetter getter{settings}; }; } // GUI:: diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 853e93d..4109249 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -46,18 +46,20 @@ #include "nolocale.h" -DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i) +DrumGizmo::DrumGizmo(Settings& settings, + AudioOutputEngine *o, AudioInputEngine *i) : MessageReceiver(MSGRCV_ENGINE) - , loader() + , loader(settings) , oe(o) , ie(i) , framesize(0) , freewheel(false) , events{} + , settings(settings) { is_stopping = false; audioCache.init(10000); // start thread - + events.reserve(1000); } @@ -81,7 +83,7 @@ bool DrumGizmo::loadkit(std::string file) // Delete all Channels, Instruments, Samples and AudioFiles. kit.clear(); - DrumKitParser parser(kit); + DrumKitParser parser(settings, kit); if(parser.parseFile(file)) { ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 632d5fc..63348da 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -50,6 +50,8 @@ #include "configfile.h" +#include "settings.h" + #define MAX_NUM_CHANNELS 64 #define REFSFILE "refs.conf" #define RESAMPLER_INPUT_BUFFER 64 @@ -58,7 +60,8 @@ class DrumGizmo : public MessageReceiver { public: - DrumGizmo(AudioOutputEngine *outputengine, AudioInputEngine *inputengine); + DrumGizmo(Settings& settings, + AudioOutputEngine *outputengine, AudioInputEngine *inputengine); virtual ~DrumGizmo(); bool loadkit(std::string kitfile); @@ -106,6 +109,7 @@ protected: size_t framesize; bool freewheel; - + std::vector events; + Settings& settings; }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index ff489ea..3cb4b68 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -31,9 +31,10 @@ #include "drumkitparser.h" #include "drumgizmo.h" -DrumKitLoader::DrumKitLoader() +DrumKitLoader::DrumKitLoader(Settings& settings) : semaphore("drumkitloader") , framesize(0) + , settings(settings) { run(); run_semaphore.wait(); // Wait for the thread to actually start. @@ -187,11 +188,14 @@ void DrumKitLoader::thread_main() if(loaded % fraction == 0 || loaded == total_num_audiofiles) { - 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); + //LoadStatusMessage *ls = new LoadStatusMessage(); + //ls->number_of_files = total_num_audiofiles; + //ls->numer_of_files_loaded = loaded; + //ls->current_file = filename; + //msghandler.sendMessage(MSGRCV_UI, ls); + settings.number_of_files.store(total_num_audiofiles); + settings.number_of_files_loaded.store(loaded); + //settings.current_file.store(filename); } } diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 3656839..2410074 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -34,6 +34,7 @@ #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 +46,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 @@ -82,4 +83,5 @@ protected: size_t fraction{1}; size_t loaded{0}; size_t framesize{0}; + Settings& settings; }; diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index ab2cb45..09f82e8 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) +DrumKitParser::DrumKitParser(Settings& setting, DrumKit& k) + : kit(k) , refs(REFSFILE) + , settings(settings) { } @@ -182,7 +183,7 @@ void DrumKitParser::endTag(const std::string& name) { if(name == "instrument") { - Instrument* instrument = new Instrument(); + Instrument* instrument = new Instrument(settings); instrument->setGroup(instr_group); InstrumentParser parser(*instrument); 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..3348a4f 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -34,7 +34,8 @@ #include "sample.h" #include "configuration.h" -Instrument::Instrument() +Instrument::Instrument(Settings& settings) + : settings(settings) { DEBUG(instrument, "new %p\n", this); mod = 1.0; @@ -65,28 +66,41 @@ Sample* Instrument::sample(level_t level, size_t pos) { Sample *sample = NULL; - if(Conf::enable_velocity_modifier == false) { + // 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(); + + 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 = (float)rand() / (float)RAND_MAX; // random number: [0;1] + r -= 0.5; // random number [-0.5;0.5] + r *= velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] level += r; if(level > 1.0) { level = 1.0; } + if(level < 0.0) { level = 0.0; } } - if(Conf::enable_velocity_modifier) { + if(enable_velocity_modifier) + { mod += (pos - lastpos) / - (Conf::samplerate * Conf::velocity_modifier_falloff); + (samplerate * velocity_modifier_falloff); if(mod > 1.0) { mod = 1.0; @@ -98,7 +112,8 @@ Sample* Instrument::sample(level_t level, size_t pos) // Version 2.0 sample = powerlist.get(level * mod); } - else { + else + { // Version 1.0 std::vector s = samples.get(level * mod); if(s.size() == 0) @@ -106,13 +121,14 @@ Sample* Instrument::sample(level_t level, size_t pos) return NULL; } - sample = rand.choose(s); + size_t idx = rand()%(s.size()); + sample = s[idx]; } - if(Conf::enable_velocity_modifier) + if(enable_velocity_modifier) { lastpos = pos; - mod *= Conf::velocity_modifier_weight; + mod *= velocity_modifier_weight; } return sample; @@ -157,41 +173,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..7c8c52d 100644 --- a/src/instrument.h +++ b/src/instrument.h @@ -36,13 +36,14 @@ #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,6 +79,8 @@ private: size_t lastpos; float mod; + Settings& settings; +}; Random rand; }; diff --git a/src/settings.h b/src/settings.h index 74c432d..4eb7dba 100644 --- a/src/settings.h +++ b/src/settings.h @@ -27,14 +27,40 @@ #pragma once #include +#include #include +class MyString { +public: + std::string value; +}; + +//! Engine settings +struct Settings +{ + std::atomic enable_velocity_modifier; + std::atomic velocity_modifier_falloff; + std::atomic velocity_modifier_weight; + + std::atomic enable_velocity_randomiser; + std::atomic velocity_randomiser_weight; + + std::atomic samplerate; + + std::atomic enable_resampling; + + std::atomic number_of_files; + std::atomic number_of_files_loaded; + //std::atomic current_file; + +}; + +//! Getter utility class. template class SettingRef { public: SettingRef(std::atomic& value) - : value{value} - , cache{} + : value(value) { // string isn't lock free either assert((std::is_same::value || value.is_lock_free())); @@ -57,20 +83,7 @@ private: std::atomic cache; }; -struct Settings -{ - std::atomic enable_velocity_modifier; - std::atomic velocity_modifier_falloff; - std::atomic velocity_modifier_weight; - - std::atomic enable_velocity_randomiser; - std::atomic velocity_randomiser_weight; - - std::atomic samplerate; - - std::atomic enable_resampling; -}; - +//! Combined getter class. struct SettingsGetter { SettingRef enable_velocity_modifier; @@ -80,10 +93,14 @@ struct SettingsGetter SettingRef enable_velocity_randomiser; SettingRef velocity_randomiser_weight; - SettingRef samplerate; + SettingRef samplerate; SettingRef enable_resampling; + SettingRef number_of_files; + SettingRef number_of_files_loaded; + //SettingRef current_file; + SettingsGetter(Settings& settings) : enable_velocity_modifier{settings.enable_velocity_modifier} , velocity_modifier_falloff{settings.velocity_modifier_falloff} @@ -92,6 +109,9 @@ struct SettingsGetter , 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} { } }; @@ -99,29 +119,35 @@ struct SettingsGetter // lovely reminder: NO, GLOCKE. NOOOO!! /* enum class IntParams { - Foo = 0 + Foo = 0 }; -struct Settings { - std::array, 5> ints; +struct Settings +{ + std::array, 5> ints; - Settings() - : ints{} { - //get(IntParams::Foo).store(3); - } + Settings() + : ints{} + { + //get(IntParams::Foo).store(3); + } - std::atomic& get(IntParams param) { - return ints[(size_t)param]; - } + std::atomic& get(IntParams param) + { + return ints[(size_t)param]; + } }; -struct SettingsGetter { - std::vector> ints; +struct SettingsGetter +{ + std::vector> 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); + } + } }; */ -- cgit v1.2.3 From 6265f9a0d8b213529905324f90059941a4f2a99a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Wed, 23 Mar 2016 22:40:27 +0100 Subject: atomic workaround --- src/atomic.h | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ test/Makefile.am | 7 +++- test/atomictest.cc | 77 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 src/atomic.h create mode 100644 test/atomictest.cc diff --git a/src/atomic.h b/src/atomic.h new file mode 100644 index 0000000..11c87fc --- /dev/null +++ b/src/atomic.h @@ -0,0 +1,105 @@ +/* -*- 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 +#include +#include + +template +class Atomic; + +// use std::atomic if possible +template +class Atomic::value>::type> + : public std::atomic { +}; + +// else work around it using a mutex +template +class Atomic::value>::type> { + public: + using self_type = Atomic::value>::type>; + + Atomic() + : data{} + , mutex{} { + } + + Atomic(T data) + : data{std::move(data)} + , mutex{} { + } + + Atomic(self_type const & other) + : data{} + , mutex{} { + std::lock_guard lock{other.mutex}; + data = other.data; + } + + Atomic(self_type&& other) + : data{} + , mutex{} { + std::lock_guard lock{other.mutex}; + std::swap(data, other.data); + } + + T operator=(T data) { + std::lock_guard 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 lock{mutex}; + this->data = std::move(data); + } + + T load() const { + std::lock_guard lock{mutex}; + return data; + } + + T exchange(T data){ + std::lock_guard lock{mutex}; + std::swap(data, this->data); + return data; + } + + private: + T data; + mutable std::mutex mutex; +}; diff --git a/test/Makefile.am b/test/Makefile.am index ccb21e6..ea0912b 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 check_PROGRAMS = $(TESTS) @@ -138,5 +138,10 @@ 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 + EXTRA_DIST = \ lv2_test_host.h diff --git a/test/atomictest.cc b/test/atomictest.cc new file mode 100644 index 0000000..d4cacf0 --- /dev/null +++ b/test/atomictest.cc @@ -0,0 +1,77 @@ +/* -*- 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 + +#include + +class AtomicTest + : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(AtomicTest); + CPPUNIT_TEST(atomicIntUsesStandardImpl); + CPPUNIT_TEST(atomicFloatUsesStandardImpl); + CPPUNIT_TEST(atomicBoolUsesStandardImpl); + CPPUNIT_TEST(atomicStringCanBeUsed); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() {} + void tearDown() {} + + void atomicIntUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicFloatUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicBoolUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicDoubleUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + } + + void atomicStringCanBeUsed() { + // note: if it couldn't be used, the compiler would complain + Atomic tmp; + } + + // todo: further testing + + private: + template + bool isUsingStandardImpl() { + return std::is_base_of, Atomic>::value; + } +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AtomicTest); + -- cgit v1.2.3 From c9f773c9f2c9ea52d5e0ed69b13870c0c5f96acf Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 23:02:09 +0100 Subject: Fix tests. --- test/engine.cc | 3 ++- test/memcheckertest.cc | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) 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 -- cgit v1.2.3 From bd1434b6cfc59c37362ea6f462034f8265072c9a Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 23:02:35 +0100 Subject: Use new Atomic class. --- src/atomic.h | 6 +++--- src/settings.h | 35 ++++++++++++++++------------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/atomic.h b/src/atomic.h index 11c87fc..f800f68 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -35,15 +35,15 @@ class Atomic; // use std::atomic if possible template -class Atomic::value>::type> +class Atomic::value>::type> : public std::atomic { }; // else work around it using a mutex template -class Atomic::value>::type> { +class Atomic::value>::type> { public: - using self_type = Atomic::value>::type>; + using self_type = Atomic::value>::type>; Atomic() : data{} diff --git a/src/settings.h b/src/settings.h index 4eb7dba..eb18909 100644 --- a/src/settings.h +++ b/src/settings.h @@ -30,28 +30,25 @@ #include #include -class MyString { -public: - std::string value; -}; +#include "atomic.h" //! Engine settings struct Settings { - std::atomic enable_velocity_modifier; - std::atomic velocity_modifier_falloff; - std::atomic velocity_modifier_weight; + Atomic enable_velocity_modifier; + Atomic velocity_modifier_falloff; + Atomic velocity_modifier_weight; - std::atomic enable_velocity_randomiser; - std::atomic velocity_randomiser_weight; + Atomic enable_velocity_randomiser; + Atomic velocity_randomiser_weight; - std::atomic samplerate; + Atomic samplerate; - std::atomic enable_resampling; + Atomic enable_resampling; - std::atomic number_of_files; - std::atomic number_of_files_loaded; - //std::atomic current_file; + Atomic number_of_files; + Atomic number_of_files_loaded; + Atomic current_file; }; @@ -59,7 +56,7 @@ struct Settings template class SettingRef { public: - SettingRef(std::atomic& value) + SettingRef(Atomic& value) : value(value) { // string isn't lock free either @@ -79,8 +76,8 @@ public: } private: - std::atomic& value; - std::atomic cache; + Atomic& value; + Atomic cache; }; //! Combined getter class. @@ -99,7 +96,7 @@ struct SettingsGetter SettingRef number_of_files; SettingRef number_of_files_loaded; - //SettingRef current_file; + SettingRef current_file; SettingsGetter(Settings& settings) : enable_velocity_modifier{settings.enable_velocity_modifier} @@ -111,7 +108,7 @@ struct SettingsGetter , 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} + , current_file{settings.current_file} { } }; -- cgit v1.2.3 From d64958fc1e51ec92b73b545530e58967d69e92a8 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 21:57:41 +0100 Subject: More cleanup. --- src/drumkit.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/drumkit.h b/src/drumkit.h index a6913c0..e3ae783 100644 --- a/src/drumkit.h +++ b/src/drumkit.h @@ -36,7 +36,6 @@ class DrumKit { friend class DrumKitParser; - public: DrumKit(); ~DrumKit(); -- cgit v1.2.3 From 04e532a2a079ceb6acfcb4ebfaca58315fe1ff2d Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 23 Mar 2016 22:38:44 +0100 Subject: Settings. --- src/instrument.h | 1 - src/settings.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/instrument.h b/src/instrument.h index 7c8c52d..0694d80 100644 --- a/src/instrument.h +++ b/src/instrument.h @@ -41,7 +41,6 @@ class Instrument { friend class InstrumentParser; - public: Instrument(Settings& settings); ~Instrument(); diff --git a/src/settings.h b/src/settings.h index eb18909..ed031b2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -49,7 +49,6 @@ struct Settings Atomic number_of_files; Atomic number_of_files_loaded; Atomic current_file; - }; //! Getter utility class. -- cgit v1.2.3 From d1d1e525a579ab55e1ffb8acc1b269360df5b1e9 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 30 Mar 2016 10:09:34 +0200 Subject: Update ChangeLog with 0.9.10 release --- ChangeLog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8e8afe5..10a2b28 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 -- cgit v1.2.3 From 0d2668121d2b3e188dc60cb7bdb5d9dcc39beab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 08:10:44 +0200 Subject: Fixed API of class Atomic for POD --- src/atomic.h | 5 +++++ test/atomictest.cc | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/atomic.h b/src/atomic.h index f800f68..1b92257 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -37,6 +37,11 @@ class Atomic; template class Atomic::value>::type> : public std::atomic { + + public: + // inherit methods + using std::atomic::atomic; + using std::atomic::operator=; }; // else work around it using a mutex diff --git a/test/atomictest.cc b/test/atomictest.cc index d4cacf0..d73695e 100644 --- a/test/atomictest.cc +++ b/test/atomictest.cc @@ -36,6 +36,12 @@ class AtomicTest CPPUNIT_TEST(atomicFloatUsesStandardImpl); CPPUNIT_TEST(atomicBoolUsesStandardImpl); CPPUNIT_TEST(atomicStringCanBeUsed); + CPPUNIT_TEST(podAtomicCanBeDefaultInitialized); + CPPUNIT_TEST(nonPodAtomicCanBeDefaultInitialized); + CPPUNIT_TEST(podAtomicCanBeValueInitialized); + CPPUNIT_TEST(nonPodAtomicCanBeValueInitialized); + CPPUNIT_TEST(podAtomicCanBeValueAssigned); + CPPUNIT_TEST(nonPodAtomicCanBeValueAssigned); CPPUNIT_TEST_SUITE_END(); public: @@ -63,6 +69,38 @@ class AtomicTest Atomic tmp; } + void podAtomicCanBeDefaultInitialized() { + Atomic i; + // note: i is initialized with garbage + } + + void nonPodAtomicCanBeDefaultInitialized() { + Atomic s; + CPPUNIT_ASSERT_EQUAL(s.load(), std::string{}); + } + + void podAtomicCanBeValueInitialized() { + Atomic i{5}; + CPPUNIT_ASSERT_EQUAL(i.load(), 5); + } + + void nonPodAtomicCanBeValueInitialized() { + Atomic s{"hello world"}; + CPPUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"}); + } + + void podAtomicCanBeValueAssigned() { + Atomic i; + i = 5; + CPPUNIT_ASSERT_EQUAL(i.load(), 5); + } + + void nonPodAtomicCanBeValueAssigned() { + Atomic s; + s = "hello world"; + CPPUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"}); + } + // todo: further testing private: -- cgit v1.2.3 From 6a25f7e4e1524db7125cc67116cd989ce994c7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 08:29:09 +0200 Subject: Added Atomic Tests about being lock free --- test/atomictest.cc | 56 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/test/atomictest.cc b/test/atomictest.cc index d73695e..1718b33 100644 --- a/test/atomictest.cc +++ b/test/atomictest.cc @@ -32,41 +32,38 @@ class AtomicTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(AtomicTest); - CPPUNIT_TEST(atomicIntUsesStandardImpl); - CPPUNIT_TEST(atomicFloatUsesStandardImpl); - CPPUNIT_TEST(atomicBoolUsesStandardImpl); - CPPUNIT_TEST(atomicStringCanBeUsed); + 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 atomicIntUsesStandardImpl() { + void podAtomicsUseStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); CPPUNIT_ASSERT(isUsingStandardImpl()); - } - - void atomicFloatUsesStandardImpl() { + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); CPPUNIT_ASSERT(isUsingStandardImpl()); - } - - void atomicBoolUsesStandardImpl() { - CPPUNIT_ASSERT(isUsingStandardImpl()); - } - - void atomicDoubleUsesStandardImpl() { CPPUNIT_ASSERT(isUsingStandardImpl()); + CPPUNIT_ASSERT(isUsingStandardImpl()); } - void atomicStringCanBeUsed() { - // note: if it couldn't be used, the compiler would complain - Atomic tmp; + void nonPodAtomicsUseOwnImpl() { + CPPUNIT_ASSERT(!isUsingStandardImpl()); } void podAtomicCanBeDefaultInitialized() { @@ -101,6 +98,23 @@ class AtomicTest CPPUNIT_ASSERT_EQUAL(s.load(), std::string{"hello world"}); } + void podAtomicsAreLockFree() { + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + CPPUNIT_ASSERT(isLockFree()); + + // compile error: undefined reference to `__atomic_is_lock_free' + //CPPUNIT_ASSERT(isLockFree()); + } + // todo: further testing private: @@ -108,6 +122,12 @@ class AtomicTest bool isUsingStandardImpl() { return std::is_base_of, Atomic>::value; } + + template + bool isLockFree() { + Atomic a; + return a.is_lock_free(); + } }; // Registers the fixture into the 'registry' -- cgit v1.2.3 From 3ecca5323cba595fa05a599777f0b4c455bdd058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:09:40 +0200 Subject: Added API for accessing structs in a thread-safe way --- src/syncedsettings.h | 112 ++++++++++++++++++++++++++++++++ test/Makefile.am | 7 +- test/syncedsettings.cc | 173 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 src/syncedsettings.h create mode 100644 test/syncedsettings.cc diff --git a/src/syncedsettings.h b/src/syncedsettings.h new file mode 100644 index 0000000..f83847c --- /dev/null +++ b/src/syncedsettings.h @@ -0,0 +1,112 @@ +/* -*- 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 + +// type trait helper + +template +struct pack_contains; + +template +struct pack_contains + : std::true_type { +}; + +template +struct pack_contains + : pack_contains { +}; + +template +struct pack_contains + : std::false_type { +}; + +// -------------------------------------------------------------------- + +template +class Group; + +template +class Accessor { + private: + std::lock_guard lock; + + public: + Accessor(Group& parent) + : lock{parent.mutex} + , data{parent.data} { + } + + T& data; +}; + +template +class Group { + private: + friend class Accessor; + + mutable std::mutex mutex; + T data; + + public: + Group() + : mutex{} + , data{} { + } + + Group(T const & data) + : mutex{} + , data{data} { + } + + Group(T&& data) + : mutex{} + , data{std::move(data)} { + } + + Group(Group const & other) + : mutex{} + , data{} { + std::lock_guard lock{other.mutex}; + data = other.data; + } + + Group(Group&& other) + : mutex{} + , data{} { + std::lock_guard lock{other.mutex}; + std::swap(data, other.data); + } + + operator T() const { + std::lock_guard lock{mutex}; + return data; + } +}; diff --git a/test/Makefile.am b/test/Makefile.am index ea0912b..f9d9c77 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 atomictest + memchecker random atomictest syncedsettingstest check_PROGRAMS = $(TESTS) @@ -143,5 +143,10 @@ atomictest_CXXFLAGS = -DOUTPUT=\"atomictest\" $(CPPUNIT_CFLAGS) \ 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/syncedsettings.cc b/test/syncedsettings.cc new file mode 100644 index 0000000..a04c870 --- /dev/null +++ b/test/syncedsettings.cc @@ -0,0 +1,173 @@ +/* -*- 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 + +#include + +class SyncedSettingsTest + : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(SyncedSettingsTest); + CPPUNIT_TEST(groupCanBeDefaultInitialized); + CPPUNIT_TEST(groupDataCanBeCopied); + CPPUNIT_TEST(groupCanBeCreatedByReference); + CPPUNIT_TEST(groupCanBeCreatedByRvalueReference); + + CPPUNIT_TEST(accessorCanGetFields); + CPPUNIT_TEST(accessorCanSetFields); + + CPPUNIT_TEST(groupHasCopyCtor); + CPPUNIT_TEST(groupHasMoveCtor); + CPPUNIT_TEST(groupHasCopyAssignOp); + CPPUNIT_TEST(groupHasMoveAssignOp); + CPPUNIT_TEST_SUITE_END(); + + private: + struct TestData { + float foo; + bool bar; + std::string msg; + }; + + public: + void setUp() {} + void tearDown() {} + + void groupCanBeDefaultInitialized() { + Group data; + } + + void groupDataCanBeCopied() { + Group data; + (TestData)data; // copies + } + + void groupCanBeCreatedByReference() { + TestData tmp{3.f, false, "hello"}; + Group 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 groupCanBeCreatedByRvalueReference() { + TestData tmp{3.f, false, "hello"}; + Group 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 accessorCanGetFields() { + TestData tmp{3.f, false, "hello"}; + Group data{tmp}; + Accessor 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 accessorCanSetFields() { + Group data; + Accessor 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 groupHasCopyCtor() { + Group tmp; + { + Accessor a{tmp}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + Group 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 tmp; + { + Accessor a{tmp}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + Group 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 tmp; + { + Accessor a{tmp}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + Group 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 tmp; + { + Accessor a{tmp}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + Group 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"}); + } + + // todo: further testing +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(SyncedSettingsTest); + -- cgit v1.2.3 From afa2b578d6debc42bd4429b6efce8868b8f8fa81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:12:20 +0200 Subject: Cleanup on Synced Settings Header --- src/syncedsettings.h | 128 ++++++++++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 72 deletions(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index f83847c..eb8e66e 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -28,85 +28,69 @@ #include -// type trait helper +template class Group; -template -struct pack_contains; +template class Accessor +{ +private: + std::lock_guard lock; -template -struct pack_contains - : std::true_type { -}; +public: + Accessor(Group& parent) + : lock{parent.mutex} + , data{parent.data} + { + } -template -struct pack_contains - : pack_contains { + T& data; }; -template -struct pack_contains - : std::false_type { -}; +template class Group +{ +private: + friend class Accessor; -// -------------------------------------------------------------------- + mutable std::mutex mutex; + T data; -template -class Group; +public: + Group() + : mutex{} + , data{} + { + } -template -class Accessor { - private: - std::lock_guard lock; - - public: - Accessor(Group& parent) - : lock{parent.mutex} - , data{parent.data} { - } - - T& data; -}; + Group(T const& data) + : mutex{} + , data{data} + { + } + + Group(T&& data) + : mutex{} + , data{std::move(data)} + { + } + + Group(Group const& other) + : mutex{} + , data{} + { + std::lock_guard lock{other.mutex}; + data = other.data; + } + + Group(Group&& other) + : mutex{} + , data{} + { + std::lock_guard lock{other.mutex}; + std::swap(data, other.data); + } -template -class Group { - private: - friend class Accessor; - - mutable std::mutex mutex; - T data; - - public: - Group() - : mutex{} - , data{} { - } - - Group(T const & data) - : mutex{} - , data{data} { - } - - Group(T&& data) - : mutex{} - , data{std::move(data)} { - } - - Group(Group const & other) - : mutex{} - , data{} { - std::lock_guard lock{other.mutex}; - data = other.data; - } - - Group(Group&& other) - : mutex{} - , data{} { - std::lock_guard lock{other.mutex}; - std::swap(data, other.data); - } - - operator T() const { - std::lock_guard lock{mutex}; - return data; - } + operator T() const + { + std::lock_guard lock{mutex}; + return data; + } }; -- cgit v1.2.3 From b3ed57f43d0fc18de5ac2610eabc5a97d9eea4a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:15:37 +0200 Subject: Added thread-safety to implicit cpy/mv assign op for synced group settings --- src/syncedsettings.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index eb8e66e..e60eb78 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -76,6 +76,7 @@ public: : mutex{} , data{} { + std::lock_guard lock{mutex}; std::lock_guard lock{other.mutex}; data = other.data; } @@ -84,6 +85,7 @@ public: : mutex{} , data{} { + std::lock_guard lock{mutex}; std::lock_guard lock{other.mutex}; std::swap(data, other.data); } -- cgit v1.2.3 From dd49e09e4a96635638ad674a337f8f95928ae277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:21:18 +0200 Subject: Added explicit cpy/mv assign operators to be sure about thread-safety of Group --- src/syncedsettings.h | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index e60eb78..4991627 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -76,7 +76,6 @@ public: : mutex{} , data{} { - std::lock_guard lock{mutex}; std::lock_guard lock{other.mutex}; data = other.data; } @@ -85,11 +84,32 @@ public: : mutex{} , data{} { - std::lock_guard lock{mutex}; std::lock_guard lock{other.mutex}; std::swap(data, other.data); } + Group& operator=(const Group& other) + { + if (*this != &other) + { + std::lock_guard lock{mutex}; + std::lock_guard lock{other.mutex}; + data = other.data; + } + return *this; + } + + Group& operator=(Group&& other) + { + if (*this != &other) + { + std::lock_guard lock{mutex}; + std::lock_guard lock{other.mutex}; + std::swap(data, tmp.data); + } + return *this; + } + operator T() const { std::lock_guard lock{mutex}; -- cgit v1.2.3 From 28aec48039c6837f14848580b9a386d9d87de21d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:22:19 +0200 Subject: Fixed my dumb fail --- src/syncedsettings.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index 4991627..b72229e 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -93,7 +93,7 @@ public: if (*this != &other) { std::lock_guard lock{mutex}; - std::lock_guard lock{other.mutex}; + std::lock_guard lock2{other.mutex}; data = other.data; } return *this; @@ -104,8 +104,8 @@ public: if (*this != &other) { std::lock_guard lock{mutex}; - std::lock_guard lock{other.mutex}; - std::swap(data, tmp.data); + std::lock_guard lock2{other.mutex}; + std::swap(data, other.data); } return *this; } -- cgit v1.2.3 From 8bbb15566e1025fe5784190fa0f594cc837c2673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:40:02 +0200 Subject: Removed unused features and fixed tests --- src/syncedsettings.h | 12 ------ test/syncedsettings.cc | 109 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 76 insertions(+), 45 deletions(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index b72229e..aa43cc0 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -60,18 +60,6 @@ public: { } - Group(T const& data) - : mutex{} - , data{data} - { - } - - Group(T&& data) - : mutex{} - , data{std::move(data)} - { - } - Group(Group const& other) : mutex{} , data{} diff --git a/test/syncedsettings.cc b/test/syncedsettings.cc index a04c870..7de7c42 100644 --- a/test/syncedsettings.cc +++ b/test/syncedsettings.cc @@ -34,8 +34,6 @@ class SyncedSettingsTest CPPUNIT_TEST_SUITE(SyncedSettingsTest); CPPUNIT_TEST(groupCanBeDefaultInitialized); CPPUNIT_TEST(groupDataCanBeCopied); - CPPUNIT_TEST(groupCanBeCreatedByReference); - CPPUNIT_TEST(groupCanBeCreatedByRvalueReference); CPPUNIT_TEST(accessorCanGetFields); CPPUNIT_TEST(accessorCanSetFields); @@ -44,6 +42,8 @@ class SyncedSettingsTest CPPUNIT_TEST(groupHasMoveCtor); CPPUNIT_TEST(groupHasCopyAssignOp); CPPUNIT_TEST(groupHasMoveAssignOp); + + CPPUNIT_TEST(mimicRealUse); CPPUNIT_TEST_SUITE_END(); private: @@ -66,18 +66,14 @@ class SyncedSettingsTest (TestData)data; // copies } - void groupCanBeCreatedByReference() { - TestData tmp{3.f, false, "hello"}; - Group 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 groupCanBeCreatedByRvalueReference() { - TestData tmp{3.f, false, "hello"}; - Group data{std::move(tmp)}; + void accessorCanSetFields() { + Group data; + { + Accessor 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); @@ -85,26 +81,22 @@ class SyncedSettingsTest } void accessorCanGetFields() { - TestData tmp{3.f, false, "hello"}; - Group data{tmp}; - Accessor 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 accessorCanSetFields() { Group data; - Accessor 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"}); + { + Accessor a{data}; + a.data.foo = 3.f; + a.data.bar = false; + a.data.msg = "hello"; + } + // now read + { + Accessor 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 tmp; { @@ -165,7 +157,58 @@ class SyncedSettingsTest CPPUNIT_ASSERT_EQUAL(copy.msg, std::string{"hello"}); } - // todo: further testing + void mimicRealUse() { + struct Settings { + struct Foo { + int a, b; + bool enabled; + }; + struct Bar { + float a, b; + bool enabled; + }; + struct Idk { + std::string label; + float bla; + }; + + Group foo; + Group bar; + Group idk; + }; + + Settings s; + + // set some settings + { + Accessor tmp{s.foo}; + tmp.data.enabled = true; + tmp.data.a = 3; + } + { + Accessor tmp{s.bar}; + tmp.data.enabled = false; + tmp.data.a = 0.f; + tmp.data.b = 0.f; + } + { + Accessor tmp{s.idk}; + tmp.data.label = "hello world"; + tmp.data.bla = 3.14f; + } + + // read some settings + { + Accessor tmp{s.foo}; + if (tmp.data.enabled) { + // do some while locked + } + } + Settings::Bar copy = s.bar; + if (copy.enabled) { + // do some stuff without locking + } + } }; // Registers the fixture into the 'registry' -- cgit v1.2.3 From ba8f8ed02dc666d405c60804fbae87101ccf6bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:44:08 +0200 Subject: Improved mimicRealUse() test case --- test/syncedsettings.cc | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/test/syncedsettings.cc b/test/syncedsettings.cc index 7de7c42..62bd8c6 100644 --- a/test/syncedsettings.cc +++ b/test/syncedsettings.cc @@ -160,54 +160,41 @@ class SyncedSettingsTest void mimicRealUse() { struct Settings { struct Foo { - int a, b; - bool enabled; + float a{5}; + float b{3}; + bool enabled{true}; }; struct Bar { - float a, b; - bool enabled; - }; - struct Idk { - std::string label; - float bla; + std::string label{"empty"}; + float bla{0.f}; }; Group foo; Group bar; - Group idk; }; Settings s; - // set some settings - { - Accessor tmp{s.foo}; - tmp.data.enabled = true; - tmp.data.a = 3; - } + // set bar settings { Accessor tmp{s.bar}; - tmp.data.enabled = false; - tmp.data.a = 0.f; - tmp.data.b = 0.f; - } - { - Accessor tmp{s.idk}; tmp.data.label = "hello world"; tmp.data.bla = 3.14f; } - // read some settings + // read foo settings { Accessor tmp{s.foo}; if (tmp.data.enabled) { // do some while locked } } - Settings::Bar copy = s.bar; + // or: + Settings::Foo copy = s.foo; if (copy.enabled) { // do some stuff without locking } + CPPUNIT_ASSERT(copy.enabled); } }; -- cgit v1.2.3 From 7a149168533e9d147eb3460c92c4c872a2580fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Gl=C3=B6ckner?= Date: Thu, 31 Mar 2016 10:53:04 +0200 Subject: Workaround outdated compiler version --- src/syncedsettings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/syncedsettings.h b/src/syncedsettings.h index aa43cc0..0fe5efd 100644 --- a/src/syncedsettings.h +++ b/src/syncedsettings.h @@ -38,7 +38,7 @@ private: public: Accessor(Group& parent) : lock{parent.mutex} - , data{parent.data} + , data(parent.data) { } -- cgit v1.2.3 From f2b504f25d8cc44206518121259920314c2c80a9 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 14:51:36 +0200 Subject: Fix compilation on windows. --- src/atomic.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/atomic.h b/src/atomic.h index 1b92257..ed6fa39 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -28,7 +28,8 @@ #include #include -#include + +#include "mutex.h" template class Atomic; -- cgit v1.2.3 From e5614c828c7c470d26890ea31f72610278d0eeb2 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 15:12:37 +0200 Subject: Fix mutex include issue. --- src/atomic.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/atomic.h b/src/atomic.h index ed6fa39..84ef949 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -29,6 +29,7 @@ #include #include +#include #include "mutex.h" template -- cgit v1.2.3 From e9c4a96ad32c2ab22f6f3edc5b68f1eb414c041e Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 15:21:28 +0200 Subject: Fix missing include on windows. --- plugingui/testmain.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc index 8282bc8..b3a0d8d 100644 --- a/plugingui/testmain.cc +++ b/plugingui/testmain.cc @@ -26,6 +26,11 @@ */ #include "plugingui.h" +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + #include // Dummy Engine class. -- cgit v1.2.3 From 6e6af33f00a17e842da81e4a04ea9c3421c55adb Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 21:26:42 +0200 Subject: Fix issues from rebasing. --- src/drumkitparser.cc | 2 +- src/instrument.cc | 8 ++++---- src/instrument.h | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 09f82e8..221e921 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -215,7 +215,7 @@ void DrumKitParser::endTag(const std::string& name) 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 { diff --git a/src/instrument.cc b/src/instrument.cc index 3348a4f..ee778d7 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -26,8 +26,8 @@ */ #include "instrument.h" -#include -#include +#include +//#include #include @@ -82,7 +82,7 @@ Sample* Instrument::sample(level_t level, size_t pos) if(enable_velocity_randomiser) { - float r = (float)rand() / (float)RAND_MAX; // random number: [0;1] + float r = (float)std::rand() / (float)RAND_MAX; // random number: [0;1] r -= 0.5; // random number [-0.5;0.5] r *= velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] level += r; @@ -121,7 +121,7 @@ Sample* Instrument::sample(level_t level, size_t pos) return NULL; } - size_t idx = rand()%(s.size()); + size_t idx = std::rand()%(s.size()); sample = s[idx]; } diff --git a/src/instrument.h b/src/instrument.h index 0694d80..a531aec 100644 --- a/src/instrument.h +++ b/src/instrument.h @@ -79,8 +79,6 @@ private: size_t lastpos; float mod; Settings& settings; -}; - Random rand; }; -- cgit v1.2.3 From 2e4175d84cc0ca765fdc0b03bf5c8420deeec268 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 21:50:28 +0200 Subject: Use new Random class. --- src/instrument.cc | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/instrument.cc b/src/instrument.cc index d246c09..ee225d5 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -26,9 +26,6 @@ */ #include "instrument.h" -#include -//#include - #include #include "sample.h" @@ -82,8 +79,7 @@ Sample* Instrument::sample(level_t level, size_t pos) if(enable_velocity_randomiser) { - float r = (float)rand() / (float)RAND_MAX; // random number: [0;1] - r -= 0.5; // random number [-0.5;0.5] + float r = rand.floatInRange(-0.5f, 0.5f); r *= velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] level += r; if(level > 1.0) @@ -121,8 +117,8 @@ Sample* Instrument::sample(level_t level, size_t pos) return NULL; } - size_t idx = rand()%(s.size()); - sample = s[idx]; + //size_t idx = ::rand()%(s.size()); + sample = rand.choose(s); } if(enable_velocity_modifier) -- cgit v1.2.3 From 19691923340e5984e3ace837d39938f718fee608 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 22:11:07 +0200 Subject: Removed the last Conf:: namespace usage and replaced it with Settings. --- plugin/Makefile.mingw32.in | 1 - src/Makefile.am | 2 -- src/Makefile.am.drumgizmo | 1 - src/audiofile.cc | 2 -- src/configuration.cc | 38 -------------------------------- src/configuration.h | 44 ------------------------------------- src/drumgizmo.cc | 55 ++++++++++++++++++++-------------------------- src/instrument.cc | 1 - src/settings.h | 36 ++++++++++++++++++++++++------ 9 files changed, 53 insertions(+), 127 deletions(-) delete mode 100644 src/configuration.cc delete mode 100644 src/configuration.h diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in index 40233b4..779f54b 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 \ diff --git a/src/Makefile.am b/src/Makefile.am index a1b1615..9dd6c29 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 \ @@ -54,7 +53,6 @@ EXTRA_DIST = \ channelmixer.cc \ chresampler.cc \ configfile.cc \ - configuration.cc \ configparser.cc \ drumgizmo.cc \ drumkit.cc \ diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo index 8f648d0..e707fe2 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 \ 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 #include -#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 4109249..f769f4e 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -41,7 +41,6 @@ #include "drumkitparser.h" #include "audioinputenginemidi.h" -#include "configuration.h" #include "configparser.h" #include "nolocale.h" @@ -103,7 +102,7 @@ bool DrumGizmo::loadkit(std::string file) #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*/ @@ -171,11 +170,11 @@ void DrumGizmo::handleMessage(Message *msg) 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; + msg->enable_velocity_modifier = settings.enable_velocity_modifier.load(); + msg->velocity_modifier_falloff = settings.velocity_modifier_falloff.load(); + msg->velocity_modifier_weight = settings.velocity_modifier_weight.load(); + msg->enable_velocity_randomiser = settings.enable_velocity_randomiser.load(); + msg->velocity_randomiser_weight = settings.velocity_randomiser_weight.load(); msghandler.sendMessage(MSGRCV_UI, msg); } break; @@ -184,13 +183,13 @@ void DrumGizmo::handleMessage(Message *msg) ChangeSettingMessage *ch = (ChangeSettingMessage*)msg; switch(ch->name) { case ChangeSettingMessage::enable_velocity_modifier: - Conf::enable_velocity_modifier = ch->value; + settings.enable_velocity_modifier.store(ch->value); break; case ChangeSettingMessage::velocity_modifier_weight: - Conf::velocity_modifier_weight = ch->value; + settings.velocity_modifier_weight.store(ch->value); break; case ChangeSettingMessage::velocity_modifier_falloff: - Conf::velocity_modifier_falloff = ch->value; + settings.velocity_modifier_falloff.store(ch->value); break; } } @@ -400,7 +399,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 @@ -638,17 +637,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) { @@ -693,15 +692,15 @@ std::string DrumGizmo::configString() " " + kit.getFile() + "\n" " " + mmapfile + "\n" " " + - bool2str(Conf::enable_velocity_modifier) + "\n" + bool2str(settings.enable_velocity_modifier.load()) + "\n" " " + - float2str(Conf::velocity_modifier_falloff) + "\n" + float2str(settings.velocity_modifier_falloff.load()) + "\n" " " + - float2str(Conf::velocity_modifier_weight) + "\n" + float2str(settings.velocity_modifier_weight.load()) + "\n" " " + - bool2str(Conf::enable_velocity_randomiser) + "\n" + bool2str(settings.enable_velocity_randomiser.load()) + "\n" " " + - float2str(Conf::velocity_randomiser_weight) + "\n" + float2str(settings.velocity_randomiser_weight.load()) + "\n" ""; } @@ -719,38 +718,32 @@ bool DrumGizmo::setConfigString(std::string cfg) 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"); diff --git a/src/instrument.cc b/src/instrument.cc index ee225d5..f187de0 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -29,7 +29,6 @@ #include #include "sample.h" -#include "configuration.h" Instrument::Instrument(Settings& settings) : settings(settings) diff --git a/src/settings.h b/src/settings.h index ed031b2..2700e26 100644 --- a/src/settings.h +++ b/src/settings.h @@ -31,20 +31,34 @@ #include #include "atomic.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; + +//operator Atomic //! Engine settings struct Settings { - Atomic enable_velocity_modifier; - Atomic velocity_modifier_falloff; - Atomic velocity_modifier_weight; + Atomic foo{"foo"}; - Atomic enable_velocity_randomiser; - Atomic velocity_randomiser_weight; + Atomic enable_velocity_modifier{true}; + Atomic velocity_modifier_falloff{0.5}; + Atomic velocity_modifier_weight{0.25}; - Atomic samplerate; + Atomic enable_velocity_randomiser{false}; + Atomic velocity_randomiser_weight{0.1}; - Atomic enable_resampling; + Atomic samplerate{44100.0}; + + Atomic enable_resampling{true}; Atomic number_of_files; Atomic number_of_files_loaded; @@ -66,6 +80,13 @@ public: { T tmp = cache; cache.exchange(value); + + if(firstAccess) + { + firstAccess = false; + return true; + } + return tmp == cache; } @@ -75,6 +96,7 @@ public: } private: + bool firstAccess{true}; Atomic& value; Atomic cache; }; -- cgit v1.2.3 From 036a667a2b0eca1339ba14beafc13a7fdfc23c34 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 31 Mar 2016 22:17:04 +0200 Subject: Fix unit tests. --- test/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index f9d9c77..3633ad8 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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 -- cgit v1.2.3 From 02784b77bb4f652d362297d947b8305dea2b195a Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 2 Apr 2016 10:19:20 +0200 Subject: Make Atimoc fit style-guide. --- src/atomic.h | 144 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 77 insertions(+), 67 deletions(-) diff --git a/src/atomic.h b/src/atomic.h index 84ef949..e0b80b1 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -38,75 +38,85 @@ class Atomic; // use std::atomic if possible template class Atomic::value>::type> - : public std::atomic { - - public: - // inherit methods - using std::atomic::atomic; - using std::atomic::operator=; + : public std::atomic +{ +public: + // inherit methods + using std::atomic::atomic; + using std::atomic::operator=; }; // else work around it using a mutex template -class Atomic::value>::type> { - public: - using self_type = Atomic::value>::type>; - - Atomic() - : data{} - , mutex{} { - } - - Atomic(T data) - : data{std::move(data)} - , mutex{} { - } - - Atomic(self_type const & other) - : data{} - , mutex{} { - std::lock_guard lock{other.mutex}; - data = other.data; - } - - Atomic(self_type&& other) - : data{} - , mutex{} { - std::lock_guard lock{other.mutex}; - std::swap(data, other.data); - } - - T operator=(T data) { - std::lock_guard 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 lock{mutex}; - this->data = std::move(data); - } - - T load() const { - std::lock_guard lock{mutex}; - return data; - } - - T exchange(T data){ - std::lock_guard lock{mutex}; - std::swap(data, this->data); - return data; - } - - private: - T data; - mutable std::mutex mutex; +class Atomic::value>::type> +{ +public: + using self_type = + Atomic::value>::type>; + + Atomic() + : data{} + , mutex{} + { + } + + Atomic(T data) + : data{std::move(data)} + , mutex{} + { + } + + Atomic(self_type const & other) + : data{} + , mutex{} + { + std::lock_guard lock{other.mutex}; + data = other.data; + } + + Atomic(self_type&& other) + : data{} + , mutex{} + { + std::lock_guard lock{other.mutex}; + std::swap(data, other.data); + } + + T operator=(T data) + { + std::lock_guard 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 lock{mutex}; + this->data = std::move(data); + } + + T load() const { + std::lock_guard lock{mutex}; + return data; + } + + T exchange(T data){ + std::lock_guard lock{mutex}; + std::swap(data, this->data); + return data; + } + +private: + T data; + mutable std::mutex mutex; }; -- cgit v1.2.3 From b530ac02af61e320e137a392decef1b3cc5af2c4 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sun, 3 Apr 2016 17:40:50 +0200 Subject: Fix logic error in SettingRef::hasChanged(). --- src/settings.h | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/settings.h b/src/settings.h index 2700e26..b132c1b 100644 --- a/src/settings.h +++ b/src/settings.h @@ -31,30 +31,16 @@ #include #include "atomic.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; - -//operator Atomic //! Engine settings struct Settings { - Atomic foo{"foo"}; - Atomic enable_velocity_modifier{true}; - Atomic velocity_modifier_falloff{0.5}; - Atomic velocity_modifier_weight{0.25}; + Atomic velocity_modifier_falloff{0.5f}; + Atomic velocity_modifier_weight{0.25f}; Atomic enable_velocity_randomiser{false}; - Atomic velocity_randomiser_weight{0.1}; + Atomic velocity_randomiser_weight{0.1f}; Atomic samplerate{44100.0}; @@ -87,7 +73,7 @@ public: return true; } - return tmp == cache; + return tmp != cache; } T getValue() const -- cgit v1.2.3 From 057ef1d83ba263fb2adf1aa86f8e281ab0065c43 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 8 Apr 2016 00:15:32 +0200 Subject: Refactoring to finally get rid of MessageHandler/Receiver in favor of the new Settings mechanism. --- drumgizmo/drumgizmoc.cc | 76 +++++++------------ drumgizmo/drumgizmoc.h | 17 ----- plugin/Makefile.mingw32.in | 2 - plugin/drumgizmo_plugin.cc | 2 +- plugingui/Makefile.am | 5 +- plugingui/button.h | 3 +- plugingui/checkbox.h | 3 +- plugingui/dgwindow.cc | 113 ++++++++++++++++++---------- plugingui/dgwindow.h | 14 ++-- plugingui/eventhandler.h | 3 +- plugingui/filebrowser.h | 4 +- plugingui/knob.h | 3 +- plugingui/layout.h | 2 +- plugingui/listboxbasic.h | 3 +- plugingui/listboxthin.h | 3 +- plugingui/notifier.h | 163 ---------------------------------------- plugingui/plugingui.cc | 183 +++++++++------------------------------------ plugingui/plugingui.h | 36 ++------- plugingui/progressbar.cc | 26 ++++--- plugingui/progressbar.h | 9 ++- plugingui/testmain.cc | 12 ++- src/Makefile.am | 6 +- src/Makefile.am.drumgizmo | 2 - src/atomic.h | 60 +++++++++++++++ src/drumgizmo.cc | 149 ++++++++++++------------------------ src/drumgizmo.h | 14 +--- src/drumkitloader.cc | 16 ++-- src/drumkitparser.cc | 2 +- src/instrument.cc | 19 ++--- src/message.h | 121 ------------------------------ src/messagehandler.cc | 89 ---------------------- src/messagehandler.h | 66 ---------------- src/messagereceiver.cc | 78 ------------------- src/messagereceiver.h | 75 ------------------- src/notifier.h | 163 ++++++++++++++++++++++++++++++++++++++++ src/settings.h | 123 +++++++++++++++++++++--------- 36 files changed, 567 insertions(+), 1098 deletions(-) delete mode 100644 plugingui/notifier.h delete mode 100644 src/message.h delete mode 100644 src/messagehandler.cc delete mode 100644 src/messagehandler.h delete mode 100644 src/messagereceiver.cc delete mode 100644 src/messagereceiver.h create mode 100644 src/notifier.h diff --git a/drumgizmo/drumgizmoc.cc b/drumgizmo/drumgizmoc.cc index 357877d..e993dc3 100644 --- a/drumgizmo/drumgizmoc.cc +++ b/drumgizmo/drumgizmoc.cc @@ -92,36 +92,7 @@ static const char usage_str[] = " dummy:\n" "\n"; -CliMain::CliMain() - : MessageReceiver(MSGRCV_UI) -{ - loading = true; // Block by default -} - -CliMain::~CliMain() -{ - hug_close(); -} - -void CliMain::handleMessage(Message* msg) -{ - switch(msg->type()) - { - case Message::LoadStatus: - { - auto ls = static_cast(msg); - if(ls->numer_of_files_loaded == ls->number_of_files) - { - loading = false; - } - } - break; - default: - break; - } -} - -int CliMain::run(int argc, char* argv[]) +int main(int argc, char* argv[]) { int c; @@ -383,21 +354,37 @@ int CliMain::run(int argc, char* argv[]) return 1; } - printf("Loading drumkit, this may take a while..."); - fflush(stdout); - loading = true; - while(async == false && loading) + printf("Loading drumkit, this may take a while:\n"); + + if(!async) { + while(settings.drumkit_load_status.load() != LoadStatus::Done) + { #ifdef WIN32 - SleepEx(500, FALSE); + SleepEx(10, FALSE); #else - usleep(500000); + usleep(10000); #endif /*WIN32*/ - handleMessages(); - printf("."); - fflush(stdout); + + int total = settings.number_of_files.load(); + int loaded = settings.number_of_files_loaded.load(); + + printf("\r%d of %d ", loaded, total); + fflush(stdout); + + if(settings.drumkit_load_status.load() == LoadStatus::Error) + { + printf("\nLoad error\n"); + return 1; + } + + if(loaded == total) + { + //break; + } + } + printf("\ndone\n"); } - printf("done.\n"); gizmo.setSamplerate(oe->getSamplerate()); @@ -412,14 +399,7 @@ int CliMain::run(int argc, char* argv[]) printf("Quit.\n"); fflush(stdout); - return 0; -} - -int main(int argc, char* argv[]) -{ - CliMain cli; - - cli.run(argc, argv); + hug_close(); return 0; } diff --git a/drumgizmo/drumgizmoc.h b/drumgizmo/drumgizmoc.h index 231aec6..cc2f96c 100644 --- a/drumgizmo/drumgizmoc.h +++ b/drumgizmo/drumgizmoc.h @@ -24,21 +24,4 @@ * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ - #pragma once - -#include "messagereceiver.h" - -class CliMain : public MessageReceiver -{ -public: - CliMain(); - virtual ~CliMain(); - - int run(int argc, char* argv[]); - void handleMessage(Message* msg); - -private: - bool loading; -}; - diff --git a/plugin/Makefile.mingw32.in b/plugin/Makefile.mingw32.in index 779f54b..8b341c7 100644 --- a/plugin/Makefile.mingw32.in +++ b/plugin/Makefile.mingw32.in @@ -28,8 +28,6 @@ DG_SRC = \ @top_srcdir@/src/instrument.cc \ @top_srcdir@/src/instrumentparser.cc \ @top_srcdir@/src/memchecker.cc \ - @top_srcdir@/src/messagehandler.cc \ - @top_srcdir@/src/messagereceiver.cc \ @top_srcdir@/src/midimapparser.cc \ @top_srcdir@/src/midimapper.cc \ @top_srcdir@/src/mutex.cc \ diff --git a/plugin/drumgizmo_plugin.cc b/plugin/drumgizmo_plugin.cc index 24cfb9a..06c2799 100644 --- a/plugin/drumgizmo_plugin.cc +++ b/plugin/drumgizmo_plugin.cc @@ -143,7 +143,7 @@ bool DrumGizmoPlugin::hasGUI() void DrumGizmoPlugin::createWindow(void *parent) { - plugin_gui = std::make_shared(parent); + plugin_gui = std::make_shared(settings, parent); resizeWindow(370, 330); onShowWindow(); } diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am index 3dee864..4176c07 100644 --- a/plugingui/Makefile.am +++ b/plugingui/Makefile.am @@ -16,9 +16,7 @@ plugingui_SOURCES = \ $(top_srcdir)/src/configfile.cc \ $(top_srcdir)/src/thread.cc \ $(top_srcdir)/src/semaphore.cc \ - $(top_srcdir)/src/mutex.cc \ - $(top_srcdir)/src/messagehandler.cc \ - $(top_srcdir)/src/messagereceiver.cc + $(top_srcdir)/src/mutex.cc rcgen_SOURCES = rcgen.cc @@ -46,7 +44,6 @@ EXTRA_DIST = \ nativewindow.h \ nativewindow_win32.h \ nativewindow_x11.h \ - notifier.h \ painter.h \ pixelbuffer.h \ pluginconfig.h \ diff --git a/plugingui/button.h b/plugingui/button.h index 7e3e168..1bfeb2d 100644 --- a/plugingui/button.h +++ b/plugingui/button.h @@ -28,9 +28,10 @@ #include +#include + #include "widget.h" #include "painter.h" -#include "notifier.h" #include "font.h" namespace GUI { diff --git a/plugingui/checkbox.h b/plugingui/checkbox.h index 3da5511..5c658a5 100644 --- a/plugingui/checkbox.h +++ b/plugingui/checkbox.h @@ -26,9 +26,10 @@ */ #pragma once +#include + #include "widget.h" #include "image.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/dgwindow.cc b/plugingui/dgwindow.cc index 25cbdf0..c325703 100644 --- a/plugingui/dgwindow.cc +++ b/plugingui/dgwindow.cc @@ -30,12 +30,12 @@ #include "verticalline.h" #include "../version.h" -#include "messagehandler.h" #include "pluginconfig.h" namespace GUI { -class LabeledControl : public Widget +class LabeledControl + : public Widget { public: LabeledControl(Widget* parent, const std::string& name) @@ -60,7 +60,8 @@ public: Label caption{this}; }; -class File : public Widget +class File + : public Widget { public: File(Widget* parent) @@ -83,7 +84,8 @@ public: Button browseButton{this}; }; -class HumanizeControls : public Widget +class HumanizeControls + : public Widget { public: HumanizeControls(Widget* parent) @@ -119,10 +121,8 @@ public: Knob falloffKnob{&falloff}; }; -DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, - Config& config, Settings& settings) +DGWindow::DGWindow(void* native_window, Config& config, Settings& settings) : Window(native_window) - , messageHandler(messageHandler) , config(config) , settings(settings) { @@ -180,6 +180,7 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, midimapFileProgress = new ProgressBar(this); midimapFileProgress->resize(width() - 40, 11); + midimapFileProgress->setTotal(2); layout.addItem(midimapFileProgress); VerticalLine *l2 = new VerticalLine(this); @@ -208,7 +209,7 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, layout.addItem(l3); Label *lbl_version = new Label(this); - lbl_version->setText(".::. v" VERSION " .::. http://www.drumgizmo.org .::. LGPLv3 .::."); + lbl_version->setText(".::. v" VERSION " .::. http://www.drumgizmo.org .::. LGPLv3 .::."); lbl_version->resize(width(), 20); lbl_version->setAlignment(TextAlignment::center); layout.addItem(lbl_version); @@ -220,6 +221,50 @@ DGWindow::DGWindow(void* native_window, MessageHandler& messageHandler, fileBrowser->hide(); } +void DGWindow::setDrumKitLoadStatus(LoadStatus load_status) +{ + ProgressBarState state = ProgressBarState::Blue; + switch(load_status) + { + case LoadStatus::Idle: + case LoadStatus::Loading: + state = ProgressBarState::Blue; + break; + case LoadStatus::Done: + state = ProgressBarState::Green; + break; + case LoadStatus::Error: + state = ProgressBarState::Red; + break; + } + drumkitFileProgress->setState(state); +} + +void DGWindow::setMidiMapLoadStatus(LoadStatus load_status) +{ + ProgressBarState state = ProgressBarState::Blue; + switch(load_status) + { + case LoadStatus::Idle: + midimapFileProgress->setValue(0); + break; + case LoadStatus::Loading: + midimapFileProgress->setValue(1); + state = ProgressBarState::Blue; + break; + case LoadStatus::Done: + midimapFileProgress->setValue(2); + state = ProgressBarState::Green; + break; + case LoadStatus::Error: + midimapFileProgress->setValue(2); + state = ProgressBarState::Red; + break; + } + + midimapFileProgress->setState(state); +} + void DGWindow::repaintEvent(RepaintEvent* repaintEvent) { if(!visible()) @@ -234,45 +279,41 @@ void DGWindow::repaintEvent(RepaintEvent* repaintEvent) void DGWindow::attackValueChanged(float value) { - //ChangeSettingMessage *msg = - // new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_weight, - // value); - //messageHandler.sendMessage(MSGRCV_ENGINE, msg); - settings.velocity_modifier_weight.store(value); -#ifdef STANDALONE +#ifdef STANDALONE // For GUI debugging int i = value * 4; switch(i) { - case 0: drumkitFileProgress->setState(ProgressBarState::Off); break; - case 1: drumkitFileProgress->setState(ProgressBarState::Blue); break; - case 2: drumkitFileProgress->setState(ProgressBarState::Green); break; - case 3: drumkitFileProgress->setState(ProgressBarState::Red); break; - default: break; + case 0: + drumkitFileProgress->setState(ProgressBarState::Off); + break; + case 1: + drumkitFileProgress->setState(ProgressBarState::Blue); + break; + case 2: + drumkitFileProgress->setState(ProgressBarState::Green); + break; + case 3: + drumkitFileProgress->setState(ProgressBarState::Red); + break; + default: + break; } #endif } void DGWindow::falloffValueChanged(float value) { - //ChangeSettingMessage *msg = - // new ChangeSettingMessage(ChangeSettingMessage::velocity_modifier_falloff, - // value); - //messageHandler.sendMessage(MSGRCV_ENGINE, msg); - settings.velocity_modifier_falloff.store(value); -#ifdef STANDALONE - drumkitFileProgress->setProgress(value); +#ifdef STANDALONE // For GUI debugging + drumkitFileProgress->setTotal(100); + drumkitFileProgress->setValue(value * 100); #endif } void DGWindow::velocityCheckClick(bool checked) { -// ChangeSettingMessage *msg = -// new ChangeSettingMessage(ChangeSettingMessage::enable_velocity_modifier, -// checked); -// messageHandler.sendMessage(MSGRCV_ENGINE, msg); settings.enable_velocity_modifier.store(checked); } @@ -323,13 +364,7 @@ void DGWindow::selectKitFile(const std::string& filename) config.lastkit = drumkit; config.save(); - drumkitFileProgress->setProgress(0); - drumkitFileProgress->setState(ProgressBarState::Blue); - - LoadDrumKitMessage *msg = new LoadDrumKitMessage(); - msg->drumkitfile = drumkit; - - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.drumkit_file.store(drumkit); } void DGWindow::selectMapFile(const std::string& filename) @@ -342,9 +377,7 @@ void DGWindow::selectMapFile(const std::string& filename) config.lastmidimap = midimap; config.save(); - LoadMidimapMessage *msg = new LoadMidimapMessage(); - msg->midimapfile = midimap; - messageHandler.sendMessage(MSGRCV_ENGINE, msg); + settings.midimap_file.store(midimap); } diff --git a/plugingui/dgwindow.h b/plugingui/dgwindow.h index c4fbeab..72e4679 100644 --- a/plugingui/dgwindow.h +++ b/plugingui/dgwindow.h @@ -26,8 +26,9 @@ */ #pragma once -#include "window.h" +#include +#include "window.h" #include "label.h" #include "lineedit.h" #include "checkbox.h" @@ -37,10 +38,6 @@ #include "filebrowser.h" #include "layout.h" -#include - -class MessageHandler; - namespace GUI { class Config; @@ -49,8 +46,7 @@ class File; class DGWindow : public Window { public: - DGWindow(void* native_window, MessageHandler& messageHandler, Config& config, - Settings& settings); + DGWindow(void* native_window, Config& config, Settings& settings); Header* header; @@ -68,6 +64,9 @@ public: Knob* falloffKnob; FileBrowser* fileBrowser; + void setDrumKitLoadStatus(LoadStatus load_status); + void setMidiMapLoadStatus(LoadStatus load_status); + protected: // From Widget: void repaintEvent(RepaintEvent* repaintEvent) override; @@ -81,7 +80,6 @@ private: void selectKitFile(const std::string& filename); void selectMapFile(const std::string& filename); - MessageHandler& messageHandler; Config& config; VBoxLayout layout{this}; diff --git a/plugingui/eventhandler.h b/plugingui/eventhandler.h index 1fdb1e8..490c515 100644 --- a/plugingui/eventhandler.h +++ b/plugingui/eventhandler.h @@ -26,9 +26,10 @@ */ #pragma once +#include + #include "guievent.h" #include "nativewindow.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/filebrowser.h b/plugingui/filebrowser.h index 04b34f6..bc2019f 100644 --- a/plugingui/filebrowser.h +++ b/plugingui/filebrowser.h @@ -26,15 +26,15 @@ */ #pragma once -#include "widget.h" +#include +#include "widget.h" #include "button.h" #include "listbox.h" #include "lineedit.h" #include "label.h" #include "image.h" #include "directory.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/knob.h b/plugingui/knob.h index 10d91d6..d144184 100644 --- a/plugingui/knob.h +++ b/plugingui/knob.h @@ -26,10 +26,11 @@ */ #pragma once +#include + #include "widget.h" #include "image.h" #include "font.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/layout.h b/plugingui/layout.h index 55cc93f..49bf75c 100644 --- a/plugingui/layout.h +++ b/plugingui/layout.h @@ -29,7 +29,7 @@ #include #include -#include "notifier.h" +#include namespace GUI { diff --git a/plugingui/listboxbasic.h b/plugingui/listboxbasic.h index 7953dc3..2ebe845 100644 --- a/plugingui/listboxbasic.h +++ b/plugingui/listboxbasic.h @@ -29,11 +29,12 @@ #include #include +#include + #include "widget.h" #include "font.h" #include "painter.h" #include "scrollbar.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/listboxthin.h b/plugingui/listboxthin.h index 3139ecc..1617234 100644 --- a/plugingui/listboxthin.h +++ b/plugingui/listboxthin.h @@ -29,10 +29,11 @@ #include #include +#include + #include "widget.h" #include "painter.h" #include "listboxbasic.h" -#include "notifier.h" namespace GUI { diff --git a/plugingui/notifier.h b/plugingui/notifier.h deleted file mode 100644 index 9e9f6eb..0000000 --- a/plugingui/notifier.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * notifier.h - * - * Thu Sep 3 15:48:39 CEST 2015 - * Copyright 2015 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#pragma once - -#include -#include -#include -#include -#include - -namespace aux -{ - template - struct placeholder - { - }; -} - -namespace std -{ - template - struct is_placeholder> - : integral_constant - { - }; -} - -namespace aux -{ - // std::integer_sequence introduced in C++14 so remove this once we start requiring that. - - template - struct int_sequence - { - }; - - template - struct gen_int_sequence - : gen_int_sequence - { - }; - - template - struct gen_int_sequence<0, Ns...> - : int_sequence - { - }; -}; - - -namespace GUI { - -class Listener; -class NotifierBase { -public: - virtual void disconnect(Listener* object) {} -}; - -class Listener { -public: - virtual ~Listener() - { - for(auto signal : signals) - { - signal->disconnect(this); - } - } - - void registerNotifier(NotifierBase* signal) - { - signals.insert(signal); - } - - void unregisterNotifier(NotifierBase* signal) - { - signals.erase(signal); - } - -private: - std::set signals; -}; - -template -class Notifier : public NotifierBase { -public: - Notifier() {} - - //! \brief When dtor is called it will automatically disconnect all its listeners. - ~Notifier() - { - for(auto& slot : slots) - { - slot.first->unregisterNotifier(this); - } - } - - using callback_type = std::function; - - //! \brief Connect object to this Notifier. - template - void connect(O* p, const F& fn) - { - slots[p] = std::move(construct_mem_fn(fn, p, aux::gen_int_sequence{})); - if(p && dynamic_cast(p)) - { - dynamic_cast(p)->registerNotifier(this); - } - } - - //! \brief Disconnect object from this Notifier. - void disconnect(Listener* object) - { - slots.erase(object); - } - - //! \brief Activate this notifier by pretending it is a function. - //! Example: Notifier foo; foo(42); - void operator()(Args... args) - { - for(auto& slot : slots) - { - slot.second(args...); - } - } - -private: - std::map slots; - - template - callback_type construct_mem_fn(const F& fn, O* p, aux::int_sequence) const - { - return std::bind(fn, p, aux::placeholder{}...); - } - -}; - -} // GUI:: - -#define CONNECT(SRC, SIG, TAR, SLO) (SRC)->SIG.connect(TAR, SLO) diff --git a/plugingui/plugingui.cc b/plugingui/plugingui.cc index 9bac007..2802c44 100644 --- a/plugingui/plugingui.cc +++ b/plugingui/plugingui.cc @@ -26,18 +26,17 @@ */ #include "plugingui.h" +#include + #include #include "pluginconfig.h" -#include "messagehandler.h" - -#include namespace GUI { -PluginGUI::PluginGUI(void* native_window) - : MessageReceiver(MSGRCV_UI) - , native_window(native_window) +PluginGUI::PluginGUI(Settings& settings, void* native_window) + : native_window(native_window) + , settings(settings) { init(); } @@ -46,70 +45,6 @@ PluginGUI::~PluginGUI() { } -void PluginGUI::handleMessage(Message *msg) -{ - Painter p(*window);// Make sure we only redraw buffer once (set refcount to 1) - - switch(msg->type()) { - case Message::LoadStatus: - { - LoadStatusMessage *ls = (LoadStatusMessage*)msg; - window->drumkitFileProgress->setProgress((float)ls->numer_of_files_loaded / - (float)ls->number_of_files); - if(ls->numer_of_files_loaded == ls->number_of_files) - { - window->drumkitFileProgress->setState(ProgressBarState::Green); - } - } - break; - case Message::LoadStatusMidimap: - { - LoadStatusMessageMidimap *ls = (LoadStatusMessageMidimap*)msg; - window->midimapFileProgress->setProgress(1); - if(ls->success) - { - window->midimapFileProgress->setState(ProgressBarState::Green); - } - else - { - window->midimapFileProgress->setState(ProgressBarState::Red); - } - } - break; - case Message::EngineSettingsMessage: - { - EngineSettingsMessage *settings = (EngineSettingsMessage *)msg; - window->lineedit->setText(settings->drumkitfile); - if(settings->drumkit_loaded) - { - window->drumkitFileProgress->setProgress(1); - window->drumkitFileProgress->setState(ProgressBarState::Green); - } - else - { - window->drumkitFileProgress->setProgress(0); - window->drumkitFileProgress->setState(ProgressBarState::Blue); - } - window->lineedit2->setText(settings->midimapfile); - if(settings->midimap_loaded) - { - window->midimapFileProgress->setProgress(1); - window->midimapFileProgress->setState(ProgressBarState::Green); - } - else - { - window->midimapFileProgress->setProgress(0); - window->midimapFileProgress->setState(ProgressBarState::Blue); - } - window->velocityCheck->setChecked(settings->enable_velocity_modifier); - window->attackKnob->setValue(settings->velocity_modifier_weight); - window->falloffKnob->setValue(settings->velocity_modifier_falloff); - } - default: - break; - } -} - bool PluginGUI::processEvents() { if(!initialised) @@ -118,69 +53,13 @@ bool PluginGUI::processEvents() } window->eventHandler()->processEvents(); - //handleMessages(); - - static bool foo = false; - static int t = 0; - if(t != time(nullptr)) - { - t = time(nullptr); - foo = !foo; - float v = settings.velocity_modifier_falloff.load(); - v += 0.1f; - settings.velocity_modifier_falloff.store(v); - } - - Painter p(*window); - - // Run through all settings one at a time propagate changes to the UI. - if(getter.enable_velocity_modifier.hasChanged()) - { - enable_velocity_modifier_notifier(getter.enable_velocity_modifier.getValue()); - } - if(getter.velocity_modifier_falloff.hasChanged()) { - velocity_modifier_falloff_notifier(getter.velocity_modifier_falloff.getValue()); - } + Painter p(*window); - if(getter.velocity_modifier_weight.hasChanged()) - { - velocity_modifier_weight_notifier(getter.velocity_modifier_weight.getValue()); - } - - if(getter.enable_velocity_randomiser.hasChanged()) - { - enable_velocity_randomiser_notifier(getter.enable_velocity_randomiser.getValue()); + settings_notifier.evaluate(); } - if(getter.velocity_randomiser_weight.hasChanged()) - { - velocity_randomiser_weight_notifier(getter.velocity_randomiser_weight.getValue()); - } - - if(getter.samplerate.hasChanged()) - { - samplerate_notifier(getter.samplerate.getValue()); - } - - if(getter.enable_resampling.hasChanged()) - { - enable_resampling_notifier(getter.enable_resampling.getValue()); - } - - if(getter.number_of_files.hasChanged() || - getter.number_of_files_loaded.hasChanged()) - { - drumkit_file_progress_notifier((float)getter.number_of_files_loaded.getValue() / - (float)getter.number_of_files.getValue()); - } - - //if(getter.current_file.hasChanged()) - //{ - // current_file_notifier(getter.current_file.getValue()); - //} - if(closing) { closeNotifier(); @@ -198,41 +77,51 @@ void PluginGUI::init() config = new Config(); config->load(); - window = new DGWindow(native_window, msghandler, *config, settings); + window = new DGWindow(native_window, *config, settings); + + + CONNECT(this, settings_notifier.drumkit_file, + window->lineedit, &LineEdit::setText); + CONNECT(this, settings_notifier.drumkit_load_status, + window, &DGWindow::setDrumKitLoadStatus); - CONNECT(this, enable_velocity_modifier_notifier, + CONNECT(this, settings_notifier.midimap_file, + window->lineedit2, &LineEdit::setText); + CONNECT(this, settings_notifier.midimap_load_status, + window, &DGWindow::setMidiMapLoadStatus); + + CONNECT(this, settings_notifier.enable_velocity_modifier, window->velocityCheck, &CheckBox::setChecked); - CONNECT(this, velocity_modifier_falloff_notifier, + CONNECT(this, settings_notifier.velocity_modifier_falloff, window->falloffKnob, &Knob::setValue); - CONNECT(this, velocity_modifier_weight_notifier, + CONNECT(this, settings_notifier.velocity_modifier_weight, window->attackKnob, &Knob::setValue); - //CONNECT(this, enable_velocity_randomiser_notifier, - // window->velocityCheck, &CheckBox::setChecked); - //CONNECT(this, velocity_randomiser_weight_notifier, - // window->velocityCheck, &CheckBox::setChecked); + // TODO: + //CONNECT(this, settings_notifier.enable_velocity_randomiser, + // window->, &CheckBox::setChecked); + //CONNECT(this, settings_notifier.velocity_randomiser_weight, + // window->, &Knob::setValue); + + //CONNECT(this, settings_notifier.samplerate, + // window->, &Knob::setValue); - //CONNECT(this, samplerate_notifier, - // window->velocityCheck, &CheckBox::setChecked); + //CONNECT(this, settings_notifier.enable_resampling, + // window->, &CheckBox::setChecked); - //CONNECT(this, enable_resampling_notifier, - // window->velocityCheck, &CheckBox::setChecked); + CONNECT(this, settings_notifier.number_of_files, + window->drumkitFileProgress, &ProgressBar::setTotal); - CONNECT(this, drumkit_file_progress_notifier, - window->drumkitFileProgress, &ProgressBar::setProgress); + CONNECT(this, settings_notifier.number_of_files_loaded, + window->drumkitFileProgress, &ProgressBar::setValue); auto eventHandler = window->eventHandler(); CONNECT(eventHandler, closeNotifier, this, &PluginGUI::closeEventHandler); window->show(); - { // Request all engine settings - EngineSettingsMessage *msg = new EngineSettingsMessage(); - msghandler.sendMessage(MSGRCV_ENGINE, msg); - } - initialised = true; } diff --git a/plugingui/plugingui.h b/plugingui/plugingui.h index ca31c41..04b0a29 100644 --- a/plugingui/plugingui.h +++ b/plugingui/plugingui.h @@ -26,24 +26,20 @@ */ #pragma once +#include +#include + #include "dgwindow.h" #include "eventhandler.h" - #include "pluginconfig.h" -#include - -#include "messagereceiver.h" -#include "notifier.h" - namespace GUI { class PluginGUI - : public MessageReceiver - , public Listener + : public Listener { public: - PluginGUI(void* native_window = nullptr); + PluginGUI(Settings& settings, void* native_window = nullptr); virtual ~PluginGUI(); //! Process all events and messages in queue @@ -56,9 +52,6 @@ public: void show(); void hide(); - - void handleMessage(Message* msg); - DGWindow* window{nullptr}; EventHandler* eventhandler{nullptr}; @@ -66,21 +59,6 @@ public: Notifier<> closeNotifier; - // Setting notifiers: - Notifier enable_velocity_modifier_notifier; - Notifier velocity_modifier_falloff_notifier; - Notifier velocity_modifier_weight_notifier; - - Notifier enable_velocity_randomiser_notifier; - Notifier velocity_randomiser_weight_notifier; - - Notifier samplerate_notifier; - - Notifier enable_resampling_notifier; - - Notifier drumkit_file_progress_notifier; - //Notifier current_file_notifier; - // Support old interface a little while longer.. void setWindowClosedCallback(void (*handler)(void*), void* ptr); @@ -97,8 +75,8 @@ private: void (*windowClosedHandler)(void *){nullptr}; void *windowClosedPtr{nullptr}; - Settings settings; - SettingsGetter getter{settings}; + Settings& settings; + SettingsNotifier settings_notifier{settings}; }; } // GUI:: diff --git a/plugingui/progressbar.cc b/plugingui/progressbar.cc index 932f17c..f934664 100644 --- a/plugingui/progressbar.cc +++ b/plugingui/progressbar.cc @@ -26,6 +26,8 @@ */ #include "progressbar.h" +#include + namespace GUI { ProgressBar::ProgressBar(Widget *parent) @@ -46,9 +48,6 @@ ProgressBar::ProgressBar(Widget *parent) bar_green.left = new Image(":progress_front_green_l.png"); bar_green.right = new Image(":progress_front_green_r.png"); bar_green.center = new Image(":progress_front_green_c.png"); - - state = ProgressBarState::Blue; - _progress = .5; } ProgressBar::~ProgressBar() @@ -79,22 +78,31 @@ void ProgressBar::setState(ProgressBarState state) } } -float ProgressBar::progress() +void ProgressBar::setTotal(int total) { - return _progress; + if(this->total != total) + { + this->total = total; + repaintEvent(nullptr); + } } -void ProgressBar::setProgress(float progress) +void ProgressBar::setValue(int value) { - _progress = progress; - repaintEvent(nullptr); + if(this->value != value) + { + this->value = value; + repaintEvent(nullptr); + } } void ProgressBar::repaintEvent(RepaintEvent* repaintEvent) { Painter p(*this); - int max = width() * _progress; + float progress = (float)value / (float)total; + + int max = width() * progress; p.clear(); diff --git a/plugingui/progressbar.h b/plugingui/progressbar.h index d5f6c61..d48a8b5 100644 --- a/plugingui/progressbar.h +++ b/plugingui/progressbar.h @@ -46,8 +46,8 @@ public: ProgressBar(Widget *parent); ~ProgressBar(); - float progress(); - void setProgress(float progress); + void setTotal(int total); + void setValue(int value); void setState(ProgressBarState state); @@ -56,7 +56,7 @@ protected: virtual void repaintEvent(RepaintEvent* repaintEvent) override; private: - ProgressBarState state; + ProgressBarState state{ProgressBarState::Blue}; Painter::Bar bar_bg; @@ -64,7 +64,8 @@ private: Painter::Bar bar_blue; Painter::Bar bar_red; - float _progress; + int total{0}; + int value{0}; }; } // GUI:: diff --git a/plugingui/testmain.cc b/plugingui/testmain.cc index b3a0d8d..84d813d 100644 --- a/plugingui/testmain.cc +++ b/plugingui/testmain.cc @@ -33,13 +33,10 @@ #include -// Dummy Engine class. -class Engine : public MessageHandler { -public: - void handleMessage(Message *msg) {} -}; +#include +#include -class TestMain : public GUI::Listener { +class TestMain : public Listener { public: TestMain() { @@ -67,7 +64,8 @@ public: bool running = true; - GUI::PluginGUI gui; + Settings settings; + GUI::PluginGUI gui{settings}; }; int main() diff --git a/src/Makefile.am b/src/Makefile.am index 9dd6c29..4d167af 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,13 +23,11 @@ EXTRA_DIST = \ instrument.h \ instrumentparser.h \ memchecker.h \ - message.h \ - messagehandler.h \ - messagereceiver.h \ midimapparser.h \ midimapper.h \ mutex.h \ nolocale.h \ + notifier.h \ path.h \ powerlist.h \ rangemap.h \ @@ -62,8 +60,6 @@ EXTRA_DIST = \ instrument.cc \ instrumentparser.cc \ memchecker.cc \ - messagehandler.cc \ - messagereceiver.cc \ midimapparser.cc \ midimapper.cc \ mutex.cc \ diff --git a/src/Makefile.am.drumgizmo b/src/Makefile.am.drumgizmo index e707fe2..6fddded 100644 --- a/src/Makefile.am.drumgizmo +++ b/src/Makefile.am.drumgizmo @@ -20,8 +20,6 @@ DRUMGIZMO_SOURCES = \ $(top_srcdir)/src/instrument.cc \ $(top_srcdir)/src/instrumentparser.cc \ $(top_srcdir)/src/memchecker.cc \ - $(top_srcdir)/src/messagehandler.cc \ - $(top_srcdir)/src/messagereceiver.cc \ $(top_srcdir)/src/midimapparser.cc \ $(top_srcdir)/src/midimapper.cc \ $(top_srcdir)/src/mutex.cc \ diff --git a/src/atomic.h b/src/atomic.h index e0b80b1..95a5e9d 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -116,7 +116,67 @@ public: return data; } + bool operator==(const T& other) const + { + std::lock_guard lock{mutex}; + return other == data; + } + + bool operator!=(const T& other) const + { + std::lock_guard lock{mutex}; + return !(other == data); + } + + bool operator==(const Atomic& other) const + { + std::lock_guard lock{mutex}; + return other.load() == data; + } + + bool operator!=(const Atomic& other) const + { + std::lock_guard lock{mutex}; + return !(other.load() == data); + } + private: T data; mutable std::mutex mutex; }; + +//! Getter utility class. +template class SettingRef +{ +public: + SettingRef(Atomic& value) + : value(value) + { + // string isn't lock free either + assert((std::is_same::value || value.is_lock_free())); + } + + bool hasChanged() + { + T tmp = cache; + cache.exchange(value); + + if(firstAccess) + { + firstAccess = false; + return true; + } + + return cache != tmp; + } + + T getValue() const + { + return cache; + } + +private: + bool firstAccess{true}; + Atomic& value; + Atomic cache; +}; diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index f769f4e..aa6be23 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -38,6 +38,7 @@ #include #include +#include #include "drumkitparser.h" #include "audioinputenginemidi.h" @@ -47,8 +48,7 @@ DrumGizmo::DrumGizmo(Settings& settings, AudioOutputEngine *o, AudioInputEngine *i) - : MessageReceiver(MSGRCV_ENGINE) - , loader(settings) + : loader(settings) , oe(o) , ie(i) , framesize(0) @@ -69,9 +69,12 @@ DrumGizmo::~DrumGizmo() bool DrumGizmo::loadkit(std::string file) { + settings.drumkit_load_status.store(LoadStatus::Idle); + if(file == "") { - return 1; + settings.drumkit_load_status.store(LoadStatus::Error); + return false; } DEBUG(drumgizmo, "loadkit(%s)\n", file.c_str()); @@ -82,20 +85,24 @@ bool DrumGizmo::loadkit(std::string file) // Delete all Channels, Instruments, Samples and AudioFiles. kit.clear(); + settings.drumkit_load_status.store(LoadStatus::Loading); + DrumKitParser parser(settings, kit); if(parser.parseFile(file)) { ERR(drumgizmo, "Drumkit parser failed: %s\n", file.c_str()); + settings.drumkit_load_status.store(LoadStatus::Error); return false; } - // Check if there is enough free RAM to load the drumkit. - if(!memchecker.enoughFreeMemory(kit)) - { - printf("WARNING: " - "There doesn't seem to be enough RAM available to load the kit.\n" - "Trying to load it anyway...\n"); - } + // TODO: Re-introduce when the code has been moved to the loader thread. + //// Check if there is enough free RAM to load the drumkit. + //if(!memchecker.enoughFreeMemory(kit)) + //{ + // printf("WARNING: " + // "There doesn't seem to be enough RAM available to load the kit.\n" + // "Trying to load it anyway...\n"); + //} loader.loadKit(&kit); @@ -126,79 +133,6 @@ bool DrumGizmo::init() return true; } -void DrumGizmo::handleMessage(Message *msg) -{ - DEBUG(msg, "got message."); - switch(msg->type()) { - case Message::LoadDrumKit: - { - DEBUG(msg, "got LoadDrumKitMessage message."); - LoadDrumKitMessage *m = (LoadDrumKitMessage*)msg; - loadkit(m->drumkitfile); - //init(true); - } - break; - case Message::LoadMidimap: - DEBUG(msg, "got LoadMidimapMessage message."); - if(!ie->isMidiEngine()) - { - break; - } - { - AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; - LoadMidimapMessage *m = (LoadMidimapMessage*)msg; - bool ret = aim->loadMidiMap(m->midimapfile, kit.instruments); - - LoadStatusMessageMidimap *ls = new LoadStatusMessageMidimap(); - ls->success = ret; - msghandler.sendMessage(MSGRCV_UI, ls); - } - break; - case Message::EngineSettingsMessage: - { - bool mmap_loaded = false; - std::string mmapfile; - if(ie->isMidiEngine()) - { - AudioInputEngineMidi *aim = (AudioInputEngineMidi*)ie; - mmapfile = aim->getMidimapFile(); - mmap_loaded = aim->isValid(); - } - - EngineSettingsMessage *msg = new EngineSettingsMessage(); - msg->midimapfile = mmapfile; - msg->midimap_loaded = mmap_loaded; - msg->drumkitfile = kit.getFile(); - msg->drumkit_loaded = loader.isDone(); - msg->enable_velocity_modifier = settings.enable_velocity_modifier.load(); - msg->velocity_modifier_falloff = settings.velocity_modifier_falloff.load(); - msg->velocity_modifier_weight = settings.velocity_modifier_weight.load(); - msg->enable_velocity_randomiser = settings.enable_velocity_randomiser.load(); - msg->velocity_randomiser_weight = settings.velocity_randomiser_weight.load(); - msghandler.sendMessage(MSGRCV_UI, msg); - } - break; - case Message::ChangeSettingMessage: - { - ChangeSettingMessage *ch = (ChangeSettingMessage*)msg; - switch(ch->name) { - case ChangeSettingMessage::enable_velocity_modifier: - settings.enable_velocity_modifier.store(ch->value); - break; - case ChangeSettingMessage::velocity_modifier_weight: - settings.velocity_modifier_weight.store(ch->value); - break; - case ChangeSettingMessage::velocity_modifier_falloff: - settings.velocity_modifier_falloff.store(ch->value); - break; - } - } - break; - default: - break; - } -} - void DrumGizmo::setFrameSize(size_t framesize) { // If we are resampling override the frame size. @@ -260,8 +194,31 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) { setFrameSize(nsamples); - // Handle engine messages, at most one in each iteration: - handleMessages(1); + // TODO: Move this to DrumKitLoader thread. + if(getter.drumkit_file.hasChanged()) + { + loadkit(getter.drumkit_file.getValue()); + } + + // TODO: Move this to DrumKitLoader thread. + if(getter.midimap_file.hasChanged()) + { + auto ie_midi = dynamic_cast(ie); + if(ie_midi) + { + settings.midimap_load_status.store(LoadStatus::Loading); + bool ret = ie_midi->loadMidiMap(getter.midimap_file.getValue(), + kit.instruments); + if(ret) + { + settings.midimap_load_status.store(LoadStatus::Done); + } + else + { + settings.midimap_load_status.store(LoadStatus::Error); + } + } + } ie->pre(); oe->pre(nsamples); @@ -712,8 +669,8 @@ bool DrumGizmo::setConfigString(std::string cfg) ConfigParser p; if(p.parseString(cfg)) { - ERR(drumgizmo, "Config parse error.\n"); - return false; + ERR(drumgizmo, "Config parse error.\n"); + return false; } if(p.value("enable_velocity_modifier") != "") @@ -747,27 +704,15 @@ bool DrumGizmo::setConfigString(std::string cfg) } std::string newkit = p.value("drumkitfile"); - if(newkit != "" && kit.getFile() != newkit) + if(newkit != "") { - /* - if(!loadkit(p.values["drumkitfile"])) - { - return false; - } - init(true); - */ - LoadDrumKitMessage *msg = new LoadDrumKitMessage(); - msg->drumkitfile = newkit; - msghandler.sendMessage(MSGRCV_ENGINE, msg); + settings.drumkit_file.store(newkit); } std::string newmidimap = p.value("midimapfile"); if(newmidimap != "") { - //midimapfile = newmidimap; - LoadMidimapMessage *msg = new LoadMidimapMessage(); - msg->midimapfile = newmidimap; - msghandler.sendMessage(MSGRCV_ENGINE, msg); + settings.midimap_file.store(newmidimap); } return true; diff --git a/src/drumgizmo.h b/src/drumgizmo.h index 63348da..7af5dbb 100644 --- a/src/drumgizmo.h +++ b/src/drumgizmo.h @@ -31,25 +31,15 @@ #include "audiooutputengine.h" #include "audioinputengine.h" - #include "events.h" #include "audiofile.h" #include "drumkit.h" #include "memchecker.h" - #include "drumkitloader.h" #include "audiocache.h" - #include "mutex.h" - -#include "message.h" - -#include "messagereceiver.h" - #include "chresampler.h" - #include "configfile.h" - #include "settings.h" #define MAX_NUM_CHANNELS 64 @@ -57,7 +47,6 @@ #define RESAMPLER_INPUT_BUFFER 64 class DrumGizmo - : public MessageReceiver { public: DrumGizmo(Settings& settings, @@ -77,8 +66,6 @@ public: std::string configString(); bool setConfigString(std::string cfg); - void handleMessage(Message *msg); - int samplerate(); void setSamplerate(int samplerate); @@ -112,4 +99,5 @@ protected: std::vector events; Settings& settings; + SettingsGetter getter{settings}; }; diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index 3cb4b68..f9e45db 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -184,18 +184,14 @@ void DrumKitLoader::thread_main() audiofile->load(preload_size); } - loaded++; + ++loaded; - if(loaded % fraction == 0 || loaded == total_num_audiofiles) + settings.number_of_files.store(total_num_audiofiles); + settings.number_of_files_loaded.store(loaded); + + if(total_num_audiofiles == loaded) { - //LoadStatusMessage *ls = new LoadStatusMessage(); - //ls->number_of_files = total_num_audiofiles; - //ls->numer_of_files_loaded = loaded; - //ls->current_file = filename; - //msghandler.sendMessage(MSGRCV_UI, ls); - settings.number_of_files.store(total_num_audiofiles); - settings.number_of_files_loaded.store(loaded); - //settings.current_file.store(filename); + settings.drumkit_load_status.store(LoadStatus::Done); } } diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc index 221e921..048a05b 100644 --- a/src/drumkitparser.cc +++ b/src/drumkitparser.cc @@ -34,7 +34,7 @@ #include "path.h" #include "drumgizmo.h" -DrumKitParser::DrumKitParser(Settings& setting, DrumKit& k) +DrumKitParser::DrumKitParser(Settings& settings, DrumKit& k) : kit(k) , refs(REFSFILE) , settings(settings) diff --git a/src/instrument.cc b/src/instrument.cc index f187de0..cc052e9 100644 --- a/src/instrument.cc +++ b/src/instrument.cc @@ -42,7 +42,7 @@ Instrument::Instrument(Settings& settings) Instrument::~Instrument() { - magic = NULL; + magic = nullptr; DEBUG(instrument, "delete %p\n", this); std::vector::iterator i = audiofiles.begin(); @@ -60,8 +60,6 @@ bool Instrument::isValid() const Sample* Instrument::sample(level_t level, size_t pos) { - Sample *sample = NULL; - // Read out all values from settings. auto enable_velocity_randomiser = settings.enable_velocity_randomiser.load(); auto velocity_randomiser_weight = settings.velocity_randomiser_weight.load(); @@ -70,6 +68,8 @@ Sample* Instrument::sample(level_t level, size_t pos) auto enable_velocity_modifier = settings.enable_velocity_modifier.load(); auto velocity_modifier_weight = settings.velocity_modifier_weight.load(); + Sample *sample = nullptr; + if(enable_velocity_modifier == false) { mod = 1.0; @@ -78,14 +78,13 @@ Sample* Instrument::sample(level_t level, size_t pos) if(enable_velocity_randomiser) { - float r = rand.floatInRange(-0.5f, 0.5f); - r *= velocity_randomiser_weight * 2; // ex. random number [-0.1;0.1] + float r = rand.floatInRange(-1.0 * velocity_randomiser_weight, + velocity_randomiser_weight); level += r; if(level > 1.0) { level = 1.0; } - if(level < 0.0) { level = 0.0; @@ -94,8 +93,7 @@ Sample* Instrument::sample(level_t level, size_t pos) if(enable_velocity_modifier) { - mod += (pos - lastpos) / - (samplerate * velocity_modifier_falloff); + mod += (pos - lastpos) / (samplerate * velocity_modifier_falloff); if(mod > 1.0) { mod = 1.0; @@ -113,11 +111,10 @@ Sample* Instrument::sample(level_t level, size_t pos) std::vector s = samples.get(level * mod); if(s.size() == 0) { - return NULL; + return nullptr; } - //size_t idx = ::rand()%(s.size()); - sample = rand.choose(s); + sample = rand.choose(s); } if(enable_velocity_modifier) diff --git a/src/message.h b/src/message.h deleted file mode 100644 index 71d0da6..0000000 --- a/src/message.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * message.h - * - * Wed Mar 20 15:50:57 CET 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#ifndef __DRUMGIZMO_MESSAGE_H__ -#define __DRUMGIZMO_MESSAGE_H__ - -#include - -class MessageHandler; - -class Message { -public: - typedef enum { - // Engine -> GUI Messages: - LoadStatus, // Signal GUI the current load status. - LoadStatusMidimap, // Signal GUI the current load status of the midimap. - - // GUI -> Engine, Engine -> Engine Messages: - LoadDrumKit, // Signal engine to load drumkit. - LoadMidimap, // Signal engine to load midimap. - EngineSettingsMessage, // Request or receive engine settings. - ChangeSettingMessage, // Update named setting in engine. - } type_t; - - typedef enum { - NormalProcessing, // Just add to the queue - FilterMultiple, // Ignore top message if it has the same type. - // SyncWait, // Block the send call until the message has been handled by the receiver. - } processing_mode_t; - - virtual ~Message() {} - virtual type_t type() = 0; - virtual processing_mode_t processing_mode() { return NormalProcessing; } -}; - -class LoadStatusMessage : public Message { -public: - type_t type() { return Message::LoadStatus; } - processing_mode_t processing_mode() { return FilterMultiple; } - unsigned int number_of_files; - unsigned int numer_of_files_loaded; - std::string current_file; -}; - -class LoadStatusMessageMidimap : public Message { -public: - type_t type() { return Message::LoadStatusMidimap; } - bool success; -}; - -class LoadDrumKitMessage : public Message { -public: - type_t type() { return Message::LoadDrumKit; } - std::string drumkitfile; -}; - -class LoadMidimapMessage : public Message { -public: - type_t type() { return Message::LoadMidimap; } - std::string midimapfile; -}; - -class EngineSettingsMessage : public Message { -public: - type_t type() { return Message::EngineSettingsMessage; } - std::string midimapfile; - bool midimap_loaded; - - std::string drumkitfile; - bool drumkit_loaded; - - float enable_velocity_modifier; - float velocity_modifier_falloff; - float velocity_modifier_weight; - float enable_velocity_randomiser; - float velocity_randomiser_weight; -}; - -class ChangeSettingMessage : public Message { -public: - typedef enum { - enable_velocity_modifier, - velocity_modifier_weight, - velocity_modifier_falloff, - } setting_name_t; - - ChangeSettingMessage(setting_name_t n, float v) { - name = n; - value = v; - } - - type_t type() { return Message::ChangeSettingMessage; } - - setting_name_t name; - float value; -}; - -#endif/*__DRUMGIZMO_MESSAGE_H__*/ diff --git a/src/messagehandler.cc b/src/messagehandler.cc deleted file mode 100644 index 7a0c7ea..0000000 --- a/src/messagehandler.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * messagehandler.cc - * - * Fri Jun 14 20:30:43 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "messagehandler.h" - -#include - -#include "messagereceiver.h" - -// Global messagehandler: -MessageHandler msghandler; - -MessageHandler::MessageHandler() -{ -} - -void MessageHandler::addReceiver(message_receiver_id_t id, - MessageReceiver *receiver) -{ - MutexAutolock l(mutex); - - receivers[id] = receiver; -} - -void MessageHandler::removeReceiver(MessageReceiver *receiver) -{ - MutexAutolock l(mutex); - - std::map::iterator i = - receivers.begin(); - while(i != receivers.end()) { - if(i->second == receiver) { - receivers.erase(i); - break; - } - i++; - } -} - -bool MessageHandler::sendMessage(message_receiver_id_t id, Message* msg) -{ - MutexAutolock l(mutex); - - if(receivers.find(id) == receivers.end()) { - //WARN(msghandler, "Could not find id %d\n", id); - delete msg; - return false; - } - - //DEBUG(msghandler, "Sending message to id %d\n", id); - - MessageReceiver *receiver = receivers[id]; - /* // This code causes sporadic segfaults on windows. - if(msg->processing_mode() == Message::FilterMultiple) { - Message *pmsg; - MutexAutolock lock(receiver->message_mutex); // Make peek/receive atomic. - while( (pmsg = receiver->peekMessage()) != NULL) { - if(pmsg->type() != msg->type()) break; - // Remove all old messages with same type. - delete receiver->receiveMessage(); - } - } - */ - receiver->sendMessage(msg); - return true; -} diff --git a/src/messagehandler.h b/src/messagehandler.h deleted file mode 100644 index 2b6c40e..0000000 --- a/src/messagehandler.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * messagehandler.h - * - * Fri Jun 14 20:30:43 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#ifndef __DRUMGIZMO_MESSAGEHANDLER_H__ -#define __DRUMGIZMO_MESSAGEHANDLER_H__ - -#include - -#include "message.h" -#include "mutex.h" - -typedef enum { - MSGRCV_ENGINE = 1, - MSGRCV_UI = 2, - MSGRCV_LOADER = 3, -} message_receiver_id_t; - -class MessageReceiver; - -class MessageHandler { -public: - MessageHandler(); - - void addReceiver(message_receiver_id_t id, MessageReceiver *receiver); - void removeReceiver(MessageReceiver *receiver); - - /** - * Send Message to receiver with specified id. - * @return Return true if id is registered. Return false if id is not - * currently registered. - */ - bool sendMessage(message_receiver_id_t id, Message* msg); - -private: - std::map receivers; - - Mutex mutex; -}; - -// Global MessageHandler; -extern MessageHandler msghandler; - -#endif/*__DRUMGIZMO_MESSAGEHANDLER_H__*/ diff --git a/src/messagereceiver.cc b/src/messagereceiver.cc deleted file mode 100644 index 590c98a..0000000 --- a/src/messagereceiver.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * messagereceiver.cc - * - * Sun Jun 16 12:09:06 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#include "messagereceiver.h" - -#include - -MessageReceiver::MessageReceiver(message_receiver_id_t id) -{ - msghandler.addReceiver(id, this); -} - -MessageReceiver::~MessageReceiver() -{ - msghandler.removeReceiver(this); -} - -void MessageReceiver::sendMessage(Message *msg) -{ - MutexAutolock l(message_mutex); - - message_queue.push_back(msg); -} - -Message *MessageReceiver::receiveMessage() -{ - Message *msg = NULL; - if(message_queue.size()) { - msg = message_queue.front(); - message_queue.pop_front(); - } - return msg; -} - -Message *MessageReceiver::peekMessage() -{ - Message *msg = NULL; - if(message_queue.size()) { - msg = message_queue.front(); - } - return msg; -} - -void MessageReceiver::handleMessages(size_t max) -{ - MutexAutolock l(message_mutex); - bool process_all = false; - if(max == 0) process_all = true; - - while((process_all || max--) && peekMessage()) { - Message *msg = receiveMessage(); - handleMessage(msg); - delete msg; - } -} diff --git a/src/messagereceiver.h b/src/messagereceiver.h deleted file mode 100644 index c1a8e60..0000000 --- a/src/messagereceiver.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/*************************************************************************** - * messagereceiver.h - * - * Sun Jun 16 12:09:06 CEST 2013 - * Copyright 2013 Bent Bisballe Nyeng - * deva@aasimon.org - ****************************************************************************/ - -/* - * This file is part of DrumGizmo. - * - * DrumGizmo is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * DrumGizmo is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with DrumGizmo; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ -#ifndef __DRUMGIZMO_MESSAGERECEIVER_H__ -#define __DRUMGIZMO_MESSAGERECEIVER_H__ - -#include - -#include "mutex.h" -#include "message.h" -#include "messagehandler.h" - -class MessageReceiver { - friend class MessageHandler; -public: - MessageReceiver(message_receiver_id_t id); - ~MessageReceiver(); - - /** - * Receive message from the message queue. - */ - Message *receiveMessage(); - - /** - * Receive message from the message queue without removing it. - */ - Message *peekMessage(); - - /** - * Add a message to the message queue. - */ - void sendMessage(Message *msg); - - /** - * Handle messages from the event queue. - * @param max_number_of_events the maximum number of events to be handled in - * this call. 0 means all. - */ - void handleMessages(size_t max_number_of_events = 0); - - /** - * Handler to be implemented in child classes. - * Handles a single event. - */ - virtual void handleMessage(Message *msg) = 0; - -private: - Mutex message_mutex; - std::list message_queue; -}; - -#endif/*__DRUMGIZMO_MESSAGERECEIVER_H__*/ diff --git a/src/notifier.h b/src/notifier.h new file mode 100644 index 0000000..ff59741 --- /dev/null +++ b/src/notifier.h @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * notifier.h + * + * Thu Sep 3 15:48:39 CEST 2015 + * Copyright 2015 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of DrumGizmo. + * + * DrumGizmo is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * DrumGizmo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with DrumGizmo; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#pragma once + +#include +#include +#include +#include +#include + +namespace aux +{ + template + struct placeholder + { + }; +} + +namespace std +{ + template + struct is_placeholder> + : integral_constant + { + }; +} + +namespace aux +{ + // std::integer_sequence introduced in C++14 so remove this once we start requiring that. + + template + struct int_sequence + { + }; + + template + struct gen_int_sequence + : gen_int_sequence + { + }; + + template + struct gen_int_sequence<0, Ns...> + : int_sequence + { + }; +}; + + +//namespace GUI { + +class Listener; +class NotifierBase { +public: + virtual void disconnect(Listener* object) {} +}; + +class Listener { +public: + virtual ~Listener() + { + for(auto signal : signals) + { + signal->disconnect(this); + } + } + + void registerNotifier(NotifierBase* signal) + { + signals.insert(signal); + } + + void unregisterNotifier(NotifierBase* signal) + { + signals.erase(signal); + } + +private: + std::set signals; +}; + +template +class Notifier : public NotifierBase { +public: + Notifier() {} + + //! \brief When dtor is called it will automatically disconnect all its listeners. + ~Notifier() + { + for(auto& slot : slots) + { + slot.first->unregisterNotifier(this); + } + } + + using callback_type = std::function; + + //! \brief Connect object to this Notifier. + template + void connect(O* p, const F& fn) + { + slots[p] = std::move(construct_mem_fn(fn, p, aux::gen_int_sequence{})); + if(p && dynamic_cast(p)) + { + dynamic_cast(p)->registerNotifier(this); + } + } + + //! \brief Disconnect object from this Notifier. + void disconnect(Listener* object) + { + slots.erase(object); + } + + //! \brief Activate this notifier by pretending it is a function. + //! Example: Notifier foo; foo(42); + void operator()(Args... args) + { + for(auto& slot : slots) + { + slot.second(args...); + } + } + +private: + std::map slots; + + template + callback_type construct_mem_fn(const F& fn, O* p, aux::int_sequence) const + { + return std::bind(fn, p, aux::placeholder{}...); + } + +}; + +//} // GUI:: + +#define CONNECT(SRC, SIG, TAR, SLO) (SRC)->SIG.connect(TAR, SLO) diff --git a/src/settings.h b/src/settings.h index b132c1b..c79e4e5 100644 --- a/src/settings.h +++ b/src/settings.h @@ -31,10 +31,25 @@ #include #include "atomic.h" +#include "notifier.h" + +enum class LoadStatus : unsigned int +{ + Idle, + Loading, + Done, + Error +}; //! Engine settings struct Settings { + Atomic drumkit_file; + Atomic drumkit_load_status{LoadStatus::Idle}; + + Atomic midimap_file; + Atomic midimap_load_status{LoadStatus::Idle}; + Atomic enable_velocity_modifier{true}; Atomic velocity_modifier_falloff{0.5f}; Atomic velocity_modifier_weight{0.25f}; @@ -51,45 +66,15 @@ struct Settings Atomic current_file; }; -//! Getter utility class. -template class SettingRef +//! Settings getter class. +struct SettingsGetter { -public: - SettingRef(Atomic& value) - : value(value) - { - // string isn't lock free either - assert((std::is_same::value || value.is_lock_free())); - } - - bool hasChanged() - { - T tmp = cache; - cache.exchange(value); - - if(firstAccess) - { - firstAccess = false; - return true; - } - - return tmp != cache; - } - - T getValue() const - { - return cache; - } + SettingRef drumkit_file; + SettingRef drumkit_load_status; -private: - bool firstAccess{true}; - Atomic& value; - Atomic cache; -}; + SettingRef midimap_file; + SettingRef midimap_load_status; -//! Combined getter class. -struct SettingsGetter -{ SettingRef enable_velocity_modifier; SettingRef velocity_modifier_falloff; SettingRef velocity_modifier_weight; @@ -106,7 +91,11 @@ struct SettingsGetter SettingRef current_file; SettingsGetter(Settings& settings) - : enable_velocity_modifier{settings.enable_velocity_modifier} + : drumkit_file(settings.drumkit_file) + , drumkit_load_status(settings.drumkit_load_status) + , midimap_file(settings.midimap_file) + , midimap_load_status(settings.midimap_load_status) + , enable_velocity_modifier{settings.enable_velocity_modifier} , velocity_modifier_falloff{settings.velocity_modifier_falloff} , velocity_modifier_weight{settings.velocity_modifier_weight} , enable_velocity_randomiser{settings.enable_velocity_randomiser} @@ -120,6 +109,66 @@ struct SettingsGetter } }; +//! Settings change notifier class. +class SettingsNotifier +{ +public: + Notifier drumkit_file; + Notifier drumkit_load_status; + + Notifier midimap_file; + Notifier midimap_load_status; + + Notifier enable_velocity_modifier; + Notifier velocity_modifier_falloff; + Notifier velocity_modifier_weight; + + Notifier enable_velocity_randomiser; + Notifier velocity_randomiser_weight; + + Notifier samplerate; + + Notifier enable_resampling; + + Notifier number_of_files; + Notifier number_of_files_loaded; + Notifier current_file; + + void evaluate() + { +#define EVAL(x) if(settings.x.hasChanged()) { x(settings.x.getValue()); } + + EVAL(drumkit_file); + EVAL(drumkit_load_status); + + EVAL(midimap_file); + EVAL(midimap_load_status); + + EVAL(enable_velocity_modifier); + EVAL(velocity_modifier_falloff); + EVAL(velocity_modifier_weight); + + EVAL(enable_velocity_randomiser); + EVAL(velocity_randomiser_weight); + + EVAL(samplerate); + + EVAL(enable_resampling); + + EVAL(number_of_files); + EVAL(number_of_files_loaded); + EVAL(current_file); + } + + SettingsNotifier(Settings& settings) + : settings(settings) + { + } + +private: + SettingsGetter settings; +}; + // lovely reminder: NO, GLOCKE. NOOOO!! /* enum class IntParams { -- cgit v1.2.3 From fb7bb2ee352cf83a7596a7ed7ba2913a2257e540 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 13 Apr 2016 18:30:56 +0200 Subject: New Semaphore method wait with timeout. --- drumgizmo/output/jackaudio.cc | 1 - src/drumkitloader.cc | 3 +- src/semaphore.cc | 96 +++++++++++++++++++++++++------------------ src/semaphore.h | 24 ++++++----- 4 files changed, 70 insertions(+), 54 deletions(-) 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/src/drumkitloader.cc b/src/drumkitloader.cc index f9e45db..d785bc4 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -32,8 +32,7 @@ #include "drumgizmo.h" DrumKitLoader::DrumKitLoader(Settings& settings) - : semaphore("drumkitloader") - , framesize(0) + : framesize(0) , settings(settings) { run(); diff --git a/src/semaphore.cc b/src/semaphore.cc index cd29bbf..3a4f6c9 100644 --- a/src/semaphore.cc +++ b/src/semaphore.cc @@ -27,87 +27,101 @@ #include "semaphore.h" #include - #include +#include #ifdef WIN32 #include #else -// Make sure we don't include /this/ file... +// Make sure we don't include /this/ files header... #include <../include/semaphore.h> +#include +#include #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::max(), - NULL); // unnamed semaphore + prv->semaphore = CreateSemaphore(nullptr, // default security attributes + initial_count, + std::numeric_limits::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() - (t.tv_sec * timeout.count())) * 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_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 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__*/ -- cgit v1.2.3 From 0ae4539e7f42d21b3ebc8ec1914a32b5cf58d490 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 13 Apr 2016 18:53:25 +0200 Subject: Remove message files. --- plugingui/Makefile.mingw32 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 -- cgit v1.2.3 From c7577fa4ecf6f9858483c5d8b4a46e7caa2b376d Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 15 Apr 2016 21:04:49 +0200 Subject: Fix Semaphore::wait(ms) --- src/semaphore.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/semaphore.cc b/src/semaphore.cc index 3a4f6c9..6172251 100644 --- a/src/semaphore.cc +++ b/src/semaphore.cc @@ -95,10 +95,10 @@ bool Semaphore::wait(const std::chrono::milliseconds& timeout) #else struct timespec t = { // Whole seconds: - (time_t)(timeout.count() % 1000), + (time_t)(timeout.count() / 1000), // Remainder as nanoseconds: - (long)((timeout.count() - (t.tv_sec * timeout.count())) * 1000000) + (long)((timeout.count() - ((timeout.count() / 1000) * 1000)) * 1000000) }; int ret = sem_timedwait(&prv->semaphore, &t); -- cgit v1.2.3 From 35e804b984c28131fe13d229c5a0867762c6e8cf Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 16 Apr 2016 13:23:11 +0200 Subject: Some DrumKitLoader refactoring. --- plugingui/progressbar.cc | 4 +-- plugingui/progressbar.h | 10 +++--- src/drumkitloader.cc | 86 ++++++++++++++++++++++-------------------------- src/drumkitloader.h | 12 +++---- src/settings.h | 12 +++---- 5 files changed, 59 insertions(+), 65 deletions(-) diff --git a/plugingui/progressbar.cc b/plugingui/progressbar.cc index f934664..8a382f5 100644 --- a/plugingui/progressbar.cc +++ b/plugingui/progressbar.cc @@ -78,7 +78,7 @@ void ProgressBar::setState(ProgressBarState state) } } -void ProgressBar::setTotal(int total) +void ProgressBar::setTotal(std::size_t total) { if(this->total != total) { @@ -87,7 +87,7 @@ void ProgressBar::setTotal(int total) } } -void ProgressBar::setValue(int value) +void ProgressBar::setValue(std::size_t value) { if(this->value != value) { diff --git a/plugingui/progressbar.h b/plugingui/progressbar.h index d48a8b5..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(); - void setTotal(int total); - void setValue(int value); + void setTotal(std::size_t total); + void setValue(std::size_t value); void setState(ProgressBarState state); @@ -64,8 +64,8 @@ private: Painter::Bar bar_blue; Painter::Bar bar_red; - int total{0}; - int value{0}; + std::size_t total{0}; + std::size_t value{0}; }; } // GUI:: diff --git a/src/drumkitloader.cc b/src/drumkitloader.cc index d785bc4..3a0e096 100644 --- a/src/drumkitloader.cc +++ b/src/drumkitloader.cc @@ -26,6 +26,8 @@ */ #include "drumkitloader.h" +#include + #include #include "drumkitparser.h" @@ -34,6 +36,7 @@ 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 guard(mutex); load_queue.clear(); } @@ -66,68 +69,48 @@ void DrumKitLoader::stop() void DrumKitLoader::skip() { - MutexAutolock l(mutex); + std::lock_guard 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 guard(mutex); + this->framesize = framesize; + framesize_semaphore.post(); // Signal that the framesize has been set. } bool DrumKitLoader::isDone() { - MutexAutolock l(mutex); + std::lock_guard guard(mutex); return load_queue.size() == 0; } void DrumKitLoader::loadKit(DrumKit *kit) { - MutexAutolock l(mutex); + std::lock_guard 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; + settings.number_of_files.store(total_num_audiofiles); - std::vector::iterator af = instr->audiofiles.begin(); - while(af != instr->audiofiles.end()) - { - AudioFile *audiofile = *af; - load_queue.push_back(audiofile); - af++; - } - - ++i; + // Now actually queue them for loading: + for(auto instr : kit->instruments) + { + std::vector::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 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 guard(mutex); + if(load_queue.size() == 0) { continue; } + AudioFile *audiofile = load_queue.front(); load_queue.pop_front(); filename = audiofile->filename; @@ -185,10 +180,9 @@ void DrumKitLoader::thread_main() ++loaded; - settings.number_of_files.store(total_num_audiofiles); settings.number_of_files_loaded.store(loaded); - if(total_num_audiofiles == loaded) + if(settings.number_of_files.load() == loaded) { settings.drumkit_load_status.store(LoadStatus::Done); } diff --git a/src/drumkitloader.h b/src/drumkitloader.h index 2410074..3fd7ec1 100644 --- a/src/drumkitloader.h +++ b/src/drumkitloader.h @@ -28,10 +28,11 @@ #include #include +#include +#include "mutex.h" #include "thread.h" #include "semaphore.h" -#include "mutex.h" #include "drumkit.h" #include "settings.h" @@ -76,12 +77,11 @@ protected: Semaphore run_semaphore; Semaphore semaphore; Semaphore framesize_semaphore; - Mutex mutex; + std::mutex mutex; volatile bool running{false}; std::list 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/settings.h b/src/settings.h index c79e4e5..6b4e882 100644 --- a/src/settings.h +++ b/src/settings.h @@ -61,8 +61,8 @@ struct Settings Atomic enable_resampling{true}; - Atomic number_of_files; - Atomic number_of_files_loaded; + Atomic number_of_files; + Atomic number_of_files_loaded; Atomic current_file; }; @@ -86,8 +86,8 @@ struct SettingsGetter SettingRef enable_resampling; - SettingRef number_of_files; - SettingRef number_of_files_loaded; + SettingRef number_of_files; + SettingRef number_of_files_loaded; SettingRef current_file; SettingsGetter(Settings& settings) @@ -130,8 +130,8 @@ public: Notifier enable_resampling; - Notifier number_of_files; - Notifier number_of_files_loaded; + Notifier number_of_files; + Notifier number_of_files_loaded; Notifier current_file; void evaluate() -- cgit v1.2.3