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