plugin: abstract service + ref

This commit is contained in:
2 * r + 2 * t 2025-09-06 15:41:19 +10:00
parent cfc1dc447c
commit c99e05026f
9 changed files with 152 additions and 33 deletions

View file

@ -59,7 +59,7 @@ Item {
service: Cava
}
Ref {
ServiceRef {
service: BeatTracker
}

View file

@ -33,7 +33,7 @@ Item {
onTriggered: Players.active?.positionChanged()
}
Ref {
ServiceRef {
service: BeatTracker
}

View file

@ -11,6 +11,8 @@ qt_add_qml_module(caelestia
filesystemmodel.hpp filesystemmodel.cpp
qalculator.hpp qalculator.cpp
beattracker.hpp beattracker.cpp
service.hpp service.cpp
serviceref.hpp serviceref.cpp
)
qt_query_qml_module(caelestia

View file

@ -1,5 +1,6 @@
#include "beattracker.hpp"
#include "service.hpp"
#include <QAudioSource>
#include <QDebug>
#include <QIODevice>
@ -10,13 +11,12 @@
namespace caelestia {
BeatTracker::BeatTracker(uint_t sampleRate, uint_t hopSize, QObject* parent)
: QObject(parent)
: Service(parent)
, m_tempo(new_aubio_tempo("default", 1024, hopSize, sampleRate))
, m_in(new_fvec(hopSize))
, m_out(new_fvec(2))
, m_hopSize(hopSize)
, m_bpm(120)
, m_refCount(0) {
, m_bpm(120) {
QAudioFormat format;
format.setSampleRate(static_cast<int>(sampleRate));
format.setChannelCount(1);
@ -39,25 +39,6 @@ smpl_t BeatTracker::bpm() const {
return m_bpm;
}
int BeatTracker::refCount() const {
return m_refCount;
}
void BeatTracker::setRefCount(int refCount) {
if (m_refCount == refCount) {
return;
}
m_refCount = refCount;
emit refCountChanged();
if (m_refCount == 0) {
stop();
} else if (!m_device) {
start();
}
}
void BeatTracker::start() {
m_device = m_source->start();
connect(m_device, &QIODevice::readyRead, this, &BeatTracker::process);

View file

@ -1,5 +1,6 @@
#pragma once
#include "service.hpp"
#include <QAudioSource>
#include <QIODevice>
#include <QObject>
@ -8,13 +9,12 @@
namespace caelestia {
class BeatTracker : public QObject {
class BeatTracker : public Service {
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(smpl_t bpm READ bpm NOTIFY bpmChanged)
Q_PROPERTY(int refCount READ refCount WRITE setRefCount NOTIFY refCountChanged)
public:
explicit BeatTracker(uint_t sampleRate = 44100, uint_t hopSize = 512, QObject* parent = nullptr);
@ -22,12 +22,8 @@ public:
[[nodiscard]] smpl_t bpm() const;
[[nodiscard]] int refCount() const;
void setRefCount(int refCount);
signals:
void bpmChanged();
void refCountChanged();
void beat(smpl_t bpm);
private:
@ -40,10 +36,9 @@ private:
uint_t m_hopSize;
smpl_t m_bpm;
int m_refCount;
void start();
void stop();
void start() override;
void stop() override;
void process();
void handleStateChanged(QtAudio::State state) const;
};

View file

@ -0,0 +1,39 @@
#include "service.hpp"
#include <QDebug>
#include <QObject>
namespace caelestia {
Service::Service(QObject* parent)
: QObject(parent)
, m_refCount(0) {}
int Service::refCount() const {
return m_refCount;
}
void Service::ref() {
if (m_refCount == 0) {
start();
}
m_refCount++;
emit refCountChanged();
}
void Service::unref() {
if (m_refCount == 0) {
qWarning() << "ServiceRef::unref: attempted to unref service with no active refs";
return;
}
m_refCount--;
emit refCountChanged();
if (m_refCount == 0) {
stop();
}
}
} // namespace caelestia

View file

@ -0,0 +1,30 @@
#pragma once
#include <QObject>
namespace caelestia {
class Service : public QObject {
Q_OBJECT
Q_PROPERTY(int refCount READ refCount NOTIFY refCountChanged)
public:
explicit Service(QObject* parent = nullptr);
[[nodiscard]] int refCount() const;
void ref();
void unref();
signals:
void refCountChanged();
private:
int m_refCount;
virtual void start() = 0;
virtual void stop() = 0;
};
} // namespace caelestia

View file

@ -0,0 +1,43 @@
#include "serviceref.hpp"
#include "service.hpp"
#include <QObject>
namespace caelestia {
ServiceRef::ServiceRef(Service* service, QObject* parent)
: QObject(parent)
, m_service(service) {
if (m_service) {
m_service->ref();
}
}
ServiceRef::~ServiceRef() {
if (m_service) {
m_service->unref();
}
}
Service* ServiceRef::service() const {
return m_service;
}
void ServiceRef::setService(Service* service) {
if (m_service == service) {
return;
}
if (m_service) {
m_service->unref();
}
m_service = service;
emit serviceChanged();
if (m_service) {
m_service->ref();
}
}
} // namespace caelestia

View file

@ -0,0 +1,29 @@
#pragma once
#include "service.hpp"
#include <QObject>
#include <qqmlintegration.h>
namespace caelestia {
class ServiceRef : public QObject {
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(Service* service READ service WRITE setService NOTIFY serviceChanged)
public:
explicit ServiceRef(Service* service = nullptr, QObject* parent = nullptr);
~ServiceRef();
[[nodiscard]] Service* service() const;
void setService(Service* service);
signals:
void serviceChanged();
private:
Service* m_service;
};
} // namespace caelestia