writable session patch, forward ported from 2.X
[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_prompt (_("Name of New Snapshot"));
1864         prompter.set_initial_text (timebuf);
1865         
1866         switch (prompter.run()) {
1867         case RESPONSE_ACCEPT:
1868         {
1869                 prompter.get_result (snapname);
1870
1871                 bool do_save = (snapname.length() != 0);
1872
1873                 vector<sys::path> p;
1874                 get_state_files_in_directory (session->session_directory().root_path(), p);
1875                 vector<string> n = get_file_names_no_extension (p);
1876                 if (find (n.begin(), n.end(), snapname) != n.end()) {
1877
1878                         ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
1879                         Label m (_("A snapshot already exists with that name.  Do you want to overwrite it?"));
1880                         confirm.get_vbox()->pack_start (m, true, true);
1881                         confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1882                         confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
1883                         confirm.show_all ();
1884                         switch (confirm.run()) {
1885                         case RESPONSE_CANCEL:
1886                                 do_save = false;
1887                         }
1888                 }
1889                 
1890                 if (do_save) {
1891                         save_state (snapname);
1892                 }
1893                 break;
1894         }
1895
1896         default:
1897                 break;
1898         }
1899 }
1900
1901 void
1902 ARDOUR_UI::save_state (const string & name)
1903 {
1904         (void) save_state_canfail (name);
1905 }
1906                 
1907 int
1908 ARDOUR_UI::save_state_canfail (string name)
1909 {
1910         if (session) {
1911                 int ret;
1912
1913                 if (name.length() == 0) {
1914                         name = session->snap_name();
1915                 }
1916
1917                 if ((ret = session->save_state (name)) != 0) {
1918                         return ret;
1919                 }
1920         }
1921         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1922         return 0;
1923 }
1924
1925 void
1926 ARDOUR_UI::primary_clock_value_changed ()
1927 {
1928         if (session) {
1929                 session->request_locate (primary_clock.current_time ());
1930         }
1931 }
1932
1933 void
1934 ARDOUR_UI::big_clock_value_changed ()
1935 {
1936         if (session) {
1937                 session->request_locate (big_clock.current_time ());
1938         }
1939 }
1940
1941 void
1942 ARDOUR_UI::secondary_clock_value_changed ()
1943 {
1944         if (session) {
1945                 session->request_locate (secondary_clock.current_time ());
1946         }
1947 }
1948
1949 void
1950 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1951 {
1952         if (session == 0) {
1953                 return;
1954         }
1955
1956         Session::RecordState const r = session->record_status ();
1957         bool const h = session->have_rec_enabled_diskstream ();
1958         
1959         if (r == Session::Enabled || (r == Session::Recording && !h)) {
1960                 if (onoff) {
1961                         rec_button.set_visual_state (2);
1962                 } else {
1963                         rec_button.set_visual_state (0);
1964                 }
1965         } else if (r == Session::Recording && h) {
1966                 rec_button.set_visual_state (1);
1967         } else {
1968                 rec_button.set_visual_state (0);
1969         }
1970 }
1971
1972 void
1973 ARDOUR_UI::save_template ()
1974
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_prompt (_("Name for mix template:"));
1985         prompter.set_initial_text(session->name() + _("-template"));
1986         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1987
1988         switch (prompter.run()) {
1989         case RESPONSE_ACCEPT:
1990                 prompter.get_result (name);
1991                 
1992                 if (name.length()) {
1993                         session->save_template (name);
1994                 }
1995                 break;
1996
1997         default:
1998                 break;
1999         }
2000 }
2001
2002 void
2003 ARDOUR_UI::edit_metadata ()
2004 {
2005         SessionMetadataEditor dialog;
2006         dialog.set_session (session);
2007         editor->ensure_float (dialog);
2008         dialog.run ();
2009 }
2010
2011 void
2012 ARDOUR_UI::import_metadata ()
2013 {
2014         SessionMetadataImporter dialog;
2015         dialog.set_session (session);
2016         editor->ensure_float (dialog);
2017         dialog.run ();
2018 }
2019
2020 void
2021 ARDOUR_UI::fontconfig_dialog ()
2022 {
2023 #ifdef GTKOSX
2024         /* X11 users will always have fontconfig info around, but new GTK-OSX users 
2025            may not and it can take a while to build it. Warn them.
2026         */
2027         
2028         Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
2029         
2030         if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
2031                 MessageDialog msg (*_startup,
2032                                    _("Welcome to Ardour.\n\n"
2033                                      "The program will take a bit longer to start up\n"
2034                                      "while the system fonts are checked.\n\n"
2035                                      "This will only be done once, and you will\n"
2036                                      "not see this message again\n"),
2037                                    true,
2038                                    Gtk::MESSAGE_INFO,
2039                                    Gtk::BUTTONS_OK);
2040                 pop_back_splash ();
2041                 msg.show_all ();
2042                 msg.present ();
2043                 msg.run ();
2044         }
2045 #endif
2046 }
2047
2048 void
2049 ARDOUR_UI::parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session)
2050 {
2051         existing_session = false;
2052
2053         if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_DIR)) {
2054                 session_path = cmdline_path;
2055                 existing_session = true;
2056         } else if (Glib::file_test (cmdline_path, Glib::FILE_TEST_IS_REGULAR)) {
2057                 session_path = Glib::path_get_dirname (string (cmdline_path));
2058                 existing_session = true;
2059         } else {
2060                 /* it doesn't exist, assume the best */
2061                 session_path = Glib::path_get_dirname (string (cmdline_path));
2062         }
2063         
2064         session_name = basename_nosuffix (string (cmdline_path));
2065 }
2066
2067 int
2068 ARDOUR_UI::load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session)
2069 {
2070         /* when this is called, the backend audio system must be running */
2071
2072         /* the main idea here is to deal with the fact that a cmdline argument for the session
2073            can be interpreted in different ways - it could be a directory or a file, and before
2074            we load, we need to know both the session directory and the snapshot (statefile) within it
2075            that we are supposed to use.
2076         */
2077
2078         if (session_name.length() == 0 || session_path.length() == 0) {
2079                 return false;
2080         }
2081         
2082         if (Glib::file_test (session_path, Glib::FILE_TEST_IS_DIR)) {
2083
2084                 Glib::ustring predicted_session_file;
2085                 
2086                 predicted_session_file = session_path;
2087                 predicted_session_file += '/';
2088                 predicted_session_file += session_name;
2089                 predicted_session_file += ARDOUR::statefile_suffix;
2090                 
2091                 if (Glib::file_test (predicted_session_file, Glib::FILE_TEST_EXISTS)) {
2092                         existing_session = true;
2093                 }
2094                 
2095         } else if (Glib::file_test (session_path, Glib::FILE_TEST_EXISTS)) {
2096                 
2097                 if (session_path.find (ARDOUR::statefile_suffix) == session_path.length() - 7) {
2098                         /* existing .ardour file */
2099                         existing_session = true;
2100                 }
2101
2102         } else {
2103                 existing_session = false;
2104         }
2105         
2106         /* lets just try to load it */
2107         
2108         if (create_engine ()) {
2109                 backend_audio_error (false, _startup);
2110                 return -1;
2111         }
2112         
2113         return load_session (session_path, session_name);
2114 }
2115
2116 bool
2117 ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path)
2118 {
2119         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
2120         
2121         MessageDialog msg (str,
2122                            false,
2123                            Gtk::MESSAGE_WARNING,
2124                            Gtk::BUTTONS_YES_NO,
2125                            true);
2126         
2127         
2128         msg.set_name (X_("CleanupDialog"));
2129         msg.set_wmclass (X_("existing_session"), "Ardour");
2130         msg.set_position (Gtk::WIN_POS_MOUSE);
2131         pop_back_splash ();
2132
2133         switch (msg.run()) {
2134         case RESPONSE_YES:
2135                 return true;
2136                 break;
2137         }
2138         return false;
2139 }
2140
2141 int
2142 ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
2143 {
2144         
2145         uint32_t cchns;
2146         uint32_t mchns;
2147         AutoConnectOption iconnect;
2148         AutoConnectOption oconnect;
2149         uint32_t nphysin;
2150         uint32_t nphysout;
2151         
2152         if (Profile->get_sae()) {
2153                 
2154                 cchns = 0;
2155                 mchns = 2;
2156                 iconnect = AutoConnectPhysical;
2157                 oconnect = AutoConnectMaster;
2158                 nphysin = 0; // use all available
2159                 nphysout = 0; // use all available
2160                 
2161         } else {
2162                 
2163                 /* get settings from advanced section of NSD */
2164                 
2165                 if (_startup->create_control_bus()) {
2166                         cchns = (uint32_t) _startup->control_channel_count();
2167                 } else {
2168                         cchns = 0;
2169                 }
2170                 
2171                 if (_startup->create_master_bus()) {
2172                         mchns = (uint32_t) _startup->master_channel_count();
2173                 } else {
2174                         mchns = 0;
2175                 }
2176                 
2177                 if (_startup->connect_inputs()) {
2178                         iconnect = AutoConnectPhysical;
2179                 } else {
2180                         iconnect = AutoConnectOption (0);
2181                 }
2182                 
2183                 /// @todo some minor tweaks.
2184                 
2185                 if (_startup->connect_outs_to_master()) {
2186                         oconnect = AutoConnectMaster;
2187                 } else if (_startup->connect_outs_to_physical()) {
2188                         oconnect = AutoConnectPhysical;
2189                 } else {
2190                         oconnect = AutoConnectOption (0);
2191                 } 
2192                 
2193                 nphysin = (uint32_t) _startup->input_limit_count();
2194                 nphysout = (uint32_t) _startup->output_limit_count();
2195         }
2196         
2197         if (build_session (session_path,
2198                            session_name,
2199                            cchns,
2200                            mchns,
2201                            iconnect,
2202                            oconnect,
2203                            nphysin,
2204                            nphysout, 
2205                            engine->frame_rate() * 60 * 5)) {
2206                 
2207                 return -1;
2208         }
2209
2210         return 0;
2211 }
2212
2213 void
2214 ARDOUR_UI::idle_load (const Glib::ustring& path)
2215 {
2216         if (session) {
2217                 if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
2218                         /* /path/to/foo => /path/to/foo, foo */
2219                         load_session (path, basename_nosuffix (path));
2220                 } else {
2221                         /* /path/to/foo/foo.ardour => /path/to/foo, foo */
2222                         load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
2223                 }
2224         } else {
2225
2226                 ARDOUR_COMMAND_LINE::session_name = path;
2227
2228                 /*
2229                  * new_session_dialog doens't exist in A3
2230                  * Try to remove all references to it to
2231                  * see if it will compile.  NOTE: this will
2232                  * likely cause a runtime issue is my somewhat
2233                  * uneducated guess.
2234                  */
2235
2236                 //if (new_session_dialog) {
2237
2238
2239                         /* make it break out of Dialog::run() and
2240                            start again.
2241                          */
2242
2243                         //new_session_dialog->response (1);
2244                 //}
2245         }
2246 }
2247
2248 void
2249 ARDOUR_UI::end_loading_messages ()
2250 {
2251         // hide_splash ();
2252 }
2253
2254 void
2255 ARDOUR_UI::loading_message (const std::string& /*msg*/)
2256 {
2257         // show_splash ();
2258         // splash->message (msg);
2259         flush_pending ();
2260 }
2261
2262 int
2263 ARDOUR_UI::get_session_parameters (bool should_be_new)
2264 {
2265         Glib::ustring session_name;
2266         Glib::ustring session_path;
2267         Glib::ustring template_name;
2268         int ret = -1;
2269         bool likely_new = false;
2270
2271         while (ret != 0) {
2272
2273                 if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
2274
2275                         /* if they named a specific statefile, use it, otherwise they are 
2276                            just giving a session folder, and we want to use it as is
2277                            to find the session.
2278                         */
2279
2280                         if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
2281                                 session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
2282                         } else {
2283                                 session_path = ARDOUR_COMMAND_LINE::session_name;
2284                         }
2285
2286                         session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
2287
2288                 } else {
2289
2290                         run_startup (should_be_new);
2291                         
2292                         /* if we run the startup dialog again, offer more than just "new session" */
2293                         
2294                         should_be_new = false;
2295                         
2296                         session_name = _startup->session_name (likely_new);
2297                         
2298                         /* this shouldn't happen, but we catch it just in case it does */
2299                         
2300                         if (session_name.empty()) {
2301                                 break;
2302                         } 
2303                         if (_startup->use_session_template()) {
2304                                 template_name = _startup->session_template_name();
2305                                 _session_is_new = true;
2306                         } 
2307
2308
2309                         if (session_name[0] == '/' || 
2310                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
2311                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
2312                                 
2313                                 session_path = Glib::path_get_dirname (session_name);
2314                                 session_name = Glib::path_get_basename (session_name);
2315                                 
2316                         } else {
2317                                 
2318                                 session_path = _startup->session_folder();
2319                         }
2320                 }
2321
2322                 if (create_engine ()) {
2323                         break;
2324                 }
2325                 
2326                 if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
2327
2328                         if (likely_new) {
2329
2330                                 Glib::ustring existing = Glib::build_filename (session_path, session_name);
2331                                 
2332                                 if (!ask_about_loading_existing_session (existing)) {
2333                                         ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2334                                         continue;
2335                                 } 
2336                         } 
2337
2338                         _session_is_new = false;
2339
2340                 } else {
2341
2342                         if (!likely_new) {
2343                                 MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
2344                                 msg.run ();
2345                                 ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
2346                                 continue;
2347                         }
2348
2349                         _session_is_new = true;
2350                 }
2351
2352                 if (likely_new && template_name.empty()) {
2353                         
2354                         ret = build_session_from_nsd (session_path, session_name);
2355
2356                 } else {
2357
2358                         ret = load_session (session_path, session_name, template_name);
2359                 }
2360         }
2361         
2362         return ret;
2363 }       
2364
2365 void
2366 ARDOUR_UI::close_session()
2367 {
2368         if (!check_audioengine()) {
2369                 return;
2370         }
2371
2372         unload_session (true);
2373
2374         ARDOUR_COMMAND_LINE::session_name = "";
2375         get_session_parameters (false);
2376 }
2377
2378 int
2379 ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_name, Glib::ustring mix_template)
2380 {
2381         Session *new_session;
2382         int unload_status;
2383         int retval = -1;
2384
2385         session_loaded = false;
2386
2387         if (!check_audioengine()) {
2388                 return -1;
2389         }
2390
2391         unload_status = unload_session ();
2392
2393         if (unload_status < 0) {
2394                 goto out;
2395         } else if (unload_status > 0) {
2396                 retval = 0;
2397                 goto out;
2398         }
2399
2400         loading_message (_("Please wait while Ardour loads your session"));
2401
2402         try {
2403                 new_session = new Session (*engine, path, snap_name, mix_template);
2404         }
2405
2406         /* this one is special */
2407
2408         catch (AudioEngine::PortRegistrationFailure& err) {
2409
2410                 MessageDialog msg (err.what(),
2411                                    true,
2412                                    Gtk::MESSAGE_INFO,
2413                                    Gtk::BUTTONS_CLOSE);
2414                 
2415                 msg.set_title (_("Port Registration Error"));
2416                 msg.set_secondary_text (_("Click the Close button to try again."));
2417                 msg.set_position (Gtk::WIN_POS_CENTER);
2418                 pop_back_splash ();
2419                 msg.present ();
2420
2421                 int response = msg.run ();
2422
2423                 msg.hide ();
2424
2425                 switch (response) {
2426                 case RESPONSE_CANCEL:
2427                         exit (1);
2428                 default:
2429                         break;
2430                 }
2431                 goto out;
2432         }
2433
2434         catch (...) {
2435
2436                 MessageDialog msg (string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name),
2437                                    true,
2438                                    Gtk::MESSAGE_INFO,
2439                                    Gtk::BUTTONS_CLOSE);
2440                 
2441                 msg.set_title (_("Loading Error"));
2442                 msg.set_secondary_text (_("Click the Close button to try again."));
2443                 msg.set_position (Gtk::WIN_POS_CENTER);
2444                 pop_back_splash ();
2445                 msg.present ();
2446
2447                 int response = msg.run ();
2448
2449                 msg.hide ();
2450
2451                 switch (response) {
2452                 case RESPONSE_CANCEL:
2453                         exit (1);
2454                 default:
2455                         break;
2456                 }
2457                 goto out;
2458         }
2459
2460         connect_to_session (new_session);
2461
2462         session_loaded = true;
2463         
2464         goto_editor_window ();
2465
2466         if (session) {
2467                 session->set_clean ();
2468         }
2469
2470         flush_pending ();
2471         retval = 0;
2472
2473   out:
2474         return retval;
2475 }
2476
2477 int
2478 ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name, 
2479                           uint32_t control_channels,
2480                           uint32_t master_channels, 
2481                           AutoConnectOption input_connect,
2482                           AutoConnectOption output_connect,
2483                           uint32_t nphysin,
2484                           uint32_t nphysout,
2485                           nframes_t initial_length)
2486 {
2487         Session *new_session;
2488         int x;
2489
2490         if (!check_audioengine()) {
2491                 return -1;
2492         }
2493
2494         session_loaded = false;
2495
2496         x = unload_session ();
2497
2498         if (x < 0) {
2499                 return -1;
2500         } else if (x > 0) {
2501                 return 0;
2502         }
2503         
2504         _session_is_new = true;
2505
2506         try {
2507                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2508                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2509         }
2510
2511         catch (...) {
2512
2513                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2514                 pop_back_splash ();
2515                 msg.run ();
2516                 return -1;
2517         }
2518
2519         connect_to_session (new_session);
2520
2521         session_loaded = true;
2522
2523         new_session->save_state(new_session->name());
2524
2525         return 0;
2526 }
2527
2528 void
2529 ARDOUR_UI::show ()
2530 {
2531         if (editor) {
2532                 editor->show_window ();
2533                 
2534                 if (!shown_flag) {
2535                         editor->present ();
2536                 }
2537
2538                 shown_flag = true;
2539         }
2540 }
2541
2542 void
2543 ARDOUR_UI::show_about ()
2544 {
2545         if (about == 0) {
2546                 about = new About;
2547                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2548         }
2549
2550         about->show_all ();
2551 }
2552
2553 void
2554 ARDOUR_UI::hide_about ()
2555 {
2556         if (about) {
2557                 about->get_window()->set_cursor ();
2558                 about->hide ();
2559         }
2560 }
2561
2562 void
2563 ARDOUR_UI::about_signal_response (int /*response*/)
2564 {
2565         hide_about();
2566 }
2567
2568 void
2569 ARDOUR_UI::show_splash ()
2570 {
2571         if (splash == 0) {
2572                 try {
2573                         splash = new Splash;
2574                 } catch (...) {
2575                         return;
2576                 }
2577         }
2578
2579         splash->show ();
2580         splash->present ();
2581         splash->queue_draw ();
2582         splash->get_window()->process_updates (true);
2583         flush_pending ();
2584 }
2585
2586 void
2587 ARDOUR_UI::hide_splash ()
2588 {
2589         if (splash) {
2590                 splash->hide();
2591         }
2592 }
2593
2594 void
2595 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, 
2596                                     const string& plural_msg, const string& singular_msg)
2597 {
2598         size_t removed;
2599
2600         removed = rep.paths.size();
2601
2602         if (removed == 0) {
2603                 MessageDialog msgd (*editor,
2604                                     _("No audio files were ready for cleanup"), 
2605                                     true,
2606                                     Gtk::MESSAGE_INFO,
2607                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2608                 msgd.set_secondary_text (_("If this seems suprising, \n\
2609 check for any existing snapshots.\n\
2610 These may still include regions that\n\
2611 require some unused files to continue to exist."));
2612         
2613                 msgd.run ();
2614                 return;
2615         } 
2616
2617         ArdourDialog results (_("ardour: cleanup"), true, false);
2618         
2619         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2620             CleanupResultsModelColumns() { 
2621                     add (visible_name);
2622                     add (fullpath);
2623             }
2624             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2625             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2626         };
2627
2628         
2629         CleanupResultsModelColumns results_columns;
2630         Glib::RefPtr<Gtk::ListStore> results_model;
2631         Gtk::TreeView results_display;
2632         
2633         results_model = ListStore::create (results_columns);
2634         results_display.set_model (results_model);
2635         results_display.append_column (list_title, results_columns.visible_name);
2636
2637         results_display.set_name ("CleanupResultsList");
2638         results_display.set_headers_visible (true);
2639         results_display.set_headers_clickable (false);
2640         results_display.set_reorderable (false);
2641
2642         Gtk::ScrolledWindow list_scroller;
2643         Gtk::Label txt;
2644         Gtk::VBox dvbox;
2645         Gtk::HBox dhbox;  // the hbox for the image and text
2646         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2647         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2648
2649         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2650
2651         const string dead_sound_directory = session->session_directory().dead_sound_path().to_string();
2652
2653
2654
2655
2656         /* subst:
2657            %1 - number of files removed
2658            %2 - location of "dead_sounds"
2659            %3 - size of files affected
2660            %4 - prefix for "bytes" to produce sensible results (e.g. mega, kilo, giga)
2661         */
2662
2663         const char* bprefix;
2664
2665         if (rep.space < 1048576.0f) {
2666                 bprefix = X_("kilo");
2667         } else if (rep.space < 1048576.0f * 1000) {
2668                 bprefix = X_("mega");
2669         } else {
2670                 bprefix = X_("giga");
2671         }
2672
2673         if (removed > 1) {
2674                 txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2675         } else {
2676                 txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
2677         }
2678
2679         dhbox.pack_start (*dimage, true, false, 5);
2680         dhbox.pack_start (txt, true, false, 5);
2681
2682         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2683                 TreeModel::Row row = *(results_model->append());
2684                 row[results_columns.visible_name] = *i;
2685                 row[results_columns.fullpath] = *i;
2686         }
2687         
2688         list_scroller.add (results_display);
2689         list_scroller.set_size_request (-1, 150);
2690         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2691
2692         dvbox.pack_start (dhbox, true, false, 5);
2693         dvbox.pack_start (list_scroller, true, false, 5);
2694         ddhbox.pack_start (dvbox, true, false, 5);
2695
2696         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2697         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2698         results.set_default_response (RESPONSE_CLOSE);
2699         results.set_position (Gtk::WIN_POS_MOUSE);
2700
2701         results_display.show();
2702         list_scroller.show();
2703         txt.show();
2704         dvbox.show();
2705         dhbox.show();
2706         ddhbox.show();
2707         dimage->show();
2708
2709         //results.get_vbox()->show();
2710         results.set_resizable (false);
2711
2712         results.run ();
2713
2714 }
2715
2716 void
2717 ARDOUR_UI::cleanup ()
2718 {
2719         if (session == 0) {
2720                 /* shouldn't happen: menu item is insensitive */
2721                 return;
2722         }
2723
2724
2725         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2726                                 true,
2727                                 Gtk::MESSAGE_QUESTION,
2728                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2729
2730         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2731 ALL undo/redo information will be lost if you cleanup.\n\
2732 After cleanup, unused audio files will be moved to a \
2733 \"dead sounds\" location."));
2734         
2735         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2736         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2737         checker.set_default_response (RESPONSE_CANCEL);
2738
2739         checker.set_name (_("CleanupDialog"));
2740         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2741         checker.set_position (Gtk::WIN_POS_MOUSE);
2742
2743         switch (checker.run()) {
2744         case RESPONSE_ACCEPT:
2745                 break;
2746         default:
2747                 return;
2748         }
2749
2750         Session::cleanup_report rep;
2751
2752         editor->prepare_for_cleanup ();
2753
2754         /* do not allow flush until a session is reloaded */
2755
2756         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2757         if (act) {
2758                 act->set_sensitive (false);
2759         }
2760
2761         if (session->cleanup_sources (rep)) {
2762                 editor->finish_cleanup ();
2763                 return;
2764         }
2765         
2766         editor->finish_cleanup ();
2767
2768         checker.hide();
2769         display_cleanup_results (rep, 
2770                                  _("cleaned files"),
2771                                  _("\
2772 The following %1 files were not in use and \n\
2773 have been moved to:\n\
2774 %2. \n\n\
2775 Flushing the wastebasket will \n\
2776 release an additional\n\
2777 %3 %4bytes of disk space.\n"),
2778                                  _("\
2779 The following file was not in use and \n        \
2780 has been moved to:\n                            \
2781 %2. \n\n\
2782 Flushing the wastebasket will \n\
2783 release an additional\n\
2784 %3 %4bytes of disk space.\n"
2785                                          ));
2786
2787 }
2788
2789 void
2790 ARDOUR_UI::flush_trash ()
2791 {
2792         if (session == 0) {
2793                 /* shouldn't happen: menu item is insensitive */
2794                 return;
2795         }
2796
2797         Session::cleanup_report rep;
2798
2799         if (session->cleanup_trash_sources (rep)) {
2800                 return;
2801         }
2802
2803         display_cleanup_results (rep, 
2804                                  _("deleted file"),
2805                                  _("The following %1 files were deleted from\n\
2806 %2,\n\
2807 releasing %3 %4bytes of disk space"),
2808                                  _("The following file was deleted from\n\
2809 %2,\n\
2810 releasing %3 %4bytes of disk space"));
2811 }
2812
2813 void
2814 ARDOUR_UI::add_route (Gtk::Window* float_window)
2815 {
2816         int count;
2817
2818         if (!session) {
2819                 return;
2820         }
2821
2822         if (add_route_dialog == 0) {
2823                 add_route_dialog = new AddRouteDialog (*session);
2824                 if (float_window) {
2825                         add_route_dialog->set_transient_for (*float_window);
2826                 }
2827         }
2828
2829         if (add_route_dialog->is_visible()) {
2830                 /* we're already doing this */
2831                 return;
2832         }
2833
2834         ResponseType r = (ResponseType) add_route_dialog->run ();
2835
2836         add_route_dialog->hide();
2837
2838         switch (r) {
2839                 case RESPONSE_ACCEPT:
2840                         break;
2841                 default:
2842                         return;
2843                         break;
2844         }
2845
2846         if ((count = add_route_dialog->count()) <= 0) {
2847                 return;
2848         }
2849
2850         string template_path = add_route_dialog->track_template();
2851         
2852         if (!template_path.empty()) {
2853                 session->new_route_from_template (count, template_path);
2854                 return;
2855         }
2856
2857         uint32_t input_chan = add_route_dialog->channels ();
2858         uint32_t output_chan;
2859         string name_template = add_route_dialog->name_template ();
2860         bool track = add_route_dialog->track ();
2861         RouteGroup* route_group = add_route_dialog->route_group ();
2862
2863         AutoConnectOption oac = Config->get_output_auto_connect();
2864
2865         if (oac & AutoConnectMaster) {
2866                 output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
2867         } else {
2868                 output_chan = input_chan;
2869         }
2870
2871         /* XXX do something with name template */
2872         
2873         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2874                 if (track) {
2875                         session_add_midi_track (route_group, count);
2876                 } else  {
2877                         MessageDialog msg (*editor,
2878                                         _("Sorry, MIDI Busses are not supported at this time."));
2879                         msg.run ();
2880                         //session_add_midi_bus();
2881                 }
2882         } else { 
2883                 if (track) {
2884                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), route_group, count);
2885                 } else {
2886                         session_add_audio_bus (input_chan, output_chan, route_group, count);
2887                 }
2888         }
2889 }
2890
2891 XMLNode*
2892 ARDOUR_UI::mixer_settings () const
2893 {
2894         XMLNode* node = 0;
2895
2896         if (session) {
2897                 node = session->instant_xml(X_("Mixer"));
2898         } else {
2899                 node = Config->instant_xml(X_("Mixer"));
2900         }
2901
2902         if (!node) {
2903                 node = new XMLNode (X_("Mixer"));
2904         }
2905
2906         return node;
2907 }
2908
2909 XMLNode*
2910 ARDOUR_UI::editor_settings () const
2911 {
2912         XMLNode* node = 0;
2913
2914         if (session) {
2915                 node = session->instant_xml(X_("Editor"));
2916         } else {
2917                 node = Config->instant_xml(X_("Editor"));
2918         }
2919         
2920         if (!node) {
2921                 if (getenv("ARDOUR_INSTANT_XML_PATH")) {
2922                         node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
2923                 }
2924         }
2925
2926         if (!node) {
2927                 node = new XMLNode (X_("Editor"));
2928         }
2929
2930         return node;
2931 }
2932
2933 XMLNode*
2934 ARDOUR_UI::keyboard_settings () const
2935 {
2936         XMLNode* node = 0;
2937
2938         node = Config->extra_xml(X_("Keyboard"));
2939         
2940         if (!node) {
2941                 node = new XMLNode (X_("Keyboard"));
2942         }
2943         return node;
2944 }
2945
2946 void
2947 ARDOUR_UI::create_xrun_marker(nframes_t where)
2948 {
2949         editor->mouse_add_new_marker (where, false, true);
2950 }
2951
2952 void
2953 ARDOUR_UI::halt_on_xrun_message ()
2954 {
2955         MessageDialog msg (*editor,
2956                            _("Recording was stopped because your system could not keep up."));
2957         msg.run ();
2958 }
2959
2960 void
2961 ARDOUR_UI::xrun_handler(nframes_t where)
2962 {
2963         if (!session) {
2964                 return;
2965         }
2966
2967         ENSURE_GUI_THREAD (bind(mem_fun(*this, &ARDOUR_UI::xrun_handler), where));
2968
2969         if (session && Config->get_create_xrun_marker() && session->actively_recording()) {
2970                 create_xrun_marker(where);
2971         }
2972
2973         if (session && Config->get_stop_recording_on_xrun() && session->actively_recording()) {
2974                 halt_on_xrun_message ();
2975         }
2976 }
2977
2978 void
2979 ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
2980 {
2981         time_t now;
2982         time (&now);
2983
2984         while (disk_buffer_stats.size() > 60) {
2985                 disk_buffer_stats.pop_front ();
2986         }
2987
2988         disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
2989 }
2990
2991 void
2992 ARDOUR_UI::write_buffer_stats ()
2993 {
2994         struct tm tm;
2995         char buf[64];
2996
2997         char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
2998         int fd = mkstemp (tmplt);
2999         if (fd) {
3000                 cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
3001                 return;
3002         }
3003
3004         FILE* fout = fdopen (fd, "w");
3005         if (!fout) {
3006                 cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), tmplt) << endl;
3007                 return;
3008         }
3009
3010         for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
3011                 std::ostringstream ss;
3012                 localtime_r (&(*i).when, &tm);
3013                 strftime (buf, sizeof (buf), "%T", &tm);
3014                 fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
3015         }
3016         
3017         disk_buffer_stats.clear ();
3018
3019         fclose (fout);
3020         close (fd);
3021
3022         cerr << "Ardour buffering statistics can be found in: " << tmplt << endl;
3023         free (tmplt);
3024 }
3025
3026 void
3027 ARDOUR_UI::disk_overrun_handler ()
3028 {
3029         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
3030
3031         write_buffer_stats ();
3032
3033         if (!have_disk_speed_dialog_displayed) {
3034                 have_disk_speed_dialog_displayed = true;
3035                 MessageDialog* msg = new MessageDialog (*editor, _("\
3036 The disk system on your computer\n\
3037 was not able to keep up with Ardour.\n\
3038 \n\
3039 Specifically, it failed to write data to disk\n\
3040 quickly enough to keep up with recording.\n"));
3041                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3042                 msg->show ();
3043         }
3044 }
3045
3046 void
3047 ARDOUR_UI::disk_underrun_handler ()
3048 {
3049         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3050
3051         write_buffer_stats ();
3052
3053         if (!have_disk_speed_dialog_displayed) {
3054                 have_disk_speed_dialog_displayed = true;
3055                 MessageDialog* msg = new MessageDialog (*editor,
3056                                    _("The disk system on your computer\n\
3057 was not able to keep up with Ardour.\n\
3058 \n\
3059 Specifically, it failed to read data from disk\n\
3060 quickly enough to keep up with playback.\n"));
3061                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
3062                 msg->show ();
3063         } 
3064 }
3065
3066 void
3067 ARDOUR_UI::disk_speed_dialog_gone (int /*ignored_response*/, MessageDialog* msg)
3068 {
3069         have_disk_speed_dialog_displayed = false;
3070         delete msg;
3071 }
3072
3073 void
3074 ARDOUR_UI::session_dialog (std::string msg)
3075 {
3076         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::session_dialog), msg));
3077         
3078         MessageDialog* d;
3079
3080         if (editor) {
3081                 d = new MessageDialog (*editor, msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3082         } else {
3083                 d = new MessageDialog (msg, false, MESSAGE_INFO, BUTTONS_OK, true);
3084         }
3085
3086         d->show_all ();
3087         d->run ();
3088         delete d;
3089 }       
3090
3091 int
3092 ARDOUR_UI::pending_state_dialog ()
3093 {
3094         HBox* hbox = new HBox();
3095         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3096         ArdourDialog dialog (_("Crash Recovery"), true);
3097         Label  message (_("\
3098 This session appears to have been in\n\
3099 middle of recording when ardour or\n\
3100 the computer was shutdown.\n\
3101 \n\
3102 Ardour can recover any captured audio for\n\
3103 you, or it can ignore it. Please decide\n\
3104 what you would like to do.\n"));
3105         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3106         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3107         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3108         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3109         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3110         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3111         dialog.set_default_response (RESPONSE_ACCEPT);
3112         dialog.set_position (WIN_POS_CENTER);
3113         message.show();
3114         image->show();
3115         hbox->show();
3116
3117         switch (dialog.run ()) {
3118         case RESPONSE_ACCEPT:
3119                 return 1;
3120         default:
3121                 return 0;
3122         }
3123 }
3124
3125 int
3126 ARDOUR_UI::sr_mismatch_dialog (nframes_t desired, nframes_t actual)
3127 {
3128         HBox* hbox = new HBox();
3129         Image* image = new Image (Stock::DIALOG_QUESTION, ICON_SIZE_DIALOG);
3130         ArdourDialog dialog (_("Sample Rate Mismatch"), true);
3131         Label  message (string_compose (_("\
3132 This session was created with a sample rate of %1 Hz\n\
3133 \n\
3134 The audioengine is currently running at %2 Hz\n"), desired, actual));
3135
3136         image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
3137         hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
3138         hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
3139         dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
3140         dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
3141         dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
3142         dialog.set_default_response (RESPONSE_ACCEPT);
3143         dialog.set_position (WIN_POS_CENTER);
3144         message.show();
3145         image->show();
3146         hbox->show();
3147
3148         switch (dialog.run ()) {
3149         case RESPONSE_ACCEPT:
3150                 return 0;
3151         default:
3152                 return 1;
3153         }
3154 }
3155
3156         
3157 void
3158 ARDOUR_UI::disconnect_from_jack ()
3159 {
3160         if (engine) {
3161                 if( engine->disconnect_from_jack ()) {
3162                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
3163                         msg.run ();
3164                 }
3165
3166                 update_sample_rate (0);
3167         }
3168 }
3169
3170 void
3171 ARDOUR_UI::reconnect_to_jack ()
3172 {
3173         if (engine) {
3174                 if (engine->reconnect_to_jack ()) {
3175                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
3176                         msg.run ();
3177                 }
3178
3179                 update_sample_rate (0);
3180         }
3181 }
3182
3183 void
3184 ARDOUR_UI::use_config ()
3185 {
3186
3187         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
3188         if (node) {
3189                 set_transport_controllable_state (*node);
3190         }
3191 }
3192
3193 void
3194 ARDOUR_UI::update_transport_clocks (nframes_t pos)
3195 {
3196         if (Config->get_primary_clock_delta_edit_cursor()) {
3197                 primary_clock.set (pos, false, editor->get_preferred_edit_position(), 1);
3198         } else {
3199                 primary_clock.set (pos, 0, true);
3200         }
3201
3202         if (Config->get_secondary_clock_delta_edit_cursor()) {
3203                 secondary_clock.set (pos, false, editor->get_preferred_edit_position(), 2);
3204         } else {
3205                 secondary_clock.set (pos);
3206         }
3207
3208         if (big_clock_window) {
3209                 big_clock.set (pos);
3210         }
3211 }
3212
3213 void
3214 ARDOUR_UI::record_state_changed ()
3215 {
3216         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
3217
3218         if (!session || !big_clock_window) {
3219                 /* why bother - the clock isn't visible */
3220                 return;
3221         }
3222
3223         Session::RecordState const r = session->record_status ();
3224         bool const h = session->have_rec_enabled_diskstream ();
3225         
3226         if (r == Session::Recording && h)  {
3227                 big_clock.set_widget_name ("BigClockRecording");
3228         } else {
3229                 big_clock.set_widget_name ("BigClockNonRecording");
3230         }
3231 }
3232
3233 bool
3234 ARDOUR_UI::first_idle ()
3235 {
3236         if (session) {
3237                 session->allow_auto_play (true);
3238         }
3239
3240         if (editor) {
3241                 editor->first_idle();
3242         }
3243
3244         Keyboard::set_can_save_keybindings (true);
3245         return false;
3246 }
3247
3248 void
3249 ARDOUR_UI::store_clock_modes ()
3250 {
3251         XMLNode* node = new XMLNode(X_("ClockModes"));
3252
3253         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
3254                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
3255         }
3256
3257         session->add_extra_xml (*node);
3258         session->set_dirty ();
3259 }
3260
3261
3262                 
3263 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
3264         : Controllable (name), ui (u), type(tp)
3265 {
3266         
3267 }
3268
3269 void
3270 ARDOUR_UI::TransportControllable::set_value (float val)
3271 {
3272         if (type == ShuttleControl) {
3273                 double fract;
3274
3275                 if (val == 0.5f) {
3276                         fract = 0.0;
3277                 } else {
3278                         if (val < 0.5f) {
3279                                 fract = -((0.5f - val)/0.5f);
3280                         } else {
3281                                 fract = ((val - 0.5f)/0.5f);
3282                         }
3283                 }
3284                 
3285                 ui.set_shuttle_fract (fract);
3286                 return;
3287         }
3288
3289         if (val < 0.5f) {
3290                 /* do nothing: these are radio-style actions */
3291                 return;
3292         }
3293
3294         const char *action = 0;
3295
3296         switch (type) {
3297         case Roll:
3298                 action = X_("Roll");
3299                 break;
3300         case Stop:
3301                 action = X_("Stop");
3302                 break;
3303         case GotoStart:
3304                 action = X_("Goto Start");
3305                 break;
3306         case GotoEnd:
3307                 action = X_("Goto End");
3308                 break;
3309         case AutoLoop:
3310                 action = X_("Loop");
3311                 break;
3312         case PlaySelection:
3313                 action = X_("Play Selection");
3314                 break;
3315         case RecordEnable:
3316                 action = X_("Record");
3317                 break;
3318         default:
3319                 break;
3320         }
3321
3322         if (action == 0) {
3323                 return;
3324         }
3325
3326         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
3327
3328         if (act) {
3329                 act->activate ();
3330         }
3331 }
3332
3333 float
3334 ARDOUR_UI::TransportControllable::get_value (void) const
3335 {
3336         float val = 0.0f;
3337         
3338         switch (type) {
3339         case Roll:
3340                 break;
3341         case Stop:
3342                 break;
3343         case GotoStart:
3344                 break;
3345         case GotoEnd:
3346                 break;
3347         case AutoLoop:
3348                 break;
3349         case PlaySelection:
3350                 break;
3351         case RecordEnable:
3352                 break;
3353         case ShuttleControl:
3354                 break;
3355         default:
3356                 break;
3357         }
3358
3359         return val;
3360 }
3361
3362 void
3363 ARDOUR_UI::TransportControllable::set_id (const string& str)
3364 {
3365         _id = str;
3366 }
3367
3368 void
3369 ARDOUR_UI::setup_profile ()
3370 {
3371         if (gdk_screen_width() < 1200) {
3372                 Profile->set_small_screen ();
3373         }
3374
3375
3376         if (getenv ("ARDOUR_SAE")) {
3377                 Profile->set_sae ();
3378                 Profile->set_single_package ();
3379         }
3380 }
3381