internally, ControllableDescriptors (used by MIDI binding maps) should use enums...
[ardour.git] / libs / ardour / controllable_descriptor.cc
1 /*
2     Copyright (C) 2009 Paul Davis
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
19 #ifdef COMPILER_MSVC
20 #include <io.h> // Microsoft's nearest equivalent to <unistd.h>
21 #include <ardourext/misc.h>
22 #else
23 #include <regex.h>
24 #endif
25
26 #include "pbd/strsplit.h"
27 #include "pbd/convert.h"
28
29 #include "ardour/controllable_descriptor.h"
30
31 using namespace std;
32 using namespace PBD;
33 using namespace ARDOUR;
34
35 int
36 ControllableDescriptor::set (const std::string& str)
37 {
38         string::size_type first_space = str.find_first_of (" ");
39
40         if (first_space == string::npos) {
41                 return -1;
42         }
43
44         string front = str.substr (0, first_space);
45         string back = str.substr (first_space);
46
47         vector<string> path;
48         split (front, path, '/');
49
50         if (path.size() < 2) {
51                 return -1;
52         }
53
54         vector<string> rest;
55         split (back, rest, ' ');
56
57         if (rest.size() < 1) {
58                 return -1;
59         }
60
61         bool stripable = false;
62         regex_t compiled_pattern;
63         const char * const pattern = "^[BS]?[0-9]+";
64
65         if (path[0] == "route" || path[0] == "rid") {
66
67                 /* this is not going to fail */
68                 regcomp (&compiled_pattern, pattern, REG_EXTENDED|REG_NOSUB);
69                 bool matched = (regexec (&compiled_pattern, rest[0].c_str(), 0, 0, 0) == 0);
70                 regfree (&compiled_pattern);
71
72                 if (matched) {
73                         _top_level_type = PresentationOrderRoute;
74                         stripable = true;
75                 } else {
76                         _top_level_type = NamedRoute;
77                         _top_level_name = rest[0];
78                 }
79
80         } else if (path[0] == "vca") {
81                 _top_level_type = PresentationOrderVCA;
82                 stripable = true;
83         } else if (path[0] == "bus") {
84                 /* digits, or B<digits> or S<digits> will be used as for route;
85                    anything else will be treated as a track name.
86                 */
87
88                 /* this is not going to fail */
89
90                 regcomp (&compiled_pattern, pattern, REG_EXTENDED|REG_NOSUB);
91                 bool matched = (regexec (&compiled_pattern, rest[0].c_str(), 0, 0, 0) == 0);
92                 regfree (&compiled_pattern);
93
94                 if (matched) {
95                         _top_level_type = PresentationOrderBus;
96                         stripable = true;
97                 } else {
98                         _top_level_type = NamedRoute;
99                         _top_level_name = rest[0];
100                 }
101
102         } else if (path[0] == "track") {
103
104                 /* digits, or B<digits> or S<digits> will be used as for route;
105                    anything else will be treated as a track name.
106                 */
107
108                 /* this is not going to fail */
109                 regcomp (&compiled_pattern, pattern, REG_EXTENDED|REG_NOSUB);
110                 bool matched = (regexec (&compiled_pattern, rest[0].c_str(), 0, 0, 0) == 0);
111                 regfree (&compiled_pattern);
112
113                 if (matched) {
114                         _top_level_type = PresentationOrderTrack;
115                         stripable = true;
116                 } else {
117                         _top_level_type = NamedRoute;
118                         _top_level_name = rest[0];
119                 }
120         }
121
122         if (stripable) {
123                 if (rest[0][0] == 'B') {
124                         _banked = true;
125                         _presentation_order = atoi (rest[0].substr (1));
126                 } else if (rest[0][0] == 'S') {
127                         _top_level_type = SelectionCount;
128                         _banked = true;
129                         _selection_id = atoi (rest[0].substr (1));
130                 } else if (isdigit (rest[0][0])) {
131                         _banked = false;
132                         _presentation_order = atoi (rest[0]);
133                 } else {
134                         return -1;
135                 }
136
137                 _presentation_order -= 1; /* order is zero-based, but maps use 1-based */
138         }
139
140         if (path[1] == "gain") {
141                 _subtype = GainAutomation;
142
143         } else if (path[1] == "trim") {
144                 _subtype = TrimAutomation;
145
146         } else if (path[1] == "solo") {
147                 _subtype = SoloAutomation;
148
149         } else if (path[1] == "mute") {
150                 _subtype = MuteAutomation;
151
152         } else if (path[1] == "recenable") {
153                 _subtype = RecEnableAutomation;
154
155         } else if (path[1] == "panwidth") {
156                 _subtype = PanWidthAutomation;
157
158         } else if (path[1] == "pandirection" || path[1] == "balance") {
159                 _subtype = PanAzimuthAutomation;
160
161         } else if (path[1] == "plugin") {
162                 if (path.size() == 3 && rest.size() == 3) {
163                         if (path[2] == "parameter") {
164                                 _subtype = PluginAutomation;
165                                 _target.push_back (atoi (rest[1]));
166                                 _target.push_back (atoi (rest[2]));
167                         } else {
168                                 return -1;
169                         }
170                 } else {
171                         return -1;
172                 }
173         } else if (path[1] == "send") {
174
175                 if (path.size() == 3 && rest.size() == 2) {
176                         if (path[2] == "gain") {
177                                 _subtype = SendLevelAutomation;
178                                 _target.push_back (atoi (rest[1]));
179                         } else {
180                                 return -1;
181                         }
182                 } else {
183                         return -1;
184                 }
185         }
186
187         return 0;
188 }
189
190 uint32_t
191 ControllableDescriptor::presentation_order () const
192 {
193         if (banked()) {
194                 return _presentation_order + _bank_offset;
195         }
196
197         return _presentation_order;
198 }
199
200 uint32_t
201 ControllableDescriptor::selection_id () const
202 {
203         if (banked()) {
204                 return _selection_id + _bank_offset;
205         }
206
207         return _selection_id;
208 }
209
210 uint32_t
211 ControllableDescriptor::target (uint32_t n) const
212 {
213         if (n < _target.size()) {
214                 return _target[n];
215         }
216
217         return 0;
218 }