Show matching controller name in automation lane header.
authorDavid Robillard <d@drobilla.net>
Sun, 20 Jan 2013 08:56:00 +0000 (08:56 +0000)
committerDavid Robillard <d@drobilla.net>
Sun, 20 Jan 2013 08:56:00 +0000 (08:56 +0000)
Completely eliminate static MIDI controller name code.
Reduce dependency on midnam_patch.h (which would have saved me several hours if I did it earlier).
Store controller name numbers as an integer.
Keep controller names in a map keyed by int instead of a list for fast lookup.
More cleanup of MIDI::Name code.

git-svn-id: svn://localhost/ardour2/branches/3.0@13927 d708f5d6-7413-0410-9779-e7cbd77b26cf

15 files changed:
gtk2_ardour/canvas_patch_change.cc
gtk2_ardour/midi_region_view.cc
gtk2_ardour/midi_time_axis.cc
gtk2_ardour/midi_time_axis.h
gtk2_ardour/patch_change_dialog.cc
gtk2_ardour/patch_change_dialog.h
libs/ardour/ardour/instrument_info.h
libs/ardour/ardour/midi_track.h
libs/ardour/automatable.cc
libs/ardour/instrument_info.cc
libs/ardour/midi_track.cc
libs/midi++2/midi++/midnam_patch.h
libs/midi++2/midi++/names.h [deleted file]
libs/midi++2/midnam_patch.cc
libs/midi++2/test/MidnamTest.cpp

index 1958ea2b5efc5c37b03b5fd56aca17892c8828fa..34658f51a493eac40f2cdfca5664389699581f75 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "gtkmm2ext/keyboard.h"
 #include "ardour/instrument_info.h"
+#include "midi++/midnam_patch.h"
 
 #include "ardour_ui.h"
 #include "midi_region_view.h"
