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