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