more changes to patch change/plugin preset support - replace regexp replacement with...
[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 <algorithm>
25 #include <iostream>
26 #include <string>
27 #include <list>
28 #include <set>
29 #include <map>
30
31 #include <stdint.h>
32
33 #include "midi++/event.h"
34 #include "pbd/xml++.h"
35
36 namespace MIDI
37 {
38
39 namespace Name
40 {
41
42 struct PatchPrimaryKey
43 {
44 public:
45         int bank_number;
46         int program_number;
47     
48         PatchPrimaryKey (uint8_t a_program_number = 0, uint16_t a_bank_number = 0) {
49                 bank_number = std::min (a_bank_number, (uint16_t) 16384);
50                 program_number = std::min (a_program_number, (uint8_t) 127);
51         }
52         
53         bool is_sane() {        
54                 return ((bank_number >= 0) && (bank_number <= 16384) && 
55                         (program_number >=0 ) && (program_number <= 127));
56         }
57         
58         inline PatchPrimaryKey& operator=(const PatchPrimaryKey& id) {
59                 bank_number = id.bank_number;
60                 program_number = id.program_number;
61                 return *this;
62         }
63         
64         inline bool operator==(const PatchPrimaryKey& id) const {
65                 return (bank_number == id.bank_number && program_number == id.program_number);
66         }
67         
68         /**
69          * obey strict weak ordering or crash in STL containers
70          */
71         inline bool operator<(const PatchPrimaryKey& id) const {
72                 if (bank_number < id.bank_number) {
73                         return true;
74                 } else if (bank_number == id.bank_number && program_number < id.program_number) {
75                         return true;
76                 }
77                 
78                 return false;
79         }
80 };
81
82 class PatchBank;
83         
84 class Patch 
85 {
86 public:
87
88         Patch (std::string a_name = std::string(), uint8_t a_number = 0, uint16_t bank_number = 0);
89         virtual ~Patch() {};
90
91         const std::string& name() const          { return _name; }
92         void set_name(const std::string a_name)       { _name = a_name; }
93
94         uint8_t program_number() const       { return _id.program_number; }
95         void set_program_number(uint8_t n)   { _id.program_number = n; }
96
97         uint16_t bank_number() const       { return _id.bank_number; }
98         void set_bank_number (uint16_t n) { _id.bank_number = n; }
99
100         const PatchPrimaryKey&   patch_primary_key()   const { return _id; }
101
102         XMLNode& get_state (void);
103         int      set_state (const XMLTree&, const XMLNode&);
104
105 private:
106         std::string     _name;
107         PatchPrimaryKey _id;
108 };
109
110 class PatchBank 
111 {
112 public:
113         typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
114
115         PatchBank (uint16_t n = 0, std::string a_name = std::string()) : _name(a_name), _number (n) {};
116         virtual ~PatchBank() { }
117
118         const std::string& name() const               { return _name; }
119         void set_name(const std::string a_name)       { _name = a_name; }
120
121         int number() const { return _number; }
122
123         const PatchNameList& patch_name_list() const { return _patch_name_list; }
124         const std::string& patch_list_name() const { return _patch_list_name; }
125
126         int set_patch_name_list (const PatchNameList&);
127
128         XMLNode& get_state (void);
129         int      set_state (const XMLTree&, const XMLNode&);
130
131 private:
132         std::string       _name;
133         uint16_t          _number;
134         PatchNameList     _patch_name_list;
135         std::string       _patch_list_name;
136 };
137
138 class ChannelNameSet
139 {
140 public:
141         typedef std::set<uint8_t>                                    AvailableForChannels;
142         typedef std::list<boost::shared_ptr<PatchBank> >             PatchBanks;
143         typedef std::map<PatchPrimaryKey, boost::shared_ptr<Patch> > PatchMap;
144         typedef std::list<PatchPrimaryKey>                           PatchList;
145
146         ChannelNameSet() {};
147         virtual ~ChannelNameSet() {};
148         ChannelNameSet(std::string a_name) : _name(a_name) {};
149
150         const std::string& name() const          { return _name; }
151         void set_name(const std::string a_name)  { _name = a_name; }
152         
153         const PatchBanks& patch_banks() const    { return _patch_banks; }
154
155         bool available_for_channel(uint8_t channel) const { 
156                 return _available_for_channels.find(channel) != _available_for_channels.end(); 
157         }
158         
159         boost::shared_ptr<Patch> find_patch(PatchPrimaryKey& key) {
160                 assert(key.is_sane());
161                 return _patch_map[key];
162         }
163         
164         boost::shared_ptr<Patch> previous_patch(PatchPrimaryKey& key) {
165                 assert(key.is_sane());
166                 for (PatchList::const_iterator i = _patch_list.begin();
167                          i != _patch_list.end();
168                          ++i) {
169                         if ((*i) == key) {
170                                 if (i != _patch_list.begin()) {
171                                         --i;
172                                         return  _patch_map[*i];
173                                 } 
174                         }
175                 }
176                         
177                 return boost::shared_ptr<Patch>();
178         }
179         
180         boost::shared_ptr<Patch> next_patch(PatchPrimaryKey& key) {
181                 assert(key.is_sane());
182                 for (PatchList::const_iterator i = _patch_list.begin();
183                          i != _patch_list.end();
184                          ++i) {
185                         if ((*i) == key) {
186                                 if (++i != _patch_list.end()) {
187                                         return  _patch_map[*i];
188                                 } else {
189                                         --i;
190                                 }
191                         }
192                 }
193                         
194                 return boost::shared_ptr<Patch>();
195         }
196
197         XMLNode& get_state (void);
198         int      set_state (const XMLTree&, const XMLNode&);
199
200         void set_patch_banks (const PatchBanks&);
201
202 private:
203         std::string _name;
204         AvailableForChannels _available_for_channels;
205         PatchBanks           _patch_banks;
206         PatchMap             _patch_map;
207         PatchList            _patch_list;
208         std::string          _patch_list_name;
209 };
210
211 class Note
212 {
213 public:
214         Note() {};
215         Note(std::string a_number, std::string a_name) : _number(a_number), _name(a_name) {};
216         ~Note() {};
217
218         const std::string& name() const               { return _name; }
219         void set_name(const std::string a_name)       { _name = a_name; }
220
221         const std::string& number() const             { return _number; }
222         void set_number(const std::string a_number)   { _number = a_number; }
223
224         XMLNode& get_state (void);
225         int      set_state (const XMLTree&, const XMLNode&);
226
227 private:
228         std::string _number;
229         std::string _name;
230 };
231
232 class NoteNameList 
233 {
234 public:
235         typedef std::list<boost::shared_ptr<Note> > Notes;
236         NoteNameList() {};
237         NoteNameList (std::string a_name) : _name(a_name) {};
238         ~NoteNameList() {};
239
240         const std::string& name() const          { return _name; }
241         void set_name(const std::string a_name)       { _name = a_name; }
242
243         const Notes& notes() const { return _notes; }
244
245         XMLNode& get_state (void);
246         int      set_state (const XMLTree&, const XMLNode&);
247
248 private:
249         std::string _name;
250         Notes  _notes;
251 };
252
253 class CustomDeviceMode
254 {
255 public:
256         CustomDeviceMode() {};
257         virtual ~CustomDeviceMode() {};
258
259         const std::string& name() const          { return _name; }
260         void set_name(const std::string a_name)  { _name = a_name; }
261
262         
263         XMLNode& get_state (void);
264         int      set_state (const XMLTree&, const XMLNode&);
265         
266         std::string channel_name_set_name_by_channel(uint8_t channel) {
267                 assert(channel <= 15);
268                 return _channel_name_set_assignments[channel]; 
269         }
270         
271 private:
272         /// array index = channel number
273         /// string contents = name of channel name set 
274         std::string _name;
275         std::string _channel_name_set_assignments[16];
276 };
277
278 class MasterDeviceNames
279 {
280 public:
281         typedef std::list<std::string>                                       Models;
282         /// maps name to CustomDeviceMode
283         typedef std::map<std::string, boost::shared_ptr<CustomDeviceMode> >  CustomDeviceModes;
284         typedef std::list<std::string>                                       CustomDeviceModeNames;
285         /// maps name to ChannelNameSet
286         typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> >    ChannelNameSets;
287         typedef std::list<boost::shared_ptr<NoteNameList> >                  NoteNameLists;
288         typedef std::map<std::string, PatchBank::PatchNameList>              PatchNameLists;
289         
290         MasterDeviceNames() {};
291         virtual ~MasterDeviceNames() {};
292         
293         const std::string& manufacturer() const { return _manufacturer; }
294         void set_manufacturer(const std::string a_manufacturer) { _manufacturer = a_manufacturer; }
295         
296         const Models& models() const { return _models; }
297         void set_models(const Models some_models) { _models = some_models; }
298         
299         const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
300         
301         boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(std::string mode_name) {
302                 assert(mode_name != "");
303                 return _custom_device_modes[mode_name];
304         }
305         
306         boost::shared_ptr<ChannelNameSet> channel_name_set_by_device_mode_and_channel(std::string mode, uint8_t channel) {
307                 return _channel_name_sets[custom_device_mode_by_name(mode)->channel_name_set_name_by_channel(channel)];
308         }
309         
310         boost::shared_ptr<Patch> find_patch(std::string mode, uint8_t channel, PatchPrimaryKey& key) {
311                 return channel_name_set_by_device_mode_and_channel(mode, channel)->find_patch(key);
312         }
313         
314         XMLNode& get_state (void);
315         int      set_state (const XMLTree&, const XMLNode&);
316         
317 private:
318         std::string           _manufacturer;
319         Models                _models;
320         CustomDeviceModes     _custom_device_modes;
321         CustomDeviceModeNames _custom_device_mode_names;
322         ChannelNameSets       _channel_name_sets;
323         NoteNameLists         _note_name_lists;
324         PatchNameLists        _patch_name_lists;
325 };
326
327 class MIDINameDocument
328 {
329 public:
330         // Maps Model names to MasterDeviceNames
331         typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
332         
333         MIDINameDocument() {}
334         MIDINameDocument(const std::string &filename);
335         virtual ~MIDINameDocument() {};
336
337         const std::string& author() const { return _author; }
338         void set_author(const std::string an_author) { _author = an_author; }
339         
340         const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; }
341         
342         const MasterDeviceNames::Models& all_models() const { return _all_models; }
343                 
344         XMLNode& get_state (void);
345         int      set_state (const XMLTree&, const XMLNode&);
346
347 private:
348         std::string                   _author;
349         MasterDeviceNamesList         _master_device_names_list;
350         XMLTree                       _document;
351         MasterDeviceNames::Models     _all_models;
352 };
353
354 extern const char* general_midi_program_names[128]; /* 0 .. 127 */
355
356 }
357
358 }
359 #endif /*MIDNAM_PATCH_H_*/