@@ -92,10 +93,10 @@ CanvasPatchChange::initialize_popup_menus()
                     ++bank) {
                        Gtk::Menu& patch_bank_menu = *manage(new Gtk::Menu());
                        
-                       const PatchBank::PatchNameList& patches = (*bank)->patch_name_list();
+                       const PatchNameList& patches = (*bank)->patch_name_list();
                        Gtk::Menu::MenuList& patch_menus = patch_bank_menu.items();
                        
-                       for (PatchBank::PatchNameList::const_iterator patch = patches.begin();
+                       for (PatchNameList::const_iterator patch = patches.begin();
                             patch != patches.end();
                             ++patch) {
                                std::string name = (*patch)->name();
@@ -119,10 +120,10 @@ CanvasPatchChange::initialize_popup_menus()
        } else {
                /* only one patch bank, so make it the initial menu */
 
-               const PatchBank::PatchNameList& patches = patch_banks.front()->patch_name_list();
+               const PatchNameList& patches = patch_banks.front()->patch_name_list();
                Gtk::Menu::MenuList& patch_menus = _popup.items();
                
-               for (PatchBank::PatchNameList::const_iterator patch = patches.begin();
+               for (PatchNameList::const_iterator patch = patches.begin();
                     patch != patches.end();
                     ++patch) {
                        std::string name = (*patch)->name();
index acd63469c6fc18953a16ef96a6631eda4df19277..542894af81b113c705d4244c1e82a5874bf2f2ad 100644 (file)
@@ -1820,10 +1820,9 @@ MidiRegionView::add_canvas_patch_change (MidiModel::PatchChangePtr patch, const
                                      displaytext,
                                      height,
                                      x, 1.0,
-                                     instrument_info(),
+                                     instrument_info(),
                                      patch,
-                                     active_channel)
-                         );
+                                     active_channel));
 
        if (patch_change->width() < _pixel_width) {
                // Show unless patch change is beyond the region bounds
index 9d96ca756f812cc383c2502ef0067f6517bf5916..2b42d65a73912338dae0e73cb533da7842d6de68 100644 (file)
@@ -55,8 +55,6 @@
 #include "ardour/track.h"
 #include "ardour/types.h"
 
-#include "midi++/names.h"
-
 #include "ardour_ui.h"
 #include "ardour_button.h"
 #include "automation_line.h"
@@ -829,14 +827,17 @@ MidiTimeAxisView::build_controller_menu ()
                /* Controllers names available in midnam file, generate fancy menu */
                unsigned n_items  = 0;
                unsigned n_groups = 0;
+
+               /* TODO: This is not correct, should look up the currently applicable ControlNameList
+                  and only build a menu for that one. */
                for (MasterDeviceNames::ControlNameLists::const_iterator l = device_names->controls().begin();
                     l != device_names->controls().end(); ++l) {
-                       boost::shared_ptr<ControlNameList> name_list = *l;
+                       boost::shared_ptr<ControlNameList> name_list = l->second;
                        Menu*                              ctl_menu  = NULL;
                        
-                       for (ControlNameList::Controls::const_iterator c = (*l)->controls().begin();
-                            c != (*l)->controls().end(); ++c) {
-                               const int ctl = atoi((*c)->number().c_str());
+                       for (ControlNameList::Controls::const_iterator c = name_list->controls().begin();
+                            c != name_list->controls().end(); ++c) {
+                               const uint16_t ctl = c->second->number();
                                if (ctl == MIDI_CTL_MSB_BANK || ctl == MIDI_CTL_LSB_BANK) {
                                        /* Skip bank select controllers since they're handled specially */
                                        continue;
@@ -849,12 +850,12 @@ MidiTimeAxisView::build_controller_menu ()
                                
                                MenuList& ctl_items (ctl_menu->items());
                                if (chn_cnt > 1) {
-                                       add_multi_channel_controller_item(ctl_items, ctl, (*c)->name());
+                                       add_multi_channel_controller_item(ctl_items, ctl, c->second->name());
                                } else {
-                                       add_single_channel_controller_item(ctl_items, ctl, (*c)->name());
+                                       add_single_channel_controller_item(ctl_items, ctl, c->second->name());
                                }
                                
-                               if (++n_items == 16 || c == (*l)->controls().end()) {
+                               if (++n_items == 16 || c == name_list->controls().end()) {
                                        /* Submenu has 16 items, add it to controller menu and reset */
                                        items.push_back(
                                                MenuElem(string_compose(_("Controllers %1-%2"),
index d61b64f36c238a99e384f9ceab0304653be7d0da..1f179baca67cfa25548181524c920920d940ad17 100644 (file)
 #include "midi_streamview.h"
 #include "midi_channel_selector.h"
 
+namespace MIDI {
+namespace Name {
+class MasterDeviceNames;
+class CustomDeviceMode;
+}
+}
+
 namespace ARDOUR {
        class Session;
        class RouteGroup;
@@ -68,8 +75,8 @@ class MidiTimeAxisView : public RouteTimeAxisView
 
        void set_height (uint32_t);
 
-        void enter_internal_edit_mode ();
-        void leave_internal_edit_mode ();
+       void enter_internal_edit_mode ();
+       void leave_internal_edit_mode ();
 
        boost::shared_ptr<ARDOUR::MidiRegion> add_region (ARDOUR::framepos_t, ARDOUR::framecnt_t, bool);
 
@@ -93,8 +100,8 @@ class MidiTimeAxisView : public RouteTimeAxisView
 
        Gtk::CheckMenuItem* automation_child_menu_item (Evoral::Parameter);
 
-        StepEditor* step_editor() { return _step_editor; }
-        void check_step_edit ();
+       StepEditor* step_editor() { return _step_editor; }
+       void check_step_edit ();
 
        void first_idle ();
 
@@ -168,7 +175,7 @@ class MidiTimeAxisView : public RouteTimeAxisView
        /** parameter -> menu item map for the controller menu */
        ParameterMenuMap _controller_menu_map;
 
-        StepEditor* _step_editor;
+       StepEditor* _step_editor;
 };
 
 #endif /* __ardour_midi_time_axis_h__ */
index c8394c2848b35ed974b21b2cf406ad9cdae2daf9..2ecfd4bdd7d47c98b1e3e55367d82932a6ab3c09 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "gtkmm2ext/utils.h"
 
+#include "midi++/midnam_patch.h"
+
 #include "ardour/midi_patch_manager.h"
 #include "ardour/beats_frames_converter.h"
 #include "ardour/instrument_info.h"
@@ -255,8 +257,8 @@ PatchChangeDialog::fill_patch_combo ()
                return;
        }
 
-       const MIDI::Name::PatchBank::PatchNameList& patches = _current_patch_bank->patch_name_list ();
-       for (MIDI::Name::PatchBank::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
+       const MIDI::Name::PatchNameList& patches = _current_patch_bank->patch_name_list ();
+       for (MIDI::Name::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
                string n = (*j)->name ();
                boost::replace_all (n, "_", " ");
                _patch_combo.append_text (n);
@@ -278,8 +280,8 @@ PatchChangeDialog::set_active_patch_combo ()
                return;
        }
        
-       const MIDI::Name::PatchBank::PatchNameList& patches = _current_patch_bank->patch_name_list ();
-       for (MIDI::Name::PatchBank::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
+       const MIDI::Name::PatchNameList& patches = _current_patch_bank->patch_name_list ();
+       for (MIDI::Name::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
                string n = (*j)->name ();
                boost::replace_all (n, "_", " ");
 
@@ -305,9 +307,9 @@ PatchChangeDialog::patch_combo_changed ()
                return;
        }
 
-       const MIDI::Name::PatchBank::PatchNameList& patches = _current_patch_bank->patch_name_list ();
+       const MIDI::Name::PatchNameList& patches = _current_patch_bank->patch_name_list ();
 
-       for (MIDI::Name::PatchBank::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
+       for (MIDI::Name::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
                string n = (*j)->name ();
                boost::replace_all (n, "_", " ");
 
index c462ff0c77e36b73b2ba16e34847dd90d572bb8c..ed0f49df34c173097f539e596f769225d7cdb339 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <gtkmm/spinbutton.h>
 #include <gtkmm/comboboxtext.h>
-#include "midi++/midnam_patch.h"
+
 #include "evoral/PatchChange.hpp"
 #include "ardour_dialog.h"
 #include "audio_clock.h"
index f83b2c06322dac16618955b13a329565ce354e8d..8691db24e5932676f5f386c46d1c7f5abbbf082f 100644 (file)
 #include <string>
 #include <stdint.h>
 
+#include <boost/weak_ptr.hpp>
+
 #include "pbd/signals.h"
 
-#include "midi++/midnam_patch.h"
+#include "evoral/Parameter.hpp"
 
-#include <boost/weak_ptr.hpp>
+namespace MIDI {
+namespace Name {
+class ChannelNameSet;
+class Patch;
+typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
+}
+}
 
 namespace ARDOUR {
 
@@ -41,13 +49,14 @@ class InstrumentInfo {
     void set_internal_instrument (boost::shared_ptr<ARDOUR::Processor>);
 
     std::string get_patch_name (uint16_t bank, uint8_t program, uint8_t channel) const;
+    std::string get_controller_name (Evoral::Parameter param) const;
     std::string get_instrument_name () const;
 
     boost::shared_ptr<MIDI::Name::ChannelNameSet> get_patches (uint8_t channel);
 
     PBD::Signal0<void> Changed;
 
-    static const MIDI::Name::PatchBank::PatchNameList& general_midi_patches();
+    static const MIDI::Name::PatchNameList& general_midi_patches();
 
   private:
     std::string external_instrument_model;
@@ -58,7 +67,7 @@ class InstrumentInfo {
     boost::shared_ptr<MIDI::Name::ChannelNameSet> plugin_programs_to_channel_name_set (boost::shared_ptr<Processor> p);
     std::string get_plugin_patch_name (boost::shared_ptr<ARDOUR::Processor>, uint16_t bank, uint8_t program, uint8_t channel) const;
 
-    static MIDI::Name::PatchBank::PatchNameList _gm_patches;
+    static MIDI::Name::PatchNameList _gm_patches;
 };
 
 } /* namespace ARDOUR */
index cf7167e3af21f3b40bafb5efaa13164937379372..c5f3bb977b85767c7cbfd2a9453e4989bf6907f9 100644 (file)
@@ -60,10 +60,18 @@ public:
 
        bool bounceable (boost::shared_ptr<Processor>, bool) const { return false; }
        boost::shared_ptr<Region> bounce (InterThreadInfo&);
-       boost::shared_ptr<Region> bounce_range (framepos_t start, framepos_t end, InterThreadInfo&, 
-                                               boost::shared_ptr<Processor> endpoint, bool include_endpoint);
-       int export_stuff (BufferSet& bufs, framepos_t start_frame, framecnt_t end_frame, 
-                         boost::shared_ptr<Processor> endpoint, bool include_endpoint, bool for_export);
+       boost::shared_ptr<Region> bounce_range (framepos_t                   start,
+                                               framepos_t                   end,
+                                               InterThreadInfo&             iti,
+                                               boost::shared_ptr<Processor> endpoint,
+                                               bool                         include_endpoint);
+
+       int export_stuff (BufferSet&                   bufs,
+                         framepos_t                   start_frame,
+                         framecnt_t                   end_frame,
+                         boost::shared_ptr<Processor> endpoint,
+                         bool                         include_endpoint,
+                         bool                         for_export);
 
        int set_state (const XMLNode&, int version);
 
@@ -86,6 +94,8 @@ public:
        NoteMode note_mode() const { return _note_mode; }
        void set_note_mode (NoteMode m);
 
+       std::string describe_parameter (Evoral::Parameter param);
+
        bool step_editing() const { return _step_editing; }
        void set_step_editing (bool yn);
        MidiRingBuffer<framepos_t>& step_edit_ring_buffer() { return _step_edit_ring_buffer; }
@@ -102,7 +112,7 @@ public:
        boost::shared_ptr<MidiBuffer> get_gui_feed_buffer () const;
 
        void set_monitoring (MonitorChoice);
-        MonitorState monitoring_state () const;
+       MonitorState monitoring_state () const;
 
        void set_input_active (bool);
        bool input_active () const;
index 16895281236316ef008dc8d11bbc1c2023ea9b69..84f8cd56cca540948a29b93998d29a72e5d3fb29 100644 (file)
@@ -25,8 +25,6 @@
 
 #include "pbd/error.h"
 
-#include "midi++/names.h"
-
 #include "ardour/amp.h"
 #include "ardour/automatable.h"
 #include "ardour/event_type_map.h"
@@ -159,8 +157,7 @@ Automatable::describe_parameter (Evoral::Parameter param)
        if (param == Evoral::Parameter(GainAutomation)) {
                return _("Fader");
        } else if (param.type() == MidiCCAutomation) {
-               return string_compose("%1: %2 [%3]",
-                               param.id(), midi_name(param.id()), int(param.channel()) + 1);
+               return string_compose("Controller %1 [%2]", param.id(), int(param.channel()) + 1);
        } else if (param.type() == MidiPgmChangeAutomation) {
                return string_compose("Program [%1]", int(param.channel()) + 1);
        } else if (param.type() == MidiPitchBenderAutomation) {
index 8bae716f4a5769f8b0e224e83fd0f2f97f0ce395..725dc3b5e94dbd04c7178bf04dd07675c8b82b2a 100644 (file)
@@ -34,7 +34,7 @@ using namespace ARDOUR;
 using namespace MIDI::Name;
 using std::string;
 
-MIDI::Name::PatchBank::PatchNameList InstrumentInfo::_gm_patches;
+MIDI::Name::PatchNameList InstrumentInfo::_gm_patches;
 
 InstrumentInfo::InstrumentInfo ()
        : external_instrument_model (_("Unknown"))
@@ -45,7 +45,6 @@ InstrumentInfo::~InstrumentInfo ()
 {
 }
 
-
 void
 InstrumentInfo::set_external_instrument (const string& model, const string& mode)
 {
@@ -68,7 +67,6 @@ string
 InstrumentInfo::get_instrument_name () const
 {
        boost::shared_ptr<Processor> p = internal_instrument.lock();
-
        if (p) {
                return p->name();
        }
@@ -84,7 +82,6 @@ string
 InstrumentInfo::get_patch_name (uint16_t bank, uint8_t program, uint8_t channel) const
 {
        boost::shared_ptr<Processor> p = internal_instrument.lock();
-
        if (p) {
                return get_plugin_patch_name (p, bank, program, channel);
        }
@@ -106,11 +103,41 @@ InstrumentInfo::get_patch_name (uint16_t bank, uint8_t program, uint8_t channel)
        }
 }      
 
+string
+InstrumentInfo::get_controller_name (Evoral::Parameter param) const
+{
+       boost::shared_ptr<Processor> p = internal_instrument.lock();
+       if (p || param.type() != MidiCCAutomation) {
+               return "";
+       }
+
+       boost::shared_ptr<MIDI::Name::MasterDeviceNames> dev_names(
+               MIDI::Name::MidiPatchManager::instance().master_device_by_model(
+                       external_instrument_model));
+       if (!dev_names) {
+               return "";
+       }
+       
+       boost::shared_ptr<ChannelNameSet> chan_names(
+               dev_names->channel_name_set_by_device_mode_and_channel(
+                       external_instrument_mode, param.channel()));
+       if (!chan_names) {
+               return "";
+       }
+
+       boost::shared_ptr<ControlNameList> control_names(
+               dev_names->control_name_list(chan_names->control_list_name()));
+       if (!control_names) {
+               return "";
+       }
+
+       return control_names->control(param.id())->name();
+}      
+
 boost::shared_ptr<MIDI::Name::ChannelNameSet>
 InstrumentInfo::get_patches (uint8_t channel)
 {
        boost::shared_ptr<Processor> p = internal_instrument.lock();
-
        if (p) {
                return plugin_programs_to_channel_name_set (p);
        }
@@ -128,10 +155,9 @@ InstrumentInfo::get_patches (uint8_t channel)
 boost::shared_ptr<MIDI::Name::ChannelNameSet>
 InstrumentInfo::plugin_programs_to_channel_name_set (boost::shared_ptr<Processor> p)
 {
-       PatchBank::PatchNameList patch_list;
+       PatchNameList patch_list;
 
        boost::shared_ptr<PluginInsert> insert = boost::dynamic_pointer_cast<PluginInsert> (p);
-
        if (!insert) {
                return boost::shared_ptr<ChannelNameSet>();
        }
@@ -177,7 +203,7 @@ InstrumentInfo::plugin_programs_to_channel_name_set (boost::shared_ptr<Processor
        return cns;
 }      
 
-const MIDI::Name::PatchBank::PatchNameList&
+const MIDI::Name::PatchNameList&
 InstrumentInfo::general_midi_patches()
 {
        if (_gm_patches.empty()) {
@@ -193,7 +219,6 @@ string
 InstrumentInfo::get_plugin_patch_name (boost::shared_ptr<Processor> p, uint16_t bank, uint8_t program, uint8_t /*channel*/) const
 {
        boost::shared_ptr<PluginInsert> insert = boost::dynamic_pointer_cast<PluginInsert> (p);
-
        if (insert) {
                boost::shared_ptr<Plugin> pp = insert->plugin();
                
index 525db3ab96b9c7f14b0505cb05d1ad39a0836b10..65a42836a35b57d981579431e9eb0eb499fcb049 100644 (file)
@@ -525,6 +525,13 @@ MidiTrack::set_note_mode (NoteMode m)
        midi_diskstream()->set_note_mode(m);
 }
 
+std::string
+MidiTrack::describe_parameter (Evoral::Parameter param)
+{
+       const std::string str(instrument_info().get_controller_name(param));
+       return str.empty() ? Automatable::describe_parameter(param) : str;
+}
+
 void
 MidiTrack::midi_panic()
 {
index 64eea6f2bf61c189c2d988309f06fc8f1c35c909..ddd62c29167a66183f6a7e331dc1a6aca324047f 100644 (file)
@@ -88,8 +88,8 @@ 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& name) { _name = name; }
        
        const std::string& note_list_name() const  { return _note_list_name; }
 
@@ -110,16 +110,16 @@ private:
        std::string     _note_list_name;
 };
 
+typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
+
 class PatchBank 
 {
 public:
-       typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
-
        PatchBank (uint16_t n = 0, std::string a_name = std::string()) : _name(a_name), _number (n) {};
        virtual ~PatchBank() { }
 
-       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; }
 
        int number() const { return _number; }
 
@@ -148,10 +148,10 @@ public:
 
        ChannelNameSet() {};
        virtual ~ChannelNameSet() {};
-       ChannelNameSet(std::string a_name) : _name(a_name) {};
+       ChannelNameSet(std::string& name) : _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 PatchBanks& patch_banks() const    { return _patch_banks; }
 
@@ -197,23 +197,26 @@ public:
                return boost::shared_ptr<Patch>();
        }
 
-       const std::string& note_list_name() const { return _note_list_name; }
+       const std::string& note_list_name()    const { return _note_list_name; }
+       const std::string& control_list_name() const { return _control_list_name; }
 
        XMLNode& get_state (void);
        int      set_state (const XMLTree&, const XMLNode&);
 
        void set_patch_banks (const PatchBanks&);
-       void use_patch_name_list (const PatchBank::PatchNameList&);
+       void use_patch_name_list (const PatchNameList&);
 
 private:
        friend std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
-       std::string _name;
+
+       std::string          _name;
        AvailableForChannels _available_for_channels;
        PatchBanks           _patch_banks;
        PatchMap             _patch_map;
        PatchList            _patch_list;
        std::string          _patch_list_name;
        std::string          _note_list_name;
+       std::string          _control_list_name;
 };
 
 std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
@@ -264,7 +267,7 @@ class Control
 public:
        Control() {}
        Control(const std::string& type,
-               const std::string& number,
+               const uint16_t     number,
                const std::string& name)
                : _type(type)
                , _number(number)
@@ -272,33 +275,35 @@ public:
        {}
 
        const std::string& type()   const { return _type; }
-       const std::string& number() const { return _number; }
+       uint16_t           number() const { return _number; }
        const std::string& name()   const { return _name; }
 
-       void set_type(const std::string& type)     { _type = type; }
-       void set_number(const std::string& number) { _number = number; }
-       void set_name(const std::string& name)     { _name = name; }
+       void set_type(const std::string& type) { _type = type; }
+       void set_number(uint16_t number)       { _number = number; }
+       void set_name(const std::string& name) { _name = name; }
 
        XMLNode& get_state(void);
        int      set_state(const XMLTree&, const XMLNode&);
 
 private:
        std::string _type;
-       std::string _number;
+       uint16_t    _number;
        std::string _name;
 };
 
 class ControlNameList 
 {
 public:
-       typedef std::list< boost::shared_ptr<Control> > Controls;
+       typedef std::map<uint16_t, boost::shared_ptr<Control> > Controls;
 
        ControlNameList() {}
        ControlNameList(const std::string& name) : _name(name) {}
 
        const std::string& name() const { return _name; }
 
-       void set_name(const std::string name) { _name = name; }
+       void set_name(const std::string& name) { _name = name; }
+
+       boost::shared_ptr<const Control> control(uint16_t num) const;
 
        const Controls& controls() const { return _controls; }
 
@@ -316,15 +321,15 @@ public:
        CustomDeviceMode() {};
        virtual ~CustomDeviceMode() {};
 
-       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; }
 
        
        XMLNode& get_state (void);
        int      set_state (const XMLTree&, const XMLNode&);
        
        /// Note: channel here is 0-based while in the MIDNAM-file it's 1-based
-       std::string channel_name_set_name_by_channel(uint8_t channel) {
+       const std::string& channel_name_set_name_by_channel(uint8_t channel) {
                assert(channel <= 15);
                return _channel_name_set_assignments[channel]; 
        }
@@ -339,21 +344,21 @@ private:
 class MasterDeviceNames
 {
 public:
-       typedef std::set<std::string>                                        Models;
+       typedef std::set<std::string>                                       Models;
        /// maps name to CustomDeviceMode
-       typedef std::map<std::string, boost::shared_ptr<CustomDeviceMode> >  CustomDeviceModes;
-       typedef std::list<std::string>                                       CustomDeviceModeNames;
+       typedef std::map<std::string, boost::shared_ptr<CustomDeviceMode> > CustomDeviceModes;
+       typedef std::list<std::string>                                      CustomDeviceModeNames;
        /// maps name to ChannelNameSet
-       typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> >    ChannelNameSets;
-       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;
+       typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> >   ChannelNameSets;
+       typedef std::map<std::string, boost::shared_ptr<NoteNameList> >     NoteNameLists;
+       typedef std::map<std::string, boost::shared_ptr<ControlNameList> >  ControlNameLists;
+       typedef std::map<std::string, PatchNameList>                        PatchNameLists;
        
        MasterDeviceNames() {};
        virtual ~MasterDeviceNames() {};
        
        const std::string& manufacturer() const { return _manufacturer; }
-       void set_manufacturer(const std::string a_manufacturer) { _manufacturer = a_manufacturer; }
+       void set_manufacturer(const std::string& manufacturer) { _manufacturer = manufacturer; }
        
        const Models& models() const { return _models; }
        void set_models(const Models some_models) { _models = some_models; }
@@ -366,8 +371,9 @@ public:
        boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(const std::string& mode, uint8_t channel);
        boost::shared_ptr<Patch> find_patch(const 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);
+       boost::shared_ptr<ControlNameList> control_name_list(const std::string& name);
+       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,
@@ -396,11 +402,11 @@ public:
        typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
        
        MIDINameDocument() {}
-       MIDINameDocument(const std::string &filename);
+       MIDINameDocument(const std::stringfilename);
        virtual ~MIDINameDocument() {};
 
        const std::string& author() const { return _author; }
-       void set_author(const std::string an_author) { _author = an_author; }
+       void set_author(const std::string& author) { _author = author; }
        
        boost::shared_ptr<MasterDeviceNames> master_device_names(const std::string& model);
 
diff --git a/libs/midi++2/midi++/names.h b/libs/midi++2/midi++/names.h
deleted file mode 100644 (file)
index 1a94e67..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/* Names of standard MIDI events and controllers.
- * Copyright (C) 2007-2008 David Robillard <http://drobilla.net>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
-
-#ifndef __midinames_h__
-#define __midinames_h__
-
-#include <stdint.h>
-
-#include "events.h"
-
-/** \group midi
- */
-
-/** Pass this a symbol defined in events.h (e.g. MIDI_CTL_PAN) to get the
- * short name of a MIDI event/controller according to General MIDI.
- */
-inline static const char* midi_name(uint8_t status)
-{
-       switch (status) {
-       
-       case MIDI_CMD_NOTE_OFF:
-               return "Note Off"; break;
-       case MIDI_CMD_NOTE_ON:
-               return "Note On"; break;
-       case MIDI_CMD_NOTE_PRESSURE:
-               return "Key Pressure"; break;
-       case MIDI_CMD_CONTROL:
-               return "Control Change"; break;
-       case MIDI_CMD_PGM_CHANGE:
-               return "Program Change"; break;
-       case MIDI_CMD_CHANNEL_PRESSURE:
-               return "Channel Pressure"; break;
-       case MIDI_CMD_BENDER:
-               return "Pitch Bender"; break;
-
-       case MIDI_CMD_COMMON_SYSEX:
-               return "Sysex (System Exclusive) Begin"; break;
-       case MIDI_CMD_COMMON_MTC_QUARTER:
-               return "MTC Quarter Frame"; break;
-       case MIDI_CMD_COMMON_SONG_POS:
-               return "Song Position"; break;
-       case MIDI_CMD_COMMON_SONG_SELECT:
-               return "Song Select"; break;
-       case MIDI_CMD_COMMON_TUNE_REQUEST:
-               return "Tune Request"; break;
-       case MIDI_CMD_COMMON_SYSEX_END:
-               return "End of Sysex"; break;
-       case MIDI_CMD_COMMON_CLOCK:
-               return "Clock"; break;
-       case MIDI_CMD_COMMON_TICK:
-               return "Tick"; break;
-       case MIDI_CMD_COMMON_START:
-               return "Start"; break;
-       case MIDI_CMD_COMMON_CONTINUE:
-               return "Continue"; break;
-       case MIDI_CMD_COMMON_STOP:
-               return "Stop"; break;
-       case MIDI_CMD_COMMON_SENSING:
-               return "Active Sensing"; break;
-       case MIDI_CMD_COMMON_RESET:
-               return "Reset"; break;
-
-       case MIDI_CTL_MSB_BANK:
-               return "Bank Select (Coarse)"; break;
-       case MIDI_CTL_MSB_MODWHEEL:
-               return "Modulation (Coarse)"; break;
-       case MIDI_CTL_MSB_BREATH:
-               return "Breath (Coarse)"; break;
-       case MIDI_CTL_MSB_FOOT:
-               return "Foot (Coarse)"; break;
-       case MIDI_CTL_MSB_PORTAMENTO_TIME:
-               return "Portamento Time (Coarse)"; break;
-       case MIDI_CTL_MSB_DATA_ENTRY:
-               return "Data Entry (Coarse)"; break;
-       case MIDI_CTL_MSB_MAIN_VOLUME:
-               return "Main Volume (Coarse)"; break;
-       case MIDI_CTL_MSB_BALANCE:
-               return "Balance (Coarse)"; break;
-       case MIDI_CTL_MSB_PAN:
-               return "Pan (Coarse)"; break;
-       case MIDI_CTL_MSB_EXPRESSION:
-               return "Expression (Coarse)"; break;
-       case MIDI_CTL_MSB_EFFECT1:
-               return "Effect 1 (Coarse)"; break;
-       case MIDI_CTL_MSB_EFFECT2:
-               return "Effect 2 (Coarse)"; break;
-       case MIDI_CTL_MSB_GENERAL_PURPOSE1:
-               return "General Purpose 1 (Coarse)"; break;
-       case MIDI_CTL_MSB_GENERAL_PURPOSE2:
-               return "General Purpose 2 (Coarse)"; break;
-       case MIDI_CTL_MSB_GENERAL_PURPOSE3:
-               return "General Purpose 3 (Coarse)"; break;
-       case MIDI_CTL_MSB_GENERAL_PURPOSE4:
-               return "General Purpose 4 (Coarse)"; break;
-       case MIDI_CTL_LSB_BANK:
-               return "Bank Select (Fine)"; break;
-       case MIDI_CTL_LSB_MODWHEEL:
-               return "Modulation (Fine)"; break;
-       case MIDI_CTL_LSB_BREATH:
-               return "Breath (Fine)"; break;
-       case MIDI_CTL_LSB_FOOT:
-               return "Foot (Fine)"; break;
-       case MIDI_CTL_LSB_PORTAMENTO_TIME:
-               return "Portamento Time (Fine)"; break;
-       case MIDI_CTL_LSB_DATA_ENTRY:
-               return "Data Entry (Fine)"; break;
-       case MIDI_CTL_LSB_MAIN_VOLUME:
-               return "Main Volume (Fine)"; break;
-       case MIDI_CTL_LSB_BALANCE:
-               return "Balance (Fine)"; break;
-       case MIDI_CTL_LSB_PAN:
-               return "Pan (Fine)"; break;
-       case MIDI_CTL_LSB_EXPRESSION:
-               return "Expression (Fine)"; break;
-       case MIDI_CTL_LSB_EFFECT1:
-               return "Effect 1 (Fine)"; break;
-       case MIDI_CTL_LSB_EFFECT2:
-               return "Effect 2 (Fine)"; break;
-       case MIDI_CTL_LSB_GENERAL_PURPOSE1:
-               return "General Purpose 1 (Fine)"; break;
-       case MIDI_CTL_LSB_GENERAL_PURPOSE2:
-               return "General Purpose 2 (Fine)"; break;
-       case MIDI_CTL_LSB_GENERAL_PURPOSE3:
-               return "General Purpose 3 (Fine)"; break;
-       case MIDI_CTL_LSB_GENERAL_PURPOSE4:
-               return "General Purpose 4 (Fine)"; break;
-       case MIDI_CTL_SUSTAIN:
-               return "Sustain Pedal"; break;
-       case MIDI_CTL_PORTAMENTO:
-               return "Portamento"; break;
-       case MIDI_CTL_SOSTENUTO:
-               return "Sostenuto"; break;
-       case MIDI_CTL_SOFT_PEDAL:
-               return "Soft Pedal"; break;
-       case MIDI_CTL_LEGATO_FOOTSWITCH:
-               return "Legato Foot Switch"; break;
-       case MIDI_CTL_HOLD2:
-               return "Hold2"; break;
-       case MIDI_CTL_SC1_SOUND_VARIATION:
-               return "Sound Variation"; break;
-       case MIDI_CTL_SC2_TIMBRE:
-               return "Sound Timbre"; break;
-       case MIDI_CTL_SC3_RELEASE_TIME:
-               return "Sound Release Time"; break;
-       case MIDI_CTL_SC4_ATTACK_TIME:
-               return "Sound Attack Time"; break;
-       case MIDI_CTL_SC5_BRIGHTNESS:
-               return "Sound Brightness"; break;
-       case MIDI_CTL_SC6:
-               return "Sound Control 6"; break;
-       case MIDI_CTL_SC7:
-               return "Sound Control 7"; break;
-       case MIDI_CTL_SC8:
-               return "Sound Control 8"; break;
-       case MIDI_CTL_SC9:
-               return "Sound Control 9"; break;
-       case MIDI_CTL_SC10:
-               return "Sound Control 10"; break;
-       case MIDI_CTL_GENERAL_PURPOSE5:
-               return "General Purpose 5"; break;
-       case MIDI_CTL_GENERAL_PURPOSE6:
-               return "General Purpose 6"; break;
-       case MIDI_CTL_GENERAL_PURPOSE7:
-               return "General Purpose 7"; break;
-       case MIDI_CTL_GENERAL_PURPOSE8:
-               return "General Purpose 8"; break;
-       case MIDI_CTL_PORTAMENTO_CONTROL:
-               return "Portamento Control"; break;
-       case MIDI_CTL_E1_REVERB_DEPTH:
-               return "Reverb Depth"; break;
-       case MIDI_CTL_E2_TREMOLO_DEPTH:
-               return "Tremolo Depth"; break;
-       case MIDI_CTL_E3_CHORUS_DEPTH:
-               return "Chorus Depth"; break;
-       case MIDI_CTL_E4_DETUNE_DEPTH:
-               return "Detune Depth"; break;
-       case MIDI_CTL_E5_PHASER_DEPTH:
-               return "Phaser Depth"; break;
-       case MIDI_CTL_DATA_INCREMENT:
-               return "Data Increment"; break;
-       case MIDI_CTL_DATA_DECREMENT:
-               return "Data Decrement"; break;
-       case MIDI_CTL_NONREG_PARM_NUM_LSB:
-               return "Non-registered Parameter Number"; break;
-       case MIDI_CTL_NONREG_PARM_NUM_MSB:
-               return "Non-registered Narameter Number"; break;
-       case MIDI_CTL_REGIST_PARM_NUM_LSB:
-               return "Registered Parameter Number"; break;
-       case MIDI_CTL_REGIST_PARM_NUM_MSB:
-               return "Registered Parameter Number"; break;
-       case MIDI_CTL_ALL_SOUNDS_OFF:
-               return "All Sounds Off"; break;
-       case MIDI_CTL_RESET_CONTROLLERS:
-               return "Reset Controllers"; break;
-       case MIDI_CTL_LOCAL_CONTROL_SWITCH:
-               return "Local Keyboard on/off"; break;
-       case MIDI_CTL_ALL_NOTES_OFF:
-               return "All Notes Off"; break;
-       case MIDI_CTL_OMNI_OFF:
-               return "Omni Off"; break;
-       case MIDI_CTL_OMNI_ON:
-               return "Omni On"; break;
-       case MIDI_CTL_MONO:
-               return "Monophonic Mode"; break;
-       case MIDI_CTL_POLY:
-               return "Polyphonic Mode"; break;
-       default:
-               break;
-       }
-
-       return "Unnamed";
-       
-}
-
-#endif /* __midinames_h__ */
-
index bb9e27ebff980cef85a6364bbdab9ad938da746d..b6067285728c2da068e2eea1c769519cd58ab45b 100644 (file)
@@ -240,11 +240,11 @@ Control::get_state (void)
 }
 
 int
-Control::set_state (const XMLTree&, const XMLNode& node)
+Control::set_state (const XMLTree& tree, const XMLNode& node)
 {
        assert(node.name() == "Control");
        _type   = node.property("Type")->value();
-       _number = node.property("Number")->value();
+       _number = string_to_int(tree, node.property("Number")->value());
        _name   = node.property("Name")->value();
 
        return 0;
@@ -265,18 +265,35 @@ ControlNameList::set_state (const XMLTree& tree, const XMLNode& node)
        assert(node.name() == "ControlNameList");
        _name = node.property("Name")->value();
 
+       _controls.clear();
        for (XMLNodeList::const_iterator i = node.children().begin();
             i != node.children().end(); ++i) {
-               if ((*i)->name() != "comment") {
+               if ((*i)->name() == "Control") {
                        boost::shared_ptr<Control> control(new Control());
                        control->set_state (tree, *(*i));
-                       _controls.push_back(control);
+                       if (_controls.find(control->number()) == _controls.end()) {
+                               _controls.insert(make_pair(control->number(), control));
+                       } else {
+                               PBD::warning << string_compose("%1: Duplicate control %2 ignored",
+                                                              tree.filename(), control->number())
+                                            << endmsg;
+                       }
                }
        }
 
        return 0;
 }
 
+boost::shared_ptr<const Control>
+ControlNameList::control(uint16_t num) const
+{
+       Controls::const_iterator i = _controls.find(num);
+       if (i != _controls.end()) {
+               return i->second;
+       }
+       return boost::shared_ptr<const Control>();
+}
+
 XMLNode&
 PatchBank::get_state (void)
 {
@@ -357,7 +374,7 @@ operator<< (std::ostream& os, const ChannelNameSet& cns)
        
        for (ChannelNameSet::PatchBanks::const_iterator pbi = cns._patch_banks.begin(); pbi != cns._patch_banks.end(); ++pbi) {
                os << "\tPatch Bank " << (*pbi)->name() << " with " << (*pbi)->patch_name_list().size() << " patches\n";
-               for (PatchBank::PatchNameList::const_iterator pni = (*pbi)->patch_name_list().begin(); pni != (*pbi)->patch_name_list().end(); ++pni) {
+               for (PatchNameList::const_iterator pni = (*pbi)->patch_name_list().begin(); pni != (*pbi)->patch_name_list().end(); ++pni) {
                        os << "\t\tPatch name " << (*pni)->name() << " prog " << (int) (*pni)->program_number() << " bank " << (*pni)->bank_number() << endl;
                }
        }
@@ -376,7 +393,7 @@ ChannelNameSet::set_patch_banks (const ChannelNameSet::PatchBanks& pb)
        _available_for_channels.clear ();
        
        for (PatchBanks::const_iterator pbi = _patch_banks.begin(); pbi != _patch_banks.end(); ++pbi) {
-               for (PatchBank::PatchNameList::const_iterator pni = (*pbi)->patch_name_list().begin(); pni != (*pbi)->patch_name_list().end(); ++pni) {
+               for (PatchNameList::const_iterator pni = (*pbi)->patch_name_list().begin(); pni != (*pbi)->patch_name_list().end(); ++pni) {
                        _patch_map[(*pni)->patch_primary_key()] = (*pni);
                        _patch_list.push_back ((*pni)->patch_primary_key());
                }
@@ -388,9 +405,9 @@ ChannelNameSet::set_patch_banks (const ChannelNameSet::PatchBanks& pb)
 }
 
 void
-ChannelNameSet::use_patch_name_list (const PatchBank::PatchNameList& pnl)
+ChannelNameSet::use_patch_name_list (const PatchNameList& pnl)
 {
-       for (PatchBank::PatchNameList::const_iterator p = pnl.begin(); p != pnl.end(); ++p) {
+       for (PatchNameList::const_iterator p = pnl.begin(); p != pnl.end(); ++p) {
                _patch_map[(*p)->patch_primary_key()] = (*p);
                _patch_list.push_back ((*p)->patch_primary_key());
        }
@@ -431,7 +448,7 @@ int
 ChannelNameSet::set_state (const XMLTree& tree, const XMLNode& node)
 {
        assert(node.name() == "ChannelNameSet");
-       _name   = node.property("Name")->value();
+       _name = node.property("Name")->value();
 
        const XMLNodeList children = node.children();
        for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
@@ -440,29 +457,27 @@ ChannelNameSet::set_state (const XMLTree& tree, const XMLNode& node)
                if (node->name() == "AvailableForChannels") {
                        boost::shared_ptr<XMLSharedNodeList> channels =
                                tree.find("//AvailableChannel[@Available = 'true']/@Channel", node);
-                       for(XMLSharedNodeList::const_iterator i = channels->begin();
+                       for (XMLSharedNodeList::const_iterator i = channels->begin();
                            i != channels->end();
                            ++i) {
                                _available_for_channels.insert(
                                        string_to_int(tree, (*i)->attribute_value()));
                        }
-               }
-
-               if (node->name() == "PatchBank") {
+               } else if (node->name() == "PatchBank") {
                        boost::shared_ptr<PatchBank> bank (new PatchBank ());
                        bank->set_state(tree, *node);
                        _patch_banks.push_back(bank);
-                       const PatchBank::PatchNameList& patches = bank->patch_name_list();
-                       for (PatchBank::PatchNameList::const_iterator patch = patches.begin();
+                       const PatchNameList& patches = bank->patch_name_list();
+                       for (PatchNameList::const_iterator patch = patches.begin();
                             patch != patches.end();
                             ++patch) {
                                _patch_map[(*patch)->patch_primary_key()] = *patch;
                                _patch_list.push_back((*patch)->patch_primary_key());
                        }
-               }
-
-               if (node->name() == "UsesNoteNameList") {
+               } else if (node->name() == "UsesNoteNameList") {
                        _note_list_name = node->property ("Name")->value();
+               } else if (node->name() == "UsesControlNameList") {
+                       _control_list_name = node->property ("Name")->value();
                }
        }
 
@@ -478,7 +493,7 @@ CustomDeviceMode::set_state(const XMLTree& tree, const XMLNode& a_node)
 
        boost::shared_ptr<XMLSharedNodeList> channel_name_set_assignments =
                tree.find("//ChannelNameSetAssign", const_cast<XMLNode *>(&a_node));
-       for(XMLSharedNodeList::const_iterator i = channel_name_set_assignments->begin();
+       for (XMLSharedNodeList::const_iterator i = channel_name_set_assignments->begin();
            i != channel_name_set_assignments->end();
            ++i) {
                const int     channel  = string_to_int(tree, (*i)->property("Channel")->value());
@@ -536,6 +551,16 @@ MasterDeviceNames::channel_name_set(const std::string& name)
        return boost::shared_ptr<ChannelNameSet>();
 }
 
+boost::shared_ptr<ControlNameList>
+MasterDeviceNames::control_name_list(const std::string& name)
+{
+       ControlNameLists::const_iterator i = _control_name_lists.find(name);
+       if (i != _control_name_lists.end()) {
+               return i->second;
+       }
+       return boost::shared_ptr<ControlNameList>();
+}
+
 boost::shared_ptr<NoteNameList>
 MasterDeviceNames::note_name_list(const std::string& name)
 {
@@ -631,7 +656,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[(*i)->property ("Name")->value()] = note_name_list;
+               _note_name_lists[note_name_list->name()] = note_name_list;
        }
 
        // ControlNameLists
@@ -641,7 +666,7 @@ MasterDeviceNames::set_state(const XMLTree& tree, const XMLNode&)
             ++i) {
                boost::shared_ptr<ControlNameList> control_name_list(new ControlNameList());
                control_name_list->set_state (tree, *(*i));
-               _control_name_lists.push_back(control_name_list);
+               _control_name_lists[control_name_list->name()] = control_name_list;
        }
 
        // global/post-facto PatchNameLists
@@ -650,7 +675,7 @@ MasterDeviceNames::set_state(const XMLTree& tree, const XMLNode&)
             i != patch_name_lists->end();
             ++i) {
 
-               PatchBank::PatchNameList patch_name_list;
+               PatchNameList patch_name_list;
                const XMLNodeList patches = (*i)->children();
 
                for (XMLNodeList::const_iterator p = patches.begin(); p != patches.end(); ++p) {
index 5a3a991286dcd865bfaccdbbdb3317807a9dda5e..9a4ba048001f7c09af1353bfb3c18c8aa57a97de 100644 (file)
@@ -77,7 +77,7 @@ MidnamTest::protools_patchfile_test()
 
     bank = banks2.front();
     CPPUNIT_ASSERT_EQUAL(string("Drum sets"), bank->name());
-    const PatchBank::PatchNameList& plist2 = bank->patch_name_list();
+    const PatchNameList& plist2 = bank->patch_name_list();
     CPPUNIT_ASSERT(plist2.size() == 49);
 }
 
@@ -136,9 +136,9 @@ MidnamTest::yamaha_PSRS900_patchfile_test()
                 CPPUNIT_ASSERT(banks1.size() > 1);
 
                 boost::shared_ptr<PatchBank> bank = banks1.front();
-                const PatchBank::PatchNameList& list = bank->patch_name_list();
+                const PatchNameList& list = bank->patch_name_list();
 
-                for(PatchBank::PatchNameList::const_iterator p = list.begin(); p != list.end(); ++p) {
+                for(PatchNameList::const_iterator p = list.begin(); p != list.end(); ++p) {
 
                 if (ns == string("GM+XG")) {
                     cerr << "got Patch with name " << (*p)->name() << " bank " << (*p)->bank_number() << " program " << (int)(*p)->program_number() << endl;