Add General MIDI drum note names and patch names.
[ardour.git] / libs / midi++2 / midi++ / midnam_patch.h
index 11bdb79f8b61db6fa896f9cf702e4341e4288057..338642025e7d68b593d3c1b54cb6a718d9a1468e 100644 (file)
@@ -1,5 +1,6 @@
 /*
-    Copyright (C) 2008 Hans Baier 
+    Copyright (C) 2012 Paul Davis
+    Author: Hans Baier
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-    $Id$
 */
 
 #ifndef MIDNAM_PATCH_H_
 #define MIDNAM_PATCH_H_
 
+#include <algorithm>
 #include <iostream>
 #include <string>
 #include <list>
 #include <set>
 #include <map>
+#include <vector>
+
+#include <stdint.h>
 
 #include "midi++/event.h"
 #include "pbd/xml++.h"
@@ -39,42 +42,36 @@ namespace Name
 struct PatchPrimaryKey
 {
 public:
-       int msb;
-       int lsb;
+       int bank_number;
        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;
+
+       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() {        
-               return ((msb >= 0) && (msb <= 127) &&
-                       (lsb >= 0) && (lsb <= 127) &&
+       bool is_sane() const {  
+               return ((bank_number >= 0) && (bank_number <= 16384) && 
                        (program_number >=0 ) && (program_number <= 127));
        }
        
        inline PatchPrimaryKey& operator=(const PatchPrimaryKey& id) {
-               msb = id.msb;
-               lsb = id.lsb; 
+               bank_number = id.bank_number;
                program_number = id.program_number;
                return *this;
        }
        
        inline bool operator==(const PatchPrimaryKey& id) const {
-               return (msb == id.msb && lsb == id.lsb && program_number == id.program_number);
+               return (bank_number == id.bank_number && 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) {
+               if (bank_number < id.bank_number) {
                        return true;
-               } else if (msb == id.msb && lsb < id.lsb) {
-                       return true;
-               } else if (msb == id.msb && lsb == id.lsb && program_number < id.program_number) {
+               } else if (bank_number == id.bank_number && program_number < id.program_number) {
                        return true;
                }
                
@@ -88,27 +85,29 @@ class Patch
 {
 public:
 
-       Patch (PatchBank* a_bank = 0);
-       Patch(std::string a_number, std::string a_name, PatchBank* a_bank = 0);
+       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& number() const        { return _number; }
-       void set_number(const std::string a_number)   { _number = a_number; }
+       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; }
+
+       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; }
 
        XMLNode& get_state (void);
        int      set_state (const XMLTree&, const XMLNode&);
 
-       int use_bank_info (PatchBank*);
-
 private:
-       std::string        _number;
-       std::string        _name;
-       PatchPrimaryKey   _id;
+       std::string     _name;
+       PatchPrimaryKey _id;
+       std::string     _note_list_name;
 };
 
 class PatchBank 
@@ -116,27 +115,26 @@ class PatchBank
 public:
        typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
 
-       PatchBank () : _id(0) {};
-       PatchBank (std::string a_name, PatchPrimaryKey* an_id = 0) : _name(a_name), _id(an_id) {};
-       virtual ~PatchBank() { delete _id; };
+       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; }
 
+       int number() const { return _number; }
+
        const PatchNameList& patch_name_list() const { return _patch_name_list; }
        const std::string& patch_list_name() const { return _patch_list_name; }
 
        int set_patch_name_list (const PatchNameList&);
 
-       const PatchPrimaryKey* patch_primary_key()  const { return _id; }
-
        XMLNode& get_state (void);
        int      set_state (const XMLTree&, const XMLNode&);
 
 private:
        std::string       _name;
+       uint16_t          _number;
        PatchNameList     _patch_name_list;
-       PatchPrimaryKey*  _id;
        std::string       _patch_list_name;
 };
 
@@ -161,20 +159,18 @@ 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());
-               std::cerr << "finding patch with "  << key.msb << "/" << key.lsb << "/" <<key.program_number << std::endl; 
                for (PatchList::const_iterator i = _patch_list.begin();
                         i != _patch_list.end();
                         ++i) {
                        if ((*i) == key) {
                                if (i != _patch_list.begin()) {
-                                       std::cerr << "got it!" << std::endl;
                                        --i;
                                        return  _patch_map[*i];
                                } 
@@ -184,15 +180,13 @@ 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());
-               std::cerr << "finding patch with "  << key.msb << "/" << key.lsb << "/" <<key.program_number << std::endl; 
                for (PatchList::const_iterator i = _patch_list.begin();
                         i != _patch_list.end();
                         ++i) {
                        if ((*i) == key) {
                                if (++i != _patch_list.end()) {
-                                       std::cerr << "got it!" << std::endl;
                                        return  _patch_map[*i];
                                } else {
                                        --i;
@@ -203,58 +197,117 @@ public:
                return boost::shared_ptr<Patch>();
        }
 
+       const std::string& note_list_name() const { return _note_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&);
+
 private:
+       friend std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
        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::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 Notes& notes() const { return _notes; }
+       const std::string& name() const  { return _name; }
+       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
+{
+public:
+       Control() {}
+       Control(const std::string& type,
+               const std::string& number,
+               const std::string& name)
+               : _type(type)
+               , _number(number)
+               , _name(name)
+       {}
+
+       const std::string& type()   const { return _type; }
+       const std::string& 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; }
+
+       XMLNode& get_state(void);
+       int      set_state(const XMLTree&, const XMLNode&);
+
+private:
+       std::string _type;
+       std::string _number;
+       std::string _name;
+};
+
+class ControlNameList 
+{
+public:
+       typedef std::list< 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; }
+
+       const Controls& controls() const { return _controls; }
+
+       XMLNode& get_state(void);
+       int      set_state(const XMLTree&, const XMLNode&);
+
+private:
+       std::string _name;
+       Controls    _controls;
 };
 
 class CustomDeviceMode
@@ -270,6 +323,7 @@ public:
        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) {
                assert(channel <= 15);
                return _channel_name_set_assignments[channel]; 
@@ -285,13 +339,14 @@ private:
 class MasterDeviceNames
 {
 public:
-       typedef std::list<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;
        /// 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;
        
        MasterDeviceNames() {};
@@ -302,22 +357,24 @@ public:
        
        const Models& models() const { return _models; }
        void set_models(const Models some_models) { _models = some_models; }
-       
+
+       const ControlNameLists& controls() const { return _control_name_lists; }
+
        const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
        
-       boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(std::string mode_name) {
-               assert(mode_name != "");
-               return _custom_device_modes[mode_name];
-       }
-       
-       boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(std::string mode, uint8_t channel) {
-               return _channel_name_sets[custom_device_mode_by_name(mode)->channel_name_set_name_by_channel(channel)];
-       }
-       
-       boost::shared_ptr<Patch> find_patch(std::string mode, uint8_t channel, PatchPrimaryKey& key) {
-               return channel_name_set_by_device_mode_and_channel(mode, channel)->find_patch(key);
-       }
-       
+       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, 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&);
        
@@ -329,6 +386,7 @@ private:
        ChannelNameSets       _channel_name_sets;
        NoteNameLists         _note_name_lists;
        PatchNameLists        _patch_name_lists;
+       ControlNameLists      _control_name_lists;
 };
 
 class MIDINameDocument
@@ -338,12 +396,14 @@ public:
        typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
        
        MIDINameDocument() {}
-        MIDINameDocument(const std::string &filename);
+       MIDINameDocument(const std::string &filename);
        virtual ~MIDINameDocument() {};
 
        const std::string& author() const { return _author; }
        void set_author(const std::string an_author) { _author = an_author; }
        
+       boost::shared_ptr<MasterDeviceNames> master_device_names(const std::string& model);
+
        const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; }
        
        const MasterDeviceNames::Models& all_models() const { return _all_models; }
@@ -358,6 +418,8 @@ private:
        MasterDeviceNames::Models     _all_models;
 };
 
+extern const char* general_midi_program_names[128]; /* 0 .. 127 */
+
 }
 
 }