| 
							- /*
 -  * Common Carla code
 -  * Copyright (C) 2011-2019 Filipe Coelho <falktx@falktx.com>
 -  *
 -  * This program is free software; you can redistribute it and/or
 -  * modify it under the terms of the GNU General Public License as
 -  * published by the Free Software Foundation; either version 2 of
 -  * the License, or any later version.
 -  *
 -  * This program is distributed in the hope that it will be useful,
 -  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 -  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 -  * GNU General Public License for more details.
 -  *
 -  * For a full copy of the GNU General Public License see the doc/GPL.txt file.
 -  */
 - 
 - #include "carla_shared.hpp"
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Imports (Global)
 - 
 - #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
 - # pragma GCC diagnostic push
 - # pragma GCC diagnostic ignored "-Wconversion"
 - # pragma GCC diagnostic ignored "-Weffc++"
 - # pragma GCC diagnostic ignored "-Wsign-conversion"
 - #endif
 - 
 - #include <QtGui/QFontMetrics>
 - 
 - #include <QtWidgets/QFileDialog>
 - #include <QtWidgets/QGridLayout>
 - #include <QtWidgets/QLineEdit>
 - 
 - #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
 - # pragma GCC diagnostic pop
 - #endif
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - 
 - #ifdef CARLA_OS_UNIX
 - # include <signal.h>
 - #endif
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Imports (Custom)
 - 
 - #include "carla_host.hpp"
 - 
 - #include "CarlaUtils.h"
 - #include "CarlaMathUtils.hpp"
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Global Carla object
 - 
 - CarlaObject::CarlaObject() noexcept
 -     : host(nullptr),
 -       gui(nullptr),
 -       nogui(false),
 -       term(false) {}
 - 
 - CarlaObject gCarla;
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Get Icon from user theme, using our own as backup (Oxygen)
 - 
 - QIcon getIcon(const QString icon, const int size)
 - {
 -     return QIcon::fromTheme(icon, QIcon(QString(":/%1x%1/%2.png").arg(size).arg(icon)));
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Handle some basic command-line arguments shared between all carla variants
 - 
 - QString handleInitialCommandLineArguments(const int argc, char* argv[])
 - {
 -     static const QStringList listArgsNoGUI   = { "-n", "--n", "-no-gui", "--no-gui", "-nogui", "--nogui" };
 -     static const QStringList listArgsHelp    = { "-h", "--h", "-help", "--help" };
 -     static const QStringList listArgsVersion = { "-v", "--v", "-version", "--version" };
 - 
 -     QString initName(argv[0]); // = os.path.basename(file) if (file is not None and os.path.dirname(file) in PATH) else sys.argv[0]
 -     // libPrefix = None
 - 
 -     for (int i=1; i<argc; ++i)
 -     {
 -         const QString arg(argv[i]);
 - 
 -         if (arg.startsWith("--with-appname="))
 -         {
 -             // initName = os.path.basename(arg.replace("--with-appname=", ""));
 -         }
 -         else if (arg.startsWith("--with-libprefix=") || arg == "--gdb")
 -         {
 -             pass();
 -         }
 -         else if (listArgsNoGUI.contains(arg))
 -         {
 -             gCarla.nogui = true;
 -         }
 -         else if (listArgsHelp.contains(arg))
 -         {
 -             carla_stdout("Usage: %s [OPTION]... [FILE|URL]", initName);
 -             carla_stdout("");
 -             carla_stdout(" where FILE can be a Carla project or preset file to be loaded, or URL if using Carla-Control");
 -             carla_stdout("");
 -             carla_stdout(" and OPTION can be one or more of the following:");
 -             carla_stdout("");
 -             carla_stdout("    --gdb    \t Run Carla inside gdb.");
 -             carla_stdout(" -n,--no-gui \t Run Carla headless, don't show UI.");
 -             carla_stdout("");
 -             carla_stdout(" -h,--help   \t Print this help text and exit.");
 -             carla_stdout(" -v,--version\t Print version information and exit.");
 -             carla_stdout("");
 - 
 -             std::exit(0);
 -         }
 -         else if (listArgsVersion.contains(arg))
 -         {
 -             /*
 -             QString pathBinaries, pathResources = getPaths();
 -             */
 - 
 -             carla_stdout("Using Carla version %s", CARLA_VERSION_STRING);
 -             /*
 -             carla_stdout("  Qt version:     %s", QT_VERSION_STR);
 -             carla_stdout("  Binary dir:     %s", pathBinaries.toUtf8());
 -             carla_stdout("  Resources dir:  %s", pathResources.toUtf8());
 -             */
 - 
 -             std::exit(0);
 -         }
 -     }
 - 
 -     return initName;
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Get initial project file (as passed in the command-line parameters)
 - 
 - QString getInitialProjectFile(bool)
 - {
 -     // TODO
 -     return "";
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Get paths (binaries, resources)
 - 
 - bool getPaths(QString& pathBinaries, QString& pathResources)
 - {
 -     const QString libFolder(carla_get_library_folder());
 - 
 -     QDir dir(libFolder);
 - 
 -     // FIXME need to completely rework this in C++ mode, so check if all cases are valid
 - 
 -     if (libFolder.endsWith("bin"))
 -     {
 -         CARLA_SAFE_ASSERT_RETURN(dir.cd("resources"), false);
 -         pathBinaries  = libFolder;
 -         pathResources = dir.absolutePath();
 -         return true;
 -     }
 -     else if (libFolder.endsWith("carla"))
 -     {
 -         for (int i=2; --i>=0;)
 -         {
 -             CARLA_SAFE_ASSERT_INT_RETURN(dir.cdUp(), i, false);
 -             CARLA_SAFE_ASSERT_INT_RETURN(dir.cd("share"), i, false);
 - 
 -             if (dir.exists())
 -             {
 -                 CARLA_SAFE_ASSERT_INT_RETURN(dir.cd("carla"), i, false);
 -                 CARLA_SAFE_ASSERT_INT_RETURN(dir.cd("resources"), i, false);
 -                 pathBinaries  = libFolder;
 -                 pathResources = dir.absolutePath();
 -                 return true;
 -             }
 -         }
 -     }
 - 
 -     return false;
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Signal handler
 - 
 - static void signalHandler(const int sig)
 - {
 -     switch (sig)
 -     {
 -     case SIGINT:
 -     case SIGTERM:
 -         gCarla.term = true;
 -         if (gCarla.host != nullptr)
 -             emit gCarla.host->SignalTerminate();
 -         break;
 -     case SIGUSR1:
 -         if (gCarla.host != nullptr)
 -             emit gCarla.host->SignalSave();
 -         break;
 -     }
 - }
 - 
 - #ifdef CARLA_OS_WIN
 - static BOOL WINAPI winSignalHandler(DWORD dwCtrlType) noexcept
 - {
 -     if (dwCtrlType == CTRL_C_EVENT)
 -     {
 -         signalHandler(SIGINT);
 -         return TRUE;
 -     }
 -     return FALSE;
 - }
 - #endif
 - 
 - void setUpSignals()
 - {
 - #if defined(CARLA_OS_UNIX)
 -     struct sigaction sig;
 -     carla_zeroStruct(sig);
 -     sig.sa_handler = signalHandler;
 -     sig.sa_flags   = SA_RESTART;
 -     sigemptyset(&sig.sa_mask);
 -     sigaction(SIGTERM, &sig, nullptr);
 -     sigaction(SIGINT, &sig, nullptr);
 -     sigaction(SIGUSR1, &sig, nullptr);
 - #elif defined(CARLA_OS_WIN)
 -     SetConsoleCtrlHandler(winSignalHandler, TRUE);
 - #endif
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // QLineEdit and QPushButton combo
 - 
 - QString getAndSetPath(QWidget* const parent, QLineEdit* const lineEdit)
 - {
 -     const QCarlaString newPath = QFileDialog::getExistingDirectory(parent, parent->tr("Set Path"), lineEdit->text(), QFileDialog::ShowDirsOnly);
 -     if (newPath.isNotEmpty())
 -         lineEdit->setText(newPath);
 -     return newPath;
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // fill up a qlists from a C arrays
 - 
 - void fillQStringListFromStringArray(QStringList& list, const char* const* const stringArray)
 - {
 -     int count = 0;
 - 
 -     // count number of strings first
 -     for (; stringArray[count] != nullptr; ++count) {}
 - 
 -     // allocate list
 -     list.reserve(count);
 - 
 -     // fill in strings
 -     for (count = 0; stringArray[count] != nullptr; ++count)
 -         list.append(stringArray[count]);
 - }
 - 
 - void fillQDoubleListFromDoubleArray(QList<double>& list, const double* const doubleArray)
 - {
 -     int count = 0;
 - 
 -     // count number of strings first
 -     for (; carla_isNotZero(doubleArray[count]); ++count) {}
 - 
 -     // allocate list
 -     list.reserve(count);
 - 
 -     // fill in strings
 -     for (count = 0; carla_isNotZero(doubleArray[count]); ++count)
 -         list.append(doubleArray[count]);
 - }
 - 
 - void fillQUIntListFromUIntArray(QList<uint>& list, const uint* const uintArray)
 - {
 -     int count = 0;
 - 
 -     // count number of strings first
 -     for (; uintArray[count] != 0; ++count) {}
 - 
 -     // allocate list
 -     list.reserve(count);
 - 
 -     // fill in strings
 -     for (count = 0; uintArray[count] != 0; ++count)
 -         list.append(uintArray[count]);
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Backwards-compatible horizontalAdvance/width call, depending on Qt version
 - 
 - int fontMetricsHorizontalAdvance(const QFontMetrics& fm, const QString& s)
 - {
 - #if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
 -     return fm.horizontalAdvance(s);
 - #else
 -     return fm.width(s);
 - #endif
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Check if a string array contains a string
 - 
 - bool stringArrayContainsString(const char* const* const stringArray, const char* const string) noexcept
 - {
 -     for (uint i=0; stringArray[i] != nullptr; ++i)
 -     {
 -         if (std::strcmp(stringArray[i], string) == 0)
 -             return true;
 -     }
 - 
 -     return false;
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Get index of a QList<double> value
 - 
 - int getIndexOfQDoubleListValue(const QList<double>& list, const double value)
 - {
 -     if (list.size() > 0)
 -     {
 -         for (QList<double>::const_iterator n = list.cbegin(), e = list.cend(); n != e; ++n)
 -             if (carla_isEqual(*n, value))
 -                 return int(n - list.cbegin());
 -     }
 - 
 -     return -1;
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Check if two QList<double> instances match
 - 
 - bool isQDoubleListEqual(const QList<double>& list1, const QList<double>& list2)
 - {
 -     if (list1.size() != list2.size())
 -         return false;
 -     if (list1.isEmpty())
 -         return true;
 - 
 -     for (QList<double>::const_iterator l1n = list1.cbegin(), l2n = list2.cbegin(), l1e = list1.cend(); l1n != l1e; ++l1n, ++l2n)
 -         if (carla_isNotEqual(*l1n, *l2n))
 -             return false;
 - 
 -     return true;
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Custom QMessageBox which resizes itself to fit text
 - 
 - void QMessageBoxWithBetterWidth::showEvent(QShowEvent* const event)
 - {
 -     const QFontMetrics metrics(fontMetrics());
 -     const QStringList lines(text().trimmed().split("\n") + informativeText().trimmed().split("\n"));
 - 
 -     if (lines.size() > 0)
 -     {
 -         int width = 0;
 - 
 -         for (const QString& line : lines)
 -             width = std::max(fontMetricsHorizontalAdvance(metrics, line), width);
 - 
 -         if (QGridLayout* const layout_ = dynamic_cast<QGridLayout*>(layout()))
 -             layout_->setColumnMinimumWidth(2, width + 12);
 -     }
 - 
 -     QMessageBox::showEvent(event);
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Safer QSettings class, which does not throw if type mismatches
 - 
 - bool QSafeSettings::valueBool(const QString key, const bool defaultValue) const
 - {
 -     QVariant var(value(key, defaultValue));
 - 
 -     if (var.isNull())
 -         return defaultValue;
 - 
 -     CARLA_SAFE_ASSERT_RETURN(var.convert(QVariant::Bool), defaultValue);
 - 
 -     return var.isValid() ? var.toBool() : defaultValue;
 - }
 - 
 - Qt::CheckState QSafeSettings::valueCheckState(const QString key, const Qt::CheckState defaultValue) const
 - {
 -     QVariant var(value(key, defaultValue));
 - 
 -     if (var.isNull())
 -         return defaultValue;
 - 
 -     CARLA_SAFE_ASSERT_RETURN(var.convert(QVariant::UInt), defaultValue);
 - 
 -     if (! var.isValid())
 -         return defaultValue;
 - 
 -     const uint value = var.toUInt();
 - 
 -     switch (value)
 -     {
 -     case Qt::Unchecked:
 -     case Qt::PartiallyChecked:
 -     case Qt::Checked:
 -         return static_cast<Qt::CheckState>(value);
 -     default:
 -         return defaultValue;
 -     }
 - }
 - 
 - int QSafeSettings::valueIntPositive(const QString key, const int defaultValue) const
 - {
 -     CARLA_SAFE_ASSERT_INT(defaultValue >= 0, defaultValue);
 - 
 -     QVariant var(value(key, defaultValue));
 - 
 -     if (var.isNull())
 -         return defaultValue;
 - 
 -     CARLA_SAFE_ASSERT_RETURN(var.convert(QVariant::Int), defaultValue);
 -     CARLA_SAFE_ASSERT_RETURN(var.isValid(), defaultValue);
 - 
 -     const int value = var.toInt();
 -     CARLA_SAFE_ASSERT_RETURN(value >= 0, defaultValue);
 - 
 -     return value;
 - }
 - 
 - uint QSafeSettings::valueUInt(const QString key, const uint defaultValue) const
 - {
 -     QVariant var(value(key, defaultValue));
 - 
 -     if (var.isNull())
 -         return defaultValue;
 - 
 -     CARLA_SAFE_ASSERT_RETURN(var.convert(QVariant::UInt), defaultValue);
 - 
 -     return var.isValid() ? var.toUInt() : defaultValue;
 - }
 - 
 - double QSafeSettings::valueDouble(const QString key, const double defaultValue) const
 - {
 -     QVariant var(value(key, defaultValue));
 - 
 -     if (var.isNull())
 -         return defaultValue;
 - 
 -     CARLA_SAFE_ASSERT_RETURN(var.convert(QVariant::Double), defaultValue);
 - 
 -     return var.isValid() ? var.toDouble() : defaultValue;
 - }
 - 
 - QString QSafeSettings::valueString(const QString key, const QString defaultValue) const
 - {
 -     QVariant var(value(key, defaultValue));
 - 
 -     if (var.isNull())
 -         return defaultValue;
 - 
 -     CARLA_SAFE_ASSERT_RETURN(var.convert(QVariant::String), defaultValue);
 - 
 -     return var.isValid() ? var.toString() : defaultValue;
 - }
 - 
 - QByteArray QSafeSettings::valueByteArray(const QString key, const QByteArray defaultValue) const
 - {
 -     QVariant var(value(key, defaultValue));
 - 
 -     if (var.isNull())
 -         return defaultValue;
 - 
 -     CARLA_SAFE_ASSERT_RETURN(var.convert(QVariant::ByteArray), defaultValue);
 - 
 -     return var.isValid() ? var.toByteArray() : defaultValue;
 - }
 - 
 - QStringList QSafeSettings::valueStringList(const QString key, const QStringList defaultValue) const
 - {
 -     QVariant var(value(key, defaultValue));
 - 
 -     if (var.isNull())
 -         return defaultValue;
 - 
 -     CARLA_SAFE_ASSERT_RETURN(var.convert(QVariant::StringList), defaultValue);
 - 
 -     return var.isValid() ? var.toStringList() : defaultValue;
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 - // Custom MessageBox
 - 
 - int CustomMessageBox(QWidget* const parent,
 -                      const QMessageBox::Icon icon,
 -                      const QString title,
 -                      const QString text,
 -                      const QString extraText,
 -                      const QMessageBox::StandardButtons buttons,
 -                      const QMessageBox::StandardButton defButton)
 - {
 -     QMessageBoxWithBetterWidth msgBox(parent);
 -     msgBox.setIcon(icon);
 -     msgBox.setWindowTitle(title);
 -     msgBox.setText(text);
 -     msgBox.setInformativeText(extraText);
 -     msgBox.setStandardButtons(buttons);
 -     msgBox.setDefaultButton(defButton);
 -     return msgBox.exec();
 - }
 - 
 - //---------------------------------------------------------------------------------------------------------------------
 
 
  |