d2658b7f9623455547c602e3a8b6c3c36f8d3272
1 /***************************************************************************
2 * Copyright (C) 2009 by Alex Montgomery and Nedko Arnaudov *
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. *
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. *
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>
23 #include <QTextStream>
27 #include "mainWindow.h"
28 #include "validator.h"
29 #include "sequencerThread.h"
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
60 // load the default configuration file if it exists
61 QFile
loadFile(QDir::homePath() + QJACKMMC_CONFIG
);
62 if (loadFile
.exists())
66 if (listenBox
->isChecked())
67 on_startButton_clicked();
73 MainWindow::~MainWindow()
78 void MainWindow::on_actionQuit_triggered()
83 void MainWindow::on_actionAbout_triggered()
87 #include "../../VERSION"
90 QMessageBox
* aboutBox
= new QMessageBox(this);
91 aboutBox
->setText(message
);
95 void MainWindow::on_actionWhat_triggered()
97 QWhatsThis::enterWhatsThisMode();
100 void MainWindow::on_startButton_clicked()
104 // stop the process and wait for it to die
107 sequencerThread
->die();
108 sequencerThread
->wait();
109 delete sequencerThread
;
113 startButton
->setText("&Start Listening");
115 g_isListening
= false;
117 enableRelevantWidgets(g_isListening
);
122 m_settings
.frameRate
= fpsEdit
->text().toInt(&ok
);
124 // we go to great lengths to make sure that the input boxes only accept positive integers, but check the fields just in case
127 QMessageBox
* inputError
= new QMessageBox(this);
128 inputError
->setText("the frames / sec parameter needs to be a positive integer.");
132 m_settings
.jitterTolerance
= jitterEdit
->text().toInt(&ok
);
135 QMessageBox
* inputError
= new QMessageBox(this);
136 inputError
->setText("the jitter tolerance needs to be a positive integer.");
140 int deviceID
= deviceEdit
->text().toInt(&ok
, 16);
141 if (!ok
|| deviceID
> 255 || deviceID
< 0)
143 QMessageBox
* inputError
= new QMessageBox(this);
144 inputError
->setText("the deviceID needs to be a hexadecimal number between 0 and ff.");
149 m_settings
.deviceID
= (uint8_t) deviceID
;
151 m_settings
.verbose
= verboseBox
->isChecked();
153 startButton
->setText("&Stop Listening");
155 // start the MMC listener thread
156 sequencerThread
= new SequencerThread(this, &m_settings
);
160 bool realtime
= rtBox
->isChecked();
161 sequencerThread
->listen(realtime
);
163 g_isListening
= true;
165 // disable tinkering with MMC parameters while the process is running
166 enableRelevantWidgets(g_isListening
);
170 void MainWindow::on_loadButton_clicked()
172 QFile
loadFile(QDir::homePath() + QJACKMMC_CONFIG
);
173 if (loadFile
.exists())
174 loadConfig(loadFile
);
177 QMessageBox
* fileError
= new QMessageBox(this);
178 fileError
->setText(QDir::homePath() + QString(QJACKMMC_CONFIG
) + " does not exist. You must save a default configuration before you can load one.");
183 void MainWindow::on_saveButton_clicked()
185 QFile
saveFile(QDir::homePath() + QJACKMMC_CONFIG
);
186 if (saveFile
.open(QIODevice::WriteOnly
| QIODevice::Text
))
188 QTextStream
out(&saveFile
);
190 // write out check boxes
192 boolVal
= (verboseBox
->isChecked() ? 1 : 0);
193 out
<< boolVal
<< endl
;
194 boolVal
= (rtBox
->isChecked() ? 1 : 0);
195 out
<< boolVal
<< endl
;
196 boolVal
= (listenBox
->isChecked() ? 1 : 0);
197 out
<< boolVal
<< endl
;
199 // write out text boxes
200 out
<< fpsEdit
->text() << endl
;
201 out
<< jitterEdit
->text() << endl
;
202 out
<< deviceEdit
->text() << endl
;
204 if (saveFile
.error() != QFile::NoError
)
206 QMessageBox
* jackError
= new QMessageBox(this);
207 jackError
->setText("An error occurred while writing to " + QDir::homePath() + QString(QJACKMMC_CONFIG
));
213 QMessageBox
* fileError
= new QMessageBox(this);
214 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.");
220 void MainWindow::onMessageReceived(QString message
)
222 messageArea
->append(message
);
225 bool MainWindow::initSound(int argc
, char *argv
[])
227 bool succeeded
= true, alsaPortCreated
= false, jackPortCreated
= false;
228 int ret
= init_alsa_sequencer("QJjackMMC");
231 QMessageBox
* alsaError
= new QMessageBox(this);
232 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.");
236 alsaPortCreated
= true;
238 if (succeeded
&& init_jack("QJjackMMC") < 0)
240 QMessageBox
* jackError
= new QMessageBox(this);
241 jackError
->setText("couldn't connect to the JACK server. Would you like to start one with default parameters? (Answering \"No\" will close this program.)");
242 jackError
->addButton(QMessageBox::Yes
);
243 jackError
->addButton(QMessageBox::No
);
244 if (jackError
->exec() == QMessageBox::No
)
248 init_lash(argc
, argv
);
252 #endif // LASH_SUPPORT
254 #if JACK_MIDI_SUPPORT
257 if (!init_jack_midi(&m_settings
))
259 QMessageBox
* activateError
= new QMessageBox(this);
260 activateError
->setText("couldn't activate JACK midi, you will not be able to connect MIDI devices to this program using JACK midi.");
261 activateError
->exec();
264 jackPortCreated
= true;
266 #endif // JACK_MIDI_SUPPORT
268 if (succeeded
&& activate_jack() != 0)
270 QMessageBox
* activateError
= new QMessageBox(this);
271 activateError
->setText("couldn't activate JACK, Please check your JACK installation and rerun this program.");
272 activateError
->exec();
276 if (jackPortCreated
== false && alsaPortCreated
== false)
278 QMessageBox
* activateError
= new QMessageBox(this);
279 activateError
->setText("Neither JACK midi nor ALSA midi could be initialized, bailing out.");
280 activateError
->exec();
286 void MainWindow::loadConfig(QFile
& loadFile
)
288 if (loadFile
.open(QIODevice::ReadOnly
| QIODevice::Text
))
290 QTextStream
in(&loadFile
);
292 // read in check boxes
295 verboseBox
->setChecked(boolVal
== 1);
297 rtBox
->setChecked(boolVal
== 1);
299 listenBox
->setChecked(boolVal
== 1);
302 // read in edit boxes
306 fpsEdit
->setText(value
);
309 jitterEdit
->setText(value
);
312 deviceEdit
->setText(value
);
314 if (loadFile
.error() != QFile::NoError
)
316 QMessageBox
* jackError
= new QMessageBox(this);
317 jackError
->setText("An error occurred while reading " + QDir::homePath() + QString(QJACKMMC_CONFIG
) +
318 ". The file is either nonexistent, corrupt, or from an older version of QJackMMC. Please set the QJackMMC parameters \
319 how you like them and click \"Save as Default settings\".");
325 QMessageBox
* fileError
= new QMessageBox(this);
326 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.");
331 void MainWindow::enableRelevantWidgets(bool isRunning
)
333 // re-enable MMC parameter input boxes
334 fpsEdit
->setEnabled(!isRunning
);
335 jitterEdit
->setEnabled(!isRunning
);
336 deviceEdit
->setEnabled(!isRunning
);
337 rtBox
->setEnabled(!isRunning
);
338 verboseBox
->setEnabled(!isRunning
);
339 loadButton
->setEnabled(!isRunning
);