mainwindow.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. #include "config.h"
  2. #include <QFileDialog>
  3. #include <QMessageBox>
  4. #include <QSettings>
  5. #include <QtGlobal>
  6. #include "mainwindow.h"
  7. #include "ui_mainwindow.h"
  8. namespace {
  9. static const struct {
  10. char backend_name[16];
  11. char menu_string[32];
  12. } backendMenuList[] = {
  13. #ifdef HAVE_JACK
  14. { "jack", "Add JACK" },
  15. #endif
  16. #ifdef HAVE_PULSEAUDIO
  17. { "pulse", "Add PulseAudio" },
  18. #endif
  19. #ifdef HAVE_ALSA
  20. { "alsa", "Add ALSA" },
  21. #endif
  22. #ifdef HAVE_COREAUDIO
  23. { "core", "Add CoreAudio" },
  24. #endif
  25. #ifdef HAVE_OSS
  26. { "oss", "Add OSS" },
  27. #endif
  28. #ifdef HAVE_SOLARIS
  29. { "solaris", "Add Solaris" },
  30. #endif
  31. #ifdef HAVE_SNDIO
  32. { "sndio", "Add SndIO" },
  33. #endif
  34. #ifdef HAVE_QSA
  35. { "qsa", "Add QSA" },
  36. #endif
  37. #ifdef HAVE_MMDEVAPI
  38. { "mmdevapi", "Add MMDevAPI" },
  39. #endif
  40. #ifdef HAVE_DSOUND
  41. { "dsound", "Add DirectSound" },
  42. #endif
  43. #ifdef HAVE_WINMM
  44. { "winmm", "Add Windows Multimedia" },
  45. #endif
  46. #ifdef HAVE_PORTAUDIO
  47. { "port", "Add PortAudio" },
  48. #endif
  49. #ifdef HAVE_OPENSL
  50. { "opensl", "Add OpenSL" },
  51. #endif
  52. { "null", "Add Null Output" },
  53. #ifdef HAVE_WAVE
  54. { "wave", "Add Wave Writer" },
  55. #endif
  56. { "", "" }
  57. };
  58. static const struct {
  59. const char name[64];
  60. const char value[16];
  61. } speakerModeList[] = {
  62. { "Autodetect", "" },
  63. { "Mono", "mono" },
  64. { "Stereo", "stereo" },
  65. { "Quadrophonic", "quad" },
  66. { "5.1 Surround (Side)", "surround51" },
  67. { "5.1 Surround (Rear)", "surround51rear" },
  68. { "6.1 Surround", "surround61" },
  69. { "7.1 Surround", "surround71" },
  70. { "", "" }
  71. }, sampleTypeList[] = {
  72. { "Autodetect", "" },
  73. { "8-bit int", "int8" },
  74. { "8-bit uint", "uint8" },
  75. { "16-bit int", "int16" },
  76. { "16-bit uint", "uint16" },
  77. { "32-bit int", "int32" },
  78. { "32-bit uint", "uint32" },
  79. { "32-bit float", "float32" },
  80. { "", "" }
  81. }, resamplerList[] = {
  82. { "Default", "" },
  83. { "Point (low quality, very fast)", "point" },
  84. { "Linear (basic quality, fast)", "linear" },
  85. { "4-Point Sinc (good quality)", "sinc4" },
  86. { "8-Point Sinc (high quality, slow)", "sinc8" },
  87. { "Band-limited Sinc (very high quality, very slow)", "bsinc" },
  88. { "", "" }
  89. }, stereoModeList[] = {
  90. { "Autodetect", "" },
  91. { "Speakers", "speakers" },
  92. { "Headphones", "headphones" },
  93. { "", "" }
  94. };
  95. static QString getDefaultConfigName()
  96. {
  97. #ifdef Q_OS_WIN32
  98. static const char fname[] = "alsoft.ini";
  99. QByteArray base = qgetenv("AppData");
  100. #else
  101. static const char fname[] = "alsoft.conf";
  102. QByteArray base = qgetenv("XDG_CONFIG_HOME");
  103. if(base.isEmpty())
  104. {
  105. base = qgetenv("HOME");
  106. if(base.isEmpty() == false)
  107. base += "/.config";
  108. }
  109. #endif
  110. if(base.isEmpty() == false)
  111. return base +'/'+ fname;
  112. return fname;
  113. }
  114. static QString getBaseDataPath()
  115. {
  116. #ifdef Q_OS_WIN32
  117. QByteArray base = qgetenv("AppData");
  118. #else
  119. QByteArray base = qgetenv("XDG_DATA_HOME");
  120. if(base.isEmpty())
  121. {
  122. base = qgetenv("HOME");
  123. if(!base.isEmpty())
  124. base += "/.local/share";
  125. }
  126. #endif
  127. return base;
  128. }
  129. static QStringList getAllDataPaths(QString append=QString())
  130. {
  131. QStringList list;
  132. list.append(getBaseDataPath());
  133. #ifdef Q_OS_WIN32
  134. // TODO: Common AppData path
  135. #else
  136. QString paths = qgetenv("XDG_DATA_DIRS");
  137. if(paths.isEmpty())
  138. paths = "/usr/local/share/:/usr/share/";
  139. list += paths.split(QChar(':'), QString::SkipEmptyParts);
  140. #endif
  141. QStringList::iterator iter = list.begin();
  142. while(iter != list.end())
  143. {
  144. if(iter->isEmpty())
  145. iter = list.erase(iter);
  146. else
  147. {
  148. iter->append(append);
  149. iter++;
  150. }
  151. }
  152. return list;
  153. }
  154. }
  155. MainWindow::MainWindow(QWidget *parent) :
  156. QMainWindow(parent),
  157. ui(new Ui::MainWindow),
  158. mPeriodSizeValidator(NULL),
  159. mPeriodCountValidator(NULL),
  160. mSourceCountValidator(NULL),
  161. mEffectSlotValidator(NULL),
  162. mSourceSendValidator(NULL),
  163. mSampleRateValidator(NULL)
  164. {
  165. ui->setupUi(this);
  166. for(int i = 0;speakerModeList[i].name[0];i++)
  167. ui->channelConfigCombo->addItem(speakerModeList[i].name);
  168. ui->channelConfigCombo->adjustSize();
  169. for(int i = 0;sampleTypeList[i].name[0];i++)
  170. ui->sampleFormatCombo->addItem(sampleTypeList[i].name);
  171. ui->sampleFormatCombo->adjustSize();
  172. for(int i = 0;resamplerList[i].name[0];i++)
  173. ui->resamplerComboBox->addItem(resamplerList[i].name);
  174. ui->resamplerComboBox->adjustSize();
  175. for(int i = 0;stereoModeList[i].name[0];i++)
  176. ui->stereoModeCombo->addItem(stereoModeList[i].name);
  177. ui->stereoModeCombo->adjustSize();
  178. ui->hrtfStateComboBox->adjustSize();
  179. #if !defined(HAVE_NEON) && !defined(HAVE_SSE)
  180. ui->cpuExtDisabledLabel->move(ui->cpuExtDisabledLabel->x(), ui->cpuExtDisabledLabel->y() - 60);
  181. #else
  182. ui->cpuExtDisabledLabel->setVisible(false);
  183. #endif
  184. #ifndef HAVE_NEON
  185. #ifndef HAVE_SSE4_1
  186. #ifndef HAVE_SSE3
  187. #ifndef HAVE_SSE2
  188. #ifndef HAVE_SSE
  189. ui->enableSSECheckBox->setVisible(false);
  190. #endif /* !SSE */
  191. ui->enableSSE2CheckBox->setVisible(false);
  192. #endif /* !SSE2 */
  193. ui->enableSSE3CheckBox->setVisible(false);
  194. #endif /* !SSE3 */
  195. ui->enableSSE41CheckBox->setVisible(false);
  196. #endif /* !SSE4.1 */
  197. ui->enableNeonCheckBox->setVisible(false);
  198. #else /* !Neon */
  199. #ifndef HAVE_SSE4_1
  200. #ifndef HAVE_SSE3
  201. #ifndef HAVE_SSE2
  202. #ifndef HAVE_SSE
  203. ui->enableNeonCheckBox->move(ui->enableNeonCheckBox->x(), ui->enableNeonCheckBox->y() - 30);
  204. ui->enableSSECheckBox->setVisible(false);
  205. #endif /* !SSE */
  206. ui->enableSSE2CheckBox->setVisible(false);
  207. #endif /* !SSE2 */
  208. ui->enableSSE3CheckBox->setVisible(false);
  209. #endif /* !SSE3 */
  210. ui->enableSSE41CheckBox->setVisible(false);
  211. #endif /* !SSE4.1 */
  212. #endif
  213. mPeriodSizeValidator = new QIntValidator(64, 8192, this);
  214. ui->periodSizeEdit->setValidator(mPeriodSizeValidator);
  215. mPeriodCountValidator = new QIntValidator(2, 16, this);
  216. ui->periodCountEdit->setValidator(mPeriodCountValidator);
  217. mSourceCountValidator = new QIntValidator(0, 256, this);
  218. ui->srcCountLineEdit->setValidator(mSourceCountValidator);
  219. mEffectSlotValidator = new QIntValidator(0, 16, this);
  220. ui->effectSlotLineEdit->setValidator(mEffectSlotValidator);
  221. mSourceSendValidator = new QIntValidator(0, 4, this);
  222. ui->srcSendLineEdit->setValidator(mSourceSendValidator);
  223. mSampleRateValidator = new QIntValidator(8000, 192000, this);
  224. ui->sampleRateCombo->lineEdit()->setValidator(mSampleRateValidator);
  225. connect(ui->actionLoad, SIGNAL(triggered()), this, SLOT(loadConfigFromFile()));
  226. connect(ui->actionSave_As, SIGNAL(triggered()), this, SLOT(saveConfigAsFile()));
  227. connect(ui->applyButton, SIGNAL(clicked()), this, SLOT(saveCurrentConfig()));
  228. connect(ui->periodSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(updatePeriodSizeEdit(int)));
  229. connect(ui->periodSizeEdit, SIGNAL(editingFinished()), this, SLOT(updatePeriodSizeSlider()));
  230. connect(ui->periodCountSlider, SIGNAL(valueChanged(int)), this, SLOT(updatePeriodCountEdit(int)));
  231. connect(ui->periodCountEdit, SIGNAL(editingFinished()), this, SLOT(updatePeriodCountSlider()));
  232. connect(ui->hrtfAddButton, SIGNAL(clicked()), this, SLOT(addHrtfFile()));
  233. connect(ui->hrtfRemoveButton, SIGNAL(clicked()), this, SLOT(removeHrtfFile()));
  234. connect(ui->hrtfFileList, SIGNAL(itemSelectionChanged()), this, SLOT(updateHrtfRemoveButton()));
  235. ui->enabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu);
  236. connect(ui->enabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showEnabledBackendMenu(QPoint)));
  237. ui->disabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu);
  238. connect(ui->disabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDisabledBackendMenu(QPoint)));
  239. loadConfig(getDefaultConfigName());
  240. }
  241. MainWindow::~MainWindow()
  242. {
  243. delete ui;
  244. delete mPeriodSizeValidator;
  245. delete mPeriodCountValidator;
  246. delete mSourceCountValidator;
  247. delete mEffectSlotValidator;
  248. delete mSourceSendValidator;
  249. delete mSampleRateValidator;
  250. }
  251. void MainWindow::loadConfigFromFile()
  252. {
  253. QString fname = QFileDialog::getOpenFileName(this, tr("Select Files"));
  254. if(fname.isEmpty() == false)
  255. loadConfig(fname);
  256. }
  257. void MainWindow::loadConfig(const QString &fname)
  258. {
  259. QSettings settings(fname, QSettings::IniFormat);
  260. QString sampletype = settings.value("sample-type").toString();
  261. ui->sampleFormatCombo->setCurrentIndex(0);
  262. if(sampletype.isEmpty() == false)
  263. {
  264. for(int i = 0;sampleTypeList[i].name[i];i++)
  265. {
  266. if(sampletype == sampleTypeList[i].value)
  267. {
  268. for(int j = 1;j < ui->sampleFormatCombo->count();j++)
  269. {
  270. QString item = ui->sampleFormatCombo->itemText(j);
  271. if(item == sampleTypeList[i].name)
  272. {
  273. ui->sampleFormatCombo->setCurrentIndex(j);
  274. break;
  275. }
  276. }
  277. break;
  278. }
  279. }
  280. }
  281. QString channelconfig = settings.value("channels").toString();
  282. ui->channelConfigCombo->setCurrentIndex(0);
  283. if(channelconfig.isEmpty() == false)
  284. {
  285. for(int i = 0;speakerModeList[i].name[i];i++)
  286. {
  287. if(channelconfig == speakerModeList[i].value)
  288. {
  289. for(int j = 1;j < ui->channelConfigCombo->count();j++)
  290. {
  291. QString item = ui->channelConfigCombo->itemText(j);
  292. if(item == speakerModeList[i].name)
  293. {
  294. ui->channelConfigCombo->setCurrentIndex(j);
  295. break;
  296. }
  297. }
  298. break;
  299. }
  300. }
  301. }
  302. QString srate = settings.value("frequency").toString();
  303. if(srate.isEmpty())
  304. ui->sampleRateCombo->setCurrentIndex(0);
  305. else
  306. {
  307. ui->sampleRateCombo->lineEdit()->clear();
  308. ui->sampleRateCombo->lineEdit()->insert(srate);
  309. }
  310. ui->srcCountLineEdit->clear();
  311. ui->srcCountLineEdit->insert(settings.value("sources").toString());
  312. ui->effectSlotLineEdit->clear();
  313. ui->effectSlotLineEdit->insert(settings.value("slots").toString());
  314. ui->srcSendLineEdit->clear();
  315. ui->srcSendLineEdit->insert(settings.value("sends").toString());
  316. QString resampler = settings.value("resampler").toString().trimmed();
  317. ui->resamplerComboBox->setCurrentIndex(0);
  318. if(resampler.isEmpty() == false)
  319. {
  320. /* The "cubic" resampler is no longer supported. It's been replaced by
  321. * "sinc4". */
  322. if(resampler == "cubic")
  323. resampler = "sinc4";
  324. for(int i = 0;resamplerList[i].name[i];i++)
  325. {
  326. if(resampler == resamplerList[i].value)
  327. {
  328. for(int j = 1;j < ui->resamplerComboBox->count();j++)
  329. {
  330. QString item = ui->resamplerComboBox->itemText(j);
  331. if(item == resamplerList[i].name)
  332. {
  333. ui->resamplerComboBox->setCurrentIndex(j);
  334. break;
  335. }
  336. }
  337. break;
  338. }
  339. }
  340. }
  341. QString stereomode = settings.value("stereo-mode").toString().trimmed();
  342. ui->stereoModeCombo->setCurrentIndex(0);
  343. if(stereomode.isEmpty() == false)
  344. {
  345. for(int i = 0;stereoModeList[i].name[i];i++)
  346. {
  347. if(stereomode == stereoModeList[i].value)
  348. {
  349. for(int j = 1;j < ui->stereoModeCombo->count();j++)
  350. {
  351. QString item = ui->stereoModeCombo->itemText(j);
  352. if(item == stereoModeList[i].name)
  353. {
  354. ui->stereoModeCombo->setCurrentIndex(j);
  355. break;
  356. }
  357. }
  358. break;
  359. }
  360. }
  361. }
  362. int periodsize = settings.value("period_size").toInt();
  363. ui->periodSizeEdit->clear();
  364. if(periodsize >= 64)
  365. {
  366. ui->periodSizeEdit->insert(QString::number(periodsize));
  367. updatePeriodSizeSlider();
  368. }
  369. int periodcount = settings.value("periods").toInt();
  370. ui->periodCountEdit->clear();
  371. if(periodcount >= 2)
  372. {
  373. ui->periodCountEdit->insert(QString::number(periodcount));
  374. updatePeriodCountSlider();
  375. }
  376. QStringList disabledCpuExts = settings.value("disable-cpu-exts").toStringList();
  377. if(disabledCpuExts.size() == 1)
  378. disabledCpuExts = disabledCpuExts[0].split(QChar(','));
  379. std::transform(disabledCpuExts.begin(), disabledCpuExts.end(),
  380. disabledCpuExts.begin(), std::mem_fun_ref(&QString::trimmed));
  381. ui->enableSSECheckBox->setChecked(!disabledCpuExts.contains("sse", Qt::CaseInsensitive));
  382. ui->enableSSE2CheckBox->setChecked(!disabledCpuExts.contains("sse2", Qt::CaseInsensitive));
  383. ui->enableSSE3CheckBox->setChecked(!disabledCpuExts.contains("sse3", Qt::CaseInsensitive));
  384. ui->enableSSE41CheckBox->setChecked(!disabledCpuExts.contains("sse4.1", Qt::CaseInsensitive));
  385. ui->enableNeonCheckBox->setChecked(!disabledCpuExts.contains("neon", Qt::CaseInsensitive));
  386. if(settings.value("hrtf").toString() == QString())
  387. ui->hrtfStateComboBox->setCurrentIndex(0);
  388. else
  389. {
  390. if(settings.value("hrtf", true).toBool())
  391. ui->hrtfStateComboBox->setCurrentIndex(1);
  392. else
  393. ui->hrtfStateComboBox->setCurrentIndex(2);
  394. }
  395. QStringList hrtf_tables = settings.value("hrtf_tables").toStringList();
  396. if(hrtf_tables.size() == 1)
  397. hrtf_tables = hrtf_tables[0].split(QChar(','));
  398. std::transform(hrtf_tables.begin(), hrtf_tables.end(),
  399. hrtf_tables.begin(), std::mem_fun_ref(&QString::trimmed));
  400. ui->hrtfFileList->clear();
  401. ui->hrtfFileList->addItems(hrtf_tables);
  402. updateHrtfRemoveButton();
  403. ui->enabledBackendList->clear();
  404. ui->disabledBackendList->clear();
  405. QStringList drivers = settings.value("drivers").toStringList();
  406. if(drivers.size() == 0)
  407. ui->backendCheckBox->setChecked(true);
  408. else
  409. {
  410. if(drivers.size() == 1)
  411. drivers = drivers[0].split(QChar(','));
  412. std::transform(drivers.begin(), drivers.end(),
  413. drivers.begin(), std::mem_fun_ref(&QString::trimmed));
  414. bool lastWasEmpty = false;
  415. foreach(const QString &backend, drivers)
  416. {
  417. lastWasEmpty = backend.isEmpty();
  418. if(!backend.startsWith(QChar('-')) && !lastWasEmpty)
  419. ui->enabledBackendList->addItem(backend);
  420. else if(backend.size() > 1)
  421. ui->disabledBackendList->addItem(backend.right(backend.size()-1));
  422. }
  423. ui->backendCheckBox->setChecked(lastWasEmpty);
  424. }
  425. QString defaultreverb = settings.value("default-reverb").toString().toLower();
  426. ui->defaultReverbComboBox->setCurrentIndex(0);
  427. if(defaultreverb.isEmpty() == false)
  428. {
  429. for(int i = 0;i < ui->defaultReverbComboBox->count();i++)
  430. {
  431. if(defaultreverb.compare(ui->defaultReverbComboBox->itemText(i).toLower()) == 0)
  432. {
  433. ui->defaultReverbComboBox->setCurrentIndex(i);
  434. break;
  435. }
  436. }
  437. }
  438. ui->emulateEaxCheckBox->setChecked(settings.value("reverb/emulate-eax", false).toBool());
  439. QStringList excludefx = settings.value("excludefx").toStringList();
  440. if(excludefx.size() == 1)
  441. excludefx = excludefx[0].split(QChar(','));
  442. std::transform(excludefx.begin(), excludefx.end(),
  443. excludefx.begin(), std::mem_fun_ref(&QString::trimmed));
  444. ui->enableEaxReverbCheck->setChecked(!excludefx.contains("eaxreverb", Qt::CaseInsensitive));
  445. ui->enableStdReverbCheck->setChecked(!excludefx.contains("reverb", Qt::CaseInsensitive));
  446. ui->enableChorusCheck->setChecked(!excludefx.contains("chorus", Qt::CaseInsensitive));
  447. ui->enableCompressorCheck->setChecked(!excludefx.contains("compressor", Qt::CaseInsensitive));
  448. ui->enableDistortionCheck->setChecked(!excludefx.contains("distortion", Qt::CaseInsensitive));
  449. ui->enableEchoCheck->setChecked(!excludefx.contains("echo", Qt::CaseInsensitive));
  450. ui->enableEqualizerCheck->setChecked(!excludefx.contains("equalizer", Qt::CaseInsensitive));
  451. ui->enableFlangerCheck->setChecked(!excludefx.contains("flanger", Qt::CaseInsensitive));
  452. ui->enableModulatorCheck->setChecked(!excludefx.contains("modulator", Qt::CaseInsensitive));
  453. ui->enableDedicatedCheck->setChecked(!excludefx.contains("dedicated", Qt::CaseInsensitive));
  454. }
  455. void MainWindow::saveCurrentConfig()
  456. {
  457. saveConfig(getDefaultConfigName());
  458. QMessageBox::information(this, tr("Information"),
  459. tr("Applications using OpenAL need to be restarted for changes to take effect."));
  460. }
  461. void MainWindow::saveConfigAsFile()
  462. {
  463. QString fname = QFileDialog::getOpenFileName(this, tr("Select Files"));
  464. if(fname.isEmpty() == false)
  465. saveConfig(fname);
  466. }
  467. void MainWindow::saveConfig(const QString &fname) const
  468. {
  469. QSettings settings(fname, QSettings::IniFormat);
  470. /* HACK: Compound any stringlist values into a comma-separated string. */
  471. QStringList allkeys = settings.allKeys();
  472. foreach(const QString &key, allkeys)
  473. {
  474. QStringList vals = settings.value(key).toStringList();
  475. if(vals.size() > 1)
  476. settings.setValue(key, vals.join(QChar(',')));
  477. }
  478. QString str = ui->sampleFormatCombo->currentText();
  479. for(int i = 0;sampleTypeList[i].name[0];i++)
  480. {
  481. if(str == sampleTypeList[i].name)
  482. {
  483. settings.setValue("sample-type", sampleTypeList[i].value);
  484. break;
  485. }
  486. }
  487. str = ui->channelConfigCombo->currentText();
  488. for(int i = 0;speakerModeList[i].name[0];i++)
  489. {
  490. if(str == speakerModeList[i].name)
  491. {
  492. settings.setValue("channels", speakerModeList[i].value);
  493. break;
  494. }
  495. }
  496. uint rate = ui->sampleRateCombo->currentText().toUInt();
  497. if(!(rate > 0))
  498. settings.setValue("frequency", QString());
  499. else
  500. settings.setValue("frequency", rate);
  501. settings.setValue("period_size", ui->periodSizeEdit->text());
  502. settings.setValue("periods", ui->periodCountEdit->text());
  503. settings.setValue("sources", ui->srcCountLineEdit->text());
  504. settings.setValue("slots", ui->effectSlotLineEdit->text());
  505. str = ui->resamplerComboBox->currentText();
  506. for(int i = 0;resamplerList[i].name[0];i++)
  507. {
  508. if(str == resamplerList[i].name)
  509. {
  510. settings.setValue("resampler", resamplerList[i].value);
  511. break;
  512. }
  513. }
  514. str = ui->stereoModeCombo->currentText();
  515. for(int i = 0;stereoModeList[i].name[0];i++)
  516. {
  517. if(str == stereoModeList[i].name)
  518. {
  519. settings.setValue("stereo-mode", stereoModeList[i].value);
  520. break;
  521. }
  522. }
  523. QStringList strlist;
  524. if(!ui->enableSSECheckBox->isChecked())
  525. strlist.append("sse");
  526. if(!ui->enableSSE2CheckBox->isChecked())
  527. strlist.append("sse2");
  528. if(!ui->enableSSE3CheckBox->isChecked())
  529. strlist.append("sse3");
  530. if(!ui->enableSSE41CheckBox->isChecked())
  531. strlist.append("sse4.1");
  532. if(!ui->enableNeonCheckBox->isChecked())
  533. strlist.append("neon");
  534. settings.setValue("disable-cpu-exts", strlist.join(QChar(',')));
  535. if(ui->hrtfStateComboBox->currentIndex() == 1)
  536. settings.setValue("hrtf", "true");
  537. else if(ui->hrtfStateComboBox->currentIndex() == 2)
  538. settings.setValue("hrtf", "false");
  539. else
  540. settings.setValue("hrtf", QString());
  541. strlist.clear();
  542. QList<QListWidgetItem*> items = ui->hrtfFileList->findItems("*", Qt::MatchWildcard);
  543. foreach(const QListWidgetItem *item, items)
  544. strlist.append(item->text());
  545. settings.setValue("hrtf_tables", strlist.join(QChar(',')));
  546. strlist.clear();
  547. items = ui->enabledBackendList->findItems("*", Qt::MatchWildcard);
  548. foreach(const QListWidgetItem *item, items)
  549. strlist.append(item->text());
  550. items = ui->disabledBackendList->findItems("*", Qt::MatchWildcard);
  551. foreach(const QListWidgetItem *item, items)
  552. strlist.append(QChar('-')+item->text());
  553. if(strlist.size() == 0 && !ui->backendCheckBox->isChecked())
  554. strlist.append("-all");
  555. else if(ui->backendCheckBox->isChecked())
  556. strlist.append(QString());
  557. settings.setValue("drivers", strlist.join(QChar(',')));
  558. // TODO: Remove check when we can properly match global values.
  559. if(ui->defaultReverbComboBox->currentIndex() == 0)
  560. settings.setValue("default-reverb", QString());
  561. else
  562. {
  563. str = ui->defaultReverbComboBox->currentText().toLower();
  564. settings.setValue("default-reverb", str);
  565. }
  566. if(ui->emulateEaxCheckBox->isChecked())
  567. settings.setValue("reverb/emulate-eax", "true");
  568. else
  569. settings.setValue("reverb/emulate-eax", QString()/*"false"*/);
  570. strlist.clear();
  571. if(!ui->enableEaxReverbCheck->isChecked())
  572. strlist.append("eaxreverb");
  573. if(!ui->enableStdReverbCheck->isChecked())
  574. strlist.append("reverb");
  575. if(!ui->enableChorusCheck->isChecked())
  576. strlist.append("chorus");
  577. if(!ui->enableDistortionCheck->isChecked())
  578. strlist.append("distortion");
  579. if(!ui->enableCompressorCheck->isChecked())
  580. strlist.append("compressor");
  581. if(!ui->enableEchoCheck->isChecked())
  582. strlist.append("echo");
  583. if(!ui->enableEqualizerCheck->isChecked())
  584. strlist.append("equalizer");
  585. if(!ui->enableFlangerCheck->isChecked())
  586. strlist.append("flanger");
  587. if(!ui->enableModulatorCheck->isChecked())
  588. strlist.append("modulator");
  589. if(!ui->enableDedicatedCheck->isChecked())
  590. strlist.append("dedicated");
  591. settings.setValue("excludefx", strlist.join(QChar(',')));
  592. /* Remove empty keys
  593. * FIXME: Should only remove keys whose value matches the globally-specified value.
  594. */
  595. allkeys = settings.allKeys();
  596. foreach(const QString &key, allkeys)
  597. {
  598. str = settings.value(key).toString();
  599. if(str == QString())
  600. settings.remove(key);
  601. }
  602. }
  603. void MainWindow::updatePeriodSizeEdit(int size)
  604. {
  605. ui->periodSizeEdit->clear();
  606. if(size >= 64)
  607. {
  608. size = (size+32)&~0x3f;
  609. ui->periodSizeEdit->insert(QString::number(size));
  610. }
  611. }
  612. void MainWindow::updatePeriodSizeSlider()
  613. {
  614. int pos = ui->periodSizeEdit->text().toInt();
  615. if(pos >= 64)
  616. {
  617. if(pos > 8192)
  618. pos = 8192;
  619. ui->periodSizeSlider->setSliderPosition(pos);
  620. }
  621. }
  622. void MainWindow::updatePeriodCountEdit(int count)
  623. {
  624. ui->periodCountEdit->clear();
  625. if(count >= 2)
  626. ui->periodCountEdit->insert(QString::number(count));
  627. }
  628. void MainWindow::updatePeriodCountSlider()
  629. {
  630. int pos = ui->periodCountEdit->text().toInt();
  631. if(pos < 2)
  632. pos = 0;
  633. else if(pos > 16)
  634. pos = 16;
  635. ui->periodCountSlider->setSliderPosition(pos);
  636. }
  637. void MainWindow::addHrtfFile()
  638. {
  639. const QStringList datapaths = getAllDataPaths("/openal/hrtf");
  640. QStringList fnames = QFileDialog::getOpenFileNames(this, tr("Select Files"),
  641. datapaths.empty() ? QString() : datapaths[0],
  642. "HRTF Datasets(*.mhr);;All Files(*.*)");
  643. if(fnames.isEmpty() == false)
  644. {
  645. for(QStringList::iterator iter = fnames.begin();iter != fnames.end();iter++)
  646. {
  647. QStringList::const_iterator path = datapaths.constBegin();
  648. for(;path != datapaths.constEnd();path++)
  649. {
  650. QDir hrtfdir(*path);
  651. if(!hrtfdir.isAbsolute())
  652. continue;
  653. const QString relname = hrtfdir.relativeFilePath(*iter);
  654. if(!relname.startsWith(".."))
  655. {
  656. // If filename is within this path, use the relative pathname
  657. ui->hrtfFileList->addItem(relname);
  658. break;
  659. }
  660. }
  661. if(path == datapaths.constEnd())
  662. {
  663. // Filename is not within any data path, use the absolute pathname
  664. ui->hrtfFileList->addItem(*iter);
  665. }
  666. }
  667. }
  668. }
  669. void MainWindow::removeHrtfFile()
  670. {
  671. QList<QListWidgetItem*> selected = ui->hrtfFileList->selectedItems();
  672. foreach(QListWidgetItem *item, selected)
  673. delete item;
  674. }
  675. void MainWindow::updateHrtfRemoveButton()
  676. {
  677. ui->hrtfRemoveButton->setEnabled(ui->hrtfFileList->selectedItems().size() != 0);
  678. }
  679. void MainWindow::showEnabledBackendMenu(QPoint pt)
  680. {
  681. QMap<QAction*,QString> actionMap;
  682. pt = ui->enabledBackendList->mapToGlobal(pt);
  683. QMenu ctxmenu;
  684. QAction *removeAction = ctxmenu.addAction(QIcon::fromTheme("list-remove"), "Remove");
  685. if(ui->enabledBackendList->selectedItems().size() == 0)
  686. removeAction->setEnabled(false);
  687. ctxmenu.addSeparator();
  688. for(size_t i = 0;backendMenuList[i].backend_name[0];i++)
  689. {
  690. QAction *action = ctxmenu.addAction(backendMenuList[i].menu_string);
  691. actionMap[action] = backendMenuList[i].backend_name;
  692. if(ui->enabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0 ||
  693. ui->disabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0)
  694. action->setEnabled(false);
  695. }
  696. QAction *gotAction = ctxmenu.exec(pt);
  697. if(gotAction == removeAction)
  698. {
  699. QList<QListWidgetItem*> selected = ui->enabledBackendList->selectedItems();
  700. foreach(QListWidgetItem *item, selected)
  701. delete item;
  702. }
  703. else if(gotAction != NULL)
  704. {
  705. QMap<QAction*,QString>::const_iterator iter = actionMap.find(gotAction);
  706. if(iter != actionMap.end())
  707. ui->enabledBackendList->addItem(iter.value());
  708. }
  709. }
  710. void MainWindow::showDisabledBackendMenu(QPoint pt)
  711. {
  712. QMap<QAction*,QString> actionMap;
  713. pt = ui->disabledBackendList->mapToGlobal(pt);
  714. QMenu ctxmenu;
  715. QAction *removeAction = ctxmenu.addAction(QIcon::fromTheme("list-remove"), "Remove");
  716. if(ui->disabledBackendList->selectedItems().size() == 0)
  717. removeAction->setEnabled(false);
  718. ctxmenu.addSeparator();
  719. for(size_t i = 0;backendMenuList[i].backend_name[0];i++)
  720. {
  721. QAction *action = ctxmenu.addAction(backendMenuList[i].menu_string);
  722. actionMap[action] = backendMenuList[i].backend_name;
  723. if(ui->disabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0 ||
  724. ui->enabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0)
  725. action->setEnabled(false);
  726. }
  727. QAction *gotAction = ctxmenu.exec(pt);
  728. if(gotAction == removeAction)
  729. {
  730. QList<QListWidgetItem*> selected = ui->disabledBackendList->selectedItems();
  731. foreach(QListWidgetItem *item, selected)
  732. delete item;
  733. }
  734. else if(gotAction != NULL)
  735. {
  736. QMap<QAction*,QString>::const_iterator iter = actionMap.find(gotAction);
  737. if(iter != actionMap.end())
  738. ui->disabledBackendList->addItem(iter.value());
  739. }
  740. }