Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
8.0KB

  1. // SPDX-FileCopyrightText: 2011-2025 Filipe Coelho <falktx@falktx.com>
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "jackappdialog.hpp"
  4. #ifdef __clang__
  5. # pragma clang diagnostic push
  6. # pragma clang diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy"
  7. # pragma clang diagnostic ignored "-Wdeprecated-register"
  8. #elif defined(__GNUC__) && __GNUC__ >= 8
  9. # pragma GCC diagnostic push
  10. # pragma GCC diagnostic ignored "-Wclass-memaccess"
  11. # pragma GCC diagnostic ignored "-Wdeprecated-copy"
  12. #endif
  13. #include <QtCore/QFileInfo>
  14. #include <QtWidgets/QPushButton>
  15. #ifdef __clang__
  16. # pragma clang diagnostic pop
  17. #elif defined(__GNUC__) && __GNUC__ >= 8
  18. # pragma GCC diagnostic pop
  19. #endif
  20. #include "qsafesettings.hpp"
  21. #include "CarlaLibJackHints.h"
  22. // --------------------------------------------------------------------------------------------------------------------
  23. // Jack Application Dialog
  24. struct JackAppDialog::PrivateData {
  25. const QString fProjectFilename;
  26. PrivateData(const char* const projectFilename)
  27. : fProjectFilename(projectFilename) {}
  28. };
  29. JackAppDialog::JackAppDialog(QWidget* const parent, const char* const projectFilename)
  30. : QDialog(parent),
  31. p(new PrivateData(projectFilename))
  32. {
  33. ui.setupUi(this);
  34. // ----------------------------------------------------------------------------------------------------------------
  35. // UI setup
  36. ui.group_error->setVisible(false);
  37. adjustSize();
  38. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  39. #ifdef CARLA_OS_MAC
  40. if (parent != nullptr)
  41. setWindowModality(Qt::WindowModal);
  42. #endif
  43. // ----------------------------------------------------------------------------------------------------------------
  44. // Load settings
  45. loadSettings();
  46. // ----------------------------------------------------------------------------------------------------------------
  47. // Set-up connections
  48. connect(this, &QDialog::finished,
  49. this, &JackAppDialog::slot_saveSettings);
  50. connect(ui.cb_session_mgr, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
  51. this, &JackAppDialog::slot_sessionManagerChanged);
  52. connect(ui.le_command, &QLineEdit::textChanged,
  53. this, &JackAppDialog::slot_commandChanged);
  54. }
  55. JackAppDialog::~JackAppDialog()
  56. {
  57. delete p;
  58. }
  59. // --------------------------------------------------------------------------------------------------------------------
  60. // public methods
  61. JackAppDialog::CommandAndFlags JackAppDialog::getCommandAndFlags() const
  62. {
  63. const QString command = ui.le_command->text();
  64. QString name = ui.le_name->text();
  65. if (name.isEmpty())
  66. {
  67. name = QFileInfo(command.split(' ').first()).baseName();
  68. name[0] = name[0].toTitleCase();
  69. }
  70. SessionManager smgr;
  71. switch (ui.cb_session_mgr->currentIndex())
  72. {
  73. case UI_SESSION_LADISH:
  74. smgr = LIBJACK_SESSION_MANAGER_LADISH;
  75. break;
  76. case UI_SESSION_NSM:
  77. smgr = LIBJACK_SESSION_MANAGER_NSM;
  78. break;
  79. default:
  80. smgr = LIBJACK_SESSION_MANAGER_NONE;
  81. break;
  82. }
  83. uint flags = 0x0;
  84. if (ui.cb_manage_window->isChecked())
  85. flags |= LIBJACK_FLAG_CONTROL_WINDOW;
  86. if (ui.cb_capture_first_window->isChecked())
  87. flags |= LIBJACK_FLAG_CAPTURE_FIRST_WINDOW;
  88. if (ui.cb_buffers_addition_mode->isChecked())
  89. flags |= LIBJACK_FLAG_AUDIO_BUFFERS_ADDITION;
  90. if (ui.cb_out_midi_mixdown->isChecked())
  91. flags |= LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN;
  92. if (ui.cb_external_start->isChecked())
  93. flags |= LIBJACK_FLAG_EXTERNAL_START;
  94. const QString labelSetup(QString("%1%2%3%4%5%6").arg(QChar('0' + ui.sb_audio_ins->value()))
  95. .arg(QChar('0' + ui.sb_audio_outs->value()))
  96. .arg(QChar('0' + ui.sb_midi_ins->value()))
  97. .arg(QChar('0' + ui.sb_midi_outs->value()))
  98. .arg(QChar('0' + smgr))
  99. .arg(QChar('0' + flags)));
  100. return {command, name, labelSetup};
  101. }
  102. // --------------------------------------------------------------------------------------------------------------------
  103. // private methods
  104. void JackAppDialog::checkIfButtonBoxShouldBeEnabled(const int index, const QCarlaString& command)
  105. {
  106. bool enabled = command.isNotEmpty();
  107. QCarlaString showErr;
  108. // NSM applications must not be abstract or absolute paths, and must not contain arguments
  109. if (enabled && index == UI_SESSION_NSM)
  110. {
  111. if (command[0] == '.' || command[0] == '/')
  112. showErr = tr("NSM applications cannot use abstract or absolute paths");
  113. else if (command.contains(' ') or command.contains(';') or command.contains('&'))
  114. showErr = tr("NSM applications cannot use CLI arguments");
  115. else if (p->fProjectFilename.isEmpty())
  116. showErr = tr("You need to save the current Carla project before NSM can be used");
  117. }
  118. if (showErr.isNotEmpty())
  119. {
  120. enabled = false;
  121. ui.l_error->setText(showErr);
  122. ui.group_error->setVisible(true);
  123. }
  124. else
  125. {
  126. ui.group_error->setVisible(false);
  127. }
  128. if (QPushButton* const button = ui.buttonBox->button(QDialogButtonBox::Ok))
  129. button->setEnabled(enabled);
  130. }
  131. void JackAppDialog::loadSettings()
  132. {
  133. const QSafeSettings settings("falkTX", "CarlaAddJackApp");
  134. const QString smName = settings.valueString("SessionManager", "");
  135. if (smName == "LADISH (SIGUSR1)")
  136. ui.cb_session_mgr->setCurrentIndex(UI_SESSION_LADISH);
  137. else if (smName == "NSM")
  138. ui.cb_session_mgr->setCurrentIndex(UI_SESSION_NSM);
  139. else
  140. ui.cb_session_mgr->setCurrentIndex(UI_SESSION_NONE);
  141. ui.le_command->setText(settings.valueString("Command", ""));
  142. ui.le_name->setText(settings.valueString("Name", ""));
  143. ui.sb_audio_ins->setValue(settings.valueIntPositive("NumAudioIns", 2));
  144. ui.sb_audio_ins->setValue(settings.valueIntPositive("NumAudioIns", 2));
  145. ui.sb_audio_outs->setValue(settings.valueIntPositive("NumAudioOuts", 2));
  146. ui.sb_midi_ins->setValue(settings.valueIntPositive("NumMidiIns", 0));
  147. ui.sb_midi_outs->setValue(settings.valueIntPositive("NumMidiOuts", 0));
  148. ui.cb_manage_window->setChecked(settings.valueBool("ManageWindow", true));
  149. ui.cb_capture_first_window->setChecked(settings.valueBool("CaptureFirstWindow", false));
  150. ui.cb_out_midi_mixdown->setChecked(settings.valueBool("MidiOutMixdown", false));
  151. checkIfButtonBoxShouldBeEnabled(ui.cb_session_mgr->currentIndex(),
  152. ui.le_command->text());
  153. }
  154. // --------------------------------------------------------------------------------------------------------------------
  155. // private slots
  156. void JackAppDialog::slot_commandChanged(const QString& command)
  157. {
  158. checkIfButtonBoxShouldBeEnabled(ui.cb_session_mgr->currentIndex(), command);
  159. }
  160. void JackAppDialog::slot_sessionManagerChanged(const int index)
  161. {
  162. checkIfButtonBoxShouldBeEnabled(index, ui.le_command->text());
  163. }
  164. void JackAppDialog::slot_saveSettings()
  165. {
  166. QSafeSettings settings("falkTX", "CarlaAddJackApp");
  167. settings.setValue("Command", ui.le_command->text());
  168. settings.setValue("Name", ui.le_name->text());
  169. settings.setValue("SessionManager", ui.cb_session_mgr->currentText());
  170. settings.setValue("NumAudioIns", ui.sb_audio_ins->value());
  171. settings.setValue("NumAudioOuts", ui.sb_audio_outs->value());
  172. settings.setValue("NumMidiIns", ui.sb_midi_ins->value());
  173. settings.setValue("NumMidiOuts", ui.sb_midi_outs->value());
  174. settings.setValue("ManageWindow", ui.cb_manage_window->isChecked());
  175. settings.setValue("CaptureFirstWindow", ui.cb_capture_first_window->isChecked());
  176. settings.setValue("MidiOutMixdown", ui.cb_out_midi_mixdown->isChecked());
  177. }
  178. // --------------------------------------------------------------------------------------------------------------------