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