removed the following environment variables:
[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
33 #include <pbd/error.h>
34 #include <pbd/compose.h>
35 #include <pbd/basename.h>
36 #include <pbd/pathscanner.h>
37 #include <pbd/failed_constructor.h>
38 #include <gtkmm2ext/gtk_ui.h>
39 #include <gtkmm2ext/pix.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 "meter_xpms.h"
76 #include "color_manager.h"
77
78 #include "i18n.h"
79
80 using namespace ARDOUR;
81 using namespace Gtkmm2ext;
82 using namespace Gtk;
83 using namespace sigc;
84
85 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
86
87 sigc::signal<void,bool> ARDOUR_UI::Blink;
88 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
89 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
90 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
91
92 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
93
94         : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
95           
96           primary_clock (X_("TransportClockDisplay"), true, false, true),
97           secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
98           preroll_clock (X_("PreRollClock"), true, true),
99           postroll_clock (X_("PostRollClock"), true, true),
100
101           /* adjuster table */
102
103           adjuster_table (3, 3),
104
105           /* preroll stuff */
106
107           preroll_button (_("pre\nroll")),
108           postroll_button (_("post\nroll")),
109
110           /* big clock */
111
112           big_clock ("BigClockDisplay", true),
113
114           /* transport */
115
116           time_master_button (_("time\nmaster")),
117
118           shuttle_units_button (_("% ")),
119
120           punch_in_button (_("punch\nin")),
121           punch_out_button (_("punch\nout")),
122           auto_return_button (_("auto\nreturn")),
123           auto_play_button (_("auto\nplay")),
124           auto_input_button (_("auto\ninput")),
125           click_button (_("click")),
126           auditioning_alert_button (_("AUDITIONING")),
127           solo_alert_button (_("SOLO")),
128           shown_flag (false)
129
130 {
131         using namespace Gtk::Menu_Helpers;
132
133         Gtkmm2ext::init();
134         
135         about = 0;
136
137         if (theArdourUI == 0) {
138                 theArdourUI = this;
139         }
140
141         ActionManager::init ();
142
143         /* load colors */
144
145         color_manager = new ColorManager();
146
147         std::string color_file = ARDOUR::find_config_file("ardour.colors");
148         
149         color_manager->load (color_file);
150
151         m_new_session_dialog = 0;
152         m_new_session_dialog_ref = NewSessionDialogFactory::create();
153         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
154         editor = 0;
155         mixer = 0;
156         session = 0;
157         _session_is_new = false;
158         big_clock_window = 0;
159         session_selector_window = 0;
160         last_key_press_time = 0;
161         connection_editor = 0;
162         add_route_dialog = 0;
163         route_params = 0;
164         option_editor = 0;
165         location_ui = 0;
166         sfdb = 0;
167         open_session_selector = 0;
168         have_configure_timeout = false;
169         have_disk_overrun_displayed = false;
170         have_disk_underrun_displayed = false;
171         _will_create_new_session_automatically = false;
172         session_loaded = false;
173         last_speed_displayed = -1.0f;
174
175         last_configure_time.tv_sec = 0;
176         last_configure_time.tv_usec = 0;
177
178         shuttle_grabbed = false;
179         shuttle_fract = 0.0;
180
181         set_shuttle_units (Percentage);
182         set_shuttle_behaviour (Sprung);
183
184         shuttle_style_menu = 0;
185         shuttle_unit_menu = 0;
186
187         gettimeofday (&last_peak_grab, 0);
188         gettimeofday (&last_shuttle_request, 0);
189
190         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
191         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
192         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
193         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
194
195         /* handle pending state with a dialog */
196
197         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
198
199         /* have to wait for AudioEngine and Configuration before proceeding */
200 }
201
202 void
203 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
204 {
205         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
206         
207         string msg = string_compose (_("\
208 You cannot record-enable\n\
209 track %1\n\
210 because it has no input connections.\n\
211 You would be wasting space recording silence."),
212                               ds->name());
213
214         MessageDialog message (*editor, msg);
215         message.run ();
216 }
217
218 void
219 ARDOUR_UI::set_engine (AudioEngine& e)
220 {
221         engine = &e;
222
223         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
224         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
225         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
226         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
227
228         _tooltips.enable();
229
230         keyboard = new Keyboard;
231         install_keybindings ();
232
233         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
234         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
235
236         if (setup_windows ()) {
237                 throw failed_constructor ();
238         }
239
240         if (GTK_ARDOUR::show_key_actions) {
241                 vector<string> names;
242                 vector<string> paths;
243                 vector<string> keys;
244                 vector<AccelKey> bindings;
245
246                 ActionManager::get_all_actions (names, paths, keys, bindings);
247
248                 vector<string>::iterator n;
249                 vector<string>::iterator k;
250                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
251                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
252                 }
253
254                 exit (0);
255         }
256
257         /* start with timecode, metering enabled
258         */
259         
260         blink_timeout_tag = -1;
261
262         /* this being a GUI and all, we want peakfiles */
263
264         FileSource::set_build_peakfiles (true);
265         FileSource::set_build_missing_peakfiles (true);
266
267         if (Source::start_peak_thread ()) {
268                 throw failed_constructor();
269         }
270
271         /* start the time-of-day-clock */
272         
273         update_wall_clock ();
274         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
275
276         update_disk_space ();
277         update_cpu_load ();
278         update_sample_rate (engine->frame_rate());
279
280         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
281         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
282 }
283
284 ARDOUR_UI::~ARDOUR_UI ()
285 {
286         save_ardour_state ();
287
288         if (keyboard) {
289                 delete keyboard;
290         }
291
292         if (editor) {
293                 delete editor;
294         }
295
296         if (mixer) {
297                 delete mixer;
298         }
299
300         if (add_route_dialog) {
301                 delete add_route_dialog;
302         }
303
304         Source::stop_peak_thread ();
305 }
306
307 gint
308 ARDOUR_UI::configure_timeout ()
309 {
310         struct timeval now;
311         struct timeval diff;
312
313         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
314                 /* no configure events yet */
315                 return TRUE;
316         }
317
318         gettimeofday (&now, 0);
319         timersub (&now, &last_configure_time, &diff);
320
321         /* force a gap of 0.5 seconds since the last configure event
322          */
323
324         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
325                 return TRUE;
326         } else {
327                 have_configure_timeout = false;
328                 save_ardour_state ();
329                 return FALSE;
330         }
331 }
332
333 gboolean
334 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
335 {
336         if (have_configure_timeout) {
337                 gettimeofday (&last_configure_time, 0);
338         } else {
339                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
340                 have_configure_timeout = true;
341         }
342                 
343         return FALSE;
344 }
345
346 void
347 ARDOUR_UI::save_ardour_state ()
348 {
349         if (!keyboard || !mixer || !editor) {
350                 return;
351         }
352         
353         /* XXX this is all a bit dubious. add_extra_xml() uses
354            a different lifetime model from add_instant_xml().
355         */
356
357         XMLNode* node = new XMLNode (keyboard->get_state());
358         Config->add_extra_xml (*node);
359         Config->save_state();
360
361         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
362         XMLNode& mnode (mixer->get_state());
363
364         if (session) {
365                 session->add_instant_xml(enode, session->path());
366                 session->add_instant_xml(mnode, session->path());
367         } else {
368                 Config->add_instant_xml(enode, get_user_ardour_path());
369                 Config->add_instant_xml(mnode, get_user_ardour_path());
370         }
371 }
372
373 void
374 ARDOUR_UI::startup ()
375 {
376         /* Once the UI is up and running, start the audio engine. Doing
377            this before the UI is up and running can cause problems
378            when not running with SCHED_FIFO, because the amount of
379            CPU and disk work needed to get the UI started can interfere
380            with the scheduling of the audio thread.
381         */
382
383         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
384 }
385
386 void
387 ARDOUR_UI::finish()
388 {
389         if (session && session->dirty()) {
390                 switch (ask_about_saving_session(_("quit"))) {
391                 case -1:
392                         return;
393                         break;
394                 case 1:
395                         /* use the default name */
396                         if (save_state_canfail ("")) {
397                                 /* failed - don't quit */
398                                 MessageDialog msg (*editor, 
399                                                _("\
400 Ardour was unable to save your session.\n\n\
401 If you still wish to quit, please use the\n\n\
402 \"Just quit\" option."));
403                                 msg.run ();
404                                 return;
405                         }
406                         break;
407                 case 0:
408                         break;
409                 }
410         }
411
412         quit ();
413 }
414
415 int
416 ARDOUR_UI::ask_about_saving_session (const string & what)
417 {
418         ArdourDialog window (_("ardour: save session?"));
419         Gtk::Label  prompt_label;
420         string msg;
421
422         msg = string_compose(_("Save and %1"), what);
423         window.add_button (msg, RESPONSE_ACCEPT);
424         msg = string_compose(_("Just %1"), what);
425         window.add_button (msg, RESPONSE_APPLY);
426         msg = string_compose(_("Don't %1"), what);
427         window.add_button (msg, RESPONSE_REJECT);
428
429         Gtk::Button noquit_button (msg);
430         noquit_button.set_name ("EditorGTKButton");
431
432         string prompt;
433         string type;
434
435         if (session->snap_name() == session->name()) {
436                 type = _("session");
437         } else {
438                 type = _("snapshot");
439         }
440         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?"), 
441                          type, session->snap_name());
442         
443         prompt_label.set_text (prompt);
444         prompt_label.set_alignment (0.5, 0.5);
445         prompt_label.set_name (X_("PrompterLabel"));
446         
447         window.get_vbox()->pack_start (prompt_label);
448
449         window.set_name (_("Prompter"));
450         window.set_position (Gtk::WIN_POS_MOUSE);
451         window.set_modal (true);
452         window.show_all ();
453
454         save_the_session = 0;
455
456         editor->ensure_float (window);
457
458         ResponseType r = (ResponseType) window.run();
459
460         window.hide ();
461
462         switch (r) {
463         case RESPONSE_ACCEPT: // save and get out of here
464                 return 1;
465         case RESPONSE_APPLY:  // get out of here
466                 return 0;
467         default:
468                 break;
469         }
470
471         return -1;
472 }
473         
474 gint
475 ARDOUR_UI::every_second ()
476 {
477         update_cpu_load ();
478         update_buffer_load ();
479         update_disk_space ();
480         // update_disk_rate ();
481         return TRUE;
482 }
483
484 gint
485 ARDOUR_UI::every_point_one_seconds ()
486 {
487         struct timeval now;
488         struct timeval diff;
489         
490         /* do not attempt to grab peak power more than once per cycle.
491          */
492
493         gettimeofday (&now, 0);
494         timersub (&now, &last_peak_grab, &diff);
495
496         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
497                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
498                 last_peak_grab = now;
499         } 
500
501         update_speed_display ();
502         RapidScreenUpdate(); /* EMIT_SIGNAL */
503         return TRUE;
504 }
505
506 gint
507 ARDOUR_UI::every_point_zero_one_seconds ()
508 {
509         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
510         return TRUE;
511 }
512
513 void
514 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
515 {
516         char buf[32];
517
518         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
519
520         if (!engine->connected()) {
521
522                 snprintf (buf, sizeof (buf), _("disconnected"));
523
524         } else {
525
526                 jack_nframes_t rate = engine->frame_rate();
527                 
528                 if (fmod (rate, 1000.0) != 0.0) {
529                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
530                                   (float) rate/1000.0f,
531                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
532                 } else {
533                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
534                                   rate/1000,
535                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
536                 }
537         }
538
539         sample_rate_label.set_text (buf);
540 }
541
542 void
543 ARDOUR_UI::update_cpu_load ()
544 {
545         char buf[32];
546         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
547         cpu_load_label.set_text (buf);
548 }
549
550 void
551 ARDOUR_UI::update_disk_rate ()
552 {
553         char buf[64];
554
555         if (session) {
556                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
557                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
558                 disk_rate_label.set_text (buf);
559         } else {
560                 disk_rate_label.set_text ("");
561         }
562 }
563
564 void
565 ARDOUR_UI::update_buffer_load ()
566 {
567         char buf[64];
568
569         if (session) {
570                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
571                           session->playback_load(), session->capture_load());
572                 buffer_load_label.set_text (buf);
573         } else {
574                 buffer_load_label.set_text ("");
575         }
576 }
577
578 void
579 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
580 {
581         if (ds.record_enabled()) {
582                 rec_enabled_diskstreams++;
583         }
584 }
585
586 void
587 ARDOUR_UI::update_disk_space()
588 {
589         if (session == 0) {
590                 return;
591         }
592
593         jack_nframes_t frames = session->available_capture_duration();
594         char buf[64];
595
596         if (frames == max_frames) {
597                 strcpy (buf, _("space: 24hrs+"));
598         } else {
599                 int hrs;
600                 int mins;
601                 int secs;
602                 jack_nframes_t fr = session->frame_rate();
603                 
604                 if (session->actively_recording()){
605                         
606                         rec_enabled_diskstreams = 0;
607                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
608                         
609                         if (rec_enabled_diskstreams) {
610                                 frames /= rec_enabled_diskstreams;
611                         }
612                         
613                 } else {
614                         
615                         /* hmmm. shall we divide by the route count? or the diskstream count?
616                            or what? for now, do nothing ...
617                         */
618                         
619                 }
620                 
621                 hrs  = frames / (fr * 3600);
622                 frames -= hrs * fr * 3600;
623                 mins = frames / (fr * 60);
624                 frames -= mins * fr * 60;
625                 secs = frames / fr;
626                 
627                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
628         }
629
630         disk_space_label.set_text (buf);
631 }                 
632
633 gint
634 ARDOUR_UI::update_wall_clock ()
635 {
636         time_t now;
637         struct tm *tm_now;
638         char buf[16];
639
640         time (&now);
641         tm_now = localtime (&now);
642
643         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
644         wall_clock_label.set_text (buf);
645
646         return TRUE;
647 }
648 void
649 ARDOUR_UI::control_methods_adjusted ()
650
651 {
652         int which_method;
653
654         which_method = (int) online_control_button->adjustment.get_value();
655         switch (which_method) {
656         case 0:
657                 allow_mmc_and_local ();
658                 break;
659         case 1:
660                 allow_mmc_only ();
661                 break;
662         case 2:
663                 allow_local_only ();
664                 break;
665         default:
666                 fatal << _("programming error: impossible control method") << endmsg;
667         }
668 }
669         
670
671 void
672 ARDOUR_UI::mmc_device_id_adjusted ()
673
674 {
675 #if 0
676         if (mmc) {
677                 int dev_id = (int) mmc_id_button->adjustment.get_value();
678                 mmc->set_device_id (dev_id);
679         }
680 #endif
681 }
682
683 gint
684 ARDOUR_UI::session_menu (GdkEventButton *ev)
685 {
686         session_popup_menu->popup (0, 0);
687         return TRUE;
688 }
689
690 void
691 ARDOUR_UI::redisplay_recent_sessions ()
692 {
693         vector<string *> *sessions;
694         vector<string *>::iterator i;
695         RecentSessionsSorter cmp;
696         
697         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
698         recent_session_model->clear ();
699
700         RecentSessions rs;
701         ARDOUR::read_recent_sessions (rs);
702
703         if (rs.empty()) {
704                 recent_session_display.set_model (recent_session_model);
705                 return;
706         }
707
708         /* sort them alphabetically */
709         sort (rs.begin(), rs.end(), cmp);
710         sessions = new vector<string*>;
711
712         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
713                 sessions->push_back (new string ((*i).second));
714         }
715
716         for (i = sessions->begin(); i != sessions->end(); ++i) {
717
718                 vector<string*>* states;
719                 vector<const gchar*> item;
720                 string fullpath = *(*i);
721                 
722                 /* remove any trailing / */
723
724                 if (fullpath[fullpath.length()-1] == '/') {
725                         fullpath = fullpath.substr (0, fullpath.length()-1);
726                 }
727
728                 /* now get available states for this session */
729
730                 if ((states = Session::possible_states (fullpath)) == 0) {
731                         /* no state file? */
732                         continue;
733                 }
734
735                 TreeModel::Row row = *(recent_session_model->append());
736
737                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
738                 row[recent_session_columns.fullpath] = fullpath;
739
740                 if (states->size() > 1) {
741
742                         /* add the children */
743                         
744                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
745                                 
746                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
747
748                                 child_row[recent_session_columns.visible_name] = **i2;
749                                 child_row[recent_session_columns.fullpath] = fullpath;
750
751                                 delete *i2;
752                         }
753                 }
754
755                 delete states;
756         }
757
758         recent_session_display.set_model (recent_session_model);
759         delete sessions;
760 }
761
762 void
763 ARDOUR_UI::build_session_selector ()
764 {
765         session_selector_window = new ArdourDialog ("session selector");
766         
767         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
768         
769         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
770         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
771
772         recent_session_model = TreeStore::create (recent_session_columns);
773         recent_session_display.set_model (recent_session_model);
774         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
775         recent_session_display.set_headers_visible (false);
776
777         scroller->add (recent_session_display);
778         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
779
780         session_selector_window->set_name ("SessionSelectorWindow");
781         session_selector_window->set_size_request (200, 400);
782         session_selector_window->get_vbox()->pack_start (*scroller);
783         session_selector_window->show_all_children();
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::send_all_midi_feedback ()
1236 {
1237         if (session) {
1238                 session->send_all_midi_feedback();
1239         }
1240 }
1241
1242 void
1243 ARDOUR_UI::allow_local_only ()
1244 {
1245
1246 }
1247
1248 void
1249 ARDOUR_UI::allow_mmc_only ()
1250 {
1251
1252 }
1253
1254 void
1255 ARDOUR_UI::allow_mmc_and_local ()
1256 {
1257
1258 }
1259
1260 void
1261 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
1262 {
1263         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
1264                 (int) adj.get_value()].c_str());
1265 }
1266
1267 void
1268 ARDOUR_UI::engine_stopped ()
1269 {
1270         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
1271         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1272         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1273 }
1274
1275
1276 void
1277 ARDOUR_UI::engine_running ()
1278 {
1279         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
1280         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
1281         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
1282 }
1283
1284 void
1285 ARDOUR_UI::engine_halted ()
1286 {
1287         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
1288
1289         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
1290         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
1291
1292         update_sample_rate (0);
1293
1294         MessageDialog msg (*editor, 
1295                            _("\
1296 JACK has either been shutdown or it\n\
1297 disconnected Ardour because Ardour\n\
1298 was not fast enough. You can save the\n\
1299 session and/or try to reconnect to JACK ."));
1300         msg.run ();
1301 }
1302
1303 int32_t
1304 ARDOUR_UI::do_engine_start ()
1305 {
1306         try { 
1307                 engine->start();
1308         }
1309
1310         catch (AudioEngine::PortRegistrationFailure& err) {
1311                 engine->stop ();
1312                 error << _("Unable to create all required ports")
1313                       << endmsg;
1314                 unload_session ();
1315                 return -1;
1316         }
1317
1318         catch (...) {
1319                 engine->stop ();
1320                 error << _("Unable to start the session running")
1321                       << endmsg;
1322                 unload_session ();
1323                 return -2;
1324         }
1325         
1326         return 0;
1327 }
1328
1329 gint
1330 ARDOUR_UI::start_engine ()
1331 {
1332         if (do_engine_start () == 0) {
1333                 if (session && _session_is_new) {
1334                         /* we need to retain initial visual 
1335                            settings for a new session 
1336                         */
1337                         session->save_state ("");
1338                 }
1339
1340                 /* there is too much going on, in too many threads, for us to 
1341                    end up with a clean session. So wait 1 second after loading,
1342                    and fix it up. its ugly, but until i come across a better
1343                    solution, its what we have.
1344                 */
1345
1346                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
1347         }
1348
1349         return FALSE;
1350 }
1351
1352 void
1353 ARDOUR_UI::update_clocks ()
1354 {
1355          Clock (session->audible_frame()); /* EMIT_SIGNAL */
1356 }
1357
1358 void
1359 ARDOUR_UI::start_clocking ()
1360 {
1361         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
1362 }
1363
1364 void
1365 ARDOUR_UI::stop_clocking ()
1366 {
1367         clock_signal_connection.disconnect ();
1368 }
1369         
1370 void
1371 ARDOUR_UI::toggle_clocking ()
1372 {
1373 #if 0
1374         if (clock_button.get_active()) {
1375                 start_clocking ();
1376         } else {
1377                 stop_clocking ();
1378         }
1379 #endif
1380 }
1381
1382 gint
1383 ARDOUR_UI::_blink (void *arg)
1384
1385 {
1386         ((ARDOUR_UI *) arg)->blink ();
1387         return TRUE;
1388 }
1389
1390 void
1391 ARDOUR_UI::blink ()
1392 {
1393          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
1394 }
1395
1396 void
1397 ARDOUR_UI::start_blinking ()
1398 {
1399         /* Start the blink signal. Everybody with a blinking widget
1400            uses Blink to drive the widget's state.
1401         */
1402
1403         if (blink_timeout_tag < 0) {
1404                 blink_on = false;       
1405                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
1406         }
1407 }
1408
1409 void
1410 ARDOUR_UI::stop_blinking ()
1411 {
1412         if (blink_timeout_tag >= 0) {
1413                 gtk_timeout_remove (blink_timeout_tag);
1414                 blink_timeout_tag = -1;
1415         }
1416 }
1417
1418
1419 void
1420 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
1421 {
1422         using namespace Gtk;
1423         using namespace Menu_Helpers;
1424
1425         if (dstream.hidden()) {
1426                 return;
1427         }
1428
1429         MenuList& items = diskstream_menu->items();
1430         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
1431 }
1432         
1433 void
1434 ARDOUR_UI::diskstream_selected (gint32 id)
1435 {
1436         selected_dstream = id;
1437         Main::quit ();
1438 }
1439
1440 gint32
1441 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
1442 {
1443         using namespace Gtk;
1444         using namespace Menu_Helpers;
1445
1446         if (session == 0) {
1447                 return -1;
1448         }
1449
1450         diskstream_menu = new Menu();
1451         diskstream_menu->set_name ("ArdourContextMenu");
1452         using namespace Gtk;
1453         using namespace Menu_Helpers;
1454
1455         MenuList& items = diskstream_menu->items();
1456         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
1457
1458         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
1459
1460         if (ev) {
1461                 diskstream_menu->popup (ev->button, ev->time);
1462         } else {
1463                 diskstream_menu->popup (0, 0);
1464         }
1465
1466         selected_dstream = -1;
1467
1468         Main::run ();
1469
1470         delete diskstream_menu;
1471
1472         return selected_dstream;
1473 }
1474
1475 void
1476 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
1477                           string& buf,
1478                           IO& io,
1479                           bool in)
1480 {
1481         if (in) {
1482                 if (io.n_inputs() == 0) {
1483                         buf = _("none");
1484                         return;
1485                 }
1486                 
1487                 /* XXX we're not handling multiple ports yet. */
1488
1489                 const char **connections = io.input(0)->get_connections();
1490                 
1491                 if (connections == 0 || connections[0] == '\0') {
1492                         buf = _("off");
1493                 } else {
1494                         buf = connections[0];
1495                 }
1496
1497                 free (connections);
1498
1499         } else {
1500
1501                 if (io.n_outputs() == 0) {
1502                         buf = _("none");
1503                         return;
1504                 }
1505                 
1506                 /* XXX we're not handling multiple ports yet. */
1507
1508                 const char **connections = io.output(0)->get_connections();
1509                 
1510                 if (connections == 0 || connections[0] == '\0') {
1511                         buf = _("off");
1512                 } else {
1513                         buf = connections[0];
1514                 }
1515
1516                 free (connections);
1517         }
1518 }
1519
1520 void
1521 ARDOUR_UI::snapshot_session ()
1522 {
1523         ArdourPrompter prompter (true);
1524         string snapname;
1525         string now;
1526         time_t n;
1527
1528         time (&n);
1529         now = ctime (&n);
1530         now = now.substr (0, now.length() - 1);
1531
1532         prompter.set_name ("Prompter");
1533         prompter.set_prompt (_("Name for snapshot"));
1534         prompter.set_initial_text (now);
1535         
1536         switch (prompter.run()) {
1537         case RESPONSE_ACCEPT:
1538                 prompter.get_result (snapname);
1539                 if (snapname.length()){
1540                         save_state (snapname);
1541                 }
1542                 break;
1543
1544         default:
1545                 break;
1546         }
1547 }
1548
1549 void
1550 ARDOUR_UI::save_state (const string & name)
1551 {
1552         (void) save_state_canfail (name);
1553 }
1554                 
1555 int
1556 ARDOUR_UI::save_state_canfail (string name)
1557 {
1558         if (session) {
1559                 int ret;
1560
1561                 if (name.length() == 0) {
1562                         name = session->snap_name();
1563                 }
1564
1565                 if ((ret = session->save_state (name)) != 0) {
1566                         return ret;
1567                 }
1568         }
1569         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
1570         return 0;
1571 }
1572
1573 void
1574 ARDOUR_UI::restore_state (string name)
1575 {
1576         if (session) {
1577                 if (name.length() == 0) {
1578                         name = session->name();
1579                 }
1580                 session->restore_state (name);
1581         }
1582 }
1583
1584 void
1585 ARDOUR_UI::primary_clock_value_changed ()
1586 {
1587         if (session) {
1588                 session->request_locate (primary_clock.current_time ());
1589         }
1590 }
1591
1592 void
1593 ARDOUR_UI::secondary_clock_value_changed ()
1594 {
1595         if (session) {
1596                 session->request_locate (secondary_clock.current_time ());
1597         }
1598 }
1599
1600 void
1601 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
1602 {
1603         if (session && dstream && dstream->record_enabled()) {
1604
1605                 Session::RecordState rs;
1606                 
1607                 rs = session->record_status ();
1608
1609                 switch (rs) {
1610                 case Session::Disabled:
1611                 case Session::Enabled:
1612                         if (w->get_state() != STATE_SELECTED) {
1613                                 w->set_state (STATE_SELECTED);
1614                         }
1615                         break;
1616
1617                 case Session::Recording:
1618                         if (w->get_state() != STATE_ACTIVE) {
1619                                 w->set_state (STATE_ACTIVE);
1620                         }
1621                         break;
1622                 }
1623
1624         } else {
1625                 if (w->get_state() != STATE_NORMAL) {
1626                         w->set_state (STATE_NORMAL);
1627                 }
1628         }
1629 }
1630
1631 void
1632 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
1633 {
1634         if (session == 0) {
1635                 return;
1636         }
1637         
1638         switch (session->record_status()) {
1639         case Session::Enabled:
1640                 if (onoff) {
1641                         rec_button.set_state (1);
1642                 } else {
1643                         rec_button.set_state (0);
1644                 }
1645                 break;
1646
1647         case Session::Recording:
1648                 rec_button.set_state (2);
1649                 break;
1650
1651         default:
1652                 rec_button.set_state (0);
1653                 break;
1654         }
1655 }
1656
1657 gint
1658 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
1659 {
1660         window->hide();
1661         Gtk::Main::quit ();
1662         return TRUE;
1663 }
1664
1665 void
1666 ARDOUR_UI::start_keyboard_prefix ()
1667 {
1668         keyboard->start_prefix();
1669 }
1670
1671 void
1672 ARDOUR_UI::save_template ()
1673
1674 {
1675         ArdourPrompter prompter (true);
1676         string name;
1677
1678         prompter.set_name (X_("Prompter"));
1679         prompter.set_prompt (_("Name for mix template:"));
1680         prompter.set_initial_text(session->name() + _("-template"));
1681         
1682         switch (prompter.run()) {
1683         case RESPONSE_ACCEPT:
1684                 prompter.get_result (name);
1685                 
1686                 if (name.length()) {
1687                         session->save_template (name);
1688                 }
1689                 break;
1690
1691         default:
1692                 break;
1693         }
1694 }
1695
1696 void
1697 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
1698 {
1699         m_new_session_dialog->show_all();
1700         m_new_session_dialog->set_transient_for(*editor);
1701         m_new_session_dialog->set_name(predetermined_path);
1702
1703         int response = Gtk::RESPONSE_CANCEL;
1704
1705         do {
1706                 response = m_new_session_dialog->run ();
1707         
1708                 if(response == Gtk::RESPONSE_OK) {
1709
1710                         _session_is_new = true;
1711                         
1712                         std::string session_name = m_new_session_dialog->session_name();
1713                         std::string session_path = m_new_session_dialog->session_folder();
1714                         
1715                         /*
1716                           XXX This is needed because session constructor wants a 
1717                           non-existant path. hopefully this will be fixed at some point.
1718                         */
1719                         session_path = Glib::build_filename(session_path, session_name);
1720                         
1721                         std::string template_name = m_new_session_dialog->session_template_name();
1722                         
1723                         if (m_new_session_dialog->use_session_template()) {
1724                                 
1725                                 load_session (session_path, session_name, &template_name);
1726                                 
1727                         } else {
1728                                 
1729                                 uint32_t cchns;
1730                                 uint32_t mchns;
1731                                 Session::AutoConnectOption iconnect;
1732                                 Session::AutoConnectOption oconnect;
1733                                 
1734                                 if (m_new_session_dialog->create_control_bus()) {
1735                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
1736                                 } else {
1737                                         cchns = 0;
1738                                 }
1739                                 
1740                                 if (m_new_session_dialog->create_master_bus()) {
1741                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
1742                                 } else {
1743                                         mchns = 0;
1744                                 }
1745                                 
1746                                 if (m_new_session_dialog->connect_inputs()) {
1747                                         iconnect = Session::AutoConnectPhysical;
1748                                 } else {
1749                                         iconnect = Session::AutoConnectOption (0);
1750                                 }
1751                                 
1752                                 /// @todo some minor tweaks.
1753
1754                                 if (m_new_session_dialog->connect_outs_to_master()) {
1755                                         oconnect = Session::AutoConnectMaster;
1756                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
1757                                         oconnect = Session::AutoConnectPhysical;
1758                                 } else {
1759                                         oconnect = Session::AutoConnectOption (0);
1760                                 } 
1761                                 
1762                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
1763                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
1764                                 
1765                                 build_session (session_path,
1766                                                session_name,
1767                                                cchns,
1768                                                mchns,
1769                                                iconnect,
1770                                                oconnect,
1771                                                nphysin,
1772                                                nphysout, 
1773                                                engine->frame_rate() * 60 * 5);
1774                         }               
1775                 }
1776
1777         } while(response == Gtk::RESPONSE_HELP);
1778         m_new_session_dialog->hide_all();
1779 }
1780
1781 int
1782 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
1783 {
1784         Session *new_session;
1785         int x;
1786         session_loaded = false;
1787         x = unload_session ();
1788
1789         if (x < 0) {
1790                 return -1;
1791         } else if (x > 0) {
1792                 return 0;
1793         }
1794
1795         /* if it already exists, we must have write access */
1796
1797         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
1798                 MessageDialog msg (*editor, _("\
1799 You do not have write access to this session.\n\
1800 This prevents the session from being loaded."));
1801                 msg.run ();
1802                 return -1;
1803         }
1804
1805         try {
1806                 new_session = new Session (*engine, path, snap_name, mix_template);
1807         }
1808
1809         catch (...) {
1810
1811                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1812                 return -1;
1813         }
1814
1815         connect_to_session (new_session);
1816
1817         //if (engine->running()) {
1818         //mixer->show_window();
1819         //}
1820         session_loaded = true;
1821         return 0;
1822 }
1823
1824 int
1825 ARDOUR_UI::make_session_clean ()
1826 {
1827         if (session) {
1828                 session->set_clean ();
1829         }
1830
1831         return FALSE;
1832 }
1833
1834 int
1835 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
1836                           uint32_t control_channels,
1837                           uint32_t master_channels, 
1838                           Session::AutoConnectOption input_connect,
1839                           Session::AutoConnectOption output_connect,
1840                           uint32_t nphysin,
1841                           uint32_t nphysout,
1842                           jack_nframes_t initial_length)
1843 {
1844         Session *new_session;
1845         int x;
1846
1847         session_loaded = false;
1848         x = unload_session ();
1849         if (x < 0) {
1850                 return -1;
1851         } else if (x > 0) {
1852                 return 0;
1853         }
1854         
1855         _session_is_new = true;
1856
1857         try {
1858                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
1859                                            control_channels, master_channels, nphysin, nphysout, initial_length);
1860         }
1861
1862         catch (...) {
1863
1864                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
1865                 return -1;
1866         }
1867
1868         connect_to_session (new_session);
1869
1870         //if (engine->running()) {
1871         //mixer->show_window();
1872         //}
1873         session_loaded = true;
1874         return 0;
1875 }
1876
1877 void
1878 ARDOUR_UI::show ()
1879 {
1880         if (editor) {
1881                 editor->show_window ();
1882                 shown_flag = true;
1883         }
1884
1885         if (session && mixer) {
1886                 // mixer->show_window ();
1887         }
1888         
1889         if (about) {
1890                 about->present ();
1891         }
1892 }
1893
1894 void
1895 ARDOUR_UI::show_splash ()
1896 {
1897         if (about == 0) {
1898                 about = new About();
1899         }
1900         about->present();
1901 }
1902
1903 void
1904 ARDOUR_UI::hide_splash ()
1905 {
1906         if (about) {
1907                 // about->hide();
1908         }
1909 }
1910
1911 void
1912 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
1913 {
1914         size_t removed;
1915
1916         removed = rep.paths.size();
1917
1918         if (removed == 0) {
1919                 MessageDialog msg (*editor, X_("cleanupresults"),
1920                                    _("\
1921 No audio files were ready for cleanup\n\n\
1922 If this seems suprising, check for any existing\n\
1923 snapshots. These may still include regions that\n\
1924 require some unused files to continue to exist."));
1925                 msg.run ();
1926                 return;
1927         } 
1928
1929         ArdourDialog results (_("ardour: cleanup"), true);
1930         
1931         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
1932             CleanupResultsModelColumns() { 
1933                     add (visible_name);
1934                     add (fullpath);
1935             }
1936             Gtk::TreeModelColumn<Glib::ustring> visible_name;
1937             Gtk::TreeModelColumn<Glib::ustring> fullpath;
1938         };
1939
1940         
1941         Glib::RefPtr<Gtk::ListStore> results_model;
1942         CleanupResultsModelColumns results_columns;
1943         Gtk::TreeView results_display;
1944         
1945         results_model = ListStore::create (results_columns);
1946         results_display.set_model (results_model);
1947         results_display.append_column (list_title, results_columns.visible_name);
1948         results_display.set_headers_visible (true);
1949
1950         Gtk::ScrolledWindow list_scroller;
1951         Gtk::Label txt;
1952
1953         if (rep.space < 1048576.0f) {
1954                 if (removed > 1) {
1955                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
1956                 } else {
1957                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
1958                 }
1959         } else {
1960                 if (removed > 1) {
1961                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
1962                 } else {
1963                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
1964                 }
1965         }
1966
1967         results.get_vbox()->pack_start (txt, false, false);
1968         
1969         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
1970                 TreeModel::Row row = *(results_model->append());
1971                 row[results_columns.visible_name] = *i;
1972                 row[results_columns.fullpath] = *i;
1973         }
1974         
1975         list_scroller.add (results_display);
1976         list_scroller.set_size_request (-1, 250);
1977         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1978         
1979         results.get_vbox()->pack_start (list_scroller, true, true);
1980         results.add_button (Stock::OK, RESPONSE_ACCEPT);
1981         results.set_position (Gtk::WIN_POS_MOUSE);
1982
1983         results.run ();
1984 }
1985
1986 void
1987 ARDOUR_UI::cleanup ()
1988 {
1989         if (session == 0) {
1990                 /* shouldn't happen: menu item is insensitive */
1991                 return;
1992         }
1993
1994         ArdourDialog checker (_("ardour cleanup"));
1995         Gtk::Label label (_("\
1996 Cleanup is a destructive operation.\n\
1997 ALL undo/redo information will be lost if you cleanup.\n\
1998 Unused audio files will be moved to a \"dead sounds\" location."));
1999         
2000         checker.get_vbox()->pack_start (label, false, false);
2001         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2002         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2003
2004         checker.set_name (_("CleanupDialog"));
2005         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2006         checker.set_position (Gtk::WIN_POS_MOUSE);
2007
2008         switch (checker.run()) {
2009         case RESPONSE_ACCEPT:
2010                 break;
2011         default:
2012                 return;
2013         }
2014
2015         Session::cleanup_report rep;
2016
2017         editor->prepare_for_cleanup ();
2018
2019         if (session->cleanup_sources (rep)) {
2020                 return;
2021         }
2022
2023         display_cleanup_results (rep, 
2024                                  _("cleaned files"),
2025                                  _("\
2026 The following %1 %2 were not in use.\n\
2027 The next time you flush the wastebasket\n\
2028 it will release an additional %3 %4bytes\n\
2029 of disk space"
2030                                          ));
2031 }
2032
2033 void
2034 ARDOUR_UI::flush_trash ()
2035 {
2036         if (session == 0) {
2037                 /* shouldn't happen: menu item is insensitive */
2038                 return;
2039         }
2040
2041         Session::cleanup_report rep;
2042
2043         if (session->cleanup_trash_sources (rep)) {
2044                 return;
2045         }
2046
2047         display_cleanup_results (rep, 
2048                                  _("deleted file"),
2049                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2050 }
2051
2052 void
2053 ARDOUR_UI::add_route ()
2054 {
2055         int count;
2056
2057         if (!session) {
2058                 return;
2059         }
2060
2061         if (add_route_dialog == 0) {
2062                 add_route_dialog = new AddRouteDialog;
2063                 editor->ensure_float (*add_route_dialog);
2064         }
2065
2066         if (add_route_dialog->is_visible()) {
2067                 /* we're already doing this */
2068                 return;
2069         }
2070
2071         ResponseType r = (ResponseType) add_route_dialog->run ();
2072         
2073         add_route_dialog->hide();
2074
2075         switch (r) {
2076         case RESPONSE_ACCEPT:
2077                 break;
2078         default:
2079                 return;
2080                 break;
2081         }
2082
2083         if ((count = add_route_dialog->count()) <= 0) {
2084                 return;
2085         }
2086
2087         uint32_t input_chan = add_route_dialog->channels ();
2088         uint32_t output_chan;
2089         string name_template = add_route_dialog->name_template ();
2090         bool track = add_route_dialog->track ();
2091
2092         Session::AutoConnectOption oac = session->get_output_auto_connect();
2093
2094         if (oac & Session::AutoConnectMaster) {
2095                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2096         } else {
2097                 output_chan = input_chan;
2098         }
2099
2100         /* XXX do something with name template */
2101
2102         while (count) {
2103                 if (track) {
2104                         session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
2105                 } else {
2106                         session_add_audio_bus (input_chan, output_chan);
2107                 }
2108                 --count;
2109                 
2110                 while (Main::events_pending()) {
2111                         Main::iteration ();
2112                 }
2113         }
2114 }
2115
2116 XMLNode*
2117 ARDOUR_UI::mixer_settings () const
2118 {
2119         XMLNode* node = 0;
2120
2121         if (session) {
2122                 node = session->instant_xml(X_("Mixer"), session->path());
2123         } else {
2124                 node = Config->instant_xml(X_("Mixer"), get_user_ardour_path());
2125         }
2126
2127         if (!node) {
2128                 node = new XMLNode (X_("Mixer"));
2129         }
2130
2131         return node;
2132 }
2133
2134 XMLNode*
2135 ARDOUR_UI::editor_settings () const
2136 {
2137         XMLNode* node = 0;
2138
2139         if (session) {
2140                 node = session->instant_xml(X_("Editor"), session->path());
2141         } else {
2142                 node = Config->instant_xml(X_("Editor"), get_user_ardour_path());
2143         }
2144
2145         if (!node) {
2146                 node = new XMLNode (X_("Editor"));
2147         }
2148         return node;
2149 }
2150
2151 XMLNode*
2152 ARDOUR_UI::keyboard_settings () const
2153 {
2154         XMLNode* node = 0;
2155
2156         node = Config->extra_xml(X_("Keyboard"));
2157         
2158         if (!node) {
2159                 node = new XMLNode (X_("Keyboard"));
2160         }
2161         return node;
2162 }
2163
2164 void
2165 ARDOUR_UI::halt_on_xrun_message ()
2166 {
2167         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
2168
2169         MessageDialog msg (*editor,
2170                            _("Recording was stopped because your system could not keep up."));
2171         msg.run ();
2172 }
2173
2174 void 
2175 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
2176 {
2177         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
2178
2179         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
2180                 delete *i;
2181         }
2182
2183         delete deletion_list;
2184 }
2185
2186 void
2187 ARDOUR_UI::disk_overrun_handler ()
2188 {
2189         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2190
2191         if (!have_disk_overrun_displayed) {
2192                 have_disk_overrun_displayed = true;
2193                 MessageDialog msg (*editor, X_("diskrate dialog"), _("\
2194 The disk system on your computer\n\
2195 was not able to keep up with Ardour.\n\
2196 \n\
2197 Specifically, it failed to write data to disk\n\
2198 quickly enough to keep up with recording.\n"));
2199                 msg.run ();
2200                 have_disk_overrun_displayed = false;
2201         }
2202 }
2203
2204 void
2205 ARDOUR_UI::disk_underrun_handler ()
2206 {
2207         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
2208
2209         if (!have_disk_underrun_displayed) {
2210                 have_disk_underrun_displayed = true;
2211                 MessageDialog msg (*editor,
2212                         (_("The disk system on your computer\n\
2213 was not able to keep up with Ardour.\n\
2214 \n\
2215 Specifically, it failed to read data from disk\n\
2216 quickly enough to keep up with playback.\n")));
2217                 msg.run ();
2218                 have_disk_underrun_displayed = false;
2219         } 
2220 }
2221
2222 void
2223 ARDOUR_UI::disk_underrun_message_gone ()
2224 {
2225         have_disk_underrun_displayed = false;
2226 }
2227
2228 void
2229 ARDOUR_UI::disk_overrun_message_gone ()
2230 {
2231         have_disk_underrun_displayed = false;
2232 }
2233
2234 int
2235 ARDOUR_UI::pending_state_dialog ()
2236 {
2237         ArdourDialog dialog ("pending state dialog");
2238         Label  message (_("\
2239 This session appears to have been in\n\
2240 middle of recording when ardour or\n\
2241 the computer was shutdown.\n\
2242 \n\
2243 Ardour can recover any captured audio for\n\
2244 you, or it can ignore it. Please decide\n\
2245 what you would like to do.\n"));
2246
2247         dialog.get_vbox()->pack_start (message);
2248         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
2249         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
2250
2251         dialog.set_position (WIN_POS_CENTER);
2252         dialog.show_all ();
2253         
2254         switch (dialog.run ()) {
2255         case RESPONSE_ACCEPT:
2256                 break;
2257         default:
2258                 return 1;
2259         }
2260
2261         return 0;
2262 }
2263         
2264         
2265 void
2266 ARDOUR_UI::disconnect_from_jack ()
2267 {
2268         if (engine) {
2269                 if( engine->disconnect_from_jack ()) {
2270                         MessageDialog msg (*editor, _("Could not disconnect from JACK"));
2271                         msg.run ();
2272                 }
2273
2274                 update_sample_rate (0);
2275         }
2276 }
2277
2278 void
2279 ARDOUR_UI::reconnect_to_jack ()
2280 {
2281         if (engine) {
2282                 if (engine->reconnect_to_jack ()) {
2283                         MessageDialog msg (*editor,  _("Could not reconnect to JACK"));
2284                         msg.run ();
2285                 }
2286
2287                 update_sample_rate (0);
2288         }
2289 }
2290
2291 void
2292 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
2293 {
2294         engine->request_buffer_size (nframes);
2295         update_sample_rate (0);
2296 }
2297
2298 int
2299 ARDOUR_UI::cmdline_new_session (string path)
2300 {
2301         if (path[0] != '/') {
2302                 char buf[PATH_MAX+1];
2303                 string str;
2304
2305                 getcwd (buf, sizeof (buf));
2306                 str = buf;
2307                 str += '/';
2308                 str += path;
2309                 path = str;
2310         }
2311
2312         new_session (false, path);
2313
2314         _will_create_new_session_automatically = false; /* done it */
2315         return FALSE; /* don't call it again */
2316 }