ensure that all waveviews have ALL their colors set accurately before first render
[ardour.git] / gtk2_ardour / ardour_ui.cc
index 10de8e795d8953068b9cbfbc8e1863365e99544f..d9ac37e36f5c94b038def8a136da7cfaa70746d4 100644 (file)
@@ -50,9 +50,9 @@
 #include "pbd/enumwriter.h"
 #include "pbd/memento_command.h"
 #include "pbd/openuri.h"
+#include "pbd/stl_delete.h"
 #include "pbd/file_utils.h"
 #include "pbd/localtime_r.h"
-#include "pbd/system_exec.h"
 
 #include "gtkmm2ext/application.h"
 #include "gtkmm2ext/bindings.h"
@@ -81,6 +81,7 @@
 #include "ardour/session_state_utils.h"
 #include "ardour/session_utils.h"
 #include "ardour/slave.h"
+#include "ardour/system_exec.h"
 
 #ifdef WINDOWS_VST_SUPPORT
 #include <fst.h>
@@ -306,7 +307,10 @@ 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), gui_context());
+       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());
 
        /* lets get this party started */
 
@@ -485,7 +489,7 @@ ARDOUR_UI::post_engine ()
 
        _tooltips.enable();
 
-       ActionManager::load_menus ();
+       ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
 
        if (setup_windows ()) {
                throw failed_constructor ();
@@ -558,11 +562,6 @@ ARDOUR_UI::~ARDOUR_UI ()
                ui_config->save_state();
        }
 
-       delete keyboard;
-       delete editor;
-       delete mixer;
-       delete meterbridge;
-
        stop_video_server();
 }
 
@@ -757,6 +756,7 @@ ARDOUR_UI::starting ()
        try {
                audio_midi_setup.get (true);
        } catch (...) {
+               std::cerr << "audio-midi engine setup failed."<< std::endl;
                return -1;
        }
 
@@ -843,6 +843,7 @@ ARDOUR_UI::starting ()
                const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
 
                if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
+                       std::cerr << "Cannot get session parameters."<< std::endl;
                        return -1;
                }
        }
@@ -1004,8 +1005,6 @@ If you still wish to quit, please use the\n\n\
 
        close_all_dialogs ();
 
-       loading_message (string_compose (_("Please wait while %1 cleans up..."), PROGRAM_NAME));
-
        if (_session) {
                // _session->set_deletion_in_progress ();
                _session->set_clean ();
@@ -1417,7 +1416,7 @@ ARDOUR_UI::redisplay_recent_sessions ()
 
                get_state_files_in_directory (*i, state_file_paths);
 
-               vector<string*>* states;
+               vector<string> states;
                vector<const gchar*> item;
                string fullpath = *i;
 
@@ -1434,8 +1433,9 @@ ARDOUR_UI::redisplay_recent_sessions ()
                }
 
                /* now get available states for this session */
+               states = Session::possible_states (fullpath);
 
-               if ((states = Session::possible_states (fullpath)) == 0) {
+               if (states.empty()) {
                        /* no state file? */
                        continue;
                }
@@ -1444,14 +1444,14 @@ ARDOUR_UI::redisplay_recent_sessions ()
 
                Gtk::TreeModel::Row row = *(recent_session_model->append());
 
-               row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
                row[recent_session_columns.fullpath] = fullpath;
                row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
 
                if (state_file_names.size() > 1) {
+                       // multiple session files in the session directory - show the directory name.
+                       row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
 
                        // add the children
-
                        for (std::vector<std::string>::iterator i2 = state_file_names.begin();
                                        i2 != state_file_names.end(); ++i2)
                        {
@@ -1462,6 +1462,9 @@ ARDOUR_UI::redisplay_recent_sessions ()
                                child_row[recent_session_columns.fullpath] = fullpath;
                                child_row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
                        }
+               } else {
+                       // only a single session file in the directory - show its actual name.
+                       row[recent_session_columns.visible_name] = state_file_names.front ();
                }
        }
 
