8465acdc265c0993600433b4642f09c17ba2d758
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()
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
);
97 void MainWindow::on_actionWhat_triggered()
99 QWhatsThis::enterWhatsThisMode();
102 void MainWindow::on_startButton_clicked()
106 // stop the process and wait for it to die
109 sequencerThread
->die();
110 sequencerThread
->wait();
111 delete sequencerThread
;
115 startButton
->setText("&Start Listening");
117 g_isListening
= false;
119 enableRelevantWidgets(g_isListening
);
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
129 QMessageBox
* inputError
= new QMessageBox(this);
130 inputError
->setText("the frames / sec parameter needs to be a positive integer.");
134 m_settings
.jitterTolerance
= jitterEdit
->text().toInt(&ok
);
137 QMessageBox
* inputError
= new QMessageBox(this);
138 inputError
->setText("the jitter tolerance needs to be a positive integer.");
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.");
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
);
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.");
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
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
));
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.");
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");
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.");
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
)
250 init_lash(argc
, argv
);
254 #endif // LASH_SUPPORT
256 #if JACK_MIDI_SUPPORT
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();
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();
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();
288 void MainWindow::loadConfig(QFile
& loadFile
)
290 if (loadFile
.open(QIODevice::ReadOnly
| QIODevice::Text
))
292 QTextStream
in(&loadFile
);
294 // read in check boxes
297 verboseBox
->setChecked(boolVal
== 1);
299 rtBox
->setChecked(boolVal
== 1);
301 listenBox
->setChecked(boolVal
== 1);
304 // read in edit boxes
308 fpsEdit
->setText(value
);
311 jitterEdit
->setText(value
);
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\".");
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.");
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
);