diff --git a/OSBindings/Qt/.gitignore b/OSBindings/Qt/.gitignore new file mode 100644 index 000000000..fab7372d7 --- /dev/null +++ b/OSBindings/Qt/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/OSBindings/Qt/ClockSignal.pro b/OSBindings/Qt/ClockSignal.pro index 865d08449..8d8ce6204 100644 --- a/OSBindings/Qt/ClockSignal.pro +++ b/OSBindings/Qt/ClockSignal.pro @@ -1,4 +1,4 @@ -QT += core gui multimedia quickwidgets +QT += core gui multimedia greaterThan(QT_MAJOR_VERSION, 4): QT += widgets diff --git a/OSBindings/Qt/mainwindow.cpp b/OSBindings/Qt/mainwindow.cpp index 042ffc98a..7956c61f4 100644 --- a/OSBindings/Qt/mainwindow.cpp +++ b/OSBindings/Qt/mainwindow.cpp @@ -63,7 +63,15 @@ void MainWindow::open() { } MainWindow::~MainWindow() { - // Stop the timer + // Stop the audio output, and its thread. + if(audioOutput) { + audioOutput->stop(); + + audioThread.quit(); + while(audioThread.isRunning()); + } + + // Stop the timer. timer.reset(); } @@ -142,7 +150,7 @@ void MainWindow::launchMachine() { // Install audio output if required. const auto audio_producer = machine->audio_producer(); if(audio_producer) { - static constexpr size_t samplesPerBuffer = 2048; // TODO: select this dynamically; it's very high. + static constexpr size_t samplesPerBuffer = 256; // TODO: select this dynamically. const auto speaker = audio_producer->get_speaker(); if(speaker) { const QAudioDeviceInfo &defaultDeviceInfo = QAudioDeviceInfo::defaultOutputDevice(); @@ -175,8 +183,7 @@ void MainWindow::launchMachine() { // If this is a timed machine, start up the timer. const auto timedMachine = machine->timed_machine(); if(timedMachine) { - timer->setMachine(timedMachine, &machineMutex); - timer->start(); + timer->startWithMachine(timedMachine, &machineMutex); } } break; diff --git a/OSBindings/Qt/timer.cpp b/OSBindings/Qt/timer.cpp index 36b4e6556..c50e903b3 100644 --- a/OSBindings/Qt/timer.cpp +++ b/OSBindings/Qt/timer.cpp @@ -6,21 +6,23 @@ #include Timer::Timer(QObject *parent) : QObject(parent) { - // Set up the emulation timer. Bluffer's guide: the QTimer will post an - // event to an event loop. QThread is a thread with an event loop. - // My class, Timer, will be wired up to receive the QTimer's events. - timer = std::make_unique(this); - timer->setInterval(1); + thread.setFunction([this] { + // Set up the emulation timer. Bluffer's guide: the QTimer will post an + // event to an event loop. QThread is a thread with an event loop. + // My class, Timer, will be wired up to receive the QTimer's events. + timer = std::make_unique(&thread); + timer->setInterval(1); - thread = std::make_unique(this); - - moveToThread(thread.get()); - connect(timer.get(), SIGNAL(timeout()), this, SLOT(tick())); + connect(timer.get(), SIGNAL(timeout()), this, SLOT(tick()), Qt::DirectConnection); + timer->start(); + }); } -void Timer::setMachine(MachineTypes::TimedMachine *machine, std::mutex *machineMutex) { +void Timer::startWithMachine(MachineTypes::TimedMachine *machine, std::mutex *machineMutex) { this->machine = machine; this->machineMutex = machineMutex; + + thread.start(); } void Timer::tick() { @@ -33,14 +35,9 @@ void Timer::tick() { machine->run_for(double(duration) / 1e9); } -void Timer::start() { - thread->start(); - timer->start(); -} - Timer::~Timer() { // Stop the timer, then ask the QThread to exit and wait for it to do so. timer->stop(); - thread->exit(); - while(thread->isRunning()); + thread.exit(); + while(thread.isRunning()); } diff --git a/OSBindings/Qt/timer.h b/OSBindings/Qt/timer.h index e1d3e0dd0..959558a6a 100644 --- a/OSBindings/Qt/timer.h +++ b/OSBindings/Qt/timer.h @@ -8,6 +8,7 @@ #include #include "../../Machines/Utility/MachineForTarget.hpp" +#include "functionthread.h" class Timer : public QObject { @@ -17,8 +18,7 @@ class Timer : public QObject explicit Timer(QObject *parent = nullptr); ~Timer(); - void setMachine(MachineTypes::TimedMachine *machine, std::mutex *machineMutex); - void start(); + void startWithMachine(MachineTypes::TimedMachine *machine, std::mutex *machineMutex); public slots: void tick(); @@ -27,7 +27,7 @@ class Timer : public QObject MachineTypes::TimedMachine *machine = nullptr; std::mutex *machineMutex = nullptr; int64_t lastTickNanos = 0; - std::unique_ptr thread; + FunctionThread thread; std::unique_ptr timer; };