@@ -1660,10 +1663,10 @@ ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& out
 
        catch (...) {
                MessageDialog msg (*editor,
-                                  string_compose (_("There are insufficient JACK ports available\n\
+                                  string_compose (_("There are insufficient ports available\n\
 to create a new track or bus.\n\
 You should save %1, exit and\n\
-restart JACK with more ports."), PROGRAM_NAME));
+restart with more ports."), PROGRAM_NAME));
                msg.run ();
        }
 }
@@ -1721,10 +1724,10 @@ ARDOUR_UI::session_add_audio_route (
 
        catch (...) {
                MessageDialog msg (*editor,
-                                  string_compose (_("There are insufficient JACK ports available\n\
+                                  string_compose (_("There are insufficient ports available\n\
 to create a new track or bus.\n\
 You should save %1, exit and\n\
-restart JACK with more ports."), PROGRAM_NAME));
+restart with more ports."), PROGRAM_NAME));
                pop_back_splash (msg);
                msg.run ();
        }
@@ -1886,12 +1889,25 @@ ARDOUR_UI::transport_roll ()
        bool rolling = _session->transport_rolling();
 
        if (_session->get_play_loop()) {
-               /* XXX it is not possible to just leave seamless loop and keep
-                  playing at present (nov 4th 2009)
+
+               /* If loop playback is not a mode, then we should cancel
+                  it when this action is requested. If it is a mode
+                  we just leave it in place.
                */
-               if (!Config->get_seamless_loop()) {
-                       _session->request_play_loop (false, true);
-               }
+
+               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);
+                       }
+               } 
+
        } else if (_session->get_play_range () && !Config->get_always_play_range()) {
                /* stop playing a range if we currently are */
                _session->request_play_range (0, true);
@@ -1948,7 +1964,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
                                /* disk buffers are normal, so we can keep playing */
                                affect_transport = false;
                        }
-                       _session->request_play_loop (false, true);
+                       _session->request_play_loop (false, affect_transport);
                } else if (_session->get_play_range ()) {
                        affect_transport = false;
                        _session->request_play_range (0, true);
@@ -1979,16 +1995,23 @@ ARDOUR_UI::toggle_session_auto_loop ()
 
        if (_session->get_play_loop()) {
 
-               if (_session->transport_rolling()) {
+               /* looping enabled, our job is to disable it */
+
+               _session->request_play_loop (false);
 
-                       _session->request_locate (looploc->start(), true);
-                       _session->request_play_loop (false);
+       } else {
+
+               /* looping not enabled, our job is to enable it.
 
+                  loop-is-NOT-mode: this action always starts the transport rolling.
+                  loop-IS-mode:     this action simply sets the loop play mechanism, but
+                                       does not start transport.
+               */
+               if (Config->get_loop_is_mode()) {
+                       _session->request_play_loop (true, false);
                } else {
-                       _session->request_play_loop (false);
+                       _session->request_play_loop (true, true);
                }
-       } else {
-               _session->request_play_loop (true);
        }
        
        //show the loop markers
@@ -2116,7 +2139,11 @@ ARDOUR_UI::map_transport_state ()
 
                        auto_loop_button.set_active (true);
                        play_selection_button.set_active (false);
-                       roll_button.set_active (false);
+                       if (Config->get_loop_is_mode()) {
+                               roll_button.set_active (true);
+                       } else {
+                               roll_button.set_active (false);
+                       }
 
                } else {
 
@@ -2138,7 +2165,11 @@ ARDOUR_UI::map_transport_state ()
                stop_button.set_active (true);
                roll_button.set_active (false);
                play_selection_button.set_active (false);
-               auto_loop_button.set_active (false);
+               if (Config->get_loop_is_mode ()) {
+                       auto_loop_button.set_active (_session->get_play_loop());
+               } else {
+                       auto_loop_button.set_active (false);
+               }
                update_disk_space ();
        }
 }
@@ -2930,7 +2961,9 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
 #ifdef WINDOWS_VST_SUPPORT
        fst_stop_threading();
 #endif
+
        flush_pending ();
+
 #ifdef WINDOWS_VST_SUPPORT
        fst_start_threading();
 #endif
@@ -3358,8 +3391,6 @@ ARDOUR_UI::add_route (Gtk::Window* float_window)
 
        setup_order_hint();
 
-       PBD::ScopedConnection idle_connection;
-
        string template_path = add_route_dialog->track_template();
 
        if (!template_path.empty()) {
@@ -3401,8 +3432,6 @@ ARDOUR_UI::add_route (Gtk::Window* float_window)
                session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template);
                break;
        }
-
-       /* idle connection will end at scope end */
 }
 
 void
@@ -3521,7 +3550,7 @@ ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
                        delete video_server_process;
                }
 
-               video_server_process = new SystemExec(icsd_exec, argp);
+               video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
                if (video_server_process->start()) {
                        warning << _("Cannot launch the video-server") << endmsg;
                        continue;
@@ -3529,6 +3558,7 @@ ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
                int timeout = 120; // 6 sec
                while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
                        Glib::usleep (50000);
+                       gui_idle_handler();
                        if (--timeout <= 0 || !video_server_process->is_running()) break;
                }
                if (timeout <= 0) {
@@ -3794,39 +3824,114 @@ quickly enough to keep up with recording.\n"), PROGRAM_NAME));
        }
 }
 
+
+/* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
+static MessageDialog *scan_dlg = NULL;
+static ProgressBar   *scan_pbar = NULL;
+static HBox          *scan_tbox = NULL;
+
 void
 ARDOUR_UI::cancel_plugin_scan ()
 {
        PluginManager::instance().cancel_plugin_scan();
 }
 
-static MessageDialog *scan_dlg = NULL;
+void
+ARDOUR_UI::cancel_plugin_timeout ()
+{
+       PluginManager::instance().cancel_plugin_timeout();
+       scan_tbox->hide();
+}
+
+void
+ARDOUR_UI::plugin_scan_timeout (int timeout)
+{
+       if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
+               return;
+       }
+       if (timeout > 0) {
+               scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
+               scan_tbox->show();
+       } else {
+               scan_tbox->hide();
+       }
+       gui_idle_handler();
+}
 
 void
-ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin)
+ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
 {
-       if (!Config->get_show_plugin_scan_window()) { return; }
+       if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
+               return;
+       }
+
+       const bool cancelled = PluginManager::instance().cancelled();
+       if (type != X_("closeme") && !Config->get_show_plugin_scan_window()) {
+               if (cancelled && scan_dlg->is_mapped()) {
+                       scan_dlg->hide();
+                       gui_idle_handler();
+                       return;
+               }
+               if (cancelled || !can_cancel) {
+                       return;
+               }
+       }
+
+       static Gtk::Button *cancel_button;
+       static Gtk::Button *timeout_button;
        if (!scan_dlg) {
-               scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE);
+               scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
                VBox* vbox = scan_dlg->get_vbox();
                vbox->set_size_request(400,-1);
                scan_dlg->set_title (_("Scanning for plugins"));
 
-               Gtk::Button *cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
+               cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
                cancel_button->set_name ("EditorGTKButton");
                cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
+               cancel_button->show();
 
                scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
+
+               scan_tbox = manage( new HBox() );
+
+               timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
+               timeout_button->set_name ("EditorGTKButton");
+               timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
+               timeout_button->show();
+
+               scan_pbar = manage(new ProgressBar());
+               scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
+               scan_pbar->set_text(_("Scan Timeout"));
+               scan_pbar->show();
+
+               scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
+               scan_tbox->pack_start (*timeout_button, PACK_SHRINK, 4);
+
+               scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
        }
 
        if (type == X_("closeme")) {
                scan_dlg->hide();
        } else {
                scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
-               scan_dlg->show_all();
+               scan_dlg->show();
+       }
+       if (!can_cancel || !cancelled) {
+               scan_tbox->hide();
        }
+       cancel_button->set_sensitive(can_cancel && !cancelled);
 
-       gtk_main_iteration ();
+       gui_idle_handler();
+}
+
+void
+ARDOUR_UI::gui_idle_handler ()
+{
+       int timeout = 30;
+       /* due to idle calls, gtk_events_pending() may always return true */
+       while (gtk_events_pending() && --timeout) {
+               gtk_main_iteration ();
+       }
 }
 
 void
@@ -4161,10 +4266,14 @@ ARDOUR_UI::setup_profile ()
                Profile->set_small_screen ();
        }
 
-       if (getenv ("ARDOUR_SAE")) {
+       if (g_getenv ("ARDOUR_SAE")) {
                Profile->set_sae ();
                Profile->set_single_package ();
        }
+
+       if (g_getenv ("TRX")) {
+               Profile->set_trx ();
+       }
 }
 
 int