Fix up cleanup summary dialogs a bit.
[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
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 (0, now.length() - 1);
1523
1524         prompter.set_name ("Prompter");
1525         prompter.set_prompt (_("Name for snapshot"));
1526         prompter.set_initial_text (now);
1527         
1528         switch (prompter.run()) {
1529         case RESPONSE_ACCEPT:
1530                 prompter.get_result (snapname);
1531                 if (snapname.length()){
1532                         save_state (snapname);
1533                 }
1534                 break;
1535
1536         default:
1537                 break;
1538         }
1539 }
1540
1541 void
1542 ARDOUR_UI::save_state (const string & name)
1543 {
1544         (void) save_state_canfail (name);
1545 }
1546                 
1547 int
1548 ARDOUR_UI::save_state_canfail (string name)
1549 {
1550         if (session) {
1551                 int ret;
1552
1553                 if (name.length() == 0) {
1554                         name = session->snap_name();
1555                 }
1556
1557                 if ((ret = session->save_state (name)) != 0) {
1558                         return ret;
1559                 }
1560         }
1561         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1562         return 0;
1563 }
1564
1565 void
1566 ARDOUR_UI::restore_state (string name)
1567 {
1568         if (session) {
1569                 if (name.length() == 0) {
1570                         name = session->name();
1571                 }
1572                 session->restore_state (name);
1573         }
1574 }
1575
1576 void
1577 ARDOUR_UI::primary_clock_value_changed ()
1578 {
1579         if (session) {
1580                 session->request_locate (primary_clock.current_time ());
1581         }
1582 }
1583
1584 void
1585 ARDOUR_UI::secondary_clock_value_changed ()
1586 {
1587         if (session) {
1588                 session->request_locate (secondary_clock.current_time ());
1589         }
1590 }
1591
1592 void
1593 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1594 {
1595         if (session && dstream && dstream->record_enabled()) {
1596
1597                 Session::RecordState rs;
1598                 
1599                 rs = session->record_status ();
1600
1601                 switch (rs) {
1602                 case Session::Disabled:
1603                 case Session::Enabled:
1604                         if (w->get_state() != STATE_SELECTED) {
1605                                 w->set_state (STATE_SELECTED);
1606                         }
1607                         break;
1608
1609                 case Session::Recording:
1610                         if (w->get_state() != STATE_ACTIVE) {
1611                                 w->set_state (STATE_ACTIVE);
1612                         }
1613                         break;
1614                 }
1615
1616         } else {
1617                 if (w->get_state() != STATE_NORMAL) {
1618                         w->set_state (STATE_NORMAL);
1619                 }
1620         }
1621 }
1622
1623 void
1624 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1625 {
1626         if (session == 0) {
1627                 return;
1628         }
1629         
1630         switch (session->record_status()) {
1631         case Session::Enabled:
1632                 if (onoff) {
1633                         rec_button.set_state (1);
1634                 } else {
1635                         rec_button.set_state (0);
1636                 }
1637                 break;
1638
1639         case Session::Recording:
1640                 rec_button.set_state (2);
1641                 break;
1642
1643         default:
1644                 rec_button.set_state (0);
1645                 break;
1646         }
1647 }
1648
1649 gint
1650 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1651 {
1652         window->hide();
1653         Gtk::Main::quit ();
1654         return TRUE;
1655 }
1656
1657 void
1658 ARDOUR_UI::start_keyboard_prefix ()
1659 {
1660         keyboard->start_prefix();
1661 }
1662
1663 void
1664 ARDOUR_UI::save_template ()
1665
1666 {
1667         ArdourPrompter prompter (true);
1668         string name;
1669
1670         prompter.set_name (X_("Prompter"));
1671         prompter.set_prompt (_("Name for mix template:"));
1672         prompter.set_initial_text(session->name() + _("-template"));
1673         
1674         switch (prompter.run()) {
1675         case RESPONSE_ACCEPT:
1676                 prompter.get_result (name);
1677                 
1678                 if (name.length()) {
1679                         session->save_template (name);
1680                 }
1681                 break;
1682
1683         default:
1684                 break;
1685         }
1686 }
1687
1688 void
1689 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1690 {
1691         m_new_session_dialog->show_all();
1692         m_new_session_dialog->set_transient_for(*editor);
1693         m_new_session_dialog->set_name(predetermined_path);
1694
1695         int response = Gtk::RESPONSE_CANCEL;
1696
1697         do {
1698                 response = m_new_session_dialog->run ();
1699         
1700                 if(response == Gtk::RESPONSE_OK) {
1701
1702                         _session_is_new = true;
1703                         
1704                         std::string session_name = m_new_session_dialog->session_name();
1705                         std::string session_path = m_new_session_dialog->session_folder();
1706                         
1707                         /*
1708                           XXX This is needed because session constructor wants a 
1709                           non-existant path. hopefully this will be fixed at some point.
1710                         */
1711                         session_path = Glib::build_filename(session_path, session_name);
1712                         
1713                         std::string template_name = m_new_session_dialog->session_template_name();
1714                         
1715                         if (m_new_session_dialog->use_session_template()) {
1716                                 
1717                                 load_session (session_path, session_name, &template_name);
1718                                 
1719                         } else {
1720                                 
1721                                 uint32_t cchns;
1722                                 uint32_t mchns;
1723                                 Session::AutoConnectOption iconnect;
1724                                 Session::AutoConnectOption oconnect;
1725                                 
1726                                 if (m_new_session_dialog->create_control_bus()) {
1727                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1728                                 } else {
1729                                         cchns = 0;
1730                                 }
1731                                 
1732                                 if (m_new_session_dialog->create_master_bus()) {
1733                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1734                                 } else {
1735                                         mchns = 0;
1736                                 }
1737                                 
1738                                 if (m_new_session_dialog->connect_inputs()) {
1739                                         iconnect = Session::AutoConnectPhysical;
1740                                 } else {
1741                                         iconnect = Session::AutoConnectOption (0);
1742                                 }
1743                                 
1744                                 /// @todo some minor tweaks.
1745
1746                                 if (m_new_session_dialog->connect_outs_to_master()) {
1747                                         oconnect = Session::AutoConnectMaster;
1748                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1749                                         oconnect = Session::AutoConnectPhysical;
1750                                 } else {
1751                                         oconnect = Session::AutoConnectOption (0);
1752                                 } 
1753                                 
1754                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1755                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1756                                 
1757                                 build_session (session_path,
1758                                                session_name,
1759                                                cchns,
1760                                                mchns,
1761                                                iconnect,
1762                                                oconnect,
1763                                                nphysin,
1764                                                nphysout, 
1765                                                engine->frame_rate() * 60 * 5);
1766                         }               
1767                 }
1768
1769         } while(response == Gtk::RESPONSE_HELP);
1770         m_new_session_dialog->hide_all();
1771 }
1772
1773 int
1774 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1775 {
1776         Session *new_session;
1777         int x;
1778         session_loaded = false;
1779         x = unload_session ();
1780
1781         if (x < 0) {
1782                 return -1;
1783         } else if (x > 0) {
1784                 return 0;
1785         }
1786
1787         /* if it already exists, we must have write access */
1788
1789         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1790                 MessageDialog msg (*editor, _("\
1791 You do not have write access to this session.\n\
1792 This prevents the session from being loaded."));
1793                 msg.run ();
1794                 return -1;
1795         }
1796
1797         try {
1798                 new_session = new Session (*engine, path, snap_name, mix_template);
1799         }
1800
1801         catch (...) {
1802
1803                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1804                 return -1;
1805         }
1806
1807         connect_to_session (new_session);
1808
1809         //if (engine->running()) {
1810         //mixer->show_window();
1811         //}
1812         session_loaded = true;
1813         return 0;
1814 }
1815
1816 int
1817 ARDOUR_UI::make_session_clean ()
1818 {
1819         if (session) {
1820                 session->set_clean ();
1821         }
1822
1823         return FALSE;
1824 }
1825
1826 int
1827 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
1828                           uint32_t control_channels,
1829                           uint32_t master_channels, 
1830                           Session::AutoConnectOption input_connect,
1831                           Session::AutoConnectOption output_connect,
1832                           uint32_t nphysin,
1833                           uint32_t nphysout,
1834                           jack_nframes_t initial_length)
1835 {
1836         Session *new_session;
1837         int x;
1838
1839         session_loaded = false;
1840         x = unload_session ();
1841         if (x < 0) {
1842                 return -1;
1843         } else if (x > 0) {
1844                 return 0;
1845         }
1846         
1847         _session_is_new = true;
1848
1849         try {
1850                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1851                                            control_channels, master_channels, nphysin, nphysout, initial_length);
1852         }
1853
1854         catch (...) {
1855
1856                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1857                 return -1;
1858         }
1859
1860         connect_to_session (new_session);
1861
1862         //if (engine->running()) {
1863         //mixer->show_window();
1864         //}
1865         session_loaded = true;
1866         return 0;
1867 }
1868
1869 void
1870 ARDOUR_UI::show ()
1871 {
1872         if (editor) {
1873                 editor->show_window ();
1874                 shown_flag = true;
1875         }
1876
1877         if (session && mixer) {
1878                 // mixer->show_window ();
1879         }
1880         
1881         if (about) {
1882                 about->present ();
1883         }
1884 }
1885
1886 void
1887 ARDOUR_UI::show_splash ()
1888 {
1889         if (about == 0) {
1890                 about = new About();
1891         }
1892         about->present();
1893 }
1894
1895 void
1896 ARDOUR_UI::hide_splash ()
1897 {
1898         if (about) {
1899                 // about->hide();
1900         }
1901 }
1902
1903 void
1904 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1905 {
1906         size_t removed;
1907
1908         removed = rep.paths.size();
1909
1910         if (removed == 0) {
1911                 MessageDialog msgd (*editor,
1912                                     _("No audio files were ready for cleanup"), 
1913                                     false,
1914                                     Gtk::MESSAGE_INFO,
1915                                     (Gtk::ButtonsType)(Gtk::BUTTONS_CLOSE)  );
1916                 msgd.set_secondary_text (_("If this seems suprising, \n\
1917 check for any existing snapshots.\n\
1918 These may still include regions that\n\
1919 require some unused files to continue to exist."));
1920         
1921                 msgd.run ();
1922                 return;
1923         } 
1924
1925         ArdourDialog results (_("ardour: cleanup"), true, true);
1926         
1927         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1928             CleanupResultsModelColumns() { 
1929                     add (visible_name);
1930                     add (fullpath);
1931             }
1932             Gtk::TreeModelColumn<Glib::ustring> visible_name;
1933             Gtk::TreeModelColumn<Glib::ustring> fullpath;
1934         };
1935
1936         
1937         CleanupResultsModelColumns results_columns;
1938         Glib::RefPtr<Gtk::ListStore> results_model;
1939         Gtk::TreeView results_display;
1940         
1941         results_model = ListStore::create (results_columns);
1942         results_display.set_model (results_model);
1943         results_display.append_column (list_title, results_columns.visible_name);
1944
1945         results_display.set_name ("CleanupResultsList");
1946         results_display.set_headers_visible (true);
1947         results_display.set_headers_clickable (false);
1948
1949         Gtk::ScrolledWindow list_scroller;
1950         Gtk::Label txt;
1951         Gtk::VBox dvbox;
1952         Gtk::HBox dhbox;
1953
1954         if (rep.space < 1048576.0f) {
1955                 if (removed > 1) {
1956                   txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
1957                 } else {
1958                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1024.0f, "kilo"));
1959                 }
1960         } else {
1961                 if (removed > 1) {
1962                         txt.set_text (string_compose (msg, removed, _("files were"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
1963                 } else {
1964                         txt.set_text (string_compose (msg, removed, _("file was"), session->path() + "dead_sounds", (float) rep.space / 1048576.0f, "mega"));
1965                 }
1966         }
1967
1968         dvbox.pack_start (txt, true, false, 10);
1969
1970         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1971                 TreeModel::Row row = *(results_model->append());
1972                 row[results_columns.visible_name] = *i;
1973                 row[results_columns.fullpath] = *i;
1974         }
1975         
1976         list_scroller.add (results_display);
1977         list_scroller.set_size_request (-1, 150);
1978         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1979
1980         dvbox.pack_start (list_scroller, true, false);
1981         dhbox.pack_start (dvbox, true, false, 10);
1982         results.get_vbox()->pack_start (dhbox, true, false);
1983         results.add_button (Stock::CLOSE, RESPONSE_CLOSE);
1984         results.set_position (Gtk::WIN_POS_CENTER);
1985         results.show_all_children ();
1986
1987         results.run ();
1988
1989 }
1990
1991 void
1992 ARDOUR_UI::cleanup ()
1993 {
1994         if (session == 0) {
1995                 /* shouldn't happen: menu item is insensitive */
1996                 return;
1997         }
1998
1999
2000         MessageDialog  checker (_("Are you sure you want to cleanup?"),
2001                                 false,
2002                                 Gtk::MESSAGE_QUESTION,
2003                                 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
2004
2005         checker.set_secondary_text(_("Cleanup is a destructive operation.\n\
2006 ALL undo/redo information will be lost if you cleanup.\n\
2007 After cleanup, unused audio files will be moved to a \
2008 \"dead sounds\" location."));
2009         
2010         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2011         checker.add_button (_("Clean Up"), RESPONSE_ACCEPT);
2012
2013         checker.set_name (_("CleanupDialog"));
2014         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2015         checker.set_position (Gtk::WIN_POS_CENTER);
2016
2017         switch (checker.run()) {
2018         case RESPONSE_ACCEPT:
2019                 break;
2020         default:
2021                 return;
2022         }
2023
2024         Session::cleanup_report rep;
2025
2026         editor->prepare_for_cleanup ();
2027
2028         if (session->cleanup_sources (rep)) {
2029                 return;
2030         }
2031         checker.hide();
2032         display_cleanup_results (rep, 
2033                                  _("cleaned files"),
2034                                  _("\
2035 The following %1 %2 not in use and \n\
2036 have been moved to %3. \n\
2037 Flushing the wastebasket will release an additional\n\
2038 %4 %5bytes of disk space by deleting these files."
2039                                          ));
2040 }
2041
2042 void
2043 ARDOUR_UI::flush_trash ()
2044 {
2045         if (session == 0) {
2046                 /* shouldn't happen: menu item is insensitive */
2047                 return;
2048         }
2049
2050         Session::cleanup_report rep;
2051
2052         if (session->cleanup_trash_sources (rep)) {
2053                 return;
2054         }
2055
2056         display_cleanup_results (rep, 
2057                                  _("deleted file"),
2058                                  _("The following %1 %2 \n\
2059 deleted from %3, releasing \n\
2060 %4 %5bytes of disk space"));
2061 }
2062
2063 void
2064 ARDOUR_UI::add_route ()
2065 {
2066         int count;
2067
2068         if (!session) {
2069                 return;
2070         }
2071
2072         if (add_route_dialog == 0) {
2073                 add_route_dialog = new AddRouteDialog;
2074                 editor->ensure_float (*add_route_dialog);
2075         }
2076
2077         if (add_route_dialog->is_visible()) {
2078                 /* we're already doing this */
2079                 return;
2080         }
2081
2082         ResponseType r = (ResponseType) add_route_dialog->run ();
2083         
2084         add_route_dialog->hide();
2085
2086         switch (r) {
2087         case RESPONSE_ACCEPT:
2088                 break;
2089         default:
2090                 return;
2091                 break;
2092         }
2093
2094         if ((count = add_route_dialog->count()) <= 0) {
2095                 return;
2096         }
2097
2098         uint32_t input_chan = add_route_dialog->channels ();
2099         uint32_t output_chan;
2100         string name_template = add_route_dialog->name_template ();
2101         bool track = add_route_dialog->track ();
2102
2103         Session::AutoConnectOption oac = session->get_output_auto_connect();
2104
2105         if (oac & Session::AutoConnectMaster) {
2106                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2107         } else {
2108                 output_chan = input_chan;
2109         }
2110
2111         /* XXX do something with name template */
2112
2113         while (count) {
2114                 if (track) {
2115                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2116                 } else {
2117                         session_add_audio_bus (input_chan, output_chan);
2118                 }
2119                 --count;
2120                 
2121                 while (Main::events_pending()) {
2122                         Main::iteration ();
2123                 }
2124         }
2125 }
2126
2127 XMLNode*
2128 ARDOUR_UI::mixer_settings () const
2129 {
2130         XMLNode* node = 0;
2131
2132         if (session) {
2133                 node = session->instant_xml(X_("Mixer"), session->path());
2134         } else {
2135                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2136         }
2137
2138         if (!node) {
2139                 node = new XMLNode (X_("Mixer"));
2140         }
2141
2142         return node;
2143 }
2144
2145 XMLNode*
2146 ARDOUR_UI::editor_settings () const
2147 {
2148         XMLNode* node = 0;
2149
2150         if (session) {
2151                 node = session->instant_xml(X_("Editor"), session->path());
2152         } else {
2153                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2154         }
2155
2156         if (!node) {
2157                 node = new XMLNode (X_("Editor"));
2158         }
2159         return node;
2160 }
2161
2162 XMLNode*
2163 ARDOUR_UI::keyboard_settings () const
2164 {
2165         XMLNode* node = 0;
2166
2167         node = Config->extra_xml(X_("Keyboard"));
2168         
2169         if (!node) {
2170                 node = new XMLNode (X_("Keyboard"));
2171         }
2172         return node;
2173 }
2174
2175 void
2176 ARDOUR_UI::halt_on_xrun_message ()
2177 {
2178         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2179
2180         MessageDialog msg (*editor,
2181                            _("Recording was stopped because your system could not keep up."));
2182         msg.run ();
2183 }
2184
2185 void 
2186 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2187 {
2188         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2189
2190         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2191                 delete *i;
2192         }
2193
2194         delete deletion_list;
2195 }
2196
2197 void
2198 ARDOUR_UI::disk_overrun_handler ()
2199 {
2200         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2201
2202         if (!have_disk_overrun_displayed) {
2203                 have_disk_overrun_displayed = true;
2204                 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2205 The disk system on your computer\n\
2206 was not able to keep up with Ardour.\n\
2207 \n\
2208 Specifically, it failed to write data to disk\n\
2209 quickly enough to keep up with recording.\n"));
2210                 msg.run ();
2211                 have_disk_overrun_displayed = false;
2212         }
2213 }
2214
2215 void
2216 ARDOUR_UI::disk_underrun_handler ()
2217 {
2218         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2219
2220         if (!have_disk_underrun_displayed) {
2221                 have_disk_underrun_displayed = true;
2222                 MessageDialog msg (*editor,
2223                         (_("The disk system on your computer\n\
2224 was not able to keep up with Ardour.\n\
2225 \n\
2226 Specifically, it failed to read data from disk\n\
2227 quickly enough to keep up with playback.\n")));
2228                 msg.run ();
2229                 have_disk_underrun_displayed = false;
2230         } 
2231 }
2232
2233 void
2234 ARDOUR_UI::disk_underrun_message_gone ()
2235 {
2236         have_disk_underrun_displayed = false;
2237 }
2238
2239 void
2240 ARDOUR_UI::disk_overrun_message_gone ()
2241 {
2242         have_disk_underrun_displayed = false;
2243 }
2244
2245 int
2246 ARDOUR_UI::pending_state_dialog ()
2247 {
2248         ArdourDialog dialog ("pending state dialog");
2249         Label  message (_("\
2250 This session appears to have been in\n\
2251 middle of recording when ardour or\n\
2252 the computer was shutdown.\n\
2253 \n\
2254 Ardour can recover any captured audio for\n\
2255 you, or it can ignore it. Please decide\n\
2256 what you would like to do.\n"));
2257
2258         dialog.get_vbox()->pack_start (message);
2259         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2260         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2261
2262         dialog.set_position (WIN_POS_CENTER);
2263         dialog.show_all ();
2264         
2265         switch (dialog.run ()) {
2266         case RESPONSE_ACCEPT:
2267                 return 1;
2268         default:
2269                 return 0;
2270         }
2271 }
2272         
2273 void
2274 ARDOUR_UI::disconnect_from_jack ()
2275 {
2276         if (engine) {
2277                 if( engine->disconnect_from_jack ()) {
2278                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2279                         msg.run ();
2280                 }
2281
2282                 update_sample_rate (0);
2283         }
2284 }
2285
2286 void
2287 ARDOUR_UI::reconnect_to_jack ()
2288 {
2289         if (engine) {
2290                 if (engine->reconnect_to_jack ()) {
2291                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
2292                         msg.run ();
2293                 }
2294
2295                 update_sample_rate (0);
2296         }
2297 }
2298
2299 void
2300 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2301 {
2302         engine->request_buffer_size (nframes);
2303         update_sample_rate (0);
2304 }
2305
2306 int
2307 ARDOUR_UI::cmdline_new_session (string path)
2308 {
2309         if (path[0] != '/') {
2310                 char buf[PATH_MAX+1];
2311                 string str;
2312
2313                 getcwd (buf, sizeof (buf));
2314                 str = buf;
2315                 str += '/';
2316                 str += path;
2317                 path = str;
2318         }
2319
2320         new_session (false, path);
2321
2322         _will_create_new_session_automatically = false; /* done it */
2323         return FALSE; /* don't call it again */
2324 }
2325
2326 void
2327 ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
2328 {
2329         Glib::RefPtr<Action> act;
2330         
2331         switch (hf) {
2332         case BWF:
2333                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2334                 break;
2335         case WAVE:
2336                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2337                 break;
2338         case WAVE64:
2339                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2340                 break;
2341         case iXML:
2342                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2343                 break;
2344         case RF64:
2345                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2346                 break;
2347         }
2348
2349         if (act) {
2350                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2351                 if (ract && ract->get_active() && Config->get_native_file_header_format() != hf) {
2352                         Config->set_native_file_header_format (hf);
2353                         if (session) {
2354                                 session->reset_native_file_format ();
2355                         }
2356                 }
2357         }
2358 }
2359
2360 void
2361 ARDOUR_UI::set_native_file_data_format (SampleFormat sf)
2362 {
2363         Glib::RefPtr<Action> act;
2364         
2365         switch (sf) {
2366         case FormatFloat:
2367                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2368                 break;
2369         case FormatInt24:
2370                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2371                 break;
2372         }
2373
2374         if (act) {
2375                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2376
2377                 if (ract && ract->get_active() && Config->get_native_file_data_format() != sf) {
2378                         Config->set_native_file_data_format (sf);
2379                         if (session) {
2380                                 session->reset_native_file_format ();
2381                         }
2382                 }
2383         }
2384 }
2385
2386 void
2387 ARDOUR_UI::use_config ()
2388 {
2389         Glib::RefPtr<Action> act;
2390
2391         switch (Config->get_native_file_data_format ()) {
2392         case FormatFloat:
2393                 act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
2394                 break;
2395         case FormatInt24:
2396                 act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
2397                 break;
2398         }
2399
2400         if (act) {
2401                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2402                 ract->set_active ();
2403         }       
2404
2405         switch (Config->get_native_file_header_format ()) {
2406         case BWF:
2407                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
2408                 break;
2409         case WAVE:
2410                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
2411                 break;
2412         case WAVE64:
2413                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
2414                 break;
2415         case iXML:
2416                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
2417                 break;
2418         case RF64:
2419                 act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
2420                 break;
2421         }
2422
2423         if (act) {
2424                 Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
2425                 ract->set_active ();
2426         }       
2427 }