* extend MIDNAM support (PatchBanks containing the bank select MIDI Commands)

git-svn-id: svn://localhost/ardour2/branches/3.0@4409 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Hans Baier 2009-01-15 03:13:24 +00:00
parent bed58e9f37
commit 625507fc1a
2 changed files with 59 additions and 27 deletions

View file

@ -82,14 +82,18 @@ public:
} }
}; };
class PatchBank;
typedef std::list<boost::shared_ptr<Evoral::MIDIEvent> > PatchMidiCommands;
class Patch : public PBD::Stateful class Patch : public PBD::Stateful
{ {
public: public:
typedef std::list<boost::shared_ptr<Evoral::MIDIEvent> > PatchMidiCommands;
Patch() {}; Patch(PatchBank* a_bank = 0) : _bank(a_bank) {};
Patch(string a_number, string a_name) : _number(a_number), _name(a_name) {}; Patch(string a_number, string a_name, PatchBank* a_bank = 0)
~Patch() {}; : _number(a_number), _name(a_name), _bank(a_bank) {};
virtual ~Patch() {};
const string& name() const { return _name; } const string& name() const { return _name; }
void set_name(const string a_name) { _name = a_name; } void set_name(const string a_name) { _name = a_name; }
@ -97,8 +101,6 @@ public:
const string& number() const { return _number; } const string& number() const { return _number; }
void set_number(const string a_number) { _number = a_number; } void set_number(const string a_number) { _number = a_number; }
const PatchMidiCommands& patch_midi_commands() const { return _patch_midi_commands; }
const PatchPrimaryKey& patch_primary_key() const { return _id; } const PatchPrimaryKey& patch_primary_key() const { return _id; }
XMLNode& get_state (void); XMLNode& get_state (void);
@ -107,8 +109,9 @@ public:
private: private:
string _number; string _number;
string _name; string _name;
// cannot use a boost::shared_ptr here in order to avoid retain cycles
PatchBank* _bank;
PatchPrimaryKey _id; PatchPrimaryKey _id;
PatchMidiCommands _patch_midi_commands;
}; };
class PatchBank : public PBD::Stateful class PatchBank : public PBD::Stateful
@ -116,21 +119,24 @@ class PatchBank : public PBD::Stateful
public: public:
typedef std::list<boost::shared_ptr<Patch> > PatchNameList; typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
PatchBank() {}; PatchBank() : _id(0) {};
virtual ~PatchBank() {}; PatchBank(string a_name, PatchPrimaryKey* an_id = 0) : _name(a_name), _id(an_id) {};
PatchBank(string a_name) : _name(a_name) {}; virtual ~PatchBank() { delete _id; };
const string& name() const { return _name; } const string& name() const { return _name; }
void set_name(const string a_name) { _name = a_name; } void set_name(const string a_name) { _name = a_name; }
const PatchNameList& patch_name_list() const { return _patch_name_list; } const PatchNameList& patch_name_list() const { return _patch_name_list; }
const PatchPrimaryKey* patch_primary_key() const { return _id; }
XMLNode& get_state (void); XMLNode& get_state (void);
int set_state (const XMLNode& a_node); int set_state (const XMLNode& a_node);
private: private:
string _name; string _name;
PatchNameList _patch_name_list; PatchNameList _patch_name_list;
PatchPrimaryKey* _id;
}; };
#include <iostream> #include <iostream>

View file

