Add support for USE_CAIRO_IMAGE_SURFACE when building with MSVC
[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++/libmidi_visibility.h"
34 #include "midi++/event.h"
35 #include "pbd/xml++.h"
36
37 namespace MIDI
38 {
39
40 namespace Name
41 {
42
43 struct LIBMIDIPP_API PatchPrimaryKey
44 {
45 public:
46         int bank_number;
47         int program_number;
48
49         PatchPrimaryKey (uint8_t a_program_number = 0, uint16_t a_bank_number = 0) {
50                 bank_number = std::min (a_bank_number, (uint16_t) 16384);
51                 program_number = std::min (a_program_number, (uint8_t) 127);
52         }
53         
54         bool is_sane() const {  
55                 return ((bank_number >= 0) && (bank_number <= 16384) && 
56                         (program_number >=0 ) && (program_number <= 127));
57         }
58         
59         inline PatchPrimaryKey& operator=(const PatchPrimaryKey& id) {
60                 bank_number = id.bank_number;
61                 program_number = id.program_number;
62                 return *this;
63         }
64         
65         inline bool operator==(const PatchPrimaryKey& id) const {
66                 return (bank_number == id.bank_number && 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 (bank_number < id.bank_number) {
74                         return true;
75                 } else if (bank_number == id.bank_number && program_number < id.program_number) {
76                         return true;
77                 }
78                 
79                 return false;
80         }
81 };
82
83 class PatchBank;
84         
85 class LIBMIDIPP_API Patch 
86 {
87 public:
88
89         Patch (std::string a_name = std::string(), uint8_t a_number = 0, uint16_t bank_number = 0);
90         virtual ~Patch() {};
91
92         const std::string& name() const        { return _name; }
93         void set_name(const std::string& name) { _name = name; }
94         
95         const std::string& note_list_name() const  { return _note_list_name; }
96
97         uint8_t program_number() const     { return _id.program_number; }
98         void set_program_number(uint8_t n) { _id.program_number = n; }
99
100         uint16_t bank_number() const      { return _id.bank_number; }
101         void set_bank_number (uint16_t n) { _id.bank_number = n; }
102
103         const PatchPrimaryKey&   patch_primary_key()   const { return _id; }
104
105         XMLNode& get_state (void);
106         int      set_state (const XMLTree&, const XMLNode&);
107
108 private:
109         std::string     _name;
110         PatchPrimaryKey _id;
111         std::string     _note_list_name;
112 };
113
114 typedef std::list<boost::shared_ptr<Patch> > PatchNameList;
115
116 class LIBMIDIPP_API PatchBank 
117 {
118 public:
119         PatchBank (uint16_t n = 0, std::string a_name = std::string()) : _name(a_name), _number (n) {};
120         virtual ~PatchBank() { }
121
122         const std::string& name() const          { return _name; }
123         void set_name(const std::string& a_name) { _name = a_name; }
124
125         int number() const { return _number; }
126
127         const PatchNameList& patch_name_list() const { return _patch_name_list; }
128         const std::string& patch_list_name() const { return _patch_list_name; }
129
130         int set_patch_name_list (const PatchNameList&);
131
132         XMLNode& get_state (void);
133         int      set_state (const XMLTree&, const XMLNode&);
134
135 private:
136         std::string       _name;
137         uint16_t          _number;
138         PatchNameList     _patch_name_list;
139         std::string       _patch_list_name;
140 };
141
142 class LIBMIDIPP_API ChannelNameSet
143 {
144 public:
145         typedef std::set<uint8_t>                                    AvailableForChannels;
146         typedef std::list<boost::shared_ptr<PatchBank> >             PatchBanks;
147         typedef std::map<PatchPrimaryKey, boost::shared_ptr<Patch> > PatchMap;
148         typedef std::list<PatchPrimaryKey>                           PatchList;
149
150         ChannelNameSet() {};
151         virtual ~ChannelNameSet() {};
152         ChannelNameSet(std::string& name) : _name(name) {};
153
154         const std::string& name() const        { return _name; }
155         void set_name(const std::string& name) { _name = name; }
156         
157         const PatchBanks& patch_banks() const    { return _patch_banks; }
158
159         bool available_for_channel(uint8_t channel) const { 
160                 return _available_for_channels.find(channel) != _available_for_channels.end(); 
161         }
162         
163         boost::shared_ptr<Patch> find_patch(const PatchPrimaryKey& key) {
164                 assert(key.is_sane());
165                 return _patch_map[key];
166         }
167         
168         boost::shared_ptr<Patch> previous_patch(const PatchPrimaryKey& key) {
169                 assert(key.is_sane());
170                 for (PatchList::const_iterator i = _patch_list.begin();
171                          i != _patch_list.end();
172                          ++i) {
173                         if ((*i) == key) {
174                                 if (i != _patch_list.begin()) {
175                                         --i;
176                                         return  _patch_map[*i];
177                                 } 
178                         }
179                 }
180                         
181                 return boost::shared_ptr<Patch>();
182         }
183         
184         boost::shared_ptr<Patch> next_patch(const PatchPrimaryKey& key) {
185                 assert(key.is_sane());
186                 for (PatchList::const_iterator i = _patch_list.begin();
187                          i != _patch_list.end();
188                          ++i) {
189                         if ((*i) == key) {
190                                 if (++i != _patch_list.end()) {
191                                         return  _patch_map[*i];
192                                 } else {
193                                         --i;
194                                 }
195                         }
196                 }
197                         
198                 return boost::shared_ptr<Patch>();
199         }
200
201         const std::string& note_list_name()    const { return _note_list_name; }
202         const std::string& control_list_name() const { return _control_list_name; }
203
204         XMLNode& get_state (void);
205         int      set_state (const XMLTree&, const XMLNode&);
206
207         void set_patch_banks (const PatchBanks&);
208         void use_patch_name_list (const PatchNameList&);
209
210 private:
211         friend std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
212
213         std::string          _name;
214         AvailableForChannels _available_for_channels;
215         PatchBanks           _patch_banks;
216         PatchMap             _patch_map;
217         PatchList            _patch_list;
218         std::string          _patch_list_name;
219         std::string          _note_list_name;
220         std::string          _control_list_name;
221 };
222
223 std::ostream& operator<< (std::ostream&, const ChannelNameSet&);
224
225 class LIBMIDIPP_API Note
226 {
227 public:
228         Note() {}
229         Note(uint8_t number, const std::string& name) : _number(number), _name(name) {}
230
231         const std::string& name() const        { return _name; }
232         void set_name(const std::string& name) { _name = name; }
233
234         uint8_t number() const             { return _number; }
235         void    set_number(uint8_t number) { _number = number; }
236
237         XMLNode& get_state (void);
238         int      set_state (const XMLTree&, const XMLNode&);
239
240 private:
241         uint8_t     _number;
242         std::string _name;
243 };
244
245 class LIBMIDIPP_API NoteNameList 
246 {
247 public:
248         typedef std::vector< boost::shared_ptr<Note> > Notes;
249
250         NoteNameList() { _notes.resize(128); }
251         NoteNameList (const std::string& name) : _name(name) { _notes.resize(128); }
252
253         const std::string& name() const  { return _name; }
254         const Notes&       notes() const { return _notes; }
255
256         void set_name(const std::string& name) { _name = name; }
257
258         XMLNode& get_state (void);
259         int      set_state (const XMLTree&, const XMLNode&);
260
261 private:
262         std::string _name;
263         Notes       _notes;
264 };
265
266 class LIBMIDIPP_API Value
267 {
268 public:
269         Value() {}
270         Value(const uint16_t     number,
271               const std::string& name)
272                 : _number(number)
273                 , _name(name)
274         {}
275
276         uint16_t           number() const { return _number; }
277         const std::string& name()   const { return _name; }
278
279         void set_number(uint16_t number)       { _number = number; }
280         void set_name(const std::string& name) { _name = name; }
281
282         XMLNode& get_state(void);
283         int      set_state(const XMLTree&, const XMLNode&);
284
285 private:
286         uint16_t    _number;
287         std::string _name;
288 };
289
290 class LIBMIDIPP_API ValueNameList
291 {
292 public:
293         typedef std::map<uint16_t, boost::shared_ptr<Value> > Values;
294
295         ValueNameList() {}
296         ValueNameList(const std::string& name) : _name(name) {}
297
298         const std::string& name() const { return _name; }
299
300         void set_name(const std::string& name) { _name = name; }
301
302         boost::shared_ptr<const Value> value(uint16_t num) const;
303         boost::shared_ptr<const Value> max_value_below(uint16_t num) const;
304
305         const Values& values() const { return _values; }
306
307         XMLNode& get_state(void);
308         int      set_state(const XMLTree&, const XMLNode&);
309
310 private:
311         std::string _name;
312         Values      _values;
313 };
314
315 class LIBMIDIPP_API Control
316 {
317 public:
318         Control() {}
319         Control(const std::string& type,
320                 const uint16_t     number,
321                 const std::string& name)
322                 : _type(type)
323                 , _number(number)
324                 , _name(name)
325         {}
326
327         const std::string& type()   const { return _type; }
328         uint16_t           number() const { return _number; }
329         const std::string& name()   const { return _name; }
330
331         const std::string&                     value_name_list_name() const { return _value_name_list_name; }
332         boost::shared_ptr<const ValueNameList> value_name_list()      const { return _value_name_list; }
333
334         void set_type(const std::string& type) { _type = type; }
335         void set_number(uint16_t number)       { _number = number; }
336         void set_name(const std::string& name) { _name = name; }
337
338         XMLNode& get_state(void);
339         int      set_state(const XMLTree&, const XMLNode&);
340
341 private:
342         std::string _type;
343         uint16_t    _number;
344         std::string _name;
345
346         std::string                      _value_name_list_name;  ///< Global, UsesValueNameList
347         boost::shared_ptr<ValueNameList> _value_name_list;       ///< Local, ValueNameList
348 };
349
350 class LIBMIDIPP_API ControlNameList 
351 {
352 public:
353         typedef std::map<uint16_t, boost::shared_ptr<Control> > Controls;
354
355         ControlNameList() {}
356         ControlNameList(const std::string& name) : _name(name) {}
357
358         const std::string& name() const { return _name; }
359
360         void set_name(const std::string& name) { _name = name; }
361
362         boost::shared_ptr<const Control> control(uint16_t num) const;
363
364         const Controls& controls() const { return _controls; }
365
366         XMLNode& get_state(void);
367         int      set_state(const XMLTree&, const XMLNode&);
368
369 private:
370         std::string _name;
371         Controls    _controls;
372 };
373
374 class LIBMIDIPP_API CustomDeviceMode
375 {
376 public:
377         CustomDeviceMode() {};
378         virtual ~CustomDeviceMode() {};
379
380         const std::string& name() const        { return _name; }
381         void set_name(const std::string& name) { _name = name; }
382
383         
384         XMLNode& get_state (void);
385         int      set_state (const XMLTree&, const XMLNode&);
386         
387         /// Note: channel here is 0-based while in the MIDNAM-file it's 1-based
388         const std::string& channel_name_set_name_by_channel(uint8_t channel) {
389                 assert(channel <= 15);
390                 return _channel_name_set_assignments[channel]; 
391         }
392         
393 private:
394         /// array index = channel number
395         /// string contents = name of channel name set 
396         std::string _name;
397         std::string _channel_name_set_assignments[16];
398 };
399
400 class LIBMIDIPP_API MasterDeviceNames
401 {
402 public:
403         typedef std::set<std::string>                                       Models;
404         /// maps name to CustomDeviceMode
405         typedef std::map<std::string, boost::shared_ptr<CustomDeviceMode> > CustomDeviceModes;
406         typedef std::list<std::string>                                      CustomDeviceModeNames;
407         /// maps name to ChannelNameSet
408         typedef std::map<std::string, boost::shared_ptr<ChannelNameSet> >   ChannelNameSets;
409         typedef std::map<std::string, boost::shared_ptr<NoteNameList> >     NoteNameLists;
410         typedef std::map<std::string, boost::shared_ptr<ControlNameList> >  ControlNameLists;
411         typedef std::map<std::string, boost::shared_ptr<ValueNameList> >    ValueNameLists;
412         typedef std::map<std::string, PatchNameList>                        PatchNameLists;
413         
414         MasterDeviceNames() {};
415         virtual ~MasterDeviceNames() {};
416         
417         const std::string& manufacturer() const { return _manufacturer; }
418         void set_manufacturer(const std::string& manufacturer) { _manufacturer = manufacturer; }
419         
420         const Models& models() const { return _models; }
421         void set_models(const Models some_models) { _models = some_models; }
422
423         const ControlNameLists& controls() const { return _control_name_lists; }
424         const ValueNameLists&   values()   const { return _value_name_lists; }
425
426         boost::shared_ptr<const ValueNameList> value_name_list_by_control(
427                 const std::string& mode,
428                 uint8_t            channel,
429                 uint8_t            number);
430
431         const CustomDeviceModeNames& custom_device_mode_names() const { return _custom_device_mode_names; }
432         
433         boost::shared_ptr<CustomDeviceMode> custom_device_mode_by_name(const std::string& mode_name);
434         boost::shared_ptr<ChannelNameSet> channel_name_set_by_channel(const std::string& mode, uint8_t channel);
435         boost::shared_ptr<Patch> find_patch(const std::string& mode, uint8_t channel, const PatchPrimaryKey& key);
436
437         boost::shared_ptr<ControlNameList> control_name_list(const std::string& name);
438         boost::shared_ptr<ValueNameList>   value_name_list(const std::string& name);
439         boost::shared_ptr<NoteNameList>    note_name_list(const std::string& name);
440         boost::shared_ptr<ChannelNameSet>  channel_name_set(const std::string& name);
441
442         std::string note_name(const std::string& mode_name,
443                               uint8_t            channel,
444                               uint16_t           bank,
445                               uint8_t            program,
446                               uint8_t            number);
447
448         XMLNode& get_state (void);
449         int      set_state (const XMLTree&, const XMLNode&);
450         
451 private:
452         std::string           _manufacturer;
453         Models                _models;
454         CustomDeviceModes     _custom_device_modes;
455         CustomDeviceModeNames _custom_device_mode_names;
456         ChannelNameSets       _channel_name_sets;
457         NoteNameLists         _note_name_lists;
458         PatchNameLists        _patch_name_lists;
459         ControlNameLists      _control_name_lists;
460         ValueNameLists        _value_name_lists;
461 };
462
463 class LIBMIDIPP_API MIDINameDocument
464 {
465 public:
466         // Maps Model names to MasterDeviceNames
467         typedef std::map<std::string, boost::shared_ptr<MasterDeviceNames> > MasterDeviceNamesList;
468         
469         MIDINameDocument() {}
470         MIDINameDocument(const std::string& filename);
471         virtual ~MIDINameDocument() {};
472
473         const std::string& author() const { return _author; }
474         void set_author(const std::string& author) { _author = author; }
475         
476         boost::shared_ptr<MasterDeviceNames> master_device_names(const std::string& model);
477
478         const MasterDeviceNamesList& master_device_names_by_model() const { return _master_device_names_list; }
479         
480         const MasterDeviceNames::Models& all_models() const { return _all_models; }
481                 
482         XMLNode& get_state (void);
483         int      set_state (const XMLTree&, const XMLNode&);
484
485 private:
486         std::string                   _author;
487         MasterDeviceNamesList         _master_device_names_list;
488         MasterDeviceNames::Models     _all_models;
489 };
490
491 LIBMIDIPP_API extern const char* general_midi_program_names[128]; /* 0 .. 127 */
492
493 }
494
495 }
496 #endif /*MIDNAM_PATCH_H_*/