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>
41 #include <glibmm/miscutils.h>
47 #include "pbd/error.h"
48 #include "pbd/stacktrace.h"
49 #include "pbd/xml++.h"
50 #include "pbd/basename.h"
51 #include "ardour/utils.h"
55 using namespace ARDOUR
;
61 legalize_for_path (ustring str
)
63 ustring::size_type pos
;
64 ustring legal_chars
= "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=: ";
70 while ((pos
= legal
.find_first_not_of (legal_chars
, pos
)) != string::npos
) {
71 legal
.replace (pos
, 1, "_");
79 bump_name_once (const std::string
& name
, char delimiter
)
81 string::size_type delim
;
84 if ((delim
= name
.find_last_of (delimiter
)) == string::npos
) {
90 const char *last_element
= name
.c_str() + delim
+ 1;
91 for (size_t i
= 0; i
< strlen(last_element
); i
++) {
92 if (!isdigit(last_element
[i
])) {
99 int32_t version
= strtol (name
.c_str()+delim
+1, (char **)NULL
, 10);
101 if (isnumber
== 0 || errno
!= 0) {
102 // last_element is not a number, or is too large
104 newname
+= delimiter
;
109 snprintf (buf
, sizeof(buf
), "%d", version
+1);
111 newname
= name
.substr (0, delim
+1);
121 find_named_node (const XMLNode
& node
, string name
)
124 XMLNodeConstIterator niter
;
127 nlist
= node
.children();
129 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
133 if (child
->name() == name
) {
142 cmp_nocase (const string
& s
, const string
& s2
)
144 string::const_iterator p
= s
.begin();
145 string::const_iterator p2
= s2
.begin();
147 while (p
!= s
.end() && p2
!= s2
.end()) {
148 if (toupper(*p
) != toupper(*p2
)) {
149 return (toupper(*p
) < toupper(*p2
)) ? -1 : 1;
155 return (s2
.size() == s
.size()) ? 0 : (s
.size() < s2
.size()) ? -1 : 1;
159 touch_file (ustring path
)
161 int fd
= open (path
.c_str(), O_RDWR
|O_CREAT
, 0660);
170 region_name_from_path (ustring path
, bool strip_channels
, bool add_channel_suffix
, uint32_t total
, uint32_t this_one
)
172 path
= PBD::basename_nosuffix (path
);
174 if (strip_channels
) {
176 /* remove any "?R", "?L" or "?[a-z]" channel identifier */
178 ustring::size_type len
= path
.length();
180 if (len
> 3 && (path
[len
-2] == '%' || path
[len
-2] == '?' || path
[len
-2] == '.') &&
181 (path
[len
-1] == 'R' || path
[len
-1] == 'L' || (islower (path
[len
-1])))) {
183 path
= path
.substr (0, path
.length() - 2);
187 if (add_channel_suffix
) {
192 path
+= (char) ('a' + this_one
);
194 path
+= (char) (this_one
== 0 ? 'L' : 'R');
202 path_is_paired (ustring path
, ustring
& pair_base
)
204 ustring::size_type pos
;
206 /* remove any leading path */
208 if ((pos
= path
.find_last_of ('/')) != string::npos
) {
209 path
= path
.substr(pos
+1);
212 /* remove filename suffixes etc. */
214 if ((pos
= path
.find_last_of ('.')) != string::npos
) {
215 path
= path
.substr (0, pos
);
218 ustring::size_type len
= path
.length();
220 /* look for possible channel identifier: "?R", "%R", ".L" etc. */
222 if (len
> 3 && (path
[len
-2] == '%' || path
[len
-2] == '?' || path
[len
-2] == '.') &&
223 (path
[len
-1] == 'R' || path
[len
-1] == 'L' || (islower (path
[len
-1])))) {
225 pair_base
= path
.substr (0, len
-2);
234 path_expand (ustring path
)
237 /* Handle tilde and environment variable expansion in session path */
241 switch (wordexp (path
.c_str(), &expansion
, WRDE_NOCMD
|WRDE_UNDEF
)) {
245 error
<< string_compose (_("illegal or badly-formed string used for path (%1)"), path
) << endmsg
;
249 if (expansion
.we_wordc
> 1) {
250 error
<< string_compose (_("path (%1) is ambiguous"), path
) << endmsg
;
254 ret
= expansion
.we_wordv
[0];
256 wordfree (&expansion
);
264 #if defined(HAVE_COREAUDIO) || defined(HAVE_AUDIOUNITS)
266 CFStringRefToStdString(CFStringRef stringRef
)
269 CFStringGetMaximumSizeForEncoding(CFStringGetLength(stringRef
) ,
270 kCFStringEncodingUTF8
);
271 char *buf
= new char[size
];
275 if(CFStringGetCString(stringRef
, buf
, size
, kCFStringEncodingUTF8
)) {
281 #endif // HAVE_COREAUDIO
284 compute_equal_power_fades (nframes_t nframes
, float* in
, float* out
)
288 step
= 1.0/(nframes
-1);
292 for (nframes_t i
= 1; i
< nframes
- 1; ++i
) {
293 in
[i
] = in
[i
-1] + step
;
298 const float pan_law_attenuation
= -3.0f
;
299 const float scale
= 2.0f
- 4.0f
* powf (10.0f
,pan_law_attenuation
/20.0f
);
301 for (nframes_t n
= 0; n
< nframes
; ++n
) {
303 float outVal
= 1 - inVal
;
304 out
[n
] = outVal
* (scale
* outVal
+ 1.0f
- scale
);
305 in
[n
] = inVal
* (scale
* inVal
+ 1.0f
- scale
);
310 string_to_edit_mode (string str
)
312 if (str
== _("Splice Edit")) {
314 } else if (str
== _("Slide Edit")) {
316 } else if (str
== _("Lock Edit")) {
319 fatal
<< string_compose (_("programming error: unknown edit mode string \"%1\""), str
) << endmsg
;
325 edit_mode_to_string (EditMode mode
)
329 return _("Slide Edit");
332 return _("Lock Edit");
336 return _("Splice Edit");
341 string_to_sync_source (string str
)
343 if (str
== _("MIDI Timecode")) {
347 if (str
== _("MIDI Clock")) {
351 if (str
== _("JACK")) {
355 fatal
<< string_compose (_("programming error: unknown sync source string \"%1\""), str
) << endmsg
;
361 sync_source_to_string (SyncSource src
)
368 return _("MIDI Timecode");
371 return _("MIDI Clock");
373 /* GRRRR .... stupid, stupid gcc - you can't get here from there, all enum values are handled */
378 meter_falloff_to_float (MeterFalloff falloff
)
381 case MeterFalloffOff
:
382 return METER_FALLOFF_OFF
;
383 case MeterFalloffSlowest
:
384 return METER_FALLOFF_SLOWEST
;
385 case MeterFalloffSlow
:
386 return METER_FALLOFF_SLOW
;
387 case MeterFalloffMedium
:
388 return METER_FALLOFF_MEDIUM
;
389 case MeterFalloffFast
:
390 return METER_FALLOFF_FAST
;
391 case MeterFalloffFaster
:
392 return METER_FALLOFF_FASTER
;
393 case MeterFalloffFastest
:
394 return METER_FALLOFF_FASTEST
;
396 return METER_FALLOFF_FAST
;
401 meter_falloff_from_float (float val
)
403 if (val
== METER_FALLOFF_OFF
) {
404 return MeterFalloffOff
;
406 else if (val
<= METER_FALLOFF_SLOWEST
) {
407 return MeterFalloffSlowest
;
409 else if (val
<= METER_FALLOFF_SLOW
) {
410 return MeterFalloffSlow
;
412 else if (val
<= METER_FALLOFF_MEDIUM
) {
413 return MeterFalloffMedium
;
415 else if (val
<= METER_FALLOFF_FAST
) {
416 return MeterFalloffFast
;
418 else if (val
<= METER_FALLOFF_FASTER
) {
419 return MeterFalloffFaster
;
422 return MeterFalloffFastest
;
427 ARDOUR::string_to_auto_state (std::string str
)
429 if (str
== X_("Off")) {
431 } else if (str
== X_("Play")) {
433 } else if (str
== X_("Write")) {
435 } else if (str
== X_("Touch")) {
439 fatal
<< string_compose (_("programming error: %1 %2"), "illegal AutoState string: ", str
) << endmsg
;
445 ARDOUR::auto_state_to_string (AutoState as
)
447 /* to be used only for XML serialization, no i18n done */
463 fatal
<< string_compose (_("programming error: %1 %2"), "illegal AutoState type: ", as
) << endmsg
;
469 ARDOUR::string_to_auto_style (std::string str
)
471 if (str
== X_("Absolute")) {
473 } else if (str
== X_("Trim")) {
477 fatal
<< string_compose (_("programming error: %1 %2"), "illegal AutoStyle string: ", str
) << endmsg
;
483 ARDOUR::auto_style_to_string (AutoStyle as
)
485 /* to be used only for XML serialization, no i18n done */
489 return X_("Absolute");
496 fatal
<< string_compose (_("programming error: %1 %2"), "illegal AutoStyle type: ", as
) << endmsg
;
502 bool_as_string (bool yn
)
504 return (yn
? "yes" : "no");
508 string_is_affirmative (const std::string
& str
)
510 /* to be used only with XML data - not intended to handle user input */
512 return str
== "1" || str
== "y" || str
== "Y" || (!g_strncasecmp(str
.c_str(), "yes", str
.length()));
516 native_header_format_extension (HeaderFormat hf
, const DataType
& type
)
518 if (type
== DataType::MIDI
) {
539 fatal
<< string_compose (_("programming error: unknown native header format: %1"), hf
);
545 matching_unsuffixed_filename_exists_in (const string
& dir
, const string
& path
)
547 string bws
= basename_nosuffix (path
);
548 struct dirent
* dentry
;
553 if ((dead
= ::opendir (dir
.c_str())) == 0) {
554 error
<< string_compose (_("cannot open directory %1 (%2)"), dir
, strerror (errno
)) << endl
;
558 while ((dentry
= ::readdir (dead
)) != 0) {
560 /* avoid '.' and '..' */
562 if ((dentry
->d_name
[0] == '.' && dentry
->d_name
[1] == '\0') ||
563 (dentry
->d_name
[2] == '\0' && dentry
->d_name
[0] == '.' && dentry
->d_name
[1] == '.')) {
567 string fullpath
= Glib::build_filename (dir
, dentry
->d_name
);
569 if (::stat (fullpath
.c_str(), &statbuf
)) {
573 if (!S_ISREG (statbuf
.st_mode
)) {
577 string bws2
= basename_nosuffix (dentry
->d_name
);
590 void c_stacktrace() { stacktrace (cerr
); }