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