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