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