Config option to disable preview audio.
authorCarl Hetherington <cth@carlh.net>
Wed, 19 Apr 2017 09:56:44 +0000 (10:56 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 19 Apr 2017 22:04:32 +0000 (23:04 +0100)
src/lib/butler.cc
src/lib/butler.h
src/lib/config.cc
src/lib/config.h
src/wx/config_dialog.cc
src/wx/film_viewer.cc

index aadfc4f..32d607c 100644 (file)
@@ -44,6 +44,7 @@ Butler::Butler (weak_ptr<const Film> film, shared_ptr<Player> player, AudioMappi
        , _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));
@@ -158,8 +159,8 @@ Butler::audio (shared_ptr<AudioBuffers> audio, DCPTime time)
 {
        {
                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;
                }
        }
@@ -191,3 +192,10 @@ Butler::get_audio (float* out, Frame frames)
        _audio.get (out, _audio_channels, frames);
        _summon.notify_all ();
 }
+
+void
+Butler::disable_audio ()
+{
+       boost::mutex::scoped_lock lm (_mutex);
+       _disable_audio = true;
+}
index 943aa9e..948a78e 100644 (file)
@@ -42,6 +42,8 @@ public:
        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);
@@ -68,6 +70,7 @@ private:
        int _audio_channels;
 
        bool _stop_thread;
+       bool _disable_audio;
 
        boost::signals2::scoped_connection _player_video_connection;
        boost::signals2::scoped_connection _player_audio_connection;
index b099cbc..01a6752 100644 (file)
@@ -116,7 +116,8 @@ Config::set_defaults ()
        _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);
@@ -310,7 +311,8 @@ try
        _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)) {
@@ -479,8 +481,9 @@ Config::write_config () const
        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 {
index 2fd3605..a574cc2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    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.
 
@@ -67,7 +67,8 @@ public:
                USE_ANY_SERVERS,
                SERVERS,
                CINEMAS,
-               SOUND_OUTPUT,
+               PREVIEW_SOUND,
+               PREVIEW_SOUND_OUTPUT,
                OTHER
        };
 
@@ -307,8 +308,12 @@ public:
                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 */
@@ -526,18 +531,22 @@ public:
                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 ();
        }
 
@@ -699,8 +708,9 @@ private:
        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;
index 3410948..613d8f6 100644 (file)
@@ -204,9 +204,10 @@ private:
                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
@@ -245,14 +246,15 @@ private:
                 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));
@@ -308,12 +310,13 @@ private:
                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);
@@ -321,11 +324,11 @@ private:
                 }
 
                 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;
@@ -335,21 +338,22 @@ private:
                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 ()
@@ -414,14 +418,19 @@ private:
                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);
                 }
         }
 
@@ -429,7 +438,8 @@ private:
        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
index 40efdce..37f9996 100644 (file)
@@ -157,7 +157,7 @@ FilmViewer::FilmViewer (wxWindow* p)
        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 ()
@@ -239,6 +239,9 @@ FilmViewer::recreate_butler ()
        }
 
        _butler.reset (new Butler (_film, _player, map, _audio_channels));
+       if (!Config::instance()->preview_sound()) {
+               _butler->disable_audio ();
+       }
 
        if (was_running) {
                start ();
@@ -305,23 +308,21 @@ FilmViewer::get ()
 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 ();
        }
@@ -680,7 +681,7 @@ FilmViewer::seek (DCPTime t, bool accurate)
 void
 FilmViewer::config_changed (Config::Property p)
 {
-       if (p != Config::SOUND_OUTPUT) {
+       if (p != Config::PREVIEW_SOUND && p != Config::PREVIEW_SOUND_OUTPUT) {
                return;
        }
 
@@ -688,36 +689,46 @@ FilmViewer::config_changed (Config::Property p)
                _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 ();
        }
 }