1 /*
2 * Carla plugin host
3 * Copyright (C) 2011-2020 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
18 #include "carla_host.hpp"
19
20 //---------------------------------------------------------------------------------------------------------------------
21 // Imports (Global)
22
23
24 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
25 # pragma GCC diagnostic push
26 # pragma GCC diagnostic ignored "-Wconversion"
27 # pragma GCC diagnostic ignored "-Weffc++"
28 # pragma GCC diagnostic ignored "-Wsign-conversion"
29 #endif
30
31 //---------------------------------------------------------------------------------------------------------------------
32
33 #include <QtCore/QDir>
34 #include <QtCore/QStringList>
35 #include <QtCore/QTimer>
36
37 #include <QtGui/QPainter>
38
39 #include <QtWidgets/QFileDialog>
40 #include <QtWidgets/QFileSystemModel>
41 #include <QtWidgets/QMainWindow>
42 #include <QtWidgets/QMessageBox>
43
44 //---------------------------------------------------------------------------------------------------------------------
45
46 #include "ui_carla_host.hpp"
47
48 //---------------------------------------------------------------------------------------------------------------------
49
50 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
51 # pragma GCC diagnostic pop
52 #endif
53
54 //---------------------------------------------------------------------------------------------------------------------
55 // Imports (Custom)
56
57 #include "carla_database.hpp"
58 #include "carla_settings.hpp"
59 #include "carla_skin.hpp"
60
61 #include "CarlaHost.h"
62 #include "CarlaUtils.h"
63
64 #include "CarlaBackendUtils.hpp"
65 #include "CarlaMathUtils.hpp"
66 #include "CarlaString.hpp"
67
68 // FIXME put in right place
69 /*
70 static QString fixLogText(QString text)
71 {
72 //v , Qt::CaseSensitive
73 return text.replace("\x1b[30;1m", "").replace("\x1b[31m", "").replace("\x1b[0m", "");
74 }
75 */
76
77 //---------------------------------------------------------------------------------------------------------------------
78 // Session Management support
79
80 static const char* const CARLA_CLIENT_NAME = getenv("CARLA_CLIENT_NAME");
81 static const char* const LADISH_APP_NAME = getenv("LADISH_APP_NAME");
82 static const char* const NSM_URL = getenv("NSM_URL");
83
84 //---------------------------------------------------------------------------------------------------------------------
85
CarlaHost()86 CarlaHost::CarlaHost()
87 : QObject(),
88 isControl(false),
89 isPlugin(false),
90 isRemote(false),
91 nsmOK(false),
92 processMode(ENGINE_PROCESS_MODE_PATCHBAY),
93 transportMode(ENGINE_TRANSPORT_MODE_INTERNAL),
94 transportExtra(),
95 nextProcessMode(processMode),
96 processModeForced(false),
97 audioDriverForced(),
98 experimental(false),
99 exportLV2(false),
100 forceStereo(false),
101 manageUIs(false),
102 maxParameters(0),
103 resetXruns(false),
104 preferPluginBridges(false),
105 preferUIBridges(false),
106 preventBadBehaviour(false),
107 showLogs(false),
108 showPluginBridges(false),
109 showWineBridges(false),
110 uiBridgesTimeout(0),
111 uisAlwaysOnTop(false),
112 pathBinaries(),
113 pathResources() {}
114
115 //---------------------------------------------------------------------------------------------------------------------
116 // Carla Host Window
117
118 enum CustomActions {
119 CUSTOM_ACTION_NONE,
120 CUSTOM_ACTION_APP_CLOSE,
121 CUSTOM_ACTION_PROJECT_LOAD
122 };
123
124 struct CachedSavedSettings {
125 int _CARLA_KEY_MAIN_REFRESH_INTERVAL = 0;
126 bool _CARLA_KEY_MAIN_CONFIRM_EXIT = false;
127 bool _CARLA_KEY_CANVAS_FANCY_EYE_CANDY = false;
128 };
129
130 //---------------------------------------------------------------------------------------------------------------------
131
132 struct CarlaHostWindow::PrivateData {
133 Ui::CarlaHostW ui;
134 CarlaHost& host;
135 CarlaHostWindow* const hostWindow;
136
137 //-----------------------------------------------------------------------------------------------------------------
138 // Internal stuff
139
140 QWidget* const fParentOrSelf;
141
142 int fIdleTimerNull; // to keep application signals alive
143 int fIdleTimerFast;
144 int fIdleTimerSlow;
145
146 bool fLadspaRdfNeedsUpdate;
147 QList<void*> fLadspaRdfList;
148
149 int fPluginCount;
150 QList<QWidget*> fPluginList;
151
152 void* fPluginDatabaseDialog;
153 QStringList fFavoritePlugins;
154
155 QCarlaString fProjectFilename;
156 bool fIsProjectLoading;
157 bool fCurrentlyRemovingAllPlugins;
158
159 double fLastTransportBPM;
160 uint64_t fLastTransportFrame;
161 bool fLastTransportState;
162 uint fBufferSize;
163 double fSampleRate;
164 QCarlaString fOscAddressTCP;
165 QCarlaString fOscAddressUDP;
166 QCarlaString fOscReportedHost;
167
168 #ifdef CARLA_OS_MAC
169 bool fMacClosingHelper;
170 #endif
171
172 // CancelableActionCallback Box
173 void* fCancelableActionBox;
174
175 // run a custom action after engine is properly closed
176 CustomActions fCustomStopAction;
177
178 // first attempt of auto-start engine doesn't show an error
179 bool fFirstEngineInit;
180
181 // to be filled with key-value pairs of current settings
182 CachedSavedSettings fSavedSettings;
183
184 QCarlaString fClientName;
185 QCarlaString fSessionManagerName;
186
187 //-----------------------------------------------------------------------------------------------------------------
188 // Internal stuff (patchbay)
189
190 QImage fExportImage;
191
192 bool fPeaksCleared;
193
194 bool fExternalPatchbay;
195 QList<uint> fSelectedPlugins;
196
197 int fCanvasWidth;
198 int fCanvasHeight;
199 int fMiniCanvasUpdateTimeout;
200 const bool fWithCanvas;
201
202 //-----------------------------------------------------------------------------------------------------------------
203 // GUI stuff (disk)
204
205 QFileSystemModel fDirModel;
206
207 //-----------------------------------------------------------------------------------------------------------------
208
209 // CarlaHostWindow* hostWindow,
PrivateDataCarlaHostWindow::PrivateData210 PrivateData(CarlaHostWindow* const hw, CarlaHost& h, const bool withCanvas)
211 : ui(),
212 host(h),
213 hostWindow(hw),
214 // Internal stuff
215 fParentOrSelf(hw->parentWidget() != nullptr ? hw->parentWidget() : hw),
216 fIdleTimerNull(0),
217 fIdleTimerFast(0),
218 fIdleTimerSlow(0),
219 fLadspaRdfNeedsUpdate(true),
220 fLadspaRdfList(),
221 fPluginCount(0),
222 fPluginList(),
223 fPluginDatabaseDialog(nullptr),
224 fFavoritePlugins(),
225 fProjectFilename(),
226 fIsProjectLoading(false),
227 fCurrentlyRemovingAllPlugins(false),
228 fLastTransportBPM(0.0),
229 fLastTransportFrame(0),
230 fLastTransportState(false),
231 fBufferSize(0),
232 fSampleRate(0.0),
233 fOscAddressTCP(),
234 fOscAddressUDP(),
235 fOscReportedHost(),
236 #ifdef CARLA_OS_MAC
237 fMacClosingHelper(true),
238 #endif
239 fCancelableActionBox(nullptr),
240 fCustomStopAction(CUSTOM_ACTION_NONE),
241 fFirstEngineInit(true),
242 fSavedSettings(),
243 fClientName(),
244 fSessionManagerName(),
245 // Internal stuff (patchbay)
246 fExportImage(),
247 fPeaksCleared(true),
248 fExternalPatchbay(false),
249 fSelectedPlugins(),
250 fCanvasWidth(0),
251 fCanvasHeight(0),
252 fMiniCanvasUpdateTimeout(0),
253 fWithCanvas(withCanvas),
254 // disk
255 fDirModel(hostWindow)
256 {
257 ui.setupUi(hostWindow);
258
259 //-------------------------------------------------------------------------------------------------------------
260 // Internal stuff
261
262 if (host.isControl)
263 {
264 fClientName = "Carla-Control";
265 fSessionManagerName = "Control";
266 }
267 else if (host.isPlugin)
268 {
269 fClientName = "Carla-Plugin";
270 fSessionManagerName = "Plugin";
271 }
272 else if (LADISH_APP_NAME != nullptr)
273 {
274 fClientName = LADISH_APP_NAME;
275 fSessionManagerName = "LADISH";
276 }
277 else if (NSM_URL != nullptr && host.nsmOK)
278 {
279 fClientName = "Carla.tmp";
280 fSessionManagerName = "Non Session Manager TMP";
281 }
282 else
283 {
284 fClientName = CARLA_CLIENT_NAME != nullptr ? CARLA_CLIENT_NAME : "Carla";
285 fSessionManagerName = "";
286 }
287
288 //-------------------------------------------------------------------------------------------------------------
289 // Set up GUI (engine stopped)
290
291 if (host.isPlugin || host.isControl)
292 {
293 ui.act_file_save->setVisible(false);
294 ui.act_engine_start->setEnabled(false);
295 ui.act_engine_start->setVisible(false);
296 ui.act_engine_stop->setEnabled(false);
297 ui.act_engine_stop->setVisible(false);
298 ui.menu_Engine->setEnabled(false);
299 ui.menu_Engine->setVisible(false);
300 if (QAction* const action = ui.menu_Engine->menuAction())
301 action->setVisible(false);
302 ui.tabWidget->removeTab(2);
303
304 if (host.isControl)
305 {
306 ui.act_file_new->setVisible(false);
307 ui.act_file_open->setVisible(false);
308 ui.act_file_save_as->setVisible(false);
309 ui.tabUtils->removeTab(0);
310 }
311 else
312 {
313 ui.act_file_save_as->setText(tr("Export as..."));
314
315 if (! withCanvas)
316 if (QTabBar* const tabBar = ui.tabWidget->tabBar())
317 tabBar->hide();
318 }
319 }
320 else
321 {
322 ui.act_engine_start->setEnabled(true);
323 #ifdef CARLA_OS_WIN
324 ui.tabWidget->removeTab(2);
325 #endif
326 }
327
328 if (host.isControl)
329 {
330 ui.act_file_refresh->setEnabled(false);
331 }
332 else
333 {
334 ui.act_file_connect->setEnabled(false);
335 ui.act_file_connect->setVisible(false);
336 ui.act_file_refresh->setEnabled(false);
337 ui.act_file_refresh->setVisible(false);
338 }
339
340 if (fSessionManagerName.isNotEmpty() && ! host.isPlugin)
341 ui.act_file_new->setEnabled(false);
342
343 ui.act_file_open->setEnabled(false);
344 ui.act_file_save->setEnabled(false);
345 ui.act_file_save_as->setEnabled(false);
346 ui.act_engine_stop->setEnabled(false);
347 ui.act_plugin_remove_all->setEnabled(false);
348
349 ui.act_canvas_show_internal->setChecked(false);
350 ui.act_canvas_show_internal->setVisible(false);
351 ui.act_canvas_show_external->setChecked(false);
352 ui.act_canvas_show_external->setVisible(false);
353
354 ui.menu_PluginMacros->setEnabled(false);
355 ui.menu_Canvas->setEnabled(false);
356
357 QWidget* const dockWidgetTitleBar = new QWidget(hostWindow);
358 ui.dockWidget->setTitleBarWidget(dockWidgetTitleBar);
359
360 if (! withCanvas)
361 {
362 ui.act_canvas_show_internal->setVisible(false);
363 ui.act_canvas_show_external->setVisible(false);
364 ui.act_canvas_arrange->setVisible(false);
365 ui.act_canvas_refresh->setVisible(false);
366 ui.act_canvas_save_image->setVisible(false);
367 ui.act_canvas_zoom_100->setVisible(false);
368 ui.act_canvas_zoom_fit->setVisible(false);
369 ui.act_canvas_zoom_in->setVisible(false);
370 ui.act_canvas_zoom_out->setVisible(false);
371 ui.act_settings_show_meters->setVisible(false);
372 ui.act_settings_show_keyboard->setVisible(false);
373 ui.menu_Canvas_Zoom->setEnabled(false);
374 ui.menu_Canvas_Zoom->setVisible(false);
375 if (QAction* const action = ui.menu_Canvas_Zoom->menuAction())
376 action->setVisible(false);
377 ui.menu_Canvas->setEnabled(false);
378 ui.menu_Canvas->setVisible(false);
379 if (QAction* const action = ui.menu_Canvas->menuAction())
380 action->setVisible(false);
381 ui.tw_miniCanvas->hide();
382 ui.tabWidget->removeTab(1);
383 #ifdef CARLA_OS_WIN
384 ui.tabWidget->tabBar().hide()
385 #endif
386 }
387
388 //-------------------------------------------------------------------------------------------------------------
389 // Set up GUI (disk)
390
391 const QString home(QDir::homePath());
392 fDirModel.setRootPath(home);
393
394 if (const char* const* const exts = carla_get_supported_file_extensions())
395 {
396 QStringList filters;
397 const QString prefix("*.");
398
399 for (uint i=0; exts[i] != nullptr; ++i)
400 filters.append(prefix + exts[i]);
401
402 fDirModel.setNameFilters(filters);
403 }
404
405 ui.fileTreeView->setModel(&fDirModel);
406 ui.fileTreeView->setRootIndex(fDirModel.index(home));
407 ui.fileTreeView->setColumnHidden(1, true);
408 ui.fileTreeView->setColumnHidden(2, true);
409 ui.fileTreeView->setColumnHidden(3, true);
410 ui.fileTreeView->setHeaderHidden(true);
411
412 //-------------------------------------------------------------------------------------------------------------
413 // Set up GUI (transport)
414
415 const QFontMetrics fontMetrics(ui.l_transport_bbt->fontMetrics());
416 int minValueWidth = fontMetricsHorizontalAdvance(fontMetrics, "000|00|0000");
417 int minLabelWidth = fontMetricsHorizontalAdvance(fontMetrics, ui.label_transport_frame->text());
418
419 int labelTimeWidth = fontMetricsHorizontalAdvance(fontMetrics, ui.label_transport_time->text());
420 int labelBBTWidth = fontMetricsHorizontalAdvance(fontMetrics, ui.label_transport_bbt->text());
421
422 if (minLabelWidth < labelTimeWidth)
423 minLabelWidth = labelTimeWidth;
424 if (minLabelWidth < labelBBTWidth)
425 minLabelWidth = labelBBTWidth;
426
427 ui.label_transport_frame->setMinimumWidth(minLabelWidth + 3);
428 ui.label_transport_time->setMinimumWidth(minLabelWidth + 3);
429 ui.label_transport_bbt->setMinimumWidth(minLabelWidth + 3);
430
431 ui.l_transport_bbt->setMinimumWidth(minValueWidth + 3);
432 ui.l_transport_frame->setMinimumWidth(minValueWidth + 3);
433 ui.l_transport_time->setMinimumWidth(minValueWidth + 3);
434
435 if (host.isPlugin)
436 {
437 ui.b_transport_play->setEnabled(false);
438 ui.b_transport_stop->setEnabled(false);
439 ui.b_transport_backwards->setEnabled(false);
440 ui.b_transport_forwards->setEnabled(false);
441 ui.group_transport_controls->setEnabled(false);
442 ui.group_transport_controls->setVisible(false);
443 ui.cb_transport_link->setEnabled(false);
444 ui.cb_transport_link->setVisible(false);
445 ui.cb_transport_jack->setEnabled(false);
446 ui.cb_transport_jack->setVisible(false);
447 ui.dsb_transport_bpm->setEnabled(false);
448 ui.dsb_transport_bpm->setReadOnly(true);
449 }
450
451 ui.w_transport->setEnabled(false);
452
453 //-------------------------------------------------------------------------------------------------------------
454 // Set up GUI (rack)
455
456 // ui.listWidget->setHostAndParent(host, self);
457
458 if (QScrollBar* const sb = ui.listWidget->verticalScrollBar())
459 {
460 ui.rackScrollBar->setMinimum(sb->minimum());
461 ui.rackScrollBar->setMaximum(sb->maximum());
462 ui.rackScrollBar->setValue(sb->value());
463
464 /*
465 sb->rangeChanged.connect(ui.rackScrollBar.setRange);
466 sb->valueChanged.connect(ui.rackScrollBar.setValue);
467 ui.rackScrollBar->rangeChanged.connect(sb.setRange);
468 ui.rackScrollBar->valueChanged.connect(sb.setValue);
469 */
470 }
471
472 updateStyle();
473
474 ui.rack->setStyleSheet(" \
475 CarlaRackList#CarlaRackList { \
476 background-color: black; \
477 } \
478 ");
479
480 //-------------------------------------------------------------------------------------------------------------
481 // Set up GUI (patchbay)
482
483 /*
484 ui.peak_in->setChannelCount(2);
485 ui.peak_in->setMeterColor(DigitalPeakMeter.COLOR_BLUE);
486 ui.peak_in->setMeterOrientation(DigitalPeakMeter.VERTICAL);
487 */
488 ui.peak_in->setFixedWidth(25);
489
490 /*
491 ui.peak_out->setChannelCount(2);
492 ui.peak_out->setMeterColor(DigitalPeakMeter.COLOR_GREEN);
493 ui.peak_out->setMeterOrientation(DigitalPeakMeter.VERTICAL);
494 */
495 ui.peak_out->setFixedWidth(25);
496
497 /*
498 ui.scrollArea = PixmapKeyboardHArea(ui.patchbay);
499 ui.keyboard = ui.scrollArea.keyboard;
500 ui.patchbay.layout().addWidget(ui.scrollArea, 1, 0, 1, 0);
501
502 ui.scrollArea->setEnabled(false);
503
504 ui.miniCanvasPreview->setRealParent(self);
505 */
506 if (QTabBar* const tabBar = ui.tw_miniCanvas->tabBar())
507 tabBar->hide();
508
509 //-------------------------------------------------------------------------------------------------------------
510 // Set up GUI (special stuff for Mac OS)
511
512 #ifdef CARLA_OS_MAC
513 ui.act_file_quit->setMenuRole(QAction::QuitRole);
514 ui.act_settings_configure->setMenuRole(QAction::PreferencesRole);
515 ui.act_help_about->setMenuRole(QAction::AboutRole);
516 ui.act_help_about_qt->setMenuRole(QAction::AboutQtRole);
517 ui.menu_Settings->setTitle("Panels");
518 if (QAction* const action = ui.menu_Help.menuAction())
519 action->setVisible(false);
520 #endif
521
522 //-------------------------------------------------------------------------------------------------------------
523 // Load Settings
524
525 loadSettings(true);
526
527 //-------------------------------------------------------------------------------------------------------------
528 // Final setup
529
530 ui.text_logs->clear();
531 setProperWindowTitle();
532
533 // Disable non-supported features
534 const char* const* const features = carla_get_supported_features();
535
536 if (! stringArrayContainsString(features, "link"))
537 {
538 ui.cb_transport_link->setEnabled(false);
539 ui.cb_transport_link->setVisible(false);
540 }
541
542 if (! stringArrayContainsString(features, "juce"))
543 {
544 ui.act_help_about_juce->setEnabled(false);
545 ui.act_help_about_juce->setVisible(false);
546 }
547
548 // Plugin needs to have timers always running so it receives messages
549 if (host.isPlugin || host.isRemote)
550 {
551 startTimers();
552 }
553 // Load initial project file if set
554 else
555 {
556 /*
557 projectFile = getInitialProjectFile(QApplication.instance());
558
559 if (projectFile)
560 loadProjectLater(projectFile);
561 */
562 }
563
564 }
565
566 //-----------------------------------------------------------------------------------------------------------------
567 // Setup
568
569 #if 0
570 def compactPlugin(self, pluginId):
571 if pluginId > self.fPluginCount:
572 return
573
574 pitem = self.fPluginList[pluginId]
575
576 if pitem is None:
577 return
578
579 pitem.recreateWidget(True)
580
581 def changePluginColor(self, pluginId, color, colorStr):
582 if pluginId > self.fPluginCount:
583 return
584
585 pitem = self.fPluginList[pluginId]
586
587 if pitem is None:
588 return
589
590 self.host.set_custom_data(pluginId, CUSTOM_DATA_TYPE_PROPERTY, "CarlaColor", colorStr)
591 pitem.recreateWidget(newColor = color)
592
593 def changePluginSkin(self, pluginId, skin):
594 if pluginId > self.fPluginCount:
595 return
596
597 pitem = self.fPluginList[pluginId]
598
599 if pitem is None:
600 return
601
602 self.host.set_custom_data(pluginId, CUSTOM_DATA_TYPE_PROPERTY, "CarlaSkin", skin)
603 if skin not in ("default","rncbc","presets","mpresets"):
604 pitem.recreateWidget(newSkin = skin, newColor = (255,255,255))
605 else:
606 pitem.recreateWidget(newSkin = skin)
607
608 def switchPlugins(self, pluginIdA, pluginIdB):
609 if pluginIdA == pluginIdB:
610 return
611 if pluginIdA < 0 or pluginIdB < 0:
612 return
613 if pluginIdA >= self.fPluginCount or pluginIdB >= self.fPluginCount:
614 return
615
616 self.host.switch_plugins(pluginIdA, pluginIdB)
617
618 itemA = self.fPluginList[pluginIdA]
619 compactA = itemA.isCompacted()
620 guiShownA = itemA.isGuiShown()
621
622 itemB = self.fPluginList[pluginIdB]
623 compactB = itemB.isCompacted()
624 guiShownB = itemB.isGuiShown()
625
626 itemA.setPluginId(pluginIdA)
627 itemA.recreateWidget2(compactB, guiShownB)
628
629 itemB.setPluginId(pluginIdB)
630 itemB.recreateWidget2(compactA, guiShownA)
631
632 if self.fWithCanvas:
633 self.slot_canvasRefresh()
634 #endif
635
setLoadRDFsNeededCarlaHostWindow::PrivateData636 void setLoadRDFsNeeded() noexcept
637 {
638 fLadspaRdfNeedsUpdate = true;
639 }
640
setProperWindowTitleCarlaHostWindow::PrivateData641 void setProperWindowTitle()
642 {
643 QString title(fClientName);
644
645 /*
646 if (fProjectFilename.isNotEmpty() && ! host.nsmOK)
647 title += QString(" - %s").arg(os.path.basename(fProjectFilename));
648 */
649 if (fSessionManagerName.isNotEmpty())
650 title += QString(" (%s)").arg(fSessionManagerName);
651
652 hostWindow->setWindowTitle(title);
653 }
654
updateBufferSizeCarlaHostWindow::PrivateData655 void updateBufferSize(const uint newBufferSize)
656 {
657 if (fBufferSize == newBufferSize)
658 return;
659 fBufferSize = newBufferSize;
660 ui.cb_buffer_size->clear();
661 ui.cb_buffer_size->addItem(QString("%1").arg(newBufferSize));
662 ui.cb_buffer_size->setCurrentIndex(0);
663 }
664
updateSampleRateCarlaHostWindow::PrivateData665 void updateSampleRate(const double newSampleRate)
666 {
667 if (carla_isEqual(fSampleRate, newSampleRate))
668 return;
669 fSampleRate = newSampleRate;
670 ui.cb_sample_rate->clear();
671 ui.cb_sample_rate->addItem(QString("%1").arg(newSampleRate));
672 ui.cb_sample_rate->setCurrentIndex(0);
673 refreshTransport(true);
674 }
675
676 //-----------------------------------------------------------------------------------------------------------------
677 // Files
678
679 #if 0
680 def makeExtraFilename(self):
681 return self.fProjectFilename.rsplit(".",1)[0]+".json"
682 #endif
683
loadProjectNowCarlaHostWindow::PrivateData684 void loadProjectNow()
685 {
686 if (fProjectFilename.isEmpty())
687 return qCritical("ERROR: loading project without filename set");
688 /*
689 if (host.nsmOK && ! os.path.exists(self.fProjectFilename))
690 return;
691 */
692
693 projectLoadingStarted();
694 fIsProjectLoading = true;
695
696 if (! carla_load_project(host.handle, fProjectFilename.toUtf8()))
697 {
698 fIsProjectLoading = false;
699 projectLoadingFinished();
700
701 CustomMessageBox(hostWindow,
702 QMessageBox::Critical,
703 tr("Error"),
704 tr("Failed to load project"),
705 carla_get_last_error(host.handle),
706 QMessageBox::Ok, QMessageBox::Ok);
707 }
708 }
709
710 #if 0
711 def loadProjectLater(self, filename):
712 self.fProjectFilename = QFileInfo(filename).absoluteFilePath()
713 self.setProperWindowTitle()
714 QTimer.singleShot(1, self.slot_loadProjectNow)
715
716 def saveProjectNow(self):
717 if not self.fProjectFilename:
718 return qCritical("ERROR: saving project without filename set")
719
720 if not self.host.save_project(self.fProjectFilename):
721 CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to save project"),
722 self.host.get_last_error(),
723 QMessageBox.Ok, QMessageBox.Ok)
724 return
725
726 if not self.fWithCanvas:
727 return
728
729 with open(self.makeExtraFilename(), 'w') as fh:
730 json.dump({
731 'canvas': patchcanvas.saveGroupPositions(),
732 }, fh)
733 #endif
734
projectLoadingStartedCarlaHostWindow::PrivateData735 void projectLoadingStarted()
736 {
737 ui.rack->setEnabled(false);
738 ui.graphicsView->setEnabled(false);
739 }
740
projectLoadingFinishedCarlaHostWindow::PrivateData741 void projectLoadingFinished()
742 {
743 ui.rack->setEnabled(true);
744 ui.graphicsView->setEnabled(true);
745
746 if (! fWithCanvas)
747 return;
748
749 QTimer::singleShot(1000, hostWindow, SLOT(slot_canvasRefresh()));
750
751 /*
752 const QString extrafile = makeExtraFilename();
753 if not os.path.exists(extrafile):
754 return;
755
756 try:
757 with open(extrafile, "r") as fh:
758 canvasdata = json.load(fh)['canvas']
759 except:
760 return
761
762 patchcanvas.restoreGroupPositions(canvasdata)
763 */
764 }
765
766 //-----------------------------------------------------------------------------------------------------------------
767 // Engine (menu actions)
768
engineStopFinalCarlaHostWindow::PrivateData769 void engineStopFinal()
770 {
771 killTimers();
772
773 if (carla_is_engine_running(host.handle))
774 {
775 if (fCustomStopAction == CUSTOM_ACTION_PROJECT_LOAD)
776 {
777 removeAllPlugins();
778 }
779 else if (fPluginCount != 0)
780 {
781 fCurrentlyRemovingAllPlugins = true;
782 projectLoadingStarted();
783 }
784
785 if (! carla_remove_all_plugins(host.handle))
786 {
787 ui.text_logs->appendPlainText("Failed to remove all plugins, error was:");
788 ui.text_logs->appendPlainText(carla_get_last_error(host.handle));
789 }
790
791 if (! carla_engine_close(host.handle))
792 {
793 ui.text_logs->appendPlainText("Failed to stop engine, error was:");
794 ui.text_logs->appendPlainText(carla_get_last_error(host.handle));
795 }
796 }
797
798 if (fCustomStopAction == CUSTOM_ACTION_APP_CLOSE)
799 {
800 hostWindow->close();
801 }
802 else if (fCustomStopAction == CUSTOM_ACTION_PROJECT_LOAD)
803 {
804 hostWindow->slot_engineStart();
805 loadProjectNow();
806 carla_nsm_ready(host.handle, NSM_CALLBACK_OPEN);
807 }
808
809 fCustomStopAction = CUSTOM_ACTION_NONE;
810 }
811
812 //-----------------------------------------------------------------------------------------------------------------
813 // Plugins
814
removeAllPluginsCarlaHostWindow::PrivateData815 void removeAllPlugins()
816 {
817 }
818
819 //-----------------------------------------------------------------------------------------------------------------
820 // Plugins (menu actions)
821
showAddPluginDialogCarlaHostWindow::PrivateData822 void showAddPluginDialog()
823 {
824 }
825
showAddJackAppDialogCarlaHostWindow::PrivateData826 void showAddJackAppDialog()
827 {
828 }
829
pluginRemoveAllCarlaHostWindow::PrivateData830 void pluginRemoveAll()
831 {
832 }
833
834 //-----------------------------------------------------------------------------------------------------------------
835 // Canvas
836
clearSideStuffCarlaHostWindow::PrivateData837 void clearSideStuff()
838 {
839 }
840
setupCanvasCarlaHostWindow::PrivateData841 void setupCanvas()
842 {
843 }
844
updateCanvasInitialPosCarlaHostWindow::PrivateData845 void updateCanvasInitialPos()
846 {
847 }
848
updateMiniCanvasLaterCarlaHostWindow::PrivateData849 void updateMiniCanvasLater()
850 {
851 }
852
853 //-----------------------------------------------------------------------------------------------------------------
854 // Settings
855
saveSettingsCarlaHostWindow::PrivateData856 void saveSettings()
857 {
858 QSafeSettings settings;
859
860 settings.setValue("Geometry", hostWindow->saveGeometry());
861 settings.setValue("ShowToolbar", ui.toolBar->isEnabled());
862
863 if (! host.isControl)
864 settings.setValue("ShowSidePanel", ui.dockWidget->isEnabled());
865
866 QStringList diskFolders;
867
868 /*
869 for i in range(ui.cb_disk.count()):
870 diskFolders.append(ui.cb_disk->itemData(i))
871 */
872
873 settings.setValue("DiskFolders", diskFolders);
874 settings.setValue("LastBPM", fLastTransportBPM);
875
876 settings.setValue("ShowMeters", ui.act_settings_show_meters->isChecked());
877 settings.setValue("ShowKeyboard", ui.act_settings_show_keyboard->isChecked());
878 settings.setValue("HorizontalScrollBarValue", ui.graphicsView->horizontalScrollBar()->value());
879 settings.setValue("VerticalScrollBarValue", ui.graphicsView->verticalScrollBar()->value());
880
881 settings.setValue(CARLA_KEY_ENGINE_TRANSPORT_MODE, host.transportMode);
882 settings.setValue(CARLA_KEY_ENGINE_TRANSPORT_EXTRA, host.transportExtra);
883 }
884
loadSettingsCarlaHostWindow::PrivateData885 void loadSettings(bool firstTime)
886 {
887 const QSafeSettings settings;
888
889 if (firstTime)
890 {
891 const QByteArray geometry(settings.valueByteArray("Geometry"));
892 if (! geometry.isNull())
893 hostWindow->restoreGeometry(geometry);
894
895 // if settings.contains("SplitterState"):
896 //ui.splitter.restoreState(settings.value("SplitterState", b""))
897 //else:
898 //ui.splitter.setSizes([210, 99999])
899
900 const bool toolbarVisible = settings.valueBool("ShowToolbar", true);
901 ui.act_settings_show_toolbar->setChecked(toolbarVisible);
902 showToolbar(toolbarVisible);
903
904 const bool sidePanelVisible = settings.valueBool("ShowSidePanel", true) && ! host.isControl;
905 ui.act_settings_show_side_panel->setChecked(sidePanelVisible);
906 showSidePanel(sidePanelVisible);
907
908 QStringList diskFolders;
909 diskFolders.append(QDir::homePath());
910 diskFolders = settings.valueStringList("DiskFolders", diskFolders);
911
912 ui.cb_disk->setItemData(0, QDir::homePath());
913
914 for (const auto& folder : diskFolders)
915 {
916 /*
917 if i == 0: continue;
918 folder = diskFolders[i];
919 ui.cb_disk->addItem(os.path.basename(folder), folder);
920 */
921 }
922
923 //if MACOS and not settings.value(CARLA_KEY_MAIN_USE_PRO_THEME, true, bool):
924 // setUnifiedTitleAndToolBarOnMac(true)
925
926 const bool showMeters = settings.valueBool("ShowMeters", true);
927 ui.act_settings_show_meters->setChecked(showMeters);
928 ui.peak_in->setVisible(showMeters);
929 ui.peak_out->setVisible(showMeters);
930
931 const bool showKeyboard = settings.valueBool("ShowKeyboard", true);
932 ui.act_settings_show_keyboard->setChecked(showKeyboard);
933 /*
934 ui.scrollArea->setVisible(showKeyboard);
935 */
936
937 const QSafeSettings settingsDBf("falkTX", "CarlaDatabase2");
938 fFavoritePlugins = settingsDBf.valueStringList("PluginDatabase/Favorites");
939
940 QTimer::singleShot(100, hostWindow, SLOT(slot_restoreCanvasScrollbarValues()));
941 }
942
943 // TODO - complete this
944 fSavedSettings._CARLA_KEY_MAIN_CONFIRM_EXIT = settings.valueBool(CARLA_KEY_MAIN_CONFIRM_EXIT,
945 CARLA_DEFAULT_MAIN_CONFIRM_EXIT);
946
947 fSavedSettings._CARLA_KEY_MAIN_REFRESH_INTERVAL = settings.valueIntPositive(CARLA_KEY_MAIN_REFRESH_INTERVAL,
948 CARLA_DEFAULT_MAIN_REFRESH_INTERVAL);
949
950 fSavedSettings._CARLA_KEY_CANVAS_FANCY_EYE_CANDY = settings.valueBool(CARLA_KEY_CANVAS_FANCY_EYE_CANDY,
951 CARLA_DEFAULT_CANVAS_FANCY_EYE_CANDY);
952
953 /*
954 {
955 CARLA_KEY_MAIN_PROJECT_FOLDER: settings.value(CARLA_KEY_MAIN_PROJECT_FOLDER, CARLA_DEFAULT_MAIN_PROJECT_FOLDER, str),
956 CARLA_KEY_MAIN_EXPERIMENTAL: settings.value(CARLA_KEY_MAIN_EXPERIMENTAL, CARLA_DEFAULT_MAIN_EXPERIMENTAL, bool),
957 CARLA_KEY_CANVAS_THEME: settings.value(CARLA_KEY_CANVAS_THEME, CARLA_DEFAULT_CANVAS_THEME, str),
958 CARLA_KEY_CANVAS_SIZE: settings.value(CARLA_KEY_CANVAS_SIZE, CARLA_DEFAULT_CANVAS_SIZE, str),
959 CARLA_KEY_CANVAS_AUTO_HIDE_GROUPS: settings.value(CARLA_KEY_CANVAS_AUTO_HIDE_GROUPS, CARLA_DEFAULT_CANVAS_AUTO_HIDE_GROUPS, bool),
960 CARLA_KEY_CANVAS_AUTO_SELECT_ITEMS: settings.value(CARLA_KEY_CANVAS_AUTO_SELECT_ITEMS, CARLA_DEFAULT_CANVAS_AUTO_SELECT_ITEMS, bool),
961 CARLA_KEY_CANVAS_USE_BEZIER_LINES: settings.value(CARLA_KEY_CANVAS_USE_BEZIER_LINES, CARLA_DEFAULT_CANVAS_USE_BEZIER_LINES, bool),
962 CARLA_KEY_CANVAS_EYE_CANDY: settings.value(CARLA_KEY_CANVAS_EYE_CANDY, CARLA_DEFAULT_CANVAS_EYE_CANDY, bool),
963 CARLA_KEY_CANVAS_USE_OPENGL: settings.value(CARLA_KEY_CANVAS_USE_OPENGL, CARLA_DEFAULT_CANVAS_USE_OPENGL, bool),
964 CARLA_KEY_CANVAS_ANTIALIASING: settings.value(CARLA_KEY_CANVAS_ANTIALIASING, CARLA_DEFAULT_CANVAS_ANTIALIASING, int),
965 CARLA_KEY_CANVAS_HQ_ANTIALIASING: settings.value(CARLA_KEY_CANVAS_HQ_ANTIALIASING, CARLA_DEFAULT_CANVAS_HQ_ANTIALIASING, bool),
966 CARLA_KEY_CANVAS_FULL_REPAINTS: settings.value(CARLA_KEY_CANVAS_FULL_REPAINTS, CARLA_DEFAULT_CANVAS_FULL_REPAINTS, bool),
967 CARLA_KEY_CANVAS_INLINE_DISPLAYS: settings.value(CARLA_KEY_CANVAS_INLINE_DISPLAYS, CARLA_DEFAULT_CANVAS_INLINE_DISPLAYS, bool),
968 CARLA_KEY_CUSTOM_PAINTING: (settings.value(CARLA_KEY_MAIN_USE_PRO_THEME, true, bool) and
969 settings.value(CARLA_KEY_MAIN_PRO_THEME_COLOR, "Black", str).lower() == "black"),
970 }
971 */
972
973 const QSafeSettings settings2("falkTX", "Carla2");
974
975 if (host.experimental)
976 {
977 const bool visible = settings2.valueBool(CARLA_KEY_EXPERIMENTAL_JACK_APPS,
978 CARLA_DEFAULT_EXPERIMENTAL_JACK_APPS);
979 ui.act_plugin_add_jack->setVisible(visible);
980 }
981 else
982 {
983 ui.act_plugin_add_jack->setVisible(false);
984 }
985
986 fMiniCanvasUpdateTimeout = fSavedSettings._CARLA_KEY_CANVAS_FANCY_EYE_CANDY ? 1000 : 0;
987
988 setEngineSettings(host);
989 restartTimersIfNeeded();
990 }
991
enableTransportCarlaHostWindow::PrivateData992 void enableTransport(const bool enabled)
993 {
994 ui.group_transport_controls->setEnabled(enabled);
995 ui.group_transport_settings->setEnabled(enabled);
996 }
997
showSidePanelCarlaHostWindow::PrivateData998 void showSidePanel(const bool yesNo)
999 {
1000 ui.dockWidget->setEnabled(yesNo);
1001 ui.dockWidget->setVisible(yesNo);
1002 }
1003
showToolbarCarlaHostWindow::PrivateData1004 void showToolbar(const bool yesNo)
1005 {
1006 ui.toolBar->setEnabled(yesNo);
1007 ui.toolBar->setVisible(yesNo);
1008 }
1009
1010 //-----------------------------------------------------------------------------------------------------------------
1011 // Transport
1012
refreshTransportCarlaHostWindow::PrivateData1013 void refreshTransport(const bool forced = false)
1014 {
1015 if (! ui.l_transport_time->isVisible())
1016 return;
1017 if (carla_isZero(fSampleRate) or ! carla_is_engine_running(host.handle))
1018 return;
1019
1020 const CarlaTransportInfo* const timeInfo = carla_get_transport_info(host.handle);
1021 const bool playing = timeInfo->playing;
1022 const uint64_t frame = timeInfo->frame;
1023 const double bpm = timeInfo->bpm;
1024
1025 if (playing != fLastTransportState || forced)
1026 {
1027 if (playing)
1028 {
1029 const QIcon icon(":/16x16/media-playback-pause.svgz");
1030 ui.b_transport_play->setChecked(true);
1031 ui.b_transport_play->setIcon(icon);
1032 // ui.b_transport_play->setText(tr("&Pause"));
1033 }
1034 else
1035 {
1036 const QIcon icon(":/16x16/media-playback-start.svgz");
1037 ui.b_transport_play->setChecked(false);
1038 ui.b_transport_play->setIcon(icon);
1039 // ui.b_play->setText(tr("&Play"));
1040 }
1041
1042 fLastTransportState = playing;
1043 }
1044
1045 if (frame != fLastTransportFrame || forced)
1046 {
1047 fLastTransportFrame = frame;
1048
1049 const uint64_t time = frame / static_cast<uint32_t>(fSampleRate);
1050 const uint64_t secs = time % 60;
1051 const uint64_t mins = (time / 60) % 60;
1052 const uint64_t hrs = (time / 3600) % 60;
1053 ui.l_transport_time->setText(QString("%1:%2:%3").arg(hrs, 2, 10, QChar('0')).arg(mins, 2, 10, QChar('0')).arg(secs, 2, 10, QChar('0')));
1054
1055 const uint64_t frame1 = frame % 1000;
1056 const uint64_t frame2 = (frame / 1000) % 1000;
1057 const uint64_t frame3 = (frame / 1000000) % 1000;
1058 ui.l_transport_frame->setText(QString("%1'%2'%3").arg(frame3, 3, 10, QChar('0')).arg(frame2, 3, 10, QChar('0')).arg(frame1, 3, 10, QChar('0')));
1059
1060 const int32_t bar = timeInfo->bar;
1061 const int32_t beat = timeInfo->beat;
1062 const int32_t tick = timeInfo->tick;
1063 ui.l_transport_bbt->setText(QString("%1|%2|%3").arg(bar, 3, 10, QChar('0')).arg(beat, 2, 10, QChar('0')).arg(tick, 4, 10, QChar('0')));
1064 }
1065
1066 if (carla_isNotEqual(bpm, fLastTransportBPM) || forced)
1067 {
1068 fLastTransportBPM = bpm;
1069
1070 if (bpm > 0.0)
1071 {
1072 ui.dsb_transport_bpm->blockSignals(true);
1073 ui.dsb_transport_bpm->setValue(bpm);
1074 ui.dsb_transport_bpm->blockSignals(false);
1075 ui.dsb_transport_bpm->setStyleSheet("");
1076 }
1077 else
1078 {
1079 ui.dsb_transport_bpm->setStyleSheet("QDoubleSpinBox { color: palette(mid); }");
1080 }
1081 }
1082 }
1083
1084 //-----------------------------------------------------------------------------------------------------------------
1085 // Timers
1086
startTimersCarlaHostWindow::PrivateData1087 void startTimers()
1088 {
1089 if (fIdleTimerFast == 0)
1090 fIdleTimerFast = hostWindow->startTimer(fSavedSettings._CARLA_KEY_MAIN_REFRESH_INTERVAL);
1091
1092 if (fIdleTimerSlow == 0)
1093 fIdleTimerSlow = hostWindow->startTimer(fSavedSettings._CARLA_KEY_MAIN_REFRESH_INTERVAL*4);
1094 }
1095
restartTimersIfNeededCarlaHostWindow::PrivateData1096 void restartTimersIfNeeded()
1097 {
1098 if (fIdleTimerFast != 0)
1099 {
1100 hostWindow->killTimer(fIdleTimerFast);
1101 fIdleTimerFast = hostWindow->startTimer(fSavedSettings._CARLA_KEY_MAIN_REFRESH_INTERVAL);
1102 }
1103
1104 if (fIdleTimerSlow != 0)
1105 {
1106 hostWindow->killTimer(fIdleTimerSlow);
1107 fIdleTimerSlow = hostWindow->startTimer(fSavedSettings._CARLA_KEY_MAIN_REFRESH_INTERVAL*4);;
1108 }
1109 }
1110
killTimersCarlaHostWindow::PrivateData1111 void killTimers()
1112 {
1113 if (fIdleTimerFast != 0)
1114 {
1115 hostWindow->killTimer(fIdleTimerFast);
1116 fIdleTimerFast = 0;
1117 }
1118
1119 if (fIdleTimerSlow != 0)
1120 {
1121 hostWindow->killTimer(fIdleTimerSlow);
1122 fIdleTimerSlow = 0;
1123 }
1124 }
1125
1126 //-----------------------------------------------------------------------------------------------------------------
1127 // Internal stuff
1128
getExtraPtrCarlaHostWindow::PrivateData1129 void* getExtraPtr(/*self, plugin*/)
1130 {
1131 return nullptr;
1132 }
1133
maybeLoadRDFsCarlaHostWindow::PrivateData1134 void maybeLoadRDFs()
1135 {
1136 }
1137
1138 //-----------------------------------------------------------------------------------------------------------------
1139
1140 /*
1141 def getPluginCount(self):
1142 return self.fPluginCount
1143
1144 def getPluginItem(self, pluginId):
1145 if pluginId >= self.fPluginCount:
1146 return None
1147
1148 pitem = self.fPluginList[pluginId]
1149 if pitem is None:
1150 return None
1151 #if False:
1152 #return CarlaRackItem(self, 0, False)
1153
1154 return pitem
1155
1156 def getPluginEditDialog(self, pluginId):
1157 if pluginId >= self.fPluginCount:
1158 return None
1159
1160 pitem = self.fPluginList[pluginId]
1161 if pitem is None:
1162 return None
1163 if False:
1164 return PluginEdit(self, self.host, 0)
1165
1166 return pitem.getEditDialog()
1167
1168 def getPluginSlotWidget(self, pluginId):
1169 if pluginId >= self.fPluginCount:
1170 return None
1171
1172 pitem = self.fPluginList[pluginId]
1173 if pitem is None:
1174 return None
1175 #if False:
1176 #return AbstractPluginSlot()
1177
1178 return pitem.getWidget()
1179 */
1180
1181 //-----------------------------------------------------------------------------------------------------------------
1182 // timer event
1183
refreshRuntimeInfoCarlaHostWindow::PrivateData1184 void refreshRuntimeInfo(const float load, const uint xruns)
1185 {
1186 const QString txt1(xruns == 0 ? QString("%1").arg(xruns) : QString("--"));
1187 const QString txt2(xruns == 1 ? "" : "s");
1188 ui.b_xruns->setText(QString("%1 Xrun%2").arg(txt1).arg(txt2));
1189 ui.pb_dsp_load->setValue(int(load));
1190 }
1191
getAndRefreshRuntimeInfoCarlaHostWindow::PrivateData1192 void getAndRefreshRuntimeInfo()
1193 {
1194 if (! ui.pb_dsp_load->isVisible())
1195 return;
1196 if (! carla_is_engine_running(host.handle))
1197 return;
1198 const CarlaRuntimeEngineInfo* const info = carla_get_runtime_engine_info(host.handle);
1199 refreshRuntimeInfo(info->load, info->xruns);
1200 }
1201
idleFastCarlaHostWindow::PrivateData1202 void idleFast()
1203 {
1204 carla_engine_idle(host.handle);
1205 refreshTransport();
1206
1207 if (fPluginCount == 0 || fCurrentlyRemovingAllPlugins)
1208 return;
1209
1210 for (auto& pitem : fPluginList)
1211 {
1212 if (pitem == nullptr)
1213 break;
1214
1215 /*
1216 pitem->getWidget().idleFast();
1217 */
1218 }
1219
1220 for (uint pluginId : fSelectedPlugins)
1221 {
1222 fPeaksCleared = false;
1223 if (ui.peak_in->isVisible())
1224 {
1225 /*
1226 ui.peak_in->displayMeter(1, carla_get_input_peak_value(pluginId, true))
1227 ui.peak_in->displayMeter(2, carla_get_input_peak_value(pluginId, false))
1228 */
1229 }
1230 if (ui.peak_out->isVisible())
1231 {
1232 /*
1233 ui.peak_out->displayMeter(1, carla_get_output_peak_value(pluginId, true))
1234 ui.peak_out->displayMeter(2, carla_get_output_peak_value(pluginId, false))
1235 */
1236 }
1237 return;
1238 }
1239
1240 if (fPeaksCleared)
1241 return;
1242
1243 fPeaksCleared = true;
1244 /*
1245 ui.peak_in->displayMeter(1, 0.0, true);
1246 ui.peak_in->displayMeter(2, 0.0, true);
1247 ui.peak_out->displayMeter(1, 0.0, true);
1248 ui.peak_out->displayMeter(2, 0.0, true);
1249 */
1250 }
1251
idleSlowCarlaHostWindow::PrivateData1252 void idleSlow()
1253 {
1254 getAndRefreshRuntimeInfo();
1255
1256 if (fPluginCount == 0 || fCurrentlyRemovingAllPlugins)
1257 return;
1258
1259 for (auto& pitem : fPluginList)
1260 {
1261 if (pitem == nullptr)
1262 break;
1263
1264 /*
1265 pitem->getWidget().idleSlow();
1266 */
1267 }
1268 }
1269
1270 //-----------------------------------------------------------------------------------------------------------------
1271 // color/style change event
1272
updateStyleCarlaHostWindow::PrivateData1273 void updateStyle()
1274 {
1275 // Rack padding images setup
1276 QImage rack_imgL(":/bitmaps/rack_padding_left.png");
1277 QImage rack_imgR(":/bitmaps/rack_padding_right.png");
1278
1279 const qreal min_value = 0.07;
1280 #if QT_VERSION >= 0x50600
1281 const qreal value_fix = 1.0/(1.0-rack_imgL.scaled(1, 1, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).pixelColor(0,0).blackF());
1282 #else
1283 const qreal value_fix = 1.5;
1284 #endif
1285
1286 const QColor bg_color = ui.rack->palette().window().color();
1287 const qreal bg_value = 1.0 - bg_color.blackF();
1288
1289 QColor pad_color;
1290
1291 if (carla_isNotZero(bg_value) && bg_value < min_value)
1292 pad_color = bg_color.lighter(static_cast<int>(100*min_value/bg_value*value_fix));
1293 else
1294 pad_color = QColor::fromHsvF(0.0, 0.0, min_value*value_fix);
1295
1296 QPainter painter;
1297 QRect fillRect(rack_imgL.rect().adjusted(-1,-1,1,1));
1298
1299 painter.begin(&rack_imgL);
1300 painter.setCompositionMode(QPainter::CompositionMode_Multiply);
1301 painter.setBrush(pad_color);
1302 painter.drawRect(fillRect);
1303 painter.end();
1304
1305 const QPixmap rack_pixmapL(QPixmap::fromImage(rack_imgL));
1306 QPalette imgL_palette; //(ui.pad_left->palette());
1307 imgL_palette.setBrush(QPalette::Window, QBrush(rack_pixmapL));
1308 ui.pad_left->setPalette(imgL_palette);
1309 ui.pad_left->setAutoFillBackground(true);
1310
1311 painter.begin(&rack_imgR);
1312 painter.setCompositionMode(QPainter::CompositionMode_Multiply);
1313 painter.setBrush(pad_color);
1314 painter.drawRect(fillRect);
1315 painter.end();
1316
1317 const QPixmap rack_pixmapR(QPixmap::fromImage(rack_imgR));
1318 QPalette imgR_palette; //(ui.pad_right->palette());
1319 imgR_palette.setBrush(QPalette::Window, QBrush(rack_pixmapR));
1320 ui.pad_right->setPalette(imgR_palette);
1321 ui.pad_right->setAutoFillBackground(true);
1322 }
1323
1324 //-----------------------------------------------------------------------------------------------------------------
1325 // close event
1326
shouldIgnoreCloseCarlaHostWindow::PrivateData1327 bool shouldIgnoreClose()
1328 {
1329 if (host.isControl || host.isPlugin)
1330 return false;
1331 if (fCustomStopAction == CUSTOM_ACTION_APP_CLOSE)
1332 return false;
1333 if (fSavedSettings._CARLA_KEY_MAIN_CONFIRM_EXIT)
1334 return QMessageBox::question(hostWindow,
1335 tr("Quit"),
1336 tr("Are you sure you want to quit Carla?"),
1337 QMessageBox::Yes|QMessageBox::No) == QMessageBox::No;
1338 return false;
1339 }
1340
1341 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
1342 };
1343
1344 //---------------------------------------------------------------------------------------------------------------------
1345
CarlaHostWindow(CarlaHost & host,const bool withCanvas,QWidget * const parent)1346 CarlaHostWindow::CarlaHostWindow(CarlaHost& host, const bool withCanvas, QWidget* const parent)
1347 : QMainWindow(parent),
1348 self(new PrivateData(this, host, withCanvas))
1349 {
1350 gCarla.gui = this;
1351
1352 self->fIdleTimerNull = startTimer(1000);
1353
1354 //-----------------------------------------------------------------------------------------------------------------
1355 // Set-up Canvas
1356
1357 /*
1358 if (withCanvas)
1359 {
1360 self->scene = patchcanvas.PatchScene(self, self->ui.graphicsView);
1361 self->ui.graphicsView->setScene(self->scene);
1362
1363 if (self->fSavedSettings[CARLA_KEY_CANVAS_USE_OPENGL])
1364 {
1365 self->ui.glView = QGLWidget(self);
1366 self->ui.graphicsView.setViewport(self->ui.glView);
1367 }
1368
1369 setupCanvas();
1370 }
1371 */
1372
1373 //-----------------------------------------------------------------------------------------------------------------
1374 // Connect actions to functions
1375
1376 // TODO
1377
1378 connect(self->ui.act_file_new, SIGNAL(triggered()), SLOT(slot_fileNew()));
1379 connect(self->ui.act_file_open, SIGNAL(triggered()), SLOT(slot_fileOpen()));
1380 connect(self->ui.act_file_save, SIGNAL(triggered()), SLOT(slot_fileSave()));
1381 connect(self->ui.act_file_save_as, SIGNAL(triggered()), SLOT(slot_fileSaveAs()));
1382
1383 connect(self->ui.act_engine_start, SIGNAL(triggered()), SLOT(slot_engineStart()));
1384 connect(self->ui.act_engine_stop, SIGNAL(triggered()), SLOT(slot_engineStop()));
1385 connect(self->ui.act_engine_panic, SIGNAL(triggered()), SLOT(slot_pluginsDisable()));
1386 connect(self->ui.act_engine_config, SIGNAL(triggered()), SLOT(slot_engineConfig()));
1387
1388 connect(self->ui.act_plugin_add, SIGNAL(triggered()), SLOT(slot_pluginAdd()));
1389 connect(self->ui.act_plugin_add_jack, SIGNAL(triggered()), SLOT(slot_jackAppAdd()));
1390 connect(self->ui.act_plugin_remove_all, SIGNAL(triggered()), SLOT(slot_confirmRemoveAll()));
1391
1392 connect(self->ui.act_plugins_enable, SIGNAL(triggered()), SLOT(slot_pluginsEnable()));
1393 connect(self->ui.act_plugins_disable, SIGNAL(triggered()), SLOT(slot_pluginsDisable()));
1394 connect(self->ui.act_plugins_volume100, SIGNAL(triggered()), SLOT(slot_pluginsVolume100()));
1395 connect(self->ui.act_plugins_mute, SIGNAL(triggered()), SLOT(slot_pluginsMute()));
1396 connect(self->ui.act_plugins_wet100, SIGNAL(triggered()), SLOT(slot_pluginsWet100()));
1397 connect(self->ui.act_plugins_bypass, SIGNAL(triggered()), SLOT(slot_pluginsBypass()));
1398 connect(self->ui.act_plugins_center, SIGNAL(triggered()), SLOT(slot_pluginsCenter()));
1399 connect(self->ui.act_plugins_compact, SIGNAL(triggered()), SLOT(slot_pluginsCompact()));
1400 connect(self->ui.act_plugins_expand, SIGNAL(triggered()), SLOT(slot_pluginsExpand()));
1401
1402 connect(self->ui.act_settings_show_toolbar, SIGNAL(toggled(bool)), SLOT(slot_showToolbar(bool)));
1403 connect(self->ui.act_settings_show_meters, SIGNAL(toggled(bool)), SLOT(slot_showCanvasMeters(bool)));
1404 connect(self->ui.act_settings_show_keyboard, SIGNAL(toggled(bool)), SLOT(slot_showCanvasKeyboard(bool)));
1405 connect(self->ui.act_settings_show_side_panel, SIGNAL(toggled(bool)), SLOT(slot_showSidePanel(bool)));
1406 connect(self->ui.act_settings_configure, SIGNAL(triggered()), SLOT(slot_configureCarla()));
1407
1408 connect(self->ui.act_help_about, SIGNAL(triggered()), SLOT(slot_aboutCarla()));
1409 connect(self->ui.act_help_about_juce, SIGNAL(triggered()), SLOT(slot_aboutJuce()));
1410 connect(self->ui.act_help_about_qt, SIGNAL(triggered()), SLOT(slot_aboutQt()));
1411
1412 connect(self->ui.cb_disk, SIGNAL(currentIndexChanged(int)), SLOT(slot_diskFolderChanged(int)));
1413 connect(self->ui.b_disk_add, SIGNAL(clicked()), SLOT(slot_diskFolderAdd()));
1414 connect(self->ui.b_disk_remove, SIGNAL(clicked()), SLOT(slot_diskFolderRemove()));
1415 connect(self->ui.fileTreeView, SIGNAL(doubleClicked(QModelIndex*)), SLOT(slot_fileTreeDoubleClicked(QModelIndex*)));
1416
1417 connect(self->ui.b_transport_play, SIGNAL(clicked(bool)), SLOT(slot_transportPlayPause(bool)));
1418 connect(self->ui.b_transport_stop, SIGNAL(clicked()), SLOT(slot_transportStop()));
1419 connect(self->ui.b_transport_backwards, SIGNAL(clicked()), SLOT(slot_transportBackwards()));
1420 connect(self->ui.b_transport_forwards, SIGNAL(clicked()), SLOT(slot_transportForwards()));
1421 connect(self->ui.dsb_transport_bpm, SIGNAL(valueChanged(qreal)), SLOT(slot_transportBpmChanged(qreal)));
1422 connect(self->ui.cb_transport_jack, SIGNAL(clicked(bool)), SLOT(slot_transportJackEnabled(bool)));
1423 connect(self->ui.cb_transport_link, SIGNAL(clicked(bool)), SLOT(slot_transportLinkEnabled(bool)));
1424
1425 connect(self->ui.b_xruns, SIGNAL(clicked()), SLOT(slot_xrunClear()));
1426
1427 connect(self->ui.listWidget, SIGNAL(customContextMenuRequested()), SLOT(slot_showPluginActionsMenu()));
1428
1429 /*
1430 connect(self->ui.keyboard, SIGNAL(noteOn(int)), SLOT(slot_noteOn(int)));
1431 connect(self->ui.keyboard, SIGNAL(noteOff(int)), SLOT(slot_noteOff(int)));
1432 */
1433
1434 connect(self->ui.tabWidget, SIGNAL(currentChanged(int)), SLOT(slot_tabChanged(int)));
1435
1436 if (withCanvas)
1437 {
1438 connect(self->ui.act_canvas_show_internal, SIGNAL(triggered()), SLOT(slot_canvasShowInternal()));
1439 connect(self->ui.act_canvas_show_external, SIGNAL(triggered()), SLOT(slot_canvasShowExternal()));
1440 connect(self->ui.act_canvas_arrange, SIGNAL(triggered()), SLOT(slot_canvasArrange()));
1441 connect(self->ui.act_canvas_refresh, SIGNAL(triggered()), SLOT(slot_canvasRefresh()));
1442 connect(self->ui.act_canvas_zoom_fit, SIGNAL(triggered()), SLOT(slot_canvasZoomFit()));
1443 connect(self->ui.act_canvas_zoom_in, SIGNAL(triggered()), SLOT(slot_canvasZoomIn()));
1444 connect(self->ui.act_canvas_zoom_out, SIGNAL(triggered()), SLOT(slot_canvasZoomOut()));
1445 connect(self->ui.act_canvas_zoom_100, SIGNAL(triggered()), SLOT(slot_canvasZoomReset()));
1446 connect(self->ui.act_canvas_save_image, SIGNAL(triggered()), SLOT(slot_canvasSaveImage()));
1447 self->ui.act_canvas_arrange->setEnabled(false); // TODO, later
1448 connect(self->ui.graphicsView->horizontalScrollBar(), SIGNAL(valueChanged(int)), SLOT(slot_horizontalScrollBarChanged(int)));
1449 connect(self->ui.graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(slot_verticalScrollBarChanged(int)));
1450 /*
1451 connect(self->ui.miniCanvasPreview, SIGNAL(miniCanvasMoved(qreal, qreal)), SLOT(slot_miniCanvasMoved(qreal, qreal)));
1452 connect(self.scene, SIGNAL(scaleChanged()), SLOT(slot_canvasScaleChanged()));
1453 connect(self.scene, SIGNAL(sceneGroupMoved()), SLOT(slot_canvasItemMoved()));
1454 connect(self.scene, SIGNAL(pluginSelected()), SLOT(slot_canvasPluginSelected()));
1455 connect(self.scene, SIGNAL(selectionChanged()), SLOT(slot_canvasSelectionChanged()));
1456 */
1457 }
1458
1459 connect(&host, SIGNAL(SIGUSR1()), SLOT(slot_handleSIGUSR1()));
1460 connect(&host, SIGNAL(SIGTERM()), SLOT(slot_handleSIGTERM()));
1461
1462 connect(&host, SIGNAL(EngineStartedCallback(uint, int, int, uint, float, QString)), SLOT(slot_handleEngineStartedCallback(uint, int, int, uint, float, QString)));
1463 connect(&host, SIGNAL(EngineStoppedCallback()), SLOT(slot_handleEngineStoppedCallback()));
1464 connect(&host, SIGNAL(TransportModeChangedCallback()), SLOT(slot_handleTransportModeChangedCallback()));
1465 connect(&host, SIGNAL(BufferSizeChangedCallback()), SLOT(slot_handleBufferSizeChangedCallback()));
1466 connect(&host, SIGNAL(SampleRateChangedCallback()), SLOT(slot_handleSampleRateChangedCallback()));
1467 connect(&host, SIGNAL(CancelableActionCallback()), SLOT(slot_handleCancelableActionCallback()));
1468 connect(&host, SIGNAL(ProjectLoadFinishedCallback()), SLOT(slot_handleProjectLoadFinishedCallback()));
1469
1470 connect(&host, SIGNAL(PluginAddedCallback()), SLOT(slot_handlePluginAddedCallback()));
1471 connect(&host, SIGNAL(PluginRemovedCallback()), SLOT(slot_handlePluginRemovedCallback()));
1472 connect(&host, SIGNAL(ReloadAllCallback()), SLOT(slot_handleReloadAllCallback()));
1473
1474 connect(&host, SIGNAL(NoteOnCallback()), SLOT(slot_handleNoteOnCallback()));
1475 connect(&host, SIGNAL(NoteOffCallback()), SLOT(slot_handleNoteOffCallback()));
1476
1477 connect(&host, SIGNAL(UpdateCallback()), SLOT(slot_handleUpdateCallback()));
1478
1479 connect(&host, SIGNAL(PatchbayClientAddedCallback()), SLOT(slot_handlePatchbayClientAddedCallback()));
1480 connect(&host, SIGNAL(PatchbayClientRemovedCallback()), SLOT(slot_handlePatchbayClientRemovedCallback()));
1481 connect(&host, SIGNAL(PatchbayClientRenamedCallback()), SLOT(slot_handlePatchbayClientRenamedCallback()));
1482 connect(&host, SIGNAL(PatchbayClientDataChangedCallback()), SLOT(slot_handlePatchbayClientDataChangedCallback()));
1483 connect(&host, SIGNAL(PatchbayPortAddedCallback()), SLOT(slot_handlePatchbayPortAddedCallback()));
1484 connect(&host, SIGNAL(PatchbayPortRemovedCallback()), SLOT(slot_handlePatchbayPortRemovedCallback()));
1485 connect(&host, SIGNAL(PatchbayPortChangedCallback()), SLOT(slot_handlePatchbayPortChangedCallback()));
1486 connect(&host, SIGNAL(PatchbayPortGroupAddedCallback()), SLOT(slot_handlePatchbayPortGroupAddedCallback()));
1487 connect(&host, SIGNAL(PatchbayPortGroupRemovedCallback()), SLOT(slot_handlePatchbayPortGroupRemovedCallback()));
1488 connect(&host, SIGNAL(PatchbayPortGroupChangedCallback()), SLOT(slot_handlePatchbayPortGroupChangedCallback()));
1489
1490 connect(&host, SIGNAL(PatchbayConnectionAddedCallback()), SLOT(slot_handlePatchbayConnectionAddedCallback()));
1491 connect(&host, SIGNAL(PatchbayConnectionRemovedCallback()), SLOT(slot_handlePatchbayConnectionRemovedCallback()));
1492
1493 connect(&host, SIGNAL(NSMCallback()), SLOT(slot_handleNSMCallback()));
1494
1495 connect(&host, SIGNAL(DebugCallback()), SLOT(slot_handleDebugCallback()));
1496 connect(&host, SIGNAL(InfoCallback()), SLOT(slot_handleInfoCallback()));
1497 connect(&host, SIGNAL(ErrorCallback()), SLOT(slot_handleErrorCallback()));
1498 connect(&host, SIGNAL(QuitCallback()), SLOT(slot_handleQuitCallback()));
1499 connect(&host, SIGNAL(InlineDisplayRedrawCallback()), SLOT(slot_handleInlineDisplayRedrawCallback()));
1500
1501 //-----------------------------------------------------------------------------------------------------------------
1502 // Final setup
1503
1504 // Qt needs this so it properly creates & resizes the canvas
1505 self->ui.tabWidget->blockSignals(true);
1506 self->ui.tabWidget->setCurrentIndex(1);
1507 self->ui.tabWidget->setCurrentIndex(0);
1508 self->ui.tabWidget->blockSignals(false);
1509
1510 // Start in patchbay tab if using forced patchbay mode
1511 if (host.processModeForced && host.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
1512 self->ui.tabWidget->setCurrentIndex(1);
1513
1514 // For NSM we wait for the open message
1515 if (NSM_URL != nullptr && host.nsmOK)
1516 {
1517 carla_nsm_ready(host.handle, NSM_CALLBACK_INIT);
1518 return;
1519 }
1520
1521 if (! host.isControl)
1522 QTimer::singleShot(0, this, SLOT(slot_engineStart()));
1523 }
1524
~CarlaHostWindow()1525 CarlaHostWindow::~CarlaHostWindow()
1526 {
1527 delete self;
1528 }
1529
1530 //---------------------------------------------------------------------------------------------------------------------
1531 // Plugin Editor Parent
1532
editDialogVisibilityChanged(int pluginId,bool visible)1533 void CarlaHostWindow::editDialogVisibilityChanged(int pluginId, bool visible)
1534 {
1535 }
1536
editDialogPluginHintsChanged(int pluginId,int hints)1537 void CarlaHostWindow::editDialogPluginHintsChanged(int pluginId, int hints)
1538 {
1539 }
1540
editDialogParameterValueChanged(int pluginId,int parameterId,float value)1541 void CarlaHostWindow::editDialogParameterValueChanged(int pluginId, int parameterId, float value)
1542 {
1543 }
1544
editDialogProgramChanged(int pluginId,int index)1545 void CarlaHostWindow::editDialogProgramChanged(int pluginId, int index)
1546 {
1547 }
1548
editDialogMidiProgramChanged(int pluginId,int index)1549 void CarlaHostWindow::editDialogMidiProgramChanged(int pluginId, int index)
1550 {
1551 }
1552
editDialogNotePressed(int pluginId,int note)1553 void CarlaHostWindow::editDialogNotePressed(int pluginId, int note)
1554 {
1555 }
1556
editDialogNoteReleased(int pluginId,int note)1557 void CarlaHostWindow::editDialogNoteReleased(int pluginId, int note)
1558 {
1559 }
1560
editDialogMidiActivityChanged(int pluginId,bool onOff)1561 void CarlaHostWindow::editDialogMidiActivityChanged(int pluginId, bool onOff)
1562 {
1563 }
1564
1565 //---------------------------------------------------------------------------------------------------------------------
1566 // show/hide event
1567
showEvent(QShowEvent * event)1568 void CarlaHostWindow::showEvent(QShowEvent* event)
1569 {
1570 QMainWindow::showEvent(event);
1571 }
1572
hideEvent(QHideEvent * event)1573 void CarlaHostWindow::hideEvent(QHideEvent* event)
1574 {
1575 QMainWindow::hideEvent(event);
1576 }
1577
1578 //---------------------------------------------------------------------------------------------------------------------
1579 // resize event
1580
resizeEvent(QResizeEvent * event)1581 void CarlaHostWindow::resizeEvent(QResizeEvent* event)
1582 {
1583 QMainWindow::resizeEvent(event);
1584 }
1585
1586 //---------------------------------------------------------------------------------------------------------------------
1587 // timer event
1588
timerEvent(QTimerEvent * const event)1589 void CarlaHostWindow::timerEvent(QTimerEvent* const event)
1590 {
1591 if (event->timerId() == self->fIdleTimerFast)
1592 self->idleFast();
1593
1594 else if (event->timerId() == self->fIdleTimerSlow)
1595 self->idleSlow();
1596
1597 QMainWindow::timerEvent(event);
1598 }
1599
1600 //---------------------------------------------------------------------------------------------------------------------
1601 // color/style change event
1602
changeEvent(QEvent * const event)1603 void CarlaHostWindow::changeEvent(QEvent* const event)
1604 {
1605 switch (event->type())
1606 {
1607 case QEvent::PaletteChange:
1608 case QEvent::StyleChange:
1609 self->updateStyle();
1610 break;
1611 default:
1612 break;
1613 }
1614
1615 QMainWindow::changeEvent(event);
1616 }
1617
1618 //---------------------------------------------------------------------------------------------------------------------
1619 // close event
1620
closeEvent(QCloseEvent * const event)1621 void CarlaHostWindow::closeEvent(QCloseEvent* const event)
1622 {
1623 if (self->shouldIgnoreClose())
1624 {
1625 event->ignore();
1626 return;
1627 }
1628
1629 #ifdef CARLA_OS_MAC
1630 if (self->fMacClosingHelper && ! (self->host.isControl || self->host.isPlugin))
1631 {
1632 self->fCustomStopAction = CUSTOM_ACTION_APP_CLOSE;
1633 self->fMacClosingHelper = false;
1634 event->ignore();
1635
1636 for i in reversed(range(self->fPluginCount)):
1637 carla_show_custom_ui(self->host.handle, i, false);
1638
1639 QTimer::singleShot(100, SIGNAL(close()));
1640 return;
1641 }
1642 #endif
1643
1644 self->killTimers();
1645 self->saveSettings();
1646
1647 if (carla_is_engine_running(self->host.handle) && ! (self->host.isControl or self->host.isPlugin))
1648 {
1649 if (! slot_engineStop(true))
1650 {
1651 self->fCustomStopAction = CUSTOM_ACTION_APP_CLOSE;
1652 event->ignore();
1653 return;
1654 }
1655 }
1656
1657 QMainWindow::closeEvent(event);
1658 }
1659
1660 //---------------------------------------------------------------------------------------------------------------------
1661 // Files (menu actions)
1662
slot_fileNew()1663 void CarlaHostWindow::slot_fileNew()
1664 {
1665 }
1666
slot_fileOpen()1667 void CarlaHostWindow::slot_fileOpen()
1668 {
1669 }
1670
slot_fileSave(const bool saveAs)1671 void CarlaHostWindow::slot_fileSave(const bool saveAs)
1672 {
1673 }
1674
slot_fileSaveAs()1675 void CarlaHostWindow::slot_fileSaveAs()
1676 {
1677 }
1678
slot_loadProjectNow()1679 void CarlaHostWindow::slot_loadProjectNow()
1680 {
1681 }
1682
1683 //---------------------------------------------------------------------------------------------------------------------
1684 // Engine (menu actions)
1685
slot_engineStart()1686 void CarlaHostWindow::slot_engineStart()
1687 {
1688 const QString audioDriver = setEngineSettings(self->host);
1689 const bool firstInit = self->fFirstEngineInit;
1690
1691 self->fFirstEngineInit = false;
1692 self->ui.text_logs->appendPlainText("======= Starting engine =======");
1693
1694 if (carla_engine_init(self->host.handle, audioDriver.toUtf8(), self->fClientName.toUtf8()))
1695 {
1696 if (firstInit && ! (self->host.isControl or self->host.isPlugin))
1697 {
1698 QSafeSettings settings;
1699 const double lastBpm = settings.valueDouble("LastBPM", 120.0);
1700 if (lastBpm >= 20.0)
1701 carla_transport_bpm(self->host.handle, lastBpm);
1702 }
1703 return;
1704 }
1705 else if (firstInit)
1706 {
1707 self->ui.text_logs->appendPlainText("Failed to start engine on first try, ignored");
1708 return;
1709 }
1710
1711 const QCarlaString audioError(carla_get_last_error(self->host.handle));
1712
1713 if (audioError.isNotEmpty())
1714 {
1715 QMessageBox::critical(this,
1716 tr("Error"),
1717 tr("Could not connect to Audio backend '%1', possible reasons:\n%2").arg(audioDriver).arg(audioError));
1718 }
1719 else
1720 {
1721 QMessageBox::critical(this,
1722 tr("Error"),
1723 tr("Could not connect to Audio backend '%1'").arg(audioDriver));
1724 }
1725 }
1726
slot_engineStop(const bool forced)1727 bool CarlaHostWindow::slot_engineStop(const bool forced)
1728 {
1729 self->ui.text_logs->appendPlainText("======= Stopping engine =======");
1730
1731 if (self->fPluginCount == 0)
1732 {
1733 self->engineStopFinal();
1734 return true;
1735 }
1736
1737 if (! forced)
1738 {
1739 const QMessageBox::StandardButton ask = QMessageBox::question(this,
1740 tr("Warning"),
1741 tr("There are still some plugins loaded, you need to remove them to stop the engine.\n"
1742 "Do you want to do this now?"),
1743 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
1744
1745 if (ask != QMessageBox::Yes)
1746 return false;
1747 }
1748
1749 return slot_engineStopTryAgain();
1750 }
1751
slot_engineConfig()1752 void CarlaHostWindow::slot_engineConfig()
1753 {
1754 RuntimeDriverSettingsW dialog(self->host.handle, self->fParentOrSelf);
1755
1756 if (dialog.exec())
1757 return;
1758
1759 QString audioDevice;
1760 uint bufferSize;
1761 double sampleRate;
1762 dialog.getValues(audioDevice, bufferSize, sampleRate);
1763
1764 if (carla_is_engine_running(self->host.handle))
1765 {
1766 carla_set_engine_buffer_size_and_sample_rate(self->host.handle, bufferSize, sampleRate);
1767 }
1768 else
1769 {
1770 carla_set_engine_option(self->host.handle, ENGINE_OPTION_AUDIO_DEVICE, 0, audioDevice.toUtf8());
1771 carla_set_engine_option(self->host.handle, ENGINE_OPTION_AUDIO_BUFFER_SIZE, static_cast<int>(bufferSize), "");
1772 carla_set_engine_option(self->host.handle, ENGINE_OPTION_AUDIO_SAMPLE_RATE, static_cast<int>(sampleRate), "");
1773 }
1774 }
1775
slot_engineStopTryAgain()1776 bool CarlaHostWindow::slot_engineStopTryAgain()
1777 {
1778 if (carla_is_engine_running(self->host.handle) && ! carla_set_engine_about_to_close(self->host.handle))
1779 {
1780 QTimer::singleShot(0, this, SLOT(slot_engineStopTryAgain()));
1781 return false;
1782 }
1783
1784 self->engineStopFinal();
1785 return true;
1786 }
1787
1788 //---------------------------------------------------------------------------------------------------------------------
1789 // Engine (host callbacks)
1790
slot_handleEngineStartedCallback(uint pluginCount,int processMode,int transportMode,uint bufferSize,float sampleRate,QString driverName)1791 void CarlaHostWindow::slot_handleEngineStartedCallback(uint pluginCount, int processMode, int transportMode, uint bufferSize, float sampleRate, QString driverName)
1792 {
1793 self->ui.menu_PluginMacros->setEnabled(true);
1794 self->ui.menu_Canvas->setEnabled(true);
1795 self->ui.w_transport->setEnabled(true);
1796
1797 self->ui.act_canvas_show_internal->blockSignals(true);
1798 self->ui.act_canvas_show_external->blockSignals(true);
1799
1800 if (processMode == ENGINE_PROCESS_MODE_PATCHBAY) // && ! self->host.isPlugin:
1801 {
1802 self->ui.act_canvas_show_internal->setChecked(true);
1803 self->ui.act_canvas_show_internal->setVisible(true);
1804 self->ui.act_canvas_show_external->setChecked(false);
1805 self->ui.act_canvas_show_external->setVisible(true);
1806 self->fExternalPatchbay = false;
1807 }
1808 else
1809 {
1810 self->ui.act_canvas_show_internal->setChecked(false);
1811 self->ui.act_canvas_show_internal->setVisible(false);
1812 self->ui.act_canvas_show_external->setChecked(true);
1813 self->ui.act_canvas_show_external->setVisible(false);
1814 self->fExternalPatchbay = true;
1815 }
1816
1817 self->ui.act_canvas_show_internal->blockSignals(false);
1818 self->ui.act_canvas_show_external->blockSignals(false);
1819
1820 if (! (self->host.isControl or self->host.isPlugin))
1821 {
1822 const bool canSave = (self->fProjectFilename.isNotEmpty() && QFile(self->fProjectFilename).exists()) || self->fSessionManagerName.isEmpty();
1823 self->ui.act_file_save->setEnabled(canSave);
1824 self->ui.act_engine_start->setEnabled(false);
1825 self->ui.act_engine_stop->setEnabled(true);
1826 }
1827
1828 if (! self->host.isPlugin)
1829 self->enableTransport(transportMode != ENGINE_TRANSPORT_MODE_DISABLED);
1830
1831 if (self->host.isPlugin || self->fSessionManagerName.isEmpty())
1832 {
1833 self->ui.act_file_open->setEnabled(true);
1834 self->ui.act_file_save_as->setEnabled(true);
1835 }
1836
1837 self->ui.cb_transport_jack->setChecked(transportMode == ENGINE_TRANSPORT_MODE_JACK);
1838 self->ui.cb_transport_jack->setEnabled(driverName == "JACK" and processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS);
1839
1840 if (self->ui.cb_transport_link->isEnabled())
1841 self->ui.cb_transport_link->setChecked(self->host.transportExtra.contains(":link:"));
1842
1843 self->updateBufferSize(bufferSize);
1844 self->updateSampleRate(sampleRate);
1845 self->refreshRuntimeInfo(0.0, 0);
1846 self->startTimers();
1847
1848 self->ui.text_logs->appendPlainText("======= Engine started ========");
1849 self->ui.text_logs->appendPlainText("Carla engine started, details:");
1850 self->ui.text_logs->appendPlainText(QString(" Driver name: %1").arg(driverName));
1851 self->ui.text_logs->appendPlainText(QString(" Sample rate: %1").arg(int(sampleRate)));
1852 self->ui.text_logs->appendPlainText(QString(" Process mode: %1").arg(EngineProcessMode2Str((EngineProcessMode)processMode)));
1853 }
1854
slot_handleEngineStoppedCallback()1855 void CarlaHostWindow::slot_handleEngineStoppedCallback()
1856 {
1857 self->ui.text_logs->appendPlainText("======= Engine stopped ========");
1858
1859 /*
1860 // TODO
1861 patchcanvas.clear();
1862 */
1863 self->killTimers();
1864
1865 // just in case
1866 self->removeAllPlugins();
1867 self->refreshRuntimeInfo(0.0, 0);
1868
1869 self->ui.menu_PluginMacros->setEnabled(false);
1870 self->ui.menu_Canvas->setEnabled(false);
1871 self->ui.w_transport->setEnabled(false);
1872
1873 if (! (self->host.isControl || self->host.isPlugin))
1874 {
1875 self->ui.act_file_save->setEnabled(false);
1876 self->ui.act_engine_start->setEnabled(true);
1877 self->ui.act_engine_stop->setEnabled(false);
1878 }
1879
1880 if (self->host.isPlugin || self->fSessionManagerName.isEmpty())
1881 {
1882 self->ui.act_file_open->setEnabled(false);
1883 self->ui.act_file_save_as->setEnabled(false);
1884 }
1885 }
1886
slot_handleTransportModeChangedCallback(int transportMode,QString transportExtra)1887 void CarlaHostWindow::slot_handleTransportModeChangedCallback(int transportMode, QString transportExtra)
1888 {
1889 }
1890
slot_handleBufferSizeChangedCallback(int newBufferSize)1891 void CarlaHostWindow::slot_handleBufferSizeChangedCallback(int newBufferSize)
1892 {
1893 }
1894
slot_handleSampleRateChangedCallback(double newSampleRate)1895 void CarlaHostWindow::slot_handleSampleRateChangedCallback(double newSampleRate)
1896 {
1897 }
1898
slot_handleCancelableActionCallback(int pluginId,bool started,QString action)1899 void CarlaHostWindow::slot_handleCancelableActionCallback(int pluginId, bool started, QString action)
1900 {
1901 }
1902
slot_canlableActionBoxClicked()1903 void CarlaHostWindow::slot_canlableActionBoxClicked()
1904 {
1905 }
1906
slot_handleProjectLoadFinishedCallback()1907 void CarlaHostWindow::slot_handleProjectLoadFinishedCallback()
1908 {
1909 }
1910
1911 //---------------------------------------------------------------------------------------------------------------------
1912 // Plugins (menu actions)
1913
slot_favoritePluginAdd()1914 void CarlaHostWindow::slot_favoritePluginAdd()
1915 {
1916 }
1917
slot_showPluginActionsMenu()1918 void CarlaHostWindow::slot_showPluginActionsMenu()
1919 {
1920 }
1921
slot_pluginAdd()1922 void CarlaHostWindow::slot_pluginAdd()
1923 {
1924 }
1925
slot_confirmRemoveAll()1926 void CarlaHostWindow::slot_confirmRemoveAll()
1927 {
1928 }
1929
slot_jackAppAdd()1930 void CarlaHostWindow::slot_jackAppAdd()
1931 {
1932 }
1933
1934 //---------------------------------------------------------------------------------------------------------------------
1935 // Plugins (macros)
1936
slot_pluginsEnable()1937 void CarlaHostWindow::slot_pluginsEnable()
1938 {
1939 }
1940
slot_pluginsDisable()1941 void CarlaHostWindow::slot_pluginsDisable()
1942 {
1943 }
1944
slot_pluginsVolume100()1945 void CarlaHostWindow::slot_pluginsVolume100()
1946 {
1947 }
1948
slot_pluginsMute()1949 void CarlaHostWindow::slot_pluginsMute()
1950 {
1951 }
1952
slot_pluginsWet100()1953 void CarlaHostWindow::slot_pluginsWet100()
1954 {
1955 }
1956
slot_pluginsBypass()1957 void CarlaHostWindow::slot_pluginsBypass()
1958 {
1959 }
1960
slot_pluginsCenter()1961 void CarlaHostWindow::slot_pluginsCenter()
1962 {
1963 }
1964
slot_pluginsCompact()1965 void CarlaHostWindow::slot_pluginsCompact()
1966 {
1967 }
1968
slot_pluginsExpand()1969 void CarlaHostWindow::slot_pluginsExpand()
1970 {
1971 }
1972
1973 //---------------------------------------------------------------------------------------------------------------------
1974 // Plugins (host callbacks)
1975
slot_handlePluginAddedCallback(int pluginId,QString pluginName)1976 void CarlaHostWindow::slot_handlePluginAddedCallback(int pluginId, QString pluginName)
1977 {
1978 }
1979
slot_handlePluginRemovedCallback(int pluginId)1980 void CarlaHostWindow::slot_handlePluginRemovedCallback(int pluginId)
1981 {
1982 }
1983
1984 //---------------------------------------------------------------------------------------------------------------------
1985 // Canvas (menu actions)
1986
slot_canvasShowInternal()1987 void CarlaHostWindow::slot_canvasShowInternal()
1988 {
1989 }
1990
slot_canvasShowExternal()1991 void CarlaHostWindow::slot_canvasShowExternal()
1992 {
1993 }
1994
slot_canvasArrange()1995 void CarlaHostWindow::slot_canvasArrange()
1996 {
1997 }
1998
slot_canvasRefresh()1999 void CarlaHostWindow::slot_canvasRefresh()
2000 {
2001 }
2002
slot_canvasZoomFit()2003 void CarlaHostWindow::slot_canvasZoomFit()
2004 {
2005 }
2006
slot_canvasZoomIn()2007 void CarlaHostWindow::slot_canvasZoomIn()
2008 {
2009 }
2010
slot_canvasZoomOut()2011 void CarlaHostWindow::slot_canvasZoomOut()
2012 {
2013 }
2014
slot_canvasZoomReset()2015 void CarlaHostWindow::slot_canvasZoomReset()
2016 {
2017 }
2018
slot_canvasSaveImage()2019 void CarlaHostWindow::slot_canvasSaveImage()
2020 {
2021 }
2022
2023 //---------------------------------------------------------------------------------------------------------------------
2024 // Canvas (canvas callbacks)
2025
slot_canvasItemMoved(int group_id,int split_mode,QPointF pos)2026 void CarlaHostWindow::slot_canvasItemMoved(int group_id, int split_mode, QPointF pos)
2027 {
2028 }
2029
slot_canvasSelectionChanged()2030 void CarlaHostWindow::slot_canvasSelectionChanged()
2031 {
2032 }
2033
slot_canvasScaleChanged(double scale)2034 void CarlaHostWindow::slot_canvasScaleChanged(double scale)
2035 {
2036 }
2037
slot_canvasPluginSelected(QList<void * > pluginList)2038 void CarlaHostWindow::slot_canvasPluginSelected(QList<void*> pluginList)
2039 {
2040 }
2041
2042 //---------------------------------------------------------------------------------------------------------------------
2043 // Canvas (host callbacks)
2044
slot_handlePatchbayClientAddedCallback(int clientId,int clientIcon,int pluginId,QString clientName)2045 void CarlaHostWindow::slot_handlePatchbayClientAddedCallback(int clientId, int clientIcon, int pluginId, QString clientName)
2046 {
2047 }
2048
slot_handlePatchbayClientRemovedCallback(int clientId)2049 void CarlaHostWindow::slot_handlePatchbayClientRemovedCallback(int clientId)
2050 {
2051 }
2052
slot_handlePatchbayClientRenamedCallback(int clientId,QString newClientName)2053 void CarlaHostWindow::slot_handlePatchbayClientRenamedCallback(int clientId, QString newClientName)
2054 {
2055 }
2056
slot_handlePatchbayClientDataChangedCallback(int clientId,int clientIcon,int pluginId)2057 void CarlaHostWindow::slot_handlePatchbayClientDataChangedCallback(int clientId, int clientIcon, int pluginId)
2058 {
2059 }
2060
slot_handlePatchbayPortAddedCallback(int clientId,int portId,int portFlags,int portGroupId,QString portName)2061 void CarlaHostWindow::slot_handlePatchbayPortAddedCallback(int clientId, int portId, int portFlags, int portGroupId, QString portName)
2062 {
2063 }
2064
slot_handlePatchbayPortRemovedCallback(int groupId,int portId)2065 void CarlaHostWindow::slot_handlePatchbayPortRemovedCallback(int groupId, int portId)
2066 {
2067 }
2068
slot_handlePatchbayPortChangedCallback(int groupId,int portId,int portFlags,int portGroupId,QString newPortName)2069 void CarlaHostWindow::slot_handlePatchbayPortChangedCallback(int groupId, int portId, int portFlags, int portGroupId, QString newPortName)
2070 {
2071 }
2072
slot_handlePatchbayPortGroupAddedCallback(int groupId,int portId,int portGroupId,QString newPortName)2073 void CarlaHostWindow::slot_handlePatchbayPortGroupAddedCallback(int groupId, int portId, int portGroupId, QString newPortName)
2074 {
2075 }
2076
slot_handlePatchbayPortGroupRemovedCallback(int groupId,int portId)2077 void CarlaHostWindow::slot_handlePatchbayPortGroupRemovedCallback(int groupId, int portId)
2078 {
2079 }
2080
slot_handlePatchbayPortGroupChangedCallback(int groupId,int portId,int portGroupId,QString newPortName)2081 void CarlaHostWindow::slot_handlePatchbayPortGroupChangedCallback(int groupId, int portId, int portGroupId, QString newPortName)
2082 {
2083 }
2084
slot_handlePatchbayConnectionAddedCallback(int connectionId,int groupOutId,int portOutId,int groupInId,int portInId)2085 void CarlaHostWindow::slot_handlePatchbayConnectionAddedCallback(int connectionId, int groupOutId, int portOutId, int groupInId, int portInId)
2086 {
2087 }
2088
slot_handlePatchbayConnectionRemovedCallback(int connectionId,int portOutId,int portInId)2089 void CarlaHostWindow::slot_handlePatchbayConnectionRemovedCallback(int connectionId, int portOutId, int portInId)
2090 {
2091 }
2092
2093 //---------------------------------------------------------------------------------------------------------------------
2094 // Settings (helpers)
2095
slot_restoreCanvasScrollbarValues()2096 void CarlaHostWindow::slot_restoreCanvasScrollbarValues()
2097 {
2098 }
2099
2100 //---------------------------------------------------------------------------------------------------------------------
2101 // Settings (menu actions)
2102
slot_showSidePanel(const bool yesNo)2103 void CarlaHostWindow::slot_showSidePanel(const bool yesNo)
2104 {
2105 self->showSidePanel(yesNo);
2106 }
2107
slot_showToolbar(const bool yesNo)2108 void CarlaHostWindow::slot_showToolbar(const bool yesNo)
2109 {
2110 self->showToolbar(yesNo);
2111 }
2112
slot_showCanvasMeters(const bool yesNo)2113 void CarlaHostWindow::slot_showCanvasMeters(const bool yesNo)
2114 {
2115 self->ui.peak_in->setVisible(yesNo);
2116 self->ui.peak_out->setVisible(yesNo);
2117 QTimer::singleShot(0, this, SLOT(slot_miniCanvasCheckAll()));
2118 }
2119
slot_showCanvasKeyboard(const bool yesNo)2120 void CarlaHostWindow::slot_showCanvasKeyboard(const bool yesNo)
2121 {
2122 /*
2123 // TODO
2124 self->ui.scrollArea->setVisible(yesNo);
2125 */
2126 QTimer::singleShot(0, this, SLOT(slot_miniCanvasCheckAll()));
2127 }
2128
slot_configureCarla()2129 void CarlaHostWindow::slot_configureCarla()
2130 {
2131 const bool hasGL = true;
2132 CarlaSettingsW dialog(self->fParentOrSelf, self->host, true, hasGL);
2133 if (! dialog.exec())
2134 return;
2135
2136 self->loadSettings(false);
2137
2138 /*
2139 // TODO
2140 patchcanvas.clear()
2141
2142 setupCanvas();
2143 */
2144 slot_miniCanvasCheckAll();
2145
2146 if (self->host.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && self->host.isPlugin)
2147 pass();
2148 else if (carla_is_engine_running(self->host.handle))
2149 carla_patchbay_refresh(self->host.handle, self->fExternalPatchbay);
2150 }
2151
2152 //---------------------------------------------------------------------------------------------------------------------
2153 // About (menu actions)
2154
slot_aboutCarla()2155 void CarlaHostWindow::slot_aboutCarla()
2156 {
2157 CarlaAboutW(self->fParentOrSelf, self->host).exec();
2158 }
2159
slot_aboutJuce()2160 void CarlaHostWindow::slot_aboutJuce()
2161 {
2162 JuceAboutW(self->fParentOrSelf).exec();
2163 }
2164
slot_aboutQt()2165 void CarlaHostWindow::slot_aboutQt()
2166 {
2167 qApp->aboutQt();
2168 }
2169
2170 //---------------------------------------------------------------------------------------------------------------------
2171 // Disk (menu actions)
2172
slot_diskFolderChanged(int index)2173 void CarlaHostWindow::slot_diskFolderChanged(int index)
2174 {
2175 }
2176
slot_diskFolderAdd()2177 void CarlaHostWindow::slot_diskFolderAdd()
2178 {
2179 }
2180
slot_diskFolderRemove()2181 void CarlaHostWindow::slot_diskFolderRemove()
2182 {
2183 }
2184
slot_fileTreeDoubleClicked(QModelIndex * modelIndex)2185 void CarlaHostWindow::slot_fileTreeDoubleClicked(QModelIndex* modelIndex)
2186 {
2187 }
2188
2189 //---------------------------------------------------------------------------------------------------------------------
2190 // Transport (menu actions)
2191
slot_transportPlayPause(const bool toggled)2192 void CarlaHostWindow::slot_transportPlayPause(const bool toggled)
2193 {
2194 if (self->host.isPlugin || ! carla_is_engine_running(self->host.handle))
2195 return;
2196
2197 if (toggled)
2198 carla_transport_play(self->host.handle);
2199 else
2200 carla_transport_pause(self->host.handle);
2201
2202 self->refreshTransport();
2203 }
2204
slot_transportStop()2205 void CarlaHostWindow::slot_transportStop()
2206 {
2207 if (self->host.isPlugin || ! carla_is_engine_running(self->host.handle))
2208 return;
2209
2210 carla_transport_pause(self->host.handle);
2211 carla_transport_relocate(self->host.handle, 0);
2212
2213 self->refreshTransport();
2214 }
2215
slot_transportBackwards()2216 void CarlaHostWindow::slot_transportBackwards()
2217 {
2218 if (self->host.isPlugin || ! carla_is_engine_running(self->host.handle))
2219 return;
2220
2221 uint64_t newFrame = carla_get_current_transport_frame(self->host.handle);
2222
2223 if (newFrame > 100000)
2224 newFrame -= 100000;
2225 else
2226 newFrame = 0;
2227
2228 carla_transport_relocate(self->host.handle, newFrame);
2229 }
2230
slot_transportBpmChanged(const qreal newValue)2231 void CarlaHostWindow::slot_transportBpmChanged(const qreal newValue)
2232 {
2233 carla_transport_bpm(self->host.handle, newValue);
2234 }
2235
slot_transportForwards()2236 void CarlaHostWindow::slot_transportForwards()
2237 {
2238 if (carla_isZero(self->fSampleRate) || self->host.isPlugin || ! carla_is_engine_running(self->host.handle))
2239 return;
2240
2241 const uint64_t newFrame = carla_get_current_transport_frame(self->host.handle) + uint64_t(self->fSampleRate*2.5);
2242 carla_transport_relocate(self->host.handle, newFrame);
2243 }
2244
slot_transportJackEnabled(const bool clicked)2245 void CarlaHostWindow::slot_transportJackEnabled(const bool clicked)
2246 {
2247 if (! carla_is_engine_running(self->host.handle))
2248 return;
2249 self->host.transportMode = clicked ? ENGINE_TRANSPORT_MODE_JACK : ENGINE_TRANSPORT_MODE_INTERNAL;
2250 carla_set_engine_option(self->host.handle, ENGINE_OPTION_TRANSPORT_MODE, self->host.transportMode, self->host.transportExtra.toUtf8());
2251 }
2252
slot_transportLinkEnabled(const bool clicked)2253 void CarlaHostWindow::slot_transportLinkEnabled(const bool clicked)
2254 {
2255 if (! carla_is_engine_running(self->host.handle))
2256 return;
2257 const char* const extra = clicked ? ":link:" : "";
2258 self->host.transportExtra = extra;
2259 carla_set_engine_option(self->host.handle, ENGINE_OPTION_TRANSPORT_MODE, self->host.transportMode, self->host.transportExtra.toUtf8());
2260 }
2261
2262 //---------------------------------------------------------------------------------------------------------------------
2263 // Other
2264
slot_xrunClear()2265 void CarlaHostWindow::slot_xrunClear()
2266 {
2267 carla_clear_engine_xruns(self->host.handle);
2268 }
2269
2270 //---------------------------------------------------------------------------------------------------------------------
2271 // Canvas scrollbars
2272
slot_horizontalScrollBarChanged(int value)2273 void CarlaHostWindow::slot_horizontalScrollBarChanged(int value)
2274 {
2275 }
2276
slot_verticalScrollBarChanged(int value)2277 void CarlaHostWindow::slot_verticalScrollBarChanged(int value)
2278 {
2279 }
2280
2281 //---------------------------------------------------------------------------------------------------------------------
2282 // Canvas keyboard
2283
slot_noteOn(int note)2284 void CarlaHostWindow::slot_noteOn(int note)
2285 {
2286 }
2287
slot_noteOff(int note)2288 void CarlaHostWindow::slot_noteOff(int note)
2289 {
2290 }
2291
2292
2293 //---------------------------------------------------------------------------------------------------------------------
2294 // Canvas keyboard (host callbacks)
2295
slot_handleNoteOnCallback(int pluginId,int channel,int note,int velocity)2296 void CarlaHostWindow::slot_handleNoteOnCallback(int pluginId, int channel, int note, int velocity)
2297 {
2298 }
2299
slot_handleNoteOffCallback(int pluginId,int channel,int note)2300 void CarlaHostWindow::slot_handleNoteOffCallback(int pluginId, int channel, int note)
2301 {
2302 }
2303
2304 //---------------------------------------------------------------------------------------------------------------------
2305
slot_handleUpdateCallback(int pluginId)2306 void CarlaHostWindow::slot_handleUpdateCallback(int pluginId)
2307 {
2308 }
2309
2310 //---------------------------------------------------------------------------------------------------------------------
2311 // MiniCanvas stuff
2312
slot_miniCanvasCheckAll()2313 void CarlaHostWindow::slot_miniCanvasCheckAll()
2314 {
2315 }
2316
slot_miniCanvasCheckSize()2317 void CarlaHostWindow::slot_miniCanvasCheckSize()
2318 {
2319 }
2320
slot_miniCanvasMoved(qreal xp,qreal yp)2321 void CarlaHostWindow::slot_miniCanvasMoved(qreal xp, qreal yp)
2322 {
2323 }
2324
2325 //---------------------------------------------------------------------------------------------------------------------
2326 // Misc
2327
slot_tabChanged(int index)2328 void CarlaHostWindow::slot_tabChanged(int index)
2329 {
2330 }
2331
slot_handleReloadAllCallback(int pluginId)2332 void CarlaHostWindow::slot_handleReloadAllCallback(int pluginId)
2333 {
2334 }
2335
2336 //---------------------------------------------------------------------------------------------------------------------
2337
slot_handleNSMCallback(int opcode,int valueInt,QString valueStr)2338 void CarlaHostWindow::slot_handleNSMCallback(int opcode, int valueInt, QString valueStr)
2339 {
2340 }
2341
2342 //---------------------------------------------------------------------------------------------------------------------
2343
slot_handleDebugCallback(int pluginId,int value1,int value2,int value3,float valuef,QString valueStr)2344 void CarlaHostWindow::slot_handleDebugCallback(int pluginId, int value1, int value2, int value3, float valuef, QString valueStr)
2345 {
2346 }
2347
slot_handleInfoCallback(QString info)2348 void CarlaHostWindow::slot_handleInfoCallback(QString info)
2349 {
2350 }
2351
slot_handleErrorCallback(QString error)2352 void CarlaHostWindow::slot_handleErrorCallback(QString error)
2353 {
2354 }
2355
slot_handleQuitCallback()2356 void CarlaHostWindow::slot_handleQuitCallback()
2357 {
2358 }
2359
slot_handleInlineDisplayRedrawCallback(int pluginId)2360 void CarlaHostWindow::slot_handleInlineDisplayRedrawCallback(int pluginId)
2361 {
2362 }
2363
2364 //---------------------------------------------------------------------------------------------------------------------
2365
slot_handleSIGUSR1()2366 void CarlaHostWindow::slot_handleSIGUSR1()
2367 {
2368 }
2369
slot_handleSIGTERM()2370 void CarlaHostWindow::slot_handleSIGTERM()
2371 {
2372 }
2373
2374 //---------------------------------------------------------------------------------------------------------------------
2375 // Canvas callback
2376
2377 /*
2378 static void _canvasCallback(void* const ptr, const int action, int value1, int value2, QString valueStr)
2379 {
2380 CarlaHost* const host = (CarlaHost*)(ptr);
2381 CARLA_SAFE_ASSERT_RETURN(host != nullptr,);
2382
2383 switch (action)
2384 {
2385 }
2386 }
2387 */
2388
2389 //---------------------------------------------------------------------------------------------------------------------
2390 // Engine callback
2391
_engineCallback(void * const ptr,const EngineCallbackOpcode action,uint pluginId,int value1,int value2,int value3,float valuef,const char * const valueStr)2392 static void _engineCallback(void* const ptr, const EngineCallbackOpcode action, uint pluginId, int value1, int value2, int value3, float valuef, const char* const valueStr)
2393 {
2394 /*
2395 carla_stdout("_engineCallback(%p, %i:%s, %u, %i, %i, %i, %f, %s)",
2396 ptr, action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, valuef, valueStr);
2397 */
2398
2399 CarlaHost* const host = (CarlaHost*)(ptr);
2400 CARLA_SAFE_ASSERT_RETURN(host != nullptr,);
2401
2402 switch (action)
2403 {
2404 case ENGINE_CALLBACK_ENGINE_STARTED:
2405 host->processMode = static_cast<EngineProcessMode>(value1);
2406 host->transportMode = static_cast<EngineTransportMode>(value2);
2407 break;
2408 case ENGINE_CALLBACK_PROCESS_MODE_CHANGED:
2409 host->processMode = static_cast<EngineProcessMode>(value1);
2410 break;
2411 case ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED:
2412 host->transportMode = static_cast<EngineTransportMode>(value1);
2413 host->transportExtra = valueStr;
2414 break;
2415 default:
2416 break;
2417 }
2418
2419 // TODO
2420 switch (action)
2421 {
2422 case ENGINE_CALLBACK_ENGINE_STARTED:
2423 CARLA_SAFE_ASSERT_INT_RETURN(value3 >= 0, value3,);
2424 emit host->EngineStartedCallback(pluginId, value1, value2, static_cast<uint>(value3), valuef, valueStr);
2425 break;
2426 case ENGINE_CALLBACK_ENGINE_STOPPED:
2427 emit host->EngineStoppedCallback();
2428 break;
2429
2430 // FIXME
2431 default:
2432 break;
2433 }
2434 }
2435
2436 //---------------------------------------------------------------------------------------------------------------------
2437 // File callback
2438
_fileCallback(void *,const FileCallbackOpcode action,const bool isDir,const char * const title,const char * const filter)2439 static const char* _fileCallback(void*, const FileCallbackOpcode action, const bool isDir, const char* const title, const char* const filter)
2440 {
2441 QString ret;
2442 const QFileDialog::Options options = QFileDialog::Options(isDir ? QFileDialog::ShowDirsOnly : 0x0);
2443
2444 switch (action)
2445 {
2446 case FILE_CALLBACK_DEBUG:
2447 break;
2448 case FILE_CALLBACK_OPEN:
2449 ret = QFileDialog::getOpenFileName(gCarla.gui, title, "", filter, nullptr, options);
2450 break;
2451 case FILE_CALLBACK_SAVE:
2452 ret = QFileDialog::getSaveFileName(gCarla.gui, title, "", filter, nullptr, options);
2453 break;
2454 }
2455
2456 if (ret.isEmpty())
2457 return nullptr;
2458
2459 static QByteArray byteRet;
2460 byteRet = ret.toUtf8();
2461
2462 return byteRet.constData();
2463 }
2464
2465 //---------------------------------------------------------------------------------------------------------------------
2466 // Init host
2467
initHost(const QString initName,const bool isControl,const bool isPlugin,const bool failError)2468 CarlaHost& initHost(const QString initName, const bool isControl, const bool isPlugin, const bool failError)
2469 {
2470 QString pathBinaries, pathResources;
2471 getPaths(pathBinaries, pathResources);
2472
2473 //-----------------------------------------------------------------------------------------------------------------
2474 // Fail if binary dir is not found
2475
2476 if (! QDir(pathBinaries).exists())
2477 {
2478 if (failError)
2479 {
2480 QMessageBox::critical(nullptr, "Error", "Failed to find the carla binaries, cannot continue");
2481 std::exit(1);
2482 }
2483 // FIXME?
2484 // return;
2485 }
2486
2487 //-----------------------------------------------------------------------------------------------------------------
2488 // Print info
2489
2490 carla_stdout(QString("Carla %1 started, status:").arg(CARLA_VERSION_STRING).toUtf8());
2491 carla_stdout(QString(" Qt version: %1").arg(QT_VERSION_STR).toUtf8());
2492 carla_stdout(QString(" Binary dir: %1").arg(pathBinaries).toUtf8());
2493 carla_stdout(QString(" Resources dir: %1").arg(pathResources).toUtf8());
2494
2495 // ----------------------------------------------------------------------------------------------------------------
2496 // Init host
2497
2498 // TODO
2499 if (failError)
2500 {
2501 // # no try
2502 // host = HostClass() if HostClass is not None else CarlaHostQtDLL(libname, loadGlobal)
2503 }
2504 else
2505 {
2506 // try:
2507 // host = HostClass() if HostClass is not None else CarlaHostQtDLL(libname, loadGlobal)
2508 // except:
2509 // host = CarlaHostQtNull()
2510 }
2511
2512 static CarlaHost host;
2513 host.isControl = isControl;
2514 host.isPlugin = isPlugin;
2515
2516 // TODO
2517 if (isPlugin)
2518 pass();
2519 else if (isControl)
2520 pass();
2521 else
2522 host.handle = carla_standalone_host_init();
2523
2524 carla_set_engine_callback(host.handle, _engineCallback, &host);
2525 carla_set_file_callback(host.handle, _fileCallback, nullptr);
2526
2527 // If it's a plugin the paths are already set
2528 if (! isPlugin)
2529 {
2530 host.pathBinaries = pathBinaries;
2531 host.pathResources = pathResources;
2532 carla_set_engine_option(host.handle, ENGINE_OPTION_PATH_BINARIES, 0, pathBinaries.toUtf8());
2533 carla_set_engine_option(host.handle, ENGINE_OPTION_PATH_RESOURCES, 0, pathResources.toUtf8());
2534
2535 if (! isControl)
2536 {
2537 const pid_t pid = getpid();
2538 if (pid > 0)
2539 host.nsmOK = carla_nsm_init(host.handle, static_cast<uint64_t>(pid), initName.toUtf8());
2540 }
2541 }
2542
2543 // ----------------------------------------------------------------------------------------------------------------
2544 // Done
2545
2546 gCarla.host = &host;
2547 return host;
2548 }
2549
2550 //---------------------------------------------------------------------------------------------------------------------
2551 // Load host settings
2552
loadHostSettings(CarlaHost & host)2553 void loadHostSettings(CarlaHost& host)
2554 {
2555 const QSafeSettings settings("falkTX", "Carla2");
2556
2557 host.experimental = settings.valueBool(CARLA_KEY_MAIN_EXPERIMENTAL, CARLA_DEFAULT_MAIN_EXPERIMENTAL);
2558 host.exportLV2 = settings.valueBool(CARLA_KEY_EXPERIMENTAL_EXPORT_LV2, CARLA_DEFAULT_EXPERIMENTAL_LV2_EXPORT);
2559 host.manageUIs = settings.valueBool(CARLA_KEY_ENGINE_MANAGE_UIS, CARLA_DEFAULT_MANAGE_UIS);
2560 host.maxParameters = settings.valueUInt(CARLA_KEY_ENGINE_MAX_PARAMETERS, CARLA_DEFAULT_MAX_PARAMETERS);
2561 host.resetXruns = settings.valueBool(CARLA_KEY_ENGINE_RESET_XRUNS, CARLA_DEFAULT_RESET_XRUNS);
2562 host.forceStereo = settings.valueBool(CARLA_KEY_ENGINE_FORCE_STEREO, CARLA_DEFAULT_FORCE_STEREO);
2563 host.preferPluginBridges = settings.valueBool(CARLA_KEY_ENGINE_PREFER_PLUGIN_BRIDGES, CARLA_DEFAULT_PREFER_PLUGIN_BRIDGES);
2564 host.preferUIBridges = settings.valueBool(CARLA_KEY_ENGINE_PREFER_UI_BRIDGES, CARLA_DEFAULT_PREFER_UI_BRIDGES);
2565 host.preventBadBehaviour = settings.valueBool(CARLA_KEY_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR, CARLA_DEFAULT_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR);
2566 host.showLogs = settings.valueBool(CARLA_KEY_MAIN_SHOW_LOGS, CARLA_DEFAULT_MAIN_SHOW_LOGS);
2567 host.showPluginBridges = settings.valueBool(CARLA_KEY_EXPERIMENTAL_PLUGIN_BRIDGES, CARLA_DEFAULT_EXPERIMENTAL_PLUGIN_BRIDGES);
2568 host.showWineBridges = settings.valueBool(CARLA_KEY_EXPERIMENTAL_WINE_BRIDGES, CARLA_DEFAULT_EXPERIMENTAL_WINE_BRIDGES);
2569 host.uiBridgesTimeout = settings.valueUInt(CARLA_KEY_ENGINE_UI_BRIDGES_TIMEOUT, CARLA_DEFAULT_UI_BRIDGES_TIMEOUT);
2570 host.uisAlwaysOnTop = settings.valueBool(CARLA_KEY_ENGINE_UIS_ALWAYS_ON_TOP, CARLA_DEFAULT_UIS_ALWAYS_ON_TOP);
2571
2572 if (host.isPlugin)
2573 return;
2574
2575 host.transportExtra = settings.valueString(CARLA_KEY_ENGINE_TRANSPORT_EXTRA, "");
2576
2577 // enums
2578 /*
2579 // TODO
2580 if (host.audioDriverForced.isNotEmpty())
2581 host.transportMode = settings.valueUInt(CARLA_KEY_ENGINE_TRANSPORT_MODE, CARLA_DEFAULT_TRANSPORT_MODE);
2582
2583 if (! host.processModeForced)
2584 host.processMode = settings.valueUInt(CARLA_KEY_ENGINE_PROCESS_MODE, CARLA_DEFAULT_PROCESS_MODE);
2585 */
2586
2587 host.nextProcessMode = host.processMode;
2588
2589 // ----------------------------------------------------------------------------------------------------------------
2590 // fix things if needed
2591
2592 if (host.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
2593 {
2594 if (LADISH_APP_NAME)
2595 {
2596 carla_stdout("LADISH detected but using multiple clients (not allowed), forcing single client now");
2597 host.nextProcessMode = host.processMode = ENGINE_PROCESS_MODE_SINGLE_CLIENT;
2598 }
2599 else
2600 {
2601 host.transportMode = ENGINE_TRANSPORT_MODE_JACK;
2602 }
2603 }
2604
2605 if (gCarla.nogui)
2606 host.showLogs = false;
2607
2608 // ----------------------------------------------------------------------------------------------------------------
2609 // run headless host now if nogui option enabled
2610
2611 if (gCarla.nogui)
2612 runHostWithoutUI(host);
2613 }
2614
2615 //---------------------------------------------------------------------------------------------------------------------
2616 // Set host settings
2617
setHostSettings(const CarlaHost & host)2618 void setHostSettings(const CarlaHost& host)
2619 {
2620 carla_set_engine_option(host.handle, ENGINE_OPTION_FORCE_STEREO, host.forceStereo, "");
2621 carla_set_engine_option(host.handle, ENGINE_OPTION_MAX_PARAMETERS, static_cast<int>(host.maxParameters), "");
2622 carla_set_engine_option(host.handle, ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, host.preferPluginBridges, "");
2623 carla_set_engine_option(host.handle, ENGINE_OPTION_PREFER_UI_BRIDGES, host.preferUIBridges, "");
2624 carla_set_engine_option(host.handle, ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, host.preventBadBehaviour, "");
2625 carla_set_engine_option(host.handle, ENGINE_OPTION_UI_BRIDGES_TIMEOUT, host.uiBridgesTimeout, "");
2626 carla_set_engine_option(host.handle, ENGINE_OPTION_UIS_ALWAYS_ON_TOP, host.uisAlwaysOnTop, "");
2627
2628 if (host.isPlugin || host.isRemote || carla_is_engine_running(host.handle))
2629 return;
2630
2631 carla_set_engine_option(host.handle, ENGINE_OPTION_PROCESS_MODE, host.nextProcessMode, "");
2632 carla_set_engine_option(host.handle, ENGINE_OPTION_TRANSPORT_MODE, host.transportMode, host.transportExtra.toUtf8());
2633 carla_set_engine_option(host.handle, ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT, host.showLogs, "");
2634 }
2635
2636 //---------------------------------------------------------------------------------------------------------------------
2637 // Set Engine settings according to carla preferences. Returns selected audio driver.
2638
setEngineSettings(CarlaHost & host)2639 QString setEngineSettings(CarlaHost& host)
2640 {
2641 //-----------------------------------------------------------------------------------------------------------------
2642 // do nothing if control
2643
2644 if (host.isControl)
2645 return "Control";
2646
2647 //-----------------------------------------------------------------------------------------------------------------
2648
2649 const QSafeSettings settings("falkTX", "Carla2");
2650
2651 //-----------------------------------------------------------------------------------------------------------------
2652 // main settings
2653
2654 setHostSettings(host);
2655
2656 //-----------------------------------------------------------------------------------------------------------------
2657 // file paths
2658
2659 QStringList FILE_PATH_AUDIO = settings.valueStringList(CARLA_KEY_PATHS_AUDIO, CARLA_DEFAULT_FILE_PATH_AUDIO);
2660 QStringList FILE_PATH_MIDI = settings.valueStringList(CARLA_KEY_PATHS_MIDI, CARLA_DEFAULT_FILE_PATH_MIDI);
2661
2662 /*
2663 // TODO
2664 carla_set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_AUDIO, splitter.join(FILE_PATH_AUDIO));
2665 carla_set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_MIDI, splitter.join(FILE_PATH_MIDI));
2666 */
2667 // CARLA_PATH_SPLITTER
2668
2669 //-----------------------------------------------------------------------------------------------------------------
2670 // plugin paths
2671
2672 QStringList LADSPA_PATH = settings.valueStringList(CARLA_KEY_PATHS_LADSPA, CARLA_DEFAULT_LADSPA_PATH);
2673 QStringList DSSI_PATH = settings.valueStringList(CARLA_KEY_PATHS_DSSI, CARLA_DEFAULT_DSSI_PATH);
2674 QStringList LV2_PATH = settings.valueStringList(CARLA_KEY_PATHS_LV2, CARLA_DEFAULT_LV2_PATH);
2675 QStringList VST2_PATH = settings.valueStringList(CARLA_KEY_PATHS_VST2, CARLA_DEFAULT_VST2_PATH);
2676 QStringList VST3_PATH = settings.valueStringList(CARLA_KEY_PATHS_VST3, CARLA_DEFAULT_VST3_PATH);
2677 QStringList SF2_PATH = settings.valueStringList(CARLA_KEY_PATHS_SF2, CARLA_DEFAULT_SF2_PATH);
2678 QStringList SFZ_PATH = settings.valueStringList(CARLA_KEY_PATHS_SFZ, CARLA_DEFAULT_SFZ_PATH);
2679
2680 /*
2681 // TODO
2682 carla_set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LADSPA, splitter.join(LADSPA_PATH))
2683 carla_set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_DSSI, splitter.join(DSSI_PATH))
2684 carla_set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2, splitter.join(LV2_PATH))
2685 carla_set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_VST2, splitter.join(VST2_PATH))
2686 carla_set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_VST3, splitter.join(VST3_PATH))
2687 carla_set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SF2, splitter.join(SF2_PATH))
2688 carla_set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SFZ, splitter.join(SFZ_PATH))
2689 */
2690
2691 //-----------------------------------------------------------------------------------------------------------------
2692 // don't continue if plugin
2693
2694 if (host.isPlugin)
2695 return "Plugin";
2696
2697 //-----------------------------------------------------------------------------------------------------------------
2698 // osc settings
2699
2700 const bool oscEnabled = settings.valueBool(CARLA_KEY_OSC_ENABLED, CARLA_DEFAULT_OSC_ENABLED);
2701
2702 int portNumTCP, portNumUDP;
2703
2704 if (! settings.valueBool(CARLA_KEY_OSC_TCP_PORT_ENABLED, CARLA_DEFAULT_OSC_TCP_PORT_ENABLED))
2705 portNumTCP = -1;
2706 else if (settings.valueBool(CARLA_KEY_OSC_TCP_PORT_RANDOM, CARLA_DEFAULT_OSC_TCP_PORT_RANDOM))
2707 portNumTCP = 0;
2708 else
2709 portNumTCP = settings.valueIntPositive(CARLA_KEY_OSC_TCP_PORT_NUMBER, CARLA_DEFAULT_OSC_TCP_PORT_NUMBER);
2710
2711 if (! settings.valueBool(CARLA_KEY_OSC_UDP_PORT_ENABLED, CARLA_DEFAULT_OSC_UDP_PORT_ENABLED))
2712 portNumUDP = -1;
2713 else if (settings.valueBool(CARLA_KEY_OSC_UDP_PORT_RANDOM, CARLA_DEFAULT_OSC_UDP_PORT_RANDOM))
2714 portNumUDP = 0;
2715 else
2716 portNumUDP = settings.valueIntPositive(CARLA_KEY_OSC_UDP_PORT_NUMBER, CARLA_DEFAULT_OSC_UDP_PORT_NUMBER);
2717
2718 carla_set_engine_option(host.handle, ENGINE_OPTION_OSC_ENABLED, oscEnabled ? 1 : 0, "");
2719 carla_set_engine_option(host.handle, ENGINE_OPTION_OSC_PORT_TCP, portNumTCP, "");
2720 carla_set_engine_option(host.handle, ENGINE_OPTION_OSC_PORT_UDP, portNumUDP, "");
2721
2722 //-----------------------------------------------------------------------------------------------------------------
2723 // wine settings
2724
2725 const QString optWineExecutable = settings.valueString(CARLA_KEY_WINE_EXECUTABLE, CARLA_DEFAULT_WINE_EXECUTABLE);
2726 const bool optWineAutoPrefix = settings.valueBool(CARLA_KEY_WINE_AUTO_PREFIX, CARLA_DEFAULT_WINE_AUTO_PREFIX);
2727 const QString optWineFallbackPrefix = settings.valueString(CARLA_KEY_WINE_FALLBACK_PREFIX, CARLA_DEFAULT_WINE_FALLBACK_PREFIX);
2728 const bool optWineRtPrioEnabled = settings.valueBool(CARLA_KEY_WINE_RT_PRIO_ENABLED, CARLA_DEFAULT_WINE_RT_PRIO_ENABLED);
2729 const int optWineBaseRtPrio = settings.valueIntPositive(CARLA_KEY_WINE_BASE_RT_PRIO, CARLA_DEFAULT_WINE_BASE_RT_PRIO);
2730 const int optWineServerRtPrio = settings.valueIntPositive(CARLA_KEY_WINE_SERVER_RT_PRIO, CARLA_DEFAULT_WINE_SERVER_RT_PRIO);
2731
2732 carla_set_engine_option(host.handle, ENGINE_OPTION_WINE_EXECUTABLE, 0, optWineExecutable.toUtf8());
2733 carla_set_engine_option(host.handle, ENGINE_OPTION_WINE_AUTO_PREFIX, optWineAutoPrefix ? 1 : 0, "");
2734 /*
2735 // TODO
2736 carla_set_engine_option(host.handle, ENGINE_OPTION_WINE_FALLBACK_PREFIX, 0, os.path.expanduser(optWineFallbackPrefix));
2737 */
2738 carla_set_engine_option(host.handle, ENGINE_OPTION_WINE_RT_PRIO_ENABLED, optWineRtPrioEnabled ? 1 : 0, "");
2739 carla_set_engine_option(host.handle, ENGINE_OPTION_WINE_BASE_RT_PRIO, optWineBaseRtPrio, "");
2740 carla_set_engine_option(host.handle, ENGINE_OPTION_WINE_SERVER_RT_PRIO, optWineServerRtPrio, "");
2741
2742 //-----------------------------------------------------------------------------------------------------------------
2743 // driver and device settings
2744
2745 QString audioDriver;
2746
2747 // driver name
2748 if (host.audioDriverForced.isNotEmpty())
2749 audioDriver = host.audioDriverForced;
2750 else
2751 audioDriver = settings.valueString(CARLA_KEY_ENGINE_AUDIO_DRIVER, CARLA_DEFAULT_AUDIO_DRIVER);
2752
2753 // driver options
2754 const QString prefix(QString("%1%2").arg(CARLA_KEY_ENGINE_DRIVER_PREFIX).arg(audioDriver));
2755 const QString audioDevice = settings.valueString(QString("%1/Device").arg(prefix), "");
2756 const int audioBufferSize = settings.valueIntPositive(QString("%1/BufferSize").arg(prefix), CARLA_DEFAULT_AUDIO_BUFFER_SIZE);
2757 const int audioSampleRate = settings.valueIntPositive(QString("%1/SampleRate").arg(prefix), CARLA_DEFAULT_AUDIO_SAMPLE_RATE);
2758 const bool audioTripleBuffer = settings.valueBool(QString("%1/TripleBuffer").arg(prefix), CARLA_DEFAULT_AUDIO_TRIPLE_BUFFER);
2759
2760 // Only setup audio things if engine is not running
2761 if (! carla_is_engine_running(host.handle))
2762 {
2763 carla_set_engine_option(host.handle, ENGINE_OPTION_AUDIO_DRIVER, 0, audioDriver.toUtf8());
2764 carla_set_engine_option(host.handle, ENGINE_OPTION_AUDIO_DEVICE, 0, audioDevice.toUtf8());
2765
2766 if (! audioDriver.startsWith("JACK"))
2767 {
2768 carla_set_engine_option(host.handle, ENGINE_OPTION_AUDIO_BUFFER_SIZE, audioBufferSize, "");
2769 carla_set_engine_option(host.handle, ENGINE_OPTION_AUDIO_SAMPLE_RATE, audioSampleRate, "");
2770 carla_set_engine_option(host.handle, ENGINE_OPTION_AUDIO_TRIPLE_BUFFER, audioTripleBuffer ? 1 : 0, "");
2771 }
2772 }
2773
2774 //-----------------------------------------------------------------------------------------------------------------
2775 // fix things if needed
2776
2777 if (audioDriver != "JACK" && host.transportMode == ENGINE_TRANSPORT_MODE_JACK)
2778 {
2779 host.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL;
2780 carla_set_engine_option(host.handle,
2781 ENGINE_OPTION_TRANSPORT_MODE,
2782 ENGINE_TRANSPORT_MODE_INTERNAL,
2783 host.transportExtra.toUtf8());
2784 }
2785
2786 //-----------------------------------------------------------------------------------------------------------------
2787 // return selected driver name
2788
2789 return audioDriver;
2790 }
2791
2792 //---------------------------------------------------------------------------------------------------------------------
2793 // Run Carla without showing UI
2794
runHostWithoutUI(CarlaHost & host)2795 void runHostWithoutUI(CarlaHost& host)
2796 {
2797 //-----------------------------------------------------------------------------------------------------------------
2798 // Some initial checks
2799
2800 if (! gCarla.nogui)
2801 return;
2802
2803 const QString projectFile = getInitialProjectFile(true);
2804
2805 if (projectFile.isEmpty())
2806 {
2807 carla_stdout("Carla no-gui mode can only be used together with a project file.");
2808 std::exit(1);
2809 }
2810
2811 //-----------------------------------------------------------------------------------------------------------------
2812 // Init engine
2813
2814 const QString audioDriver = setEngineSettings(host);
2815
2816 if (! carla_engine_init(host.handle, audioDriver.toUtf8(), "Carla"))
2817 {
2818 carla_stdout("Engine failed to initialize, possible reasons:\n%s", carla_get_last_error(host.handle));
2819 std::exit(1);
2820 }
2821
2822 if (! carla_load_project(host.handle, projectFile.toUtf8()))
2823 {
2824 carla_stdout("Failed to load selected project file, possible reasons:\n%s", carla_get_last_error(host.handle));
2825 carla_engine_close(host.handle);
2826 std::exit(1);
2827 }
2828
2829 //-----------------------------------------------------------------------------------------------------------------
2830 // Idle
2831
2832 carla_stdout("Carla ready!");
2833
2834 while (carla_is_engine_running(host.handle) && ! gCarla.term)
2835 {
2836 carla_engine_idle(host.handle);
2837 carla_msleep(33); // 30 Hz
2838 }
2839
2840 //-----------------------------------------------------------------------------------------------------------------
2841 // Stop
2842
2843 carla_engine_close(host.handle);
2844 std::exit(0);
2845 }
2846
2847 //---------------------------------------------------------------------------------------------------------------------
2848