@ -38,27 +38,22 @@ Patch::get_state (void)
XMLNode* node = new XMLNode("Patch"); XMLNode* node = new XMLNode("Patch");
node->add_property("Number", _number); node->add_property("Number", _number);
node->add_property("Name", _name); node->add_property("Name", _name);
/*
XMLNode* commands = node->add_child("PatchMIDICommands"); XMLNode* commands = node->add_child("PatchMIDICommands");
for (PatchMidiCommands::const_iterator event = _patch_midi_commands.begin(); for (PatchMidiCommands::const_iterator event = _patch_midi_commands.begin();
event != _patch_midi_commands.end(); event != _patch_midi_commands.end();
++event) { ++event) {
commands->add_child_copy(*((((Evoral::MIDIEvent&)*event)).to_xml())); commands->add_child_copy(*((((Evoral::MIDIEvent&)*event)).to_xml()));
} }
*/
return *node; return *node;
} }
int void initialize_primary_key_from_commands (PatchPrimaryKey& id, const XMLNode* node)
Patch::set_state (const XMLNode& node)
{ {
assert(node.name() == "Patch"); const XMLNodeList events = node->children();
_number = node.property("Number")->value();
_name = node.property("Name")->value();
XMLNode* commands = node.child("PatchMIDICommands");
assert(commands);
const XMLNodeList events = commands->children();
for (XMLNodeList::const_iterator i = events.begin(); i != events.end(); ++i) { for (XMLNodeList::const_iterator i = events.begin(); i != events.end(); ++i) {
_patch_midi_commands.push_back(boost::shared_ptr<Evoral::MIDIEvent> (new Evoral::MIDIEvent(*(*i))));
XMLNode* node = *i; XMLNode* node = *i;
if (node->name() == "ControlChange") { if (node->name() == "ControlChange") {
string control = node->property("Control")->value(); string control = node->property("Control")->value();
@ -67,18 +62,42 @@ Patch::set_state (const XMLNode& node)
assert(value != ""); assert(value != "");
if (control == "0") { if (control == "0") {
_id.msb = PBD::atoi(value); id.msb = PBD::atoi(value);
} else if (control == "32") { } else if (control == "32") {
_id.lsb = PBD::atoi(value); id.lsb = PBD::atoi(value);
} }
} else if (node->name() == "ProgramChange") { } else if (node->name() == "ProgramChange") {
string number = node->property("Number")->value(); string number = node->property("Number")->value();
assert(number != ""); assert(number != "");
_id.program_number = PBD::atoi(number); id.program_number = PBD::atoi(number);
}
}
}
int
Patch::set_state (const XMLNode& node)
{
assert(node.name() == "Patch");
_number = node.property("Number")->value();
_name = node.property("Name")->value();
XMLNode* commands = node.child("PatchMIDICommands");
if (commands) {
initialize_primary_key_from_commands(_id, commands);
} else {
string program_change = node.property("ProgramChange")->value();
assert(program_change.length());
assert(_bank);
assert(_bank->patch_primary_key());
if ( _bank && _bank->patch_primary_key() ) {
_id.msb = _bank->patch_primary_key()->msb;
_id.lsb = _bank->patch_primary_key()->lsb;
_id.program_number = PBD::atoi(program_change);
} }
} }
//cerr << "deserialized Patch: name: " << _name << _id.msb << " lsb: " << _id.lsb << " program " << _id.program_number << endl; cerr << "deserialized Patch: name: " << _name << " msb: " << _id.msb << " lsb: " << _id.lsb << " program " << _id.program_number << endl;
// TODO: handle that more gracefully // TODO: handle that more gracefully
assert(_id.is_sane()); assert(_id.is_sane());
@ -152,11 +171,18 @@ PatchBank::set_state (const XMLNode& node)
{ {
assert(node.name() == "PatchBank"); assert(node.name() == "PatchBank");
_name = node.property("Name")->value(); _name = node.property("Name")->value();
XMLNode* commands = node.child("MIDICommands");
if (commands) {
_id = new PatchPrimaryKey();
initialize_primary_key_from_commands(*_id, commands);
}
XMLNode* patch_name_list = node.child("PatchNameList"); XMLNode* patch_name_list = node.child("PatchNameList");
assert(patch_name_list); assert(patch_name_list);
const XMLNodeList patches = patch_name_list->children(); const XMLNodeList patches = patch_name_list->children();
for (XMLNodeList::const_iterator i = patches.begin(); i != patches.end(); ++i) { for (XMLNodeList::const_iterator i = patches.begin(); i != patches.end(); ++i) {
boost::shared_ptr<Patch> patch(new Patch()); boost::shared_ptr<Patch> patch(new Patch(this));
patch->set_state(*(*i)); patch->set_state(*(*i));
_patch_name_list.push_back(patch); _patch_name_list.push_back(patch);
} }