summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Baier <hansfbaier@googlemail.com>2008-12-10 10:54:45 +0000
committerHans Baier <hansfbaier@googlemail.com>2008-12-10 10:54:45 +0000
commitdfed4965b7cf74f21a9e78689dbda1bc5892cde8 (patch)
tree9fab763740cd1e48a26f1165c2eaa958d151f141
parentf8480d6392e6d0e61aa39e564904ba67822f711e (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.cc21
-rw-r--r--libs/ardour/ardour/midi_patch_manager.h8
-rw-r--r--libs/midi++2/midi++/midnam_patch.h103
-rw-r--r--libs/midi++2/midnam_patch.cc47
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)
{