per-route OSC control of solo/mute/recenable/gain
[ardour.git] / libs / pbd / convert.cc
1 /*
2     Copyright (C) 2006 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
20 #include <cmath>
21 #include <locale>
22 #include <algorithm>
23 #include <stdint.h>
24 #ifndef __STDC_FORMAT_MACROS
25 #define __STDC_FORMAT_MACROS
26 #endif
27 #include <inttypes.h>
28
29 #include "pbd/convert.h"
30
31 #include "i18n.h"
32
33 using std::string;
34 using std::vector;
35 using Glib::ustring;
36
37 namespace PBD {
38
39 string
40 short_version (string orig, string::size_type target_length)
41 {
42         /* this tries to create a recognizable abbreviation
43            of "orig" by removing characters until we meet
44            a certain target length.
45
46            note that we deliberately leave digits in the result
47            without modification.
48         */
49
50
51         string::size_type pos;
52
53         /* remove white-space and punctuation, starting at end */
54
55         while (orig.length() > target_length) {
56                 if ((pos = orig.find_last_of (_("\"\n\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="))) == string::npos) {
57                         break;
58                 }
59                 orig.replace (pos, 1, "");
60         }
61
62         /* remove lower-case vowels, starting at end */
63
64         while (orig.length() > target_length) {
65                 if ((pos = orig.find_last_of (_("aeiou"))) == string::npos) {
66                         break;
67                 }
68                 orig.replace (pos, 1, "");
69         }
70
71         /* remove upper-case vowels, starting at end */
72
73         while (orig.length() > target_length) {
74                 if ((pos = orig.find_last_of (_("AEIOU"))) == string::npos) {
75                         break;
76                 }
77                 orig.replace (pos, 1, "");
78         }
79
80         /* remove lower-case consonants, starting at end */
81
82         while (orig.length() > target_length) {
83                 if ((pos = orig.find_last_of (_("bcdfghjklmnpqrtvwxyz"))) == string::npos) {
84                         break;
85                 }
86                 orig.replace (pos, 1, "");
87         }
88
89         /* remove upper-case consonants, starting at end */
90
91         while (orig.length() > target_length) {
92                 if ((pos = orig.find_last_of (_("BCDFGHJKLMNPQRTVWXYZ"))) == string::npos) {
93                         break;
94                 }
95                 orig.replace (pos, 1, "");
96         }
97
98         /* whatever the length is now, use it */
99         
100         return orig;
101 }
102
103 int
104 atoi (const string& s)
105 {
106         return std::atoi (s.c_str());
107 }
108
109 double
110 atof (const string& s)
111 {
112         return std::atof (s.c_str());
113 }
114
115 vector<string>
116 internationalize (const char *package_name, const char **array)
117 {
118         vector<string> v;
119
120         for (uint32_t i = 0; array[i]; ++i) {
121                 v.push_back (dgettext(package_name, array[i]));
122         }
123
124         return v;
125 }
126
127 static int32_t 
128 int_from_hex (char hic, char loc) 
129 {
130         int hi;         /* hi byte */
131         int lo;         /* low byte */
132
133         hi = (int) hic;
134
135         if( ('0'<=hi) && (hi<='9') ) {
136                 hi -= '0';
137         } else if( ('a'<= hi) && (hi<= 'f') ) {
138                 hi -= ('a'-10);
139         } else if( ('A'<=hi) && (hi<='F') ) {
140                 hi -= ('A'-10);
141         }
142         
143         lo = (int) loc;
144         
145         if( ('0'<=lo) && (lo<='9') ) {
146                 lo -= '0';
147         } else if( ('a'<=lo) && (lo<='f') ) {
148                 lo -= ('a'-10);
149         } else if( ('A'<=lo) && (lo<='F') ) {
150                 lo -= ('A'-10);
151         }
152
153         return lo + (16 * hi);
154 }
155
156 void
157 url_decode (string& url)
158 {
159         string::iterator last;
160         string::iterator next;
161
162         for (string::iterator i = url.begin(); i != url.end(); ++i) {
163                 if ((*i) == '+') {
164                         *i = ' ';
165                 }
166         }
167
168         if (url.length() <= 3) {
169                 return;
170         }
171
172         last = url.end();
173
174         --last; /* points at last char */
175         --last; /* points at last char - 1 */
176
177         for (string::iterator i = url.begin(); i != last; ) {
178
179                 if (*i == '%') {
180
181                         next = i;
182
183                         url.erase (i);
184                         
185                         i = next;
186                         ++next;
187                         
188                         if (isxdigit (*i) && isxdigit (*next)) {
189                                 /* replace first digit with char */
190                                 *i = int_from_hex (*i,*next);
191                                 ++i; /* points at 2nd of 2 digits */
192                                 url.erase (i);
193                         }
194                 } else {
195                         ++i;
196                 }
197         }
198 }
199
200 void
201 url_decode (ustring& url)
202 {
203         ustring::iterator last;
204         ustring::iterator next;
205
206         for (ustring::iterator i = url.begin(); i != url.end(); ++i) {
207                 if ((*i) == '+') {
208                         next = i;
209                         ++next;
210                         url.replace (i, next, 1, ' ');
211                 }
212         }
213
214         if (url.length() <= 3) {
215                 return;
216         }
217
218         last = url.end();
219
220         --last; /* points at last char */
221         --last; /* points at last char - 1 */
222
223         for (ustring::iterator i = url.begin(); i != last; ) {
224
225                 if (*i == '%') {
226
227                         next = i;
228
229                         url.erase (i);
230                         
231                         i = next;
232                         ++next;
233                         
234                         if (isxdigit (*i) && isxdigit (*next)) {
235                                 /* replace first digit with char */
236                                 url.replace (i, next, 1, (gunichar) int_from_hex (*i,*next));
237                                 ++i; /* points at 2nd of 2 digits */
238                                 url.erase (i);
239                         }
240                 } else {
241                         ++i;
242                 }
243         }
244 }
245
246 #if 0
247 string
248 length2string (const int32_t frames, const float sample_rate)
249 {
250     int32_t secs = (int32_t) (frames / sample_rate);
251     int32_t hrs =  secs / 3600;
252     secs -= (hrs * 3600);
253     int32_t mins = secs / 60;
254     secs -= (mins * 60);
255
256     int32_t total_secs = (hrs * 3600) + (mins * 60) + secs;
257     int32_t frames_remaining = (int) floor (frames - (total_secs * sample_rate));
258     float fractional_secs = (float) frames_remaining / sample_rate;
259
260     char duration_str[32];
261     sprintf (duration_str, "%02" PRIi32 ":%02" PRIi32 ":%05.2f", hrs, mins, (float) secs + fractional_secs);
262
263     return duration_str;
264 }
265 #endif
266
267 string
268 length2string (const int64_t frames, const double sample_rate)
269 {
270         int64_t secs = (int64_t) floor (frames / sample_rate);
271         int64_t hrs =  secs / 3600LL;
272         secs -= (hrs * 3600LL);
273         int64_t mins = secs / 60LL;
274         secs -= (mins * 60LL);
275         
276         int64_t total_secs = (hrs * 3600LL) + (mins * 60LL) + secs;
277         int64_t frames_remaining = (int64_t) floor (frames - (total_secs * sample_rate));
278         float fractional_secs = (float) frames_remaining / sample_rate;
279         
280         char duration_str[64];
281         sprintf (duration_str, "%02" PRIi64 ":%02" PRIi64 ":%05.2f", hrs, mins, (float) secs + fractional_secs);
282         
283         return duration_str;
284 }
285
286 static bool 
287 chars_equal_ignore_case(char x, char y)
288 {
289         static std::locale loc;
290         return toupper(x, loc) == toupper(y, loc);
291 }
292
293 bool 
294 strings_equal_ignore_case (const string& a, const string& b)
295 {
296         if (a.length() == b.length()) {
297                 return std::equal (a.begin(), a.end(), b.begin(), chars_equal_ignore_case);
298         }
299         return false;
300 }
301
302
303
304 } // namespace PBD