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