Add additional roll check in transport_record
[ardour.git] / gtk2_ardour / ardour_ui.cc
index 8cc3cbe3669412668d27b989dd1d42edd42631f4..b5ff6eed86b277df1557cdef2d00ea17db09105b 100644 (file)
@@ -151,6 +151,7 @@ typedef uint64_t microseconds_t;
 #include "actions.h"
 #include "add_route_dialog.h"
 #include "ambiguous_file_dialog.h"
+#include "ardour_message.h"
 #include "ardour_ui.h"
 #include "audio_clock.h"
 #include "audio_region_view.h"
@@ -197,7 +198,6 @@ typedef uint64_t microseconds_t;
 #include "session_option_editor.h"
 #include "speaker_dialog.h"
 #include "splash.h"
-#include "startup.h"
 #include "template_dialog.h"
 #include "time_axis_view_item.h"
 #include "time_info_box.h"
@@ -206,6 +206,7 @@ typedef uint64_t microseconds_t;
 #include "utils.h"
 #include "utils_videotl.h"
 #include "video_server_dialog.h"
+#include "virtual_keyboard_window.h"
 #include "add_video_dialog.h"
 #include "transcode_video_dialog.h"
 
@@ -228,14 +229,15 @@ sigc::signal<void> ARDOUR_UI::CloseAllDialogs;
 static bool
 ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
 {
-       MessageDialog msg (string_compose (_("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
-                                            "Would you like these files to be copied and used for %1 %2.x?\n\n"
-                                            "(This will require you to restart %1.)"),
-                                          PROGRAM_NAME, PROGRAM_VERSION, version),
-                          false, /* no markup */
-                          Gtk::MESSAGE_INFO,
-                          Gtk::BUTTONS_YES_NO,
-                          true /* modal, though it hardly matters since it is the only window */
+       ArdourMessageDialog msg (string_compose (
+                                 _("%1 %2.x has discovered configuration files from %1 %3.x.\n\n"
+                                   "Would you like these files to be copied and used for %1 %2.x?\n\n"
+                                   "(This will require you to restart %1.)"),
+                                    PROGRAM_NAME, PROGRAM_VERSION, version),
+                                false, /* no markup */
+                                Gtk::MESSAGE_INFO,
+                                Gtk::BUTTONS_YES_NO,
+                                true /* modal, though it hardly matters since it is the only window */
        );
 
        msg.set_default_response (Gtk::RESPONSE_YES);
@@ -300,8 +302,8 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , nsm (0)
        , _was_dirty (false)
        , _mixer_on_top (false)
-       , _initial_verbose_plugin_scan (false)
        , _shared_popup_menu (0)
+       , startup_fsm (0)
        , secondary_clock_spacer (0)
        , auto_input_button (ArdourButton::led_default_elements)
        , latency_disable_button (ArdourButton::led_default_elements)
@@ -337,11 +339,11 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
        , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
        , big_transport_window (X_("big-transport"), _("Transport Controls"), boost::bind (&ARDOUR_UI::create_big_transport_window, this))
+       , virtual_keyboard_window (X_("virtual-keyboard"), _("Virtual Keyboard"), boost::bind (&ARDOUR_UI::create_virtual_keyboard_window, this))
        , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
        , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
        , key_editor (X_("key-editor"), _("Keyboard Shortcuts"), boost::bind (&ARDOUR_UI::create_key_editor, this))
        , video_server_process (0)
-       , splash (0)
        , have_configure_timeout (false)
        , last_configure_time (0)
        , last_peak_grab (0)
@@ -363,20 +365,13 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
                        /* "touch" the been-here-before path now that config has been migrated */
                        PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
                }
-               MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
+               ArdourMessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
                msg.run ();
                /* configuration was modified, exit immediately */
                _exit (EXIT_SUCCESS);
        }
 
 
-       if (string (VERSIONSTRING).find (".pre") != string::npos) {
-               /* check this is not being run from ./ardev etc. */
-               if (!running_from_source_tree ()) {
-                       pre_release_dialog ();
-               }
-       }
-
        if (theArdourUI == 0) {
                theArdourUI = this;
        }
@@ -435,10 +430,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
 
        ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this));
 
-       /* handle Audio/MIDI setup when session requires it */
-
-       ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1));
-
        /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
 
        ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
@@ -466,10 +457,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
 
        ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
 
