, _audio_mapping (audio_mapping)
, _audio_channels (audio_channels)
, _stop_thread (false)
+ , _disable_audio (false)
{
_player_video_connection = _player->Video.connect (bind (&Butler::video, this, _1, _2));
_player_audio_connection = _player->Audio.connect (bind (&Butler::audio, this, _1, _2));
{
{
boost::mutex::scoped_lock lm (_mutex);
- if (_pending_seek_position) {
- /* Don't store any audio while a seek is pending */
+ if (_pending_seek_position || _disable_audio) {
+ /* Don't store any audio while a seek is pending, or if audio is disabled */
return;
}
}
_audio.get (out, _audio_channels, frames);
_summon.notify_all ();
}
+
+void
+Butler::disable_audio ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ _disable_audio = true;
+}
std::pair<boost::shared_ptr<PlayerVideo>, DCPTime> get_video ();
void get_audio (float* out, Frame frames);
+ void disable_audio ();
+
private:
void thread ();
void video (boost::shared_ptr<PlayerVideo> video, DCPTime time);
int _audio_channels;
bool _stop_thread;
+ bool _disable_audio;
boost::signals2::scoped_connection _player_video_connection;
boost::signals2::scoped_connection _player_audio_connection;
_dcp_metadata_filename_format = dcp::NameFormat ("%t");
_dcp_asset_filename_format = dcp::NameFormat ("%t");
_jump_to_selected = true;
- _sound_output = optional<string> ();
+ _preview_sound = false;
+ _preview_sound_output = optional<string> ();
_allowed_dcp_frame_rates.clear ();
_allowed_dcp_frame_rates.push_back (24);
_dcp_metadata_filename_format = dcp::NameFormat (f.optional_string_child("DCPMetadataFilenameFormat").get_value_or ("%t"));
_dcp_asset_filename_format = dcp::NameFormat (f.optional_string_child("DCPAssetFilenameFormat").get_value_or ("%t"));
_jump_to_selected = f.optional_bool_child("JumpToSelected").get_value_or (true);
- _sound_output = f.optional_string_child("SoundOutput");
+ _preview_sound = f.optional_bool_child("PreviewSound").get_value_or (false);
+ _preview_sound_output = f.optional_string_child("PreviewSoundOutput");
/* Replace any cinemas from config.xml with those from the configured file */
if (boost::filesystem::exists (_cinemas_file)) {
root->add_child("DCPMetadataFilenameFormat")->add_child_text (_dcp_metadata_filename_format.specification ());
root->add_child("DCPAssetFilenameFormat")->add_child_text (_dcp_asset_filename_format.specification ());
root->add_child("JumpToSelected")->add_child_text (_jump_to_selected ? "1" : "0");
- if (_sound_output) {
- root->add_child("SoundOutput")->add_child_text (_sound_output.get());
+ root->add_child("PreviewSound")->add_child_text (_preview_sound ? "1" : "0");
+ if (_preview_sound_output) {
+ root->add_child("PreviewSoundOutput")->add_child_text (_preview_sound_output.get());
}
try {
/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
USE_ANY_SERVERS,
SERVERS,
CINEMAS,
- SOUND_OUTPUT,
+ PREVIEW_SOUND,
+ PREVIEW_SOUND_OUTPUT,
OTHER
};
return _jump_to_selected;
}
- boost::optional<std::string> sound_output () const {
- return _sound_output;
+ bool preview_sound () const {
+ return _preview_sound;
+ }
+
+ boost::optional<std::string> preview_sound_output () const {
+ return _preview_sound_output;
}
/** @param n New number of local encoding threads */
maybe_set (_confirm_kdm_email, s);
}
- void set_sound_output (std::string o)
+ void set_preview_sound (bool s) {
+ maybe_set (_preview_sound, s, PREVIEW_SOUND);
+ }
+
+ void set_preview_sound_output (std::string o)
{
- maybe_set (_sound_output, o, SOUND_OUTPUT);
+ maybe_set (_preview_sound_output, o, PREVIEW_SOUND_OUTPUT);
}
- void unset_sound_output ()
+ void unset_preview_sound_output ()
{
- if (!_sound_output) {
+ if (!_preview_sound_output) {
return;
}
- _sound_output = boost::none;
+ _preview_sound_output = boost::none;
changed ();
}
dcp::NameFormat _dcp_metadata_filename_format;
dcp::NameFormat _dcp_asset_filename_format;
bool _jump_to_selected;
- /** name of a specific sound output stream to use for preview */
- boost::optional<std::string> _sound_output;
+ bool _preview_sound;
+ /** name of a specific sound output stream to use for preview, or empty to use the default */
+ boost::optional<std::string> _preview_sound_output;
/** Singleton instance, or 0 */
static Config* _instance;
table->Add (_cinemas_file, wxGBPosition (r, 1));
++r;
- add_label_to_sizer (table, _panel, _("Sound output"), true, wxGBPosition (r, 0));
- _sound_output = new wxChoice (_panel, wxID_ANY);
- table->Add (_sound_output, wxGBPosition (r, 1));
+ _preview_sound = new wxCheckBox (_panel, wxID_ANY, _("Play sound in the preview via"));
+ table->Add (_preview_sound, wxGBPosition (r, 0));
+ _preview_sound_output = new wxChoice (_panel, wxID_ANY);
+ table->Add (_preview_sound_output, wxGBPosition (r, 1));
++r;
#ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
for (unsigned int i = 0; i < audio.getDeviceCount(); ++i) {
RtAudio::DeviceInfo dev = audio.getDeviceInfo (i);
if (dev.probed && dev.outputChannels > 0) {
- _sound_output->Append (std_to_wx (dev.name));
+ _preview_sound_output->Append (std_to_wx (dev.name));
}
}
- _set_language->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::set_language_changed, this));
- _language->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::language_changed, this));
- _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
- _sound_output->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::sound_output_changed, this));
+ _set_language->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::set_language_changed, this));
+ _language->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::language_changed, this));
+ _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
+ _preview_sound->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::preview_sound_changed, this));
+ _preview_sound_output->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::preview_sound_output_changed, this));
_num_local_encoding_threads->SetRange (1, 128);
_num_local_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
checked_set (_issuer, config->dcp_issuer ());
checked_set (_creator, config->dcp_creator ());
checked_set (_cinemas_file, config->cinemas_file());
+ checked_set (_preview_sound, config->preview_sound());
- optional<string> const current_so = get_sound_output ();
+ optional<string> const current_so = get_preview_sound_output ();
string configured_so;
- if (config->sound_output()) {
- configured_so = config->sound_output().get();
+ if (config->preview_sound_output()) {
+ configured_so = config->preview_sound_output().get();
} else {
/* No configured output means we should use the default */
RtAudio audio (DCPOMATIC_RTAUDIO_API);
}
if (!current_so || *current_so != configured_so) {
- /* Update _sound_output with the configured value */
+ /* Update _preview_sound_output with the configured value */
unsigned int i = 0;
- while (i < _sound_output->GetCount()) {
- if (_sound_output->GetString(i) == std_to_wx(configured_so)) {
- _sound_output->SetSelection (i);
+ while (i < _preview_sound_output->GetCount()) {
+ if (_preview_sound_output->GetString(i) == std_to_wx(configured_so)) {
+ _preview_sound_output->SetSelection (i);
break;
}
++i;
setup_sensitivity ();
}
- /** @return Currently-selected sound output in the dialogue */
- optional<string> get_sound_output ()
+ /** @return Currently-selected preview sound output in the dialogue */
+ optional<string> get_preview_sound_output ()
{
- int const sel = _sound_output->GetSelection ();
+ int const sel = _preview_sound_output->GetSelection ();
if (sel == wxNOT_FOUND) {
return optional<string> ();
}
- return wx_to_std (_sound_output->GetString (sel));
+ return wx_to_std (_preview_sound_output->GetString (sel));
}
void setup_sensitivity ()
{
_language->Enable (_set_language->GetValue ());
_check_for_test_updates->Enable (_check_for_updates->GetValue ());
+ _preview_sound_output->Enable (_preview_sound->GetValue ());
}
void set_language_changed ()
Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
}
- void sound_output_changed ()
+ void preview_sound_changed ()
+ {
+ Config::instance()->set_preview_sound (_preview_sound->GetValue ());
+ }
+
+ void preview_sound_output_changed ()
{
RtAudio audio (DCPOMATIC_RTAUDIO_API);
- optional<string> const so = get_sound_output();
+ optional<string> const so = get_preview_sound_output();
if (!so || *so == audio.getDeviceInfo(audio.getDefaultOutputDevice()).name) {
- Config::instance()->unset_sound_output ();
+ Config::instance()->unset_preview_sound_output ();
} else {
- Config::instance()->set_sound_output (*so);
+ Config::instance()->set_preview_sound_output (*so);
}
}
wxChoice* _language;
wxSpinCtrl* _num_local_encoding_threads;
FilePickerCtrl* _cinemas_file;
- wxChoice* _sound_output;
+ wxCheckBox* _preview_sound;
+ wxChoice* _preview_sound_output;
#ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
wxCheckBox* _analyse_ebur128;
#endif
setup_sensitivity ();
_config_changed_connection = Config::instance()->Changed.connect (bind (&FilmViewer::config_changed, this, _1));
- config_changed (Config::SOUND_OUTPUT);
+ config_changed (Config::PREVIEW_SOUND_OUTPUT);
}
FilmViewer::~FilmViewer ()
}
_butler.reset (new Butler (_film, _player, map, _audio_channels));
+ if (!Config::instance()->preview_sound()) {
+ _butler->disable_audio ();
+ }
if (was_running) {
start ();
void
FilmViewer::timer ()
{
- if (!_film) {
+ if (!_film || !_playing) {
return;
}
- if (_audio.isStreamRunning ()) {
- get ();
- update_position_label ();
- update_position_slider ();
- DCPTime const next = _video_position + DCPTime::from_frames (1, _film->video_frame_rate ());
-
- if (next >= _film->length()) {
- stop ();
- }
+ get ();
+ update_position_label ();
+ update_position_slider ();
+ DCPTime const next = _video_position + DCPTime::from_frames (1, _film->video_frame_rate ());
- _timer.Start (max ((next.seconds() - time().seconds()) * 1000, 0.0), wxTIMER_ONE_SHOT);
+ if (next >= _film->length()) {
+ stop ();
}
+ _timer.Start (max ((next.seconds() - time().seconds()) * 1000, 0.0), wxTIMER_ONE_SHOT);
+
if (_butler) {
_butler->rethrow ();
}
void
FilmViewer::config_changed (Config::Property p)
{
- if (p != Config::SOUND_OUTPUT) {
+ if (p != Config::PREVIEW_SOUND && p != Config::PREVIEW_SOUND_OUTPUT) {
return;
}
_audio.closeStream ();
}
- unsigned int st = 0;
- if (Config::instance()->sound_output()) {
- while (st < _audio.getDeviceCount()) {
- if (_audio.getDeviceInfo(st).name == Config::instance()->sound_output().get()) {
- break;
+ if (Config::instance()->preview_sound()) {
+ unsigned int st = 0;
+ if (Config::instance()->preview_sound_output()) {
+ while (st < _audio.getDeviceCount()) {
+ if (_audio.getDeviceInfo(st).name == Config::instance()->preview_sound_output().get()) {
+ break;
+ }
+ ++st;
}
- ++st;
- }
- if (st == _audio.getDeviceCount()) {
+ if (st == _audio.getDeviceCount()) {
+ st = _audio.getDefaultOutputDevice();
+ }
+ } else {
st = _audio.getDefaultOutputDevice();
}
- } else {
- st = _audio.getDefaultOutputDevice();
- }
- _audio_channels = _audio.getDeviceInfo(st).outputChannels;
- recreate_butler ();
+ _audio_channels = _audio.getDeviceInfo(st).outputChannels;
- RtAudio::StreamParameters sp;
- sp.deviceId = st;
- sp.nChannels = _audio_channels;
- sp.firstChannel = 0;
- try {
- _audio.openStream (&sp, 0, RTAUDIO_FLOAT32, 48000, &_audio_block_size, &rtaudio_callback, this);
+ recreate_butler ();
+
+ RtAudio::StreamParameters sp;
+ sp.deviceId = st;
+ sp.nChannels = _audio_channels;
+ sp.firstChannel = 0;
+ try {
+ _audio.openStream (&sp, 0, RTAUDIO_FLOAT32, 48000, &_audio_block_size, &rtaudio_callback, this);
#ifdef DCPOMATIC_USE_RTERROR
- } catch (RtError& e) {
+ } catch (RtError& e) {
#else
- } catch (RtAudioError& e) {
+ } catch (RtAudioError& e) {
#endif
- error_dialog (this, wxString::Format (_("Could not set up audio output (%s). There will be no audio during the preview."), e.what()));
+ error_dialog (
+ this,
+ wxString::Format (_("Could not set up audio output (%s). There will be no audio during the preview."), e.what())
+ );
+ }
+
+ } else {
+ _audio_channels = 0;
+ recreate_butler ();
}
}