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