diff options
| author | Carl Hetherington <cth@carlh.net> | 2024-09-11 02:04:49 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2024-09-11 02:04:49 +0200 |
| commit | 88bf4891b813b5fbf14b3073200429d2c12f751b (patch) | |
| tree | 74da3e945f070b169a0db1ef9b8c79f8d8071273 /src/wx | |
| parent | a405989c24016b543702640006170ce3d5089ecb (diff) | |
other stuff.more-abstract
Diffstat (limited to 'src/wx')
| -rw-r--r-- | src/wx/audio_backend.cc | 145 | ||||
| -rw-r--r-- | src/wx/audio_backend.h | 18 | ||||
| -rw-r--r-- | src/wx/config_dialog.cc | 19 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 107 |
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 (); } |
