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