diff options
author | Hans Baier <hansfbaier@googlemail.com> | 2008-12-10 10:54:45 +0000 |
---|---|---|
committer | Hans Baier <hansfbaier@googlemail.com> | 2008-12-10 10:54:45 +0000 |
commit | dfed4965b7cf74f21a9e78689dbda1bc5892cde8 (patch) | |
tree | 9fab763740cd1e48a26f1165c2eaa958d151f141 | |
parent | f8480d6392e6d0e61aa39e564904ba67822f711e (diff) |
* make patch selection appear only when there are patches loaded
* add combobox to select CustomDeviceMode
* add code to resolve patch names by their msb, lsb and program change number
git-svn-id: svn://localhost/ardour2/branches/3.0@4306 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/midi_time_axis.cc | 21 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_patch_manager.h | 8 | ||||
-rw-r--r-- | libs/midi++2/midi++/midnam_patch.h | 103 | ||||
-rw-r--r-- | libs/midi++2/midnam_patch.cc | 47 |
4 files changed, 150 insertions, 29 deletions
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index 1052b57912..ab0f0279f1 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -140,11 +140,11 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shar _view->attach (); } - // add channel selector expander HBox* midi_controls_hbox = manage(new HBox()); // Instrument patch selector - ComboBoxText* model_selector = manage(new ComboBoxText()); + ComboBoxText* model_selector = manage(new ComboBoxText()); + ComboBoxText* custom_device_mode_selector = manage(new ComboBoxText()); MIDI::Name::MidiPatchManager& patch_manager = MIDI::Name::MidiPatchManager::instance(); @@ -154,10 +154,25 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shar model_selector->append_text(model->c_str()); } + // TODO: persist the choice model_selector->set_active(0); + std::list<std::string> device_modes = patch_manager.custom_device_mode_names_by_model(model_selector->get_active_text()); + + for (std::list<std::string>::const_iterator i = device_modes.begin(); i != device_modes.end(); ++i) { + cerr << "found custom device mode " << *i << endl; + custom_device_mode_selector->append_text(*i); + } + + // TODO: persist the choice + custom_device_mode_selector->set_active(0); + midi_controls_hbox->pack_start(_channel_selector, true, false); - _midi_controls_box.pack_start(*model_selector, true, false); + if (!patch_manager.all_models().empty()) { + _midi_controls_box.pack_start(*model_selector, true, false); + _midi_controls_box.pack_start(*custom_device_mode_selector, true, false); + } + _midi_controls_box.pack_start(*midi_controls_hbox, true, true); controls_vbox.pack_start(_midi_controls_box, false, false); diff --git a/libs/ardour/ardour/midi_patch_manager.h b/libs/ardour/ardour/midi_patch_manager.h index 3591f87d89..9a99571f79 100644 --- a/libs/ardour/ardour/midi_patch_manager.h +++ b/libs/ardour/ardour/midi_patch_manager.h @@ -63,6 +63,14 @@ public: boost::shared_ptr<MasterDeviceNames> master_device_by_model(std::string model_name) { return _master_devices_by_model[model_name]; } + std::list<string> custom_device_mode_names_by_model(std::string model_name) { + if (model_name != "") { + return master_device_by_model(model_name)->custom_device_mode_names(); + } else { + return std::list<string>(); + } + } + const MasterDeviceNames::Models& all_models() const { return _all_models; } private: diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h index f9616ecf2d..b025268c45 100644 --- a/libs/midi++2/midi++/midnam_patch.h +++ b/libs/midi++2/midi++/midnam_patch.h @@ -36,6 +36,46 @@ namespace MIDI namespace Name { +struct PatchPrimaryKey +{ +public: + int msb; + int lsb; + int program_number; + + PatchPrimaryKey(int a_msb = -1, int a_lsb = -1, int a_program_number = -1) { + msb = a_msb; + lsb = a_lsb; + program_number = a_program_number; + } + + bool is_sane() { + return + 0 <= msb <= 127 && + 0 <= lsb <= 127 && + 0 <= program_number <= 127; + } + + inline bool operator==(const PatchPrimaryKey& id) const { + return (msb == id.msb && lsb == id.lsb && program_number == id.program_number); + } + + /** + * obey strict weak ordering or crash in STL containers + */ + inline bool operator<(const PatchPrimaryKey& id) const { + if (msb < id.msb) { + return true; + } else if (msb == id.msb && lsb < id.lsb) { + return true; + } else if (lsb == id.lsb && program_number < id.program_number) { + return true; + } + + return false; + } +}; + class Patch : public PBD::Stateful { public: @@ -52,13 +92,16 @@ public: 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; } XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: - string _number; - string _name; + string _number; + string _name; + PatchPrimaryKey _id; PatchMidiCommands _patch_midi_commands; }; @@ -89,6 +132,7 @@ class ChannelNameSet : public PBD::Stateful public: typedef std::set<uint8_t> AvailableForChannels; typedef std::list<PatchBank> PatchBanks; + typedef std::map<PatchPrimaryKey, Patch> PatchMap; ChannelNameSet() {}; virtual ~ChannelNameSet() {}; @@ -97,8 +141,14 @@ public: const string& name() const { return _name; } void set_name(const string a_name) { _name = a_name; } - const AvailableForChannels& available_for_channels() const { return _available_for_channels; } - const PatchBanks& patch_banks() const { return _patch_banks; } + bool available_for_channel(uint8_t channel) const { + return _available_for_channels.find(channel) != _available_for_channels.end(); + } + + Patch& find_patch(uint8_t msb, uint8_t lsb, uint8_t program_number) { + PatchPrimaryKey key(msb, lsb, program_number); + return _patch_map[key]; + } XMLNode& get_state (void); int set_state (const XMLNode& a_node); @@ -107,6 +157,7 @@ private: string _name; AvailableForChannels _available_for_channels; PatchBanks _patch_banks; + PatchMap _patch_map; }; class Note : public PBD::Stateful @@ -164,6 +215,11 @@ public: XMLNode& get_state (void); int set_state (const XMLNode& a_node); + string channel_name_set_name_by_channel(uint8_t channel) { + assert(channel <= 15); + return _channel_name_set_assignments[channel]; + } + private: /// array index = channel number /// string contents = name of channel name set @@ -174,10 +230,13 @@ private: class MasterDeviceNames : public PBD::Stateful { public: - typedef std::list<std::string> Models; - typedef std::list<CustomDeviceMode> CustomDeviceModes; - typedef std::list<ChannelNameSet> ChannelNameSets; - typedef std::list<NoteNameList> NoteNameLists; + typedef std::list<std::string> Models; + /// maps name to CustomDeviceMode + typedef std::map<std::string, CustomDeviceMode> CustomDeviceModes; + typedef std::list<std::string> CustomDeviceModeNames; + /// maps name to ChannelNameSet + typedef std::map<std::string, ChannelNameSet> ChannelNameSets; + typedef std::list<NoteNameList> NoteNameLists; MasterDeviceNames() {}; @@ -189,15 +248,31 @@ public: const Models& models() const { return _models; } void set_models(const Models some_models) { _models = some_models; } + const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; } + + CustomDeviceMode& custom_device_mode_by_name(string& mode_name) { + assert(mode_name != ""); + return _custom_device_modes[mode_name]; + } + + ChannelNameSet& channel_name_set_by_device_mode_and_channel(string mode, uint8_t channel) { + return _channel_name_sets[custom_device_mode_by_name(mode).channel_name_set_name_by_channel(channel)]; + } + + Patch& find_patch(string mode, uint8_t channel, uint8_t msb, uint8_t lsb, uint8_t program_number) { + return channel_name_set_by_device_mode_and_channel(mode, channel).find_patch(msb, lsb, program_number); + } + XMLNode& get_state (void); int set_state (const XMLNode& a_node); private: - string _manufacturer; - Models _models; - CustomDeviceModes _custom_device_modes; - ChannelNameSets _channel_name_sets; - NoteNameLists _note_name_lists; + string _manufacturer; + Models _models; + CustomDeviceModes _custom_device_modes; + CustomDeviceModeNames _custom_device_mode_names; + ChannelNameSets _channel_name_sets; + NoteNameLists _note_name_lists; }; class MIDINameDocument : public PBD::Stateful @@ -216,7 +291,7 @@ public: const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; } const MasterDeviceNames::Models& all_models() const { return _all_models; } - + XMLNode& get_state (void); int set_state (const XMLNode& a_node); diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc index c23901d721..0581a706f1 100644 --- a/libs/midi++2/midnam_patch.cc +++ b/libs/midi++2/midnam_patch.cc @@ -18,11 +18,12 @@ $Id$ */ -#include "midi++/midnam_patch.h" #include <algorithm> - #include <iostream> +#include "midi++/midnam_patch.h" +#include "pbd/convert.h" + using namespace std; namespace MIDI @@ -58,8 +59,27 @@ Patch::set_state (const XMLNode& node) const XMLNodeList events = commands->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); + } else if (control == "32") { + _id.lsb = PBD::atoi(value); + } + } else if (node->name() == "ProgramChange") { + string number = node->property("Number")->value(); + assert(number != ""); + _id.program_number = PBD::atoi(number); + } } + assert(_id.is_sane()); + return 0; } @@ -204,6 +224,12 @@ ChannelNameSet::set_state (const XMLNode& node) PatchBank* bank = new PatchBank(); bank->set_state(*node); _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; + } // cerr << "after PatchBank pushback" << endl; } } @@ -217,6 +243,9 @@ int CustomDeviceMode::set_state(const XMLNode& a_node) { 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(); @@ -278,7 +307,9 @@ MasterDeviceNames::set_state(const XMLNode& a_node) ++i) { CustomDeviceMode* custom_device_mode = new CustomDeviceMode(); custom_device_mode->set_state(*(*i)); - _custom_device_modes.push_back(*custom_device_mode); + + _custom_device_modes[custom_device_mode->name()] = *custom_device_mode; + _custom_device_mode_names.push_back(custom_device_mode->name()); } // cerr << "MasterDeviceNames::set_state ChannelNameSets" << endl; @@ -290,7 +321,7 @@ MasterDeviceNames::set_state(const XMLNode& a_node) ChannelNameSet* channel_name_set = new ChannelNameSet(); // cerr << "MasterDeviceNames::set_state ChannelNameSet before set_state" << endl; channel_name_set->set_state(*(*i)); - _channel_name_sets.push_back(*channel_name_set); + _channel_name_sets[channel_name_set->name()] = *channel_name_set; } // cerr << "MasterDeviceNames::set_state NoteNameLists" << endl; @@ -348,14 +379,6 @@ MIDINameDocument::set_state(const XMLNode& a_node) return 0; } -/* -const MasterDeviceNames::Models& -MIDINameDocument::models(void) -{ - ; -} -*/ - XMLNode& MIDINameDocument::get_state(void) { |