fix up start-in-source values from regions created as sections of another region...
[ardour.git] / libs / midi++2 / midnam_patch.cc
index 0581a706f140e1f158ad4f4922f0e546b2bd39b9..b9a810ba588a7b03f0edd47a7140cbca909db099 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2008 Hans Baier 
+    Copyright (C) 2008 Hans Baier
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -38,48 +38,70 @@ Patch::get_state (void)
        XMLNode* node = new XMLNode("Patch");
        node->add_property("Number", _number);
        node->add_property("Name",   _name);
+       /*
+       typedef std::list< boost::shared_ptr< Evoral::MIDIEvent<double> > > PatchMidiCommands;
        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(*(new Evoral::MIDIEvent(*(*i))));
                XMLNode* node = *i;
                if (node->name() == "ControlChange") {
                        string control = node->property("Control")->value();
                        assert(control != "");
                        string value = node->property("Value")->value();
                        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, int /*version*/)
+{
+       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 << " msb: " << _id.msb << " lsb: " << _id.lsb << " program " << _id.program_number << endl;
+       // TODO: handle that more gracefully
        assert(_id.is_sane());
-       
+
        return 0;
 }
 
@@ -94,7 +116,7 @@ Note::get_state (void)
 }
 
 int
-Note::set_state (const XMLNode& node)
+Note::set_state (const XMLNode& node, int /*version*/)
 {
        assert(node.name() == "Note");
        _number = node.property("Number")->value();
@@ -113,7 +135,7 @@ NoteNameList::get_state (void)
 }
 
 int
-NoteNameList::set_state (const XMLNode& node)
+NoteNameList::set_state (const XMLNode& node, int version)
 {
        assert(node.name() == "NoteNameList");
        _name   = node.property("Name")->value();
@@ -121,11 +143,11 @@ NoteNameList::set_state (const XMLNode& node)
        boost::shared_ptr<XMLSharedNodeList> notes =
                                        node.find("//Note");
        for (XMLSharedNodeList::const_iterator i = notes->begin(); i != notes->end(); ++i) {
-               Note* note = new Note();
-               note->set_state(*(*i));
-               _notes.push_back(*note);
+               boost::shared_ptr<Note> note(new Note());
+               note->set_state(*(*i), version);
+               _notes.push_back(note);
        }
-       
+
        return 0;
 }
 
@@ -139,24 +161,31 @@ PatchBank::get_state (void)
        for (PatchNameList::iterator patch = _patch_name_list.begin();
            patch != _patch_name_list.end();
            ++patch) {
-               patch_name_list->add_child_nocopy(patch->get_state());
+               patch_name_list->add_child_nocopy((*patch)->get_state());
        }
 
        return *node;
 }
 
 int
-PatchBank::set_state (const XMLNode& node)
+PatchBank::set_state (const XMLNode& node, int version)
 {
        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) {
-               Patch* patch = new Patch();
-               patch->set_state(*(*i));
-               _patch_name_list.push_back(*patch);
+               boost::shared_ptr<Patch> patch(new Patch(this));
+               patch->set_state(*(*i), version);
+               _patch_name_list.push_back(patch);
        }
 
        return 0;
@@ -187,14 +216,14 @@ ChannelNameSet::get_state (void)
        for (PatchBanks::iterator patch_bank = _patch_banks.begin();
            patch_bank != _patch_banks.end();
            ++patch_bank) {
-               node->add_child_nocopy(patch_bank->get_state());
+               node->add_child_nocopy((*patch_bank)->get_state());
        }
 
        return *node;
 }
 
 int
-ChannelNameSet::set_state (const XMLNode& node)
+ChannelNameSet::set_state (const XMLNode& node, int version)
 {
        assert(node.name() == "ChannelNameSet");
        _name   = node.property("Name")->value();
@@ -216,36 +245,37 @@ ChannelNameSet::set_state (const XMLNode& node)
                                // cerr << "AvailableForChannels after insert" << endl;
                        }
                }
-               
+
                // cerr << "before PatchBank" << endl;
 
                if (node->name() == "PatchBank") {
                        // cerr << "got PatchBank" << endl;
-                       PatchBank* bank = new PatchBank();
-                       bank->set_state(*node);
-                       _patch_banks.push_back(*bank);
+                       boost::shared_ptr<PatchBank> bank(new PatchBank());
+                       bank->set_state(*node, version);
+                       _patch_banks.push_back(bank);
                        const PatchBank::PatchNameList& patches = bank->patch_name_list();
                        for (PatchBank::PatchNameList::const_iterator patch = patches.begin();
                             patch != patches.end();
                             ++patch) {
-                               _patch_map[patch->patch_primary_key()] = *patch;
+                               _patch_map[(*patch)->patch_primary_key()] = *patch;
+                               _patch_list.push_back((*patch)->patch_primary_key());
                        }
                        // cerr << "after PatchBank pushback" << endl;
                }
        }
-       
+
        // cerr << "ChannelnameSet done" << endl;
 
        return 0;
 }
 
 int
-CustomDeviceMode::set_state(const XMLNode& a_node)
+CustomDeviceMode::set_state(const XMLNode& a_node, int /*version*/)
 {
        assert(a_node.name() == "CustomDeviceMode");
-       
+
        _name = a_node.property("Name")->value();
-       
+
        boost::shared_ptr<XMLSharedNodeList> channel_name_set_assignments =
                a_node.find("//ChannelNameSetAssign");
        for(XMLSharedNodeList::const_iterator i = channel_name_set_assignments->begin();
@@ -254,7 +284,7 @@ CustomDeviceMode::set_state(const XMLNode& a_node)
                int channel = atoi((*i)->property("Channel")->value().c_str());
                string name_set = (*i)->property("NameSet")->value();
                assert( 1 <= channel && channel <= 16 );
-               _channel_name_set_assignments[channel -1] = name_set;
+               _channel_name_set_assignments[channel - 1] = name_set;
        }
        return 0;
 }
