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