summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-11-29 17:14:35 +0100
committerDavid Robillard <d@drobilla.net>2020-11-29 18:03:31 +0100
commit78b359c44b67f4f1fff9e31dd9243af5e996f38a (patch)
tree59aeee028fd339894e94eb21fc5cdbf53a2b8c5d
parentd3561e8cf1d5a289ff2ce4a26e4a970437a812d5 (diff)
downloadpatchage-78b359c44b67f4f1fff9e31dd9243af5e996f38a.tar.gz
patchage-78b359c44b67f4f1fff9e31dd9243af5e996f38a.tar.bz2
patchage-78b359c44b67f4f1fff9e31dd9243af5e996f38a.zip
Add AudioDriver interface
-rw-r--r--src/AudioDriver.hpp48
-rw-r--r--src/JackDbusDriver.cpp110
-rw-r--r--src/JackDbusDriver.hpp25
-rw-r--r--src/JackDriver.cpp86
-rw-r--r--src/JackDriver.hpp23
-rw-r--r--src/Patchage.cpp2
6 files changed, 176 insertions, 118 deletions
diff --git a/src/AudioDriver.hpp b/src/AudioDriver.hpp
new file mode 100644
index 0000000..7e1e5a7
--- /dev/null
+++ b/src/AudioDriver.hpp
@@ -0,0 +1,48 @@
+/* This file is part of Patchage.
+ * Copyright 2007-2020 David Robillard <d@drobilla.net>
+ *
+ * Patchage is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Patchage is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Patchage. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PATCHAGE_AUDIODRIVER_HPP
+#define PATCHAGE_AUDIODRIVER_HPP
+
+#include "Driver.hpp"
+
+#include <cstdint>
+
+/// Base class for drivers that work with an audio system
+class AudioDriver : public Driver
+{
+public:
+ explicit AudioDriver(EventSink emit_event)
+ : Driver{std::move(emit_event)}
+ {}
+
+ /// Return the number of xruns (dropouts) since the last reset
+ virtual uint32_t xruns() = 0;
+
+ /// Reset the xrun count
+ virtual void reset_xruns() = 0;
+
+ /// Return the current buffer size in frames
+ virtual uint32_t buffer_size() = 0;
+
+ /// Try to set the current buffer size in frames, return true on success
+ virtual bool set_buffer_size(uint32_t frames) = 0;
+
+ /// Return the current sample rate in Hz
+ virtual uint32_t sample_rate() = 0;
+};
+
+#endif // PATCHAGE_AUDIODRIVER_HPP
diff --git a/src/JackDbusDriver.cpp b/src/JackDbusDriver.cpp
index 4ab7b8c..add838d 100644
--- a/src/JackDbusDriver.cpp
+++ b/src/JackDbusDriver.cpp
@@ -55,7 +55,7 @@ PATCHAGE_RESTORE_WARNINGS
#define JACKDBUS_PORT_TYPE_MIDI 1
JackDriver::JackDriver(ILog& log, EventSink emit_event)
- : Driver{std::move(emit_event)}
+ : AudioDriver{std::move(emit_event)}
, _log(log)
, _dbus_error()
, _dbus_connection(nullptr)
@@ -722,6 +722,56 @@ JackDriver::disconnect(const PortID& tail_id, const PortID& head_id)
}
uint32_t
+JackDriver::xruns()
+{
+ DBusMessage* reply_ptr = nullptr;
+ dbus_uint32_t xruns = 0u;
+
+ if (_server_responding && !_server_started) {
+ return 0;
+ }
+
+ if (!call(true,
+ JACKDBUS_IFACE_CONTROL,
+ "GetXruns",
+ &reply_ptr,
+ DBUS_TYPE_INVALID)) {
+ return 0;
+ }
+
+ if (!dbus_message_get_args(reply_ptr,
+ &_dbus_error,
+ DBUS_TYPE_UINT32,
+ &xruns,
+ DBUS_TYPE_INVALID)) {
+ dbus_message_unref(reply_ptr);
+ dbus_error_free(&_dbus_error);
+ error_msg("Decoding reply of GetXruns failed");
+ return 0;
+ }
+
+ dbus_message_unref(reply_ptr);
+
+ return xruns;
+}
+
+void
+JackDriver::reset_xruns()
+{
+ DBusMessage* reply_ptr = nullptr;
+
+ if (!call(true,
+ JACKDBUS_IFACE_CONTROL,
+ "ResetXruns",
+ &reply_ptr,
+ DBUS_TYPE_INVALID)) {
+ return;
+ }
+
+ dbus_message_unref(reply_ptr);
+}
+
+uint32_t
JackDriver::buffer_size()
{
DBusMessage* reply_ptr = nullptr;
@@ -756,12 +806,10 @@ JackDriver::buffer_size()
}
bool
-JackDriver::set_buffer_size(const uint32_t size)
+JackDriver::set_buffer_size(const uint32_t frames)
{
DBusMessage* reply_ptr = nullptr;
- dbus_uint32_t buffer_size = 0u;
-
- buffer_size = size;
+ dbus_uint32_t buffer_size = frames;
if (!call(true,
JACKDBUS_IFACE_CONTROL,
@@ -778,7 +826,7 @@ JackDriver::set_buffer_size(const uint32_t size)
return true;
}
-float
+uint32_t
JackDriver::sample_rate()
{
DBusMessage* reply_ptr = nullptr;
@@ -808,56 +856,6 @@ JackDriver::sample_rate()
return sample_rate;
}
-uint32_t
-JackDriver::get_xruns()
-{
- DBusMessage* reply_ptr = nullptr;
- dbus_uint32_t xruns = 0u;
-
- if (_server_responding && !_server_started) {
- return 0;
- }
-
- if (!call(true,
- JACKDBUS_IFACE_CONTROL,
- "GetXruns",
- &reply_ptr,
- DBUS_TYPE_INVALID)) {
- return 0;
- }
-
- if (!dbus_message_get_args(reply_ptr,
- &_dbus_error,
- DBUS_TYPE_UINT32,
- &xruns,
- DBUS_TYPE_INVALID)) {
- dbus_message_unref(reply_ptr);
- dbus_error_free(&_dbus_error);
- error_msg("Decoding reply of GetXruns failed");
- return 0;
- }
-
- dbus_message_unref(reply_ptr);
-
- return xruns;
-}
-
-void
-JackDriver::reset_xruns()
-{
- DBusMessage* reply_ptr = nullptr;
-
- if (!call(true,
- JACKDBUS_IFACE_CONTROL,
- "ResetXruns",
- &reply_ptr,
- DBUS_TYPE_INVALID)) {
- return;
- }
-
- dbus_message_unref(reply_ptr);
-}
-
PortType
JackDriver::patchage_port_type(const dbus_uint32_t dbus_port_type) const
{
diff --git a/src/JackDbusDriver.hpp b/src/JackDbusDriver.hpp
index 42c70ef..068c7cc 100644
--- a/src/JackDbusDriver.hpp
+++ b/src/JackDbusDriver.hpp
@@ -18,7 +18,7 @@
#ifndef PATCHAGE_JACKDBUSDRIVER_HPP
#define PATCHAGE_JACKDBUSDRIVER_HPP
-#include "Driver.hpp"
+#include "AudioDriver.hpp"
#include <dbus/dbus.h>
@@ -28,7 +28,7 @@
class ILog;
/// Driver for JACK audio and midi ports that uses D-Bus
-class JackDriver : public Driver
+class JackDriver : public AudioDriver
{
public:
explicit JackDriver(ILog& log, EventSink emit_event);
@@ -41,23 +41,20 @@ public:
~JackDriver() override;
+ // Driver interface
void attach(bool launch_daemon) override;
void detach() override;
-
bool is_attached() const override;
-
void refresh(const EventSink& sink) override;
-
bool connect(const PortID& tail_id, const PortID& head_id) override;
-
bool disconnect(const PortID& tail_id, const PortID& head_id) override;
- uint32_t get_xruns();
- void reset_xruns();
-
- float sample_rate();
- uint32_t buffer_size();
- bool set_buffer_size(uint32_t size);
+ // AudioDriver interface
+ uint32_t xruns() override;
+ void reset_xruns() override;
+ uint32_t buffer_size() override;
+ bool set_buffer_size(uint32_t frames) override;
+ uint32_t sample_rate() override;
private:
PortType patchage_port_type(dbus_uint32_t dbus_port_type) const;
@@ -96,8 +93,8 @@ private:
DBusError _dbus_error;
DBusConnection* _dbus_connection;
- bool _server_responding;
- bool _server_started;
+ mutable bool _server_responding;
+ bool _server_started;
dbus_uint64_t _graph_version;
};
diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp
index b30d45f..b3c7658 100644
--- a/src/JackDriver.cpp
+++ b/src/JackDriver.cpp
@@ -46,7 +46,7 @@ PATCHAGE_RESTORE_WARNINGS
#include <utility>
JackDriver::JackDriver(ILog& log, EventSink emit_event)
- : Driver{std::move(emit_event)}
+ : AudioDriver{std::move(emit_event)}
, _log{log}
, _is_activated{false}
{}
@@ -108,6 +108,12 @@ JackDriver::detach()
_emit_event(DriverDetachmentEvent{ClientType::jack});
}
+bool
+JackDriver::is_attached() const
+{
+ return _client != nullptr;
+}
+
static std::string
get_property(const jack_uuid_t subject, const char* const key)
{
@@ -299,6 +305,51 @@ JackDriver::disconnect(const PortID& tail_id, const PortID& head_id)
return true;
}
+uint32_t
+JackDriver::xruns()
+{
+ return _xruns;
+}
+
+void
+JackDriver::reset_xruns()
+{
+ _xruns = 0;
+}
+
+uint32_t
+JackDriver::buffer_size()
+{
+ return _is_activated ? _buffer_size : jack_get_buffer_size(_client);
+}
+
+bool
+JackDriver::set_buffer_size(const uint32_t frames)
+{
+ if (!_client) {
+ _buffer_size = frames;
+ return true;
+ }
+
+ if (buffer_size() == frames) {
+ return true;
+ }
+
+ if (jack_set_buffer_size(_client, frames)) {
+ _log.error("[JACK] Unable to set buffer size");
+ return false;
+ }
+
+ _buffer_size = frames;
+ return true;
+}
+
+uint32_t
+JackDriver::sample_rate()
+{
+ return jack_get_sample_rate(_client);
+}
+
void
JackDriver::jack_client_registration_cb(const char* const name,
const int registered,
@@ -375,36 +426,3 @@ JackDriver::jack_shutdown_cb(void* const jack_driver)
me->_emit_event(DriverDetachmentEvent{ClientType::jack});
}
-
-jack_nframes_t
-JackDriver::buffer_size()
-{
- return _is_activated ? _buffer_size : jack_get_buffer_size(_client);
-}
-
-void
-JackDriver::reset_xruns()
-{
- _xruns = 0;
-}
-
-bool
-JackDriver::set_buffer_size(jack_nframes_t size)
-{
- if (!_client) {
- _buffer_size = size;
- return true;
- }
-
- if (buffer_size() == size) {
- return true;
- }
-
- if (jack_set_buffer_size(_client, size)) {
- _log.error("[JACK] Unable to set buffer size");
- return false;
- }
-
- _buffer_size = size;
- return true;
-}
diff --git a/src/JackDriver.hpp b/src/JackDriver.hpp
index d93b491..078e7d2 100644
--- a/src/JackDriver.hpp
+++ b/src/JackDriver.hpp
@@ -17,8 +17,8 @@
#ifndef PATCHAGE_JACKDRIVER_HPP
#define PATCHAGE_JACKDRIVER_HPP
+#include "AudioDriver.hpp"
#include "ClientInfo.hpp"
-#include "Driver.hpp"
#include "PortInfo.hpp"
#include <jack/jack.h>
@@ -30,7 +30,7 @@
class ILog;
/// Driver for JACK audio and midi ports that uses libjack
-class JackDriver : public Driver
+class JackDriver : public AudioDriver
{
public:
explicit JackDriver(ILog& log, EventSink emit_event);
@@ -43,23 +43,20 @@ public:
~JackDriver() override;
+ // Driver interface
void attach(bool launch_daemon) override;
void detach() override;
-
- bool is_attached() const override { return (_client != nullptr); }
-
+ bool is_attached() const override;
void refresh(const EventSink& sink) override;
-
bool connect(const PortID& tail_id, const PortID& head_id) override;
-
bool disconnect(const PortID& tail_id, const PortID& head_id) override;
- uint32_t get_xruns() const { return _xruns; }
- void reset_xruns();
-
- uint32_t sample_rate() { return jack_get_sample_rate(_client); }
- uint32_t buffer_size();
- bool set_buffer_size(jack_nframes_t size);
+ // AudioDriver interface
+ uint32_t xruns() override;
+ void reset_xruns() override;
+ uint32_t buffer_size() override;
+ bool set_buffer_size(uint32_t frames) override;
+ uint32_t sample_rate() override;
private:
ClientInfo get_client_info(const char* name);
diff --git a/src/Patchage.cpp b/src/Patchage.cpp
index 7ce1f07..5936107 100644
--- a/src/Patchage.cpp
+++ b/src/Patchage.cpp
@@ -430,7 +430,7 @@ Patchage::update_load()
{
#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
if (_jack_driver->is_attached()) {
- const auto xruns = _jack_driver->get_xruns();
+ const auto xruns = _jack_driver->xruns();
if (xruns > 0u) {
_dropouts_label->set_text(fmt::format(" Dropouts: {}", xruns));
_dropouts_label->show();