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