diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h index 265511e50c..d810d96c7a 100644 --- a/libs/midi++2/midi++/midnam_patch.h +++ b/libs/midi++2/midi++/midnam_patch.h @@ -82,22 +82,24 @@ public: } }; +class PatchBank; + +typedef std::list > PatchMidiCommands; + class Patch : public PBD::Stateful { public: - typedef std::list > PatchMidiCommands; - Patch() {}; - Patch(string a_number, string a_name) : _number(a_number), _name(a_name) {}; - ~Patch() {}; + Patch(PatchBank* a_bank = 0) : _bank(a_bank) {}; + Patch(string a_number, string a_name, PatchBank* a_bank = 0) + : _number(a_number), _name(a_name), _bank(a_bank) {}; + virtual ~Patch() {}; const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } const string& number() const { return _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; } @@ -107,8 +109,9 @@ public: private: string _number; string _name; + // cannot use a boost::shared_ptr here in order to avoid retain cycles + PatchBank* _bank; PatchPrimaryKey _id; - PatchMidiCommands _patch_midi_commands; }; class PatchBank : public PBD::Stateful @@ -116,21 +119,24 @@ class PatchBank : public PBD::Stateful public: typedef std::list > PatchNameList; - PatchBank() {}; - virtual ~PatchBank() {}; - PatchBank(string a_name) : _name(a_name) {}; + PatchBank() : _id(0) {}; + PatchBank(string a_name, PatchPrimaryKey* an_id = 0) : _name(a_name), _id(an_id) {}; + virtual ~PatchBank() { delete _id; }; const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } const PatchNameList& patch_name_list() const { return _patch_name_list; } + + const PatchPrimaryKey* patch_primary_key() const { return _id; } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: - string _name; - PatchNameList _patch_name_list; + string _name; + PatchNameList _patch_name_list; + PatchPrimaryKey* _id; }; #include diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc index acbf9208a8..87f062e3b2 100644 --- a/libs/midi++2/midnam_patch.cc +++ b/libs/midi++2/midnam_patch.cc @@ -38,27 +38,22 @@ Patch::get_state (void) XMLNode* node = new XMLNode("Patch"); node->add_property("Number", _number); node->add_property("Name", _name); + /* XMLNode* commands = node->add_child("PatchMIDICommands"); for (PatchMidiCommands::const_iterator event = _patch_midi_commands.begin(); event != _patch_midi_commands.end(); ++event) { commands->add_child_copy(*((((Evoral::MIDIEvent&)*event)).to_xml())); } + */ return *node; } -int -Patch::set_state (const XMLNode& node) +void initialize_primary_key_from_commands (PatchPrimaryKey& id, const XMLNode* node) { - assert(node.name() == "Patch"); - _number = node.property("Number")->value(); - _name = node.property("Name")->value(); - XMLNode* commands = node.child("PatchMIDICommands"); - assert(commands); - const XMLNodeList events = commands->children(); + const XMLNodeList events = node->children(); for (XMLNodeList::const_iterator i = events.begin(); i != events.end(); ++i) { - _patch_midi_commands.push_back(boost::shared_ptr (new Evoral::MIDIEvent(*(*i)))); XMLNode* node = *i; if (node->name() == "ControlChange") { string control = node->property("Control")->value(); @@ -67,18 +62,42 @@ Patch::set_state (const XMLNode& node) assert(value != ""); if (control == "0") { - _id.msb = PBD::atoi(value); + id.msb = PBD::atoi(value); } else if (control == "32") { - _id.lsb = PBD::atoi(value); + id.lsb = PBD::atoi(value); } } else if (node->name() == "ProgramChange") { string number = node->property("Number")->value(); 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 assert(_id.is_sane()); @@ -152,15 +171,22 @@ PatchBank::set_state (const XMLNode& node) { assert(node.name() == "PatchBank"); _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"); assert(patch_name_list); const XMLNodeList patches = patch_name_list->children(); for (XMLNodeList::const_iterator i = patches.begin(); i != patches.end(); ++i) { - boost::shared_ptr patch(new Patch()); + boost::shared_ptr patch(new Patch(this)); patch->set_state(*(*i)); _patch_name_list.push_back(patch); } - + return 0; }