Merged with trunk R1736.
[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> 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 void
955 ARDOUR_UI::open_session ()
956 {
957         /* popup selector window */
958
959         if (open_session_selector == 0) {
960
961                 /* ardour sessions are folders */
962
963                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
964                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
965                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
966
967                 FileFilter session_filter;
968                 session_filter.add_pattern ("*.ardour");
969                 session_filter.set_name (_("Ardour sessions"));
970                 open_session_selector->add_filter (session_filter);
971                 open_session_selector->set_filter (session_filter);
972         }
973
974         int response = open_session_selector->run();
975         open_session_selector->hide ();
976
977         switch (response) {
978         case RESPONSE_ACCEPT:
979                 break;
980         default:
981                 open_session_selector->hide();
982                 return;
983         }
984
985         open_session_selector->hide();
986         string session_path = open_session_selector->get_filename();
987         string path, name;
988         bool isnew;
989
990         if (session_path.length() > 0) {
991                 if (Session::find_session (session_path, path, name, isnew) == 0) {
992                         _session_is_new = isnew;
993                         load_session (path, name);
994                 }
995         }
996 }
997
998
999 void
1000 ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
1001 {
1002         list<boost::shared_ptr<MidiTrack> > tracks;
1003
1004         if (session == 0) {
1005                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1006                 return;
1007         }
1008
1009         try { 
1010                 if (disk) {
1011
1012                         tracks = session->new_midi_track (ARDOUR::Normal, how_many);
1013
1014                         if (tracks.size() != how_many) {
1015                                 if (how_many == 1) {
1016                                         error << _("could not create a new midi track") << endmsg;
1017                                 } else {
1018                                         error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
1019                                 }
1020                         }
1021                 } /*else {
1022                         if ((route = session->new_midi_route ()) == 0) {
1023                                 error << _("could not create new midi bus") << endmsg;
1024                         }
1025                 }*/
1026         }
1027
1028         catch (...) {
1029                 MessageDialog msg (*editor, 
1030                                    _("There are insufficient JACK ports available\n\
1031 to create a new track or bus.\n\
1032 You should save Ardour, exit and\n\
1033 restart JACK with more ports."));
1034                 msg.run ();
1035         }
1036 }
1037
1038
1039 void
1040 ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
1041 {
1042         list<boost::shared_ptr<AudioTrack> > tracks;
1043         Session::RouteList routes;
1044
1045         if (session == 0) {
1046                 warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
1047                 return;
1048         }
1049
1050         try { 
1051                 if (track) {
1052                         tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
1053
1054                         if (tracks.size() != how_many) {
1055                                 if (how_many == 1) {
1056                                         error << _("could not create a new audio track") << endmsg;
1057                                 } else {
1058                                         error << string_compose (_("could only create %1 of %2 new audio %3"), 
1059                                                                  tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
1060                                 }
1061                         }
1062
1063                 } else {
1064
1065                         routes = session->new_audio_route (input_channels, output_channels, how_many);
1066
1067                         if (routes.size() != how_many) {
1068                                 if (how_many == 1) {
1069                                         error << _("could not create a new audio track") << endmsg;
1070                                 } else {
1071                                         error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
1072                                 }
1073                         }
1074                 }
1075                 
1076 #if CONTROLOUTS
1077                 if (need_control_room_outs) {
1078                         pan_t pans[2];
1079                         
1080                         pans[0] = 0.5;
1081                         pans[1] = 0.5;
1082                         
1083                         route->set_stereo_control_outs (control_lr_channels);
1084                         route->control_outs()->set_stereo_pan (pans, this);
1085                 }
1086 #endif /* CONTROLOUTS */
1087         }
1088
1089         catch (...) {
1090                 cerr << "About to complain about JACK\n";
1091                 MessageDialog msg (*editor, 
1092                                    _("There are insufficient JACK ports available\n\
1093 to create a new track or bus.\n\
1094 You should save Ardour, exit and\n\
1095 restart JACK with more ports."));
1096                 msg.run ();
1097         }
1098 }
1099
1100 void
1101 ARDOUR_UI::do_transport_locate (nframes_t new_position)
1102 {
1103         nframes_t _preroll = 0;
1104
1105         if (session) {
1106                 // XXX CONFIG_CHANGE FIX - requires AnyTime handling
1107                 // _preroll = session->convert_to_frames_at (new_position, Config->get_preroll());
1108
1109                 if (new_position > _preroll) {
1110                         new_position -= _preroll;
1111                 } else {
1112                         new_position = 0;
1113                 }
1114
1115                 session->request_locate (new_position);
1116         }
1117 }
1118
1119 void
1120 ARDOUR_UI::transport_goto_start ()
1121 {
1122         if (session) {
1123                 session->goto_start();
1124
1125                 
1126                 /* force displayed area in editor to start no matter
1127                    what "follow playhead" setting is.
1128                 */
1129                 
1130                 if (editor) {
1131                         editor->reset_x_origin (session->current_start_frame());
1132                 }
1133         }
1134 }
1135
1136 void
1137 ARDOUR_UI::transport_goto_zero ()
1138 {
1139         if (session) {
1140                 session->request_locate (0);
1141
1142                 
1143                 /* force displayed area in editor to start no matter
1144                    what "follow playhead" setting is.
1145                 */
1146                 
1147                 if (editor) {
1148                         editor->reset_x_origin (0);
1149                 }
1150         }
1151 }
1152
1153 void
1154 ARDOUR_UI::transport_goto_end ()
1155 {
1156         if (session) {
1157                 nframes_t frame = session->current_end_frame();
1158                 session->request_locate (frame);
1159
1160                 /* force displayed area in editor to start no matter
1161                    what "follow playhead" setting is.
1162                 */
1163                 
1164                 if (editor) {
1165                         editor->reset_x_origin (frame);
1166                 }
1167         }
1168 }
1169
1170 void
1171 ARDOUR_UI::transport_stop ()
1172 {
1173         if (!session) {
1174                 return;
1175         }
1176
1177         if (session->is_auditioning()) {
1178                 session->cancel_audition ();
1179                 return;
1180         }
1181         
1182         if (session->get_play_loop ()) {
1183                 session->request_play_loop (false);
1184         }
1185         
1186         session->request_stop ();
1187 }
1188
1189 void
1190 ARDOUR_UI::transport_stop_and_forget_capture ()
1191 {
1192         if (session) {
1193                 session->request_stop (true);
1194         }
1195 }
1196
1197 void
1198 ARDOUR_UI::remove_last_capture()
1199 {
1200         if (editor) {
1201                 editor->remove_last_capture();
1202         }
1203 }
1204
1205 void
1206 ARDOUR_UI::transport_record ()
1207 {
1208         if (session) {
1209                 switch (session->record_status()) {
1210                 case Session::Disabled:
1211                         if (session->ntracks() == 0) {
1212                                 MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."));
1213                                 msg.run ();
1214                                 return;
1215                         }
1216                         session->maybe_enable_record ();
1217                         break;
1218                 case Session::Recording:
1219                 case Session::Enabled:
1220                         session->disable_record (true);
1221                 }
1222         }
1223 }
1224
1225 void
1226 ARDOUR_UI::transport_roll ()
1227 {
1228         bool rolling;
1229
1230         if (!session) {
1231                 return;
1232         }
1233
1234         rolling = session->transport_rolling ();
1235
1236         if (session->get_play_loop()) {
1237                 session->request_play_loop (false);
1238                 auto_loop_button.set_visual_state (1);
1239                 roll_button.set_visual_state (1);
1240         } else if (session->get_play_range ()) {
1241                 session->request_play_range (false);
1242                 play_selection_button.set_visual_state (0);
1243         } else if (rolling) {
1244                 session->request_locate (session->last_transport_start(), true);
1245         }
1246
1247         session->request_transport_speed (1.0f);
1248 }
1249
1250 void
1251 ARDOUR_UI::transport_loop()
1252 {
1253         if (session) {
1254                 if (session->get_play_loop()) {
1255                         if (session->transport_rolling()) {
1256                                 Location * looploc = session->locations()->auto_loop_location();
1257                                 if (looploc) {
1258                                         session->request_locate (looploc->start(), true);
1259                                 }
1260                         }
1261                 }
1262                 else {
1263                         session->request_play_loop (true);
1264                 }
1265         }
1266 }
1267
1268 void
1269 ARDOUR_UI::transport_play_selection ()
1270 {
1271         if (!session) {
1272                 return;
1273         }
1274
1275         if (!session->get_play_range()) {
1276                 session->request_stop ();
1277         }
1278
1279         editor->play_selection ();
1280 }
1281
1282 void
1283 ARDOUR_UI::transport_rewind (int option)
1284 {
1285         float current_transport_speed;
1286  
1287         if (session) {
1288                 current_transport_speed = session->transport_speed();
1289                 
1290                 if (current_transport_speed >= 0.0f) {
1291                         switch (option) {
1292                         case 0:
1293                                 session->request_transport_speed (-1.0f);
1294                                 break;
1295                         case 1:
1296                                 session->request_transport_speed (-4.0f);
1297                                 break;
1298                         case -1:
1299                                 session->request_transport_speed (-0.5f);
1300                                 break;
1301                         }
1302                 } else {
1303                         /* speed up */
1304                         session->request_transport_speed (current_transport_speed * 1.5f);
1305                 }
1306         }
1307 }
1308
1309 void
1310 ARDOUR_UI::transport_forward (int option)
1311 {
1312         float current_transport_speed;
1313         
1314         if (session) {
1315                 current_transport_speed = session->transport_speed();
1316                 
1317                 if (current_transport_speed <= 0.0f) {
1318                         switch (option) {
1319                         case 0:
1320                                 session->request_transport_speed (1.0f);
1321                                 break;
1322                         case 1:
1323                                 session->request_transport_speed (4.0f);
1324                                 break;
1325                         case -1:
1326                                 session->request_transport_speed (0.5f);
1327                                 break;
1328                         }
1329                 } else {
1330                         /* speed up */
1331                         session->request_transport_speed (current_transport_speed * 1.5f);
1332                 }
1333         }
1334 }
1335
1336 void
1337 ARDOUR_UI::toggle_record_enable (uint32_t dstream)
1338 {
1339         if (session == 0) {
1340                 return;
1341         }
1342
1343         boost::shared_ptr<Route> r;
1344         
1345         if ((r = session->route_by_remote_id (dstream)) != 0) {
1346
1347                 Track* t;
1348
1349                 if ((t = dynamic_cast<Track*>(r.get())) != 0) {
1350                         t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
1351                 }
1352         }
1353         if (session == 0) {
1354                 return;
1355         }
1356 }
1357
1358 void
1359 ARDOUR_UI::queue_transport_change ()
1360 {
1361         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
1362 }
1363
1364 void
1365 ARDOUR_UI::map_transport_state ()
1366 {
1367         float sp = session->transport_speed();
1368
1369         if (sp == 1.0f) {
1370                 transport_rolling ();
1371         } else if (sp < 0.0f) {
1372                 transport_rewinding ();
1373         } else if (sp > 0.0f) {
1374                 transport_forwarding ();
1375         } else {
1376                 transport_stopped ();
1377         }
1378 }
1379
1380 void
1381 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1382 {
1383         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1384                 (int) adj.get_value()].c_str());
1385 }
1386
1387 void
1388 ARDOUR_UI::engine_stopped ()
1389 {
1390         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1391         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1392         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1393 }
1394
1395 void
1396 ARDOUR_UI::engine_running ()
1397 {
1398         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1399         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1400         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1401
1402         Glib::RefPtr<Action> action;
1403         char* action_name = 0;
1404
1405         switch (engine->frames_per_cycle()) {
1406         case 32:
1407                 action_name = X_("JACKLatency32");
1408                 break;
1409         case 64:
1410                 action_name = X_("JACKLatency64");
1411                 break;
1412         case 128:
1413                 action_name = X_("JACKLatency128");
1414                 break;
1415         case 512:
1416                 action_name = X_("JACKLatency512");
1417                 break;
1418         case 1024:
1419                 action_name = X_("JACKLatency1024");
1420                 break;
1421         case 2048:
1422                 action_name = X_("JACKLatency2048");
1423                 break;
1424         case 4096:
1425                 action_name = X_("JACKLatency4096");
1426                 break;
1427         case 8192:
1428                 action_name = X_("JACKLatency8192");
1429                 break;
1430         default:
1431                 /* XXX can we do anything useful ? */
1432                 break;
1433         }
1434
1435         if (action_name) {
1436
1437                 action = ActionManager::get_action (X_("JACK"), action_name);
1438                 
1439                 if (action) {
1440                         Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
1441                         ract->set_active ();
1442                 }
1443         }
1444 }
1445
1446 void
1447 ARDOUR_UI::engine_halted ()
1448 {
1449         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1450
1451         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1452         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1453
1454         update_sample_rate (0);
1455
1456         MessageDialog msg (*editor, 
1457                            _("\
1458 JACK has either been shutdown or it\n\
1459 disconnected Ardour because Ardour\n\
1460 was not fast enough. You can save the\n\
1461 session and/or try to reconnect to JACK ."));
1462         msg.run ();
1463 }
1464
1465 int32_t
1466 ARDOUR_UI::do_engine_start ()
1467 {
1468         try { 
1469                 engine->start();
1470         }
1471
1472         catch (...) {
1473                 engine->stop ();
1474                 error << _("Unable to start the session running")
1475                       << endmsg;
1476                 unload_session ();
1477                 return -2;
1478         }
1479         
1480         return 0;
1481 }
1482
1483 gint
1484 ARDOUR_UI::start_engine ()
1485 {
1486         if (do_engine_start () == 0) {
1487                 if (session && _session_is_new) {
1488                         /* we need to retain initial visual 
1489                            settings for a new session 
1490                         */
1491                         session->save_state ("");
1492                 }
1493         }
1494
1495         return FALSE;
1496 }
1497
1498 void
1499 ARDOUR_UI::update_clocks ()
1500 {
1501         if (!editor || !editor->dragging_playhead()) {
1502                 Clock (session->audible_frame()); /* EMIT_SIGNAL */
1503         }
1504 }
1505
1506 void
1507 ARDOUR_UI::start_clocking ()
1508 {
1509         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1510 }
1511
1512 void
1513 ARDOUR_UI::stop_clocking ()
1514 {
1515         clock_signal_connection.disconnect ();
1516 }
1517         
1518 void
1519 ARDOUR_UI::toggle_clocking ()
1520 {
1521 #if 0
1522         if (clock_button.get_active()) {
1523                 start_clocking ();
1524         } else {
1525                 stop_clocking ();
1526         }
1527 #endif
1528 }
1529
1530 gint
1531 ARDOUR_UI::_blink (void *arg)
1532
1533 {
1534         ((ARDOUR_UI *) arg)->blink ();
1535         return TRUE;
1536 }
1537
1538 void
1539 ARDOUR_UI::blink ()
1540 {
1541         Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1542 }
1543
1544 void
1545 ARDOUR_UI::start_blinking ()
1546 {
1547         /* Start the blink signal. Everybody with a blinking widget
1548            uses Blink to drive the widget's state.
1549         */
1550
1551         if (blink_timeout_tag < 0) {
1552                 blink_on = false;       
1553                 blink_timeout_tag = g_timeout_add (240, _blink, this);
1554         }
1555 }
1556
1557 void
1558 ARDOUR_UI::stop_blinking ()
1559 {
1560         if (blink_timeout_tag >= 0) {
1561                 g_source_remove (blink_timeout_tag);
1562                 blink_timeout_tag = -1;
1563         }
1564 }
1565
1566 void
1567 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
1568                           string& buf,
1569                           IO& io,
1570                           bool in)
1571 {
1572         if (in) {
1573                 if (io.n_inputs().get_total() == 0) {
1574                         buf = _("none");
1575                         return;
1576                 }
1577                 
1578                 /* XXX we're not handling multiple ports yet. */
1579
1580                 const char **connections = io.input(0)->get_connections();
1581                 
1582                 if (connections == 0 || connections[0] == '\0') {
1583                         buf = _("off");
1584                 } else {
1585                         buf = connections[0];
1586                 }
1587
1588                 free (connections);
1589
1590         } else {
1591
1592                 if (io.n_outputs().get_total() == 0) {
1593                         buf = _("none");
1594                         return;
1595                 }
1596                 
1597                 /* XXX we're not handling multiple ports yet. */
1598
1599                 const char **connections = io.output(0)->get_connections();
1600                 
1601                 if (connections == 0 || connections[0] == '\0') {
1602                         buf = _("off");
1603                 } else {
1604                         buf = connections[0];
1605                 }
1606
1607                 free (connections);
1608         }
1609 }
1610
1611 /** Ask the user for the name of a new shapshot and then take it.
1612  */
1613 void
1614 ARDOUR_UI::snapshot_session ()
1615 {
1616         ArdourPrompter prompter (true);
1617         string snapname;
1618         char timebuf[128];
1619         time_t n;
1620         struct tm local_time;
1621
1622         time (&n);
1623         localtime_r (&n, &local_time);
1624         strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
1625
1626         prompter.set_name ("Prompter");
1627         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1628         prompter.set_prompt (_("Name of New Snapshot"));
1629         prompter.set_initial_text (timebuf);
1630         
1631         switch (prompter.run()) {
1632         case RESPONSE_ACCEPT:
1633                 prompter.get_result (snapname);
1634                 if (snapname.length()){
1635                         save_state (snapname);
1636                 }
1637                 break;
1638
1639         default:
1640                 break;
1641         }
1642 }
1643
1644 void
1645 ARDOUR_UI::save_state (const string & name)
1646 {
1647         (void) save_state_canfail (name);
1648 }
1649                 
1650 int
1651 ARDOUR_UI::save_state_canfail (string name)
1652 {
1653         if (session) {
1654                 int ret;
1655
1656                 if (name.length() == 0) {
1657                         name = session->snap_name();
1658                 }
1659
1660                 if ((ret = session->save_state (name)) != 0) {
1661                         return ret;
1662                 }
1663         }
1664         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1665         return 0;
1666 }
1667
1668 void
1669 ARDOUR_UI::restore_state (string name)
1670 {
1671         if (session) {
1672                 if (name.length() == 0) {
1673                         name = session->name();
1674                 }
1675                 session->restore_state (name);
1676         }
1677 }
1678
1679 void
1680 ARDOUR_UI::primary_clock_value_changed ()
1681 {
1682         if (session) {
1683                 session->request_locate (primary_clock.current_time ());
1684         }
1685 }
1686
1687 void
1688 ARDOUR_UI::secondary_clock_value_changed ()
1689 {
1690         if (session) {
1691                 session->request_locate (secondary_clock.current_time ());
1692         }
1693 }
1694
1695 void
1696 ARDOUR_UI::rec_enable_button_blink (bool onoff, AudioDiskstream *dstream, Widget *w)
1697 {
1698         if (session && dstream && dstream->record_enabled()) {
1699
1700                 Session::RecordState rs;
1701                 
1702                 rs = session->record_status ();
1703
1704                 switch (rs) {
1705                 case Session::Disabled:
1706                 case Session::Enabled:
1707                         if (w->get_state() != STATE_SELECTED) {
1708                                 w->set_state (STATE_SELECTED);
1709                         }
1710                         break;
1711
1712                 case Session::Recording:
1713                         if (w->get_state() != STATE_ACTIVE) {
1714                                 w->set_state (STATE_ACTIVE);
1715                         }
1716                         break;
1717                 }
1718
1719         } else {
1720                 if (w->get_state() != STATE_NORMAL) {
1721                         w->set_state (STATE_NORMAL);
1722                 }
1723         }
1724 }
1725
1726 void
1727 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1728 {
1729         if (session == 0) {
1730                 return;
1731         }
1732         
1733         switch (session->record_status()) {
1734         case Session::Enabled:
1735                 if (onoff) {
1736                         rec_button.set_visual_state (2);
1737                 } else {
1738                         rec_button.set_visual_state (0);
1739                 }
1740                 break;
1741
1742         case Session::Recording:
1743                 rec_button.set_visual_state (1);
1744                 break;
1745
1746         default:
1747                 rec_button.set_visual_state (0);
1748                 break;
1749         }
1750 }
1751
1752 gint
1753 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1754 {
1755         window->hide();
1756         Gtk::Main::quit ();
1757         return TRUE;
1758 }
1759
1760 void
1761 ARDOUR_UI::save_template ()
1762
1763 {
1764         ArdourPrompter prompter (true);
1765         string name;
1766
1767         prompter.set_name (X_("Prompter"));
1768         prompter.set_prompt (_("Name for mix template:"));
1769         prompter.set_initial_text(session->name() + _("-template"));
1770         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1771
1772         switch (prompter.run()) {
1773         case RESPONSE_ACCEPT:
1774                 prompter.get_result (name);
1775                 
1776                 if (name.length()) {
1777                         session->save_template (name);
1778                 }
1779                 break;
1780
1781         default:
1782                 break;
1783         }
1784 }
1785
1786 bool
1787 ARDOUR_UI::new_session (std::string predetermined_path)
1788 {
1789         string session_name;
1790         string session_path;
1791
1792         if (!engine->connected()) {
1793                 MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1794                 msg.run ();
1795                 return false;
1796         }
1797
1798         int response = Gtk::RESPONSE_NONE;
1799
1800         new_session_dialog->set_modal(true);
1801         new_session_dialog->set_name (predetermined_path);
1802         new_session_dialog->reset_recent();
1803         new_session_dialog->show();
1804
1805         do {
1806                 response = new_session_dialog->run ();
1807
1808                 if (!engine->connected()) {
1809                         new_session_dialog->hide ();
1810                         MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
1811                         msg.run ();
1812                         return false;
1813                 }
1814                 
1815                 _session_is_new = false;
1816
1817                 if (response == Gtk::RESPONSE_CANCEL || response == Gtk::RESPONSE_DELETE_EVENT) {
1818
1819                         if (!session) {
1820                                 quit();
1821                         }
1822                         new_session_dialog->hide ();
1823                         return false;
1824
1825                 } else if (response == Gtk::RESPONSE_NONE) {
1826
1827                         /* Clear was pressed */
1828                         new_session_dialog->reset();
1829
1830                 } else if (response == Gtk::RESPONSE_YES) {
1831
1832                         /* YES  == OPEN, but there's no enum for that */
1833
1834                         session_name = new_session_dialog->session_name();
1835                         
1836                         if (session_name.empty()) {
1837                                 response = Gtk::RESPONSE_NONE;
1838                                 continue;
1839                         } 
1840
1841                         if (session_name[0] == '/' || 
1842                             (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1843                             (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1844                                 load_session (Glib::path_get_dirname (session_name), session_name);
1845                         } else {
1846                                 session_path = new_session_dialog->session_folder();
1847                                 load_session (session_path, session_name);
1848                         }
1849                         
1850                 } else if (response == Gtk::RESPONSE_OK) {
1851
1852                         session_name = new_session_dialog->session_name();
1853                         
1854                         if (new_session_dialog->get_current_page() == 1) {
1855                   
1856                                 /* XXX this is a bit of a hack.. 
1857                                    i really want the new sesion dialog to return RESPONSE_YES
1858                                    if we're on page 1 (the load page)
1859                                    Unfortunately i can't see how atm.. 
1860                                 */
1861                                 
1862                                 if (session_name.empty()) {
1863                                         response = Gtk::RESPONSE_NONE;
1864                                         continue;
1865                                 } 
1866                                 
1867                                 if (session_name[0] == '/' || 
1868                                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1869                                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1870                                         load_session (Glib::path_get_dirname (session_name), session_name);
1871                                 } else {
1872                                         session_path = new_session_dialog->session_folder();
1873                                         load_session (session_path, session_name);
1874                                 }
1875                         
1876                         } else {
1877
1878                                 if (session_name.empty()) {
1879                                         response = Gtk::RESPONSE_NONE;
1880                                         continue;
1881                                 } 
1882
1883                                 if (session_name[0] == '/' || 
1884                                     (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
1885                                     (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
1886
1887                                         session_path = Glib::path_get_dirname (session_name);
1888                                         session_name = Glib::path_get_basename (session_name);
1889
1890                                 } else {
1891
1892                                         session_path = new_session_dialog->session_folder();
1893
1894                                 }
1895                                 
1896                                 //XXX This is needed because session constructor wants a 
1897                                 //non-existant path. hopefully this will be fixed at some point.
1898                                 
1899                                 session_path = Glib::build_filename (session_path, session_name);
1900                                                 
1901                                 if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
1902
1903                                         Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
1904
1905                                         MessageDialog msg (str,
1906                                                            false,
1907                                                            Gtk::MESSAGE_WARNING,
1908                                                            Gtk::BUTTONS_YES_NO,
1909                                                            true);
1910
1911
1912                                         msg.set_name (X_("CleanupDialog"));
1913                                         msg.set_wmclass (X_("existing_session"), "Ardour");
1914                                         msg.set_position (Gtk::WIN_POS_MOUSE);
1915                                         
1916                                         switch (msg.run()) {
1917                                         case RESPONSE_YES:
1918                                                 load_session (session_path, session_name);
1919                                                 goto done;
1920                                                 break;
1921                                         default:
1922                                                 response = RESPONSE_NONE;
1923                                                 new_session_dialog->reset ();
1924                                                 continue;
1925                                         }
1926                                 }
1927
1928                                 _session_is_new = true;
1929
1930                                 std::string template_name = new_session_dialog->session_template_name();
1931                                                 
1932                                 if (new_session_dialog->use_session_template()) {
1933                                                         
1934                                         load_session (session_path, session_name, &template_name);
1935                           
1936                                 } else {
1937                                                         
1938                                         uint32_t cchns;
1939                                         uint32_t mchns;
1940                                         AutoConnectOption iconnect;
1941                                         AutoConnectOption oconnect;
1942                                                         
1943                                         if (new_session_dialog->create_control_bus()) {
1944                                                 cchns = (uint32_t) new_session_dialog->control_channel_count();
1945                                         } else {
1946                                                 cchns = 0;
1947                                         }
1948                                                         
1949                                         if (new_session_dialog->create_master_bus()) {
1950                                                 mchns = (uint32_t) new_session_dialog->master_channel_count();
1951                                         } else {
1952                                                 mchns = 0;
1953                                         }
1954                                                         
1955                                         if (new_session_dialog->connect_inputs()) {
1956                                                 iconnect = AutoConnectPhysical;
1957                                         } else {
1958                                                 iconnect = AutoConnectOption (0);
1959                                         }
1960                                                         
1961                                         /// @todo some minor tweaks.
1962                                                         
1963                                         if (new_session_dialog->connect_outs_to_master()) {
1964                                                 oconnect = AutoConnectMaster;
1965                                         } else if (new_session_dialog->connect_outs_to_physical()) {
1966                                                 oconnect = AutoConnectPhysical;
1967                                         } else {
1968                                                 oconnect = AutoConnectOption (0);
1969                                         } 
1970                                                         
1971                                         uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
1972                                         uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
1973                                                         
1974                                         if (build_session (session_path,
1975                                                            session_name,
1976                                                            cchns,
1977                                                            mchns,
1978                                                            iconnect,
1979                                                            oconnect,
1980                                                            nphysin,
1981                                                            nphysout, 
1982                                                            engine->frame_rate() * 60 * 5)) {
1983
1984                                                 response = Gtk::RESPONSE_NONE;
1985                                                 new_session_dialog->reset ();
1986                                                 continue;
1987                                         }
1988                                 }
1989                         }
1990                 }
1991                 
1992         } while (response == Gtk::RESPONSE_NONE);
1993
1994   done:
1995         show();
1996         new_session_dialog->get_window()->set_cursor();
1997         new_session_dialog->hide();
1998         return true;
1999 }
2000
2001 void
2002 ARDOUR_UI::close_session()
2003 {
2004         unload_session();
2005         new_session ();
2006 }
2007
2008 int
2009 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2010 {
2011         Session *new_session;
2012         int x;
2013         session_loaded = false;
2014         
2015         x = unload_session ();
2016
2017         if (x < 0) {
2018                 return -1;
2019         } else if (x > 0) {
2020                 return 0;
2021         }
2022
2023         /* if it already exists, we must have write access */
2024
2025         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2026                 MessageDialog msg (*editor, _("You do not have write access to this session.\n"
2027                                               "This prevents the session from being loaded."));
2028                 msg.run ();
2029                 return -1;
2030         }
2031
2032         try {
2033                 new_session = new Session (*engine, path, snap_name, mix_template);
2034         }
2035
2036         catch (...) {
2037
2038                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2039                 return -1;
2040         }
2041
2042         connect_to_session (new_session);
2043
2044         Config->set_current_owner (ConfigVariableBase::Interface);
2045
2046         session_loaded = true;
2047         
2048         goto_editor_window ();
2049
2050         if (session) {
2051                 session->set_clean ();
2052         }
2053
2054         editor->edit_cursor_position (true);
2055         return 0;
2056 }
2057
2058 int
2059 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
2060                           uint32_t control_channels,
2061                           uint32_t master_channels, 
2062                           AutoConnectOption input_connect,
2063                           AutoConnectOption output_connect,
2064                           uint32_t nphysin,
2065                           uint32_t nphysout,
2066                           nframes_t initial_length)
2067 {
2068         Session *new_session;
2069         int x;
2070
2071         session_loaded = false;
2072         x = unload_session ();
2073         if (x < 0) {
2074                 return -1;
2075         } else if (x > 0) {
2076                 return 0;
2077         }
2078         
2079         _session_is_new = true;
2080
2081         try {
2082                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2083                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2084         }
2085
2086         catch (...) {
2087
2088                 MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
2089                 msg.run ();
2090                 return -1;
2091         }
2092
2093         connect_to_session (new_session);
2094
2095         session_loaded = true;
2096         return 0;
2097 }
2098
2099 void
2100 ARDOUR_UI::show ()
2101 {
2102         if (editor) {
2103                 editor->show_window ();
2104                 
2105                 if (!shown_flag) {
2106                         editor->present ();
2107                 }
2108
2109                 shown_flag = true;
2110         }
2111 }
2112
2113 void
2114 ARDOUR_UI::show_splash ()
2115 {
2116         if (about == 0) {
2117                 about = new About();
2118                 about->signal_response().connect(mem_fun (*this, &ARDOUR_UI::about_signal_response) );
2119         }
2120         about->present();
2121         flush_pending ();
2122 }
2123
2124 void
2125 ARDOUR_UI::about_signal_response(int response)
2126 {
2127         hide_splash();
2128 }
2129
2130 void
2131 ARDOUR_UI::hide_splash ()
2132 {
2133         if (about) {
2134                 about->get_window()->set_cursor ();
2135                 about->hide();
2136         }
2137 }
2138
2139 void
2140 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2141 {
2142         size_t removed;
2143
2144         removed = rep.paths.size();
2145
2146         if (removed == 0) {
2147                 MessageDialog msgd (*editor,
2148                                     _("No audio files were ready for cleanup"), 
2149                                     true,
2150                                     Gtk::MESSAGE_INFO,
2151                                     (Gtk::ButtonsType)(Gtk::BUTTONS_OK)  );
2152                 msgd.set_secondary_text (_("If this seems suprising, \n\
2153 check for any existing snapshots.\n\
2154 These may still include regions that\n\
2155 require some unused files to continue to exist."));
2156         
2157                 msgd.run ();
2158                 return;
2159         } 
2160
2161         ArdourDialog results (_("ardour: cleanup"), true, false);
2162         
2163         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2164             CleanupResultsModelColumns() { 
2165                     add (visible_name);
2166                     add (fullpath);
2167             }
2168             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2169             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2170         };
2171
2172         
2173         CleanupResultsModelColumns results_columns;
2174         Glib::RefPtr<Gtk::ListStore> results_model;
2175         Gtk::TreeView results_display;
2176         
2177         results_model = ListStore::create (results_columns);
2178         results_display.set_model (results_model);
2179         results_display.append_column (list_title, results_columns.visible_name);
2180
2181         results_display.set_name ("CleanupResultsList");
2182         results_display.set_headers_visible (true);
2183         results_display.set_headers_clickable (false);
2184         results_display.set_reorderable (false);
2185
2186         Gtk::ScrolledWindow list_scroller;
2187         Gtk::Label txt;
2188         Gtk::VBox dvbox;
2189         Gtk::HBox dhbox;  // the hbox for the image and text
2190         Gtk::HBox ddhbox; // the hbox we eventually pack into the dialog's vbox
2191         Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_INFO,  Gtk::ICON_SIZE_DIALOG));
2192
2193         dimage->set_alignment(ALIGN_LEFT, ALIGN_TOP);
2194
2195         if (rep.space < 1048576.0f) {
2196                 if (removed > 1) {
2197                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2198                 } else {
2199                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
2200                 }
2201         } else {
2202                 if (removed > 1) {
2203                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2204                 } else {
2205                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
2206                 }
2207         }
2208
2209         dhbox.pack_start (*dimage, true, false, 5);
2210         dhbox.pack_start (txt, true, false, 5);
2211
2212         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2213                 TreeModel::Row row = *(results_model->append());
2214                 row[results_columns.visible_name] = *i;
2215                 row[results_columns.fullpath] = *i;
2216         }
2217         
2218         list_scroller.add (results_display);
2219         list_scroller.set_size_request (-1, 150);
2220         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2221
2222         dvbox.pack_start (dhbox, true, false, 5);
2223         dvbox.pack_start (list_scroller, true, false, 5);
2224         ddhbox.pack_start (dvbox, true, false, 5);
2225
2226         results.get_vbox()->pack_start (ddhbox, true, false, 5);
2227         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
2228         results.set_default_response (RESPONSE_CLOSE);
2229         results.set_position (Gtk::WIN_POS_MOUSE);
2230         results.show_all_children ();
2231         results.set_resizable (false);
2232
2233         results.run ();
2234
2235 }
2236
2237 void
2238 ARDOUR_UI::cleanup ()
2239 {
2240         if (session == 0) {
2241                 /* shouldn't happen: menu item is insensitive */
2242                 return;
2243         }
2244
2245
2246         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2247                                 true,
2248                                 Gtk::MESSAGE_QUESTION,
2249                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2250
2251         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2252 ALL undo/redo information will be lost if you cleanup.\n\
2253 After cleanup, unused audio files will be moved to a \
2254 \"dead sounds\" location."));
2255         
2256         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2257         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2258         checker.set_default_response (RESPONSE_CANCEL);
2259
2260         checker.set_name (_("CleanupDialog"));
2261         checker.set_wmclass (X_("ardour_cleanup"), "Ardour");
2262         checker.set_position (Gtk::WIN_POS_MOUSE);
2263
2264         switch (checker.run()) {
2265         case RESPONSE_ACCEPT:
2266                 break;
2267         default:
2268                 return;
2269         }
2270
2271         Session::cleanup_report rep;
2272
2273         editor->prepare_for_cleanup ();
2274
2275         /* do not allow flush until a session is reloaded */
2276
2277         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
2278         if (act) {
2279                 act->set_sensitive (false);
2280         }
2281
2282         if (session->cleanup_sources (rep)) {
2283                 return;
2284         }
2285
2286         checker.hide();
2287         display_cleanup_results (rep, 
2288                                  _("cleaned files"),
2289                                  _("\
2290 The following %1 %2 not in use and \n\
2291 have been moved to:\n\
2292 %3. \n\n\
2293 Flushing the wastebasket will \n\
2294 release an additional\n\
2295 %4 %5bytes of disk space.\n"
2296                                          ));
2297
2298
2299
2300 }
2301
2302 void
2303 ARDOUR_UI::flush_trash ()
2304 {
2305         if (session == 0) {
2306                 /* shouldn't happen: menu item is insensitive */
2307                 return;
2308         }
2309
2310         Session::cleanup_report rep;
2311
2312         if (session->cleanup_trash_sources (rep)) {
2313                 return;
2314         }
2315
2316         display_cleanup_results (rep, 
2317                                  _("deleted file"),
2318                                  _("The following %1 %2 deleted from\n\
2319 %3,\n\
2320 releasing %4 %5bytes of disk space"));
2321 }
2322
2323 void
2324 ARDOUR_UI::add_route (Gtk::Window* float_window)
2325 {
2326         int count;
2327
2328         if (!session) {
2329                 return;
2330         }
2331
2332         if (add_route_dialog == 0) {
2333                 add_route_dialog = new AddRouteDialog;
2334                 if (float_window) {
2335                         add_route_dialog->set_transient_for (*float_window);
2336                 }
2337         }
2338
2339         if (add_route_dialog->is_visible()) {
2340                 /* we're already doing this */
2341                 return;
2342         }
2343
2344         ResponseType r = (ResponseType) add_route_dialog->run ();
2345
2346         add_route_dialog->hide();
2347
2348         switch (r) {
2349                 case RESPONSE_ACCEPT:
2350                         break;
2351                 default:
2352                         return;
2353                         break;
2354         }
2355
2356         if ((count = add_route_dialog->count()) <= 0) {
2357                 return;
2358         }
2359
2360         uint32_t input_chan = add_route_dialog->channels ();
2361         uint32_t output_chan;
2362         string name_template = add_route_dialog->name_template ();
2363         bool track = add_route_dialog->track ();
2364
2365         AutoConnectOption oac = Config->get_output_auto_connect();
2366
2367         if (oac & AutoConnectMaster) {
2368                 output_chan = (session->master_out() ? session->master_out()->n_inputs().get(DataType::AUDIO) : input_chan);
2369         } else {
2370                 output_chan = input_chan;
2371         }
2372
2373         /* XXX do something with name template */
2374
2375         if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
2376                 if (track) {
2377                         session_add_midi_track(count);
2378                 } else  {
2379                         MessageDialog msg (*editor,
2380                                         _("Sorry, MIDI Busses are not supported at this time."));
2381                         msg.run ();
2382                         //session_add_midi_bus();
2383                 }
2384         } else { 
2385                 if (track) {
2386                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
2387                 } else {
2388                         session_add_audio_bus (input_chan, output_chan, count);
2389                 }
2390         }
2391 }
2392
2393 XMLNode*
2394 ARDOUR_UI::mixer_settings () const
2395 {
2396         XMLNode* node = 0;
2397
2398         if (session) {
2399                 node = session->instant_xml(X_("Mixer"), session->path());
2400         } else {
2401                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2402         }
2403
2404         if (!node) {
2405                 node = new XMLNode (X_("Mixer"));
2406         }
2407
2408         return node;
2409 }
2410
2411 XMLNode*
2412 ARDOUR_UI::editor_settings () const
2413 {
2414         XMLNode* node = 0;
2415
2416         if (session) {
2417                 node = session->instant_xml(X_("Editor"), session->path());
2418         } else {
2419                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2420         }
2421
2422         if (!node) {
2423                 node = new XMLNode (X_("Editor"));
2424         }
2425         return node;
2426 }
2427
2428 XMLNode*
2429 ARDOUR_UI::keyboard_settings () const
2430 {
2431         XMLNode* node = 0;
2432
2433         node = Config->extra_xml(X_("Keyboard"));
2434         
2435         if (!node) {
2436                 node = new XMLNode (X_("Keyboard"));
2437         }
2438         return node;
2439 }
2440
2441 void
2442 ARDOUR_UI::halt_on_xrun_message ()
2443 {
2444         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2445
2446         MessageDialog msg (*editor,
2447                            _("Recording was stopped because your system could not keep up."));
2448         msg.run ();
2449 }
2450
2451 void
2452 ARDOUR_UI::disk_overrun_handler ()
2453 {
2454         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
2455
2456         if (!have_disk_speed_dialog_displayed) {
2457                 have_disk_speed_dialog_displayed = true;
2458                 MessageDialog* msg = new MessageDialog (*editor, _("\
2459 The disk system on your computer\n\
2460 was not able to keep up with Ardour.\n\
2461 \n\
2462 Specifically, it failed to write data to disk\n\
2463 quickly enough to keep up with recording.\n"));
2464                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2465                 msg->show_all ();
2466         }
2467 }
2468
2469 void
2470 ARDOUR_UI::disk_underrun_handler ()
2471 {
2472         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2473
2474         if (!have_disk_speed_dialog_displayed) {
2475                 have_disk_speed_dialog_displayed = true;
2476                 MessageDialog* msg = new MessageDialog (*editor,
2477                                    _("The disk system on your computer\n\
2478 was not able to keep up with Ardour.\n\
2479 \n\
2480 Specifically, it failed to read data from disk\n\
2481 quickly enough to keep up with playback.\n"));
2482                 msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
2483                 msg->show_all ();
2484         } 
2485 }
2486
2487 void
2488 ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
2489 {
2490         have_disk_speed_dialog_displayed = false;
2491         delete msg;
2492 }
2493
2494 int
2495 ARDOUR_UI::pending_state_dialog ()
2496 {
2497         ArdourDialog dialog ("pending state dialog");
2498         Label  message (_("\
2499 This session appears to have been in\n\
2500 middle of recording when ardour or\n\
2501 the computer was shutdown.\n\
2502 \n\
2503 Ardour can recover any captured audio for\n\
2504 you, or it can ignore it. Please decide\n\
2505 what you would like to do.\n"));
2506
2507         dialog.get_vbox()->pack_start (message);
2508         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2509         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2510
2511         dialog.set_position (WIN_POS_CENTER);
2512         dialog.show_all ();
2513         
2514         switch (dialog.run ()) {
2515         case RESPONSE_ACCEPT:
2516                 return 1;
2517         default:
2518                 return 0;
2519         }
2520 }
2521         
2522 void
2523 ARDOUR_UI::disconnect_from_jack ()
2524 {
2525         if (engine) {
2526                 if( engine->disconnect_from_jack ()) {
2527                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2528                         msg.run ();
2529                 }
2530
2531                 update_sample_rate (0);
2532         }
2533 }
2534
2535 void
2536 ARDOUR_UI::reconnect_to_jack ()
2537 {
2538         if (engine) {
2539                 if (engine->reconnect_to_jack ()) {
2540                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
2541                         msg.run ();
2542                 }
2543
2544                 update_sample_rate (0);
2545         }
2546 }
2547
2548 int
2549 ARDOUR_UI::cmdline_new_session (string path)
2550 {
2551         if (path[0] != '/') {
2552                 char buf[PATH_MAX+1];
2553                 string str;
2554
2555                 getcwd (buf, sizeof (buf));
2556                 str = buf;
2557                 str += '/';
2558                 str += path;
2559                 path = str;
2560         }
2561
2562         new_session (path);
2563
2564         _will_create_new_session_automatically = false; /* done it */
2565         return FALSE; /* don't call it again */
2566 }
2567
2568 void
2569 ARDOUR_UI::use_config ()
2570 {
2571         Glib::RefPtr<Action> act;
2572
2573         switch (Config->get_native_file_data_format ()) {
2574         case FormatFloat:
2575                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2576                 break;
2577         case FormatInt24:
2578                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2579                 break;
2580         }
2581
2582         if (act) {
2583                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2584                 ract->set_active ();
2585         }       
2586
2587         switch (Config->get_native_file_header_format ()) {
2588         case BWF:
2589                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2590                 break;
2591         case WAVE:
2592                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2593                 break;
2594         case WAVE64:
2595                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2596                 break;
2597         case iXML:
2598                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2599                 break;
2600         case RF64:
2601                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2602                 break;
2603         case CAF:
2604                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
2605                 break;
2606         case AIFF:
2607                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
2608                 break;
2609         }
2610
2611         if (act) {
2612                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2613                 ract->set_active ();
2614         }       
2615
2616         XMLNode* node = Config->extra_xml (X_("TransportControllables"));
2617         if (node) {
2618                 set_transport_controllable_state (*node);
2619         }
2620 }
2621
2622 void
2623 ARDOUR_UI::update_transport_clocks (nframes_t pos)
2624 {
2625         primary_clock.set (pos);
2626         secondary_clock.set (pos);
2627
2628         if (big_clock_window) {
2629                 big_clock.set (pos);
2630         }
2631 }
2632
2633 void
2634 ARDOUR_UI::record_state_changed ()
2635 {
2636         ENSURE_GUI_THREAD (mem_fun (*this, &ARDOUR_UI::record_state_changed));
2637
2638         if (!session || !big_clock_window) {
2639                 /* why bother - the clock isn't visible */
2640                 return;
2641         }
2642
2643         switch (session->record_status()) {
2644         case Session::Recording:
2645                 big_clock.set_widget_name ("BigClockRecording");
2646                 break;
2647         default:
2648                 big_clock.set_widget_name ("BigClockNonRecording");
2649                 break;
2650         }
2651 }
2652
2653 void
2654 ARDOUR_UI::set_keybindings_path (string path)
2655 {
2656         keybindings_path = path;
2657 }
2658
2659 void
2660 ARDOUR_UI::save_keybindings ()
2661 {
2662         if (can_save_keybindings) {
2663                 AccelMap::save (keybindings_path);
2664         } 
2665 }
2666
2667 bool
2668 ARDOUR_UI::first_idle ()
2669 {
2670         if (session) {
2671                 session->allow_auto_play (true);
2672         }
2673         can_save_keybindings = true;
2674         return false;
2675 }
2676
2677 void
2678 ARDOUR_UI::store_clock_modes ()
2679 {
2680         XMLNode* node = new XMLNode(X_("ClockModes"));
2681
2682         for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
2683                 node->add_property ((*x)->name().c_str(), enum_2_string ((*x)->mode()));
2684         }
2685
2686         session->add_extra_xml (*node);
2687         session->set_dirty ();
2688 }
2689
2690
2691                 
2692 ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
2693         : Controllable (name), ui (u), type(tp)
2694 {
2695         
2696 }
2697
2698 void
2699 ARDOUR_UI::TransportControllable::set_value (float val)
2700 {
2701         if (type == ShuttleControl) {
2702                 double fract;
2703
2704                 if (val == 0.5f) {
2705                         fract = 0.0;
2706                 } else {
2707                         if (val < 0.5f) {
2708                                 fract = -((0.5f - val)/0.5f);
2709                         } else {
2710                                 fract = ((val - 0.5f)/0.5f);
2711                         }
2712                 }
2713                 
2714                 ui.set_shuttle_fract (fract);
2715                 return;
2716         }
2717
2718         if (val < 0.5f) {
2719                 /* do nothing: these are radio-style actions */
2720                 return;
2721         }
2722
2723         char *action = 0;
2724
2725         switch (type) {
2726         case Roll:
2727                 action = X_("Roll");
2728                 break;
2729         case Stop:
2730                 action = X_("Stop");
2731                 break;
2732         case GotoStart:
2733                 action = X_("Goto Start");
2734                 break;
2735         case GotoEnd:
2736                 action = X_("Goto End");
2737                 break;
2738         case AutoLoop:
2739                 action = X_("Loop");
2740                 break;
2741         case PlaySelection:
2742                 action = X_("Play Selection");
2743                 break;
2744         case RecordEnable:
2745                 action = X_("Record");
2746                 break;
2747         default:
2748                 break;
2749         }
2750
2751         if (action == 0) {
2752                 return;
2753         }
2754
2755         Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
2756
2757         if (act) {
2758                 act->activate ();
2759         }
2760 }
2761
2762 float
2763 ARDOUR_UI::TransportControllable::get_value (void) const
2764 {
2765         float val = 0.0f;
2766         
2767         switch (type) {
2768         case Roll:
2769                 break;
2770         case Stop:
2771                 break;
2772         case GotoStart:
2773                 break;
2774         case GotoEnd:
2775                 break;
2776         case AutoLoop:
2777                 break;
2778         case PlaySelection:
2779                 break;
2780         case RecordEnable:
2781                 break;
2782         case ShuttleControl:
2783                 break;
2784         default:
2785                 break;
2786         }
2787
2788         return val;
2789 }
2790
2791 void
2792 ARDOUR_UI::TransportControllable::set_id (const string& str)
2793 {
2794         _id = str;
2795 }
2796
2797 void
2798 ARDOUR_UI::setup_profile ()
2799 {
2800         if (gdk_screen_width() < 1200) {
2801                 Profile->set_small_screen ();
2802         }
2803 }