* some refactoring of patch name stuff in preparation for altering program changes...
[ardour.git] / libs / midi++2 / midi++ / midnam_patch.h
1 /*
2     Copyright (C) 2008 Hans Baier 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #ifndef MIDNAM_PATCH_H_
22 #define MIDNAM_PATCH_H_
23
24 #include <string>
25 #include <list>
26 #include <set>
27 #include <map>
28
29 #include "pbd/stateful.h"
30 #include "midi++/event.h"
31 #include "pbd/xml++.h"
32
33 namespace MIDI
34 {
35
36 namespace Name
37 {
38
39 struct PatchPrimaryKey
40 {
41 public:
42         int msb;
43         int lsb;
44         int program_number;
45         
46         PatchPrimaryKey(int a_msb = -1, int a_lsb = -1, int a_program_number = -1) {
47                 msb = a_msb;
48                 lsb = a_lsb;
49                 program_number = a_program_number;
50         }
51         
52         bool is_sane() {        
53                 return ((msb >= 0) && (msb <= 127) &&
54                         (lsb >= 0) && (lsb <= 127) &&
55                         (program_number >=0 ) && (program_number <= 127));
56         }
57         
58         inline PatchPrimaryKey& operator=(const PatchPrimaryKey& id) {
59                 msb = id.msb;
60                 lsb = id.lsb; 
61                 program_number = id.program_number;
62                 return *this;
63         }
64         
65         inline bool operator==(const PatchPrimaryKey& id) const {
66                 return (msb == id.msb && lsb == id.lsb && program_number == id.program_number);
67         }
68         
69         /**
70          * obey strict weak ordering or crash in STL containers
71          */
72         inline bool operator<(const PatchPrimaryKey& id) const {
73                 if (msb < id.msb) {
74                         return true;
75                 } else if (msb == id.msb && lsb < id.lsb) {
76                         return true;
77                 } else if (lsb == id.lsb && program_number < id.program_number) {
78                         return true;
79                 }
80                 
81                 return false;
82         }
83 };
84
85 class Patch : public PBD::Stateful
86 {
87 public:
88         typedef std::list<boost::shared_ptr<Evoral::MIDIEvent> > PatchMidiCommands;
89
90         Patch() {};
91         Patch(string a_number, string a_name) : _number(a_number), _name(a_name) {};
92         ~Patch() {};
93
94         const string& name() const               { return _name; }
95         void set_name(const string a_name)       { _name = a_name; }
96
97         const string& number() const             { return _number; }
98         void set_number(const string a_number)   { _number = a_number; }
99
100         const PatchMidiCommands& patch_midi_commands() const { return _patch_midi_commands; }
101         
102         const PatchPrimaryKey&   patch_primary_key()   const { return _id; }
103
104         XMLNode& get_state (void);
105         int      set_state (const XMLNode& a_node);
106
107 private:
108         string            _number;
109         string            _name;
110         PatchPrimaryKey   _id;
111         PatchMidiCommands _patch_midi_commands;
112 };
113
114 class PatchBank : public PBD::Stateful
115 {
116 public:
117         typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
118
119         PatchBank() {};
120         virtual ~PatchBank() {};
121         PatchBank(string a_name) : _name(a_name) {};
122
123         const string& name() const               { return _name; }
124         void set_name(const string a_name)       { _name = a_name; }
125
126         const PatchNameList& patch_name_list() const { return _patch_name_list; }
127
128         XMLNode& get_state (void);
129         int      set_state (const XMLNode& a_node);
130
131 private:
132         string        _name;
133         PatchNameList _patch_name_list;
134 };
135
136 class ChannelNameSet : public PBD::Stateful
137 {
138 public:
139         typedef std::set<uint8_t>                                    AvailableForChannels;
140         typedef std::list<boost::shared_ptr<PatchBank> >             PatchBanks;
141         typedef std::map<PatchPrimaryKey, boost::shared_ptr<Patch> > PatchMap;
142
143         ChannelNameSet() {};
144         virtual ~ChannelNameSet() {};
145         ChannelNameSet(string a_name) : _name(a_name) {};
146
147         const string& name() const               { return _name; }
148         void set_name(const string a_name)       { _name = a_name; }
149
150         bool available_for_channel(uint8_t channel) const { 
151                 return _available_for_channels.find(channel) != _available_for_channels.end(); 
152         }
153         
154         boost::shared_ptr<Patch> find_patch(PatchPrimaryKey& key) {
155                 assert(key.is_sane());
156                 return _patch_map[key];
157         }
158         
159         boost::shared_ptr<Patch> previous_patch(PatchPrimaryKey& key) {
160                 assert(key.is_sane());
161                 return (*(--_patch_map.find(key))).second;
162         }
163         
164         boost::shared_ptr<Patch> next_patch(PatchPrimaryKey& key) {
165                 assert(key.is_sane());
166                 return (*(++_patch_map.find(key))).second;
167         }
168
169         XMLNode& get_state (void);
170         int      set_state (const XMLNode& a_node);
171
172 private:
173         string _name;
174         AvailableForChannels _available_for_channels;
175         PatchBanks           _patch_banks;
176         PatchMap             _patch_map;
177 };
178
179 class Note : public PBD::Stateful
180 {
181 public:
182         Note() {};
183         Note(string a_number, string a_name) : _number(a_number), _name(a_name) {};
184         ~Note() {};
185
186         const string& name() const               { return _name; }
187         void set_name(const string a_name)       { _name = a_name; }
188
189         const string& number() const             { return _number; }
190         void set_number(const string a_number)   { _number = a_number; }
191
192         XMLNode& get_state (void);
193         int      set_state (const XMLNode& a_node);
194
195 private:
196         string _number;
197         string _name;
198 };
199
200 class NoteNameList : public PBD::Stateful
201 {
202 public:
203         typedef std::list<boost::shared_ptr<Note> > Notes;
204         NoteNameList() {};
205         NoteNameList(string a_name) : _name(a_name) {};
206         ~NoteNameList() {};
207
208         const string& name() const               { return _name; }
209         void set_name(const string a_name)       { _name = a_name; }
210
211         const Notes& notes() const { return _notes; }
212
213         XMLNode& get_state (void);
214         int      set_state (const XMLNode& a_node);
215
216 private:
217         string _name;
218         Notes  _notes;
219 };
220
221 class CustomDeviceMode : public PBD::Stateful
222 {
223 public:
224         CustomDeviceMode() {};
225         virtual ~CustomDeviceMode() {};
226
227         const string& name() const               { return _name; }
228         void set_name(const string a_name)       { _name = a_name; }
229
230         
231         XMLNode& get_state (void);
232         int      set_state (const XMLNode& a_node);
233         
234         string channel_name_set_name_by_channel(uint8_t channel) {
235                 assert(channel <= 15);
236                 return _channel_name_set_assignments[channel]; 
237         }
238         
239 private:
240         /// array index = channel number
241         /// string contents = name of channel name set 
242         string _name;
243         string _channel_name_set_assignments[16];
244 };
245
246 class MasterDeviceNames : public PBD::Stateful
247 {
248 public:
249         typedef std::list<std::string>                                       Models;
250         /// maps name to CustomDeviceMode
251         typedef std::map<std::string, boost::shared_ptr<CustomDeviceMode> >  CustomDeviceModes;
252         typedef std::list<std::string>                                       CustomDeviceModeNames;
253         /// maps name to ChannelNameSet
254         typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> >    ChannelNameSets;
255         typedef std::list<boost::shared_ptr<NoteNameList> >                  NoteNameLists;
256         
257         
258         MasterDeviceNames() {};
259         virtual ~MasterDeviceNames() {};
260         
261         const string& manufacturer() const { return _manufacturer; }
262         void set_manufacturer(const string a_manufacturer) { _manufacturer = a_manufacturer; }
263         
264         const Models& models() const { return _models; }
265         void set_models(const Models some_models) { _models = some_models; }
266         
267         const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
268         
269         boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(string mode_name) {
270                 assert(mode_name != "");
271                 return _custom_device_modes[mode_name];
272         }
273         
274         boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(string mode, uint8_t channel) {
275                 return _channel_name_sets[custom_device_mode_by_name(mode)->channel_name_set_name_by_channel(channel)];
276         }
277         
278         boost::shared_ptr<Patch> find_patch(string mode, uint8_t channel, PatchPrimaryKey& key) {
279                 return channel_name_set_by_device_mode_and_channel(mode, channel)->find_patch(key);
280         }
281         
282         XMLNode& get_state (void);
283         int      set_state (const XMLNode& a_node);
284         
285 private:
286         string                _manufacturer;
287         Models                _models;
288         CustomDeviceModes     _custom_device_modes;
289         CustomDeviceModeNames _custom_device_mode_names;
290         ChannelNameSets       _channel_name_sets;
291         NoteNameLists         _note_name_lists;
292 };
293
294 class MIDINameDocument : public PBD::Stateful
295 {
296 public:
297         // Maps Model names to MasterDeviceNames
298         typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
299         
300         MIDINameDocument() {};
301         MIDINameDocument(const string &filename) : _document(XMLTree(filename)) { set_state(*_document.root()); };
302         virtual ~MIDINameDocument() {};
303
304         const string& author() const { return _author; }
305         void set_author(const string an_author) { _author = an_author; }
306         
307         const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; }
308         
309         const MasterDeviceNames::Models& all_models() const { return _all_models; }
310                 
311         XMLNode& get_state (void);
312         int      set_state (const XMLNode& a_node);
313
314 private:
315         string                        _author;
316         MasterDeviceNamesList         _master_device_names_list;
317         XMLTree                       _document;
318         MasterDeviceNames::Models     _all_models;
319 };
320
321 }
322
323 }
324 #endif /*MIDNAM_PATCH_H_*/