summaryrefslogtreecommitdiff
path: root/src/wx
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2024-09-11 02:04:49 +0200
committerCarl Hetherington <cth@carlh.net>2024-09-11 02:04:49 +0200
commit88bf4891b813b5fbf14b3073200429d2c12f751b (patch)
tree74da3e945f070b169a0db1ef9b8c79f8d8071273 /src/wx
parenta405989c24016b543702640006170ce3d5089ecb (diff)
other stuff.more-abstract
Diffstat (limited to 'src/wx')
-rw-r--r--src/wx/audio_backend.cc145
-rw-r--r--src/wx/audio_backend.h18
-rw-r--r--src/wx/config_dialog.cc19
-rw-r--r--src/wx/film_viewer.cc107
4 files changed, 183 insertions, 106 deletions
diff --git a/src/wx/audio_backend.cc b/src/wx/audio_backend.cc
index 787ff4ee4..9e3dd1dee 100644
--- a/src/wx/audio_backend.cc
+++ b/src/wx/audio_backend.cc
@@ -20,9 +20,12 @@
#include "audio_backend.h"
+#include "wx_util.h"
#include <boost/bind/bind.hpp>
+
+using std::map;
using std::string;
using std::vector;
using boost::optional;
@@ -184,3 +187,145 @@ AudioBackend::start_stream()
}
+bool
+AudioBackend::stream_open() const
+{
+ return _rtaudio.isStreamOpen();
+}
+
+
+bool
+AudioBackend::stream_running() const
+{
+ return _rtaudio.isStreamRunning();
+}
+
+
+double
+AudioBackend::stream_time() const
+{
+ return const_cast<RtAudio&>(_rtaudio).getStreamTime();
+}
+
+
+wxString
+AudioBackend::current_api_name() const
+{
+ switch (const_cast<RtAudio&>(_rtaudio).getCurrentApi()) {
+ case RtAudio::MACOSX_CORE:
+ return _("CoreAudio");
+ case RtAudio::WINDOWS_ASIO:
+ return _("ASIO");
+ case RtAudio::WINDOWS_DS:
+ return _("Direct Sound");
+ case RtAudio::WINDOWS_WASAPI:
+ return _("WASAPI");
+ case RtAudio::UNIX_JACK:
+ return _("JACK");
+ case RtAudio::LINUX_ALSA:
+ return _("ALSA");
+ case RtAudio::LINUX_PULSE:
+ return _("PulseAudio");
+ case RtAudio::LINUX_OSS:
+ return _("OSS");
+ case RtAudio::RTAUDIO_DUMMY:
+ return _("Dummy");
+ default:
+ DCPOMATIC_ASSERT(false);
+ }
+}
+
+
+int64_t
+AudioBackend::stream_latency() const
+{
+ return const_cast<RtAudio&>(_rtaudio).getStreamLatency();
+}
+
+
+void
+AudioBackend::set_stream_time(double time)
+{
+ _rtaudio.setStreamTime(time);
+}
+
+
+void
+AudioBackend::close_stream()
+{
+ _rtaudio.closeStream();
+}
+
+
+bool
+AudioBackend::open_stream(RtAudioCallback callback, void* context, int* channels, unsigned int* block_size, optional<string> output)
+{
+ optional<unsigned int> chosen_device_id;
+#if (RTAUDIO_VERSION_MAJOR >= 6)
+ if (output) {
+ for (auto device_id: _rtaudio.getDeviceIds()) {
+ if (_rtaudio.getDeviceInfo(device_id).name == *output) {
+ chosen_device_id = device_id;
+ break;
+ }
+ }
+ }
+
+ if (!chosen_device_id) {
+ chosen_device_id = _rtaudio.getDefaultOutputDevice();
+ }
+ *channels = _rtaudio.getDeviceInfo(*chosen_device_id).outputChannels;
+ RtAudio::StreamParameters sp;
+ sp.deviceId = *chosen_device_id;
+ sp.nChannels = *channels;
+ sp.firstChannel = 0;
+ if (_rtaudio.openStream(&sp, 0, RTAUDIO_FLOAT32, 48000, block_size, callback, context) != RTAUDIO_NO_ERROR) {
+ *channels = 0;
+ return false;
+ }
+#else
+ unsigned int st = 0;
+ if (output) {
+ while (st < _rtaudio.getDeviceCount()) {
+ try {
+ if (_rtaudio.getDeviceInfo(st).name == *output) {
+ break;
+ }
+ } catch (RtAudioError&) {
+ /* Something went wrong with that device so we don't want to use it anyway */
+ }
+ ++st;
+ }
+ if (st == _rtaudio.getDeviceCount()) {
+ try {
+ st = _rtaudio.getDefaultOutputDevice();
+ } catch (RtAudioError&) {
+ /* Something went wrong with that device so we don't want to use it anyway */
+ }
+ }
+ } else {
+ try {
+ st = _rtaudio.getDefaultOutputDevice();
+ } catch (RtAudioError&) {
+ /* Something went wrong with that device so we don't want to use it anyway */
+ }
+ }
+
+ try {
+ *channels = audio.getDeviceInfo(st).outputChannels;
+ RtAudio::StreamParameters sp;
+ sp.deviceId = st;
+ sp.nChannels = *channels;
+ sp.firstChannel = 0;
+ _rtaudio.openStream(&sp, 0, RTAUDIO_FLOAT32, 48000, block_size, callback, context);
+ } catch (RtAudioError& e) {
+ boost::mutex::scoped_lock lm(_last_error_mutex);
+ _last_error = e.what();
+ *channels = 0;
+ return false;
+ }
+#endif
+
+ return true;
+}
+
diff --git a/src/wx/audio_backend.h b/src/wx/audio_backend.h
index 170c71e05..05d1a06b5 100644
--- a/src/wx/audio_backend.h
+++ b/src/wx/audio_backend.h
@@ -23,6 +23,7 @@
LIBDCP_DISABLE_WARNINGS
#include <RtAudio.h>
LIBDCP_ENABLE_WARNINGS
+#include <wx/wx.h>
#include <boost/optional.hpp>
#include <boost/thread/mutex.hpp>
@@ -36,16 +37,23 @@ public:
AudioBackend(AudioBackend const&) = delete;
AudioBackend& operator=(AudioBackend const&) = delete;
- RtAudio& rtaudio() {
- return _rtaudio;
- }
-
std::vector<std::string> device_names();
boost::optional<std::string> default_device_name();
boost::optional<int> device_channels(std::string name);
- void abort_stream_if_running();
+ bool open_stream(RtAudioCallback callback, void* context, int* channels, unsigned int* block_size, boost::optional<std::string> output);
boost::optional<std::string> start_stream();
+ void abort_stream_if_running();
+ void close_stream();
+
+ bool stream_open() const;
+ bool stream_running() const;
+ double stream_time() const;
+ int64_t stream_latency() const;
+
+ void set_stream_time(double time);
+
+ wxString current_api_name() const;
#if (RTAUDIO_VERSION_MAJOR >= 6)
std::string last_error() const;
diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc
index fd380d5d1..4f7b70390 100644
--- a/src/wx/config_dialog.cc
+++ b/src/wx/config_dialog.cc
@@ -934,13 +934,13 @@ SoundPage::config_changed ()
auto const current_so = get_sound_output ();
optional<string> configured_so;
- auto& audio = AudioBackend::instance()->rtaudio();
+ auto audio = AudioBackend::instance();
if (config->sound_output()) {
configured_so = config->sound_output().get();
} else {
/* No configured output means we should use the default */
- configured_so = AudioBackend::instance()->default_device_name();
+ configured_so = audio->default_device_name();
}
if (configured_so && current_so != configured_so) {
@@ -955,21 +955,10 @@ SoundPage::config_changed ()
}
}
- map<int, wxString> apis;
- apis[RtAudio::MACOSX_CORE] = _("CoreAudio");
- apis[RtAudio::WINDOWS_ASIO] = _("ASIO");
- apis[RtAudio::WINDOWS_DS] = _("Direct Sound");
- apis[RtAudio::WINDOWS_WASAPI] = _("WASAPI");
- apis[RtAudio::UNIX_JACK] = _("JACK");
- apis[RtAudio::LINUX_ALSA] = _("ALSA");
- apis[RtAudio::LINUX_PULSE] = _("PulseAudio");
- apis[RtAudio::LINUX_OSS] = _("OSS");
- apis[RtAudio::RTAUDIO_DUMMY] = _("Dummy");
-
- int const channels = configured_so ? AudioBackend::instance()->device_output_channels(*configured_so).get_value_or(0) : 0;
+ int const channels = configured_so ? AudioBackend::instance()->device_channels(*configured_so).get_value_or(0) : 0;
_sound_output_details->SetLabel (
- wxString::Format(_("%d channels on %s"), channels, apis[audio.getCurrentApi()])
+ wxString::Format(_("%d channels on %s"), channels, audio->current_api_name())
);
_map->set (Config::instance()->audio_mapping(channels));
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index 9edd4578e..d26cac681 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -239,7 +239,7 @@ FilmViewer::create_butler()
DCPOMATIC_ASSERT(_player);
- auto& audio = AudioBackend::instance()->rtaudio();
+ auto audio = AudioBackend::instance();
_butler = std::make_shared<Butler>(
_film,
@@ -251,7 +251,7 @@ FilmViewer::create_butler()
(opengl && _optimisation != Optimisation::NONE) ? Image::Alignment::COMPACT : Image::Alignment::PADDED,
true,
opengl && _optimisation == Optimisation::JPEG2000,
- (Config::instance()->sound() && audio.isStreamOpen()) ? Butler::Audio::ENABLED : Butler::Audio::DISABLED
+ (Config::instance()->sound() && audio->stream_open()) ? Butler::Audio::ENABLED : Butler::Audio::DISABLED
);
_closed_captions_dialog->set_butler (_butler);
@@ -350,11 +350,11 @@ FilmViewer::suspend ()
void
FilmViewer::start_audio_stream_if_open ()
{
- auto& audio = AudioBackend::instance()->rtaudio();
+ auto audio = AudioBackend::instance();
- if (audio.isStreamOpen()) {
- audio.setStreamTime(_video_view->position().seconds());
- auto error = AudioBackend::instance()->start_stream();
+ if (audio->stream_open()) {
+ audio->set_stream_time(_video_view->position().seconds());
+ auto error = audio->start_stream();
if (error) {
_audio_channels = 0;
error_dialog(
@@ -603,85 +603,20 @@ FilmViewer::config_changed (Config::Property p)
return;
}
- auto backend = AudioBackend::instance();
- auto& audio = backend->rtaudio();
+ auto audio = AudioBackend::instance();
- if (audio.isStreamOpen()) {
- audio.closeStream();
+ if (audio->stream_open()) {
+ audio->close_stream();
}
- if (Config::instance()->sound() && audio.getDeviceCount() > 0) {
- optional<unsigned int> chosen_device_id;
-#if (RTAUDIO_VERSION_MAJOR >= 6)
- if (Config::instance()->sound_output()) {
- for (auto device_id: audio.getDeviceIds()) {
- if (audio.getDeviceInfo(device_id).name == Config::instance()->sound_output().get()) {
- chosen_device_id = device_id;
- break;
- }
- }
- }
-
- if (!chosen_device_id) {
- chosen_device_id = audio.getDefaultOutputDevice();
- }
- _audio_channels = audio.getDeviceInfo(*chosen_device_id).outputChannels;
- RtAudio::StreamParameters sp;
- sp.deviceId = *chosen_device_id;
- sp.nChannels = _audio_channels;
- sp.firstChannel = 0;
- if (audio.openStream(&sp, 0, RTAUDIO_FLOAT32, 48000, &_audio_block_size, &rtaudio_callback, this) != RTAUDIO_NO_ERROR) {
- _audio_channels = 0;
+ if (Config::instance()->sound() && !audio->device_names().empty()) {
+ if (!audio->open_stream(&rtaudio_callback, this, &_audio_channels, &_audio_block_size, Config::instance()->sound_output())) {
error_dialog(
_video_view->get(),
- _("Could not set up audio output. There will be no audio during the preview."), std_to_wx(backend->last_rtaudio_error())
- );
- }
-#else
- unsigned int st = 0;
- if (Config::instance()->sound_output()) {
- while (st < audio.getDeviceCount()) {
- try {
- if (audio.getDeviceInfo(st).name == Config::instance()->sound_output().get()) {
- break;
- }
- } catch (RtAudioError&) {
- /* Something went wrong with that device so we don't want to use it anyway */
- }
- ++st;
- }
- if (st == audio.getDeviceCount()) {
- try {
- st = audio.getDefaultOutputDevice();
- } catch (RtAudioError&) {
- /* Something went wrong with that device so we don't want to use it anyway */
- }
- }
- } else {
- try {
- st = audio.getDefaultOutputDevice();
- } catch (RtAudioError&) {
- /* Something went wrong with that device so we don't want to use it anyway */
- }
- }
-
- try {
- _audio_channels = audio.getDeviceInfo(st).outputChannels;
- RtAudio::StreamParameters sp;
- sp.deviceId = st;
- sp.nChannels = _audio_channels;
- sp.firstChannel = 0;
- audio.openStream(&sp, 0, RTAUDIO_FLOAT32, 48000, &_audio_block_size, &rtaudio_callback, this);
- } catch (RtAudioError& e) {
- _audio_channels = 0;
- error_dialog (
- _video_view->get(),
- _("Could not set up audio output. There will be no audio during the preview."), std_to_wx(e.what())
+ _("Could not set up audio output. There will be no audio during the preview."), std_to_wx(audio->last_error())
);
+ destroy_and_maybe_create_butler();
}
-#endif
- destroy_and_maybe_create_butler();
-
} else {
_audio_channels = 0;
destroy_and_maybe_create_butler();
@@ -692,10 +627,10 @@ FilmViewer::config_changed (Config::Property p)
DCPTime
FilmViewer::uncorrected_time () const
{
- auto& audio = AudioBackend::instance()->rtaudio();
+ auto audio = AudioBackend::instance();
- if (audio.isStreamRunning()) {
- return DCPTime::from_seconds(audio.getStreamTime());
+ if (audio->stream_running()) {
+ return DCPTime::from_seconds(audio->stream_time());
}
return _video_view->position();
@@ -705,13 +640,13 @@ FilmViewer::uncorrected_time () const
optional<DCPTime>
FilmViewer::audio_time () const
{
- auto& audio = AudioBackend::instance()->rtaudio();
+ auto audio = AudioBackend::instance();
- if (!audio.isStreamRunning()) {
+ if (!audio->stream_running()) {
return {};
}
- return DCPTime::from_seconds(audio.getStreamTime()) -
+ return DCPTime::from_seconds(audio->stream_time()) -
DCPTime::from_frames (average_latency(), _film->audio_frame_rate());
}
@@ -735,11 +670,11 @@ FilmViewer::audio_callback (void* out_p, unsigned int frames)
/* The audio we just got was (very) late; drop it and get some more. */
}
- auto& audio = AudioBackend::instance()->rtaudio();
+ auto audio = AudioBackend::instance();
boost::mutex::scoped_lock lm (_latency_history_mutex, boost::try_to_lock);
if (lm) {
- _latency_history.push_back(audio.getStreamLatency());
+ _latency_history.push_back(audio->stream_latency());
if (_latency_history.size() > static_cast<size_t> (_latency_history_count)) {
_latency_history.pop_front ();
}