1 /*
2  * Carla settings code
3  * Copyright (C) 2011-2019 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_settings.hpp"
19 
20 //---------------------------------------------------------------------------------------------------------------------
21 // Imports (Global)
22 
23 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
24 # pragma GCC diagnostic push
25 # pragma GCC diagnostic ignored "-Wconversion"
26 # pragma GCC diagnostic ignored "-Weffc++"
27 # pragma GCC diagnostic ignored "-Wsign-conversion"
28 #endif
29 
30 // --------------------------------------------------------------------------------------------------------------------
31 
32 #include <QtCore/QStringList>
33 
34 #include <QtWidgets/QFileDialog>
35 
36 // --------------------------------------------------------------------------------------------------------------------
37 
38 #include "ui_carla_settings.hpp"
39 #include "ui_carla_settings_driver.hpp"
40 
41 // --------------------------------------------------------------------------------------------------------------------
42 
43 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
44 # pragma GCC diagnostic pop
45 #endif
46 
47 //---------------------------------------------------------------------------------------------------------------------
48 // Imports (Custom)
49 
50 #include "carla_host.hpp"
51 #include "patchcanvas/theme.hpp"
52 
53 #include "CarlaHost.h"
54 #include "CarlaMathUtils.hpp"
55 
56 // --------------------------------------------------------------------------------------------------------------------
57 
58 static const char* const AUTOMATIC_OPTION = "(Auto)";
59 
60 static const QList<uint> BUFFER_SIZE_LIST = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
61 static const QList<double> SAMPLE_RATE_LIST = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000 };
62 
63 CARLA_BACKEND_USE_NAMESPACE;
64 
65 // --------------------------------------------------------------------------------------------------------------------
66 // Driver Settings
67 
68 struct DriverSettingsW::PrivateData {
69     Ui::DriverSettingsW ui;
70 
71     uint fDriverIndex;
72     QString fDriverName;
73     QStringList fDeviceNames;
74 
75     QList<uint> fBufferSizes;
76     QList<double> fSampleRates;
77 
PrivateDataDriverSettingsW::PrivateData78     PrivateData(DriverSettingsW* const self, const uint driverIndex, const QString driverName)
79         : ui(),
80           fDriverIndex(driverIndex),
81           fDriverName(driverName),
82           fDeviceNames(),
83           fBufferSizes(BUFFER_SIZE_LIST),
84           fSampleRates(SAMPLE_RATE_LIST)
85     {
86         ui.setupUi(self);
87 
88         const char* const* const deviceNames = carla_get_engine_driver_device_names(driverIndex);
89         CARLA_SAFE_ASSERT_RETURN(deviceNames != nullptr,);
90 
91         fillQStringListFromStringArray(fDeviceNames, deviceNames);
92     }
93 
loadSettingsDriverSettingsW::PrivateData94     void loadSettings(DriverSettingsW* const self)
95     {
96         const QSafeSettings settings("falkTX", "Carla2");
97 
98         const QString prefix(QString("%1%2").arg(CARLA_KEY_ENGINE_DRIVER_PREFIX).arg(fDriverName));
99 
100         const QCarlaString audioDevice       = settings.valueString(QString("%1/Device").arg(prefix), "");
101         const uint         audioBufferSize   = settings.valueUInt(QString("%1/BufferSize").arg(prefix), CARLA_DEFAULT_AUDIO_BUFFER_SIZE);
102         const uint         audioSampleRate   = settings.valueUInt(QString("%1/SampleRate").arg(prefix), CARLA_DEFAULT_AUDIO_SAMPLE_RATE);
103         const bool         audioTripleBuffer = settings.valueBool(QString("%1/TripleBuffer").arg(prefix), CARLA_DEFAULT_AUDIO_TRIPLE_BUFFER);
104 
105         if (audioDevice.isNotEmpty() && fDeviceNames.contains(audioDevice))
106             ui.cb_device->setCurrentIndex(fDeviceNames.indexOf(audioDevice));
107         else
108             ui.cb_device->setCurrentIndex(-1);
109 
110         // fill combo-boxes first
111         self->slot_updateDeviceInfo();
112 
113         if (audioBufferSize != 0 && fBufferSizes.contains(audioBufferSize))
114             ui.cb_buffersize->setCurrentIndex(fBufferSizes.indexOf(audioBufferSize));
115         else if (fBufferSizes == BUFFER_SIZE_LIST)
116             ui.cb_buffersize->setCurrentIndex(BUFFER_SIZE_LIST.indexOf(CARLA_DEFAULT_AUDIO_BUFFER_SIZE));
117         else
118             ui.cb_buffersize->setCurrentIndex(fBufferSizes.size()/2);
119 
120         if (audioSampleRate != 0 && fSampleRates.contains(audioSampleRate))
121             ui.cb_samplerate->setCurrentIndex(getIndexOfQDoubleListValue(fSampleRates, audioSampleRate));
122         else if (isQDoubleListEqual(fSampleRates, SAMPLE_RATE_LIST))
123             ui.cb_samplerate->setCurrentIndex(getIndexOfQDoubleListValue(SAMPLE_RATE_LIST, CARLA_DEFAULT_AUDIO_SAMPLE_RATE));
124         else
125             ui.cb_samplerate->setCurrentIndex(fSampleRates.size()/2);
126 
127         ui.cb_triple_buffer->setChecked(audioTripleBuffer && ui.cb_triple_buffer->isEnabled());
128     }
129 
130     CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
131 };
132 
DriverSettingsW(QWidget * const parent,const uint driverIndex,const QString driverName)133 DriverSettingsW::DriverSettingsW(QWidget* const parent, const uint driverIndex, const QString driverName)
134     : QDialog(parent),
135       self(new PrivateData(this, driverIndex, driverName))
136 {
137     // ----------------------------------------------------------------------------------------------------------------
138     // Set-up GUI
139 
140     for (const auto& name : self->fDeviceNames)
141         self->ui.cb_device->addItem(name);
142 
143     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
144 
145     // ----------------------------------------------------------------------------------------------------------------
146     // Load settings
147 
148     self->loadSettings(this);
149 
150     // ----------------------------------------------------------------------------------------------------------------
151     // Set-up connections
152 
153     connect(this, SIGNAL(accepted()), SLOT(slot_saveSettings()));
154     connect(self->ui.b_panel, SIGNAL(clicked()), SLOT(slot_showDevicePanel()));
155     connect(self->ui.cb_device, SIGNAL(currentIndexChanged(int)), SLOT(slot_updateDeviceInfo()));
156 }
157 
~DriverSettingsW()158 DriverSettingsW::~DriverSettingsW()
159 {
160     delete self;
161 }
162 
163 // --------------------------------------------------------------------------------------------------------------------
164 
slot_saveSettings()165 void DriverSettingsW::slot_saveSettings()
166 {
167     QSafeSettings settings("falkTX", "Carla2");
168 
169     QString bufferSize = self->ui.cb_buffersize->currentText();
170     QString sampleRate = self->ui.cb_samplerate->currentText();
171 
172     if (bufferSize == AUTOMATIC_OPTION)
173         bufferSize = "0";
174     if (sampleRate == AUTOMATIC_OPTION)
175         sampleRate = "0";
176 
177     const QString prefix(QString("%1%2").arg(CARLA_KEY_ENGINE_DRIVER_PREFIX).arg(self->fDriverName));
178 
179     settings.setValue(QString("%1/Device").arg(prefix), self->ui.cb_device->currentText());
180     settings.setValue(QString("%1/BufferSize").arg(prefix), bufferSize);
181     settings.setValue(QString("%1/SampleRate").arg(prefix), sampleRate);
182     settings.setValue(QString("%1/TripleBuffer").arg(prefix), self->ui.cb_triple_buffer->isChecked());
183 }
184 
slot_showDevicePanel()185 void DriverSettingsW::slot_showDevicePanel()
186 {
187     carla_show_engine_driver_device_control_panel(self->fDriverIndex, self->ui.cb_device->currentText().toUtf8());
188 }
189 
slot_updateDeviceInfo()190 void DriverSettingsW::slot_updateDeviceInfo()
191 {
192     const QString deviceName = self->ui.cb_device->currentText();
193 
194     const QString oldBufferSize = self->ui.cb_buffersize->currentText();
195     const QString oldSampleRate = self->ui.cb_samplerate->currentText();
196 
197     self->ui.cb_buffersize->clear();
198     self->ui.cb_samplerate->clear();
199 
200     self->fBufferSizes.clear();
201     self->fSampleRates.clear();
202 
203     const EngineDriverDeviceInfo* const driverDeviceInfo = carla_get_engine_driver_device_info(self->fDriverIndex, deviceName.toUtf8());
204     CARLA_SAFE_ASSERT_RETURN(driverDeviceInfo != nullptr,);
205 
206     const uint driverDeviceHints = driverDeviceInfo->hints;
207 
208     fillQUIntListFromUIntArray(self->fBufferSizes, driverDeviceInfo->bufferSizes);
209     fillQDoubleListFromDoubleArray(self->fSampleRates, driverDeviceInfo->sampleRates);
210 
211     if (driverDeviceHints & ENGINE_DRIVER_DEVICE_CAN_TRIPLE_BUFFER)
212         self->ui.cb_triple_buffer->setEnabled(true);
213     else
214         self->ui.cb_triple_buffer->setEnabled(false);
215 
216     if (driverDeviceHints & ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL)
217         self->ui.b_panel->setEnabled(true);
218     else
219         self->ui.b_panel->setEnabled(false);
220 
221     if (self->fBufferSizes.size() > 0)
222     {
223         for (const uint bsize : self->fBufferSizes)
224         {
225             const QString sbsize(QString("%1").arg(bsize));
226             self->ui.cb_buffersize->addItem(sbsize);
227 
228             if (oldBufferSize == sbsize)
229                 self->ui.cb_buffersize->setCurrentIndex(self->ui.cb_buffersize->count()-1);
230         }
231     }
232     else
233     {
234         self->ui.cb_buffersize->addItem(AUTOMATIC_OPTION);
235         self->ui.cb_buffersize->setCurrentIndex(0);
236     }
237 
238     if (self->fSampleRates.size() > 0)
239     {
240         for (const double srate : self->fSampleRates)
241         {
242             const QString ssrate(QString("%1").arg(srate));
243             self->ui.cb_samplerate->addItem(ssrate);
244 
245             if (oldSampleRate == ssrate)
246                 self->ui.cb_samplerate->setCurrentIndex(self->ui.cb_samplerate->count()-1);
247         }
248     }
249     else
250     {
251         self->ui.cb_samplerate->addItem(AUTOMATIC_OPTION);
252         self->ui.cb_samplerate->setCurrentIndex(0);
253     }
254 }
255 
256 // --------------------------------------------------------------------------------------------------------------------
257 // Runtime Driver Settings
258 
259 struct RuntimeDriverSettingsW::PrivateData {
260     Ui::DriverSettingsW ui;
261     const CarlaHostHandle hostHandle;
262 
PrivateDataRuntimeDriverSettingsW::PrivateData263     PrivateData(RuntimeDriverSettingsW* const self, const CarlaHostHandle h)
264         : ui(),
265           hostHandle(h)
266     {
267         ui.setupUi(self);
268     }
269 
270     CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PrivateData)
271 };
272 
RuntimeDriverSettingsW(const CarlaHostHandle hostHandle,QWidget * const parent)273 RuntimeDriverSettingsW::RuntimeDriverSettingsW(const CarlaHostHandle hostHandle, QWidget* const parent)
274     : QDialog(parent),
275       self(new PrivateData(this, hostHandle))
276 {
277     const CarlaRuntimeEngineDriverDeviceInfo* const driverDeviceInfo =
278         carla_get_runtime_engine_driver_device_info(hostHandle);
279 
280     QList<uint> bufferSizes;
281     fillQUIntListFromUIntArray(bufferSizes, driverDeviceInfo->bufferSizes);
282 
283     QList<double> sampleRates;
284     fillQDoubleListFromDoubleArray(sampleRates, driverDeviceInfo->sampleRates);
285 
286     // ----------------------------------------------------------------------------------------------------------------
287     // Set-up GUI
288 
289     self->ui.cb_device->clear();
290     self->ui.cb_buffersize->clear();
291     self->ui.cb_samplerate->clear();
292     self->ui.cb_triple_buffer->hide();
293     self->ui.ico_restart->hide();
294     self->ui.label_restart->hide();
295 
296     self->ui.layout_triple_buffer->takeAt(2);
297     self->ui.layout_triple_buffer->takeAt(1);
298     self->ui.layout_triple_buffer->takeAt(0);
299     self->ui.verticalLayout->removeItem(self->ui.layout_triple_buffer);
300 
301     self->ui.layout_restart->takeAt(3);
302     self->ui.layout_restart->takeAt(2);
303     self->ui.layout_restart->takeAt(1);
304     self->ui.layout_restart->takeAt(0);
305     self->ui.verticalLayout->removeItem(self->ui.layout_restart);
306 
307     adjustSize();
308     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
309 
310     // ----------------------------------------------------------------------------------------------------------------
311     // Load runtime settings
312 
313     if (carla_is_engine_running(hostHandle))
314     {
315         self->ui.cb_device->addItem(driverDeviceInfo->name);
316         self->ui.cb_device->setCurrentIndex(0);
317         self->ui.cb_device->setEnabled(false);
318     }
319     else
320     {
321         self->ui.cb_device->addItem(driverDeviceInfo->name);
322         self->ui.cb_device->setCurrentIndex(0);
323     }
324 
325     if (bufferSizes.size() > 0)
326     {
327         for (const uint bsize : bufferSizes)
328         {
329             const QString sbsize(QString("%1").arg(bsize));
330             self->ui.cb_buffersize->addItem(sbsize);
331 
332             if (driverDeviceInfo->bufferSize == bsize)
333                 self->ui.cb_buffersize->setCurrentIndex(self->ui.cb_buffersize->count()-1);
334         }
335     }
336     else
337     {
338         self->ui.cb_buffersize->addItem(AUTOMATIC_OPTION);
339         self->ui.cb_buffersize->setCurrentIndex(0);
340     }
341 
342     if ((driverDeviceInfo->hints & ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE) == 0x0)
343         self->ui.cb_buffersize->setEnabled(false);
344 
345     if (sampleRates.size() > 0)
346     {
347         for (const double srate : sampleRates)
348         {
349             const QString ssrate(QString("%1").arg(srate));
350             self->ui.cb_samplerate->addItem(ssrate);
351 
352             if (carla_isEqual(driverDeviceInfo->sampleRate, srate))
353                 self->ui.cb_samplerate->setCurrentIndex(self->ui.cb_samplerate->count()-1);
354         }
355     }
356     else
357     {
358         self->ui.cb_samplerate->addItem(AUTOMATIC_OPTION);
359         self->ui.cb_samplerate->setCurrentIndex(0);
360     }
361 
362     if ((driverDeviceInfo->hints & ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE) == 0x0)
363         self->ui.cb_samplerate->setEnabled(false);
364 
365     if ((driverDeviceInfo->hints & ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL) == 0x0)
366         self->ui.b_panel->setEnabled(false);
367 
368     // ----------------------------------------------------------------------------------------------------------------
369     // Set-up connections
370 
371     connect(self->ui.b_panel, SIGNAL(clicked()), SLOT(slot_showDevicePanel()));
372 }
373 
~RuntimeDriverSettingsW()374 RuntimeDriverSettingsW::~RuntimeDriverSettingsW()
375 {
376     delete self;
377 }
378 
getValues(QString & retAudioDevice,uint & retBufferSize,double & retSampleRate)379 void RuntimeDriverSettingsW::getValues(QString& retAudioDevice, uint& retBufferSize, double& retSampleRate)
380 {
381     const QString bufferSize = self->ui.cb_buffersize->currentText();
382     const QString sampleRate = self->ui.cb_samplerate->currentText();
383 
384     if (bufferSize == AUTOMATIC_OPTION)
385         retBufferSize = 0;
386     else
387         retBufferSize = bufferSize.toUInt();
388 
389     if (sampleRate == AUTOMATIC_OPTION)
390         retSampleRate = 0.0;
391     else
392         retSampleRate = sampleRate.toDouble();
393 
394     retAudioDevice = self->ui.cb_buffersize->currentText();
395 }
396 
slot_showDevicePanel()397 void RuntimeDriverSettingsW::slot_showDevicePanel()
398 {
399     carla_show_engine_device_control_panel(self->hostHandle);
400 }
401 
402 // --------------------------------------------------------------------------------------------------------------------
403 // Settings Dialog
404 
405 enum TabIndexes {
406     TAB_INDEX_MAIN,
407     TAB_INDEX_CANVAS,
408     TAB_INDEX_ENGINE,
409     TAB_INDEX_OSC,
410     TAB_INDEX_FILEPATHS,
411     TAB_INDEX_PLUGINPATHS,
412     TAB_INDEX_WINE,
413     TAB_INDEX_EXPERIMENTAL,
414     TAB_INDEX_NONE,
415 };
416 
417 enum FilePathIndexes {
418     FILEPATH_INDEX_AUDIO,
419     FILEPATH_INDEX_MIDI
420 };
421 
422 enum PluginPathIndexes {
423     PLUGINPATH_INDEX_LADSPA,
424     PLUGINPATH_INDEX_DSSI,
425     PLUGINPATH_INDEX_LV2,
426     PLUGINPATH_INDEX_VST2,
427     PLUGINPATH_INDEX_VST3,
428     PLUGINPATH_INDEX_SF2,
429     PLUGINPATH_INDEX_SFZ
430 };
431 
432 /*
433   Single and Multiple client mode is only for JACK,
434   but we still want to match QComboBox index to backend defines,
435   so add +2 pos padding if driverName != "JACK".
436 */
437 #define PROCESS_MODE_NON_JACK_PADDING 2
438 
439 struct CarlaSettingsW::PrivateData {
440     Ui::CarlaSettingsW ui;
441     CarlaHost& host;
442 
PrivateDataCarlaSettingsW::PrivateData443     PrivateData(CarlaSettingsW* const self, CarlaHost& h)
444         : ui(),
445           host(h)
446     {
447         ui.setupUi(self);
448     }
449 
loadSettingsCarlaSettingsW::PrivateData450     void loadSettings()
451     {
452         {
453             const QSafeSettings settings;
454 
455             // --------------------------------------------------------------------------------------------------------
456             // Main
457 
458             ui.ch_main_show_logs->setChecked(host.showLogs);
459             ui.ch_engine_uis_always_on_top->setChecked(host.uisAlwaysOnTop);
460 
461             ui.le_main_proj_folder->setText(settings.valueString(CARLA_KEY_MAIN_PROJECT_FOLDER,
462                                                                  CARLA_DEFAULT_MAIN_PROJECT_FOLDER));
463 
464             ui.ch_main_theme_pro->setChecked(settings.valueBool(CARLA_KEY_MAIN_USE_PRO_THEME,
465                                                                 CARLA_DEFAULT_MAIN_USE_PRO_THEME) && ui.group_main_theme->isEnabled());
466 
467             ui.cb_main_theme_color->setCurrentIndex(ui.cb_main_theme_color->findText(settings.valueString(CARLA_KEY_MAIN_PRO_THEME_COLOR,
468                                                                                                           CARLA_DEFAULT_MAIN_PRO_THEME_COLOR)));
469 
470             ui.sb_main_refresh_interval->setValue(settings.valueIntPositive(CARLA_KEY_MAIN_REFRESH_INTERVAL,
471                                                                             CARLA_DEFAULT_MAIN_REFRESH_INTERVAL));
472 
473             ui.ch_main_confirm_exit->setChecked(settings.valueBool(CARLA_KEY_MAIN_CONFIRM_EXIT,
474                                                                    CARLA_DEFAULT_MAIN_CONFIRM_EXIT));
475 
476             // --------------------------------------------------------------------------------------------------------
477             // Canvas
478 
479             ui.cb_canvas_theme->setCurrentIndex(ui.cb_canvas_theme->findText(settings.valueString(CARLA_KEY_CANVAS_THEME,
480                                                                                                   CARLA_DEFAULT_CANVAS_THEME)));
481 
482             ui.cb_canvas_size->setCurrentIndex(ui.cb_canvas_size->findText(settings.valueString(CARLA_KEY_CANVAS_SIZE,
483                                                                                                 CARLA_DEFAULT_CANVAS_SIZE)));
484 
485             ui.cb_canvas_bezier_lines->setChecked(settings.valueBool(CARLA_KEY_CANVAS_USE_BEZIER_LINES,
486                                                                     CARLA_DEFAULT_CANVAS_USE_BEZIER_LINES));
487 
488             ui.cb_canvas_hide_groups->setChecked(settings.valueBool(CARLA_KEY_CANVAS_AUTO_HIDE_GROUPS,
489                                                                     CARLA_DEFAULT_CANVAS_AUTO_HIDE_GROUPS));
490 
491             ui.cb_canvas_auto_select->setChecked(settings.valueBool(CARLA_KEY_CANVAS_AUTO_SELECT_ITEMS,
492                                                                     CARLA_DEFAULT_CANVAS_AUTO_SELECT_ITEMS));
493 
494             ui.cb_canvas_eyecandy->setChecked(settings.valueBool(CARLA_KEY_CANVAS_EYE_CANDY,
495                                                                  CARLA_DEFAULT_CANVAS_EYE_CANDY));
496 
497             ui.cb_canvas_fancy_eyecandy->setChecked(settings.valueBool(CARLA_KEY_CANVAS_FANCY_EYE_CANDY,
498                                                                       CARLA_DEFAULT_CANVAS_FANCY_EYE_CANDY));
499 
500             ui.cb_canvas_use_opengl->setChecked(settings.valueBool(CARLA_KEY_CANVAS_USE_OPENGL,
501                                                                    CARLA_DEFAULT_CANVAS_USE_OPENGL) && ui.cb_canvas_use_opengl->isEnabled());
502 
503             ui.cb_canvas_render_aa->setCheckState(settings.valueCheckState(CARLA_KEY_CANVAS_ANTIALIASING,
504                                                                            CARLA_DEFAULT_CANVAS_ANTIALIASING));
505 
506             ui.cb_canvas_render_hq_aa->setChecked(settings.valueBool(CARLA_KEY_CANVAS_HQ_ANTIALIASING,
507                                                                      CARLA_DEFAULT_CANVAS_HQ_ANTIALIASING) && ui.cb_canvas_render_hq_aa->isEnabled());
508 
509             ui.cb_canvas_full_repaints->setChecked(settings.valueBool(CARLA_KEY_CANVAS_FULL_REPAINTS,
510                                                                       CARLA_DEFAULT_CANVAS_FULL_REPAINTS));
511 
512             ui.cb_canvas_inline_displays->setChecked(settings.valueBool(CARLA_KEY_CANVAS_INLINE_DISPLAYS,
513                                                                         CARLA_DEFAULT_CANVAS_INLINE_DISPLAYS));
514         }
515 
516         // ------------------------------------------------------------------------------------------------------------
517 
518         const QSafeSettings settings("falkTX", "Carla2");
519 
520         // ------------------------------------------------------------------------------------------------------------
521         // Main
522 
523         ui.ch_main_experimental->setChecked(host.experimental);
524 
525         if (! host.experimental)
526         {
527             ui.lw_page->hideRow(TAB_INDEX_EXPERIMENTAL);
528             ui.lw_page->hideRow(TAB_INDEX_WINE);
529         }
530         else if (! host.showWineBridges)
531         {
532             ui.lw_page->hideRow(TAB_INDEX_WINE);
533         }
534 
535         // ------------------------------------------------------------------------------------------------------------
536         // Engine
537 
538         QString audioDriver;
539 
540         if (host.isPlugin)
541         {
542             audioDriver = "Plugin";
543             ui.cb_engine_audio_driver->setCurrentIndex(0);
544         }
545         else if (host.audioDriverForced.isNotEmpty())
546         {
547             audioDriver = host.audioDriverForced;
548             ui.cb_engine_audio_driver->setCurrentIndex(0);
549         }
550         else
551         {
552             audioDriver = settings.valueString(CARLA_KEY_ENGINE_AUDIO_DRIVER, CARLA_DEFAULT_AUDIO_DRIVER);
553 
554             bool found = false;
555             for (int i=0; i < ui.cb_engine_audio_driver->count(); ++i)
556             {
557                 if (ui.cb_engine_audio_driver->itemText(i) == audioDriver)
558                 {
559                     found = true;
560                     ui.cb_engine_audio_driver->setCurrentIndex(i);
561                     break;
562                 }
563             }
564 
565             if (! found)
566                 ui.cb_engine_audio_driver->setCurrentIndex(-1);
567         }
568 
569         if (audioDriver == "JACK")
570             ui.sw_engine_process_mode->setCurrentIndex(0);
571         else
572             ui.sw_engine_process_mode->setCurrentIndex(1);
573 
574         ui.tb_engine_driver_config->setEnabled(host.audioDriverForced.isNotEmpty() && ! host.isPlugin);
575 
576         ui.cb_engine_process_mode_jack->setCurrentIndex(host.nextProcessMode);
577 
578         if (host.nextProcessMode >= PROCESS_MODE_NON_JACK_PADDING)
579             ui.cb_engine_process_mode_other->setCurrentIndex(host.nextProcessMode-PROCESS_MODE_NON_JACK_PADDING);
580         else
581             ui.cb_engine_process_mode_other->setCurrentIndex(0);
582 
583         ui.sb_engine_max_params->setValue(static_cast<int>(host.maxParameters));
584         ui.cb_engine_reset_xruns->setChecked(host.resetXruns);
585         ui.ch_engine_manage_uis->setChecked(host.manageUIs);
586         ui.ch_engine_prefer_ui_bridges->setChecked(host.preferUIBridges);
587         ui.sb_engine_ui_bridges_timeout->setValue(host.uiBridgesTimeout);
588         ui.ch_engine_force_stereo->setChecked(host.forceStereo || ! ui.ch_engine_force_stereo->isEnabled());
589         ui.ch_engine_prefer_plugin_bridges->setChecked(host.preferPluginBridges);
590         ui.ch_exp_export_lv2->setChecked(host.exportLV2);
591         ui.cb_exp_plugin_bridges->setChecked(host.showPluginBridges);
592         ui.ch_exp_wine_bridges->setChecked(host.showWineBridges);
593 
594         // ------------------------------------------------------------------------------------------------------------
595         // OSC
596 
597         ui.ch_osc_enable->setChecked(settings.valueBool(CARLA_KEY_OSC_ENABLED,
598                                                         CARLA_DEFAULT_OSC_ENABLED));
599 
600         ui.group_osc_tcp_port->setChecked(settings.valueBool(CARLA_KEY_OSC_TCP_PORT_ENABLED,
601                                                              CARLA_DEFAULT_OSC_TCP_PORT_ENABLED));
602 
603         ui.group_osc_udp_port->setChecked(settings.valueBool(CARLA_KEY_OSC_UDP_PORT_ENABLED,
604                                                              CARLA_DEFAULT_OSC_UDP_PORT_ENABLED));
605 
606         ui.sb_osc_tcp_port_number->setValue(settings.valueIntPositive(CARLA_KEY_OSC_TCP_PORT_NUMBER,
607                                                                       CARLA_DEFAULT_OSC_TCP_PORT_NUMBER));
608 
609         ui.sb_osc_udp_port_number->setValue(settings.valueIntPositive(CARLA_KEY_OSC_UDP_PORT_NUMBER,
610                                                                       CARLA_DEFAULT_OSC_UDP_PORT_NUMBER));
611 
612         if (settings.valueBool(CARLA_KEY_OSC_TCP_PORT_RANDOM, CARLA_DEFAULT_OSC_TCP_PORT_RANDOM))
613         {
614             ui.rb_osc_tcp_port_specific->setChecked(false);
615             ui.rb_osc_tcp_port_random->setChecked(true);
616         }
617         else
618         {
619             ui.rb_osc_tcp_port_random->setChecked(false);
620             ui.rb_osc_tcp_port_specific->setChecked(true);
621         }
622 
623         if (settings.valueBool(CARLA_KEY_OSC_UDP_PORT_RANDOM, CARLA_DEFAULT_OSC_UDP_PORT_RANDOM))
624         {
625             ui.rb_osc_udp_port_specific->setChecked(false);
626             ui.rb_osc_udp_port_random->setChecked(true);
627         }
628         else
629         {
630             ui.rb_osc_udp_port_random->setChecked(false);
631             ui.rb_osc_udp_port_specific->setChecked(true);
632         }
633 
634         // ------------------------------------------------------------------------------------------------------------
635         // File Paths
636 
637         QStringList audioPaths = settings.valueStringList(CARLA_KEY_PATHS_AUDIO, CARLA_DEFAULT_FILE_PATH_AUDIO);
638         QStringList midiPaths  = settings.valueStringList(CARLA_KEY_PATHS_MIDI,  CARLA_DEFAULT_FILE_PATH_MIDI);
639 
640         audioPaths.sort();
641         midiPaths.sort();
642 
643         for (const QString& audioPath : audioPaths)
644         {
645             if (audioPath.isEmpty()) continue;
646             ui.lw_files_audio->addItem(audioPath);
647         }
648 
649         for (const QString& midiPath : midiPaths)
650         {
651             if (midiPath.isEmpty()) continue;
652             ui.lw_files_midi->addItem(midiPath);
653         }
654 
655         // ------------------------------------------------------------------------------------------------------------
656         // Plugin Paths
657 
658         QStringList ladspas = settings.valueStringList(CARLA_KEY_PATHS_LADSPA, CARLA_DEFAULT_LADSPA_PATH);
659         QStringList dssis   = settings.valueStringList(CARLA_KEY_PATHS_DSSI,   CARLA_DEFAULT_DSSI_PATH);
660         QStringList lv2s    = settings.valueStringList(CARLA_KEY_PATHS_LV2,    CARLA_DEFAULT_LV2_PATH);
661         QStringList vst2s   = settings.valueStringList(CARLA_KEY_PATHS_VST2,   CARLA_DEFAULT_VST2_PATH);
662         QStringList vst3s   = settings.valueStringList(CARLA_KEY_PATHS_VST3,   CARLA_DEFAULT_VST3_PATH);
663         QStringList sf2s    = settings.valueStringList(CARLA_KEY_PATHS_SF2,    CARLA_DEFAULT_SF2_PATH);
664         QStringList sfzs    = settings.valueStringList(CARLA_KEY_PATHS_SFZ,    CARLA_DEFAULT_SFZ_PATH);
665 
666         ladspas.sort();
667         dssis.sort();
668         lv2s.sort();
669         vst2s.sort();
670         vst3s.sort();
671         sf2s.sort();
672         sfzs.sort();
673 
674         for (const QString& ladspa : ladspas)
675         {
676             if (ladspa.isEmpty()) continue;
677             ui.lw_ladspa->addItem(ladspa);
678         }
679 
680         for (const QString& dssi : dssis)
681         {
682             if (dssi.isEmpty()) continue;
683             ui.lw_dssi->addItem(dssi);
684         }
685 
686         for (const QString& lv2 : lv2s)
687         {
688             if (lv2.isEmpty()) continue;
689             ui.lw_lv2->addItem(lv2);
690         }
691 
692         for (const QString& vst2 : vst2s)
693         {
694             if (vst2.isEmpty()) continue;
695             ui.lw_vst->addItem(vst2);
696         }
697 
698         for (const QString& vst3 : vst3s)
699         {
700             if (vst3.isEmpty()) continue;
701             ui.lw_vst3->addItem(vst3);
702         }
703 
704         for (const QString& sf2 : sf2s)
705         {
706             if (sf2.isEmpty()) continue;
707             ui.lw_sf2->addItem(sf2);
708         }
709 
710         for (const QString& sfz : sfzs)
711         {
712             if (sfz.isEmpty()) continue;
713             ui.lw_sfz->addItem(sfz);
714         }
715 
716         // ------------------------------------------------------------------------------------------------------------
717         // Wine
718 
719         ui.le_wine_exec->setText(settings.valueString(CARLA_KEY_WINE_EXECUTABLE,
720                                                       CARLA_DEFAULT_WINE_EXECUTABLE));
721 
722         ui.cb_wine_prefix_detect->setChecked(settings.valueBool(CARLA_KEY_WINE_AUTO_PREFIX,
723                                                                 CARLA_DEFAULT_WINE_AUTO_PREFIX));
724 
725         ui.le_wine_prefix_fallback->setText(settings.valueString(CARLA_KEY_WINE_FALLBACK_PREFIX,
726                                                                  CARLA_DEFAULT_WINE_FALLBACK_PREFIX));
727 
728         ui.group_wine_realtime->setChecked(settings.valueBool(CARLA_KEY_WINE_RT_PRIO_ENABLED,
729                                                               CARLA_DEFAULT_WINE_RT_PRIO_ENABLED));
730 
731         ui.sb_wine_base_prio->setValue(settings.valueIntPositive(CARLA_KEY_WINE_BASE_RT_PRIO,
732                                                                  CARLA_DEFAULT_WINE_BASE_RT_PRIO));
733 
734         ui.sb_wine_server_prio->setValue(settings.valueIntPositive(CARLA_KEY_WINE_SERVER_RT_PRIO,
735                                                                    CARLA_DEFAULT_WINE_SERVER_RT_PRIO));
736 
737         // ------------------------------------------------------------------------------------------------------------
738         // Experimental
739 
740         ui.ch_exp_jack_apps->setChecked(settings.valueBool(CARLA_KEY_EXPERIMENTAL_JACK_APPS,
741                                                            CARLA_DEFAULT_EXPERIMENTAL_JACK_APPS));
742 
743         ui.ch_exp_export_lv2->setChecked(settings.valueBool(CARLA_KEY_EXPERIMENTAL_EXPORT_LV2,
744                                                             CARLA_DEFAULT_EXPERIMENTAL_LV2_EXPORT));
745 
746         ui.ch_exp_load_lib_global->setChecked(settings.valueBool(CARLA_KEY_EXPERIMENTAL_LOAD_LIB_GLOBAL,
747                                                                  CARLA_DEFAULT_EXPERIMENTAL_LOAD_LIB_GLOBAL));
748 
749         ui.ch_exp_prevent_bad_behaviour->setChecked(settings.valueBool(CARLA_KEY_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR,
750                                                                        CARLA_DEFAULT_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR));
751     }
752 
saveSettingsCarlaSettingsW::PrivateData753     void saveSettings()
754     {
755         {
756             QSafeSettings settings;
757 
758             host.experimental = ui.ch_main_experimental->isChecked();
759 
760             if (! host.experimental)
761                 resetExperimentalSettings();
762 
763             // --------------------------------------------------------------------------------------------------------
764             // Main
765 
766             settings.setValue(CARLA_KEY_MAIN_PROJECT_FOLDER,   ui.le_main_proj_folder->text());
767             settings.setValue(CARLA_KEY_MAIN_CONFIRM_EXIT,     ui.ch_main_confirm_exit->isChecked());
768             settings.setValue(CARLA_KEY_MAIN_USE_PRO_THEME,    ui.ch_main_theme_pro->isChecked());
769             settings.setValue(CARLA_KEY_MAIN_PRO_THEME_COLOR,  ui.cb_main_theme_color->currentText());
770             settings.setValue(CARLA_KEY_MAIN_REFRESH_INTERVAL, ui.sb_main_refresh_interval->value());
771 
772             // --------------------------------------------------------------------------------------------------------
773             // Canvas
774 
775             settings.setValue(CARLA_KEY_CANVAS_THEME,             ui.cb_canvas_theme->currentText());
776             settings.setValue(CARLA_KEY_CANVAS_SIZE,              ui.cb_canvas_size->currentText());
777             settings.setValue(CARLA_KEY_CANVAS_USE_BEZIER_LINES,  ui.cb_canvas_bezier_lines->isChecked());
778             settings.setValue(CARLA_KEY_CANVAS_AUTO_HIDE_GROUPS,  ui.cb_canvas_hide_groups->isChecked());
779             settings.setValue(CARLA_KEY_CANVAS_AUTO_SELECT_ITEMS, ui.cb_canvas_auto_select->isChecked());
780             settings.setValue(CARLA_KEY_CANVAS_EYE_CANDY,         ui.cb_canvas_eyecandy->isChecked());
781             settings.setValue(CARLA_KEY_CANVAS_FANCY_EYE_CANDY,   ui.cb_canvas_fancy_eyecandy->isChecked());
782             settings.setValue(CARLA_KEY_CANVAS_USE_OPENGL,        ui.cb_canvas_use_opengl->isChecked());
783             settings.setValue(CARLA_KEY_CANVAS_HQ_ANTIALIASING,   ui.cb_canvas_render_hq_aa->isChecked());
784             settings.setValue(CARLA_KEY_CANVAS_ANTIALIASING,      ui.cb_canvas_render_aa->checkState()); // 0, 1, 2 match their enum variants
785             settings.setValue(CARLA_KEY_CANVAS_FULL_REPAINTS,     ui.cb_canvas_full_repaints->isChecked());
786             settings.setValue(CARLA_KEY_CANVAS_INLINE_DISPLAYS,   ui.cb_canvas_inline_displays->isChecked());
787         }
788 
789         // ------------------------------------------------------------------------------------------------------------
790 
791         QSafeSettings settings("falkTX", "Carla2");
792 
793         // ------------------------------------------------------------------------------------------------------------
794         // Main
795 
796         settings.setValue(CARLA_KEY_MAIN_EXPERIMENTAL, host.experimental);
797 
798         // ------------------------------------------------------------------------------------------------------------
799         // Engine
800 
801         const QCarlaString audioDriver = ui.cb_engine_audio_driver->currentText();
802 
803         if (audioDriver.isNotEmpty() && host.audioDriverForced.isEmpty() && ! host.isPlugin)
804             settings.setValue(CARLA_KEY_ENGINE_AUDIO_DRIVER, audioDriver);
805 
806         if (! host.processModeForced)
807         {
808             // engine sends callback if processMode really changes
809             if (audioDriver == "JACK")
810                 host.nextProcessMode = static_cast<EngineProcessMode>(ui.cb_engine_process_mode_jack->currentIndex());
811             else
812                 host.nextProcessMode = static_cast<EngineProcessMode>(ui.cb_engine_process_mode_other->currentIndex() + PROCESS_MODE_NON_JACK_PADDING);
813 
814             settings.setValue(CARLA_KEY_ENGINE_PROCESS_MODE, host.nextProcessMode);
815         }
816 
817         host.exportLV2           = ui.ch_exp_export_lv2->isChecked();
818         host.forceStereo         = ui.ch_engine_force_stereo->isChecked();
819         host.resetXruns          = ui.cb_engine_reset_xruns->isChecked();
820         host.maxParameters       = static_cast<uint>(std::max(0, ui.sb_engine_max_params->value()));
821         host.manageUIs           = ui.ch_engine_manage_uis->isChecked();
822         host.preferPluginBridges = ui.ch_engine_prefer_plugin_bridges->isChecked();
823         host.preferUIBridges     = ui.ch_engine_prefer_ui_bridges->isChecked();
824         host.showLogs            = ui.ch_main_show_logs->isChecked();
825         host.showPluginBridges   = ui.cb_exp_plugin_bridges->isChecked();
826         host.showWineBridges     = ui.ch_exp_wine_bridges->isChecked();
827         host.uiBridgesTimeout    = ui.sb_engine_ui_bridges_timeout->value();
828         host.uisAlwaysOnTop      = ui.ch_engine_uis_always_on_top->isChecked();
829 
830         if (ui.ch_engine_force_stereo->isEnabled())
831             settings.setValue(CARLA_KEY_ENGINE_FORCE_STEREO, host.forceStereo);
832 
833         settings.setValue(CARLA_KEY_MAIN_SHOW_LOGS,               host.showLogs);
834         settings.setValue(CARLA_KEY_ENGINE_MAX_PARAMETERS,        host.maxParameters);
835         settings.setValue(CARLA_KEY_ENGINE_RESET_XRUNS,           host.resetXruns);
836         settings.setValue(CARLA_KEY_ENGINE_MANAGE_UIS,            host.manageUIs);
837         settings.setValue(CARLA_KEY_ENGINE_PREFER_PLUGIN_BRIDGES, host.preferPluginBridges);
838         settings.setValue(CARLA_KEY_ENGINE_PREFER_UI_BRIDGES,     host.preferUIBridges);
839         settings.setValue(CARLA_KEY_ENGINE_UI_BRIDGES_TIMEOUT,    host.uiBridgesTimeout);
840         settings.setValue(CARLA_KEY_ENGINE_UIS_ALWAYS_ON_TOP,     host.uisAlwaysOnTop);
841         settings.setValue(CARLA_KEY_EXPERIMENTAL_EXPORT_LV2,      host.exportLV2);
842         settings.setValue(CARLA_KEY_EXPERIMENTAL_PLUGIN_BRIDGES,  host.showPluginBridges);
843         settings.setValue(CARLA_KEY_EXPERIMENTAL_WINE_BRIDGES,    host.showWineBridges);
844 
845         // ------------------------------------------------------------------------------------------------------------
846         // OSC
847 
848         settings.setValue(CARLA_KEY_OSC_ENABLED,          ui.ch_osc_enable->isChecked());
849         settings.setValue(CARLA_KEY_OSC_TCP_PORT_ENABLED, ui.group_osc_tcp_port->isChecked());
850         settings.setValue(CARLA_KEY_OSC_UDP_PORT_ENABLED, ui.group_osc_udp_port->isChecked());
851         settings.setValue(CARLA_KEY_OSC_TCP_PORT_RANDOM,  ui.rb_osc_tcp_port_random->isChecked());
852         settings.setValue(CARLA_KEY_OSC_UDP_PORT_RANDOM,  ui.rb_osc_udp_port_random->isChecked());
853         settings.setValue(CARLA_KEY_OSC_TCP_PORT_NUMBER,  ui.sb_osc_tcp_port_number->value());
854         settings.setValue(CARLA_KEY_OSC_UDP_PORT_NUMBER,  ui.sb_osc_udp_port_number->value());
855 
856         // ------------------------------------------------------------------------------------------------------------
857         // File Paths
858 
859         QStringList audioPaths;
860         QStringList midiPaths;
861 
862         for (int i=0; i < ui.lw_files_audio->count(); ++i)
863             audioPaths.append(ui.lw_files_audio->item(i)->text());
864 
865         for (int i=0; i < ui.lw_files_midi->count(); ++i)
866             midiPaths.append(ui.lw_files_midi->item(i)->text());
867 
868         /* TODO
869         host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_AUDIO, splitter.join(audioPaths));
870         host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_MIDI,  splitter.join(midiPaths));
871         */
872 
873         settings.setValue(CARLA_KEY_PATHS_AUDIO, audioPaths);
874         settings.setValue(CARLA_KEY_PATHS_MIDI, midiPaths);
875 
876         // ------------------------------------------------------------------------------------------------------------
877         // Plugin Paths
878 
879         QStringList ladspas;
880         QStringList dssis;
881         QStringList lv2s;
882         QStringList vst2s;
883         QStringList vst3s;
884         QStringList sf2s;
885         QStringList sfzs;
886 
887         for (int i=0; i < ui.lw_ladspa->count(); ++i)
888             ladspas.append(ui.lw_ladspa->item(i)->text());
889 
890         for (int i=0; i < ui.lw_dssi->count(); ++i)
891             dssis.append(ui.lw_dssi->item(i)->text());
892 
893         for (int i=0; i < ui.lw_lv2->count(); ++i)
894             lv2s.append(ui.lw_lv2->item(i)->text());
895 
896         for (int i=0; i < ui.lw_vst->count(); ++i)
897             vst2s.append(ui.lw_vst->item(i)->text());
898 
899         for (int i=0; i < ui.lw_vst3->count(); ++i)
900             vst3s.append(ui.lw_vst3->item(i)->text());
901 
902         for (int i=0; i < ui.lw_sf2->count(); ++i)
903             sf2s.append(ui.lw_sf2->item(i)->text());
904 
905         for (int i=0; i < ui.lw_sfz->count(); ++i)
906             sfzs.append(ui.lw_sfz->item(i)->text());
907 
908         /* TODO
909         host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LADSPA, splitter.join(ladspas));
910         host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_DSSI,   splitter.join(dssis));
911         host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2,    splitter.join(lv2s));
912         host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_VST2,   splitter.join(vst2s));
913         host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_VST3,   splitter.join(vst3s));
914         host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SF2,    splitter.join(sf2s));
915         host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SFZ,    splitter.join(sfzs));
916         */
917 
918         settings.setValue(CARLA_KEY_PATHS_LADSPA, ladspas);
919         settings.setValue(CARLA_KEY_PATHS_DSSI, dssis);
920         settings.setValue(CARLA_KEY_PATHS_LV2, lv2s);
921         settings.setValue(CARLA_KEY_PATHS_VST2, vst2s);
922         settings.setValue(CARLA_KEY_PATHS_VST3, vst3s);
923         settings.setValue(CARLA_KEY_PATHS_SF2, sf2s);
924         settings.setValue(CARLA_KEY_PATHS_SFZ, sfzs);
925 
926         // ------------------------------------------------------------------------------------------------------------
927         // Wine
928 
929         settings.setValue(CARLA_KEY_WINE_EXECUTABLE, ui.le_wine_exec->text());
930         settings.setValue(CARLA_KEY_WINE_AUTO_PREFIX, ui.cb_wine_prefix_detect->isChecked());
931         settings.setValue(CARLA_KEY_WINE_FALLBACK_PREFIX, ui.le_wine_prefix_fallback->text());
932         settings.setValue(CARLA_KEY_WINE_RT_PRIO_ENABLED, ui.group_wine_realtime->isChecked());
933         settings.setValue(CARLA_KEY_WINE_BASE_RT_PRIO, ui.sb_wine_base_prio->value());
934         settings.setValue(CARLA_KEY_WINE_SERVER_RT_PRIO, ui.sb_wine_server_prio->value());
935 
936         // ------------------------------------------------------------------------------------------------------------
937         // Experimental
938 
939         settings.setValue(CARLA_KEY_EXPERIMENTAL_JACK_APPS, ui.ch_exp_jack_apps->isChecked());
940         settings.setValue(CARLA_KEY_EXPERIMENTAL_LOAD_LIB_GLOBAL, ui.ch_exp_load_lib_global->isChecked());
941         settings.setValue(CARLA_KEY_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR, ui.ch_exp_prevent_bad_behaviour->isChecked());
942     }
943 
resetSettingsCarlaSettingsW::PrivateData944     void resetSettings()
945     {
946         switch (ui.lw_page->currentRow())
947         {
948         // ------------------------------------------------------------------------------------------------------------
949         // Main
950 
951         case TAB_INDEX_MAIN:
952             ui.le_main_proj_folder->setText(CARLA_DEFAULT_MAIN_PROJECT_FOLDER);
953             ui.ch_main_theme_pro->setChecked(CARLA_DEFAULT_MAIN_USE_PRO_THEME && ui.group_main_theme->isEnabled());
954             ui.cb_main_theme_color->setCurrentIndex(ui.cb_main_theme_color->findText(CARLA_DEFAULT_MAIN_PRO_THEME_COLOR));
955             ui.sb_main_refresh_interval->setValue(CARLA_DEFAULT_MAIN_REFRESH_INTERVAL);
956             ui.ch_main_confirm_exit->setChecked(CARLA_DEFAULT_MAIN_CONFIRM_EXIT);
957             ui.ch_main_show_logs->setChecked(CARLA_DEFAULT_MAIN_SHOW_LOGS);
958             break;
959 
960         // ------------------------------------------------------------------------------------------------------------
961         // Canvas
962 
963         case TAB_INDEX_CANVAS:
964             ui.cb_canvas_theme->setCurrentIndex(ui.cb_canvas_theme->findText(CARLA_DEFAULT_CANVAS_THEME));
965             ui.cb_canvas_size->setCurrentIndex(ui.cb_canvas_size->findText(CARLA_DEFAULT_CANVAS_SIZE));
966             ui.cb_canvas_bezier_lines->setChecked(CARLA_DEFAULT_CANVAS_USE_BEZIER_LINES);
967             ui.cb_canvas_hide_groups->setChecked(CARLA_DEFAULT_CANVAS_AUTO_HIDE_GROUPS);
968             ui.cb_canvas_auto_select->setChecked(CARLA_DEFAULT_CANVAS_AUTO_SELECT_ITEMS);
969             ui.cb_canvas_eyecandy->setChecked(CARLA_DEFAULT_CANVAS_EYE_CANDY);
970             ui.cb_canvas_render_aa->setCheckState(Qt::PartiallyChecked); // CARLA_DEFAULT_CANVAS_ANTIALIASING
971             ui.cb_canvas_full_repaints->setChecked(CARLA_DEFAULT_CANVAS_FULL_REPAINTS);
972             break;
973 
974         // ------------------------------------------------------------------------------------------------------------
975         // Engine
976 
977         case TAB_INDEX_ENGINE:
978             if (! host.isPlugin)
979                 ui.cb_engine_audio_driver->setCurrentIndex(0);
980 
981             if (! host.processModeForced)
982             {
983                 if (ui.cb_engine_audio_driver->currentText() == "JACK")
984                 {
985                     ui.cb_engine_process_mode_jack->setCurrentIndex(CARLA_DEFAULT_PROCESS_MODE);
986                     ui.sw_engine_process_mode->setCurrentIndex(0); // show all modes
987                 }
988                 else
989                 {
990                     ui.cb_engine_process_mode_other->setCurrentIndex(CARLA_DEFAULT_PROCESS_MODE-PROCESS_MODE_NON_JACK_PADDING);
991                     ui.sw_engine_process_mode->setCurrentIndex(1); // hide single+multi client modes
992                 }
993             }
994 
995             ui.sb_engine_max_params->setValue(CARLA_DEFAULT_MAX_PARAMETERS);
996             ui.cb_engine_reset_xruns->setChecked(CARLA_DEFAULT_RESET_XRUNS);
997             ui.ch_engine_uis_always_on_top->setChecked(CARLA_DEFAULT_UIS_ALWAYS_ON_TOP);
998             ui.ch_engine_prefer_ui_bridges->setChecked(CARLA_DEFAULT_PREFER_UI_BRIDGES);
999             ui.sb_engine_ui_bridges_timeout->setValue(CARLA_DEFAULT_UI_BRIDGES_TIMEOUT);
1000             ui.ch_engine_manage_uis->setChecked(CARLA_DEFAULT_MANAGE_UIS);
1001             break;
1002 
1003         // ------------------------------------------------------------------------------------------------------------
1004         // OSC
1005 
1006         case TAB_INDEX_OSC:
1007             ui.ch_osc_enable->setChecked(CARLA_DEFAULT_OSC_ENABLED);
1008             ui.group_osc_tcp_port->setChecked(CARLA_DEFAULT_OSC_TCP_PORT_ENABLED);
1009             ui.group_osc_udp_port->setChecked(CARLA_DEFAULT_OSC_UDP_PORT_ENABLED);
1010             ui.sb_osc_tcp_port_number->setValue(CARLA_DEFAULT_OSC_TCP_PORT_NUMBER);
1011             ui.sb_osc_udp_port_number->setValue(CARLA_DEFAULT_OSC_UDP_PORT_NUMBER);
1012 
1013             if (CARLA_DEFAULT_OSC_TCP_PORT_RANDOM)
1014             {
1015                 ui.rb_osc_tcp_port_specific->setChecked(false);
1016                 ui.rb_osc_tcp_port_random->setChecked(true);
1017             }
1018             else
1019             {
1020                 ui.rb_osc_tcp_port_random->setChecked(false);
1021                 ui.rb_osc_tcp_port_specific->setChecked(true);
1022             }
1023 
1024             if (CARLA_DEFAULT_OSC_UDP_PORT_RANDOM)
1025             {
1026                 ui.rb_osc_udp_port_specific->setChecked(false);
1027                 ui.rb_osc_udp_port_random->setChecked(true);
1028             }
1029             else
1030             {
1031                 ui.rb_osc_udp_port_random->setChecked(false);
1032                 ui.rb_osc_udp_port_specific->setChecked(true);
1033             }
1034             break;
1035 
1036         // ------------------------------------------------------------------------------------------------------------
1037         // Plugin Paths
1038 
1039         case TAB_INDEX_FILEPATHS:
1040             switch (ui.tw_filepaths->currentIndex())
1041             {
1042             case FILEPATH_INDEX_AUDIO:
1043                 ui.lw_files_audio->clear();
1044                 break;
1045             case FILEPATH_INDEX_MIDI:
1046                 ui.lw_files_midi->clear();
1047                 break;
1048             }
1049             break;
1050 
1051         // ------------------------------------------------------------------------------------------------------------
1052         // Plugin Paths
1053 
1054         case TAB_INDEX_PLUGINPATHS:
1055         {
1056             QStringList paths;
1057 
1058             switch (ui.tw_paths->currentIndex())
1059             {
1060             case PLUGINPATH_INDEX_LADSPA:
1061                 paths = CARLA_DEFAULT_LADSPA_PATH;
1062                 paths.sort();
1063                 ui.lw_ladspa->clear();
1064 
1065                 for (const auto& path : paths)
1066                 {
1067                     if (path.isEmpty())
1068                         continue;
1069                     ui.lw_ladspa->addItem(path);
1070                 }
1071                 break;
1072 
1073             case PLUGINPATH_INDEX_DSSI:
1074                 paths = CARLA_DEFAULT_DSSI_PATH;
1075                 paths.sort();
1076                 ui.lw_dssi->clear();
1077 
1078                 for (const auto& path : paths)
1079                 {
1080                     if (path.isEmpty())
1081                         continue;
1082                     ui.lw_dssi->addItem(path);
1083                 }
1084                 break;
1085 
1086             case PLUGINPATH_INDEX_LV2:
1087                 paths = CARLA_DEFAULT_LV2_PATH;
1088                 paths.sort();
1089                 ui.lw_lv2->clear();
1090 
1091                 for (const auto& path : paths)
1092                 {
1093                     if (path.isEmpty())
1094                         continue;
1095                     ui.lw_lv2->addItem(path);
1096                 }
1097                 break;
1098 
1099             case PLUGINPATH_INDEX_VST2:
1100                 paths = CARLA_DEFAULT_VST2_PATH;
1101                 paths.sort();
1102                 ui.lw_vst->clear();
1103 
1104                 for (const auto& path : paths)
1105                 {
1106                     if (path.isEmpty())
1107                         continue;
1108                     ui.lw_vst->addItem(path);
1109                 }
1110                 break;
1111 
1112             case PLUGINPATH_INDEX_VST3:
1113                 paths = CARLA_DEFAULT_VST3_PATH;
1114                 paths.sort();
1115                 ui.lw_vst3->clear();
1116 
1117                 for (const auto& path : paths)
1118                 {
1119                     if (path.isEmpty())
1120                         continue;
1121                     ui.lw_vst3->addItem(path);
1122                 }
1123                 break;
1124 
1125             case PLUGINPATH_INDEX_SF2:
1126                 paths = CARLA_DEFAULT_SF2_PATH;
1127                 paths.sort();
1128                 ui.lw_sf2->clear();
1129 
1130                 for (const auto& path : paths)
1131                 {
1132                     if (path.isEmpty())
1133                         continue;
1134                     ui.lw_sf2->addItem(path);
1135                 }
1136                 break;
1137 
1138             case PLUGINPATH_INDEX_SFZ:
1139                 paths = CARLA_DEFAULT_SFZ_PATH;
1140                 paths.sort();
1141                 ui.lw_sfz->clear();
1142 
1143                 for (const auto& path : paths)
1144                 {
1145                     if (path.isEmpty())
1146                         continue;
1147                     ui.lw_sfz->addItem(path);
1148                 }
1149                 break;
1150             }
1151             break;
1152         }
1153 
1154         // ------------------------------------------------------------------------------------------------------------
1155         // Wine
1156 
1157         case TAB_INDEX_WINE:
1158             ui.le_wine_exec->setText(CARLA_DEFAULT_WINE_EXECUTABLE);
1159             ui.cb_wine_prefix_detect->setChecked(CARLA_DEFAULT_WINE_AUTO_PREFIX);
1160             ui.le_wine_prefix_fallback->setText(CARLA_DEFAULT_WINE_FALLBACK_PREFIX);
1161             ui.group_wine_realtime->setChecked(CARLA_DEFAULT_WINE_RT_PRIO_ENABLED);
1162             ui.sb_wine_base_prio->setValue(CARLA_DEFAULT_WINE_BASE_RT_PRIO);
1163             ui.sb_wine_server_prio->setValue(CARLA_DEFAULT_WINE_SERVER_RT_PRIO);
1164             break;
1165 
1166         // ------------------------------------------------------------------------------------------------------------
1167         // Experimental
1168 
1169         case TAB_INDEX_EXPERIMENTAL:
1170             resetExperimentalSettings();
1171             break;
1172         }
1173 
1174     }
1175 
resetExperimentalSettingsCarlaSettingsW::PrivateData1176     void resetExperimentalSettings()
1177     {
1178         // Forever experimental
1179         ui.cb_exp_plugin_bridges->setChecked(CARLA_DEFAULT_EXPERIMENTAL_PLUGIN_BRIDGES);
1180         ui.ch_exp_wine_bridges->setChecked(CARLA_DEFAULT_EXPERIMENTAL_WINE_BRIDGES);
1181         ui.ch_exp_jack_apps->setChecked(CARLA_DEFAULT_EXPERIMENTAL_JACK_APPS);
1182         ui.ch_exp_export_lv2->setChecked(CARLA_DEFAULT_EXPERIMENTAL_LV2_EXPORT);
1183         ui.ch_exp_load_lib_global->setChecked(CARLA_DEFAULT_EXPERIMENTAL_LOAD_LIB_GLOBAL);
1184         ui.ch_exp_prevent_bad_behaviour->setChecked(CARLA_DEFAULT_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR);
1185 
1186         // Temporary, until stable
1187         ui.cb_canvas_fancy_eyecandy->setChecked(CARLA_DEFAULT_CANVAS_FANCY_EYE_CANDY);
1188         ui.cb_canvas_use_opengl->setChecked(CARLA_DEFAULT_CANVAS_USE_OPENGL and ui.cb_canvas_use_opengl->isEnabled());
1189         ui.cb_canvas_render_hq_aa->setChecked(CARLA_DEFAULT_CANVAS_HQ_ANTIALIASING and ui.cb_canvas_render_hq_aa->isEnabled());
1190         ui.cb_canvas_inline_displays->setChecked(CARLA_DEFAULT_CANVAS_INLINE_DISPLAYS);
1191         ui.ch_engine_force_stereo->setChecked(CARLA_DEFAULT_FORCE_STEREO);
1192         ui.ch_engine_prefer_plugin_bridges->setChecked(CARLA_DEFAULT_PREFER_PLUGIN_BRIDGES);
1193     }
1194 };
1195 
CarlaSettingsW(QWidget * const parent,CarlaHost & host,const bool hasCanvas,const bool hasCanvasGL)1196 CarlaSettingsW::CarlaSettingsW(QWidget* const parent, CarlaHost& host, const bool hasCanvas, const bool hasCanvasGL)
1197     : QDialog(parent),
1198       self(new PrivateData(this, host))
1199 {
1200     // ----------------------------------------------------------------------------------------------------------------
1201     // Set-up GUI
1202 
1203     self->ui.lw_page->setFixedWidth(48 + 6*3 + fontMetricsHorizontalAdvance(self->ui.lw_page->fontMetrics(), "   Experimental   "));
1204 
1205     for (uint i=0; i < carla_get_engine_driver_count(); ++i)
1206         self->ui.cb_engine_audio_driver->addItem(carla_get_engine_driver_name(i));
1207 
1208     for (uint i=0; i < Theme::THEME_MAX; ++i)
1209         self->ui.cb_canvas_theme->addItem(getThemeName((Theme::List)i));
1210 
1211 #ifdef CARLA_OS_MAC
1212     self->ui.group_main_theme->setEnabled(false);
1213     self->ui.group_main_theme->setVisible(false);
1214 #endif
1215 
1216 #ifdef CARLA_OS_Win
1217     if (true)
1218 #else
1219     if (host.isControl)
1220 #endif
1221     {
1222         self->ui.ch_main_show_logs->setEnabled(false);
1223         self->ui.ch_main_show_logs->setVisible(false);
1224     }
1225 
1226     if (host.isControl)
1227     {
1228         self->ui.lw_page->hideRow(TAB_INDEX_ENGINE);
1229         self->ui.lw_page->hideRow(TAB_INDEX_FILEPATHS);
1230         self->ui.lw_page->hideRow(TAB_INDEX_PLUGINPATHS);
1231         self->ui.ch_exp_export_lv2->hide();
1232         self->ui.group_experimental_engine->hide();
1233     }
1234     else if (! hasCanvas)
1235     {
1236         self->ui.lw_page->hideRow(TAB_INDEX_CANVAS);
1237     }
1238     else if (! hasCanvasGL)
1239     {
1240         self->ui.cb_canvas_use_opengl->setEnabled(false);
1241         self->ui.cb_canvas_render_hq_aa->setEnabled(false);
1242     }
1243 
1244     if (host.isPlugin)
1245         self->ui.cb_engine_audio_driver->setEnabled(false);
1246 
1247     if (host.audioDriverForced.isNotEmpty())
1248     {
1249         self->ui.cb_engine_audio_driver->setEnabled(false);
1250         self->ui.tb_engine_driver_config->setEnabled(false);
1251     }
1252 
1253     if (host.processModeForced)
1254     {
1255         self->ui.cb_engine_process_mode_jack->setEnabled(false);
1256         self->ui.cb_engine_process_mode_other->setEnabled(false);
1257 
1258         if (host.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
1259             self->ui.ch_engine_force_stereo->setEnabled(false);
1260     }
1261 
1262     if (host.isControl || host.isPlugin)
1263     {
1264         self->ui.ch_main_confirm_exit->hide();
1265         self->ui.ch_exp_load_lib_global->hide();
1266         self->ui.lw_page->hideRow(TAB_INDEX_OSC);
1267         self->ui.lw_page->hideRow(TAB_INDEX_WINE);
1268     }
1269 
1270 #ifndef CARLA_OS_LINUX
1271     self->ui.ch_exp_wine_bridges->setVisible(false);
1272     self->ui.ch_exp_jack_apps->setVisible(false);
1273     self->ui.ch_exp_prevent_bad_behaviour->setVisible(false);
1274     self->ui.lw_page->hideRow(TAB_INDEX_WINE);
1275 #endif
1276 
1277 #ifndef CARLA_OS_MAC
1278     self->ui.label_engine_ui_bridges_mac_note->setVisible(false);
1279 #endif
1280 
1281     // FIXME, not implemented yet
1282     self->ui.ch_engine_uis_always_on_top->hide();
1283 
1284     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
1285 
1286     // ----------------------------------------------------------------------------------------------------------------
1287     // Load settings
1288 
1289     self->loadSettings();
1290 
1291     // ----------------------------------------------------------------------------------------------------------------
1292     // Set-up connections
1293 
1294     connect(this, SIGNAL(accepted()), SLOT(slot_saveSettings()));
1295     connect(self->ui.buttonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()), SLOT(slot_resetSettings()));
1296 
1297     connect(self->ui.b_main_proj_folder_open, SIGNAL(clicked()), SLOT(slot_getAndSetProjectPath()));
1298 
1299     connect(self->ui.cb_engine_audio_driver, SIGNAL(currentIndexChanged(int)), SLOT(slot_engineAudioDriverChanged()));
1300     connect(self->ui.tb_engine_driver_config, SIGNAL(clicked()), SLOT(slot_showAudioDriverSettings()));
1301 
1302     connect(self->ui.b_paths_add, SIGNAL(clicked()), SLOT(slot_addPluginPath()));
1303     connect(self->ui.b_paths_remove, SIGNAL(clicked()), SLOT(slot_removePluginPath()));
1304     connect(self->ui.b_paths_change, SIGNAL(clicked()), SLOT(slot_changePluginPath()));
1305     connect(self->ui.cb_paths, SIGNAL(currentIndexChanged(int)), SLOT(slot_pluginPathTabChanged(int)));
1306     connect(self->ui.lw_ladspa, SIGNAL(currentRowChanged(int)), SLOT(slot_pluginPathRowChanged(int)));
1307     connect(self->ui.lw_dssi, SIGNAL(currentRowChanged(int)), SLOT(slot_pluginPathRowChanged(int)));
1308     connect(self->ui.lw_lv2, SIGNAL(currentRowChanged(int)), SLOT(slot_pluginPathRowChanged(int)));
1309     connect(self->ui.lw_vst, SIGNAL(currentRowChanged(int)), SLOT(slot_pluginPathRowChanged(int)));
1310     connect(self->ui.lw_vst3, SIGNAL(currentRowChanged(int)), SLOT(slot_pluginPathRowChanged(int)));
1311     connect(self->ui.lw_sf2, SIGNAL(currentRowChanged(int)), SLOT(slot_pluginPathRowChanged(int)));
1312     connect(self->ui.lw_sfz, SIGNAL(currentRowChanged(int)), SLOT(slot_pluginPathRowChanged(int)));
1313 
1314     connect(self->ui.b_filepaths_add, SIGNAL(clicked()), SLOT(slot_addFilePath()));
1315     connect(self->ui.b_filepaths_remove, SIGNAL(clicked()), SLOT(slot_removeFilePath()));
1316     connect(self->ui.b_filepaths_change, SIGNAL(clicked()), SLOT(slot_changeFilePath()));
1317     connect(self->ui.cb_filepaths, SIGNAL(currentIndexChanged(int)), SLOT(slot_filePathTabChanged(int)));
1318     connect(self->ui.lw_files_audio, SIGNAL(currentRowChanged(int)), SLOT(slot_filePathRowChanged(int)));
1319     connect(self->ui.lw_files_midi, SIGNAL(currentRowChanged(int)), SLOT(slot_filePathRowChanged(int)));
1320 
1321     connect(self->ui.ch_main_experimental, SIGNAL(toggled(bool)), SLOT(slot_enableExperimental(bool)));
1322     connect(self->ui.ch_exp_wine_bridges, SIGNAL(toggled(bool)), SLOT(slot_enableWineBridges(bool)));
1323     connect(self->ui.cb_exp_plugin_bridges, SIGNAL(toggled(bool)), SLOT(slot_pluginBridgesToggled(bool)));
1324     connect(self->ui.cb_canvas_eyecandy, SIGNAL(toggled(bool)), SLOT(slot_canvasEyeCandyToggled(bool)));
1325     connect(self->ui.cb_canvas_fancy_eyecandy, SIGNAL(toggled(bool)), SLOT(slot_canvasFancyEyeCandyToggled(bool)));
1326     connect(self->ui.cb_canvas_use_opengl, SIGNAL(toggled(bool)), SLOT(slot_canvasOpenGLToggled(bool)));
1327 
1328     // ----------------------------------------------------------------------------------------------------------------
1329     // Post-connect setup
1330 
1331     self->ui.lw_ladspa->setCurrentRow(0);
1332     self->ui.lw_dssi->setCurrentRow(0);
1333     self->ui.lw_lv2->setCurrentRow(0);
1334     self->ui.lw_vst->setCurrentRow(0);
1335     self->ui.lw_vst3->setCurrentRow(0);
1336     self->ui.lw_sf2->setCurrentRow(0);
1337     self->ui.lw_sfz->setCurrentRow(0);
1338 
1339     self->ui.lw_files_audio->setCurrentRow(0);
1340     self->ui.lw_files_midi->setCurrentRow(0);
1341 
1342     self->ui.lw_page->setCurrentCell(0, 0);
1343 
1344     slot_filePathTabChanged(0);
1345     slot_pluginPathTabChanged(0);
1346 
1347     adjustSize();
1348 }
1349 
~CarlaSettingsW()1350 CarlaSettingsW::~CarlaSettingsW()
1351 {
1352     delete self;
1353 }
1354 
1355 // --------------------------------------------------------------------------------------------------------------------
1356 
slot_saveSettings()1357 void CarlaSettingsW::slot_saveSettings()
1358 {
1359     self->saveSettings();
1360 }
1361 
slot_resetSettings()1362 void CarlaSettingsW::slot_resetSettings()
1363 {
1364     self->resetSettings();
1365 }
1366 
1367 // --------------------------------------------------------------------------------------------------------------------
1368 
slot_enableExperimental(const bool toggled)1369 void CarlaSettingsW::slot_enableExperimental(const bool toggled)
1370 {
1371     if (toggled)
1372     {
1373         self->ui.lw_page->showRow(TAB_INDEX_EXPERIMENTAL);
1374         if (self->ui.ch_exp_wine_bridges->isChecked() and not self->host.isControl)
1375             self->ui.lw_page->showRow(TAB_INDEX_WINE);
1376     }
1377     else
1378     {
1379         self->ui.lw_page->hideRow(TAB_INDEX_EXPERIMENTAL);
1380         self->ui.lw_page->hideRow(TAB_INDEX_WINE);
1381     }
1382 }
1383 
slot_enableWineBridges(const bool toggled)1384 void CarlaSettingsW::slot_enableWineBridges(const bool toggled)
1385 {
1386     if (toggled && ! self->host.isControl)
1387         self->ui.lw_page->showRow(TAB_INDEX_WINE);
1388     else
1389         self->ui.lw_page->hideRow(TAB_INDEX_WINE);
1390 }
1391 
slot_pluginBridgesToggled(const bool toggled)1392 void CarlaSettingsW::slot_pluginBridgesToggled(const bool toggled)
1393 {
1394     if (! toggled)
1395     {
1396         self->ui.ch_exp_wine_bridges->setChecked(false);
1397         self->ui.ch_engine_prefer_plugin_bridges->setChecked(false);
1398         self->ui.lw_page->hideRow(TAB_INDEX_WINE);
1399     }
1400 }
1401 
slot_canvasEyeCandyToggled(const bool toggled)1402 void CarlaSettingsW::slot_canvasEyeCandyToggled(const bool toggled)
1403 {
1404     if (! toggled)
1405     {
1406         // disable fancy eyecandy too
1407         self->ui.cb_canvas_fancy_eyecandy->setChecked(false);
1408     }
1409 }
1410 
slot_canvasFancyEyeCandyToggled(const bool toggled)1411 void CarlaSettingsW::slot_canvasFancyEyeCandyToggled(const bool toggled)
1412 {
1413     if (! toggled)
1414     {
1415         // make sure normal eyecandy is enabled too
1416         self->ui.cb_canvas_eyecandy->setChecked(true);
1417     }
1418 }
1419 
slot_canvasOpenGLToggled(const bool toggled)1420 void CarlaSettingsW::slot_canvasOpenGLToggled(const bool toggled)
1421 {
1422     if (! toggled)
1423     {
1424         // uncheck GL specific option
1425         self->ui.cb_canvas_render_hq_aa->setChecked(false);
1426     }
1427 }
1428 
1429 // --------------------------------------------------------------------------------------------------------------------
1430 
slot_getAndSetProjectPath()1431 void CarlaSettingsW::slot_getAndSetProjectPath()
1432 {
1433     // FIXME?
1434     getAndSetPath(this, self->ui.le_main_proj_folder);
1435 }
1436 
1437 // --------------------------------------------------------------------------------------------------------------------
1438 
slot_engineAudioDriverChanged()1439 void CarlaSettingsW::slot_engineAudioDriverChanged()
1440 {
1441     if (self->ui.cb_engine_audio_driver->currentText() == "JACK")
1442         self->ui.sw_engine_process_mode->setCurrentIndex(0);
1443     else
1444         self->ui.sw_engine_process_mode->setCurrentIndex(1);
1445 }
1446 
slot_showAudioDriverSettings()1447 void CarlaSettingsW::slot_showAudioDriverSettings()
1448 {
1449     const int     driverIndex = self->ui.cb_engine_audio_driver->currentIndex();
1450     const QString driverName  = self->ui.cb_engine_audio_driver->currentText();
1451     CARLA_SAFE_ASSERT_RETURN(driverIndex >= 0,);
1452 
1453     DriverSettingsW(this, static_cast<uint>(driverIndex), driverName).exec();
1454 }
1455 
1456 // --------------------------------------------------------------------------------------------------------------------
1457 
slot_addPluginPath()1458 void CarlaSettingsW::slot_addPluginPath()
1459 {
1460     const QString newPath = QFileDialog::getExistingDirectory(this, tr("Add Path"), "", QFileDialog::ShowDirsOnly);
1461 
1462     if (newPath.isEmpty())
1463         return;
1464 
1465     switch (self->ui.tw_paths->currentIndex())
1466     {
1467     case PLUGINPATH_INDEX_LADSPA:
1468         self->ui.lw_ladspa->addItem(newPath);
1469         break;
1470     case PLUGINPATH_INDEX_DSSI:
1471         self->ui.lw_dssi->addItem(newPath);
1472         break;
1473     case PLUGINPATH_INDEX_LV2:
1474         self->ui.lw_lv2->addItem(newPath);
1475         break;
1476     case PLUGINPATH_INDEX_VST2:
1477         self->ui.lw_vst->addItem(newPath);
1478         break;
1479     case PLUGINPATH_INDEX_VST3:
1480         self->ui.lw_vst3->addItem(newPath);
1481         break;
1482     case PLUGINPATH_INDEX_SF2:
1483         self->ui.lw_sf2->addItem(newPath);
1484         break;
1485     case PLUGINPATH_INDEX_SFZ:
1486         self->ui.lw_sfz->addItem(newPath);
1487         break;
1488     }
1489 }
1490 
slot_removePluginPath()1491 void CarlaSettingsW::slot_removePluginPath()
1492 {
1493     switch (self->ui.tw_paths->currentIndex())
1494     {
1495     case PLUGINPATH_INDEX_LADSPA:
1496         self->ui.lw_ladspa->takeItem(self->ui.lw_ladspa->currentRow());
1497         break;
1498     case PLUGINPATH_INDEX_DSSI:
1499         self->ui.lw_dssi->takeItem(self->ui.lw_dssi->currentRow());
1500         break;
1501     case PLUGINPATH_INDEX_LV2:
1502         self->ui.lw_lv2->takeItem(self->ui.lw_lv2->currentRow());
1503         break;
1504     case PLUGINPATH_INDEX_VST2:
1505         self->ui.lw_vst->takeItem(self->ui.lw_vst->currentRow());
1506         break;
1507     case PLUGINPATH_INDEX_VST3:
1508         self->ui.lw_vst3->takeItem(self->ui.lw_vst3->currentRow());
1509         break;
1510     case PLUGINPATH_INDEX_SF2:
1511         self->ui.lw_sf2->takeItem(self->ui.lw_sf2->currentRow());
1512         break;
1513     case PLUGINPATH_INDEX_SFZ:
1514         self->ui.lw_sfz->takeItem(self->ui.lw_sfz->currentRow());
1515         break;
1516     }
1517 }
1518 
slot_changePluginPath()1519 void CarlaSettingsW::slot_changePluginPath()
1520 {
1521     const int curIndex = self->ui.tw_paths->currentIndex();
1522 
1523     QString currentPath;
1524 
1525     switch (curIndex)
1526     {
1527     case PLUGINPATH_INDEX_LADSPA:
1528         currentPath = self->ui.lw_ladspa->currentItem()->text();
1529         break;
1530     case PLUGINPATH_INDEX_DSSI:
1531         currentPath = self->ui.lw_dssi->currentItem()->text();
1532         break;
1533     case PLUGINPATH_INDEX_LV2:
1534         currentPath = self->ui.lw_lv2->currentItem()->text();
1535         break;
1536     case PLUGINPATH_INDEX_VST2:
1537         currentPath = self->ui.lw_vst->currentItem()->text();
1538         break;
1539     case PLUGINPATH_INDEX_VST3:
1540         currentPath = self->ui.lw_vst3->currentItem()->text();
1541         break;
1542     case PLUGINPATH_INDEX_SF2:
1543         currentPath = self->ui.lw_sf2->currentItem()->text();
1544         break;
1545     case PLUGINPATH_INDEX_SFZ:
1546         currentPath = self->ui.lw_sfz->currentItem()->text();
1547         break;
1548     }
1549 
1550     const QString newPath = QFileDialog::getExistingDirectory(this, tr("Add Path"), currentPath, QFileDialog::ShowDirsOnly);
1551 
1552     if (newPath.isEmpty())
1553         return;
1554 
1555     switch (curIndex)
1556     {
1557     case PLUGINPATH_INDEX_LADSPA:
1558         self->ui.lw_ladspa->currentItem()->setText(newPath);
1559         break;
1560     case PLUGINPATH_INDEX_DSSI:
1561         self->ui.lw_dssi->currentItem()->setText(newPath);
1562         break;
1563     case PLUGINPATH_INDEX_LV2:
1564         self->ui.lw_lv2->currentItem()->setText(newPath);
1565         break;
1566     case PLUGINPATH_INDEX_VST2:
1567         self->ui.lw_vst->currentItem()->setText(newPath);
1568         break;
1569     case PLUGINPATH_INDEX_VST3:
1570         self->ui.lw_vst3->currentItem()->setText(newPath);
1571         break;
1572     case PLUGINPATH_INDEX_SF2:
1573         self->ui.lw_sf2->currentItem()->setText(newPath);
1574         break;
1575     case PLUGINPATH_INDEX_SFZ:
1576         self->ui.lw_sfz->currentItem()->setText(newPath);
1577         break;
1578     }
1579 }
1580 
1581 // --------------------------------------------------------------------------------------------------------------------
1582 
slot_pluginPathTabChanged(const int index)1583 void CarlaSettingsW::slot_pluginPathTabChanged(const int index)
1584 {
1585     int row;
1586 
1587     switch (index)
1588     {
1589     case PLUGINPATH_INDEX_LADSPA:
1590         row = self->ui.lw_ladspa->currentRow();
1591         break;
1592     case PLUGINPATH_INDEX_DSSI:
1593         row = self->ui.lw_dssi->currentRow();
1594         break;
1595     case PLUGINPATH_INDEX_LV2:
1596         row = self->ui.lw_lv2->currentRow();
1597         break;
1598     case PLUGINPATH_INDEX_VST2:
1599         row = self->ui.lw_vst->currentRow();
1600         break;
1601     case PLUGINPATH_INDEX_VST3:
1602         row = self->ui.lw_vst3->currentRow();
1603         break;
1604     case PLUGINPATH_INDEX_SF2:
1605         row = self->ui.lw_sf2->currentRow();
1606         break;
1607     case PLUGINPATH_INDEX_SFZ:
1608         row = self->ui.lw_sfz->currentRow();
1609         break;
1610     default:
1611         row = -1;
1612         break;
1613     }
1614 
1615     slot_pluginPathRowChanged(row);
1616 }
1617 
slot_pluginPathRowChanged(const int row)1618 void CarlaSettingsW::slot_pluginPathRowChanged(const int row)
1619 {
1620     const bool check = bool(row >= 0);
1621     self->ui.b_paths_remove->setEnabled(check);
1622     self->ui.b_paths_change->setEnabled(check);
1623 }
1624 
1625 // --------------------------------------------------------------------------------------------------------------------
1626 
slot_addFilePath()1627 void CarlaSettingsW::slot_addFilePath()
1628 {
1629     const QString newPath = QFileDialog::getExistingDirectory(this, tr("Add Path"), "", QFileDialog::ShowDirsOnly);
1630 
1631     if (newPath.isEmpty())
1632         return;
1633 
1634     switch (self->ui.tw_filepaths->currentIndex())
1635     {
1636     case FILEPATH_INDEX_AUDIO:
1637         self->ui.lw_files_audio->addItem(newPath);
1638         break;
1639     case FILEPATH_INDEX_MIDI:
1640         self->ui.lw_files_midi->addItem(newPath);
1641         break;
1642     }
1643 }
1644 
slot_removeFilePath()1645 void CarlaSettingsW::slot_removeFilePath()
1646 {
1647     switch (self->ui.tw_filepaths->currentIndex())
1648     {
1649     case FILEPATH_INDEX_AUDIO:
1650         self->ui.lw_files_audio->takeItem(self->ui.lw_files_audio->currentRow());
1651         break;
1652     case FILEPATH_INDEX_MIDI:
1653         self->ui.lw_files_midi->takeItem(self->ui.lw_files_midi->currentRow());
1654         break;
1655     }
1656 }
1657 
slot_changeFilePath()1658 void CarlaSettingsW::slot_changeFilePath()
1659 {
1660     const int curIndex = self->ui.tw_filepaths->currentIndex();
1661 
1662     QString currentPath;
1663 
1664     switch (curIndex)
1665     {
1666     case FILEPATH_INDEX_AUDIO:
1667         currentPath = self->ui.lw_files_audio->currentItem()->text();
1668         break;
1669     case FILEPATH_INDEX_MIDI:
1670         currentPath = self->ui.lw_files_midi->currentItem()->text();
1671         break;
1672     }
1673 
1674     const QString newPath = QFileDialog::getExistingDirectory(this, tr("Add Path"), currentPath, QFileDialog::ShowDirsOnly);
1675 
1676     if (newPath.isEmpty())
1677         return;
1678 
1679     switch (curIndex)
1680     {
1681     case FILEPATH_INDEX_AUDIO:
1682         self->ui.lw_files_audio->currentItem()->setText(newPath);
1683         break;
1684     case FILEPATH_INDEX_MIDI:
1685         self->ui.lw_files_midi->currentItem()->setText(newPath);
1686         break;
1687     }
1688 }
1689 
1690 // --------------------------------------------------------------------------------------------------------------------
1691 
slot_filePathTabChanged(const int index)1692 void CarlaSettingsW::slot_filePathTabChanged(const int index)
1693 {
1694     int row;
1695 
1696     switch (index)
1697     {
1698     case FILEPATH_INDEX_AUDIO:
1699         row = self->ui.lw_files_audio->currentRow();
1700         break;
1701     case FILEPATH_INDEX_MIDI:
1702         row = self->ui.lw_files_midi->currentRow();
1703         break;
1704     default:
1705         row = -1;
1706         break;
1707     }
1708 
1709     slot_filePathRowChanged(row);
1710 }
1711 
slot_filePathRowChanged(const int row)1712 void CarlaSettingsW::slot_filePathRowChanged(const int row)
1713 {
1714     const bool check = bool(row >= 0);
1715     self->ui.b_filepaths_remove->setEnabled(check);
1716     self->ui.b_filepaths_change->setEnabled(check);
1717 }
1718 
1719 // --------------------------------------------------------------------------------------------------------------------
1720