|
- /*
- * Carla plugin host
- * Copyright (C) 2011-2023 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 "jackappdialog.hpp"
-
- #ifdef __clang__
- # pragma clang diagnostic push
- # pragma clang diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy"
- # pragma clang diagnostic ignored "-Wdeprecated-register"
- #elif defined(__GNUC__) && __GNUC__ >= 8
- # pragma GCC diagnostic push
- # pragma GCC diagnostic ignored "-Wclass-memaccess"
- # pragma GCC diagnostic ignored "-Wdeprecated-copy"
- #endif
-
- #include "ui_jackappdialog.h"
- #include <QtCore/QFileInfo>
- #include <QtCore/QVector>
- #include <QtWidgets/QPushButton>
-
- #ifdef __clang__
- # pragma clang diagnostic pop
- #elif defined(__GNUC__) && __GNUC__ >= 8
- # pragma GCC diagnostic pop
- #endif
-
- #include "qsafesettings.hpp"
-
- #include "CarlaFrontend.h"
- #include "CarlaLibJackHints.h"
- #include "CarlaString.hpp"
-
- // --------------------------------------------------------------------------------------------------------------------
- // Jack Application Dialog
-
- enum {
- UI_SESSION_NONE = 0,
- UI_SESSION_LADISH = 1,
- UI_SESSION_NSM = 2,
- };
-
- struct JackAppDialog::Self {
- Ui_JackAppDialog ui;
- const QString fProjectFilename;
-
- Self(const char* const projectFilename)
- : fProjectFilename(projectFilename) {}
-
- static Self& create(const char* const projectFilename)
- {
- Self* const self = new Self(projectFilename);
- return *self;
- }
- };
-
- JackAppDialog::JackAppDialog(QWidget* const parent, const char* const projectFilename)
- : QDialog(parent),
- self(Self::create(projectFilename))
- {
- self.ui.setupUi(this);
-
- // -------------------------------------------------------------------------------------------------------------
- // UI setup
-
- self.ui.group_error->setVisible(false);
-
- adjustSize();
- setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
-
- #ifdef CARLA_OS_MAC
- if (parent != nullptr)
- setWindowModality(Qt::WindowModal);
- #endif
-
- // -------------------------------------------------------------------------------------------------------------
- // Load settings
-
- loadSettings();
-
- // -------------------------------------------------------------------------------------------------------------
- // Set-up connections
-
- connect(this, &QDialog::finished,
- this, &JackAppDialog::slot_saveSettings);
- connect(self.ui.cb_session_mgr, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &JackAppDialog::slot_sessionManagerChanged);
- connect(self.ui.le_command, &QLineEdit::textChanged,
- this, &JackAppDialog::slot_commandChanged);
- }
-
- JackAppDialog::~JackAppDialog()
- {
- delete &self;
- }
-
- // -----------------------------------------------------------------------------------------------------------------
- // public methods
-
- JackAppDialog::CommandAndFlags JackAppDialog::getCommandAndFlags() const
- {
- const QString command = self.ui.le_command->text();
- QString name = self.ui.le_name->text();
-
- if (name.isEmpty())
- {
- name = QFileInfo(command.split(' ').first()).baseName();
- name[0] = name[0].toTitleCase();
- }
-
- SessionManager smgr;
- switch (self.ui.cb_session_mgr->currentIndex())
- {
- case UI_SESSION_LADISH:
- smgr = LIBJACK_SESSION_MANAGER_LADISH;
- break;
- case UI_SESSION_NSM:
- smgr = LIBJACK_SESSION_MANAGER_NSM;
- break;
- default:
- smgr = LIBJACK_SESSION_MANAGER_NONE;
- break;
- }
-
- uint flags = 0x0;
- if (self.ui.cb_manage_window->isChecked())
- flags |= LIBJACK_FLAG_CONTROL_WINDOW;
- if (self.ui.cb_capture_first_window->isChecked())
- flags |= LIBJACK_FLAG_CAPTURE_FIRST_WINDOW;
- if (self.ui.cb_buffers_addition_mode->isChecked())
- flags |= LIBJACK_FLAG_AUDIO_BUFFERS_ADDITION;
- if (self.ui.cb_out_midi_mixdown->isChecked())
- flags |= LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN;
- if (self.ui.cb_external_start->isChecked())
- flags |= LIBJACK_FLAG_EXTERNAL_START;
-
- const QString labelSetup(QString("%1%2%3%4%5%6").arg(QChar('0' + self.ui.sb_audio_ins->value()))
- .arg(QChar('0' + self.ui.sb_audio_outs->value()))
- .arg(QChar('0' + self.ui.sb_midi_ins->value()))
- .arg(QChar('0' + self.ui.sb_midi_outs->value()))
- .arg(QChar('0' + smgr))
- .arg(QChar('0' + flags)));
-
- return {command, name, labelSetup};
- }
-
- // -----------------------------------------------------------------------------------------------------------------
- // private methods
-
- void JackAppDialog::checkIfButtonBoxShouldBeEnabled(const int index, const QCarlaString& command)
- {
- bool enabled = command.isNotEmpty();
- QCarlaString showErr;
-
- // NSM applications must not be abstract or absolute paths, and must not contain arguments
- if (enabled and index == UI_SESSION_NSM)
- {
- if (QVector<QChar>{'.', '/'}.contains(command[0]))
- showErr = tr("NSM applications cannot use abstract or absolute paths");
- else if (command.contains(' ') or command.contains(';') or command.contains('&'))
- showErr = tr("NSM applications cannot use CLI arguments");
- else if (self.fProjectFilename.isEmpty())
- showErr = tr("You need to save the current Carla project before NSM can be used");
- }
-
- if (showErr.isNotEmpty())
- {
- enabled = false;
- self.ui.l_error->setText(showErr);
- self.ui.group_error->setVisible(true);
- }
- else
- {
- self.ui.group_error->setVisible(false);
- }
-
- if (QPushButton* const button = self.ui.buttonBox->button(QDialogButtonBox::Ok))
- button->setEnabled(enabled);
- }
-
- void JackAppDialog::loadSettings()
- {
- const QSafeSettings settings("falkTX", "CarlaAddJackApp");
-
- const QString smName = settings.valueString("SessionManager", "");
-
- if (smName == "LADISH (SIGUSR1)")
- self.ui.cb_session_mgr->setCurrentIndex(UI_SESSION_LADISH);
- else if (smName == "NSM")
- self.ui.cb_session_mgr->setCurrentIndex(UI_SESSION_NSM);
- else
- self.ui.cb_session_mgr->setCurrentIndex(UI_SESSION_NONE);
-
- self.ui.le_command->setText(settings.valueString("Command", ""));
- self.ui.le_name->setText(settings.valueString("Name", ""));
- self.ui.sb_audio_ins->setValue(settings.valueIntPositive("NumAudioIns", 2));
- self.ui.sb_audio_ins->setValue(settings.valueIntPositive("NumAudioIns", 2));
- self.ui.sb_audio_outs->setValue(settings.valueIntPositive("NumAudioOuts", 2));
- self.ui.sb_midi_ins->setValue(settings.valueIntPositive("NumMidiIns", 0));
- self.ui.sb_midi_outs->setValue(settings.valueIntPositive("NumMidiOuts", 0));
- self.ui.cb_manage_window->setChecked(settings.valueBool("ManageWindow", true));
- self.ui.cb_capture_first_window->setChecked(settings.valueBool("CaptureFirstWindow", false));
- self.ui.cb_out_midi_mixdown->setChecked(settings.valueBool("MidiOutMixdown", false));
-
- checkIfButtonBoxShouldBeEnabled(self.ui.cb_session_mgr->currentIndex(),
- self.ui.le_command->text());
- }
-
- // -----------------------------------------------------------------------------------------------------------------
- // private slots
-
- void JackAppDialog::slot_commandChanged(const QString& command)
- {
- checkIfButtonBoxShouldBeEnabled(self.ui.cb_session_mgr->currentIndex(), command);
- }
-
- void JackAppDialog::slot_sessionManagerChanged(const int index)
- {
- checkIfButtonBoxShouldBeEnabled(index, self.ui.le_command->text());
- }
-
- void JackAppDialog::slot_saveSettings()
- {
- QSafeSettings settings("falkTX", "CarlaAddJackApp");
- settings.setValue("Command", self.ui.le_command->text());
- settings.setValue("Name", self.ui.le_name->text());
- settings.setValue("SessionManager", self.ui.cb_session_mgr->currentText());
- settings.setValue("NumAudioIns", self.ui.sb_audio_ins->value());
- settings.setValue("NumAudioOuts", self.ui.sb_audio_outs->value());
- settings.setValue("NumMidiIns", self.ui.sb_midi_ins->value());
- settings.setValue("NumMidiOuts", self.ui.sb_midi_outs->value());
- settings.setValue("ManageWindow", self.ui.cb_manage_window->isChecked());
- settings.setValue("CaptureFirstWindow", self.ui.cb_capture_first_window->isChecked());
- settings.setValue("MidiOutMixdown", self.ui.cb_out_midi_mixdown->isChecked());
- }
-
- // --------------------------------------------------------------------------------------------------------------------
-
- const JackAppDialogResults*
- carla_frontend_createAndExecJackAppDialog(void* const parent, const char* const projectFilename)
- {
- JackAppDialog gui(reinterpret_cast<QWidget*>(parent), projectFilename);
-
- if (gui.exec())
- {
- static JackAppDialogResults ret = {};
- static CarlaString retCommand;
- static CarlaString retName;
- static CarlaString retLabelSetup;
-
- const JackAppDialog::CommandAndFlags cafs = gui.getCommandAndFlags();
- retCommand = cafs.command.toUtf8().constData();
- retName = cafs.name.toUtf8().constData();
- retLabelSetup = cafs.labelSetup.toUtf8().constData();
-
- ret.command = retCommand;
- ret.name = retName;
- ret.labelSetup = retLabelSetup;
-
- return &ret;
- }
-
- return nullptr;
- }
-
- #if 0
- // --------------------------------------------------------------------------------------------------------------------
- // Testing
-
- #include "../utils/qsafesettings.cpp"
-
- int main(int argc, char* argv[])
- {
- QApplication app(argc, argv);
-
- if (JackAppDialogResults* const res = carla_frontend_createAndExecJackAppDialog(nullptr, ""))
- {
- printf("Results:\n");
- printf("\tCommand: %s\n", res->command);
- printf("\tName: %s\n", res->name);
- printf("\tLabelSetup: %s\n", res->labelSetup);
- }
-
- return 0;
- }
- #endif
-
- // --------------------------------------------------------------------------------------------------------------------
|