* 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
This commit is contained in:
Hans Baier 2008-12-10 10:54:45 +00:00
parent f8480d6392
commit dfed4965b7
4 changed files with 150 additions and 29 deletions

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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)
{