summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2013-01-20 00:46:55 +0000
committerDavid Robillard <d@drobilla.net>2013-01-20 00:46:55 +0000
commit88de45b7ccc933ee46a13d4e4e21caf9e5fb379e (patch)
tree5e72e7caa7b88b8d29e8dad226c317fc8e31d3bb /libs
parent448c156b4bac6204dd6b627b07b226f63f1301b4 (diff)
Support note names from midnam files (tested with the DM5).
Do this via a simple MasterDeviceNames::note_name() function. The same really needs to be done for program names, this stuff is absolutely brutal to use. Store note names in a vector indexed by number instead of a list with string "numbers" for reasonable lookup time. Make some references const that should be. git-svn-id: svn://localhost/ardour2/branches/3.0@13908 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/midi++2/midi++/midnam_patch.h70
-rw-r--r--libs/midi++2/midnam_patch.cc89
2 files changed, 122 insertions, 37 deletions
diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h
index e218eeeedd..54d36735e5 100644
--- a/libs/midi++2/midi++/midnam_patch.h
+++ b/libs/midi++2/midi++/midnam_patch.h
@@ -26,6 +26,7 @@
#include <list>
#include <set>
#include <map>
+#include <vector>
#include <stdint.h>
@@ -44,12 +45,12 @@ public:
int bank_number;
int program_number;
- PatchPrimaryKey (uint8_t a_program_number = 0, uint16_t a_bank_number = 0) {
+ PatchPrimaryKey (uint8_t a_program_number = 0, uint16_t a_bank_number = 0) {
bank_number = std::min (a_bank_number, (uint16_t) 16384);
program_number = std::min (a_program_number, (uint8_t) 127);
}
- bool is_sane() {
+ bool is_sane() const {
return ((bank_number >= 0) && (bank_number <= 16384) &&
(program_number >=0 ) && (program_number <= 127));
}
@@ -87,13 +88,15 @@ public:
Patch (std::string a_name = std::string(), uint8_t a_number = 0, uint16_t bank_number = 0);
virtual ~Patch() {};
- const std::string& name() const { return _name; }
- void set_name(const std::string a_name) { _name = a_name; }
+ const std::string& name() const { return _name; }
+ void set_name(const std::string a_name) { _name = a_name; }
+
+ const std::string& note_list_name() const { return _note_list_name; }
- uint8_t program_number() const { return _id.program_number; }
- void set_program_number(uint8_t n) { _id.program_number = n; }
+ uint8_t program_number() const { return _id.program_number; }
+ void set_program_number(uint8_t n) { _id.program_number = n; }
- uint16_t bank_number() const { return _id.bank_number; }
+ uint16_t bank_number() const { return _id.bank_number; }
void set_bank_number (uint16_t n) { _id.bank_number = n; }
const PatchPrimaryKey& patch_primary_key() const { return _id; }
@@ -104,6 +107,7 @@ public:
private:
std::string _name;
PatchPrimaryKey _id;
+ std::string _note_list_name;
};
class PatchBank
@@ -155,12 +159,12 @@ public:
return _available_for_channels.find(channel) != _available_for_channels.end();
}
- boost::shared_ptr<Patch> find_patch(PatchPrimaryKey& key) {
+ boost::shared_ptr<Patch> find_patch(const PatchPrimaryKey& key) {
assert(key.is_sane());
return _patch_map[key];
}
- boost::shared_ptr<Patch> previous_patch(PatchPrimaryKey& key) {
+ boost::shared_ptr<Patch> previous_patch(const PatchPrimaryKey& key) {
assert(key.is_sane());
for (PatchList::const_iterator i = _patch_list.begin();
i != _patch_list.end();
@@ -176,7 +180,7 @@ public:
return boost::shared_ptr<Patch>();
}
- boost::shared_ptr<Patch> next_patch(PatchPrimaryKey& key) {
+ boost::shared_ptr<Patch> next_patch(const PatchPrimaryKey& key) {
assert(key.is_sane());
for (PatchList::const_iterator i = _patch_list.begin();
i != _patch_list.end();
@@ -214,43 +218,42 @@ std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
class Note
{
public:
- Note() {};
- Note(std::string a_number, std::string a_name) : _number(a_number), _name(a_name) {};
- ~Note() {};
+ Note() {}
+ Note(uint8_t number, const std::string& name) : _number(number), _name(name) {}
- const std::string& name() const { return _name; }
- void set_name(const std::string a_name) { _name = a_name; }
+ const std::string& name() const { return _name; }
+ void set_name(const std::string& name) { _name = name; }
- const std::string& number() const { return _number; }
- void set_number(const std::string a_number) { _number = a_number; }
+ uint8_t number() const { return _number; }
+ void set_number(uint8_t number) { _number = number; }
XMLNode& get_state (void);
int set_state (const XMLTree&, const XMLNode&);
private:
- std::string _number;
+ uint8_t _number;
std::string _name;
};
class NoteNameList
{
public:
- typedef std::list<boost::shared_ptr<Note> > Notes;
- NoteNameList() {};
- NoteNameList (std::string a_name) : _name(a_name) {};
- ~NoteNameList() {};
+ typedef std::vector< boost::shared_ptr<Note> > Notes;
- const std::string& name() const { return _name; }
- void set_name(const std::string a_name) { _name = a_name; }
+ NoteNameList() { _notes.resize(128); }
+ NoteNameList (const std::string& name) : _name(name) { _notes.resize(128); }
+
+ const std::string& name() const { return _name; }
+ const Notes& notes() const { return _notes; }
- const Notes& notes() const { return _notes; }
+ void set_name(const std::string& name) { _name = name; }
XMLNode& get_state (void);
int set_state (const XMLTree&, const XMLNode&);
private:
std::string _name;
- Notes _notes;
+ Notes _notes;
};
class Control
@@ -339,7 +342,7 @@ public:
typedef std::list<std::string> CustomDeviceModeNames;
/// maps name to ChannelNameSet
typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> > ChannelNameSets;
- typedef std::list<boost::shared_ptr<NoteNameList> > NoteNameLists;
+ typedef std::map<std::string, boost::shared_ptr<NoteNameList> > NoteNameLists;
typedef std::list<boost::shared_ptr<ControlNameList> > ControlNameLists;
typedef std::map<std::string, PatchBank::PatchNameList> PatchNameLists;
@@ -358,8 +361,17 @@ public:
boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(std::string mode_name);
boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(std::string mode, uint8_t channel);
- boost::shared_ptr<Patch> find_patch(std::string mode, uint8_t channel, PatchPrimaryKey& key);
-
+ boost::shared_ptr<Patch> find_patch(std::string mode, uint8_t channel, const PatchPrimaryKey& key);
+
+ boost::shared_ptr<NoteNameList> note_name_list(const std::string& name);
+ boost::shared_ptr<ChannelNameSet> channel_name_set(const std::string& name);
+
+ std::string note_name(const std::string& mode_name,
+ uint8_t channel,
+ uint16_t bank,
+ uint8_t program,
+ uint8_t number);
+
XMLNode& get_state (void);
int set_state (const XMLTree&, const XMLNode&);
diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc
index 39238114c7..1e21d602e3 100644
--- a/libs/midi++2/midnam_patch.cc
+++ b/libs/midi++2/midnam_patch.cc
@@ -128,6 +128,11 @@ Patch::set_state (const XMLTree&, const XMLNode& node)
assert(program_change.length());
_id.program_number = PBD::atoi(program_change);
}
+
+ XMLNode* use_note_name_list = node.child("UsesNoteNameList");
+ if (use_note_name_list) {
+ _note_list_name = use_note_name_list->property ("Name")->value();
+ }
return 0;
}
@@ -146,7 +151,12 @@ int
Note::set_state (const XMLTree&, const XMLNode& node)
{
assert(node.name() == "Note");
- _number = node.property("Number")->value();
+
+ /* If the note number is junk, this will pull a number from the start, or
+ return zero if there isn't one. Better error detection would be a good
+ idea, but the duplicate check in NoteNameList::set_state() will probably
+ catch really broken files anyway. */
+ _number = atoi(node.property("Number")->value().c_str());
_name = node.property("Name")->value();
return 0;
@@ -156,7 +166,7 @@ XMLNode&
NoteNameList::get_state (void)
{
XMLNode* node = new XMLNode("NoteNameList");
- node->add_property("Name", _name);
+ node->add_property("Name", _name);
return *node;
}
@@ -165,13 +175,29 @@ int
NoteNameList::set_state (const XMLTree& tree, const XMLNode& node)
{
assert(node.name() == "NoteNameList");
- _name = node.property("Name")->value();
+ _name = node.property("Name")->value();
+ _notes.clear();
+ _notes.resize(128);
- boost::shared_ptr<XMLSharedNodeList> notes = tree.find("//Note");
- for (XMLSharedNodeList::const_iterator i = notes->begin(); i != notes->end(); ++i) {
+ for (XMLNodeList::const_iterator i = node.children().begin();
+ i != node.children().end(); ++i) {
+ if ((*i)->name() != "Note") {
+ continue;
+ }
boost::shared_ptr<Note> note(new Note());
note->set_state (tree, *(*i));
- _notes.push_back(note);
+ if (note->number() > 127) {
+ PBD::warning << string_compose("Note number %1 in %3 out of range",
+ (int)note->number(), tree.filename())
+ << endmsg;
+ } else if (_notes[note->number()]) {
+ PBD::warning <<
+ string_compose("Duplicate note number %1 name %2 in %3 ignored",
+ (int)note->number(), note->name(), tree.filename())
+ << endmsg;
+ } else {
+ _notes[note->number()] = note;
+ }
}
return 0;
@@ -465,11 +491,58 @@ MasterDeviceNames::channel_name_set_by_device_mode_and_channel(std::string mode,
}
boost::shared_ptr<Patch>
-MasterDeviceNames::find_patch(std::string mode, uint8_t channel, PatchPrimaryKey& key)
+MasterDeviceNames::find_patch(std::string mode, uint8_t channel, const PatchPrimaryKey& key)
{
return channel_name_set_by_device_mode_and_channel(mode, channel)->find_patch(key);
}
+boost::shared_ptr<ChannelNameSet>
+MasterDeviceNames::channel_name_set(const std::string& name)
+{
+ ChannelNameSets::const_iterator i = _channel_name_sets.find(name);
+ if (i != _channel_name_sets.end()) {
+ return i->second;
+ }
+ return boost::shared_ptr<ChannelNameSet>();
+}
+
+boost::shared_ptr<NoteNameList>
+MasterDeviceNames::note_name_list(const std::string& name)
+{
+ NoteNameLists::const_iterator i = _note_name_lists.find(name);
+ if (i != _note_name_lists.end()) {
+ return i->second;
+ }
+ return boost::shared_ptr<NoteNameList>();
+}
+
+std::string
+MasterDeviceNames::note_name(const std::string& mode_name,
+ uint8_t channel,
+ uint16_t bank,
+ uint8_t program,
+ uint8_t number)
+{
+ if (number > 127) {
+ return "";
+ }
+
+ boost::shared_ptr<const Patch> patch(
+ find_patch(mode_name, channel, PatchPrimaryKey(program, bank)));
+ if (!patch) {
+ return "";
+ }
+
+ boost::shared_ptr<const NoteNameList> note_names(
+ note_name_list(patch->note_list_name()));
+ if (!note_names) {
+ return "";
+ }
+
+ boost::shared_ptr<const Note> note(note_names->notes()[number]);
+ return note ? note->name() : "";
+}
+
int
MasterDeviceNames::set_state(const XMLTree& tree, const XMLNode&)
{
@@ -520,7 +593,7 @@ MasterDeviceNames::set_state(const XMLTree& tree, const XMLNode&)
++i) {
boost::shared_ptr<NoteNameList> note_name_list(new NoteNameList());
note_name_list->set_state (tree, *(*i));
- _note_name_lists.push_back(note_name_list);
+ _note_name_lists[(*i)->property ("Name")->value()] = note_name_list;
}
// ControlNameLists