now correctly setting the window's icon
[jackctlmmc.git] / qt / src / mainWindow.cpp
blob8465acdc265c0993600433b4642f09c17ba2d758
1 /***************************************************************************
2 * Copyright (C) 2009 by Alex Montgomery and Nedko Arnaudov *
3 * check@Adaon *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) 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 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include <QMessageBox>
22 #include <QFile>
23 #include <QTextStream>
24 #include <QDir>
25 #include <QWhatsThis>
27 #include "mainWindow.h"
28 #include "validator.h"
29 #include "sequencerThread.h"
31 extern "C" {
32 #include "../../common.h"
35 MainWindow::MainWindow() : sequencerThread(0)
37 setupUi(this); // use the UI layout generated by qjackmmc.ui
39 // make sure the fps and jitter edit boxes only take positive whole numbers
40 QValidator* validator = new Validator(this);
41 fpsEdit->setValidator(validator);
42 jitterEdit->setValidator(validator);
44 // make sure the device edit box only take positive hexadecimal values
45 validator = new HexValidator(this);
46 deviceEdit->setValidator(validator);
48 // set the program's icon
49 const QString iconPath(QString(ICON_DIR) + "/qjackmmc.png");
50 if (QFile::exists(iconPath))
51 setWindowIcon(QPixmap(iconPath));
54 bool MainWindow::init(int argc, char *argv[])
56 bool succeeded = initSound(argc, argv); // setup Jack, ALSA, and Lash so the user can connect MIDI to the program
58 if (succeeded)
60 // load the default configuration file if it exists
61 QFile loadFile(QDir::homePath() + QJACKMMC_CONFIG);
62 if (loadFile.exists())
63 loadConfig(loadFile);
66 if (listenBox->isChecked())
67 on_startButton_clicked();
70 return succeeded;
73 MainWindow::~MainWindow()
75 cleanup_globals();
78 void MainWindow::on_actionQuit_triggered()
80 close();
83 void MainWindow::on_actionAbout_triggered()
85 QFile aboutFile(QJACKMMC_ABOUT);
86 if (aboutFile.exists() && aboutFile.open(QIODevice::ReadOnly | QIODevice::Text))
88 QTextStream in(&aboutFile);
89 QString message(in.readLine());
91 QMessageBox* aboutBox = new QMessageBox(this);
92 aboutBox->setText(message);
93 aboutBox->exec();
97 void MainWindow::on_actionWhat_triggered()
99 QWhatsThis::enterWhatsThisMode();
102 void MainWindow::on_startButton_clicked()
104 if (g_isListening)
106 // stop the process and wait for it to die
107 if (sequencerThread)
109 sequencerThread->die();
110 sequencerThread->wait();
111 delete sequencerThread;
112 sequencerThread = 0;
115 startButton->setText("&Start Listening");
117 g_isListening = false;
119 enableRelevantWidgets(g_isListening);
121 else
123 bool ok = true;
124 m_settings.frameRate = fpsEdit->text().toInt(&ok);
126 // we go to great lengths to make sure that the input boxes only accept positive integers, but check the fields just in case
127 if (!ok)
129 QMessageBox* inputError = new QMessageBox(this);
130 inputError->setText("the frames / sec parameter needs to be a positive integer.");
131 inputError->exec();
132 return;
134 m_settings.jitterTolerance = jitterEdit->text().toInt(&ok);
135 if (!ok)
137 QMessageBox* inputError = new QMessageBox(this);
138 inputError->setText("the jitter tolerance needs to be a positive integer.");
139 inputError->exec();
140 return;
142 int deviceID = deviceEdit->text().toInt(&ok, 16);
143 if (!ok || deviceID > 255 || deviceID < 0)
145 QMessageBox* inputError = new QMessageBox(this);
146 inputError->setText("the deviceID needs to be a hexadecimal number between 0 and ff.");
147 inputError->exec();
148 return;
150 else
151 m_settings.deviceID = (uint8_t) deviceID;
153 m_settings.verbose = verboseBox->isChecked();
155 startButton->setText("&Stop Listening");
157 // start the MMC listener thread
158 sequencerThread = new SequencerThread(this, &m_settings);
162 bool realtime = rtBox->isChecked();
163 sequencerThread->listen(realtime);
165 g_isListening = true;
167 // disable tinkering with MMC parameters while the process is running
168 enableRelevantWidgets(g_isListening);
172 void MainWindow::on_loadButton_clicked()
174 QFile loadFile(QDir::homePath() + QJACKMMC_CONFIG);
175 if (loadFile.exists())
176 loadConfig(loadFile);
177 else
179 QMessageBox* fileError = new QMessageBox(this);
180 fileError->setText(QDir::homePath() + QString(QJACKMMC_CONFIG) + " does not exist. You must save a default configuration before you can load one.");
181 fileError->exec();
185 void MainWindow::on_saveButton_clicked()
187 QFile saveFile(QDir::homePath() + QJACKMMC_CONFIG);
188 if (saveFile.open(QIODevice::WriteOnly | QIODevice::Text))
190 QTextStream out(&saveFile);
192 // write out check boxes
193 int boolVal;
194 boolVal = (verboseBox->isChecked() ? 1 : 0);
195 out << boolVal << endl;
196 boolVal = (rtBox->isChecked() ? 1 : 0);
197 out << boolVal << endl;
198 boolVal = (listenBox->isChecked() ? 1 : 0);
199 out << boolVal << endl;
201 // write out text boxes
202 out << fpsEdit->text() << endl;
203 out << jitterEdit->text() << endl;
204 out << deviceEdit->text() << endl;
206 if (saveFile.error() != QFile::NoError)
208 QMessageBox* jackError = new QMessageBox(this);
209 jackError->setText("An error occurred while writing to " + QDir::homePath() + QString(QJACKMMC_CONFIG));
210 jackError->exec();
213 else
215 QMessageBox* fileError = new QMessageBox(this);
216 fileError->setText(QDir::homePath() + QString(QJACKMMC_CONFIG) + " cannot be opened for writing. Make sure that you have permission to write to that directory and file.");
217 fileError->exec();
222 void MainWindow::onMessageReceived(QString message)
224 messageArea->append(message);
227 bool MainWindow::initSound(int argc, char *argv[])
229 bool succeeded = true, alsaPortCreated = false, jackPortCreated = false;
230 int ret = init_alsa_sequencer("QJjackMMC");
231 if (ret < 0)
233 QMessageBox* alsaError = new QMessageBox(this);
234 alsaError->setText("Can't create alsa sequencer. You will not be able to connect MIDI devices to this program using ALSA. Jack Midi might still function.");
235 alsaError->exec();
237 else
238 alsaPortCreated = true;
240 if (succeeded && init_jack("QJjackMMC") < 0)
242 QMessageBox* jackError = new QMessageBox(this);
243 jackError->setText("couldn't connect to the JACK server. Would you like to start one with default parameters? (Answering \"No\" will close this program.)");
244 jackError->addButton(QMessageBox::Yes);
245 jackError->addButton(QMessageBox::No);
246 if (jackError->exec() == QMessageBox::No)
247 succeeded = false;
249 #if LASH_SUPPORT
250 init_lash(argc, argv);
251 #else
252 Q_UNUSED(argc);
253 Q_UNUSED(argv);
254 #endif // LASH_SUPPORT
256 #if JACK_MIDI_SUPPORT
257 if (succeeded)
259 if (!init_jack_midi(&m_settings))
261 QMessageBox* activateError = new QMessageBox(this);
262 activateError->setText("couldn't activate JACK midi, you will not be able to connect MIDI devices to this program using JACK midi.");
263 activateError->exec();
265 else
266 jackPortCreated = true;
268 #endif // JACK_MIDI_SUPPORT
270 if (succeeded && activate_jack() != 0)
272 QMessageBox* activateError = new QMessageBox(this);
273 activateError->setText("couldn't activate JACK, Please check your JACK installation and rerun this program.");
274 activateError->exec();
275 succeeded = false;
278 if (jackPortCreated == false && alsaPortCreated == false)
280 QMessageBox* activateError = new QMessageBox(this);
281 activateError->setText("Neither JACK midi nor ALSA midi could be initialized, bailing out.");
282 activateError->exec();
283 succeeded = false;
285 return succeeded;
288 void MainWindow::loadConfig(QFile& loadFile)
290 if (loadFile.open(QIODevice::ReadOnly | QIODevice::Text))
292 QTextStream in(&loadFile);
294 // read in check boxes
295 int boolVal;
296 in >> boolVal;
297 verboseBox->setChecked(boolVal == 1);
298 in >> boolVal;
299 rtBox->setChecked(boolVal == 1);
300 in >> boolVal;
301 listenBox->setChecked(boolVal == 1);
304 // read in edit boxes
305 QString value;
306 in >> value;
307 if (value.length())
308 fpsEdit->setText(value);
309 in >> value;
310 if (value.length())
311 jitterEdit->setText(value);
312 in >> value;
313 if (value.length())
314 deviceEdit->setText(value);
316 if (loadFile.error() != QFile::NoError)
318 QMessageBox* jackError = new QMessageBox(this);
319 jackError->setText("An error occurred while reading " + QDir::homePath() + QString(QJACKMMC_CONFIG) +
320 ". The file is either nonexistent, corrupt, or from an older version of QJackMMC. Please set the QJackMMC parameters \
321 how you like them and click \"Save as Default settings\".");
322 jackError->exec();
325 else
327 QMessageBox* fileError = new QMessageBox(this);
328 fileError->setText(QDir::homePath() + QString(QJACKMMC_CONFIG) + " cannot be opened for reading. It's either corrupt, or you don't have permission to read it.");
329 fileError->exec();
333 void MainWindow::enableRelevantWidgets(bool isRunning)
335 // re-enable MMC parameter input boxes
336 fpsEdit->setEnabled(!isRunning);
337 jitterEdit->setEnabled(!isRunning);
338 deviceEdit->setEnabled(!isRunning);
339 rtBox->setEnabled(!isRunning);
340 verboseBox->setEnabled(!isRunning);
341 loadButton->setEnabled(!isRunning);