Merge remote-tracking branch 'origin/master' into export-dialog
[ardour.git] / libs / midi++2 / midi++ / midnam_patch.h
1 /*
2     Copyright (C) 2012 Paul Davis
3     Author: Hans Baier
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #ifndef MIDNAM_PATCH_H_
21 #define MIDNAM_PATCH_H_
22
23 #include <algorithm>
24 #include <iostream>
25 #include <string>
26 #include <list>
27 #include <set>
28 #include <map>
29 #include <vector>
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() const {  
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& name) { _name = name; }
93         
94         const std::string& note_list_name() const  { return _note_list_name; }
95
96         uint8_t program_number() const     { return _id.program_number; }
97         void set_program_number(uint8_t n) { _id.program_number = n; }
98
99         uint16_t bank_number() const      { return _id.bank_number; }
100         void set_bank_number (uint16_t n) { _id.bank_number = n; }
101
102         const PatchPrimaryKey&   patch_primary_key()   const { return _id; }
103
104         XMLNode& get_state (void);
105         int      set_state (const XMLTree&, const XMLNode&);
106
107 private:
108         std::string     _name;
109         PatchPrimaryKey _id;
110         std::string     _note_list_name;
111 };
112
113 typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
114
115 class PatchBank 
116 {
117 public:
118         PatchBank (uint16_t n = 0, std::string a_name = std::string()) : _name(a_name), _number (n) {};
119         virtual ~PatchBank() { }
120
121         const std::string& name() const          { return _name; }
122         void set_name(const std::string& a_name) { _name = a_name; }
123
124         int number() const { return _number; }
125
126         const PatchNameList& patch_name_list() const { return _patch_name_list; }
127         const std::string& patch_list_name() const { return _patch_list_name; }
128
129         int set_patch_name_list (const PatchNameList&);
130
131         XMLNode& get_state (void);
132         int      set_state (const XMLTree&, const XMLNode&);
133
134 private:
135         std::string       _name;
136         uint16_t          _number;
137         PatchNameList     _patch_name_list;
138         std::string       _patch_list_name;
139 };
140
141 class ChannelNameSet
142 {
143 public:
144         typedef std::set<uint8_t>                                    AvailableForChannels;
145         typedef std::list<boost::shared_ptr<PatchBank> >             PatchBanks;
146         typedef std::map<PatchPrimaryKey, boost::shared_ptr<Patch> > PatchMap;
147         typedef std::list<PatchPrimaryKey>                           PatchList;
148
149         ChannelNameSet() {};
150         virtual ~ChannelNameSet() {};
151         ChannelNameSet(std::string& name) : _name(name) {};
152
153         const std::string& name() const        { return _name; }
154         void set_name(const std::string& name) { _name = name; }
155         
156         const PatchBanks& patch_banks() const    { return _patch_banks; }
157
158         bool available_for_channel(uint8_t channel) const { 
159                 return _available_for_channels.find(channel) != _available_for_channels.end(); 
160         }
161         
162         boost::shared_ptr<Patch> find_patch(const PatchPrimaryKey& key) {
163                 assert(key.is_sane());
164                 return _patch_map[key];
165         }
166         
167         boost::shared_ptr<Patch> previous_patch(const PatchPrimaryKey& key) {
168                 assert(key.is_sane());
169                 for (PatchList::const_iterator i = _patch_list.begin();
170                          i != _patch_list.end();
171                          ++i) {
172                         if ((*i) == key) {
173                                 if (i != _patch_list.begin()) {
174                                         --i;
175                                         return  _patch_map[*i];
176                                 } 
177                         }
178                 }
179                         
180                 return boost::shared_ptr<Patch>();
181         }
182         
183         boost::shared_ptr<Patch> next_patch(const PatchPrimaryKey& key) {
184                 assert(key.is_sane());
185                 for (PatchList::const_iterator i = _patch_list.begin();
186                          i != _patch_list.end();
187                          ++i) {
188                         if ((*i) == key) {
189                                 if (++i != _patch_list.end()) {
190                                         return  _patch_map[*i];
191                                 } else {
192                                         --i;
193                                 }
194                         }
195                 }
196                         
197                 return boost::shared_ptr<Patch>();
198         }
199
200         const std::string& note_list_name()    const { return _note_list_name; }
201         const std::string& control_list_name() const { return _control_list_name; }
202
203         XMLNode& get_state (void);
204         int      set_state (const XMLTree&, const XMLNode&);
205
206         void set_patch_banks (const PatchBanks&);
207         void use_patch_name_list (const PatchNameList&);
208
209 private:
210         friend std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
211
212         std::string          _name;
213         AvailableForChannels _available_for_channels;
214         PatchBanks           _patch_banks;
215         PatchMap             _patch_map;
216         PatchList            _patch_list;
217         std::string          _patch_list_name;
218         std::string          _note_list_name;
219         std::string          _control_list_name;
220 };
221
222 std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
223
224 class Note
225 {
226 public:
227         Note() {}
228         Note(uint8_t number, const std::string& name) : _number(number), _name(name) {}
229
230         const std::string& name() const        { return _name; }
231         void set_name(const std::string& name) { _name = name; }
232
233         uint8_t number() const             { return _number; }
234         void    set_number(uint8_t number) { _number = number; }
235
236         XMLNode& get_state (void);
237         int      set_state (const XMLTree&, const XMLNode&);
238
239 private:
240         uint8_t     _number;
241         std::string _name;
242 };
243
244 class NoteNameList 
245 {
246 public:
247         typedef std::vector< boost::shared_ptr<Note> > Notes;
248
249         NoteNameList() { _notes.resize(128); }
250         NoteNameList (const std::string& name) : _name(name) { _notes.resize(128); }
251
252         const std::string& name() const  { return _name; }
253         const Notes&       notes() const { return _notes; }
254
255         void set_name(const std::string& name) { _name = name; }
256
257         XMLNode& get_state (void);
258         int      set_state (const XMLTree&, const XMLNode&);
259
260 private:
261         std::string _name;
262         Notes       _notes;
263 };
264
265 class Value
266 {
267 public:
268         Value() {}
269         Value(const uint16_t     number,
270               const std::string& name)
271                 : _number(number)
272                 , _name(name)
273         {}
274
275         uint16_t           number() const { return _number; }
276         const std::string& name()   const { return _name; }
277
278         void set_number(uint16_t number)       { _number = number; }
279         void set_name(const std::string& name) { _name = name; }
280
281         XMLNode& get_state(void);
282         int      set_state(const XMLTree&, const XMLNode&);
283
284 private:
285         uint16_t    _number;
286         std::string _name;
287 };
288
289 class ValueNameList
290 {
291 public:
292         typedef std::map<uint16_t, boost::shared_ptr<Value> > Values;
293
294         ValueNameList() {}
295         ValueNameList(const std::string& name) : _name(name) {}
296
297         const std::string& name() const { return _name; }
298
299         void set_name(const std::string& name) { _name = name; }
300
301         boost::shared_ptr<const Value> value(uint16_t num) const;
302         boost::shared_ptr<const Value> max_value_below(uint16_t num) const;
303
304         const Values& values() const { return _values; }
305
306         XMLNode& get_state(void);
307         int      set_state(const XMLTree&, const XMLNode&);
308
309 private:
310         std::string _name;
311         Values      _values;
312 };
313
314 class Control
315 {
316 public:
317         Control() {}
318         Control(const std::string& type,
319                 const uint16_t     number,
320                 const std::string& name)
321                 : _type(type)
322                 , _number(number)
323                 , _name(name)
324         {}
325
326         const std::string& type()   const { return _type; }
327         uint16_t           number() const { return _number; }
328         const std::string& name()   const { return _name; }
329
330         const std::string&                     value_name_list_name() const { return _value_name_list_name; }
331         boost::shared_ptr<const ValueNameList> value_name_list()      const { return _value_name_list; }
332
333         void set_type(const std::string& type) { _type = type; }
334         void set_number(uint16_t number)       { _number = number; }
335         void set_name(const std::string& name) { _name = name; }
336
337         XMLNode& get_state(void);
338         int      set_state(const XMLTree&, const XMLNode&);
339
340 private:
341         std::string _type;
342         uint16_t    _number;
343         std::string _name;
344
345         std::string                      _value_name_list_name;  ///< Global, UsesValueNameList
346         boost::shared_ptr<ValueNameList> _value_name_list;       ///< Local, ValueNameList
347 };
348
349 class ControlNameList 
350 {
351 public:
352         typedef std::map<uint16_t, boost::shared_ptr<Control> > Controls;
353
354         ControlNameList() {}
355         ControlNameList(const std::string& name) : _name(name) {}
356
357         const std::string& name() const { return _name; }
358
359         void set_name(const std::string& name) { _name = name; }
360
361         boost::shared_ptr<const Control> control(uint16_t num) const;
362
363         const Controls& controls() const { return _controls; }
364
365         XMLNode& get_state(void);
366         int      set_state(const XMLTree&, const XMLNode&);
367
368 private:
369         std::string _name;
370         Controls    _controls;
371 };
372
373 class CustomDeviceMode
374 {
375 public:
376         CustomDeviceMode() {};
377         virtual ~CustomDeviceMode() {};
378
379         const std::string& name() const        { return _name; }
380         void set_name(const std::string& name) { _name = name; }
381
382         
383         XMLNode& get_state (void);
384         int      set_state (const XMLTree&, const XMLNode&);
385         
386         /// Note: channel here is 0-based while in the MIDNAM-file it's 1-based
387         const std::string& channel_name_set_name_by_channel(uint8_t channel) {
388                 assert(channel <= 15);
389                 return _channel_name_set_assignments[channel]; 
390         }
391         
392 private:
393         /// array index = channel number
394         /// string contents = name of channel name set 
395         std::string _name;
396         std::string _channel_name_set_assignments[16];
397 };
398
399 class MasterDeviceNames
400 {
401 public:
402         typedef std::set<std::string>                                       Models;
403         /// maps name to CustomDeviceMode
404         typedef std::map<std::string, boost::shared_ptr<CustomDeviceMode> > CustomDeviceModes;
405         typedef std::list<std::string>                                      CustomDeviceModeNames;
406         /// maps name to ChannelNameSet
407         typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> >   ChannelNameSets;
408         typedef std::map<std::string, boost::shared_ptr<NoteNameList> >     NoteNameLists;
409         typedef std::map<std::string, boost::shared_ptr<ControlNameList> >  ControlNameLists;
410         typedef std::map<std::string, boost::shared_ptr<ValueNameList> >    ValueNameLists;
411         typedef std::map<std::string, PatchNameList>                        PatchNameLists;
412         
413         MasterDeviceNames() {};
414         virtual ~MasterDeviceNames() {};
415         
416         const std::string& manufacturer() const { return _manufacturer; }
417         void set_manufacturer(const std::string& manufacturer) { _manufacturer = manufacturer; }
418         
419         const Models& models() const { return _models; }
420         void set_models(const Models some_models) { _models = some_models; }
421
422         const ControlNameLists& controls() const { return _control_name_lists; }
423         const ValueNameLists&   values()   const { return _value_name_lists; }
424
425         boost::shared_ptr<const ValueNameList> value_name_list_by_control(
426                 const std::string& mode,
427                 uint8_t            channel,
428                 uint8_t            number);
429
430         const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
431         
432         boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(const std::string& mode_name);
433         boost::shared_ptr<ChannelNameSet> channel_name_set_by_channel(const std::string& mode, uint8_t channel);
434         boost::shared_ptr<Patch> find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key);
435
436         boost::shared_ptr<ControlNameList> control_name_list(const std::string& name);
437         boost::shared_ptr<ValueNameList>   value_name_list(const std::string& name);
438         boost::shared_ptr<NoteNameList>    note_name_list(const std::string& name);
439         boost::shared_ptr<ChannelNameSet>  channel_name_set(const std::string& name);
440
441         std::string note_name(const std::string& mode_name,
442                               uint8_t            channel,
443                               uint16_t           bank,
444                               uint8_t            program,
445                               uint8_t            number);
446
447         XMLNode& get_state (void);
448         int      set_state (const XMLTree&, const XMLNode&);
449         
450 private:
451         std::string           _manufacturer;
452         Models                _models;
453         CustomDeviceModes     _custom_device_modes;
454         CustomDeviceModeNames _custom_device_mode_names;
455         ChannelNameSets       _channel_name_sets;
456         NoteNameLists         _note_name_lists;
457         PatchNameLists        _patch_name_lists;
458         ControlNameLists      _control_name_lists;
459         ValueNameLists        _value_name_lists;
460 };
461
462 class MIDINameDocument
463 {
464 public:
465         // Maps Model names to MasterDeviceNames
466         typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
467         
468         MIDINameDocument() {}
469         MIDINameDocument(const std::string& filename);
470         virtual ~MIDINameDocument() {};
471
472         const std::string& author() const { return _author; }
473         void set_author(const std::string& author) { _author = author; }
474         
475         boost::shared_ptr<MasterDeviceNames> master_device_names(const std::string& model);
476
477         const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; }
478         
479         const MasterDeviceNames::Models& all_models() const { return _all_models; }
480                 
481         XMLNode& get_state (void);
482         int      set_state (const XMLTree&, const XMLNode&);
483
484 private:
485         std::string                   _author;
486         MasterDeviceNamesList         _master_device_names_list;
487         XMLTree                       _document;
488         MasterDeviceNames::Models     _all_models;
489 };
490
491 extern const char* general_midi_program_names[128]; /* 0 .. 127 */
492
493 }
494
495 }
496 #endif /*MIDNAM_PATCH_H_*/