X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Futils.cc;h=e7b76481493155ffcbb7beb22aacc16b0b64505f;hb=6bcdf4f0f106d0b83ed7f221f546c132585e19e7;hp=9698486e9061eb4862b853350da8b1c9d15c999b;hpb=b85b4d9e54caef0585d308ef3bffee21d0e5ae56;p=ardour.git diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc index 9698486e90..e7b7648149 100644 --- a/libs/ardour/utils.cc +++ b/libs/ardour/utils.cc @@ -25,6 +25,8 @@ #include /* for sprintf */ #include +#include +#include #include #include #include @@ -36,20 +38,21 @@ #include #include #include +#include #include #include -#ifdef HAVE_WORDEXP -#include -#endif - +#include "pbd/cpus.h" #include "pbd/error.h" #include "pbd/stacktrace.h" #include "pbd/xml++.h" #include "pbd/basename.h" #include "pbd/strsplit.h" +#include "pbd/replace_all.h" + #include "ardour/utils.h" +#include "ardour/rc_configuration.h" #include "i18n.h" @@ -57,41 +60,99 @@ using namespace ARDOUR; using namespace std; using namespace PBD; -string -legalize_for_path (const string& str) +static string +replace_chars (const string& str, const string& illegal_chars) { -#if OLD_SCHOOL_PROHIBITIVE string::size_type pos; - string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=: "; - string legal; + Glib::ustring legal; + + /* this is the one place in Ardour where we need to iterate across + * potential multibyte characters, and thus we need Glib::ustring + */ legal = str; pos = 0; - while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) { + while ((pos = legal.find_first_of (illegal_chars, pos)) != string::npos) { legal.replace (pos, 1, "_"); pos += 1; } - return legal; -#else + return string (legal); +} +/** take an arbitrary string as an argument, and return a version of it + * suitable for use as a path (directory/folder name). This is the Ardour 3.X + * and later version of this code. It defines a very small number of characters + * that are not allowed in a path on the build target filesystem (basically, + * POSIX or Windows) and replaces any instances of them with an underscore. + * + * NOTE: this is intended only to legalize for the filesystem that Ardour + * is running on. Export should use legalize_for_universal_path() since + * the goal there is to be legal across filesystems. + */ +string +legalize_for_path (const string& str) +{ + return replace_chars (str, "/\\"); +} + +/** take an arbitrary string as an argument, and return a version of it + * suitable for use as a path (directory/folder name). This is the Ardour 3.X + * and later version of this code. It defines a small number + * of characters that are not allowed in a path on any of our target + * filesystems, and replaces any instances of them with an underscore. + * + * NOTE: this is intended to create paths that should be legal on + * ANY filesystem. + */ +string +legalize_for_universal_path (const string& str) +{ + return replace_chars (str, "<>:\"/\\|?*"); +} + +/** Legalize for a URI path component. This is like + * legalize_for_universal_path, but stricter, disallowing spaces and hash. + * This avoids %20 escapes in URIs, but probably needs work to be more strictly + * correct. + */ +string +legalize_for_uri (const string& str) +{ + return replace_chars (str, "<>:\"/\\|?* #"); +} + +/** take an arbitrary string as an argument, and return a version of it + * suitable for use as a path (directory/folder name). This is the Ardour 2.X + * version of this code, which used an approach that came to be seen as + * problematic: defining the characters that were allowed and replacing all + * others with underscores. See legalize_for_path() for the 3.X and later + * version. + */ + +string +legalize_for_path_2X (const string& str) +{ string::size_type pos; - string illegal_chars = "/\\"; /* DOS, POSIX. Yes, we're going to ignore HFS */ - string legal; + string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=: "; + Glib::ustring legal; + + /* this is the one place in Ardour where we need to iterate across + * potential multibyte characters, and thus we need Glib::ustring + */ legal = str; pos = 0; - while ((pos = legal.find_first_of (illegal_chars, pos)) != string::npos) { + while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) { legal.replace (pos, 1, "_"); pos += 1; } - return legal; -#endif + return string (legal); } -string +string bump_name_once (const std::string& name, char delimiter) { string::size_type delim; @@ -133,46 +194,6 @@ bump_name_once (const std::string& name, char delimiter) } -bool -could_be_a_valid_path (const string& path) -{ - vector posix_dirs; - vector dos_dirs; - string testpath; - - split (path, posix_dirs, '/'); - split (path, dos_dirs, '\\'); - - /* remove the last component of each */ - - posix_dirs.erase (--posix_dirs.end()); - dos_dirs.erase (--dos_dirs.end()); - - if (G_DIR_SEPARATOR == '/') { - for (vector::iterator x = posix_dirs.begin(); x != posix_dirs.end(); ++x) { - testpath = Glib::build_filename (testpath, *x); - cerr << "Testing " << testpath << endl; - if (!Glib::file_test (testpath, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) { - return false; - } - } - } - - if (G_DIR_SEPARATOR == '\\') { - testpath = ""; - for (vector::iterator x = dos_dirs.begin(); x != dos_dirs.end(); ++x) { - testpath = Glib::build_filename (testpath, *x); - cerr << "Testing " << testpath << endl; - if (!Glib::file_test (testpath, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) { - return false; - } - } - } - - return true; -} - - XMLNode * find_named_node (const XMLNode& node, string name) { @@ -286,41 +307,6 @@ path_is_paired (string path, string& pair_base) return false; } -string -path_expand (string path) -{ - if (path.empty()) { - return path; - } - -#ifdef HAVE_WORDEXP - /* Handle tilde and environment variable expansion in session path */ - string ret = path; - - wordexp_t expansion; - switch (wordexp (path.c_str(), &expansion, WRDE_NOCMD|WRDE_UNDEF)) { - case 0: - break; - default: - error << string_compose (_("illegal or badly-formed string used for path (%1)"), path) << endmsg; - goto out; - } - - if (expansion.we_wordc > 1) { - error << string_compose (_("path (%1) is ambiguous"), path) << endmsg; - goto out; - } - - ret = expansion.we_wordv[0]; - out: - wordfree (&expansion); - return ret; - -#else - return path; -#endif -} - #if __APPLE__ string CFStringRefToStdString(CFStringRef stringRef) @@ -341,7 +327,7 @@ CFStringRefToStdString(CFStringRef stringRef) #endif // __APPLE__ void -compute_equal_power_fades (nframes_t nframes, float* in, float* out) +compute_equal_power_fades (framecnt_t nframes, float* in, float* out) { double step; @@ -349,7 +335,7 @@ compute_equal_power_fades (nframes_t nframes, float* in, float* out) in[0] = 0.0f; - for (nframes_t i = 1; i < nframes - 1; ++i) { + for (framecnt_t i = 1; i < nframes - 1; ++i) { in[i] = in[i-1] + step; } @@ -358,7 +344,7 @@ compute_equal_power_fades (nframes_t nframes, float* in, float* out) const float pan_law_attenuation = -3.0f; const float scale = 2.0f - 4.0f * powf (10.0f,pan_law_attenuation/20.0f); - for (nframes_t n = 0; n < nframes; ++n) { + for (framecnt_t n = 0; n < nframes; ++n) { float inVal = in[n]; float outVal = 1 - inVal; out[n] = outVal * (scale * outVal + 1.0f - scale); @@ -400,7 +386,7 @@ edit_mode_to_string (EditMode mode) SyncSource string_to_sync_source (string str) { - if (str == _("MIDI Timecode")) { + if (str == _("MIDI Timecode") || str == _("MTC")) { return MTC; } @@ -417,18 +403,30 @@ string_to_sync_source (string str) return JACK; } +/** @param sh Return a short version of the string */ const char* -sync_source_to_string (SyncSource src) +sync_source_to_string (SyncSource src, bool sh) { switch (src) { case JACK: return _("JACK"); case MTC: - return _("MIDI Timecode"); + if (sh) { + return _("MTC"); + } else { + return _("MIDI Timecode"); + } case MIDIClock: - return _("MIDI Clock"); + if (sh) { + return _("M-Clock"); + } else { + return _("MIDI Clock"); + } + + case LTC: + return _("LTC"); } /* GRRRR .... stupid, stupid gcc - you can't get here from there, all enum values are handled */ return _("JACK"); @@ -444,8 +442,12 @@ meter_falloff_to_float (MeterFalloff falloff) return METER_FALLOFF_SLOWEST; case MeterFalloffSlow: return METER_FALLOFF_SLOW; + case MeterFalloffSlowish: + return METER_FALLOFF_SLOWISH; case MeterFalloffMedium: return METER_FALLOFF_MEDIUM; + case MeterFalloffModerate: + return METER_FALLOFF_MODERATE; case MeterFalloffFast: return METER_FALLOFF_FAST; case MeterFalloffFaster: @@ -469,6 +471,12 @@ meter_falloff_from_float (float val) else if (val <= METER_FALLOFF_SLOW) { return MeterFalloffSlow; } + else if (val <= METER_FALLOFF_SLOWISH) { + return MeterFalloffSlowish; + } + else if (val <= METER_FALLOFF_MODERATE) { + return MeterFalloffModerate; + } else if (val <= METER_FALLOFF_MEDIUM) { return MeterFalloffMedium; } @@ -564,21 +572,13 @@ bool_as_string (bool yn) return (yn ? "yes" : "no"); } -bool -string_is_affirmative (const std::string& str) -{ - /* to be used only with XML data - not intended to handle user input */ - - return str == "1" || str == "y" || str == "Y" || (!g_strncasecmp(str.c_str(), "yes", str.length())); -} - const char* native_header_format_extension (HeaderFormat hf, const DataType& type) { if (type == DataType::MIDI) { return ".mid"; } - + switch (hf) { case BWF: return ".wav"; @@ -614,28 +614,28 @@ matching_unsuffixed_filename_exists_in (const string& dir, const string& path) error << string_compose (_("cannot open directory %1 (%2)"), dir, strerror (errno)) << endl; return false; } - + while ((dentry = ::readdir (dead)) != 0) { - + /* avoid '.' and '..' */ - + if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') || (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) { continue; } - + string fullpath = Glib::build_filename (dir, dentry->d_name); if (::stat (fullpath.c_str(), &statbuf)) { continue; } - + if (!S_ISREG (statbuf.st_mode)) { continue; } string bws2 = basename_nosuffix (dentry->d_name); - + if (bws2 == bws) { ret = true; break; @@ -646,6 +646,50 @@ matching_unsuffixed_filename_exists_in (const string& dir, const string& path) return ret; } +uint32_t +how_many_dsp_threads () +{ + /* CALLER MUST HOLD PROCESS LOCK */ + + int num_cpu = hardware_concurrency(); + int pu = Config->get_processor_usage (); + uint32_t num_threads = max (num_cpu - 1, 2); // default to number of cpus minus one, or 2, whichever is larger + + if (pu < 0) { + /* pu is negative: use "pu" less cores for DSP than appear to be available + */ + + if (-pu < num_cpu) { + num_threads = num_cpu + pu; + } + + } else if (pu == 0) { + + /* use all available CPUs + */ + + num_threads = num_cpu; + + } else { + /* use "pu" cores, if available + */ + + num_threads = min (num_cpu, pu); + } + + return num_threads; +} + +double gain_to_slider_position_with_max (double g, double max_gain) +{ + return gain_to_slider_position (g * 2.0/max_gain); +} + +double slider_position_to_gain_with_max (double g, double max_gain) +{ + return slider_position_to_gain (g * max_gain/2.0); +} + extern "C" { void c_stacktrace() { stacktrace (cerr); } }