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