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