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.

265 lines
9.6KB

  1. /*
  2. * Carla plugin host
  3. * Copyright (C) 2011-2022 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "jackappdialog.hpp"
  18. #ifdef __clang__
  19. # pragma clang diagnostic push
  20. # pragma clang diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy"
  21. # pragma clang diagnostic ignored "-Wdeprecated-register"
  22. #elif defined(__GNUC__) && __GNUC__ >= 8
  23. # pragma GCC diagnostic push
  24. # pragma GCC diagnostic ignored "-Wclass-memaccess"
  25. # pragma GCC diagnostic ignored "-Wdeprecated-copy"
  26. #endif
  27. #include "jackappdialog_ui.hpp"
  28. #include <QtCore/QFileInfo>
  29. #include <QtCore/QVector>
  30. #include <QtWidgets/QPushButton>
  31. #ifdef __clang__
  32. # pragma clang diagnostic pop
  33. #elif defined(__GNUC__) && __GNUC__ >= 8
  34. # pragma GCC diagnostic pop
  35. #endif
  36. #include "../utils/qsafesettings.hpp"
  37. #include "../../includes/CarlaLibJackHints.h"
  38. // --------------------------------------------------------------------------------------------------------------------
  39. // Jack Application Dialog
  40. enum {
  41. UI_SESSION_NONE = 0,
  42. UI_SESSION_LADISH = 1,
  43. UI_SESSION_NSM = 2,
  44. };
  45. struct JackApplicationW::Self {
  46. Ui_Dialog ui;
  47. const QString fProjectFilename;
  48. Self(const char* const projectFilename)
  49. : fProjectFilename(projectFilename) {}
  50. static Self& create(const char* const projectFilename)
  51. {
  52. Self* const self = new Self(projectFilename);
  53. return *self;
  54. }
  55. };
  56. JackApplicationW::JackApplicationW(QWidget* const parent, const char* const projectFilename)
  57. : QDialog(parent),
  58. self(Self::create(projectFilename))
  59. {
  60. self.ui.setupUi(this);
  61. // -------------------------------------------------------------------------------------------------------------
  62. // UI setup
  63. self.ui.group_error->setVisible(false);
  64. adjustSize();
  65. setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
  66. // -------------------------------------------------------------------------------------------------------------
  67. // Load settings
  68. loadSettings();
  69. // -------------------------------------------------------------------------------------------------------------
  70. // Set-up connections
  71. connect(this, &QDialog::finished,
  72. this, &JackApplicationW::slot_saveSettings);
  73. connect(self.ui.cb_session_mgr, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
  74. this, &JackApplicationW::slot_sessionManagerChanged);
  75. connect(self.ui.le_command, &QLineEdit::textChanged,
  76. this, &JackApplicationW::slot_commandChanged);
  77. }
  78. JackApplicationW::~JackApplicationW()
  79. {
  80. delete &self;
  81. }
  82. // -----------------------------------------------------------------------------------------------------------------
  83. // public methods
  84. JackApplicationW::CommandAndFlags JackApplicationW::getCommandAndFlags() const
  85. {
  86. const QString command = self.ui.le_command->text();
  87. QString name = self.ui.le_name->text();
  88. if (name.isEmpty())
  89. {
  90. name = QFileInfo(command.split(' ').first()).baseName();
  91. name[0] = name[0].toTitleCase();
  92. }
  93. SessionManager smgr;
  94. switch(self.ui.cb_session_mgr->currentIndex())
  95. {
  96. case UI_SESSION_LADISH:
  97. smgr = LIBJACK_SESSION_MANAGER_LADISH;
  98. break;
  99. case UI_SESSION_NSM:
  100. smgr = LIBJACK_SESSION_MANAGER_NSM;
  101. break;
  102. default:
  103. smgr = LIBJACK_SESSION_MANAGER_NONE;
  104. break;
  105. }
  106. uint flags = 0x0;
  107. if (self.ui.cb_manage_window->isChecked())
  108. flags |= LIBJACK_FLAG_CONTROL_WINDOW;
  109. if (self.ui.cb_capture_first_window->isChecked())
  110. flags |= LIBJACK_FLAG_CAPTURE_FIRST_WINDOW;
  111. if (self.ui.cb_buffers_addition_mode->isChecked())
  112. flags |= LIBJACK_FLAG_AUDIO_BUFFERS_ADDITION;
  113. if (self.ui.cb_out_midi_mixdown->isChecked())
  114. flags |= LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN;
  115. if (self.ui.cb_external_start->isChecked())
  116. flags |= LIBJACK_FLAG_EXTERNAL_START;
  117. const QString labelSetup(QString("%1%2%3%4%5%6").arg(QChar('0' + self.ui.sb_audio_ins->value()))
  118. .arg(QChar('0' + self.ui.sb_audio_outs->value()))
  119. .arg(QChar('0' + self.ui.sb_midi_ins->value()))
  120. .arg(QChar('0' + self.ui.sb_midi_outs->value()))
  121. .arg(QChar('0' + smgr))
  122. .arg(QChar('0' + flags)));
  123. return {command, name, labelSetup};
  124. }
  125. // -----------------------------------------------------------------------------------------------------------------
  126. // private methods
  127. void JackApplicationW::checkIfButtonBoxShouldBeEnabled(const int index, const QCarlaString& command)
  128. {
  129. bool enabled = command.isNotEmpty();
  130. QCarlaString showErr;
  131. // NSM applications must not be abstract or absolute paths, and must not contain arguments
  132. if (enabled and index == UI_SESSION_NSM)
  133. {
  134. if (QVector<QChar>{'.', '/'}.contains(command[0]))
  135. showErr = tr("NSM applications cannot use abstract or absolute paths");
  136. else if (command.contains(' ') or command.contains(';') or command.contains('&'))
  137. showErr = tr("NSM applications cannot use CLI arguments");
  138. else if (self.fProjectFilename.isEmpty())
  139. showErr = tr("You need to save the current Carla project before NSM can be used");
  140. }
  141. if (showErr.isNotEmpty())
  142. {
  143. enabled = false;
  144. self.ui.l_error->setText(showErr);
  145. self.ui.group_error->setVisible(true);
  146. }
  147. else
  148. {
  149. self.ui.group_error->setVisible(false);
  150. }
  151. if (QPushButton* const button = self.ui.buttonBox->button(QDialogButtonBox::Ok))
  152. button->setEnabled(enabled);
  153. }
  154. void JackApplicationW::loadSettings()
  155. {
  156. const QSafeSettings settings("falkTX", "CarlaAddJackApp");
  157. const QString smName = settings.valueString("SessionManager", "");
  158. if (smName == "LADISH (SIGUSR1)")
  159. self.ui.cb_session_mgr->setCurrentIndex(UI_SESSION_LADISH);
  160. else if (smName == "NSM")
  161. self.ui.cb_session_mgr->setCurrentIndex(UI_SESSION_NSM);
  162. else
  163. self.ui.cb_session_mgr->setCurrentIndex(UI_SESSION_NONE);
  164. self.ui.le_command->setText(settings.valueString("Command", ""));
  165. self.ui.le_name->setText(settings.valueString("Name", ""));
  166. self.ui.sb_audio_ins->setValue(settings.valueIntPositive("NumAudioIns", 2));
  167. self.ui.sb_audio_ins->setValue(settings.valueIntPositive("NumAudioIns", 2));
  168. self.ui.sb_audio_outs->setValue(settings.valueIntPositive("NumAudioOuts", 2));
  169. self.ui.sb_midi_ins->setValue(settings.valueIntPositive("NumMidiIns", 0));
  170. self.ui.sb_midi_outs->setValue(settings.valueIntPositive("NumMidiOuts", 0));
  171. self.ui.cb_manage_window->setChecked(settings.valueBool("ManageWindow", true));
  172. self.ui.cb_capture_first_window->setChecked(settings.valueBool("CaptureFirstWindow", false));
  173. self.ui.cb_out_midi_mixdown->setChecked(settings.valueBool("MidiOutMixdown", false));
  174. checkIfButtonBoxShouldBeEnabled(self.ui.cb_session_mgr->currentIndex(),
  175. self.ui.le_command->text());
  176. }
  177. // -----------------------------------------------------------------------------------------------------------------
  178. // private slots
  179. void JackApplicationW::slot_commandChanged(const QString& command)
  180. {
  181. checkIfButtonBoxShouldBeEnabled(self.ui.cb_session_mgr->currentIndex(), command);
  182. }
  183. void JackApplicationW::slot_sessionManagerChanged(const int index)
  184. {
  185. checkIfButtonBoxShouldBeEnabled(index, self.ui.le_command->text());
  186. }
  187. void JackApplicationW::slot_saveSettings()
  188. {
  189. QSafeSettings settings("falkTX", "CarlaAddJackApp");
  190. settings.setValue("Command", self.ui.le_command->text());
  191. settings.setValue("Name", self.ui.le_name->text());
  192. settings.setValue("SessionManager", self.ui.cb_session_mgr->currentText());
  193. settings.setValue("NumAudioIns", self.ui.sb_audio_ins->value());
  194. settings.setValue("NumAudioOuts", self.ui.sb_audio_outs->value());
  195. settings.setValue("NumMidiIns", self.ui.sb_midi_ins->value());
  196. settings.setValue("NumMidiOuts", self.ui.sb_midi_outs->value());
  197. settings.setValue("ManageWindow", self.ui.cb_manage_window->isChecked());
  198. settings.setValue("CaptureFirstWindow", self.ui.cb_capture_first_window->isChecked());
  199. settings.setValue("MidiOutMixdown", self.ui.cb_out_midi_mixdown->isChecked());
  200. }
  201. // --------------------------------------------------------------------------------------------------------------------
  202. // Testing
  203. #include "../utils/qsafesettings.cpp"
  204. int main(int argc, char* argv[])
  205. {
  206. QApplication app(argc, argv);
  207. JackApplicationW gui(nullptr, "");
  208. gui.show();
  209. if (gui.exec())
  210. {
  211. auto cf = gui.getCommandAndFlags();
  212. printf("Results:\n");
  213. printf("\tCommand: %s\n", cf.command.toUtf8().constData());
  214. printf("\tName: %s\n", cf.name.toUtf8().constData());
  215. printf("\tLabelSetup: %s\n", cf.labelSetup.toUtf8().constData());
  216. }
  217. return 0;
  218. }
  219. // --------------------------------------------------------------------------------------------------------------------