@@ -264,20 +294,20 @@ CustomDeviceMode::get_state(void)
 {
        XMLNode* custom_device_mode = new XMLNode("CustomDeviceMode");
        custom_device_mode->add_property("Name",   _name);
-       XMLNode* channel_name_set_assignments = 
+       XMLNode* channel_name_set_assignments =
                custom_device_mode->add_child("ChannelNameSetAssignments");
        for (int i = 0; i < 15 && !_channel_name_set_assignments[i].empty(); i++) {
-               XMLNode* channel_name_set_assign = 
+               XMLNode* channel_name_set_assign =
                        channel_name_set_assignments->add_child("ChannelNameSetAssign");
                channel_name_set_assign->add_property("Channel", i + 1);
                channel_name_set_assign->add_property("NameSet", _channel_name_set_assignments[i]);
        }
-       
+
        return *custom_device_mode;
 }
 
 int
-MasterDeviceNames::set_state(const XMLNode& a_node)
+MasterDeviceNames::set_state(const XMLNode& a_node, int version)
 {
        // cerr << "MasterDeviceNames::set_state Manufacturer" << endl;
        // Manufacturer
@@ -305,10 +335,10 @@ MasterDeviceNames::set_state(const XMLNode& a_node)
        for (XMLSharedNodeList::iterator i = custom_device_modes->begin();
             i != custom_device_modes->end();
             ++i) {
-               CustomDeviceMode* custom_device_mode = new CustomDeviceMode();
-               custom_device_mode->set_state(*(*i));
-               
-               _custom_device_modes[custom_device_mode->name()] = *custom_device_mode;
+               boost::shared_ptr<CustomDeviceMode> custom_device_mode(new CustomDeviceMode());
+               custom_device_mode->set_state(*(*i), version);
+
+               _custom_device_modes[custom_device_mode->name()] = custom_device_mode;
                _custom_device_mode_names.push_back(custom_device_mode->name());
        }
 
@@ -318,10 +348,10 @@ MasterDeviceNames::set_state(const XMLNode& a_node)
        for (XMLSharedNodeList::iterator i = channel_name_sets->begin();
             i != channel_name_sets->end();
             ++i) {
-               ChannelNameSet* channel_name_set = new ChannelNameSet();
+               boost::shared_ptr<ChannelNameSet> channel_name_set(new ChannelNameSet());
                // cerr << "MasterDeviceNames::set_state ChannelNameSet before set_state" << endl;
-               channel_name_set->set_state(*(*i));
-               _channel_name_sets[channel_name_set->name()] = *channel_name_set;
+               channel_name_set->set_state(*(*i), version);
+               _channel_name_sets[channel_name_set->name()] = channel_name_set;
        }
 
        // cerr << "MasterDeviceNames::set_state NoteNameLists" << endl;
@@ -330,9 +360,9 @@ MasterDeviceNames::set_state(const XMLNode& a_node)
        for (XMLSharedNodeList::iterator i = note_name_lists->begin();
             i != note_name_lists->end();
             ++i) {
-               NoteNameList* note_name_list = new NoteNameList();
-               note_name_list->set_state(*(*i));
-               _note_name_lists.push_back(*note_name_list);
+               boost::shared_ptr<NoteNameList> note_name_list(new NoteNameList());
+               note_name_list->set_state(*(*i), version);
+               _note_name_lists.push_back(note_name_list);
        }
 
        return 0;
@@ -345,14 +375,20 @@ MasterDeviceNames::get_state(void)
        return nothing;
 }
 
+MIDINameDocument::MIDINameDocument (const string& filename)
+       : _document(XMLTree(filename))
+{
+       set_state(*_document.root(), 0);
+}
+
 int
-MIDINameDocument::set_state(const XMLNode& a_node)
+MIDINameDocument::set_state(const XMLNode& a_node, int version)
 {
        // Author
        boost::shared_ptr<XMLSharedNodeList> author = a_node.find("//Author");
        assert(author->size() == 1);
        _author = author->front()->content();
-       
+
        // cerr << "MIDINameDocument::set_state befor masterdevicenames" << endl;
        // MasterDeviceNames
        boost::shared_ptr<XMLSharedNodeList> master_device_names_list = a_node.find("//MasterDeviceNames");
@@ -361,9 +397,9 @@ MIDINameDocument::set_state(const XMLNode& a_node)
             ++i) {
                boost::shared_ptr<MasterDeviceNames> master_device_names(new MasterDeviceNames());
                // cerr << "MIDINameDocument::set_state before masterdevicenames->set_state" << endl;
-               master_device_names->set_state(*(*i));
+               master_device_names->set_state(*(*i), version);
                // cerr << "MIDINameDocument::set_state after masterdevicenames->set_state" << endl;
-               
+
                for (MasterDeviceNames::Models::const_iterator model = master_device_names->models().begin();
                     model != master_device_names->models().end();
                     ++model) {
@@ -371,11 +407,11 @@ MIDINameDocument::set_state(const XMLNode& a_node)
                                _master_device_names_list.insert(
                                                std::pair<std::string, boost::shared_ptr<MasterDeviceNames> >
                                                         (*model,      master_device_names));
-                               
+
                                _all_models.push_back(*model);
                }
        }
-       
+
        return 0;
 }