2 Copyright (C) 2000-2003 Paul Davis
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.
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.
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.
21 #include "libardour-config.h"
24 #define __STDC_FORMAT_MACROS 1
27 #include <cstdio> /* for sprintf */
34 #include <sys/types.h>
44 #include "pbd/error.h"
45 #include "pbd/stacktrace.h"
46 #include "pbd/xml++.h"
47 #include "pbd/basename.h"
48 #include "ardour/utils.h"
52 using namespace ARDOUR
;
58 legalize_for_path (ustring str
)
60 ustring::size_type pos
;
61 ustring legal_chars
= "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=: ";
67 while ((pos
= legal
.find_first_not_of (legal_chars
, pos
)) != string::npos
) {
68 legal
.replace (pos
, 1, "_");
75 string
bump_name_once(std::string name
)
77 string::size_type period
;
80 if ((period
= name
.find_last_of ('.')) == string::npos
) {
85 const char *last_element
= name
.c_str() + period
+ 1;
86 for (size_t i
= 0; i
< strlen(last_element
); i
++) {
87 if (!isdigit(last_element
[i
])) {
94 long int version
= strtol (name
.c_str()+period
+1, (char **)NULL
, 10);
96 if (isnumber
== 0 || errno
!= 0) {
97 // last_element is not a number, or is too large
103 snprintf (buf
, sizeof(buf
), "%ld", version
+1);
105 newname
= name
.substr (0, period
+1);
115 find_named_node (const XMLNode
& node
, string name
)
118 XMLNodeConstIterator niter
;
121 nlist
= node
.children();
123 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
127 if (child
->name() == name
) {
136 cmp_nocase (const string
& s
, const string
& s2
)
138 string::const_iterator p
= s
.begin();
139 string::const_iterator p2
= s2
.begin();
141 while (p
!= s
.end() && p2
!= s2
.end()) {
142 if (toupper(*p
) != toupper(*p2
)) {
143 return (toupper(*p
) < toupper(*p2
)) ? -1 : 1;
149 return (s2
.size() == s
.size()) ? 0 : (s
.size() < s2
.size()) ? -1 : 1;
153 touch_file (ustring path
)
155 int fd
= open (path
.c_str(), O_RDWR
|O_CREAT
, 0660);
164 region_name_from_path (ustring path
, bool strip_channels
, bool add_channel_suffix
, uint32_t total
, uint32_t this_one
)
166 path
= PBD::basename_nosuffix (path
);
168 if (strip_channels
) {
170 /* remove any "?R", "?L" or "?[a-z]" channel identifier */
172 ustring::size_type len
= path
.length();
174 if (len
> 3 && (path
[len
-2] == '%' || path
[len
-2] == '?' || path
[len
-2] == '.') &&
175 (path
[len
-1] == 'R' || path
[len
-1] == 'L' || (islower (path
[len
-1])))) {
177 path
= path
.substr (0, path
.length() - 2);
181 if (add_channel_suffix
) {
186 path
+= (char) ('a' + this_one
);
188 path
+= (char) (this_one
== 0 ? 'L' : 'R');
196 path_is_paired (ustring path
, ustring
& pair_base
)
198 ustring::size_type pos
;
200 /* remove any leading path */
202 if ((pos
= path
.find_last_of ('/')) != string::npos
) {
203 path
= path
.substr(pos
+1);
206 /* remove filename suffixes etc. */
208 if ((pos
= path
.find_last_of ('.')) != string::npos
) {
209 path
= path
.substr (0, pos
);
212 ustring::size_type len
= path
.length();
214 /* look for possible channel identifier: "?R", "%R", ".L" etc. */
216 if (len
> 3 && (path
[len
-2] == '%' || path
[len
-2] == '?' || path
[len
-2] == '.') &&
217 (path
[len
-1] == 'R' || path
[len
-1] == 'L' || (islower (path
[len
-1])))) {
219 pair_base
= path
.substr (0, len
-2);
228 path_expand (ustring path
)
231 /* Handle tilde and environment variable expansion in session path */
235 switch (wordexp (path
.c_str(), &expansion
, WRDE_NOCMD
|WRDE_UNDEF
)) {
239 error
<< string_compose (_("illegal or badly-formed string used for path (%1)"), path
) << endmsg
;
243 if (expansion
.we_wordc
> 1) {
244 error
<< string_compose (_("path (%1) is ambiguous"), path
) << endmsg
;
248 ret
= expansion
.we_wordv
[0];
250 wordfree (&expansion
);
258 #if defined(HAVE_COREAUDIO) || defined(HAVE_AUDIOUNITS)
260 CFStringRefToStdString(CFStringRef stringRef
)
263 CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef
) ,
264 kCFStringEncodingUTF8
);
265 char *buf
= new char[size
];
269 if(CFStringGetCString(stringRef
, buf
, size
, kCFStringEncodingUTF8
)) {
275 #endif // HAVE_COREAUDIO
278 compute_equal_power_fades (nframes_t nframes
, float* in
, float* out
)
282 step
= 1.0/(nframes
-1);
286 for (nframes_t i
= 1; i
< nframes
- 1; ++i
) {
287 in
[i
] = in
[i
-1] + step
;
292 const float pan_law_attenuation
= -3.0f
;
293 const float scale
= 2.0f
- 4.0f
* powf (10.0f
,pan_law_attenuation
/20.0f
);
295 for (nframes_t n
= 0; n
< nframes
; ++n
) {
297 float outVal
= 1 - inVal
;
298 out
[n
] = outVal
* (scale
* outVal
+ 1.0f
- scale
);
299 in
[n
] = inVal
* (scale
* inVal
+ 1.0f
- scale
);
304 string_to_edit_mode (string str
)
306 if (str
== _("Splice Edit")) {
308 } else if (str
== _("Slide Edit")) {
310 } else if (str
== _("Lock Edit")) {
313 fatal
<< string_compose (_("programming error: unknown edit mode string \"%1\""), str
) << endmsg
;
319 edit_mode_to_string (EditMode mode
)
323 return _("Slide Edit");
326 return _("Lock Edit");
330 return _("Splice Edit");
335 string_to_slave_source (string str
)
337 if (str
== _("Internal")) {
341 if (str
== _("MTC")) {
345 if (str
== _("MIDI Clock")) {
349 if (str
== _("JACK")) {
353 fatal
<< string_compose (_("programming error: unknown slave source string \"%1\""), str
) << endmsg
;
359 slave_source_to_string (SlaveSource src
)
369 return _("MIDI Clock");
373 return _("Internal");
379 meter_falloff_to_float (MeterFalloff falloff
)
382 case MeterFalloffOff
:
383 return METER_FALLOFF_OFF
;
384 case MeterFalloffSlowest
:
385 return METER_FALLOFF_SLOWEST
;
386 case MeterFalloffSlow
:
387 return METER_FALLOFF_SLOW
;
388 case MeterFalloffMedium
:
389 return METER_FALLOFF_MEDIUM
;
390 case MeterFalloffFast
:
391 return METER_FALLOFF_FAST
;
392 case MeterFalloffFaster
:
393 return METER_FALLOFF_FASTER
;
394 case MeterFalloffFastest
:
395 return METER_FALLOFF_FASTEST
;
397 return METER_FALLOFF_FAST
;
402 meter_falloff_from_float (float val
)
404 if (val
== METER_FALLOFF_OFF
) {
405 return MeterFalloffOff
;
407 else if (val
<= METER_FALLOFF_SLOWEST
) {
408 return MeterFalloffSlowest
;
410 else if (val
<= METER_FALLOFF_SLOW
) {
411 return MeterFalloffSlow
;
413 else if (val
<= METER_FALLOFF_MEDIUM
) {
414 return MeterFalloffMedium
;
416 else if (val
<= METER_FALLOFF_FAST
) {
417 return MeterFalloffFast
;
419 else if (val
<= METER_FALLOFF_FASTER
) {
420 return MeterFalloffFaster
;
423 return MeterFalloffFastest
;
428 ARDOUR::string_to_auto_state (std::string str
)
430 if (str
== X_("Off")) {
432 } else if (str
== X_("Play")) {
434 } else if (str
== X_("Write")) {
436 } else if (str
== X_("Touch")) {
440 fatal
<< string_compose (_("programming error: %1 %2"), "illegal AutoState string: ", str
) << endmsg
;
446 ARDOUR::auto_state_to_string (AutoState as
)
448 /* to be used only for XML serialization, no i18n done */
464 fatal
<< string_compose (_("programming error: %1 %2"), "illegal AutoState type: ", as
) << endmsg
;
470 ARDOUR::string_to_auto_style (std::string str
)
472 if (str
== X_("Absolute")) {
474 } else if (str
== X_("Trim")) {
478 fatal
<< string_compose (_("programming error: %1 %2"), "illegal AutoStyle string: ", str
) << endmsg
;
484 ARDOUR::auto_style_to_string (AutoStyle as
)
486 /* to be used only for XML serialization, no i18n done */
490 return X_("Absolute");
497 fatal
<< string_compose (_("programming error: %1 %2"), "illegal AutoStyle type: ", as
) << endmsg
;
503 bool_as_string (bool yn
)
505 return (yn
? "yes" : "no");
509 string_is_affirmative (const std::string
& str
)
511 /* to be used only with XML data - not intended to handle user input */
513 return str
== "1" || str
== "y" || str
== "Y" || (!g_strncasecmp(str
.c_str(), "yes", str
.length()));
517 void c_stacktrace() { stacktrace (cerr
); }