summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-09-06 00:45:44 +0200
committerCarl Hetherington <cth@carlh.net>2025-09-07 20:04:44 +0200
commit0eadbd860d04cc2322d18046f69e7a9b2cb437f4 (patch)
tree84f39eead37d204cbb80e956122b8f48f001cf42
parent506b98d414e96e53eb56a41ca991b691c8393408 (diff)
Add audio delay option to Config and player prefs.
-rw-r--r--src/lib/config.cc4
-rw-r--r--src/lib/config.h13
-rw-r--r--src/wx/full_config_dialog.cc2
-rw-r--r--src/wx/player_config_dialog.cc2
-rw-r--r--src/wx/sound_preferences_page.cc25
-rw-r--r--src/wx/sound_preferences_page.h11
m---------test/data0
7 files changed, 53 insertions, 4 deletions
diff --git a/src/lib/config.cc b/src/lib/config.cc
index 9b5bd34be..af97c7af7 100644
--- a/src/lib/config.cc
+++ b/src/lib/config.cc
@@ -115,6 +115,7 @@ Config::set_defaults()
_default_video_bit_rate[VideoEncoding::JPEG2000] = 150000000;
_default_video_bit_rate[VideoEncoding::MPEG2] = 5000000;
_default_audio_delay = 0;
+ _player_audio_delay = 0;
_default_interop = false;
_default_metadata.clear();
_upload_after_make_dcp = false;
@@ -385,6 +386,7 @@ try
}
_default_video_bit_rate[VideoEncoding::MPEG2] = f.optional_number_child<int64_t>("DefaultMPEG2VideoBitRate").get_value_or(5000000);
_default_audio_delay = f.optional_number_child<int>("DefaultAudioDelay").get_value_or(0);
+ _player_audio_delay = f.optional_number_child<int>("PlayerAudioDelay").get_value_or(0);
_default_interop = f.optional_bool_child("DefaultInterop").get_value_or(false);
try {
@@ -812,6 +814,8 @@ Config::write_config() const
cxml::add_text_child(root, "DefaultStillLength", fmt::to_string(_default_still_length));
/* [XML] DefaultAudioDelay Default delay to apply to audio (positive moves audio later) in milliseconds. */
cxml::add_text_child(root, "DefaultAudioDelay", fmt::to_string(_default_audio_delay));
+ /* [XML] PlayerAudioDelay Delay to apply to audio in the player (positive moves audio later) in milliseconds. */
+ cxml::add_text_child(root, "PlayerAudioDelay", fmt::to_string(_player_audio_delay));
if (_default_audio_language) {
/* [XML] DefaultAudioLanguage Default audio language to use for new films */
cxml::add_text_child(root, "DefaultAudioLanguage", _default_audio_language->as_string());
diff --git a/src/lib/config.h b/src/lib/config.h
index 2bc700e86..d8ff70db8 100644
--- a/src/lib/config.h
+++ b/src/lib/config.h
@@ -254,6 +254,10 @@ public:
return _default_audio_delay;
}
+ int player_audio_delay() const {
+ return _player_audio_delay;
+ }
+
bool default_interop() const {
return _default_interop;
}
@@ -821,6 +825,10 @@ public:
maybe_set(_default_audio_delay, d);
}
+ void set_player_audio_delay(int d) {
+ maybe_set(_player_audio_delay, d);
+ }
+
void set_default_audio_language(dcp::LanguageTag tag) {
maybe_set(_default_audio_language, tag);
}
@@ -1400,7 +1408,12 @@ private:
std::string _dcp_product_version;
std::string _dcp_j2k_comment;
EnumIndexedVector<int64_t, VideoEncoding> _default_video_bit_rate;
+ /** Default audio delay in ms */
int _default_audio_delay;
+ /** Delay for audio (with respect to picture) in the player, in ms.
+ * Can be negative to advance audio.
+ */
+ int _player_audio_delay;
bool _default_interop;
boost::optional<dcp::LanguageTag> _default_audio_language;
boost::optional<dcp::LanguageTag::RegionSubtag> _default_territory;
diff --git a/src/wx/full_config_dialog.cc b/src/wx/full_config_dialog.cc
index 704bce621..eff3fdee2 100644
--- a/src/wx/full_config_dialog.cc
+++ b/src/wx/full_config_dialog.cc
@@ -1487,7 +1487,7 @@ create_full_config_dialog()
#endif
e->AddPage(new FullGeneralPage(ps, border));
- e->AddPage(new preferences::SoundPage(ps, border));
+ e->AddPage(new preferences::SoundPage(ps, border, preferences::SoundPage::Purpose::MAIN));
e->AddPage(new DefaultsPage(ps, border));
e->AddPage(new EncodingServersPage(ps, border));
#ifdef DCPOMATIC_GROK
diff --git a/src/wx/player_config_dialog.cc b/src/wx/player_config_dialog.cc
index 90afdf3e6..5c0a34940 100644
--- a/src/wx/player_config_dialog.cc
+++ b/src/wx/player_config_dialog.cc
@@ -433,7 +433,7 @@ create_player_config_dialog()
#endif
e->AddPage(new PlayerGeneralPage(wxSize(-1, 500), border));
- e->AddPage(new preferences::SoundPage(ps, border));
+ e->AddPage(new preferences::SoundPage(ps, border, preferences::SoundPage::Purpose::PLAYER));
e->AddPage(new preferences::LocationsPage(ps, border));
e->AddPage(new preferences::KeysPage(ps, border));
e->AddPage(new PlayerAdvancedPage(ps, border));
diff --git a/src/wx/sound_preferences_page.cc b/src/wx/sound_preferences_page.cc
index dd2130f59..10e803e20 100644
--- a/src/wx/sound_preferences_page.cc
+++ b/src/wx/sound_preferences_page.cc
@@ -23,6 +23,7 @@
#include "audio_mapping_view.h"
#include "check_box.h"
#include "dcpomatic_button.h"
+#include "dcpomatic_spin_ctrl.h"
#include "sound_preferences_page.h"
#include "wx_util.h"
#include "lib/constants.h"
@@ -41,8 +42,9 @@ using namespace boost::placeholders;
using namespace dcpomatic::preferences;
-SoundPage::SoundPage(wxSize panel_size, int border)
+SoundPage::SoundPage(wxSize panel_size, int border, Purpose purpose)
: Page(panel_size, border)
+ , _purpose(purpose)
{
}
@@ -81,6 +83,16 @@ SoundPage::setup()
table->Add(s, wxGBPosition(r, 1));
++r;
+ if (_purpose == Purpose::PLAYER) {
+ add_label_to_sizer(table, _panel, _("Delay audio by"), true, wxGBPosition(r, 0));
+ auto s = new wxBoxSizer(wxHORIZONTAL);
+ _delay = new SpinCtrl(_panel, -1000, 1000);
+ s->Add(_delay, 0);
+ s->Add(new wxStaticText(_panel, wxID_ANY, _("ms")), 1, wxALIGN_CENTER_VERTICAL | wxLEFT, DCPOMATIC_SIZER_X_GAP);
+ table->Add(s, wxGBPosition(r, 1));
+ ++r;
+ }
+
add_label_to_sizer(table, _panel, _("Mapping"), true, wxGBPosition(r, 0));
_map = new AudioMappingView(_panel, _("DCP"), _("DCP"), _("Output"), _("output"));
table->Add(_map, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND);
@@ -101,6 +113,9 @@ SoundPage::setup()
_sound->bind(&SoundPage::sound_changed, this);
_sound_output->Bind(wxEVT_CHOICE, bind(&SoundPage::sound_output_changed, this));
+ if (_delay) {
+ _delay->bind(&SoundPage::delay_changed, this);
+ }
_map->Changed.connect(bind(&SoundPage::map_changed, this, _1));
_reset_to_default->Bind(wxEVT_BUTTON, bind(&SoundPage::reset_to_default, this));
}
@@ -136,6 +151,14 @@ SoundPage::sound_output_changed()
}
}
+
+void
+SoundPage::delay_changed()
+{
+ Config::instance()->set_player_audio_delay(_delay->get());
+}
+
+
void
SoundPage::config_changed()
{
diff --git a/src/wx/sound_preferences_page.h b/src/wx/sound_preferences_page.h
index f48083de9..52d2d17f8 100644
--- a/src/wx/sound_preferences_page.h
+++ b/src/wx/sound_preferences_page.h
@@ -28,6 +28,7 @@ class wxStaticText;
class AudioMappingView;
class Button;
class CheckBox;
+class SpinCtrl;
namespace dcpomatic {
@@ -37,7 +38,12 @@ namespace preferences {
class SoundPage : public Page
{
public:
- SoundPage(wxSize panel_size, int border);
+ enum class Purpose {
+ MAIN,
+ PLAYER,
+ };
+
+ SoundPage(wxSize panel_size, int border, Purpose purpose);
wxString GetName() const override;
@@ -51,12 +57,15 @@ private:
boost::optional<std::string> get_sound_output();
void sound_changed();
void sound_output_changed();
+ void delay_changed();
void setup_sensitivity();
void map_changed(AudioMapping m);
void reset_to_default();
+ Purpose _purpose;
CheckBox* _sound;
wxChoice* _sound_output;
+ SpinCtrl* _delay = nullptr;
wxStaticText* _sound_output_details;
AudioMappingView* _map;
Button* _reset_to_default;
diff --git a/test/data b/test/data
-Subproject 349501404a251e7250094937c418b7802724392
+Subproject e9931b4a897f730a1dddef460a20fd17006902f