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