diff --git a/qml/Sailfish.qml b/qml/Sailfish.qml index 5b947c8..ddafe49 100644 --- a/qml/Sailfish.qml +++ b/qml/Sailfish.qml @@ -75,7 +75,7 @@ ApplicationWindow { Tuner { id: tunerObject - running: Qt.application.active && app.userRunning + running: Qt.application.active && page.status == PageStatus.Active && app.userRunning temperament_idx: Config.temperament_idx la: Config.la } diff --git a/src/Tuner.cpp b/src/Tuner.cpp index 2006db1..cdd3398 100644 --- a/src/Tuner.cpp +++ b/src/Tuner.cpp @@ -57,6 +57,18 @@ Tuner::~Tuner() workerThread.wait(100); } +bool Tuner::GetPlaying() +{ + return playing; +} + +void Tuner::SetPlaying(bool p) +{ + if (p == playing) return; + playing = p; + emit playingChanged(); +} + bool Tuner::GetRunning() { return running; diff --git a/src/Tuner.hpp b/src/Tuner.hpp index 7960a86..a29b8e1 100644 --- a/src/Tuner.hpp +++ b/src/Tuner.hpp @@ -25,6 +25,7 @@ class Tuner : public QObject { Q_OBJECT + Q_PROPERTY(bool playing READ GetPlaying WRITE SetPlaying NOTIFY playingChanged) Q_PROPERTY(bool running READ GetRunning WRITE SetRunning NOTIFY runningChanged) Q_PROPERTY(double freq READ GetFreq NOTIFY resultChanged) Q_PROPERTY(double deviation READ GetDeviation NOTIFY resultChanged) @@ -41,7 +42,7 @@ class Tuner : public QObject { PitchDetection::PitchResult result; QStringList temperament_list; - bool running; + bool running, playing; double la; int temperament_idx; @@ -49,6 +50,8 @@ class Tuner : public QObject { Tuner(); ~Tuner(); + bool GetPlaying(); + void SetPlaying(bool p); bool GetRunning(); void SetRunning(bool r); double GetFreq(); @@ -69,6 +72,7 @@ class Tuner : public QObject { signals: // signals to UI + void playingChanged(); void runningChanged(); void foundChanged(); void laChanged(); diff --git a/src/TunerWorker.cpp b/src/TunerWorker.cpp index 1c69ff9..a27caa2 100644 --- a/src/TunerWorker.cpp +++ b/src/TunerWorker.cpp @@ -83,10 +83,19 @@ void TunerWorker::Stop() mutex.unlock(); } +void TunerWorker::SetPlaying(bool p) +{ + cerr << __func__ << " " << p << endl; + if (p == playing) return; + mutex.lock(); + playing = p; + if (p) condition.wakeOne(); + mutex.unlock(); +} + void TunerWorker::Quit() { mutex.lock(); - running = false; quit = true; condition.wakeOne(); mutex.unlock(); @@ -112,7 +121,6 @@ void TunerWorker::Entry() int nbSamplePreventBlanking = nbSecPreventBlanking * PitchDetection::rate; int nb_sample_running = 0; - bool new_stream = true, waked; int16_t *buffer = new int16_t[nbSampleBuffer]; @@ -125,34 +133,43 @@ void TunerWorker::Entry() emit temperamentListUpdated(pitchDetection->GetTemperamentList()); // pulseaudio - pa_simple *p_simple = NULL; + pa_simple *p_record = NULL, *p_play = NULL; pa_sample_spec p_spec; p_spec.format = PA_SAMPLE_S16NE; p_spec.channels = 1; p_spec.rate = PitchDetection::rate; + // prevent lpm if running on startup + if (running || playing) blank_prevent(true); + while (1) { + // free pulseaudio if not running + if (!running && p_record) { + pa_simple_free(p_record); + p_record = NULL; + } + if (!playing && p_play) { + pa_simple_free(p_play); + p_play = NULL; + } + // wait for running mutex.lock(); - if (!running) { + if (!running && !playing) { blank_prevent(false); - while (!running && !quit) { - waked = condition.wait(&mutex, p_simple ? stopPulseAfterMs : ULONG_MAX); - if (!waked && p_simple) { - // stop pulseaudio after a delay if not running - pa_simple_free(p_simple); - p_simple = NULL; - } + while (!running && !playing && !quit) { + condition.wait(&mutex); } cerr << "wake-up" << endl; - // reset operations on start - new_stream = true; + nb_sample_running = 0; + if (!quit) blank_prevent(true); } if (quit) { mutex.unlock(); break; } + // update config if (la_to_update) { pitchDetection->SetLa(la_to_update); @@ -164,52 +181,64 @@ void TunerWorker::Entry() } mutex.unlock(); - if (!p_simple) { - // start pulseaudio if stopped - p_simple = pa_simple_new( - NULL, - NAME, - PA_STREAM_RECORD, - NULL, - "Mic", - &p_spec, - NULL, - NULL, - NULL - ); - } - else if (new_stream) { - // flush pulseaudio if paused - pa_simple_flush(p_simple, NULL); + if (running ) { + // tuner detection running + + if (!p_record) { + // start pulseaudio if stopped + p_record = pa_simple_new( + NULL, + NAME, + PA_STREAM_RECORD, + NULL, + "Tuner record", + &p_spec, + NULL, + NULL, + NULL + ); + // reset detection + pitchDetection->Reset(); + result.found = false; + emit resultUpdated(result); + } + + // get audio data + int size = pa_simple_read(p_record, (void*) buffer, nbSampleBuffer << 1, NULL); + if (size < 0) { + cerr << "audio read failed " << size << endl; + continue; + } + //cerr << "read " << nb_sample_running << endl; + + // record in file is needed + if (file) file->write((char*) buffer, nbSampleBuffer << 1); + + pitchDetection->AudioAnalyse(buffer, nbSampleBuffer); + + if (pitchDetection->GetResultUpdated(result)) { + if (result.found) cout << Scale::NoteName(result.note) << " " << result.frequency << endl; + emit resultUpdated(result); + } + } - // if stream was stopped, reset analyse - if (new_stream) { - pitchDetection->Reset(); - blank_prevent(true); - nb_sample_running = 0; - new_stream = false; - // send a not-found result on restart - result.found = false; - emit resultUpdated(result); - } - - // get audio data - int size = pa_simple_read(p_simple, (void*) buffer, nbSampleBuffer << 1, NULL); - if (size < 0) { - cerr << "audio read failed " << size << endl; - continue; - } - //cerr << "read " << nb_sample_running << endl; - - // record in file is needed - if (file) file->write((char*) buffer, nbSampleBuffer << 1); - - pitchDetection->AudioAnalyse(buffer, nbSampleBuffer); - - if (pitchDetection->GetResultUpdated(result)) { - if (result.found) cout << Scale::NoteName(result.note) << " " << result.frequency << endl; - emit resultUpdated(result); + if (playing) { + // play + if (!p_play) { + // start pulseaudio if stopped + p_record = pa_simple_new( + NULL, + NAME, + PA_STREAM_PLAYBACK, + NULL, + "Tuner playback", + &p_spec, + NULL, + NULL, + NULL + ); + } } // prevent screen blanking @@ -220,7 +249,8 @@ void TunerWorker::Entry() } } - if (p_simple) pa_simple_free(p_simple); + if (p_record) pa_simple_free(p_record); + if (p_play) pa_simple_free(p_play); delete pitchDetection; delete buffer; @@ -229,6 +259,7 @@ void TunerWorker::Entry() file->close(); delete file; } + blank_prevent(false); } /// Set a filename before instanciation to record raw audio stream diff --git a/src/TunerWorker.hpp b/src/TunerWorker.hpp index eec2d87..2e5e352 100644 --- a/src/TunerWorker.hpp +++ b/src/TunerWorker.hpp @@ -39,15 +39,13 @@ class TunerWorker : public QObject { static const int nbSecPreventBlanking = 40; /// nb of audio sample to read from pulseaudio at once static const int nbSampleBuffer = 512; - /// stop pulseaudio after time if not running - static const int stopPulseAfterMs = 2000; // 2 sec static const char *filename_record; QMutex mutex; QWaitCondition condition; - bool running, quit; + bool running, playing, quit; // to update vars double la_to_update; @@ -61,6 +59,7 @@ class TunerWorker : public QObject { public slots: void Start(); void Stop(); + void SetPlaying(bool p); void SetTemperamentIndex(int idx); void SetLa(double la); void Entry();