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