mainwindow.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. #include <QFileDialog>
  2. #include <QMessageBox>
  3. #include <QSettings>
  4. #include <QtGlobal>
  5. #include "mainwindow.h"
  6. #include "ui_mainwindow.h"
  7. namespace {
  8. static const struct {
  9. char backend_name[16];
  10. char menu_string[32];
  11. } backendMenuList[] = {
  12. #ifdef Q_OS_WIN32
  13. { "mmdevapi", "Add MMDevAPI" },
  14. { "dsound", "Add DirectSound" },
  15. { "winmm", "Add Windows Multimedia" },
  16. #endif
  17. #ifdef Q_OS_MAC
  18. { "core", "Add CoreAudio" },
  19. #endif
  20. { "pulse", "Add PulseAudio" },
  21. #ifdef Q_OS_UNIX
  22. { "alsa", "Add ALSA" },
  23. { "oss", "Add OSS" },
  24. { "solaris", "Add Solaris" },
  25. { "sndio", "Add SndIO" },
  26. { "qsa", "Add QSA" },
  27. #endif
  28. { "port", "Add PortAudio" },
  29. { "opensl", "Add OpenSL" },
  30. { "null", "Add Null Output" },
  31. { "wave", "Add Wave Writer" },
  32. { "", "" }
  33. };
  34. static QString getDefaultConfigName()
  35. {
  36. #ifdef Q_OS_WIN32
  37. static const char fname[] = "alsoft.ini";
  38. QByteArray base = qgetenv("AppData");
  39. #else
  40. static const char fname[] = "alsoft.conf";
  41. QByteArray base = qgetenv("XDG_CONFIG_HOME");
  42. if(base.isEmpty())
  43. {
  44. base = qgetenv("HOME");
  45. if(base.isEmpty() == false)
  46. base += "/.config";
  47. }
  48. #endif
  49. if(base.isEmpty() == false)
  50. return base +'/'+ fname;
  51. return fname;
  52. }
  53. }
  54. MainWindow::MainWindow(QWidget *parent) :
  55. QMainWindow(parent),
  56. ui(new Ui::MainWindow),
  57. mPeriodSizeValidator(NULL),
  58. mPeriodCountValidator(NULL),
  59. mSourceCountValidator(NULL),
  60. mEffectSlotValidator(NULL),
  61. mSourceSendValidator(NULL),
  62. mSampleRateValidator(NULL),
  63. mReverbBoostValidator(NULL)
  64. {
  65. ui->setupUi(this);
  66. mPeriodSizeValidator = new QIntValidator(64, 8192, this);
  67. ui->periodSizeEdit->setValidator(mPeriodSizeValidator);
  68. mPeriodCountValidator = new QIntValidator(2, 16, this);
  69. ui->periodCountEdit->setValidator(mPeriodCountValidator);
  70. mSourceCountValidator = new QIntValidator(0, 256, this);
  71. ui->srcCountLineEdit->setValidator(mSourceCountValidator);
  72. mEffectSlotValidator = new QIntValidator(0, 16, this);
  73. ui->effectSlotLineEdit->setValidator(mEffectSlotValidator);
  74. mSourceSendValidator = new QIntValidator(0, 4, this);
  75. ui->srcSendLineEdit->setValidator(mSourceSendValidator);
  76. mSampleRateValidator = new QIntValidator(8000, 192000, this);
  77. ui->sampleRateCombo->lineEdit()->setValidator(mSampleRateValidator);
  78. mReverbBoostValidator = new QDoubleValidator(-12.0, +12.0, 1, this);
  79. ui->reverbBoostEdit->setValidator(mReverbBoostValidator);
  80. connect(ui->actionLoad, SIGNAL(triggered()), this, SLOT(loadConfigFromFile()));
  81. connect(ui->actionSave_As, SIGNAL(triggered()), this, SLOT(saveConfigAsFile()));
  82. connect(ui->applyButton, SIGNAL(clicked()), this, SLOT(saveCurrentConfig()));
  83. connect(ui->periodSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(updatePeriodSizeEdit(int)));
  84. connect(ui->periodSizeEdit, SIGNAL(editingFinished()), this, SLOT(updatePeriodSizeSlider()));
  85. connect(ui->periodCountSlider, SIGNAL(valueChanged(int)), this, SLOT(updatePeriodCountEdit(int)));
  86. connect(ui->periodCountEdit, SIGNAL(editingFinished()), this, SLOT(updatePeriodCountSlider()));
  87. connect(ui->hrtfAddButton, SIGNAL(clicked()), this, SLOT(addHrtfFile()));
  88. connect(ui->hrtfRemoveButton, SIGNAL(clicked()), this, SLOT(removeHrtfFile()));
  89. connect(ui->hrtfFileList, SIGNAL(itemSelectionChanged()), this, SLOT(updateHrtfRemoveButton()));
  90. ui->enabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu);
  91. connect(ui->enabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showEnabledBackendMenu(QPoint)));
  92. ui->disabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu);
  93. connect(ui->disabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDisabledBackendMenu(QPoint)));
  94. connect(ui->reverbBoostSlider, SIGNAL(valueChanged(int)), this, SLOT(updateReverbBoostEdit(int)));
  95. connect(ui->reverbBoostEdit, SIGNAL(textEdited(QString)), this, SLOT(updateReverbBoostSlider(QString)));
  96. loadConfig(getDefaultConfigName());
  97. }
  98. MainWindow::~MainWindow()
  99. {
  100. delete ui;
  101. delete mPeriodSizeValidator;
  102. delete mPeriodCountValidator;
  103. delete mSourceCountValidator;
  104. delete mEffectSlotValidator;
  105. delete mSourceSendValidator;
  106. delete mSampleRateValidator;
  107. delete mReverbBoostValidator;
  108. }
  109. void MainWindow::loadConfigFromFile()
  110. {
  111. QString fname = QFileDialog::getOpenFileName(this, tr("Select Files"));
  112. if(fname.isEmpty() == false)
  113. loadConfig(fname);
  114. }
  115. void MainWindow::loadConfig(const QString &fname)
  116. {
  117. QSettings settings(fname, QSettings::IniFormat);
  118. QString sampletype = settings.value("sample-type").toString();
  119. ui->sampleFormatCombo->setCurrentIndex(0);
  120. if(sampletype.isEmpty() == false)
  121. {
  122. for(int i = 1;i < ui->sampleFormatCombo->count();i++)
  123. {
  124. QString item = ui->sampleFormatCombo->itemText(i);
  125. if(item.startsWith(sampletype))
  126. {
  127. ui->sampleFormatCombo->setCurrentIndex(i);
  128. break;
  129. }
  130. }
  131. }
  132. QString channelconfig = settings.value("channels").toString();
  133. ui->channelConfigCombo->setCurrentIndex(0);
  134. if(channelconfig.isEmpty() == false)
  135. {
  136. for(int i = 1;i < ui->channelConfigCombo->count();i++)
  137. {
  138. QString item = ui->channelConfigCombo->itemText(i);
  139. if(item.startsWith(channelconfig))
  140. {
  141. ui->channelConfigCombo->setCurrentIndex(i);
  142. break;
  143. }
  144. }
  145. }
  146. QString srate = settings.value("frequency").toString();
  147. if(srate.isEmpty())
  148. ui->sampleRateCombo->setCurrentIndex(0);
  149. else
  150. {
  151. ui->sampleRateCombo->lineEdit()->clear();
  152. ui->sampleRateCombo->lineEdit()->insert(srate);
  153. }
  154. ui->srcCountLineEdit->clear();
  155. ui->srcCountLineEdit->insert(settings.value("sources").toString());
  156. ui->effectSlotLineEdit->clear();
  157. ui->effectSlotLineEdit->insert(settings.value("slots").toString());
  158. ui->srcSendLineEdit->clear();
  159. ui->srcSendLineEdit->insert(settings.value("sends").toString());
  160. QString resampler = settings.value("resampler").toString().trimmed();
  161. if(resampler.isEmpty())
  162. ui->resamplerComboBox->setCurrentIndex(0);
  163. else
  164. {
  165. for(int i = 1;i < ui->resamplerComboBox->count();i++)
  166. {
  167. QString item = ui->resamplerComboBox->itemText(i);
  168. int end = item.indexOf(' ');
  169. if(end < 0) end = item.size();
  170. if(resampler.size() == end && resampler.compare(item.leftRef(end), Qt::CaseInsensitive) == 0)
  171. {
  172. ui->resamplerComboBox->setCurrentIndex(i);
  173. break;
  174. }
  175. }
  176. }
  177. int periodsize = settings.value("period_size").toInt();
  178. ui->periodSizeEdit->clear();
  179. if(periodsize >= 64)
  180. {
  181. ui->periodSizeEdit->insert(QString::number(periodsize));
  182. updatePeriodSizeSlider();
  183. }
  184. int periodcount = settings.value("periods").toInt();
  185. ui->periodCountEdit->clear();
  186. if(periodcount >= 2)
  187. {
  188. ui->periodCountEdit->insert(QString::number(periodcount));
  189. updatePeriodCountSlider();
  190. }
  191. QStringList disabledCpuExts = settings.value("disable-cpu-exts").toStringList();
  192. if(disabledCpuExts.size() == 1)
  193. disabledCpuExts = disabledCpuExts[0].split(QChar(','));
  194. std::transform(disabledCpuExts.begin(), disabledCpuExts.end(),
  195. disabledCpuExts.begin(), std::mem_fun_ref(&QString::trimmed));
  196. ui->disableSSECheckBox->setChecked(disabledCpuExts.contains("sse", Qt::CaseInsensitive));
  197. ui->disableSSE2CheckBox->setChecked(disabledCpuExts.contains("sse2", Qt::CaseInsensitive));
  198. ui->disableNeonCheckBox->setChecked(disabledCpuExts.contains("neon", Qt::CaseInsensitive));
  199. if(settings.value("hrtf").toString() == QString())
  200. ui->hrtfEnableButton->setChecked(true);
  201. else
  202. {
  203. if(settings.value("hrtf", true).toBool())
  204. ui->hrtfForceButton->setChecked(true);
  205. else
  206. ui->hrtfDisableButton->setChecked(true);
  207. }
  208. QStringList hrtf_tables = settings.value("hrtf_tables").toStringList();
  209. if(hrtf_tables.size() == 1)
  210. hrtf_tables = hrtf_tables[0].split(QChar(','));
  211. std::transform(hrtf_tables.begin(), hrtf_tables.end(),
  212. hrtf_tables.begin(), std::mem_fun_ref(&QString::trimmed));
  213. ui->hrtfFileList->clear();
  214. ui->hrtfFileList->addItems(hrtf_tables);
  215. updateHrtfRemoveButton();
  216. ui->enabledBackendList->clear();
  217. ui->disabledBackendList->clear();
  218. QStringList drivers = settings.value("drivers").toStringList();
  219. if(drivers.size() == 0)
  220. ui->backendCheckBox->setChecked(true);
  221. else
  222. {
  223. if(drivers.size() == 1)
  224. drivers = drivers[0].split(QChar(','));
  225. std::transform(drivers.begin(), drivers.end(),
  226. drivers.begin(), std::mem_fun_ref(&QString::trimmed));
  227. bool lastWasEmpty = false;
  228. foreach(const QString &backend, drivers)
  229. {
  230. lastWasEmpty = backend.isEmpty();
  231. if(!backend.startsWith(QChar('-')) && !lastWasEmpty)
  232. ui->enabledBackendList->addItem(backend);
  233. else if(backend.size() > 1)
  234. ui->disabledBackendList->addItem(backend.right(backend.size()-1));
  235. }
  236. ui->backendCheckBox->setChecked(lastWasEmpty);
  237. }
  238. QString defaultreverb = settings.value("default-reverb").toString().toLower();
  239. ui->defaultReverbComboBox->setCurrentIndex(0);
  240. if(defaultreverb.isEmpty() == false)
  241. {
  242. for(int i = 0;i < ui->defaultReverbComboBox->count();i++)
  243. {
  244. if(defaultreverb.compare(ui->defaultReverbComboBox->itemText(i).toLower()) == 0)
  245. {
  246. ui->defaultReverbComboBox->setCurrentIndex(i);
  247. break;
  248. }
  249. }
  250. }
  251. ui->emulateEaxCheckBox->setChecked(settings.value("reverb/emulate-eax", false).toBool());
  252. ui->reverbBoostEdit->clear();
  253. ui->reverbBoostEdit->insert(settings.value("reverb/boost").toString());
  254. QStringList excludefx = settings.value("excludefx").toStringList();
  255. if(excludefx.size() == 1)
  256. excludefx = excludefx[0].split(QChar(','));
  257. std::transform(excludefx.begin(), excludefx.end(),
  258. excludefx.begin(), std::mem_fun_ref(&QString::trimmed));
  259. ui->disableEaxReverbCheck->setChecked(excludefx.contains("eaxreverb", Qt::CaseInsensitive));
  260. ui->disableStdReverbCheck->setChecked(excludefx.contains("reverb", Qt::CaseInsensitive));
  261. ui->disableChorusCheck->setChecked(excludefx.contains("chorus", Qt::CaseInsensitive));
  262. ui->disableDistortionCheck->setChecked(excludefx.contains("distortion", Qt::CaseInsensitive));
  263. ui->disableEchoCheck->setChecked(excludefx.contains("echo", Qt::CaseInsensitive));
  264. ui->disableEqualizerCheck->setChecked(excludefx.contains("equalizer", Qt::CaseInsensitive));
  265. ui->disableFlangerCheck->setChecked(excludefx.contains("flanger", Qt::CaseInsensitive));
  266. ui->disableModulatorCheck->setChecked(excludefx.contains("modulator", Qt::CaseInsensitive));
  267. ui->disableDedicatedCheck->setChecked(excludefx.contains("dedicated", Qt::CaseInsensitive));
  268. }
  269. void MainWindow::saveCurrentConfig()
  270. {
  271. saveConfig(getDefaultConfigName());
  272. QMessageBox::information(this, tr("Information"),
  273. tr("Applications using OpenAL need to be restarted for changes to take effect."));
  274. }
  275. void MainWindow::saveConfigAsFile()
  276. {
  277. QString fname = QFileDialog::getOpenFileName(this, tr("Select Files"));
  278. if(fname.isEmpty() == false)
  279. saveConfig(fname);
  280. }
  281. void MainWindow::saveConfig(const QString &fname) const
  282. {
  283. QSettings settings(fname, QSettings::IniFormat);
  284. /* HACK: Compound any stringlist values into a comma-separated string. */
  285. QStringList allkeys = settings.allKeys();
  286. foreach(const QString &key, allkeys)
  287. {
  288. QStringList vals = settings.value(key).toStringList();
  289. if(vals.size() > 1)
  290. settings.setValue(key, vals.join(QChar(',')));
  291. }
  292. QString str = ui->sampleFormatCombo->currentText();
  293. str.truncate(str.indexOf('-'));
  294. settings.setValue("sample-type", str.trimmed());
  295. str = ui->channelConfigCombo->currentText();
  296. str.truncate(str.indexOf('-'));
  297. settings.setValue("channels", str.trimmed());
  298. uint rate = ui->sampleRateCombo->currentText().toUInt();
  299. if(rate == 0)
  300. settings.setValue("frequency", QString());
  301. else
  302. settings.setValue("frequency", rate);
  303. settings.setValue("period_size", ui->periodSizeEdit->text());
  304. settings.setValue("periods", ui->periodCountEdit->text());
  305. settings.setValue("sources", ui->srcCountLineEdit->text());
  306. settings.setValue("slots", ui->effectSlotLineEdit->text());
  307. if(ui->resamplerComboBox->currentIndex() == 0)
  308. settings.setValue("resampler", QString());
  309. else
  310. {
  311. str = ui->resamplerComboBox->currentText();
  312. settings.setValue("resampler", str.split(' ').first().toLower());
  313. }
  314. QStringList strlist;
  315. if(ui->disableSSECheckBox->isChecked())
  316. strlist.append("sse");
  317. if(ui->disableSSE2CheckBox->isChecked())
  318. strlist.append("sse2");
  319. if(ui->disableNeonCheckBox->isChecked())
  320. strlist.append("neon");
  321. settings.setValue("disable-cpu-exts", strlist.join(QChar(',')));
  322. if(ui->hrtfForceButton->isChecked())
  323. settings.setValue("hrtf", "true");
  324. else if(ui->hrtfDisableButton->isChecked())
  325. settings.setValue("hrtf", "false");
  326. else
  327. settings.setValue("hrtf", QString());
  328. strlist.clear();
  329. QList<QListWidgetItem*> items = ui->hrtfFileList->findItems("*", Qt::MatchWildcard);
  330. foreach(const QListWidgetItem *item, items)
  331. strlist.append(item->text());
  332. settings.setValue("hrtf_tables", strlist.join(QChar(',')));
  333. strlist.clear();
  334. items = ui->enabledBackendList->findItems("*", Qt::MatchWildcard);
  335. foreach(const QListWidgetItem *item, items)
  336. strlist.append(item->text());
  337. items = ui->disabledBackendList->findItems("*", Qt::MatchWildcard);
  338. foreach(const QListWidgetItem *item, items)
  339. strlist.append(QChar('-')+item->text());
  340. if(strlist.size() == 0 && !ui->backendCheckBox->isChecked())
  341. strlist.append("-all");
  342. else if(ui->backendCheckBox->isChecked())
  343. strlist.append(QString());
  344. settings.setValue("drivers", strlist.join(QChar(',')));
  345. // TODO: Remove check when we can properly match global values.
  346. if(ui->defaultReverbComboBox->currentIndex() == 0)
  347. settings.setValue("default-reverb", QString());
  348. else
  349. {
  350. str = ui->defaultReverbComboBox->currentText().toLower();
  351. settings.setValue("default-reverb", str);
  352. }
  353. if(ui->emulateEaxCheckBox->isChecked())
  354. settings.setValue("reverb/emulate-eax", "true");
  355. else
  356. settings.setValue("reverb/emulate-eax", QString()/*"false"*/);
  357. // TODO: Remove check when we can properly match global values.
  358. if(ui->reverbBoostSlider->sliderPosition() == 0)
  359. settings.setValue("reverb/boost", QString());
  360. else
  361. settings.setValue("reverb/boost", ui->reverbBoostEdit->text());
  362. strlist.clear();
  363. if(ui->disableEaxReverbCheck->isChecked())
  364. strlist.append("eaxreverb");
  365. if(ui->disableStdReverbCheck->isChecked())
  366. strlist.append("reverb");
  367. if(ui->disableChorusCheck->isChecked())
  368. strlist.append("chorus");
  369. if(ui->disableDistortionCheck->isChecked())
  370. strlist.append("distortion");
  371. if(ui->disableEchoCheck->isChecked())
  372. strlist.append("echo");
  373. if(ui->disableEqualizerCheck->isChecked())
  374. strlist.append("equalizer");
  375. if(ui->disableFlangerCheck->isChecked())
  376. strlist.append("flanger");
  377. if(ui->disableModulatorCheck->isChecked())
  378. strlist.append("modulator");
  379. if(ui->disableDedicatedCheck->isChecked())
  380. strlist.append("dedicated");
  381. settings.setValue("excludefx", strlist.join(QChar(',')));
  382. /* Remove empty keys
  383. * FIXME: Should only remove keys whose value matches the globally-specified value.
  384. */
  385. allkeys = settings.allKeys();
  386. foreach(const QString &key, allkeys)
  387. {
  388. str = settings.value(key).toString();
  389. if(str == QString())
  390. settings.remove(key);
  391. }
  392. }
  393. void MainWindow::updatePeriodSizeEdit(int size)
  394. {
  395. ui->periodSizeEdit->clear();
  396. if(size >= 64)
  397. {
  398. size = (size+32)&~0x3f;
  399. ui->periodSizeEdit->insert(QString::number(size));
  400. }
  401. }
  402. void MainWindow::updatePeriodSizeSlider()
  403. {
  404. int pos = ui->periodSizeEdit->text().toInt();
  405. if(pos >= 64)
  406. {
  407. if(pos > 8192)
  408. pos = 8192;
  409. ui->periodSizeSlider->setSliderPosition(pos);
  410. }
  411. }
  412. void MainWindow::updatePeriodCountEdit(int count)
  413. {
  414. ui->periodCountEdit->clear();
  415. if(count >= 2)
  416. ui->periodCountEdit->insert(QString::number(count));
  417. }
  418. void MainWindow::updatePeriodCountSlider()
  419. {
  420. int pos = ui->periodCountEdit->text().toInt();
  421. if(pos < 2)
  422. pos = 0;
  423. else if(pos > 16)
  424. pos = 16;
  425. ui->periodCountSlider->setSliderPosition(pos);
  426. }
  427. void MainWindow::addHrtfFile()
  428. {
  429. QStringList fnames = QFileDialog::getOpenFileNames(this, tr("Select Files"), QString(),
  430. "HRTF Datasets(*.mhr);;All Files(*.*)");
  431. if(fnames.isEmpty() == false)
  432. ui->hrtfFileList->addItems(fnames);
  433. }
  434. void MainWindow::removeHrtfFile()
  435. {
  436. QList<QListWidgetItem*> selected = ui->hrtfFileList->selectedItems();
  437. foreach(QListWidgetItem *item, selected)
  438. delete item;
  439. }
  440. void MainWindow::updateHrtfRemoveButton()
  441. {
  442. ui->hrtfRemoveButton->setEnabled(ui->hrtfFileList->selectedItems().size() != 0);
  443. }
  444. void MainWindow::showEnabledBackendMenu(QPoint pt)
  445. {
  446. QMap<QAction*,QString> actionMap;
  447. pt = ui->enabledBackendList->mapToGlobal(pt);
  448. QMenu ctxmenu;
  449. QAction *removeAction = ctxmenu.addAction(QIcon::fromTheme("list-remove"), "Remove");
  450. if(ui->enabledBackendList->selectedItems().size() == 0)
  451. removeAction->setEnabled(false);
  452. ctxmenu.addSeparator();
  453. for(size_t i = 0;backendMenuList[i].backend_name[0];i++)
  454. {
  455. QAction *action = ctxmenu.addAction(backendMenuList[i].menu_string);
  456. actionMap[action] = backendMenuList[i].backend_name;
  457. if(ui->enabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0 ||
  458. ui->disabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0)
  459. action->setEnabled(false);
  460. }
  461. QAction *gotAction = ctxmenu.exec(pt);
  462. if(gotAction == removeAction)
  463. {
  464. QList<QListWidgetItem*> selected = ui->enabledBackendList->selectedItems();
  465. foreach(QListWidgetItem *item, selected)
  466. delete item;
  467. }
  468. else if(gotAction != NULL)
  469. {
  470. QMap<QAction*,QString>::const_iterator iter = actionMap.find(gotAction);
  471. if(iter != actionMap.end())
  472. ui->enabledBackendList->addItem(iter.value());
  473. }
  474. }
  475. void MainWindow::showDisabledBackendMenu(QPoint pt)
  476. {
  477. QMap<QAction*,QString> actionMap;
  478. pt = ui->disabledBackendList->mapToGlobal(pt);
  479. QMenu ctxmenu;
  480. QAction *removeAction = ctxmenu.addAction(QIcon::fromTheme("list-remove"), "Remove");
  481. if(ui->disabledBackendList->selectedItems().size() == 0)
  482. removeAction->setEnabled(false);
  483. ctxmenu.addSeparator();
  484. for(size_t i = 0;backendMenuList[i].backend_name[0];i++)
  485. {
  486. QAction *action = ctxmenu.addAction(backendMenuList[i].menu_string);
  487. actionMap[action] = backendMenuList[i].backend_name;
  488. if(ui->disabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0 ||
  489. ui->enabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0)
  490. action->setEnabled(false);
  491. }
  492. QAction *gotAction = ctxmenu.exec(pt);
  493. if(gotAction == removeAction)
  494. {
  495. QList<QListWidgetItem*> selected = ui->disabledBackendList->selectedItems();
  496. foreach(QListWidgetItem *item, selected)
  497. delete item;
  498. }
  499. else if(gotAction != NULL)
  500. {
  501. QMap<QAction*,QString>::const_iterator iter = actionMap.find(gotAction);
  502. if(iter != actionMap.end())
  503. ui->disabledBackendList->addItem(iter.value());
  504. }
  505. }
  506. void MainWindow::updateReverbBoostEdit(int value)
  507. {
  508. ui->reverbBoostEdit->clear();
  509. if(value != 0)
  510. ui->reverbBoostEdit->insert(QString::number(value/10.0, 'f', 1));
  511. }
  512. void MainWindow::updateReverbBoostSlider(QString value)
  513. {
  514. int pos = int(value.toFloat()*10.0f);
  515. ui->reverbBoostSlider->setSliderPosition(pos);
  516. }