diff options
author | André Nusser <andre.nusser@googlemail.com> | 2016-03-22 00:40:15 +0100 |
---|---|---|
committer | André Nusser <andre.nusser@googlemail.com> | 2016-03-29 22:19:49 +0200 |
commit | 0930fdc014bf36fb9e2715b3d14bff5fedf354a9 (patch) | |
tree | 9136c06ba9311f164e03156312ed449367acf20a /src | |
parent | 866b09992668f97af063dcd77dc5dd0e3a512b94 (diff) |
Parser refactoring.
* Use new style
* Update to C++11
* Use more std::string than char*
Diffstat (limited to 'src')
-rw-r--r-- | src/configparser.cc | 45 | ||||
-rw-r--r-- | src/configparser.h | 24 | ||||
-rw-r--r-- | src/drumkitparser.cc | 413 | ||||
-rw-r--r-- | src/drumkitparser.h | 39 | ||||
-rw-r--r-- | src/instrumentparser.cc | 406 | ||||
-rw-r--r-- | src/instrumentparser.h | 32 | ||||
-rw-r--r-- | src/midimapparser.cc | 36 | ||||
-rw-r--r-- | src/midimapparser.h | 22 | ||||
-rw-r--r-- | src/saxparser.cc | 150 | ||||
-rw-r--r-- | src/saxparser.h | 37 |
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); +}; |