Tidy up window titles, according to GNOME HIG and as suggested in mantis 2803.
[ardour.git] / gtk2_ardour / ardour_ui.cc
1 /*
2     Copyright (C) 1999-2007 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #define __STDC_FORMAT_MACROS 1
21 #include <stdint.h>
22
23 #include <algorithm>
24 #include <cmath>
25 #include <fcntl.h>
26 #include <signal.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <cerrno>
30 #include <fstream>
31
32 #include <iostream>
33
34 #include <sys/resource.h>
35
36 #include <gtkmm/messagedialog.h>
37 #include <gtkmm/accelmap.h>
38
39 #include "pbd/error.h"
40 #include "pbd/basename.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/file_utils.h"
46
47 #include <gtkmm2ext/gtk_ui.h>
48 #include <gtkmm2ext/utils.h>
49 #include <gtkmm2ext/click_box.h>
50 #include <gtkmm2ext/fastmeter.h>
51 #include <gtkmm2ext/stop_signal.h>
52 #include <gtkmm2ext/popup.h>
53 #include <gtkmm2ext/window_title.h>
54
55 #include "midi++/manager.h"
56
57 #include "ardour/ardour.h"
58 #include "ardour/profile.h"
59 #include "ardour/session_directory.h"
60 #include "ardour/session_route.h"
61 #include "ardour/session_state_utils.h"
62 #include "ardour/session_utils.h"
63 #include "ardour/port.h"
64 #include "ardour/audioengine.h"
65 #include "ardour/playlist.h"
66 #include "ardour/utils.h"
67 #include "ardour/audio_diskstream.h"
68 #include "ardour/audiofilesource.h"
69 #include "ardour/recent_sessions.h"
70 #include "ardour/port.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/midi_track.h"
73 #include "ardour/filesystem_paths.h"
74 #include "ardour/filename_extensions.h"
75
76 typedef uint64_t microseconds_t;
77
78 #include "actions.h"
79 #include "ardour_ui.h"
80 #include "public_editor.h"
81 #include "audio_clock.h"
82 #include "keyboard.h"
83 #include "mixer_ui.h"
84 #include "prompter.h"
85 #include "opts.h"
86 #include "add_route_dialog.h"
87 #include "about.h"
88 #include "splash.h"
89 #include "utils.h"
90 #include "gui_thread.h"
91 #include "theme_manager.h"
92 #include "bundle_manager.h"
93 #include "session_metadata_dialog.h"
94 #include "gain_meter.h"
95 #include "route_time_axis.h"
96 #include "startup.h"
97 #include "engine_dialog.h"
98
99 #include "i18n.h"
100
101 using namespace ARDOUR;
102 using namespace PBD;
103 using namespace Gtkmm2ext;
104 using namespace Gtk;
105 using namespace sigc;
106
107 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
108 UIConfiguration *ARDOUR_UI::ui_config = 0;
109
110 sigc::signal<void,bool> ARDOUR_UI::Blink;
111 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
112 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
113 sigc::signal<void,nframes_t, bool, nframes_t> ARDOUR_UI::Clock;
114
115 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
116
117         : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
118
119           primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
120           secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
121           preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
122           postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
123
124           /* preroll stuff */
125
126           preroll_button (_("pre\nroll")),
127           postroll_button (_("post\nroll")),
128
129           /* big clock */
130
131           big_clock (X_("bigclock"), false, "BigClockNonRecording", true, false, true),
132
133           /* transport */
134
135           roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll)),
136           stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop)),
137           goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart)),
138           goto_end_controllable (new TransportControllable ("transport goto end", *this, TransportControllable::GotoEnd)),
139           auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop)),
140           play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection)),
141           rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable)),
142           shuttle_controllable (new TransportControllable ("shuttle", *this, TransportControllable::ShuttleControl)),
143           shuttle_controller_binding_proxy (shuttle_controllable),
144
145           roll_button (roll_controllable),
146           stop_button (stop_controllable),
147           goto_start_button (goto_start_controllable),
148           goto_end_button (goto_end_controllable),
149           auto_loop_button (auto_loop_controllable),
150           play_selection_button (play_selection_controllable),
151           rec_button (rec_controllable),
152
153           shuttle_units_button (_("% ")),
154
155           punch_in_button (_("Punch In")),
156           punch_out_button (_("Punch Out")),
157           auto_return_button (_("Auto Return")),
158           auto_play_button (_("Auto Play")),
159           auto_input_button (_("Auto Input")),
160           click_button (_("Click")),
161           time_master_button (_("time\nmaster")),
162
163           auditioning_alert_button (_("AUDITION")),
164           solo_alert_button (_("SOLO")),
165           shown_flag (false),
166           error_log_button (_("Errors"))
167
168 {
169         using namespace Gtk::Menu_Helpers;
170
171         Gtkmm2ext::init();
172
173
174 #ifdef TOP_MENUBAR
175         // _auto_display_errors = false;
176         /*
177          * This was commented out as it wasn't defined
178          * in A3 IIRC.  If this is not needed it should
179          * be completely removed.
180          */
181 #endif
182
183         about = 0;
184         splash = 0;
185         _startup = 0;
186
187         if (theArdourUI == 0) {
188                 theArdourUI = this;
189         }
190
191         ui_config = new UIConfiguration();
192         theme_manager = new ThemeManager();
193
194         editor = 0;
195         mixer = 0;
196         session = 0;
197         editor = 0;
198         engine = 0;
199         _session_is_new = false;
200         big_clock_window = 0;
201         session_selector_window = 0;
202         last_key_press_time = 0;
203         _will_create_new_session_automatically = false;
204         add_route_dialog = 0;
205         route_params = 0;
206         rc_option_editor = 0;
207         session_option_editor = 0;
208         location_ui = 0;
209         open_session_selector = 0;
210         have_configure_timeout = false;
211         have_disk_speed_dialog_displayed = false;
212         session_loaded = false;
213         last_speed_displayed = -1.0f;
214         ignore_dual_punch = false;
215         _mixer_on_top = false;
216
217         roll_button.unset_flags (Gtk::CAN_FOCUS);
218         stop_button.unset_flags (Gtk::CAN_FOCUS);
219         goto_start_button.unset_flags (Gtk::CAN_FOCUS);
220         goto_end_button.unset_flags (Gtk::CAN_FOCUS);
221         auto_loop_button.unset_flags (Gtk::CAN_FOCUS);
222         play_selection_button.unset_flags (Gtk::CAN_FOCUS);
223         rec_button.unset_flags (Gtk::CAN_FOCUS);
224
225         last_configure_time= 0;
226
227         shuttle_grabbed = false;
228         shuttle_fract = 0.0;
229         shuttle_max_speed = 8.0f;
230
231         shuttle_style_menu = 0;
232         shuttle_unit_menu = 0;
233
234         // We do not have jack linked in yet so;
235
236         last_shuttle_request = last_peak_grab = 0; //  get_microseconds();
237
238         ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
239         ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
240
241         /* handle dialog requests */
242
243         ARDOUR::Session::Dialog.connect (mem_fun(*this, &ARDOUR_UI::session_dialog));
244
245         /* handle pending state with a dialog */
246
247         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
248
249         /* handle sr mismatch with a dialog */
250
251         ARDOUR::Session::AskAboutSampleRateMismatch.connect (mem_fun(*this, &ARDOUR_UI::sr_mismatch_dialog));
252
253         /* lets get this party started */
254
255         try {
256                 if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization)) {
257                         throw failed_constructor ();
258                 }
259
260                 setup_gtk_ardour_enums ();
261                 setup_profile ();
262
263                 GainMeter::setup_slider_pix ();
264                 RouteTimeAxisView::setup_slider_pix ();
265
266         } catch (failed_constructor& err) {
267                 error << _("could not initialize Ardour.") << endmsg;
268                 // pass it on up
269                 throw;
270         }
271
272         /* we like keyboards */
273
274         keyboard = new Keyboard;
275
276         reset_dpi();
277
278         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
279         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
280
281         platform_setup ();
282 }
283
284 void
285 ARDOUR_UI::run_startup (bool should_be_new)
286 {
287         if (_startup == 0) {
288                 _startup = new ArdourStartup ();
289         }
290
291         _startup->set_new_only (should_be_new);
292         _startup->present ();
293
294         main().run();
295
296         /* we don't return here until the startup assistant is finished */
297
298         _startup->hide ();
299 }
300
301 int
302 ARDOUR_UI::create_engine ()
303 {
304         // this gets called every time by new_session()
305
306         if (engine) {
307                 return 0;
308         }
309
310         loading_message (_("Starting audio engine"));
311
312         try {
313                 engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
314
315         } catch (...) {
316
317                 return -1;
318         }
319
320         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
321         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
322         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
323         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
324
325         post_engine ();
326
327         return 0;
328 }
329
330 void
331 ARDOUR_UI::post_engine ()
332 {
333         /* Things to be done once we create the AudioEngine
334          */
335
336         MIDI::Manager::instance()->set_api_data (engine->jack());
337         setup_midi ();
338
339         ARDOUR::init_post_engine ();
340
341         ActionManager::init ();
342         _tooltips.enable();
343
344         if (setup_windows ()) {
345                 throw failed_constructor ();
346         }
347
348         check_memory_locking();
349
350         /* this is the first point at which all the keybindings are available */
351
352         if (ARDOUR_COMMAND_LINE::show_key_actions) {
353                 vector<string> names;
354                 vector<string> paths;
355                 vector<string> keys;
356                 vector<AccelKey> bindings;
357
358                 ActionManager::get_all_actions (names, paths, keys, bindings);
359
360                 vector<string>::iterator n;
361                 vector<string>::iterator k;
362                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
363                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
364                 }
365
366                 exit (0);
367         }
368
369         blink_timeout_tag = -1;
370
371         /* this being a GUI and all, we want peakfiles */
372
373         AudioFileSource::set_build_peakfiles (true);
374         AudioFileSource::set_build_missing_peakfiles (true);
375
376         /* set default clock modes */
377
378         if (Profile->get_sae()) {
379                 primary_clock.set_mode (AudioClock::BBT);
380                 secondary_clock.set_mode (AudioClock::MinSec);
381         }  else {
382                 primary_clock.set_mode (AudioClock::SMPTE);
383                 secondary_clock.set_mode (AudioClock::BBT);
384         }
385
386         /* start the time-of-day-clock */
387
388 #ifndef GTKOSX
389         /* OS X provides an always visible wallclock, so don't be stupid */
390         update_wall_clock ();
391         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
392 #endif
393
394         update_disk_space ();
395         update_cpu_load ();
396         update_sample_rate (engine->frame_rate());
397
398         /* now start and maybe save state */
399
400         if (do_engine_start () == 0) {
401                 if (session && _session_is_new) {
402                         /* we need to retain initial visual
403                            settings for a new session
404                         */
405                         session->save_state ("");
406                 }
407         }
408 }
409
410 ARDOUR_UI::~ARDOUR_UI ()
411 {
412         save_ardour_state ();
413
414         delete keyboard;
415         delete editor;
416         delete mixer;
417         delete add_route_dialog;
418 }
419
420 void
421 ARDOUR_UI::pop_back_splash ()
422 {
423         if (Splash::instance()) {
424                 // Splash::instance()->pop_back();
425                 Splash::instance()->hide ();
426         }
427 }
428
429 gint
430 ARDOUR_UI::configure_timeout ()
431 {
432         if (last_configure_time == 0) {
433                 /* no configure events yet */
434                 return TRUE;
435         }
436
437         /* force a gap of 0.5 seconds since the last configure event
438          */
439
440         if (get_microseconds() - last_configure_time < 500000) {
441                 return TRUE;
442         } else {
443                 have_configure_timeout = false;
444                 save_ardour_state ();
445                 return FALSE;
446         }
447 }
448
449 gboolean
450 ARDOUR_UI::configure_handler (GdkEventConfigure* /*conf*/)
451 {
452         if (have_configure_timeout) {
453                 last_configure_time = get_microseconds();
454         } else {
455                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
456                 have_configure_timeout = true;
457         }
458
459         return FALSE;
460 }
461
462 void
463 ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
464 {
465         const XMLProperty* prop;
466
467         if ((prop = node.property ("roll")) != 0) {
468                 roll_controllable->set_id (prop->value());
469         }
470         if ((prop = node.property ("stop")) != 0) {
471                 stop_controllable->set_id (prop->value());
472         }
473         if ((prop = node.property ("goto-start")) != 0) {
474                 goto_start_controllable->set_id (prop->value());
475         }
476         if ((prop = node.property ("goto-end")) != 0) {
477                 goto_end_controllable->set_id (prop->value());
478         }
479         if ((prop = node.property ("auto-loop")) != 0) {
480                 auto_loop_controllable->set_id (prop->value());
481         }
482         if ((prop = node.property ("play-selection")) != 0) {
483                 play_selection_controllable->set_id (prop->value());
484         }
485         if ((prop = node.property ("rec")) != 0) {
486                 rec_controllable->set_id (prop->value());
487         }
488         if ((prop = node.property ("shuttle")) != 0) {
489                 shuttle_controllable->set_id (prop->value());
490         }
491 }
492
493 XMLNode&
494 ARDOUR_UI::get_transport_controllable_state ()
495 {
496         XMLNode* node = new XMLNode(X_("TransportControllables"));
497         char buf[64];
498
499         roll_controllable->id().print (buf, sizeof (buf));
500         node->add_property (X_("roll"), buf);
501         stop_controllable->id().print (buf, sizeof (buf));
502         node->add_property (X_("stop"), buf);
503         goto_start_controllable->id().print (buf, sizeof (buf));
504         node->add_property (X_("goto_start"), buf);
505         goto_end_controllable->id().print (buf, sizeof (buf));
506         node->add_property (X_("goto_end"), buf);
507         auto_loop_controllable->id().print (buf, sizeof (buf));
508         node->add_property (X_("auto_loop"), buf);
509         play_selection_controllable->id().print (buf, sizeof (buf));
510         node->add_property (X_("play_selection"), buf);
511         rec_controllable->id().print (buf, sizeof (buf));
512         node->add_property (X_("rec"), buf);
513         shuttle_controllable->id().print (buf, sizeof (buf));
514         node->add_property (X_("shuttle"), buf);
515
516         return *node;
517 }
518
519 void
520 ARDOUR_UI::save_ardour_state ()
521 {
522         if (!keyboard || !mixer || !editor) {
523                 return;
524         }
525
526         /* XXX this is all a bit dubious. add_extra_xml() uses
527            a different lifetime model from add_instant_xml().
528         */
529
530         XMLNode* node = new XMLNode (keyboard->get_state());
531         Config->add_extra_xml (*node);
532         Config->add_extra_xml (get_transport_controllable_state());
533         if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
534                 Config->add_extra_xml (_startup->engine_control()->get_state());
535         }
536         Config->save_state();
537         ui_config->save_state ();
538
539         XMLNode enode(static_cast<Stateful*>(editor)->get_state());
540         XMLNode mnode(mixer->get_state());
541
542         if (session) {
543                 session->add_instant_xml (enode);
544                 session->add_instant_xml (mnode);
545         } else {
546                 Config->add_instant_xml (enode);
547                 Config->add_instant_xml (mnode);
548         }
549
550         Keyboard::save_keybindings ();
551 }
552
553 gint
554 ARDOUR_UI::autosave_session ()
555 {
556         if (g_main_depth() > 1) {
557                 /* inside a recursive main loop,
558                    give up because we may not be able to
559                    take a lock.
560                 */
561                 return 1;
562         }
563
564         if (!Config->get_periodic_safety_backups()) {
565                 return 1;
566         }
567
568         if (session) {
569                 session->maybe_write_autosave();
570         }
571
572         return 1;
573 }
574
575 void
576 ARDOUR_UI::update_autosave ()
577 {
578         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::update_autosave));
579
580         if (session && session->dirty()) {
581                 if (_autosave_connection.connected()) {
582                         _autosave_connection.disconnect();
583                 }
584
585                 _autosave_connection = Glib::signal_timeout().connect (mem_fun (*this, &ARDOUR_UI::autosave_session),
586                                 Config->get_periodic_safety_backup_interval() * 1000);
587
588         } else {
589                 if (_autosave_connection.connected()) {
590                         _autosave_connection.disconnect();
591                 }
592         }
593 }
594
595 void
596 ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
597 {
598         string title;
599         if (we_set_params) {
600                 title = _("Ardour could not start JACK");
601         } else {
602                 title = _("Ardour could not connect to JACK.");
603         }
604
605         MessageDialog win (title,
606                            false,
607                            Gtk::MESSAGE_INFO,
608                            Gtk::BUTTONS_NONE);
609
610         if (we_set_params) {
611                 win.set_secondary_text(_("There are several possible reasons:\n\
612 \n\
613 1) You requested audio parameters that are not supported..\n\
614 2) JACK is running as another user.\n\
615 \n\
616 Please consider the possibilities, and perhaps try different parameters."));
617         } else {
618                 win.set_secondary_text(_("There are several possible reasons:\n\
619 \n\
620 1) JACK is not running.\n\
621 2) JACK is running as another user, perhaps root.\n\
622 3) There is already another client called \"ardour\".\n\
623 \n\
624 Please consider the possibilities, and perhaps (re)start JACK."));
625         }
626
627         if (toplevel) {
628                 win.set_transient_for (*toplevel);
629         }
630
631         if (we_set_params) {
632                 win.add_button (Stock::OK, RESPONSE_CLOSE);
633         } else {
634                 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
635         }
636
637         win.set_default_response (RESPONSE_CLOSE);
638
639         win.show_all ();
640         win.set_position (Gtk::WIN_POS_CENTER);
641         pop_back_splash ();
642
643         /* we just don't care about the result, but we want to block */
644
645         win.run ();
646 }
647
648 void
649 ARDOUR_UI::startup ()
650 {
651         XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
652
653         if (audio_setup && _startup && _startup->engine_control()) {
654                 _startup->engine_control()->set_state (*audio_setup);
655         }
656
657         if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
658                 exit (1);
659         }
660
661         use_config ();
662
663         goto_editor_window ();
664
665         BootMessage (_("Ardour is ready for use"));
666         show ();
667 }
668
669 void
670 ARDOUR_UI::no_memory_warning ()
671 {
672         XMLNode node (X_("no-memory-warning"));
673         Config->add_instant_xml (node);
674 }
675
676 void
677 ARDOUR_UI::check_memory_locking ()
678 {
679 #ifdef __APPLE__
680         /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
681         return;
682 #else // !__APPLE__
683
684         XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
685
686         if (engine->is_realtime() && memory_warning_node == 0) {
687
688                 struct rlimit limits;
689                 int64_t ram;
690                 long pages, page_size;
691
692                 if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
693                         ram = 0;
694                 } else {
695                         ram = (int64_t) pages * (int64_t) page_size;
696                 }
697
698                 if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
699                         return;
700                 }
701
702                 if (limits.rlim_cur != RLIM_INFINITY) {
703
704                         if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
705
706
707                                 MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
708                                                      "This might cause Ardour to run out of memory before your system "
709                                                      "runs out of memory. \n\n"
710                                                      "You can view the memory limit with 'ulimit -l', "
711                                                      "and it is normally controlled by /etc/security/limits.conf"));
712
713                                 VBox* vbox = msg.get_vbox();
714                                 HBox hbox;
715                                 CheckButton cb (_("Do not show this window again"));
716
717                                 cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
718
719                                 hbox.pack_start (cb, true, false);
720                                 vbox->pack_start (hbox);
721                                 cb.show();
722                                 vbox->show();
723                                 hbox.show ();
724
725                                 pop_back_splash ();
726
727                                 editor->ensure_float (msg);
728                                 msg.run ();
729                         }
730                 }
731         }
732 #endif // !__APPLE__
733 }
734
735
736 void
737 ARDOUR_UI::finish()
738 {
739         if (session) {
740
741                 if (session->transport_rolling()) {
742                         session->request_stop ();
743                         usleep (250000);
744                 }
745
746                 if (session->dirty()) {
747                         switch (ask_about_saving_session(_("quit"))) {
748                         case -1:
749                                 return;
750                                 break;
751                         case 1:
752                                 /* use the default name */
753                                 if (save_state_canfail ("")) {
754                                         /* failed - don't quit */
755                                         MessageDialog msg (*editor,
756                                                            _("\
757 Ardour was unable to save your session.\n\n\
758 If you still wish to quit, please use the\n\n\
759 \"Just quit\" option."));
760                                         pop_back_splash();
761                                         msg.run ();
762                                         return;
763                                 }
764                                 break;
765                         case 0:
766                                 break;
767                         }
768                 }
769
770                 session->set_deletion_in_progress ();
771         }
772
773         ArdourDialog::close_all_dialogs ();
774         engine->stop (true);
775         save_ardour_state ();
776         quit ();
777 }
778
779 int
780 ARDOUR_UI::ask_about_saving_session (const string & what)
781 {
782         ArdourDialog window (_("ardour: save session?"));
783         Gtk::HBox dhbox;  // the hbox for the image and text
784         Gtk::Label  prompt_label;
785         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING,  Gtk::ICON_SIZE_DIALOG));
786
787         string msg;
788
789         msg = string_compose(_("Don't %1"), what);
790         window.add_button (msg, RESPONSE_REJECT);
791         msg = string_compose(_("Just %1"), what);
792         window.add_button (msg, RESPONSE_APPLY);
793         msg = string_compose(_("Save and %1"), what);
794         window.add_button (msg, RESPONSE_ACCEPT);
795
796         window.set_default_response (RESPONSE_ACCEPT);
797
798         Gtk::Button noquit_button (msg);
799         noquit_button.set_name ("EditorGTKButton");
800
801         string prompt;
802         string type;
803
804         if (session->snap_name() == session->name()) {
805                 type = _("session");
806         } else {
807                 type = _("snapshot");
808         }
809         prompt = string_compose(_("The %1 \"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
810                          type, session->snap_name());
811
812         prompt_label.set_text (prompt);
813         prompt_label.set_name (X_("PrompterLabel"));
814         prompt_label.set_alignment(ALIGN_LEFT, ALIGN_TOP);
815
816         dimage->set_alignment(ALIGN_CENTER, ALIGN_TOP);
817         dhbox.set_homogeneous (false);
818         dhbox.pack_start (*dimage, false, false, 5);
819         dhbox.pack_start (prompt_label, true, false, 5);
820         window.get_vbox()->pack_start (dhbox);
821
822         window.set_name (_("Prompter"));
823         window.set_position (Gtk::WIN_POS_MOUSE);
824         window.set_modal (true);
825         window.set_resizable (false);
826
827         dhbox.show();
828         prompt_label.show();
829         dimage->show();
830         window.show();
831         window.set_keep_above (true);
832         window.present ();
833
834         ResponseType r = (ResponseType) window.run();
835
836         window.hide ();
837
838         switch (r) {
839         case RESPONSE_ACCEPT: // save and get out of here
840                 return 1;
841         case RESPONSE_APPLY:  // get out of here
842                 return 0;
843         default:
844                 break;
845         }
846
847         return -1;
848 }
849
850 gint
851 ARDOUR_UI::every_second ()
852 {
853         update_cpu_load ();
854         update_buffer_load ();
855         update_disk_space ();
856         return TRUE;
857 }
858
859 gint
860 ARDOUR_UI::every_point_one_seconds ()
861 {
862         update_speed_display ();
863         RapidScreenUpdate(); /* EMIT_SIGNAL */
864         return TRUE;
865 }
866
867 gint
868 ARDOUR_UI::every_point_zero_one_seconds ()
869 {
870         // august 2007: actual update frequency: 40Hz, not 100Hz
871
872         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
873         return TRUE;
874 }
875
876 void
877 ARDOUR_UI::update_sample_rate (nframes_t ignored)
878 {
879         char buf[32];
880
881         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
882
883         if (!engine->connected()) {
884
885                 snprintf (buf, sizeof (buf), _("disconnected"));
886
887         } else {
888
889                 nframes_t rate = engine->frame_rate();
890
891                 if (fmod (rate, 1000.0) != 0.0) {
892                         snprintf (buf, sizeof (buf), _("%.1f kHz / %4.1f ms"),
893                                   (float) rate/1000.0f,
894                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
895                 } else {
896                         snprintf (buf, sizeof (buf), _("%u kHz / %4.1f ms"),
897                                   rate/1000,
898                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
899                 }
900         }
901
902         sample_rate_label.set_text (buf);
903 }
904
905 void
906 ARDOUR_UI::update_cpu_load ()
907 {
908         char buf[32];
909         snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), engine->get_cpu_load());
910         cpu_load_label.set_text (buf);
911 }
912
913 void
914 ARDOUR_UI::update_buffer_load ()
915 {
916         char buf[64];
917         uint32_t c, p;
918
919         if (session) {
920                 c = session->capture_load ();
921                 p = session->playback_load ();
922
923                 push_buffer_stats (c, p);
924
925                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
926                           session->playback_load(), session->capture_load());
927                 buffer_load_label.set_text (buf);
928         } else {
929                 buffer_load_label.set_text ("");
930         }
931 }
932
933 void
934 ARDOUR_UI::count_recenabled_streams (Route& route)
935 {
936         Track* track = dynamic_cast<Track*>(&route);
937         if (track && track->diskstream()->record_enabled()) {
938                 rec_enabled_streams += track->n_inputs().n_total();
939         }
940 }
941
942 void
943 ARDOUR_UI::update_disk_space()
944 {
945         if (session == 0) {
946                 return;
947         }
948
949         nframes_t frames = session->available_capture_duration();
950         char buf[64];
951         nframes_t fr = session->frame_rate();
952
953         if (frames == max_frames) {
954                 strcpy (buf, _("Disk: 24hrs+"));
955         } else {
956                 rec_enabled_streams = 0;
957                 session->foreach_route (this, &ARDOUR_UI::count_recenabled_streams);
958
959                 if (rec_enabled_streams) {
960                         frames /= rec_enabled_streams;
961                 }
962
963                 int hrs;
964                 int mins;
965                 int secs;
966
967                 hrs  = frames / (fr * 3600);
968                 frames -= hrs * fr * 3600;
969                 mins = frames / (fr * 60);
970                 frames -= mins * fr * 60;
971                 secs = frames / fr;
972
973                 snprintf (buf, sizeof(buf), _("Disk: %02dh:%02dm:%02ds"), hrs, mins, secs);
974         }
975
976         disk_space_label.set_text (buf);
977
978         // An attempt to make the disk space label flash red when space has run out.
979
980         if (frames < fr * 60 * 5) {
981         /*      disk_space_box.style ("disk_space_label_empty"); */
982         } else {
983         /*      disk_space_box.style ("disk_space_label"); */
984         }
985
986 }
987
988 gint
989 ARDOUR_UI::update_wall_clock ()
990 {
991         time_t now;
992         struct tm *tm_now;
993         char buf[16];
994
995         time (&now);
996         tm_now = localtime (&now);
997
998         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
999         wall_clock_label.set_text (buf);
1000
1001         return TRUE;
1002 }
1003
1004 gint
1005 ARDOUR_UI::session_menu (GdkEventButton */*ev*/)
1006 {
1007         session_popup_menu->popup (0, 0);
1008         return TRUE;
1009 }
1010
1011 void
1012 ARDOUR_UI::redisplay_recent_sessions ()
1013 {
1014         std::vector<sys::path> session_directories;
1015         RecentSessionsSorter cmp;
1016
1017         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1018         recent_session_model->clear ();
1019
1020         ARDOUR::RecentSessions rs;
1021         ARDOUR::read_recent_sessions (rs);
1022
1023         if (rs.empty()) {
1024                 recent_session_display.set_model (recent_session_model);
1025                 return;
1026         }
1027         //
1028         // sort them alphabetically
1029         sort (rs.begin(), rs.end(), cmp);
1030
1031         for (ARDOUR::RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1032                 session_directories.push_back ((*i).second);
1033         }
1034
1035         for (vector<sys::path>::const_iterator i = session_directories.begin();
1036                         i != session_directories.end(); ++i)
1037         {
1038                 std::vector<sys::path> state_file_paths;
1039
1040                 // now get available states for this session
1041
1042                 get_state_files_in_directory (*i, state_file_paths);
1043
1044                 vector<string*>* states;
1045                 vector<const gchar*> item;
1046                 string fullpath = (*i).to_string();
1047
1048                 /* remove any trailing / */
1049
1050                 if (fullpath[fullpath.length()-1] == '/') {
1051                         fullpath = fullpath.substr (0, fullpath.length()-1);
1052                 }
1053
1054                 /* check whether session still exists */
1055                 if (!Glib::file_test(fullpath.c_str(), Glib::FILE_TEST_EXISTS)) {
1056                         /* session doesn't exist */
1057                         cerr << "skipping non-existent session " << fullpath << endl;
1058                         continue;
1059                 }
1060
1061                 /* now get available states for this session */
1062
1063                 if ((states = Session::possible_states (fullpath)) == 0) {
1064                         /* no state file? */
1065                         continue;
1066                 }
1067
1068                 std::vector<string> state_file_names(get_file_names_no_extension (state_file_paths));
1069
1070                 Gtk::TreeModel::Row row = *(recent_session_model->append());
1071
1072                 row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
1073                 row[recent_session_columns.fullpath] = fullpath;
1074
1075                 if (state_file_names.size() > 1) {
1076
1077                         // add the children
1078
1079                         for (std::vector<std::string>::iterator i2 = state_file_names.begin();
1080                                         i2 != state_file_names.end(); ++i2)
1081                         {
1082
1083                                 Gtk::TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1084
1085                                 child_row[recent_session_columns.visible_name] = *i2;
1086                                 child_row[recent_session_columns.fullpath] = fullpath;
1087                         }
1088                 }
1089         }
1090
1091         recent_session_display.set_model (recent_session_model);
1092 }
1093
1094 void
1095 ARDOUR_UI::build_session_selector ()
1096 {
1097         session_selector_window = new ArdourDialog (_("Recent Sessions"));
1098
1099         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1100
1101         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1102         session_selector_window->add_button (Stock::OPEN, RESPONSE_ACCEPT);
1103         session_selector_window->set_default_response (RESPONSE_ACCEPT);
1104         recent_session_model = TreeStore::create (recent_session_columns);
1105         recent_session_display.set_model (recent_session_model);
1106         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1107         recent_session_display.set_headers_visible (false);
1108         recent_session_display.get_selection()->set_mode (SELECTION_BROWSE);
1109         recent_session_display.signal_row_activated().connect (mem_fun (*this, &ARDOUR_UI::recent_session_row_activated));
1110
1111         scroller->add (recent_session_display);
1112         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1113
1114         session_selector_window->set_name ("SessionSelectorWindow");
1115         session_selector_window->set_size_request (200, 400);
1116         session_selector_window->get_vbox()->pack_start (*scroller);
1117
1118         recent_session_display.show();
1119         scroller->show();
1120         //session_selector_window->get_vbox()->show();
1121 }
1122
1123 void
1124 ARDOUR_UI::recent_session_row_activated (const TreePath& /*path*/, TreeViewColumn* /*col*/)
1125 {
1126         session_selector_window->response (RESPONSE_ACCEPT);
1127 }
1128
1129 void
1130 ARDOUR_UI::open_recent_session ()
1131 {
1132         bool can_return = (session != 0);
1133
1134         if (session_selector_window == 0) {
1135                 build_session_selector ();
1136         }
1137
1138         redisplay_recent_sessions ();
1139
1140         while (true) {
1141
1142                 session_selector_window->set_position (WIN_POS_MOUSE);
1143
1144                 ResponseType r = (ResponseType) session_selector_window->run ();
1145
1146                 switch (r) {
1147                 case RESPONSE_ACCEPT:
1148                         break;
1149                 default:
1150                         if (can_return) {
1151                                 session_selector_window->hide();
1152                                 return;
1153                         } else {
1154                                 exit (1);
1155                         }
1156                 }
1157
1158                 if (recent_session_display.get_selection()->count_selected_rows() == 0) {
1159                         continue;
1160                 }
1161
1162                 session_selector_window->hide();
1163
1164                 Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1165
1166                 if (i == recent_session_model->children().end()) {
1167                         return;
1168                 }
1169
1170                 Glib::ustring path = (*i)[recent_session_columns.fullpath];
1171                 Glib::ustring state = (*i)[recent_session_columns.visible_name];
1172
1173                 _session_is_new = false;
1174
1175                 if (load_session (path, state) == 0) {
1176                         break;
1177                 }
1178
1179                 can_return = false;
1180         }
1181 }
1182
1183 bool
1184 ARDOUR_UI::check_audioengine ()
1185 {
1186         if (engine) {
1187                 if (!engine->connected()) {
1188                         MessageDialog msg (_("Ardour is not connected to JACK\n"
1189                                              "You cannot open or close sessions in this condition"));
1190                         pop_back_splash ();
1191                         msg.run ();
1192                         return false;
1193                 }
1194                 return true;
1195         } else {
1196                 return false;
1197         }
1198 }
1199
1200 void
1201 ARDOUR_UI::open_session ()
1202 {
1203         if (!check_audioengine()) {
1204                 return;
1205
1206         }
1207
1208         /* popup selector window */
1209
1210         if (open_session_selector == 0) {
1211
1212                 /* ardour sessions are folders */
1213
1214                 open_session_selector = new Gtk::FileChooserDialog (_("Open Session"), FILE_CHOOSER_ACTION_OPEN);
1215                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1216                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1217                 open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
1218
1219                 FileFilter session_filter;
1220                 session_filter.add_pattern ("*.ardour");
1221                 session_filter.set_name (_("Ardour sessions"));
1222                 open_session_selector->add_filter (session_filter);
1223                 open_session_selector->set_filter (session_filter);
1224         }
1225
1226         int response = open_session_selector->run();
1227         open_session_selector->hide ();
1228
1229         switch (response) {
1230         case RESPONSE_ACCEPT:
1231                 break;
1232         default:
1233                 open_session_selector->hide();
1234                 return;
1235         }
1236
1237         open_session_selector->hide();
1238         string session_path = open_session_selector->get_filename();
1239         string path, name;
1240         bool isnew;
1241
1242         if (session_path.length() > 0) {
1243                 if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
1244                         _session_is_new = isnew;
1245                         load_session (path, name);
1246                 }
1247         }
1248 }
1249
1250
1251 void
1252 ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many)
1253 {
1254         list<boost::shared_ptr<MidiTrack> > tracks;
1255
1256         if (session == 0) {
1257                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1258                 return;
1259         }
1260
1261         try {
1262                 if (disk) {
1263
1264                         tracks = session->new_midi_track (ARDOUR::Normal, route_group, how_many);
1265
1266                         if (tracks.size() != how_many) {
1267                                 if (how_many == 1) {
1268                                         error << _("could not create a new midi track") << endmsg;
1269                                 } else {
1270                                         error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1271                                 }
1272                         }
1273                 } /*else {
1274                         if ((route = session->new_midi_route ()) == 0) {
1275                                 error << _("could not create new midi bus") << endmsg;
1276                         }
1277                 }*/
1278         }
1279
1280         catch (...) {
1281                 MessageDialog msg (*editor,
1282                                    _("There are insufficient JACK ports available\n\
1283 to create a new track or bus.\n\
1284 You should save Ardour, exit and\n\
1285 restart JACK with more ports."));
1286                 msg.run ();
1287         }
1288 }
1289
1290
1291 void
1292 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, RouteGroup* route_group, uint32_t how_many)
1293 {
1294         list<boost::shared_ptr<AudioTrack> > tracks;
1295         RouteList routes;
1296
1297         if (session == 0) {
1298                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1299                 return;
1300         }
1301
1302         try {
1303                 if (track) {
1304                         tracks = session->new_audio_track (input_channels, output_channels, mode, route_group, how_many);
1305
1306                         if (tracks.size() != how_many) {
1307                                 if (how_many == 1) {
1308                                         error << _("could not create a new audio track") << endmsg;
1309                                 } else {
1310                                         error << string_compose (_("could only create %1 of %2 new audio %3"),
1311                                                                  tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1312                                 }
1313                         }
1314
1315                 } else {
1316
1317                         routes = session->new_audio_route (input_channels, output_channels, route_group, how_many);
1318
1319                         if (routes.size() != how_many) {
1320                                 if (how_many == 1) {
1321                                         error << _("could not create a new audio track") << endmsg;
1322                                 } else {
1323                                         error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1324                                 }
1325                         }
1326                 }
1327
1328 #if CONTROLOUTS
1329                 if (need_control_room_outs) {
1330                         pan_t pans[2];
1331
1332                         pans[0] = 0.5;
1333                         pans[1] = 0.5;
1334
1335                         route->set_stereo_control_outs (control_lr_channels);
1336                         route->control_outs()->set_stereo_pan (pans, this);
1337                 }
1338 #endif /* CONTROLOUTS */
1339         }
1340
1341         catch (...) {
1342                 MessageDialog msg (*editor,
1343                                    _("There are insufficient JACK ports available\n\
1344 to create a new track or bus.\n\
1345 You should save Ardour, exit and\n\
1346 restart JACK with more ports."));
1347                 pop_back_splash ();
1348                 msg.run ();
1349         }
1350 }
1351
1352 void
1353 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1354 {
1355         nframes_t _preroll = 0;
1356
1357         if (session) {
1358                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1359                 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1360
1361                 if (new_position > _preroll) {
1362                         new_position -= _preroll;
1363                 } else {
1364                         new_position = 0;
1365                 }
1366
1367                 session->request_locate (new_position);
1368         }
1369 }
1370
1371 void
1372 ARDOUR_UI::transport_goto_start ()
1373 {
1374         if (session) {
1375                 session->goto_start();
1376
1377
1378                 /* force displayed area in editor to start no matter
1379                    what "follow playhead" setting is.
1380                 */
1381
1382                 if (editor) {
1383                         editor->reset_x_origin (session->current_start_frame());
1384                 }
1385         }
1386 }
1387
1388 void
1389 ARDOUR_UI::transport_goto_zero ()
1390 {
1391         if (session) {
1392                 session->request_locate (0);
1393
1394
1395                 /* force displayed area in editor to start no matter
1396                    what "follow playhead" setting is.
1397                 */
1398
1399                 if (editor) {
1400                         editor->reset_x_origin (0);
1401                 }
1402         }
1403 }
1404
1405 void
1406 ARDOUR_UI::transport_goto_wallclock ()
1407 {
1408         if (session && editor) {
1409
1410                 time_t now;
1411                 struct tm tmnow;
1412                 nframes64_t frames;
1413
1414                 time (&now);
1415                 localtime_r (&now, &tmnow);
1416
1417                 frames = tmnow.tm_hour * (60 * 60 * session->frame_rate());
1418                 frames += tmnow.tm_min * (60 * session->frame_rate());
1419                 frames += tmnow.tm_sec * session->frame_rate();
1420
1421                 session->request_locate (frames);
1422
1423                 /* force displayed area in editor to start no matter
1424                    what "follow playhead" setting is.
1425                 */
1426
1427                 if (editor) {
1428                         editor->reset_x_origin (frames - (editor->current_page_frames()/2));
1429                 }
1430         }
1431 }
1432
1433 void
1434 ARDOUR_UI::transport_goto_end ()
1435 {
1436         if (session) {
1437                 nframes_t frame = session->current_end_frame();
1438                 session->request_locate (frame);
1439
1440                 /* force displayed area in editor to start no matter
1441                    what "follow playhead" setting is.
1442                 */
1443
1444                 if (editor) {
1445                         editor->reset_x_origin (frame);
1446                 }
1447         }
1448 }
1449
1450 void
1451 ARDOUR_UI::transport_stop ()
1452 {
1453         if (!session) {
1454                 return;
1455         }
1456
1457         if (session->is_auditioning()) {
1458                 session->cancel_audition ();
1459                 return;
1460         }
1461
1462         if (session->get_play_loop ()) {
1463                 session->request_play_loop (false);
1464         }
1465
1466         session->request_stop ();
1467 }
1468
1469 void
1470 ARDOUR_UI::transport_stop_and_forget_capture ()
1471 {
1472         if (session) {
1473                 session->request_stop (true);
1474         }
1475 }
1476
1477 void
1478 ARDOUR_UI::remove_last_capture()
1479 {
1480         if (editor) {
1481                 editor->remove_last_capture();
1482         }
1483 }
1484
1485 void
1486 ARDOUR_UI::transport_record (bool roll)
1487 {
1488
1489         if (session) {
1490                 switch (session->record_status()) {
1491                 case Session::Disabled:
1492                         if (session->ntracks() == 0) {
1493                                 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1494                                 msg.run ();
1495                                 return;
1496                         }
1497                         session->maybe_enable_record ();
1498                         if (roll) {
1499                                 transport_roll ();
1500                         }
1501                         break;
1502                 case Session::Recording:
1503                         if (roll) {
1504                                 session->request_stop();
1505                         } else {
1506                                 session->disable_record (false, true);
1507                         }
1508                         break;
1509
1510                 case Session::Enabled:
1511                         session->disable_record (false, true);
1512                 }
1513         }
1514         //cerr << "ARDOUR_UI::transport_record () called roll = " << roll << " session->record_status() = " << session->record_status() << endl;
1515 }
1516
1517 void
1518 ARDOUR_UI::transport_roll ()
1519 {
1520         bool rolling;
1521
1522         if (!session) {
1523                 return;
1524         }
1525
1526         rolling = session->transport_rolling ();
1527
1528         //cerr << "ARDOUR_UI::transport_roll () called session->record_status() = " << session->record_status() << endl;
1529
1530         if (session->get_play_loop()) {
1531                 session->request_play_loop (false);
1532                 auto_loop_button.set_visual_state (1);
1533                 roll_button.set_visual_state (1);
1534         } else if (session->get_play_range ()) {
1535                 session->request_play_range (false);
1536                 play_selection_button.set_visual_state (0);
1537         } else if (rolling) {
1538                 session->request_locate (session->last_transport_start(), true);
1539         }
1540
1541         session->request_transport_speed (1.0f);
1542 }
1543
1544 void
1545 ARDOUR_UI::transport_loop()
1546 {
1547         if (session) {
1548                 if (session->get_play_loop()) {
1549                         if (session->transport_rolling()) {
1550                                 Location * looploc = session->locations()->auto_loop_location();
1551                                 if (looploc) {
1552                                         session->request_locate (looploc->start(), true);
1553                                 }
1554                         }
1555                 }
1556                 else {
1557                         session->request_play_loop (true);
1558                 }
1559         }
1560 }
1561
1562 void
1563 ARDOUR_UI::transport_play_selection ()
1564 {
1565         if (!session) {
1566                 return;
1567         }
1568
1569         if (!session->get_play_range()) {
1570                 session->request_stop ();
1571         }
1572
1573         editor->play_selection ();
1574 }
1575
1576 void
1577 ARDOUR_UI::transport_rewind (int option)
1578 {
1579         float current_transport_speed;
1580
1581         if (session) {
1582                 current_transport_speed = session->transport_speed();
1583
1584                 if (current_transport_speed >= 0.0f) {
1585                         switch (option) {
1586                         case 0:
1587                                 session->request_transport_speed (-1.0f);
1588                                 break;
1589                         case 1:
1590                                 session->request_transport_speed (-4.0f);
1591                                 break;
1592                         case -1:
1593                                 session->request_transport_speed (-0.5f);
1594                                 break;
1595                         }
1596                 } else {
1597                         /* speed up */
1598                         session->request_transport_speed (current_transport_speed * 1.5f);
1599                 }
1600         }
1601 }
1602
1603 void
1604 ARDOUR_UI::transport_forward (int option)
1605 {
1606         float current_transport_speed;
1607
1608         if (session) {
1609                 current_transport_speed = session->transport_speed();
1610
1611                 if (current_transport_speed <= 0.0f) {
1612                         switch (option) {
1613                         case 0:
1614                                 session->request_transport_speed (1.0f);
1615                                 break;
1616                         case 1:
1617                                 session->request_transport_speed (4.0f);
1618                                 break;
1619                         case -1:
1620                                 session->request_transport_speed (0.5f);
1621                                 break;
1622                         }
1623                 } else {
1624                         /* speed up */
1625                         session->request_transport_speed (current_transport_speed * 1.5f);
1626                 }
1627         }
1628 }
1629
1630 void
1631 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1632 {
1633         if (session == 0) {
1634                 return;
1635         }
1636
1637         boost::shared_ptr<Route> r;
1638
1639         if ((r = session->route_by_remote_id (dstream)) != 0) {
1640
1641                 Track* t;
1642
1643                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1644                         t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1645                 }
1646         }
1647         if (session == 0) {
1648                 return;
1649         }
1650 }
1651
1652 void
1653 ARDOUR_UI::queue_transport_change ()
1654 {
1655         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1656 }
1657
1658 void
1659 ARDOUR_UI::map_transport_state ()
1660 {
1661         float sp = session->transport_speed();
1662
1663         if (sp == 1.0f) {
1664                 transport_rolling ();
1665         } else if (sp < 0.0f) {
1666                 transport_rewinding ();
1667         } else if (sp > 0.0f) {
1668                 transport_forwarding ();
1669         } else {
1670                 transport_stopped ();
1671         }
1672 }
1673
1674 void
1675 ARDOUR_UI::engine_stopped ()
1676 {
1677         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1678         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1679         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1680 }
1681
1682 void
1683 ARDOUR_UI::engine_running ()
1684 {
1685         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1686         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1687         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1688
1689         Glib::RefPtr<Action> action;
1690         const char* action_name = 0;
1691
1692         switch (engine->frames_per_cycle()) {
1693         case 32:
1694                 action_name = X_("JACKLatency32");
1695                 break;
1696         case 64:
1697                 action_name = X_("JACKLatency64");
1698                 break;
1699         case 128:
1700                 action_name = X_("JACKLatency128");
1701                 break;
1702         case 512:
1703                 action_name = X_("JACKLatency512");
1704                 break;
1705         case 1024:
1706                 action_name = X_("JACKLatency1024");
1707                 break;
1708         case 2048:
1709                 action_name = X_("JACKLatency2048");
1710                 break;
1711         case 4096:
1712                 action_name = X_("JACKLatency4096");
1713                 break;
1714         case 8192:
1715                 action_name = X_("JACKLatency8192");
1716                 break;
1717         default:
1718                 /* XXX can we do anything useful ? */
1719                 break;
1720         }
1721
1722         if (action_name) {
1723
1724                 action = ActionManager::get_action (X_("JACK"), action_name);
1725
1726                 if (action) {
1727                         Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1728                         ract->set_active ();
1729                 }
1730         }
1731 }
1732
1733 void
1734 ARDOUR_UI::engine_halted ()
1735 {
1736         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1737
1738         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1739         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1740
1741         update_sample_rate (0);
1742
1743         MessageDialog msg (*editor,
1744                            _("\
1745 JACK has either been shutdown or it\n\
1746 disconnected Ardour because Ardour\n\
1747 was not fast enough. Try to restart\n\
1748 JACK, reconnect and save the session."));
1749         pop_back_splash ();
1750         msg.run ();
1751 }
1752
1753 int32_t
1754 ARDOUR_UI::do_engine_start ()
1755 {
1756         try {
1757                 engine->start();
1758         }
1759
1760         catch (...) {
1761                 engine->stop ();
1762                 error << _("Unable to start the session running")
1763                       << endmsg;
1764                 unload_session ();
1765                 return -2;
1766         }
1767
1768         return 0;
1769 }
1770
1771 void
1772 ARDOUR_UI::setup_theme ()
1773 {
1774         theme_manager->setup_theme();
1775 }
1776
1777 void
1778 ARDOUR_UI::update_clocks ()
1779 {
1780         if (!editor || !editor->dragging_playhead()) {
1781                 Clock (session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
1782         }
1783 }
1784
1785 void
1786 ARDOUR_UI::start_clocking ()
1787 {
1788         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1789 }
1790
1791 void
1792 ARDOUR_UI::stop_clocking ()
1793 {
1794         clock_signal_connection.disconnect ();
1795 }
1796
1797 void
1798 ARDOUR_UI::toggle_clocking ()
1799 {
1800 #if 0
1801         if (clock_button.get_active()) {
1802                 start_clocking ();
1803         } else {
1804                 stop_clocking ();
1805         }
1806 #endif
1807 }
1808
1809 gint
1810 ARDOUR_UI::_blink (void *arg)
1811
1812 {
1813         ((ARDOUR_UI *) arg)->blink ();
1814         return TRUE;
1815 }
1816
1817 void
1818 ARDOUR_UI::blink ()
1819 {
1820         Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1821 }
1822
1823 void
1824 ARDOUR_UI::start_blinking ()
1825 {
1826         /* Start the blink signal. Everybody with a blinking widget
1827            uses Blink to drive the widget's state.
1828         */
1829
1830         if (blink_timeout_tag < 0) {
1831                 blink_on = false;
1832                 blink_timeout_tag = g_timeout_add (240, _blink, this);
1833         }
1834 }
1835
1836 void
1837 ARDOUR_UI::stop_blinking ()
1838 {
1839         if (blink_timeout_tag >= 0) {
1840                 g_source_remove (blink_timeout_tag);
1841                 blink_timeout_tag = -1;
1842         }
1843 }
1844
1845
1846 /** Ask the user for the name of a new shapshot and then take it.
1847  */
1848 void
1849 ARDOUR_UI::snapshot_session ()
1850 {
1851         ArdourPrompter prompter (true);
1852         string snapname;
1853         char timebuf[128];
1854         time_t n;
1855         struct tm local_time;
1856
1857         time (&n);
1858         localtime_r (&n, &local_time);
1859         strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1860
1861         prompter.set_name ("Prompter");
1862         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1863         prompter.set_title (_("Take Snapshot"));
1864         prompter.set_prompt (_("Name of New Snapshot"));
1865         prompter.set_initial_text (timebuf);
1866
1867         switch (prompter.run()) {
1868         case RESPONSE_ACCEPT:
1869         {
1870                 prompter.get_result (snapname);
1871
1872                 bool do_save = (snapname.length() != 0);
1873
1874                 vector<sys::path> p;
1875                 get_state_files_in_directory (session->session_directory().root_path(), p);
1876                 vector<string> n = get_file_names_no_extension (p);
1877                 if (find (n.begin(), n.end(), snapname) != n.end()) {
1878
1879                         ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1880                         Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
1881                         confirm.get_vbox()->pack_start (m, true, true);
1882                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1883                         confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1884                         confirm.show_all ();
1885                         switch (confirm.run()) {
1886                         case RESPONSE_CANCEL:
1887                                 do_save = false;
1888                         }
1889                 }
1890
1891                 if (do_save) {
1892                         save_state (snapname);
1893                 }
1894                 break;
1895         }
1896
1897         default:
1898                 break;
1899         }
1900 }
1901
1902 void
1903 ARDOUR_UI::save_state (const string & name)
1904 {
1905         (void) save_state_canfail (name);
1906 }
1907
1908 int
1909 ARDOUR_UI::save_state_canfail (string name)
1910 {
1911         if (session) {
1912                 int ret;
1913
1914                 if (name.length() == 0) {
1915                         name = session->snap_name();
1916                 }
1917
1918                 if ((ret = session->save_state (name)) != 0) {
1919                         return ret;
1920                 }
1921         }
1922         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1923         return 0;
1924 }
1925
1926 void
1927 ARDOUR_UI::primary_clock_value_changed ()
1928 {
1929         if (session) {
1930                 session->request_locate (primary_clock.current_time ());
1931         }
1932 }
1933
1934 void
1935 ARDOUR_UI::big_clock_value_changed ()
1936 {
1937         if (session) {
1938                 session->request_locate (big_clock.current_time ());
1939         }
1940 }
1941
1942 void
1943 ARDOUR_UI::secondary_clock_value_changed ()
1944 {
1945         if (session) {
1946                 session->request_locate (secondary_clock.current_time ());
1947         }
1948 }
1949
1950 void
1951 ARDOUR_UI::transport_rec_enable_blink (bool onoff)
1952 {
1953         if (session == 0) {
1954                 return;
1955         }
1956
1957         Session::RecordState const r = session->record_status ();
1958         bool const h = session->have_rec_enabled_diskstream ();
1959
1960         if (r == Session::Enabled || (r == Session::Recording && !h)) {
1961                 if (onoff) {
1962                         rec_button.set_visual_state (2);
1963                 } else {
1964                         rec_button.set_visual_state (0);
1965                 }
1966         } else if (r == Session::Recording && h) {
1967                 rec_button.set_visual_state (1);
1968         } else {
1969                 rec_button.set_visual_state (0);
1970         }
1971 }
1972
1973 void
1974 ARDOUR_UI::save_template ()
1975 {
1976         ArdourPrompter prompter (true);
1977         string name;
1978
1979         if (!check_audioengine()) {
1980                 return;
1981         }
1982
1983         prompter.set_name (X_("Prompter"));
1984         prompter.set_title (_("Save Mix Template"));
1985         prompter.set_prompt (_("Name for mix template:"));
1986         prompter.set_initial_text(session->name() + _("-template"));
1987         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1988
1989         switch (prompter.run()) {
1990         case RESPONSE_ACCEPT:
1991                 prompter.get_result (name);
1992
1993                 if (name.length()) {
1994                         session->save_template (name);
1995                 }
1996                 break;
1997
1998         default:
1999                 break;
2000         }
2001 }
2002
2003 void
2004 ARDOUR_UI::edit_metadata ()
2005 {
2006         SessionMetadataEditor dialog;
2007         dialog.set_session (session);
2008         editor->ensure_float (dialog);
2009         dialog.run ();
2010 }
2011
2012 void
2013 ARDOUR_UI::import_metadata ()
2014 {
2015         SessionMetadataImporter dialog;
2016         dialog.set_session (session);
2017         editor->ensure_float (dialog);
2018         dialog.run ();
2019 }
2020
2021 void
2022 ARDOUR_UI::fontconfig_dialog ()
2023 {
2024 #ifdef GTKOSX
2025         /* X11 users will always have fontconfig info around, but new GTK-OSX users
2026            may not and it can take a while to build it. Warn them.
2027         */
2028
2029         Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2030
2031         if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2032                 MessageDialog msg (*_startup,
2033                                    _("Welcome to Ardour.\n\n"
2034                                      "The program will take a bit longer to start up\n"
2035                                      "while the system fonts are checked.\n\n"
2036                                      "This will only be done once, and you will\n"
2037                                      "not see this message again\n"),
2038                                    true,
2039                                    Gtk::MESSAGE_INFO,
2040                                    Gtk::BUTTONS_OK);
2041                 pop_back_splash ();
2042                 msg.show_all ();
2043                 msg.present ();
2044                 msg.run ();
2045         }
2046 #endif
2047 }
2048
2049 void
2050 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2051 {
2052         existing_session = false;
2053
2054         if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2055                 session_path = cmdline_path;
2056                 existing_session = true;
2057         } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2058                 session_path = Glib::path_get_dirname (string (cmdline_path));
2059                 existing_session = true;
2060         } else {
2061                 /* it doesn't exist, assume the best */
2062                 session_path = Glib::path_get_dirname (string (cmdline_path));
2063         }
2064
2065         session_name = basename_nosuffix (string (cmdline_path));
2066 }
2067
2068 int
2069 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2070 {
2071         /* when this is called, the backend audio system must be running */
2072
2073         /* the main idea here is to deal with the fact that a cmdline argument for the session
2074            can be interpreted in different ways - it could be a directory or a file, and before
2075            we load, we need to know both the session directory and the snapshot (statefile) within it
2076            that we are supposed to use.
2077         */
2078
2079         if (session_name.length() == 0 || session_path.length() == 0) {
2080                 return false;
2081         }
2082
2083         if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2084
2085                 Glib::ustring predicted_session_file;
2086
2087                 predicted_session_file = session_path;
2088                 predicted_session_file += '/';
2089                 predicted_session_file += session_name;
2090                 predicted_session_file += ARDOUR::statefile_suffix;
2091
2092                 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2093                         existing_session = true;
2094                 }
2095
2096         } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2097
2098                 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2099                         /* existing .ardour file */
2100                         existing_session = true;
2101                 }
2102
2103         } else {
2104                 existing_session = false;
2105         }
2106
2107         /* lets just try to load it */
2108
2109         if (create_engine ()) {
2110                 backend_audio_error (false, _startup);
2111                 return -1;
2112         }
2113
2114         return load_session (session_path, session_name);
2115 }
2116
2117 bool
2118 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2119 {
2120         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2121
2122         MessageDialog msg (str,
2123                            false,
2124                            Gtk::MESSAGE_WARNING,
2125                            Gtk::BUTTONS_YES_NO,
2126                            true);
2127
2128
2129         msg.set_name (X_("CleanupDialog"));
2130         msg.set_title (_("Cleanup Unused Sources"));
2131         msg.set_wmclass (X_("existing_session"), "Ardour");
2132         msg.set_position (Gtk::WIN_POS_MOUSE);
2133         pop_back_splash ();
2134
2135         switch (msg.run()) {
2136         case RESPONSE_YES:
2137                 return true;
2138                 break;
2139         }
2140         return false;
2141 }
2142
2143 int
2144 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2145 {
2146
2147         uint32_t cchns;
2148         uint32_t mchns;
2149         AutoConnectOption iconnect;
2150         AutoConnectOption oconnect;
2151         uint32_t nphysin;
2152         uint32_t nphysout;
2153
2154         if (Profile->get_sae()) {
2155
2156                 cchns = 0;
2157                 mchns = 2;
2158                 iconnect = AutoConnectPhysical;
2159                 oconnect = AutoConnectMaster;
2160                 nphysin = 0; // use all available
2161                 nphysout = 0; // use all available
2162
2163         } else {
2164
2165                 /* get settings from advanced section of NSD */
2166
2167                 if (_startup->create_control_bus()) {
2168                         cchns = (uint32_t) _startup->control_channel_count();
2169                 } else {
2170                         cchns = 0;
2171                 }
2172
2173                 if (_startup->create_master_bus()) {
2174                         mchns = (uint32_t) _startup->master_channel_count();
2175                 } else {
2176                         mchns = 0;
2177                 }
2178
2179                 if (_startup->connect_inputs()) {
2180                         iconnect = AutoConnectPhysical;
2181                 } else {
2182                         iconnect = AutoConnectOption (0);
2183                 }
2184
2185                 /// @todo some minor tweaks.
2186
2187                 if (_startup->connect_outs_to_master()) {
2188                         oconnect = AutoConnectMaster;
2189                 } else if (_startup->connect_outs_to_physical()) {
2190                         oconnect = AutoConnectPhysical;
2191                 } else {
2192                         oconnect = AutoConnectOption (0);
2193                 }
2194
2195                 nphysin = (uint32_t) _startup->input_limit_count();
2196                 nphysout = (uint32_t) _startup->output_limit_count();
2197         }
2198
2199         if (build_session (session_path,
2200                            session_name,
2201                            cchns,
2202                            mchns,
2203                            iconnect,
2204                            oconnect,
2205                            nphysin,
2206                            nphysout,
2207                            engine->frame_rate() * 60 * 5)) {
2208
2209                 return -1;
2210         }
2211
2212         return 0;
2213 }
2214
2215 void
2216 ARDOUR_UI::idle_load (const Glib::ustring& path)
2217 {
2218         if (session) {
2219                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2220                         /* /path/to/foo => /path/to/foo, foo */
2221                         load_session (path, basename_nosuffix (path));
2222                 } else {
2223                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2224                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2225                 }
2226         } else {
2227
2228                 ARDOUR_COMMAND_LINE::session_name = path;
2229
2230                 /*
2231                  * new_session_dialog doens't exist in A3
2232                  * Try to remove all references to it to
2233                  * see if it will compile.  NOTE: this will
2234                  * likely cause a runtime issue is my somewhat
2235                  * uneducated guess.
2236                  */
2237
2238                 //if (new_session_dialog) {
2239
2240
2241                         /* make it break out of Dialog::run() and
2242                            start again.
2243                          */
2244
2245                         //new_session_dialog->response (1);
2246                 //}
2247         }
2248 }
2249
2250 void
2251 ARDOUR_UI::end_loading_messages ()
2252 {
2253         // hide_splash ();
2254 }
2255
2256 void
2257 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2258 {
2259         // show_splash ();
2260         // splash->message (msg);
2261         flush_pending ();
2262 }
2263
2264 int
2265 ARDOUR_UI::get_session_parameters (bool should_be_new)
2266 {
2267         Glib::ustring session_name;
2268         Glib::ustring session_path;
2269         Glib::ustring template_name;
2270         int ret = -1;
2271         bool likely_new = false;
2272
2273         while (ret != 0) {
2274
2275                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2276
2277                         /* if they named a specific statefile, use it, otherwise they are
2278                            just giving a session folder, and we want to use it as is
2279                            to find the session.
2280                         */
2281
2282                         if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2283                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2284                         } else {
2285                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2286                         }
2287
2288                         session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2289
2290                 } else {
2291
2292                         run_startup (should_be_new);
2293
2294                         /* if we run the startup dialog again, offer more than just "new session" */
2295
2296                         should_be_new = false;
2297
2298                         session_name = _startup->session_name (likely_new);
2299
2300                         /* this shouldn't happen, but we catch it just in case it does */
2301
2302                         if (session_name.empty()) {
2303                                 break;
2304                         }
2305                         if (_startup->use_session_template()) {
2306                                 template_name = _startup->session_template_name();
2307                                 _session_is_new = true;
2308                         }
2309
2310
2311                         if (session_name[0] == '/' ||
2312                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2313                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2314
2315                                 session_path = Glib::path_get_dirname (session_name);
2316                                 session_name = Glib::path_get_basename (session_name);
2317
2318                         } else {
2319
2320                                 session_path = _startup->session_folder();
2321                         }
2322                 }
2323
2324                 if (create_engine ()) {
2325                         break;
2326                 }
2327
2328                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2329
2330                         if (likely_new) {
2331
2332                                 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2333
2334                                 if (!ask_about_loading_existing_session (existing)) {
2335                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2336                                         continue;
2337                                 }
2338                         }
2339
2340                         _session_is_new = false;
2341
2342                 } else {
2343
2344                         if (!likely_new) {
2345                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2346                                 msg.run ();
2347                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2348                                 continue;
2349                         }
2350
2351                         _session_is_new = true;
2352                 }
2353
2354                 if (likely_new && template_name.empty()) {
2355
2356                         ret = build_session_from_nsd (session_path, session_name);
2357
2358                 } else {
2359
2360                         ret = load_session (session_path, session_name, template_name);
2361                         if (!ARDOUR_COMMAND_LINE::immediate_save.empty()) {
2362                                 session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false);
2363                                 exit (1);
2364                         }
2365                 }
2366         }
2367
2368         return ret;
2369 }
2370
2371 void
2372 ARDOUR_UI::close_session()
2373 {
2374         if (!check_audioengine()) {
2375                 return;
2376         }
2377
2378         unload_session (true);
2379
2380         ARDOUR_COMMAND_LINE::session_name = "";
2381         get_session_parameters (false);
2382 }
2383
2384 int
2385 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2386 {
2387         Session *new_session;
2388         int unload_status;
2389         int retval = -1;
2390
2391         session_loaded = false;
2392
2393         if (!check_audioengine()) {
2394                 return -1;
2395         }
2396
2397         unload_status = unload_session ();
2398
2399         if (unload_status < 0) {
2400                 goto out;
2401         } else if (unload_status > 0) {
2402                 retval = 0;
2403                 goto out;
2404         }
2405
2406         loading_message (_("Please wait while Ardour loads your session"));
2407
2408         try {
2409                 new_session = new Session (*engine, path, snap_name, mix_template);
2410         }
2411
2412         /* this one is special */
2413
2414         catch (AudioEngine::PortRegistrationFailure& err) {
2415
2416                 MessageDialog msg (err.what(),
2417                                    true,
2418                                    Gtk::MESSAGE_INFO,
2419                                    Gtk::BUTTONS_CLOSE);
2420
2421                 msg.set_title (_("Port Registration Error"));
2422                 msg.set_secondary_text (_("Click the Close button to try again."));
2423                 msg.set_position (Gtk::WIN_POS_CENTER);
2424                 pop_back_splash ();
2425                 msg.present ();
2426
2427                 int response = msg.run ();
2428
2429                 msg.hide ();
2430
2431                 switch (response) {
2432                 case RESPONSE_CANCEL:
2433                         exit (1);
2434                 default:
2435                         break;
2436                 }
2437                 goto out;
2438         }
2439
2440         catch (...) {
2441
2442                 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2443                                    true,
2444                                    Gtk::MESSAGE_INFO,
2445                                    Gtk::BUTTONS_CLOSE);
2446
2447                 msg.set_title (_("Loading Error"));
2448                 msg.set_secondary_text (_("Click the Close button to try again."));
2449                 msg.set_position (Gtk::WIN_POS_CENTER);
2450                 pop_back_splash ();
2451                 msg.present ();
2452
2453                 int response = msg.run ();
2454
2455                 msg.hide ();
2456
2457                 switch (response) {
2458                 case RESPONSE_CANCEL:
2459                         exit (1);
2460                 default:
2461                         break;
2462                 }
2463                 goto out;
2464         }
2465
2466         connect_to_session (new_session);
2467
2468         session_loaded = true;
2469
2470         goto_editor_window ();
2471
2472         if (session) {
2473                 session->set_clean ();
2474         }
2475
2476         flush_pending ();
2477         retval = 0;
2478
2479   out:
2480         return retval;
2481 }
2482
2483 int
2484 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
2485                           uint32_t control_channels,
2486                           uint32_t master_channels,
2487                           AutoConnectOption input_connect,
2488                           AutoConnectOption output_connect,
2489                           uint32_t nphysin,
2490                           uint32_t nphysout,
2491                           nframes_t initial_length)
2492 {
2493         Session *new_session;
2494         int x;
2495
2496         if (!check_audioengine()) {
2497                 return -1;
2498         }
2499
2500         session_loaded = false;
2501
2502         x = unload_session ();
2503
2504         if (x < 0) {
2505                 return -1;
2506         } else if (x > 0) {
2507                 return 0;
2508         }
2509
2510         _session_is_new = true;
2511
2512         try {
2513                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2514                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2515         }
2516
2517         catch (...) {
2518
2519                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2520                 pop_back_splash ();
2521                 msg.run ();
2522                 return -1;
2523         }
2524
2525         connect_to_session (new_session);
2526
2527         session_loaded = true;
2528
2529         new_session->save_state(new_session->name());
2530
2531         return 0;
2532 }
2533
2534 void
2535 ARDOUR_UI::show ()
2536 {
2537         if (editor) {
2538                 editor->show_window ();
2539
2540                 if (!shown_flag) {
2541                         editor->present ();
2542                 }
2543
2544                 shown_flag = true;
2545         }
2546 }
2547
2548 void
2549 ARDOUR_UI::show_about ()
2550 {
2551         if (about == 0) {
2552                 about = new About;
2553                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2554         }
2555
2556         about->show_all ();
2557 }
2558
2559 void
2560 ARDOUR_UI::hide_about ()
2561 {
2562         if (about) {
2563                 about->get_window()->set_cursor ();
2564                 about->hide ();
2565         }
2566 }
2567
2568 void
2569 ARDOUR_UI::about_signal_response (int /*response*/)
2570 {
2571         hide_about();
2572 }
2573
2574 void
2575 ARDOUR_UI::show_splash ()
2576 {
2577         if (splash == 0) {
2578                 try {
2579                         splash = new Splash;
2580                 } catch (...) {
2581                         return;
2582                 }
2583         }
2584
2585         splash->show ();
2586         splash->present ();
2587         splash->queue_draw ();
2588         splash->get_window()->process_updates (true);
2589         flush_pending ();
2590 }
2591
2592 void
2593 ARDOUR_UI::hide_splash ()
2594 {
2595         if (splash) {
2596                 splash->hide();
2597         }
2598 }
2599
2600 void
2601 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title,
2602                                     const string& plural_msg, const string& singular_msg)
2603 {
2604         size_t removed;
2605
2606         removed = rep.paths.size();
2607
2608         if (removed == 0) {
2609                 MessageDialog msgd (*editor,
2610                                     _("No audio files were ready for cleanup"),
2611                                     true,
2612                                     Gtk::MESSAGE_INFO,
2613                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2614                 msgd.set_secondary_text (_("If this seems suprising, \n\
2615 check for any existing snapshots.\n\
2616 These may still include regions that\n\
2617 require some unused files to continue to exist."));
2618
2619                 msgd.run ();
2620                 return;
2621         }
2622
2623         ArdourDialog results (_("ardour: cleanup"), true, false);
2624
2625         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2626             CleanupResultsModelColumns() {
2627                     add (visible_name);
2628                     add (fullpath);
2629             }
2630             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2631             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2632         };
2633
2634
2635         CleanupResultsModelColumns results_columns;
2636         Glib::RefPtr<Gtk::ListStore> results_model;
2637         Gtk::TreeView results_display;
2638
2639         results_model = ListStore::create (results_columns);
2640         results_display.set_model (results_model);
2641         results_display.append_column (list_title, results_columns.visible_name);
2642
2643         results_display.set_name ("CleanupResultsList");
2644         results_display.set_headers_visible (true);
2645         results_display.set_headers_clickable (false);
2646         results_display.set_reorderable (false);
2647
2648         Gtk::ScrolledWindow list_scroller;
2649         Gtk::Label txt;
2650         Gtk::VBox dvbox;
2651         Gtk::HBox dhbox;  // the hbox for the image and text
2652         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2653         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2654
2655         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2656
2657         const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2658
2659
2660
2661
2662         /* subst:
2663            %1 - number of files removed
2664            %2 - location of "dead_sounds"
2665            %3 - size of files affected
2666            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2667         */
2668
2669         const char* bprefix;
2670
2671         if (rep.space < 1048576.0f) {
2672                 bprefix = X_("kilo");
2673         } else if (rep.space < 1048576.0f * 1000) {
2674                 bprefix = X_("mega");
2675         } else {
2676                 bprefix = X_("giga");
2677         }
2678
2679         if (removed > 1) {
2680                 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2681         } else {
2682                 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2683         }
2684
2685         dhbox.pack_start (*dimage, true, false, 5);
2686         dhbox.pack_start (txt, true, false, 5);
2687
2688         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2689                 TreeModel::Row row = *(results_model->append());
2690                 row[results_columns.visible_name] = *i;
2691                 row[results_columns.fullpath] = *i;
2692         }
2693
2694         list_scroller.add (results_display);
2695         list_scroller.set_size_request (-1, 150);
2696         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2697
2698         dvbox.pack_start (dhbox, true, false, 5);
2699         dvbox.pack_start (list_scroller, true, false, 5);
2700         ddhbox.pack_start (dvbox, true, false, 5);
2701
2702         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2703         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2704         results.set_default_response (RESPONSE_CLOSE);
2705         results.set_position (Gtk::WIN_POS_MOUSE);
2706
2707         results_display.show();
2708         list_scroller.show();
2709         txt.show();
2710         dvbox.show();
2711         dhbox.show();
2712         ddhbox.show();
2713         dimage->show();
2714
2715         //results.get_vbox()->show();
2716         results.set_resizable (false);
2717
2718         results.run ();
2719
2720 }
2721
2722 void
2723 ARDOUR_UI::cleanup ()
2724 {
2725         if (session == 0) {
2726                 /* shouldn't happen: menu item is insensitive */
2727                 return;
2728         }
2729
2730
2731         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2732                                 true,
2733                                 Gtk::MESSAGE_QUESTION,
2734                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2735
2736         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2737 ALL undo/redo information will be lost if you cleanup.\n\
2738 After cleanup, unused audio files will be moved to a \
2739 \"dead sounds\" location."));
2740
2741         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2742         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2743         checker.set_default_response (RESPONSE_CANCEL);
2744
2745         checker.set_name (_("CleanupDialog"));
2746         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2747         checker.set_position (Gtk::WIN_POS_MOUSE);
2748
2749         switch (checker.run()) {
2750         case RESPONSE_ACCEPT:
2751                 break;
2752         default:
2753                 return;
2754         }
2755
2756         Session::cleanup_report rep;
2757
2758         editor->prepare_for_cleanup ();
2759
2760         /* do not allow flush until a session is reloaded */
2761
2762         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2763         if (act) {
2764                 act->set_sensitive (false);
2765         }
2766
2767         if (session->cleanup_sources (rep)) {
2768                 editor->finish_cleanup ();
2769                 return;
2770         }
2771
2772         editor->finish_cleanup ();
2773
2774         checker.hide();
2775         display_cleanup_results (rep,
2776                                  _("cleaned files"),
2777                                  _("\
2778 The following %1 files were not in use and \n\
2779 have been moved to:\n\
2780 %2. \n\n\
2781 Flushing the wastebasket will \n\
2782 release an additional\n\
2783 %3 %4bytes of disk space.\n"),
2784                                  _("\
2785 The following file was not in use and \n        \
2786 has been moved to:\n                            \
2787 %2. \n\n\
2788 Flushing the wastebasket will \n\
2789 release an additional\n\
2790 %3 %4bytes of disk space.\n"
2791                                          ));
2792
2793 }
2794
2795 void
2796 ARDOUR_UI::flush_trash ()
2797 {
2798         if (session == 0) {
2799                 /* shouldn't happen: menu item is insensitive */
2800                 return;
2801         }
2802
2803         Session::cleanup_report rep;
2804
2805         if (session->cleanup_trash_sources (rep)) {
2806                 return;
2807         }
2808
2809         display_cleanup_results (rep,
2810                                  _("deleted file"),
2811                                  _("The following %1 files were deleted from\n\
2812 %2,\n\
2813 releasing %3 %4bytes of disk space"),
2814                                  _("The following file was deleted from\n\
2815 %2,\n\
2816 releasing %3 %4bytes of disk space"));
2817 }
2818
2819 void
2820 ARDOUR_UI::add_route (Gtk::Window* float_window)
2821 {
2822         int count;
2823
2824         if (!session) {
2825                 return;
2826         }
2827
2828         if (add_route_dialog == 0) {
2829                 add_route_dialog = new AddRouteDialog (*session);
2830                 if (float_window) {
2831                         add_route_dialog->set_transient_for (*float_window);
2832                 }
2833         }
2834
2835         if (add_route_dialog->is_visible()) {
2836                 /* we're already doing this */
2837                 return;
2838         }
2839
2840         ResponseType r = (ResponseType) add_route_dialog->run ();
2841
2842         add_route_dialog->hide();
2843
2844         switch (r) {
2845                 case RESPONSE_ACCEPT:
2846                         break;
2847                 default:
2848                         return;
2849                         break;
2850         }
2851
2852         if ((count = add_route_dialog->count()) <= 0) {
2853                 return;
2854         }
2855
2856         string template_path = add_route_dialog->track_template();
2857
2858         if (!template_path.empty()) {
2859                 session->new_route_from_template (count, template_path);
2860                 return;
2861         }
2862
2863         uint32_t input_chan = add_route_dialog->channels ();
2864         uint32_t output_chan;
2865         string name_template = add_route_dialog->name_template ();
2866         bool track = add_route_dialog->track ();
2867         RouteGroup* route_group = add_route_dialog->route_group ();
2868
2869         AutoConnectOption oac = Config->get_output_auto_connect();
2870
2871         if (oac & AutoConnectMaster) {
2872                 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2873         } else {
2874                 output_chan = input_chan;
2875         }
2876
2877         /* XXX do something with name template */
2878
2879         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2880                 if (track) {
2881                         session_add_midi_track (route_group, count);
2882                 } else  {
2883                         MessageDialog msg (*editor,
2884                                         _("Sorry, MIDI Busses are not supported at this time."));
2885                         msg.run ();
2886                         //session_add_midi_bus();
2887                 }
2888         } else {
2889                 if (track) {
2890                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
2891                 } else {
2892                         session_add_audio_bus (input_chan, output_chan, route_group, count);
2893                 }
2894         }
2895 }
2896
2897 XMLNode*
2898 ARDOUR_UI::mixer_settings () const
2899 {
2900         XMLNode* node = 0;
2901
2902         if (session) {
2903                 node = session->instant_xml(X_("Mixer"));
2904         } else {
2905                 node = Config->instant_xml(X_("Mixer"));
2906         }
2907
2908         if (!node) {
2909                 node = new XMLNode (X_("Mixer"));
2910         }
2911
2912         return node;
2913 }
2914
2915 XMLNode*
2916 ARDOUR_UI::editor_settings () const
2917 {
2918         XMLNode* node = 0;
2919
2920         if (session) {
2921                 node = session->instant_xml(X_("Editor"));
2922         } else {
2923                 node = Config->instant_xml(X_("Editor"));
2924         }
2925
2926         if (!node) {
2927                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2928                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2929                 }
2930         }
2931
2932         if (!node) {
2933                 node = new XMLNode (X_("Editor"));
2934         }
2935
2936         return node;
2937 }
2938
2939 XMLNode*
2940 ARDOUR_UI::keyboard_settings () const
2941 {
2942         XMLNode* node = 0;
2943
2944         node = Config->extra_xml(X_("Keyboard"));
2945
2946         if (!node) {
2947                 node = new XMLNode (X_("Keyboard"));
2948         }
2949         return node;
2950 }
2951
2952 void
2953 ARDOUR_UI::create_xrun_marker(nframes_t where)
2954 {
2955         editor->mouse_add_new_marker (where, false, true);
2956 }
2957
2958 void
2959 ARDOUR_UI::halt_on_xrun_message ()
2960 {
2961         MessageDialog msg (*editor,
2962                            _("Recording was stopped because your system could not keep up."));
2963         msg.run ();
2964 }
2965
2966 void
2967 ARDOUR_UI::xrun_handler(nframes_t where)
2968 {
2969         if (!session) {
2970                 return;
2971         }
2972
2973         ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2974
2975         if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2976                 create_xrun_marker(where);
2977         }
2978
2979         if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2980                 halt_on_xrun_message ();
2981         }
2982 }
2983
2984 void
2985 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2986 {
2987         time_t now;
2988         time (&now);
2989
2990         while (disk_buffer_stats.size() > 60) {
2991                 disk_buffer_stats.pop_front ();
2992         }
2993
2994         disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2995 }
2996
2997 void
2998 ARDOUR_UI::write_buffer_stats ()
2999 {
3000         struct tm tm;
3001         char buf[64];
3002
3003         char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
3004         int fd = mkstemp (tmplt);
3005         if (fd) {
3006                 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3007                 return;
3008         }
3009
3010         FILE* fout = fdopen (fd, "w");
3011         if (!fout) {
3012                 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), tmplt) << endl;
3013                 return;
3014         }
3015
3016         for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3017                 std::ostringstream ss;
3018                 localtime_r (&(*i).when, &tm);
3019                 strftime (buf, sizeof (buf), "%T", &tm);
3020                 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
3021         }
3022
3023         disk_buffer_stats.clear ();
3024
3025         fclose (fout);
3026         close (fd);
3027
3028         cerr << "Ardour buffering statistics can be found in: " << tmplt << endl;
3029         free (tmplt);
3030 }
3031
3032 void
3033 ARDOUR_UI::disk_overrun_handler ()
3034 {
3035         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3036
3037         write_buffer_stats ();
3038
3039         if (!have_disk_speed_dialog_displayed) {
3040                 have_disk_speed_dialog_displayed = true;
3041                 MessageDialog* msg = new MessageDialog (*editor, _("\
3042 The disk system on your computer\n\
3043 was not able to keep up with Ardour.\n\
3044 \n\
3045 Specifically, it failed to write data to disk\n\
3046 quickly enough to keep up with recording.\n"));
3047                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3048                 msg->show ();
3049         }
3050 }
3051
3052 void
3053 ARDOUR_UI::disk_underrun_handler ()
3054 {
3055         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3056
3057         write_buffer_stats ();
3058
3059         if (!have_disk_speed_dialog_displayed) {
3060                 have_disk_speed_dialog_displayed = true;
3061                 MessageDialog* msg = new MessageDialog (*editor,
3062                                    _("The disk system on your computer\n\
3063 was not able to keep up with Ardour.\n\
3064 \n\
3065 Specifically, it failed to read data from disk\n\
3066 quickly enough to keep up with playback.\n"));
3067                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3068                 msg->show ();
3069         }
3070 }
3071
3072 void
3073 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3074 {
3075         have_disk_speed_dialog_displayed = false;
3076         delete msg;
3077 }
3078
3079 void
3080 ARDOUR_UI::session_dialog (std::string msg)
3081 {
3082         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3083
3084         MessageDialog* d;
3085
3086         if (editor) {
3087                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3088         } else {
3089                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3090         }
3091
3092         d->show_all ();
3093         d->run ();
3094         delete d;
3095 }
3096
3097 int
3098 ARDOUR_UI::pending_state_dialog ()
3099 {
3100         HBox* hbox = new HBox();
3101         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3102         ArdourDialog dialog (_("Crash Recovery"), true);
3103         Label  message (_("\
3104 This session appears to have been in\n\
3105 middle of recording when ardour or\n\
3106 the computer was shutdown.\n\
3107 \n\
3108 Ardour can recover any captured audio for\n\
3109 you, or it can ignore it. Please decide\n\
3110 what you would like to do.\n"));
3111         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3112         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3113         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3114         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3115         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3116         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3117         dialog.set_default_response (RESPONSE_ACCEPT);
3118         dialog.set_position (WIN_POS_CENTER);
3119         message.show();
3120         image->show();
3121         hbox->show();
3122
3123         switch (dialog.run ()) {
3124         case RESPONSE_ACCEPT:
3125                 return 1;
3126         default:
3127                 return 0;
3128         }
3129 }
3130
3131 int
3132 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3133 {
3134         HBox* hbox = new HBox();
3135         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3136         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3137         Label  message (string_compose (_("\
3138 This session was created with a sample rate of %1 Hz\n\
3139 \n\
3140 The audioengine is currently running at %2 Hz\n"), desired, actual));
3141
3142         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3143         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3144         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3145         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3146         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3147         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3148         dialog.set_default_response (RESPONSE_ACCEPT);
3149         dialog.set_position (WIN_POS_CENTER);
3150         message.show();
3151         image->show();
3152         hbox->show();
3153
3154         switch (dialog.run ()) {
3155         case RESPONSE_ACCEPT:
3156                 return 0;
3157         default:
3158                 return 1;
3159         }
3160 }
3161
3162
3163 void
3164 ARDOUR_UI::disconnect_from_jack ()
3165 {
3166         if (engine) {
3167                 if( engine->disconnect_from_jack ()) {
3168                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3169                         msg.run ();
3170                 }
3171
3172                 update_sample_rate (0);
3173         }
3174 }
3175
3176 void
3177 ARDOUR_UI::reconnect_to_jack ()
3178 {
3179         if (engine) {
3180                 if (engine->reconnect_to_jack ()) {
3181                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3182                         msg.run ();
3183                 }
3184
3185                 update_sample_rate (0);
3186         }
3187 }
3188
3189 void
3190 ARDOUR_UI::use_config ()
3191 {
3192
3193         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3194         if (node) {
3195                 set_transport_controllable_state (*node);
3196         }
3197 }
3198
3199 void
3200 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3201 {
3202         if (Config->get_primary_clock_delta_edit_cursor()) {
3203                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3204         } else {
3205                 primary_clock.set (pos, 0, true);
3206         }
3207
3208         if (Config->get_secondary_clock_delta_edit_cursor()) {
3209                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3210         } else {
3211                 secondary_clock.set (pos);
3212         }
3213
3214         if (big_clock_window) {
3215                 big_clock.set (pos);
3216         }
3217 }
3218
3219 void
3220 ARDOUR_UI::record_state_changed ()
3221 {
3222         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3223
3224         if (!session || !big_clock_window) {
3225                 /* why bother - the clock isn't visible */
3226                 return;
3227         }
3228
3229         Session::RecordState const r = session->record_status ();
3230         bool const h = session->have_rec_enabled_diskstream ();
3231
3232         if (r == Session::Recording && h)  {
3233                 big_clock.set_widget_name ("BigClockRecording");
3234         } else {
3235                 big_clock.set_widget_name ("BigClockNonRecording");
3236         }
3237 }
3238
3239 bool
3240 ARDOUR_UI::first_idle ()
3241 {
3242         if (session) {
3243                 session->allow_auto_play (true);
3244         }
3245
3246         if (editor) {
3247                 editor->first_idle();
3248         }
3249
3250         Keyboard::set_can_save_keybindings (true);
3251         return false;
3252 }
3253
3254 void
3255 ARDOUR_UI::store_clock_modes ()
3256 {
3257         XMLNode* node = new XMLNode(X_("ClockModes"));
3258
3259         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3260                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3261         }
3262
3263         session->add_extra_xml (*node);
3264         session->set_dirty ();
3265 }
3266
3267
3268
3269 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3270         : Controllable (name), ui (u), type(tp)
3271 {
3272
3273 }
3274
3275 void
3276 ARDOUR_UI::TransportControllable::set_value (float val)
3277 {
3278         if (type == ShuttleControl) {
3279                 double fract;
3280
3281                 if (val == 0.5f) {
3282                         fract = 0.0;
3283                 } else {
3284                         if (val < 0.5f) {
3285                                 fract = -((0.5f - val)/0.5f);
3286                         } else {
3287                                 fract = ((val - 0.5f)/0.5f);
3288                         }
3289                 }
3290
3291                 ui.set_shuttle_fract (fract);
3292                 return;
3293         }
3294
3295         if (val < 0.5f) {
3296                 /* do nothing: these are radio-style actions */
3297                 return;
3298         }
3299
3300         const char *action = 0;
3301
3302         switch (type) {
3303         case Roll:
3304                 action = X_("Roll");
3305                 break;
3306         case Stop:
3307                 action = X_("Stop");
3308                 break;
3309         case GotoStart:
3310                 action = X_("Goto Start");
3311                 break;
3312         case GotoEnd:
3313                 action = X_("Goto End");
3314                 break;
3315         case AutoLoop:
3316                 action = X_("Loop");
3317                 break;
3318         case PlaySelection:
3319                 action = X_("Play Selection");
3320                 break;
3321         case RecordEnable:
3322                 action = X_("Record");
3323                 break;
3324         default:
3325                 break;
3326         }
3327
3328         if (action == 0) {
3329                 return;
3330         }
3331
3332         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3333
3334         if (act) {
3335                 act->activate ();
3336         }
3337 }
3338
3339 float
3340 ARDOUR_UI::TransportControllable::get_value (void) const
3341 {
3342         float val = 0.0f;
3343
3344         switch (type) {
3345         case Roll:
3346                 break;
3347         case Stop:
3348                 break;
3349         case GotoStart:
3350                 break;
3351         case GotoEnd:
3352                 break;
3353         case AutoLoop:
3354                 break;
3355         case PlaySelection:
3356                 break;
3357         case RecordEnable:
3358                 break;
3359         case ShuttleControl:
3360                 break;
3361         default:
3362                 break;
3363         }
3364
3365         return val;
3366 }
3367
3368 void
3369 ARDOUR_UI::TransportControllable::set_id (const string& str)
3370 {
3371         _id = str;
3372 }
3373
3374 void
3375 ARDOUR_UI::setup_profile ()
3376 {
3377         if (gdk_screen_width() < 1200) {
3378                 Profile->set_small_screen ();
3379         }
3380
3381
3382         if (getenv ("ARDOUR_SAE")) {
3383                 Profile->set_sae ();
3384                 Profile->set_single_package ();
3385         }
3386 }
3387