26 #include <QLibraryInfo> 29 #include <QStandardPaths> 31 #include <QQmlProperty> 32 #include <QDialogButtonBox> 53 , mRestartRequest(false)
59 , mMidiMicrotonalConverter()
64 , mMidiHandler(mSoundGenerator,mAudioOutput)
68 , mAvailableMidiDevices()
69 , mAvailableMidiOutputDevices()
70 , mCurrentMidiDevice(
"")
71 , mMidiAutomaticRecognition(true)
72 , mMidiPlayerWasPlaying(false)
74 , mLastEmittedPitchProgression(0)
161 if (engine.rootObjects().empty())
return;
162 QObject* pQml = engine.rootObjects().first();
163 if (not pQml)
return;
176 connect(pQml,SIGNAL(selectInstrument(
int)),
this,SLOT(
loadInstrument(
int)));
179 connect(&
mInstrument,SIGNAL(showProgressBar(QVariant)),pQml,SLOT(showProgressBar(QVariant)));
180 connect(&
mInstrument,SIGNAL(hideProgressBar()),pQml,SLOT(hideProgressBar()));
181 connect(
mInstrument.
getVoice(),SIGNAL(setProgressText(QVariant)),pQml,SLOT(setProgressText(QVariant)));
182 connect(
mInstrument.
getVoice(),SIGNAL(setProgress(QVariant)),pQml,SLOT(setProgress(QVariant)));
183 connect(pQml,SIGNAL(progressCancelButton()),
this,SLOT(
cancelLoading()));
186 connect(&
mMidiPlayer,SIGNAL(signalPlayingStatusChanged(QVariant)),pQml,SLOT(setPlayingStatus(QVariant)));
187 connect(pQml,SIGNAL(togglePlayPause()),&
mMidiPlayer,SLOT(togglePlayPause()));
189 connect(
this,SIGNAL(
setSelectedExample(QVariant)),pQml,SLOT(setQmlSelectedExample(QVariant)));
190 connect(pQml,SIGNAL(rewind()),&
mMidiPlayer,SLOT(rewind()));
191 connect(pQml,SIGNAL(progressChangedManually(
double)),&
mMidiPlayer,SLOT(setMidiProgress(
double)));
192 connect(pQml,SIGNAL(setTempoFactor(
double)),&
mMidiPlayer,SLOT(setTempo(
double)));
193 connect(pQml,SIGNAL(setRepeatMode(
bool)),&
mMidiPlayer,SLOT(setRepeatMode(
bool)));
194 connect(pQml,SIGNAL(openFile(QString)),&
mMidiPlayer,SLOT(loadUrl(QString)));
196 connect(&
mMidiPlayer,SIGNAL(signalProgressInPercent(QVariant)),pQml,SLOT(setMidiProgress(QVariant)));
197 connect(&
mMidiPlayer,SIGNAL(setDisplayedMidiFilename(QVariant)),pQml,SLOT(setDisplayedMidiFilename(QVariant)));
200 connect(pQml,SIGNAL(signalTuningMode(
int,
int)),&
mTuner,SLOT(setTuningMode(
int,
int)));
201 connect(pQml,SIGNAL(signalCentsChanged(
int,
double)),&
mTuner,SLOT(setIntervalSize(
int,
double)));
202 connect(pQml,SIGNAL(signalWeightsChanged(
int,
double)),&
mTuner,SLOT(setIntervalWeight(
int,
double)));
203 connect(&
mTuner,SIGNAL(signalReadyForReceivingParameters()),pQml,SLOT(sendAllCentsAndWeights()));
204 connect(pQml,SIGNAL(signalLoadCustomTemperament()),&
mFileHandler,SLOT(loadData()));
205 connect(pQml,SIGNAL(signalSaveCustomTemperament(QString,QString,QString)),&
mFileHandler,SLOT(saveData(QString,QString,QString)));
206 connect(&
mFileHandler,SIGNAL(loadedData(QVariant,QVariant,QVariant)),pQml,SLOT(loadCustomTemperament(QVariant,QVariant,QVariant)));
209 connect (pQml,SIGNAL(setTuningDelay(
double)),&
mTuner,SLOT(setDelayParameter(
double)));
212 connect(pQml,SIGNAL(setStaticTuning(
bool,
int)),&
mTuner,SLOT(setStaticTuningMode(
bool,
int)));
215 connect (pQml,SIGNAL(setDriftCorrectionParameter(
double)),&
mTuner,SLOT(setPitchProgressionCompensationParameter(
double)));
216 connect (pQml,SIGNAL(setMemoryLength(
double)),&
mTuner,SLOT(setMemoryLength(
double)));
217 connect (pQml,SIGNAL(resetPitchProgression()),&
mTuner,SLOT(resetPitchProgression()));
220 connect (&
mTuningLog,SIGNAL(signalNewLogMessage(QVariant)),pQml,SLOT(appendLogfile(QVariant)));
221 connect (&
mMidiPlayer,SIGNAL(signalPlayingStatusChanged(QVariant)),pQml,SLOT(clearLogFile(QVariant)));
222 connect (pQml,SIGNAL(activateLogFile(
bool)),&
mTuningLog,SLOT(activateLogFile(
bool)));
225 connect (&
mMidiHandler,SIGNAL(changeTargetFrequency(QVariant)),pQml,SLOT(changeTargetFrequency(QVariant)));
226 connect (pQml,SIGNAL(setFrequencyOfA4(
double)),&
mTuner,SLOT(setFrequencyOfA4(
double)));
230 connect (
this,SIGNAL(
signalCircularGauge(QVariant)),pQml,SLOT(setAveragePitchDeviation(QVariant)));
231 connect (&
mTuner,SIGNAL(signalIntervalString(QVariant)),pQml,SLOT(setIntervalString(QVariant)));
232 connect (&
mTuner,SIGNAL(signalTension(QVariant)),pQml,SLOT(setTension(QVariant)));
236 connect(&
mDownloader,SIGNAL(signalDownloading(QVariant)),pQml,SLOT(showDownloader(QVariant)));
237 connect(&
mDownloader,SIGNAL(signalProgress(QVariant,QVariant)),pQml,SLOT(setDownloaderProgress(QVariant,QVariant)));
238 connect(&
mDownloader,SIGNAL(signalNoInternetConnection(QVariant)),pQml,SLOT(noInternetConnection(QVariant)));
247 connect(
this,SIGNAL(
setAudioBufferSizes(QVariant,QVariant)),pQml,SLOT(setBufferSizes(QVariant,QVariant)));
250 connect(pQml,SIGNAL(sendTouchscreenKeyboardEvent(QVariant)),
251 &
mKeyboard,SLOT(receiveTouchpadKeyboardEvent(QVariant)));
252 connect(pQml,SIGNAL(setToggleMode(
bool)),
254 connect(pQml,SIGNAL(clearTouchscreenKeyboard()),
256 connect(&
mKeyboard,SIGNAL(highlightKey(QVariant,QVariant)),
257 pQml,SLOT(highlightKey(QVariant,QVariant)));
263 globalApplicationPointer =
this;
264 connect(
this,SIGNAL(
sendMobileMessage(QVariant)),pQml,SLOT(getMobileErrorMessage(QVariant)));
270 connect(pQml,SIGNAL(openFileOpenDialog(
int,
int)),&
mFileHandler,SLOT(openMidiFileDialog(
int,
int)));
322 bool midiFileLoaded =
false;
323 #if (!defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)) 351 QThread::msleep(200);
444 #if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) 445 LOGMESSAGE <<
"******** Application state changed to" << state;
446 if (state==Qt::ApplicationActive)
resume();
468 QString locale = (
mLocale.size()>=2 ?
mLocale : QLocale::system().name());
469 if (locale.mid(0,2)==
"en")
return;
470 QString qtqm =
"qt_"+locale;
472 if (not
mQtTranslator.load(qtqm,QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
473 {
LOGWARNING <<
"Could not load translations for" << qtqm;}
475 {
LOGWARNING <<
"Could not install translations for" << qtqm;}
477 {
LOGWARNING <<
"Could not load translations for" << appqm;}
479 {
LOGWARNING <<
"Could not install translations for" << appqm;}
527 LOGMESSAGE <<
"Slot called from Qml: Start download, forced =" << forced;
548 QString resource =
":/audio/example" 560 QString resource =
":/audio/example" 581 if (pitchProgression > -50 and pitchProgression < 50)
599 LOGMESSAGE <<
"Update shown instrument names";
601 LOGSTATUS <<
"The paths of the instrument files are:" << instruments;
604 QStringList InstrumentQmlNames = instruments;
605 for (QString &name : InstrumentQmlNames)
607 if (name.contains(
"Piano")) name=tr(
"Grand Piano");
608 else if (name.contains(
"Organ")) name=tr(
"Organ");
609 else if (name.contains(
"Harpsichord")) name=tr(
"Harpsichord");
610 else name=tr(
"Unknown Instrument");
612 InstrumentQmlNames.prepend(tr(
"Artificial sound"));
613 InstrumentQmlNames.append(tr(
"External device"));
614 LOGSTATUS <<
"Corresponding instrument names names:" << InstrumentQmlNames;
617 return InstrumentQmlNames;
631 if (index==0) index =
mSettings.value(
"controller/instrumentindex",0).toInt();
632 if (index >= numberOfInstruments) index = 0;
654 LOGMESSAGE <<
"Signal from Qml: Selected instrument number" << selectedindex;
656 const int indexExternalMidi = filenames.size()+1;
657 if (selectedindex > indexExternalMidi)
659 LOGWARNING <<
"Cannot load file with index" << selectedindex;
667 QThread::msleep(200);
671 if (selectedindex == 0)
673 LOGMESSAGE <<
"Constructing artificial sound";
676 else if (selectedindex == indexExternalMidi)
682 const QString filename = filenames[selectedindex-1];
683 LOGMESSAGE <<
"Loading file with index" << selectedindex;
687 mSettings.setValue(
"controller/instrumentindex",selectedindex);
702 LOGMESSAGE <<
"*** CANCEL LOADING INSTRUMENT ***";
717 LOGMESSAGE <<
"Receiving signal that loading was finished";
733 LOGMESSAGE <<
"Receive signal: New instrument downloaded:";
739 LOGMESSAGE <<
"First instrument is now loaded automatically";
753 LOGMESSAGE <<
"Receive signal: Downloader shutdown, now update instruments";
772 QString dev = device;
776 int opening = dev.indexOf(
"(");
777 int closing = dev.indexOf(
")");
778 if (opening>0 and closing>opening)
779 dev = device.mid(opening+1,closing-opening-1);
782 if (dev.size() > truncation)
784 dev.remove(0,dev.size()-truncation);
785 int pos1 = dev.indexOf(
"_");
786 int pos2 = dev.indexOf(
"-");
787 if (pos1>=0 and pos1<truncation/4) dev.remove(0,pos1+1);
788 else if (pos2>=0 and pos2<truncation/4) dev.remove(0,pos2+1);
806 int buffersize,
int packetsize)
811 LOGSTATUS <<
"Select audio device: Selection index =" << devIndex;
813 if (devIndex < deviceNames.size() and devIndex>=0)
815 parameters.
deviceName = deviceNames[devIndex];
819 LOGSTATUS <<
"Select sample rate: Selection index =" << srIndex;
821 if (srIndex >= 0 and srIndex < listOfSampleRates.size())
823 parameters.
sampleRate = listOfSampleRates[srIndex];
827 LOGMESSAGE <<
"Select buffer size:" << buffersize;
829 mSettings.setValue(
"audiooutput/buffersize",buffersize);
831 LOGMESSAGE <<
"Select packet size:" << packetsize;
833 mSettings.setValue(
"audiooutput/packetsize",packetsize);
850 LOGMESSAGE <<
"New audio device added" << list;
879 LOGMESSAGE <<
"List of audio devices changed:" << list;
880 for (
auto &e : list) e =
shorten(e);
881 list.prepend(tr(
"[Choose output device]"));
884 int deviceIndex = devices.indexOf(parameters.
deviceName);
903 LOGMESSAGE <<
"List of audio parameters changed.";
923 LOGMESSAGE <<
"Audio connected = " << success;
926 if (dev.size()>0 and success) dev =
shorten(dev);
927 else dev = tr(
"No device connected");
942 LOGMESSAGE <<
"Trying to load Midi file" << filename;
943 QFile midifile (filename);
944 if (midifile.exists())
951 LOGWARNING <<
"MIDI File" << filename <<
"does not exist";
969 qDebug() <<
"MOBILE ERROR MESSAGE" << msg;
983 LOGWARNING <<
"Received signal about a closed Midi feedback loop";
1015 LOGMESSAGE <<
"Reset buffer size:" << buffersize;
1016 parameters.bufferSize = buffersize;
1017 mSettings.setValue(
"audiooutput/buffersize",buffersize);
1019 LOGMESSAGE <<
"Reset packet size:" << packetsize;
1021 mSettings.setValue(
"audiooutput/packetsize",packetsize);
void stop()
Stop the application and its components.
void setInstrumentSelector(int index=0)
Set the content of the instrument selector.
void suspend()
Suspend the application This function suspends the application and all modules. This is essential e...
bool mMidiPlayerWasPlaying
void playStartupSound()
Play startup sound.
void resume()
Resume from suspend mode.
void setAudioSampleRates(QVariant list, QVariant index)
virtual bool init() override
Init audio device.
MidiMicrotonal mMidiMicrotonalConverter
bool loadMidiFile(QString filename)
Load a Midi file.
bool start() override final
Public slot: Start the tuner, starting the tuner thread.
bool stop()
Stop the microtonal converter.
double mLastEmittedPitchProgression
void changeLocale(QString locale)
Slot: Change the language.
void receiveTuningCorrections(QMap< int, double > corrections)
Input slot: Receive tuning corrections from the tuner (<key,cent>)
void hearExample(int number)
Private slot: Hear a Midi example.
void signalSostenutoPedal(bool pressed)
void play()
Start or resume playing.
void setModuleName(const QString &name)
Specify the name of the class-specific module.
virtual void suspend()
Mark the thread as suspended.
void stop()
Stop downloading.
void newInstrumentDownloaded(QString localpath)
Private slot: New instrument downloaded.
void setQmlSelectedInstrument(QVariant index)
void handleApplicationStates(Qt::ApplicationState state)
Function executed when application state changes (platform-dependent) Takes action if the state of th...
void startLoadingInstrument(QString name)
void receiveTuningCorrections(QMap< int, double > corrections)
bool exit()
Shutdown, no functionality.
#define INT_SAMPLES_REPOSITORY
QString deviceName
Name of the audio device.
void onAudioDevicesRemoved(QStringList list)
Private slot: An audio device has been removed (test)
void setAudioDeviceName(QVariant name)
void start(bool forced)
Start the downloading process in the background.
void play(double volume)
Play startup sound.
bool init() override final
Initialize the Tuner.
void init(QQmlApplicationEngine &engine)
Initialization of the application.
void receiveTuningCorrections(const QMap< int, double > &corrections)
Public slot: Receive tuning corrections.
bool init(QObject *qml)
Initialize the Midi wrapper and connect it with Qml.
bool isPlaying() const
Find out whether the player is playing.
void setQmlInstrumentNames(QVariant stringlist)
void start()
Start the application and its components.
void setQmlLocale(QVariant string)
void connectAudioDevice(bool active)
void sendMidiEvent(QMidiMessage event)
Output signal: This is the converted outgoing stream of Midi events.
Structure holding the parameters and status of an audio device.
void onInputOutputStatusChanged()
I/O configuration changed, cancel converter inhibition.
virtual void resume()
Resume from the suspend mode.
void mobileError(QString msg)
void openMidiFile(QString fileName, bool autostart)
virtual bool stop() override
Stop audio device.
Application(QApplication &app)
Application constructor.
QString shorten(const QString &device, int truncation=30) const
Shorten very long device names.
bool start()
Start the microtonal converter.
virtual bool init()
Virtual initialization function (no functionality here)
void loadFile(QString filename, bool autostart=false)
Load a midi file (*.mid) from disk.
void emitAveragePitchProgression(double pitchProgression)
Emit the newly calculated average pitch progression.
QApplication * pApplication
void onConnectionSuccessfullyEstablished(bool success)
Private slot: on audio connection established.
void signalSoftPedal(bool pressed)
void allInstrumentsDownloaded()
Private slot: All instrumenst downloaded.
void activate(bool active)
Activate or deactivate the module.
void suspend()
Suspend (stop playing, thread idle)
int sampleRate
Actual sample rate.
void setAudioGenerator(AudioGenerator &generator)
Select an AudioGenerator for output.
void automaticCyclicMorphing()
Function defined externally (Importer)
void setMaxPacketSize(int n)
void getSettingsFromQml()
const AudioParameters getActualDeviceParameters() const
Get the actual audio device parameters.
Application * globalApplicationPointer
void receiveMidiEvent(const QMidiMessage &event)
QTranslator mQtTranslator
void disableScreenSaver()
void setSelectedExample(QVariant number)
void pause()
Pause: Interrupt playing.
#define INT_APPLICATIONNAME_LOWERCASE
void loadInstrument(int selectedindex)
Private slot: Load an instrument.
TouchscreenKeyboard mKeyboard
void exit()
Exit from the application and all its components.
void sendTouchpadMidiEvent(QMidiMessage event)
Signal: On keypress send the corresponding Midi event to a different module.
void sendMidiMessage(const QMidiMessage &event)
Send a Midi message to the output device.
void signalTuningCorrections(QMap< int, double > corrections)
Signal sending the tuning results to the microtonal sound device in the form of a map keyindex -> cen...
virtual bool exit() override
Exit audio device.
void resetAudioParameters()
Reset audio parameters.
void onAudioDevicesAdded(QStringList list)
Private slot: New audio device added (test)
void cancelLoading()
Private slot: Cancel the loading process.
void receiveMidiEvent(QMidiMessage event)
Public slot: Receive Midi event (Main input of the tuner)
int bufferSize
Buffer size of the device if applicable.
SoundGenerator mSoundGenerator
void resume()
Resume from suspend mode.
void restartApplication()
Restart the application by force.
bool stop() override final
Stop the instrument thread.
void receiveMidiEvent(QMidiMessage event)
Public slot: Receive MIDI event.
void setSustainPedal(bool pressed)
StartupSound mStartupSound
bool init()
Initialization, no functionality.
void startDownload(bool forced=false)
Private slot: Start download.
void loadInstrument(QString path)
Load or generate an instrument (voice)
virtual bool exit()
Virtual exit function (no functionality here)
void loadingFinished(bool success)
Private slot: Loading finished.
void selectAudioParameters(int devIndex, int srIndex, int buffersize, int packetsize)
Private slot: Select audio parameters.
#define INT_NUMBER_OF_EXAMPLES
void setAudioDeviceList(QVariant list, QVariant index)
void setSoftPedal(bool pressed)
void suspend()
Suspend the microtonal converter.
virtual bool start()
Start the thread.
void sendMobileMessage(QVariant string)
void installTranslations()
Install existing translations.
void suspend() override final
Mark the thread as suspended.
void togglePlayPause()
Toggle between play and pause.
QStringList updateShownInstrumentNames()
Update the list of instruments in the Qml Combo box.
void onChangeOfAvailableAudioDevices(QStringList list)
Private slot: The list of availabel devices has changed (test)
QList< int > supportedSampleRates
List of supported sample rates.
void reInitializeConvertedMidiStream()
Slot: Re-initialize the output stream.
QTranslator mAppTranslator
void receiveMidiEvent(const QMidiMessage event)
Input slot: Here the module receives the stream of incoming Midi events.
void setAudioBufferSizes(QVariant buffer, QVariant packet)
void onCurrentDeviceParametersChanged()
Private slot: on current audio device parameters changed.
void mobileMessage(QString msg)
Show error message on mobile phone while it is connected to a keyboard.
bool stop()
Stop the player.
void init(Application *application, Voice *voice)
Initialize the SoundGenerator.
void signalMidiEvent(QMidiMessage event)
void signalCircularGauge(QVariant progression)
virtual bool stop()
Stop the thread.
QStringList getPathsOfDownloadedFiles()
Get a list of paths of all downloaded files.
void signalSustainPedal(bool pressed)
void setWantedParameters(const AudioParameters ¶meters)
Set the wanted audio device parameters.
void setDefaultBufferSize(int n)
QStringList getListOfDevices() const
Get the current list of devices from the last update.
virtual bool start() override
Start audio device.
void receivedMidiMessage(const QMidiMessage &event)
void onClosedMidiLoopDetected()
Slot: Closed Midi feedback loop discovered, inhibit converter.
void setSostenutoPedal(bool pressed)