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