mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 08:36:32 +01:00
* 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:
parent
f8480d6392
commit
dfed4965b7
4 changed files with 150 additions and 29 deletions
|
|
@ -140,11 +140,11 @@ MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shar
|
||||||
_view->attach ();
|
_view->attach ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// add channel selector expander
|
|
||||||
HBox* midi_controls_hbox = manage(new HBox());
|
HBox* midi_controls_hbox = manage(new HBox());
|
||||||
|
|
||||||
// Instrument patch selector
|
// 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();
|
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());
|
model_selector->append_text(model->c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: persist the choice
|
||||||
model_selector->set_active(0);
|
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_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);
|
_midi_controls_box.pack_start(*midi_controls_hbox, true, true);
|
||||||
|
|
||||||
controls_vbox.pack_start(_midi_controls_box, false, false);
|
controls_vbox.pack_start(_midi_controls_box, false, false);
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,14 @@ public:
|
||||||
boost::shared_ptr<MasterDeviceNames> master_device_by_model(std::string model_name)
|
boost::shared_ptr<MasterDeviceNames> master_device_by_model(std::string model_name)
|
||||||
{ return _master_devices_by_model[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; }
|
const MasterDeviceNames::Models& all_models() const { return _all_models; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,46 @@ namespace MIDI
|
||||||
namespace Name
|
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
|
class Patch : public PBD::Stateful
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -53,12 +93,15 @@ public:
|
||||||
|
|
||||||
const PatchMidiCommands& patch_midi_commands() const { return _patch_midi_commands; }
|
const PatchMidiCommands& patch_midi_commands() const { return _patch_midi_commands; }
|
||||||
|
|
||||||
|
const PatchPrimaryKey& patch_primary_key() const { return _id; }
|
||||||
|
|
||||||
XMLNode& get_state (void);
|
XMLNode& get_state (void);
|
||||||
int set_state (const XMLNode& a_node);
|
int set_state (const XMLNode& a_node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string _number;
|
string _number;
|
||||||
string _name;
|
string _name;
|
||||||
|
PatchPrimaryKey _id;
|
||||||
PatchMidiCommands _patch_midi_commands;
|
PatchMidiCommands _patch_midi_commands;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -89,6 +132,7 @@ class ChannelNameSet : public PBD::Stateful
|
||||||
public:
|
public:
|
||||||
typedef std::set<uint8_t> AvailableForChannels;
|
typedef std::set<uint8_t> AvailableForChannels;
|
||||||
typedef std::list<PatchBank> PatchBanks;
|
typedef std::list<PatchBank> PatchBanks;
|
||||||
|
typedef std::map<PatchPrimaryKey, Patch> PatchMap;
|
||||||
|
|
||||||
ChannelNameSet() {};
|
ChannelNameSet() {};
|
||||||
virtual ~ChannelNameSet() {};
|
virtual ~ChannelNameSet() {};
|
||||||
|
|
@ -97,8 +141,14 @@ public:
|
||||||
const string& name() const { return _name; }
|
const string& name() const { return _name; }
|
||||||
void set_name(const string a_name) { _name = a_name; }
|
void set_name(const string a_name) { _name = a_name; }
|
||||||
|
|
||||||
const AvailableForChannels& available_for_channels() const { return _available_for_channels; }
|
bool available_for_channel(uint8_t channel) const {
|
||||||
const PatchBanks& patch_banks() const { return _patch_banks; }
|
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);
|
XMLNode& get_state (void);
|
||||||
int set_state (const XMLNode& a_node);
|
int set_state (const XMLNode& a_node);
|
||||||
|
|
@ -107,6 +157,7 @@ private:
|
||||||
string _name;
|
string _name;
|
||||||
AvailableForChannels _available_for_channels;
|
AvailableForChannels _available_for_channels;
|
||||||
PatchBanks _patch_banks;
|
PatchBanks _patch_banks;
|
||||||
|
PatchMap _patch_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Note : public PBD::Stateful
|
class Note : public PBD::Stateful
|
||||||
|
|
@ -164,6 +215,11 @@ public:
|
||||||
XMLNode& get_state (void);
|
XMLNode& get_state (void);
|
||||||
int set_state (const XMLNode& a_node);
|
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:
|
private:
|
||||||
/// array index = channel number
|
/// array index = channel number
|
||||||
/// string contents = name of channel name set
|
/// string contents = name of channel name set
|
||||||
|
|
@ -174,10 +230,13 @@ private:
|
||||||
class MasterDeviceNames : public PBD::Stateful
|
class MasterDeviceNames : public PBD::Stateful
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::list<std::string> Models;
|
typedef std::list<std::string> Models;
|
||||||
typedef std::list<CustomDeviceMode> CustomDeviceModes;
|
/// maps name to CustomDeviceMode
|
||||||
typedef std::list<ChannelNameSet> ChannelNameSets;
|
typedef std::map<std::string, CustomDeviceMode> CustomDeviceModes;
|
||||||
typedef std::list<NoteNameList> NoteNameLists;
|
typedef std::list<std::string> CustomDeviceModeNames;
|
||||||
|
/// maps name to ChannelNameSet
|
||||||
|
typedef std::map<std::string, ChannelNameSet> ChannelNameSets;
|
||||||
|
typedef std::list<NoteNameList> NoteNameLists;
|
||||||
|
|
||||||
|
|
||||||
MasterDeviceNames() {};
|
MasterDeviceNames() {};
|
||||||
|
|
@ -189,15 +248,31 @@ public:
|
||||||
const Models& models() const { return _models; }
|
const Models& models() const { return _models; }
|
||||||
void set_models(const Models some_models) { _models = some_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);
|
XMLNode& get_state (void);
|
||||||
int set_state (const XMLNode& a_node);
|
int set_state (const XMLNode& a_node);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string _manufacturer;
|
string _manufacturer;
|
||||||
Models _models;
|
Models _models;
|
||||||
CustomDeviceModes _custom_device_modes;
|
CustomDeviceModes _custom_device_modes;
|
||||||
ChannelNameSets _channel_name_sets;
|
CustomDeviceModeNames _custom_device_mode_names;
|
||||||
NoteNameLists _note_name_lists;
|
ChannelNameSets _channel_name_sets;
|
||||||
|
NoteNameLists _note_name_lists;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MIDINameDocument : public PBD::Stateful
|
class MIDINameDocument : public PBD::Stateful
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,12 @@
|
||||||
$Id$
|
$Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "midi++/midnam_patch.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "midi++/midnam_patch.h"
|
||||||
|
#include "pbd/convert.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace MIDI
|
namespace MIDI
|
||||||
|
|
@ -58,8 +59,27 @@ Patch::set_state (const XMLNode& node)
|
||||||
const XMLNodeList events = commands->children();
|
const XMLNodeList events = commands->children();
|
||||||
for (XMLNodeList::const_iterator i = events.begin(); i != events.end(); ++i) {
|
for (XMLNodeList::const_iterator i = events.begin(); i != events.end(); ++i) {
|
||||||
_patch_midi_commands.push_back(*(new Evoral::MIDIEvent(*(*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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,6 +224,12 @@ ChannelNameSet::set_state (const XMLNode& node)
|
||||||
PatchBank* bank = new PatchBank();
|
PatchBank* bank = new PatchBank();
|
||||||
bank->set_state(*node);
|
bank->set_state(*node);
|
||||||
_patch_banks.push_back(*bank);
|
_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;
|
// cerr << "after PatchBank pushback" << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -217,6 +243,9 @@ int
|
||||||
CustomDeviceMode::set_state(const XMLNode& a_node)
|
CustomDeviceMode::set_state(const XMLNode& a_node)
|
||||||
{
|
{
|
||||||
assert(a_node.name() == "CustomDeviceMode");
|
assert(a_node.name() == "CustomDeviceMode");
|
||||||
|
|
||||||
|
_name = a_node.property("Name")->value();
|
||||||
|
|
||||||
boost::shared_ptr<XMLSharedNodeList> channel_name_set_assignments =
|
boost::shared_ptr<XMLSharedNodeList> channel_name_set_assignments =
|
||||||
a_node.find("//ChannelNameSetAssign");
|
a_node.find("//ChannelNameSetAssign");
|
||||||
for(XMLSharedNodeList::const_iterator i = channel_name_set_assignments->begin();
|
for(XMLSharedNodeList::const_iterator i = channel_name_set_assignments->begin();
|
||||||
|
|
@ -278,7 +307,9 @@ MasterDeviceNames::set_state(const XMLNode& a_node)
|
||||||
++i) {
|
++i) {
|
||||||
CustomDeviceMode* custom_device_mode = new CustomDeviceMode();
|
CustomDeviceMode* custom_device_mode = new CustomDeviceMode();
|
||||||
custom_device_mode->set_state(*(*i));
|
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;
|
// cerr << "MasterDeviceNames::set_state ChannelNameSets" << endl;
|
||||||
|
|
@ -290,7 +321,7 @@ MasterDeviceNames::set_state(const XMLNode& a_node)
|
||||||
ChannelNameSet* channel_name_set = new ChannelNameSet();
|
ChannelNameSet* channel_name_set = new ChannelNameSet();
|
||||||
// cerr << "MasterDeviceNames::set_state ChannelNameSet before set_state" << endl;
|
// cerr << "MasterDeviceNames::set_state ChannelNameSet before set_state" << endl;
|
||||||
channel_name_set->set_state(*(*i));
|
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;
|
// cerr << "MasterDeviceNames::set_state NoteNameLists" << endl;
|
||||||
|
|
@ -348,14 +379,6 @@ MIDINameDocument::set_state(const XMLNode& a_node)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
const MasterDeviceNames::Models&
|
|
||||||
MIDINameDocument::models(void)
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
XMLNode&
|
XMLNode&
|
||||||
MIDINameDocument::get_state(void)
|
MIDINameDocument::get_state(void)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue