Tweak/fix splash screen event-loop
[ardour.git] / gtk2_ardour / ardour_ui.cc
index 1cf2d3f79f13dc8dffd8e4a3c74c38606e2ae684..f48d4f527dcfe3e1f24d9cd267906d8f464fdfb0 100644 (file)
@@ -61,6 +61,7 @@
 #include "pbd/memento_command.h"
 #include "pbd/openuri.h"
 #include "pbd/stl_delete.h"
+#include "pbd/types_convert.h"
 #include "pbd/file_utils.h"
 #include "pbd/localtime_r.h"
 #include "pbd/pthread_utils.h"
@@ -94,6 +95,7 @@
 #include "ardour/profile.h"
 #include "ardour/recent_sessions.h"
 #include "ardour/record_enable_control.h"
+#include "ardour/revision.h"
 #include "ardour/session_directory.h"
 #include "ardour/session_route.h"
 #include "ardour/session_state_utils.h"
@@ -125,6 +127,7 @@ typedef uint64_t microseconds_t;
 
 #include "about.h"
 #include "editing.h"
+#include "enums_convert.h"
 #include "actions.h"
 #include "add_route_dialog.h"
 #include "ambiguous_file_dialog.h"
@@ -685,6 +688,55 @@ ARDOUR_UI::post_engine ()
         */
 
        if (ARDOUR_COMMAND_LINE::show_key_actions) {
+               stringstream sstr;
+               Bindings::save_all_bindings_as_html (sstr);
+
+               if (sstr.str().empty()) {
+                       return;
+               }
+               gchar* file_name;
+               GError *err = NULL;
+               gint fd;
+
+               if ((fd = g_file_open_tmp ("akprintXXXXXX.html", &file_name, &err)) < 0) {
+                       if (err) {
+                               error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg;
+                               g_error_free (err);
+                       }
+                       return;
+               }
+
+#ifdef PLATFORM_WINDOWS
+               ::close (fd);
+#endif
+
+               err = NULL;
+
+               if (!g_file_set_contents (file_name, sstr.str().c_str(), sstr.str().size(), &err)) {
+#ifndef PLATFORM_WINDOWS
+                       ::close (fd);
+#endif
+                       g_unlink (file_name);
+                       if (err) {
+                               error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg;
+                               g_error_free (err);
+                       }
+                       return;
+               }
+
+#ifndef PLATFORM_WINDOWS
+               ::close (fd);
+#endif
+
+               PBD::open_uri (string_compose ("file:///%1", file_name));
+
+               halt_connection.disconnect ();
+               AudioEngine::instance()->stop ();
+               exit (0);
+
+       }
+
+       if (ARDOUR_COMMAND_LINE::show_actions) {
 
 
                vector<string> paths;
@@ -692,21 +744,70 @@ ARDOUR_UI::post_engine ()
                vector<string> tooltips;
                vector<string> keys;
                vector<Glib::RefPtr<Gtk::Action> > actions;
+               string ver_in = revision;
+               string ver = ver_in.substr(0, ver_in.find("-"));
+
+               stringstream output;
+               output << "\n<h2>Menu actions</h2>" << endl;
+               output << "<p>\n  Every single menu item in " << PROGRAM_NAME << "'s GUI is accessible by control" << endl;
+               output << "  surfaces or scripts.\n</p>\n" << endl;
+               output << "<p>\n  The list below shows all available values of <em>action-name</em> as of" << endl;
+               output << "  " << PROGRAM_NAME << " " << ver << ". You can get the current list at any" << endl;
+               output << "  time by running " << PROGRAM_NAME << " with the -A flag.\n</p>\n" << endl;
+               output << "<table class=\"dl\">\n  <thead>" << endl;
+               output << "      <tr><th>Action Name</th><th>Menu Name</th></tr>" << endl;
+               output << "  </thead>\n  <tbody>" << endl;
 
                Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
 
-               vector<string>::iterator k;
                vector<string>::iterator p;
+               vector<string>::iterator l;
+
+               for (p = paths.begin(), l = labels.begin(); p != paths.end(); ++p, ++l) {
+                       output << "     <tr><th><kbd class=\"osc\">" << (*p).substr (9, string::npos);
+                       output << "</kbd></th><td>" << *l << "</td></tr>" << endl;
+               }
+               output << "  </tbody>\n  </table>" << endl;
+
+               // output this mess to a browser for easiest X-platform use
+               // it is not pretty HTML, but it works and it's main purpose
+               // is to create raw html to fit in Ardour's manual with no editing
+               gchar* file_name;
+               GError *err = NULL;
+               gint fd;
+
+               if ((fd = g_file_open_tmp ("akprintXXXXXX.html", &file_name, &err)) < 0) {
+                       if (err) {
+                               error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg;
+                               g_error_free (err);
+                       }
+                       return;
+               }
 
-               for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) {
+#ifdef PLATFORM_WINDOWS
+               ::close (fd);
+#endif
 
-                       if ((*k).empty()) {
-                               cout << *p << endl;
-                       } else {
-                               cout << *p << " => " << *k << endl;
+               err = NULL;
+
+               if (!g_file_set_contents (file_name, output.str().c_str(), output.str().size(), &err)) {
+#ifndef PLATFORM_WINDOWS
+                       ::close (fd);
+#endif
+                       g_unlink (file_name);
+                       if (err) {
+                               error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg;
+                               g_error_free (err);
                        }
+                       return;
                }
 
+#ifndef PLATFORM_WINDOWS
+               ::close (fd);
+#endif
+
+               PBD::open_uri (string_compose ("file:///%1", file_name));
+
                halt_connection.disconnect ();
                AudioEngine::instance()->stop ();
                exit (0);
@@ -819,31 +920,31 @@ ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
 void
 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
 {
-       XMLProperty const * prop;
+       std::string str;
 
-       if ((prop = node.property ("roll")) != 0) {
-               roll_controllable->set_id (prop->value());
+       if (node.get_property ("roll", str)){
+               roll_controllable->set_id (str);
        }
-       if ((prop = node.property ("stop")) != 0) {
-               stop_controllable->set_id (prop->value());
+       if (node.get_property ("stop", str)) {
+               stop_controllable->set_id (str);
        }
-       if ((prop = node.property ("goto-start")) != 0) {
-               goto_start_controllable->set_id (prop->value());
+       if (node.get_property ("goto-start", str)) {
+               goto_start_controllable->set_id (str);
        }
-       if ((prop = node.property ("goto-end")) != 0) {
-               goto_end_controllable->set_id (prop->value());
+       if (node.get_property ("goto-end", str)) {
+               goto_end_controllable->set_id (str);
        }
-       if ((prop = node.property ("auto-loop")) != 0) {
-               auto_loop_controllable->set_id (prop->value());
+       if (node.get_property ("auto-loop", str)) {
+               auto_loop_controllable->set_id (str);
        }
-       if ((prop = node.property ("play-selection")) != 0) {
-               play_selection_controllable->set_id (prop->value());
+       if (node.get_property ("play-selection", str)) {
+               play_selection_controllable->set_id (str);
        }
-       if ((prop = node.property ("rec")) != 0) {
-               rec_controllable->set_id (prop->value());
+       if (node.get_property ("rec", str)) {
+               rec_controllable->set_id (str);
        }
-       if ((prop = node.property ("shuttle")) != 0) {
-               shuttle_box.controllable()->set_id (prop->value());
+       if (node.get_property ("shuttle", str)) {
+               shuttle_box.controllable()->set_id (str);
        }
 }
 
@@ -851,24 +952,15 @@ XMLNode&
 ARDOUR_UI::get_transport_controllable_state ()
 {
        XMLNode* node = new XMLNode(X_("TransportControllables"));
-       char buf[64];
 
-       roll_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("roll"), buf);
-       stop_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("stop"), buf);
-       goto_start_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("goto_start"), buf);
-       goto_end_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("goto_end"), buf);
-       auto_loop_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("auto_loop"), buf);
-       play_selection_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("play_selection"), buf);
-       rec_controllable->id().print (buf, sizeof (buf));
-       node->add_property (X_("rec"), buf);
-       shuttle_box.controllable()->id().print (buf, sizeof (buf));
-       node->add_property (X_("shuttle"), buf);
+       node->set_property (X_("roll"), roll_controllable->id());
+       node->set_property (X_("stop"), stop_controllable->id());
+       node->set_property (X_("goto_start"), goto_start_controllable->id());
+       node->set_property (X_("goto_end"), goto_end_controllable->id());
+       node->set_property (X_("auto_loop"), auto_loop_controllable->id());
+       node->set_property (X_("play_selection"), play_selection_controllable->id());
+       node->set_property (X_("rec"), rec_controllable->id());
+       node->set_property (X_("shuttle"), shuttle_box.controllable()->id());
 
        return *node;
 }
@@ -1190,7 +1282,7 @@ ARDOUR_UI::starting ()
 
        BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
 
-       if (splash && splash->is_visible()) {
+       if (splash) {
                // in 1 second, hide the splash screen
                Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
        }
@@ -1835,7 +1927,7 @@ ARDOUR_UI::open_recent_session ()
 
                can_return = false;
        }
-       if (splash && splash->is_visible()) {
+       if (splash) {
                // in 1 second, hide the splash screen
                Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
        }
@@ -2616,11 +2708,15 @@ void
 ARDOUR_UI::blink_handler (bool blink_on)
 {
        transport_rec_enable_blink (blink_on);
-       solo_blink (blink_on);
        sync_blink (blink_on);
+
+       if (!UIConfiguration::instance().get_blink_alert_indicators()) {
+               blink_on = true;
+       }
+       error_blink (blink_on);
+       solo_blink (blink_on);
        audition_blink (blink_on);
        feedback_blink (blink_on);
-       error_blink (blink_on);
 }
 
 void
@@ -3733,8 +3829,8 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name,
        /* Put the playhead at 0 and scroll fully left */
        n = new_session->instant_xml (X_("Editor"));
        if (n) {
-               n->add_property (X_("playhead"), X_("0"));
-               n->add_property (X_("left-frame"), X_("0"));
+               n->set_property (X_("playhead"), X_("0"));
+               n->set_property (X_("left-frame"), X_("0"));
        }
 
        set_session (new_session);
@@ -4379,9 +4475,8 @@ ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg)
                if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
                        Config->set_video_advanced_setup(false);
                } else {
-                       std::ostringstream osstream;
-                       osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
-                       Config->set_video_server_url(osstream.str());
+                       std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/";
+                       Config->set_video_server_url(url_str);
                        Config->set_video_server_docroot(icsd_docroot);
                        Config->set_video_advanced_setup(true);
                }
@@ -4513,11 +4608,11 @@ ARDOUR_UI::add_video (Gtk::Window* float_window)
 
        if (video_timeline->video_file_info(path, local_file)) {
                XMLNode* node = new XMLNode(X_("Videotimeline"));
-               node->add_property (X_("Filename"), path);
-               node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
-               node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
+               node->set_property (X_("Filename"), path);
+               node->set_property (X_("AutoFPS"), auto_set_session_fps);
+               node->set_property (X_("LocalFile"), local_file);
                if (orig_local_file) {
-                       node->add_property (X_("OriginalVideoFile"), orig_path);
+                       node->set_property (X_("OriginalVideoFile"), orig_path);
                } else {
                        node->remove_property (X_("OriginalVideoFile"));
                }
@@ -5104,9 +5199,9 @@ ARDOUR_UI::store_clock_modes ()
        for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
                XMLNode* child = new XMLNode (X_("Clock"));
 
-               child->add_property (X_("name"), (*x)->name());
-               child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
-               child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
+               child->set_property (X_("name"), (*x)->name());
+               child->set_property (X_("mode"), (*x)->mode());
+               child->set_property (X_("on"), (*x)->on());
 
                node->add_child_nocopy (*child);
        }
@@ -5390,10 +5485,16 @@ ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
 
        while (true) {
                int response = audio_midi_setup->run();
-               printf("RESPONSE %d\n", response);
                switch (response) {
                case Gtk::RESPONSE_DELETE_EVENT:
-                       return -1;
+                       // after latency callibration engine may run,
+                       // Running() signal was emitted, but dialog will not
+                       // have emitted a response. The user needs to close
+                       // the dialog -> Gtk::RESPONSE_DELETE_EVENT
+                       if (!AudioEngine::instance()->running()) {
+                               return -1;
+                       }
+                       // fall through
                default:
                        if (!AudioEngine::instance()->running()) {
                                continue;