-       /* also plugin scan messages */
-       ARDOUR::PluginScanMessage.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_dialog, this, _1, _2, _3), gui_context());
-       ARDOUR::PluginScanTimeout.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_timeout, this, _1), gui_context());
-
        ARDOUR::GUIIdle.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::gui_idle_handler, this), gui_context());
 
        Config->ParameterChanged.connect ( forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::set_flat_buttons, this), gui_context() );
@@ -506,6 +493,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
                location_ui.set_state (*ui_xml, 0);
                big_clock_window.set_state (*ui_xml, 0);
                big_transport_window.set_state (*ui_xml, 0);
+               virtual_keyboard_window.set_state (*ui_xml, 0);
                audio_port_matrix.set_state (*ui_xml, 0);
                midi_port_matrix.set_state (*ui_xml, 0);
                export_video_dialog.set_state (*ui_xml, 0);
@@ -531,6 +519,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
        WM::Manager::instance().register_window (&location_ui);
        WM::Manager::instance().register_window (&big_clock_window);
        WM::Manager::instance().register_window (&big_transport_window);
+       WM::Manager::instance().register_window (&virtual_keyboard_window);
        WM::Manager::instance().register_window (&audio_port_matrix);
        WM::Manager::instance().register_window (&midi_port_matrix);
        WM::Manager::instance().register_window (&idleometer);
@@ -546,42 +535,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
 
        _process_thread = new ProcessThread ();
 
-       attach_to_engine ();
-}
-
-void
-ARDOUR_UI::pre_release_dialog ()
-{
-       ArdourDialog d (_("Pre-Release Warning"), true, false);
-       d.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
-
-       Label* label = manage (new Label);
-       label->set_markup (string_compose (_("<b>Welcome to this pre-release build of %1 %2</b>\n\n\
-There are still several issues and bugs to be worked on,\n\
-as well as general workflow improvements, before this can be considered\n\
-release software. So, a few guidelines:\n\
-\n\
-1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
-   though it may be so, depending on your workflow.\n\
-2) Please wait for a helpful writeup of new features.\n\
-3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
-4) <b>Please do NOT file bugs for this alpha-development versions at this point in time</b>.\n\
-   There is no bug triaging before the initial development concludes and\n\
-   reporting issue for incomplete, ongoing work-in-progress is mostly useless.\n\
-5) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
-   can get there directly from within the program via the Help->Chat menu option.\n\
-6) Please <b>DO</b> submit patches for issues after discussing them on IRC.\n\
-\n\
-Full information on all the above can be found on the support page at\n\
-\n\
-                http://ardour.org/support\n\
-"), PROGRAM_NAME, VERSIONSTRING));
-
-       d.get_vbox()->set_border_width (12);
-       d.get_vbox()->pack_start (*label, false, false, 12);
-       d.get_vbox()->show_all ();
-
-       d.run ();
+       ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
 }
 
 GlobalPortMatrixWindow*
@@ -597,7 +551,7 @@ void
 ARDOUR_UI::attach_to_engine ()
 {
        AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this, _1), gui_context());
-       ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
+       engine_running (0);
 }
 
 void
@@ -663,8 +617,7 @@ was not fast enough. Try to restart\n\
 the audio backend and save the session."), PROGRAM_NAME);
        }
 
-       MessageDialog msg (_main_window, msgstr);
-       pop_back_splash (msg);
+       ArdourMessageDialog msg (_main_window, msgstr);
        msg.run ();
 
        if (free_reason) {
@@ -904,14 +857,6 @@ ARDOUR_UI::~ARDOUR_UI ()
 #endif
 }
 
