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