summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Nusser <andre.nusser@googlemail.com>2016-03-22 00:40:15 +0100
committerAndré Nusser <andre.nusser@googlemail.com>2016-03-29 22:19:49 +0200
commit0930fdc014bf36fb9e2715b3d14bff5fedf354a9 (patch)
tree9136c06ba9311f164e03156312ed449367acf20a
parent866b09992668f97af063dcd77dc5dd0e3a512b94 (diff)
Parser refactoring.
* Use new style * Update to C++11 * Use more std::string than char*
-rw-r--r--src/configparser.cc45
-rw-r--r--src/configparser.h24
-rw-r--r--src/drumkitparser.cc413
-rw-r--r--src/drumkitparser.h39
-rw-r--r--src/instrumentparser.cc406
-rw-r--r--src/instrumentparser.h32
-rw-r--r--src/midimapparser.cc36
-rw-r--r--src/midimapparser.h22
-rw-r--r--src/saxparser.cc150
-rw-r--r--src/saxparser.h37
10 files changed, 583 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 <map>
#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<std::string, std::string> values;
- std::string *str;
+ std::map<std::string, std::string> values;
+ std::string* str;
};
-
-#endif/*__DRUMGIZMO_CONFIGPARSER_H__*/
diff --git a/src/drumkitparser.cc b/src/drumkitparser.cc
index f0fddf8..b3f3b99 100644
--- a/src/drumkitparser.cc
+++ b/src/drumkitparser.cc
@@ -34,244 +34,217 @@
#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<std::string, std::string> 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<InstrumentChannel*>::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<InstrumentChannel*>::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;
+ }
+
+ 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);
}
-
-#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[] =
-"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-"<drumkit name=\"The Aasimonster\"\n"
-" description=\"A large deathmetal drumkit\">\n"
-" <channels>\n"
-" <channel name=\"Alesis\"/>\n"
-" <channel name=\"Kick-L\"/>\n"
-" <channel name=\"Kick-R\"/>\n"
-" <channel name=\"SnareTop\"/>\n"
-" <channel name=\"SnareTrigger\"/>\n"
-" <channel name=\"SnareBottom\"/>\n"
-" <channel name=\"OH-L\"/>\n"
-" <channel name=\"OH-R\"/>\n"
-" <channel name=\"Hihat\"/>\n"
-" <channel name=\"Ride\"/>\n"
-" <channel name=\"Tom1\"/>\n"
-" <channel name=\"Tom2\"/>\n"
-" <channel name=\"Tom3\"/>\n"
-" <channel name=\"Tom4\"/>\n"
-" <channel name=\"Amb-R\"/>\n"
-" <channel name=\"Amb-L\"/>\n"
-" </channels>\n"
-" <instruments>\n"
-" <instrument name=\"Ride\" file=\"ride.xml\">\n"
-" <channelmap in=\"Alesis\" out=\"Alesis\" gain=\"1.5\"/>\n"
-" <channelmap in=\"Kick-L\" out=\"Kick-L\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Kick-R\" out=\"Kick-R\"/>\n"
-" <channelmap in=\"SnareTop\" out=\"SnareTop\" gain=\"0.5\"/>\n"
-" <channelmap in=\"SnareTrigger\" out=\"SnareTrigger\" gain=\"0.5\"/>\n"
-" <channelmap in=\"SnareBottom\" out=\"SnareBottom\" gain=\"0.5\"/>\n"
-" <channelmap in=\"OH-L\" out=\"OH-L\"/>\n"
-" <channelmap in=\"OH-R\" out=\"OH-R\"/>\n"
-" <channelmap in=\"Hihat\" out=\"Hihat\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Ride\" out=\"Ride\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Tom1\" out=\"Tom1\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Tom2\" out=\"Tom2\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Tom3\" out=\"Tom3\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Tom4\" out=\"Tom4\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Amb-R\" out=\"Amb-R\"/>\n"
-" <channelmap in=\"Amb-L\" out=\"Amb-L\"/>\n"
-" </instrument>\n"
-" <instrument name=\"Snare\" file=\"snare.xml\">\n"
-" <channelmap in=\"Alesis\" out=\"Alesis\" gain=\"1.5\"/>\n"
-" <channelmap in=\"Kick-L\" out=\"Kick-L\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Kick-R\" out=\"Kick-R\"/>\n"
-" <channelmap in=\"SnareTop\" out=\"SnareTop\" gain=\"0.5\"/>\n"
-" <channelmap in=\"SnareTrigger\" out=\"SnareTrigger\" gain=\"0.5\"/>\n"
-" <channelmap in=\"SnareBottom\" out=\"SnareBottom\" gain=\"0.5\"/>\n"
-" <channelmap in=\"OH-L\" out=\"OH-L\"/>\n"
-" <channelmap in=\"OH-R\" out=\"OH-R\"/>\n"
-" <channelmap in=\"Hihat\" out=\"Hihat\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Ride\" out=\"Ride\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Tom1\" out=\"Tom1\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Tom2\" out=\"Tom2\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Tom3\" out=\"Tom3\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Tom4\" out=\"Tom4\" gain=\"0.5\"/>\n"
-" <channelmap in=\"Amb-R\" out=\"Amb-R\"/>\n"
-" <channelmap in=\"Amb-L\" out=\"Amb-L\"/>\n"
-" </instrument>\n"
-" </instruments>\n"
-"</drumkit>\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*/
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<std::string, std::string> channelmap;
- std::string instr_file;
- std::string instr_name;
- std::string instr_group;
+ std::map<std::string, std::string> 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..eed179d 100644
--- a/src/instrumentparser.cc
+++ b/src/instrumentparser.cc
@@ -35,228 +35,214 @@
#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<std::string, std::string> 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<Sample *>::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<Sample *>::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;
+ }
+
+ 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;
}
-
-
-#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[] =
-"<?xml version='1.0' encoding='UTF-8'?>\n"
-"<instrument name=\"kick-r\">\n"
-" <samples>\n"
-" <sample name=\"kick-r-1\">\n"
-" <audiofile channel=\"Alesis\" file=\"samples/1-kick-r-Alesis-3.wav\"/>\n"
-" <audiofile channel=\"Amb L\" file=\"samples/1-kick-r-Amb L-3.wav\"/>\n"
-" <audiofile channel=\"Amb R\" file=\"samples/1-kick-r-Amb R-3.wav\"/>\n"
-" <audiofile channel=\"Kick L\" file=\"samples/1-kick-r-Kick L-3.wav\"/>\n"
-" <audiofile channel=\"Kick R\" file=\"samples/1-kick-r-Kick R-3.wav\"/>\n"
-" </sample>\n"
-" <sample name=\"kick-r-2\">\n"
-" <audiofile channel=\"Alesis\" file=\"samples/2-kick-r-Alesis-3.wav\"/>\n"
-" <audiofile channel=\"Amb L\" file=\"samples/2-kick-r-Amb L-3.wav\"/>\n"
-" <audiofile channel=\"Amb R\" file=\"samples/2-kick-r-Amb R-3.wav\"/>\n"
-" <audiofile channel=\"Kick L\" file=\"samples/2-kick-r-Kick L-3.wav\"/>\n"
-" <audiofile channel=\"Kick R\" file=\"samples/2-kick-r-Kick R-3.wav\"/>\n"
-" </sample>\n"
-" <sample name=\"kick-r-3\">\n"
-" <audiofile channel=\"Alesis\" file=\"samples/3-kick-r-Alesis-3.wav\"/>\n"
-" <audiofile channel=\"Amb L\" file=\"samples/3-kick-r-Amb L-3.wav\"/>\n"
-" <audiofile channel=\"Amb R\" file=\"samples/3-kick-r-Amb R-3.wav\"/>\n"
-" <audiofile channel=\"Kick L\" file=\"samples/3-kick-r-Kick L-3.wav\"/>\n"
-" <audiofile channel=\"Kick R\" file=\"samples/3-kick-r-Kick R-3.wav\"/>\n"
-" </sample>\n"
-" </samples>\n"
-" <velocities>\n"
-" <velocity lower=\"0\" upper=\"0.7\">\n"
-" <sampleref name=\"kick-r-1\"/>\n"
-" <sampleref name=\"kick-r-2\"/>\n"
-" </velocity>\n"
-" <velocity lower=\"0.7\" upper=\"1.0\">\n"
-" <sampleref name=\"kick-r-3\"/>\n"
-" </velocity>\n"
-" </velocities>\n"
-"</instrument>\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 <vector>
-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<InstrumentChannel *> channellist;
+ std::vector<InstrumentChannel*> 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..2d4563a 100644
--- a/src/midimapparser.cc
+++ b/src/midimapparser.cc
@@ -26,27 +26,39 @@
*/
#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;
+ }
+
+ 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 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 <stdio.h>
#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 <string.h>
#include <hugin.hpp>
-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 <string>
#include <map>
#include <expat.h>
-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<std::string, std::string>;
+
+ 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);
+};