-void
-ARDOUR_UI::pop_back_splash (Gtk::Window& win)
-{
-       if (Splash::instance()) {
-               Splash::instance()->pop_back_for (win);
-       }
-}
-
 gint
 ARDOUR_UI::configure_timeout ()
 {
@@ -1050,12 +995,11 @@ ARDOUR_UI::finish()
                                /* use the default name */
                                if (save_state_canfail ("")) {
                                        /* failed - don't quit */
-                                       MessageDialog msg (_main_window,
+                                       ArdourMessageDialog msg (_main_window,
                                                           string_compose (_("\
 %1 was unable to save your session.\n\n\
 If you still wish to quit, please use the\n\n\
 \"Just quit\" option."), PROGRAM_NAME));
-                                       pop_back_splash(msg);
                                        msg.run ();
                                        return;
                                }
@@ -1377,13 +1321,13 @@ ARDOUR_UI::update_disk_space()
        if (!opt_samples) {
                /* Available space is unknown */
                format_disk_space_label (-1);
-       } else if (opt_samples.get_value_or (0) == max_samplecnt) {
+       } else if (opt_samples.value_or (0) == max_samplecnt) {
                format_disk_space_label (max_samplecnt);
        } else {
                rec_enabled_streams = 0;
                _session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams, false);
 
-               samplecnt_t samples = opt_samples.get_value_or (0);
+               samplecnt_t samples = opt_samples.value_or (0);
 
                if (rec_enabled_streams) {
                        samples /= rec_enabled_streams;
@@ -1603,12 +1547,11 @@ ARDOUR_UI::session_add_foldback_bus (int32_t channels, uint32_t how_many, string
 void
 ARDOUR_UI::display_insufficient_ports_message ()
 {
-       MessageDialog msg (_main_window,
+       ArdourMessageDialog msg (_main_window,
                        string_compose (_("There are insufficient ports available\n\
 to create a new track or bus.\n\
 You should save %1, exit and\n\
 restart with more ports."), PROGRAM_NAME));
-       pop_back_splash (msg);
        msg.run ();
 }
 
@@ -1748,7 +1691,7 @@ ARDOUR_UI::transport_record (bool roll)
                switch (_session->record_status()) {
                case Session::Disabled:
                        if (_session->ntracks() == 0) {
-                               MessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu."));
+                               ArdourMessageDialog msg (_main_window, _("Please create one or more tracks before trying to record.\nYou can do this with the \"Add Track or Bus\" option in the Session menu."));
                                msg.run ();
                                return;
                        }
@@ -1766,7 +1709,11 @@ ARDOUR_UI::transport_record (bool roll)
                        break;
 
                case Session::Enabled:
-                       _session->disable_record (false, true);
+                       if (roll) {
+                               transport_roll();
+                       } else {
+                               _session->disable_record (false, true);
+                       }
                }
        }
 }
@@ -1802,16 +1749,8 @@ ARDOUR_UI::transport_roll ()
                */
 
                if (!Config->get_loop_is_mode()) {
-                       /* XXX it is not possible to just leave seamless loop and keep
-                          playing at present (nov 4th 2009)
-                       */
-                       if (!Config->get_seamless_loop()) {
-                               /* stop loop playback and stop rolling */
-                               _session->request_play_loop (false, true);
-                       } else if (rolling) {
-                               /* stop loop playback but keep rolling */
-                               _session->request_play_loop (false, false);
-                       }
+                       /* stop loop playback but keep transport state */
+                       _session->request_play_loop (false, false);
                }
 
        } else if (_session->get_play_range () ) {
@@ -1854,54 +1793,49 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
        }
 
        bool rolling = _session->transport_rolling();
-       bool affect_transport = true;
 
-       if (rolling && roll_out_of_bounded_mode) {
-               /* drop out of loop/range playback but leave transport rolling */
-               if (_session->get_play_loop()) {
-                       if (_session->actively_recording()) {
+       if (rolling) {
 
-                               /* just stop using the loop, then actually stop
-                                * below
-                                */
-                               _session->request_play_loop (false, affect_transport);
+               if (roll_out_of_bounded_mode) {
+                       /* drop out of loop/range playback but leave transport rolling */
 
-                       } else {
-                               if (Config->get_seamless_loop()) {
-                                       /* the disk buffers contain copies of the loop - we can't
-                                          just keep playing, so stop the transport. the user
-                                          can restart as they wish.
+                       if (_session->get_play_loop()) {
+
+                               if (_session->actively_recording()) {
+                                       /* actually stop transport because
+                                          otherwise the captured data will make
+                                          no sense.
                                        */
-                                       affect_transport = true;
+                                       _session->request_play_loop (false, true);
+
                                } else {
-                                       /* disk buffers are normal, so we can keep playing */
-                                       affect_transport = false;
+                                       _session->request_play_loop (false, false);
                                }
-                               _session->request_play_loop (false, affect_transport);
+
+                       } else if (_session->get_play_range ()) {
+
+                               _session->request_cancel_play_range ();
                        }
-               } else if (_session->get_play_range ()) {
-                       affect_transport = false;
-                       _session->request_play_range (0, true);
-               }
-       }
 
-       if (affect_transport) {
-               if (rolling) {
+               } else {
                        _session->request_stop (with_abort, true);
+               }
 
-               } else if (!with_abort) { /* with_abort == true means the
-                                          * command was intended to stop
-                                          * transport, not start.
-                                          */
+       } else { /* not rolling */
 
-                       /* the only external sync condition we can be in here
-                        * would be Engine (JACK) sync, in which case we still
-                        * want to do this.
-                        */
+               if (with_abort) { /* with_abort == true means the command was intended to stop transport, not start. */
+                       return;
+               }
 
-                       if (UIConfiguration::instance().get_follow_edits() && ( editor->get_selection().time.front().start == _session->transport_sample() ) ) {  //if playhead is exactly at the start of a range, we can assume it was placed there by follow_edits
-                               _session->request_play_range (&editor->get_selection().time, true);
-                               _session->set_requested_return_sample( editor->get_selection().time.front().start );  //force an auto-return here
+               if (_session->get_play_loop() && Config->get_loop_is_mode()) {
+                       _session->request_locate (_session->locations()->auto_loop_location()->start(), true);
+               } else {
+                       if (UIConfiguration::instance().get_follow_edits()) {
+                               list<AudioRange>& range = editor->get_selection().time;
+                               if (range.front().start == _session->transport_sample()) { // if playhead is exactly at the start of a range, we assume it was placed there by follow_edits
+                                       _session->request_play_range (&range, true);
+                                       _session->set_requested_return_sample (range.front().start);  //force an auto-return here
+                               }
                        }
                        _session->request_transport_speed (1.0f);
                }
@@ -2061,6 +1995,9 @@ ARDOUR_UI::map_transport_state ()
 {
        if (!_session) {
                layered_button.set_sensitive (false);
+               if (UIConfiguration::instance().get_screen_saver_mode () == InhibitWhileRecording) {
+                       inhibit_screensaver (false);
+               }
                return;
        }
 
@@ -2383,11 +2320,11 @@ ARDOUR_UI::display_cleanup_results (ARDOUR::CleanupReport& rep, const gchar* lis
        removed = rep.paths.size();
 
        if (removed == 0) {
-               MessageDialog msgd (_main_window,
-                                   _("No files were ready for clean-up"),
-                                   true,
-                                   Gtk::MESSAGE_INFO,
-                                   Gtk::BUTTONS_OK);
+               ArdourMessageDialog msgd (_main_window,
+                                         _("No files were ready for clean-up"),
+                                         true,
+                                         Gtk::MESSAGE_INFO,
+                                         Gtk::BUTTONS_OK);
                msgd.set_title (_("Clean-up"));
                msgd.set_secondary_text (_("If this seems surprising, \n\
 check for any existing snapshots.\n\
@@ -2526,10 +2463,10 @@ ARDOUR_UI::cleanup ()
        }
 
 
-       MessageDialog checker (_("Are you sure you want to clean-up?"),
-                               true,
-                               Gtk::MESSAGE_QUESTION,
-                               Gtk::BUTTONS_NONE);
+       ArdourMessageDialog checker (_("Are you sure you want to clean-up?"),
+                                    true,
+                                    Gtk::MESSAGE_QUESTION,
+                                    Gtk::BUTTONS_NONE);
 
        checker.set_title (_("Clean-up"));
 
@@ -2805,7 +2742,7 @@ ARDOUR_UI::disk_overrun_handler ()
 
        if (!have_disk_speed_dialog_displayed) {
                have_disk_speed_dialog_displayed = true;
-               MessageDialog* msg = new MessageDialog (_main_window, string_compose (_("\
+               ArdourMessageDialog* msg = new ArdourMessageDialog (_main_window, string_compose (_("\
 The disk system on your computer\n\
 was not able to keep up with %1.\n\
 \n\
@@ -2833,7 +2770,7 @@ ARDOUR_UI::disk_underrun_handler ()
 
        if (!have_disk_speed_dialog_displayed) {
                have_disk_speed_dialog_displayed = true;
-               MessageDialog* msg = new MessageDialog (
+               ArdourMessageDialog* msg = new ArdourMessageDialog (
                        _main_window, string_compose (_("The disk system on your computer\n\
 was not able to keep up with %1.\n\
 \n\
@@ -2855,13 +2792,8 @@ void
 ARDOUR_UI::session_dialog (std::string msg)
 {
        ENSURE_GUI_THREAD (*this, &ARDOUR_UI::session_dialog, msg)
-
-       MessageDialog* d;
-
-       d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
-       d->show_all ();
-       d->run ();
-       delete d;
+       ArdourMessageDialog d (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
+       d.run ();
 }
 
 int
@@ -2901,6 +2833,11 @@ what you would like to do.\n"), PROGRAM_NAME));
 void
 ARDOUR_UI::store_clock_modes ()
 {
+       if (session_load_in_progress) {
+               /* Do not overwrite clock modes while loading them (with a session) */
+               return;
+       }
+
        XMLNode* node = new XMLNode(X_("ClockModes"));
 
        for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {