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