snapshot(prompter) and recent dialog fixes
[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 <pbd/error.h>
32 #include <pbd/compose.h>
33 #include <pbd/basename.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/failed_constructor.h>
36 #include <gtkmm2ext/gtk_ui.h>
37 #include <gtkmm2ext/pix.h>
38 #include <gtkmm2ext/utils.h>
39 #include <gtkmm2ext/click_box.h>
40 #include <gtkmm2ext/fastmeter.h>
41 #include <gtkmm2ext/stop_signal.h>
42 #include <gtkmm2ext/popup.h>
43
44 #include <midi++/port.h>
45 #include <midi++/mmc.h>
46
47 #include <ardour/ardour.h>
48 #include <ardour/port.h>
49 #include <ardour/audioengine.h>
50 #include <ardour/playlist.h>
51 #include <ardour/utils.h>
52 #include <ardour/diskstream.h>
53 #include <ardour/filesource.h>
54 #include <ardour/recent_sessions.h>
55 #include <ardour/session_diskstream.h>
56 #include <ardour/port.h>
57 #include <ardour/audio_track.h>
58
59 #include "actions.h"
60 #include "ardour_ui.h"
61 #include "ardour_message.h"
62 #include "public_editor.h"
63 #include "audio_clock.h"
64 #include "keyboard.h"
65 #include "mixer_ui.h"
66 #include "prompter.h"
67 #include "opts.h"
68 #include "keyboard_target.h"
69 #include "add_route_dialog.h"
70 #include "new_session_dialog.h"
71 #include "about.h"
72 #include "utils.h"
73 #include "gui_thread.h"
74
75 #include "i18n.h"
76
77 using namespace ARDOUR;
78 using namespace Gtkmm2ext;
79 using namespace Gtk;
80 using namespace sigc;
81
82 ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
83
84 sigc::signal<void,bool> ARDOUR_UI::Blink;
85 sigc::signal<void>      ARDOUR_UI::RapidScreenUpdate;
86 sigc::signal<void>      ARDOUR_UI::SuperRapidScreenUpdate;
87 sigc::signal<void,jack_nframes_t> ARDOUR_UI::Clock;
88
89 /* XPM */
90 static const gchar *h_meter_strip_xpm[] = {
91 "186 5 187 2",
92 "       c None",
93 ".      c #2BFE00",
94 "+      c #2DFE00",
95 "@      c #2FFE01",
96 "#      c #32FE01",
97 "$      c #34FE02",
98 "%      c #36FE02",
99 "&      c #38FE03",
100 "*      c #3BFE03",
101 "=      c #3DFD04",
102 "-      c #3FFD04",
103 ";      c #41FD05",
104 ">      c #44FD05",
105 ",      c #46FD06",
106 "'      c #48FD06",
107 ")      c #4AFD07",
108 "!      c #4DFD07",
109 "~      c #4FFD08",
110 "{      c #51FC08",
111 "]      c #53FC09",
112 "^      c #56FC09",
113 "/      c #58FC09",
114 "(      c #5AFC0A",
115 "_      c #5CFC0A",
116 ":      c #5FFC0B",
117 "<      c #61FC0B",
118 "[      c #63FB0C",
119 "}      c #65FB0C",
120 "|      c #68FB0D",
121 "1      c #6AFB0D",
122 "2      c #6CFB0E",
123 "3      c #6EFB0E",
124 "4      c #71FB0F",
125 "5      c #73FB0F",
126 "6      c #75FB10",
127 "7      c #77FA10",
128 "8      c #7AFA11",
129 "9      c #7CFA11",
130 "0      c #7EFA12",
131 "a      c #80FA12",
132 "b      c #83FA12",
133 "c      c #85FA13",
134 "d      c #87FA13",
135 "e      c #89FA14",
136 "f      c #8CF914",
137 "g      c #8EF915",
138 "h      c #90F915",
139 "i      c #92F916",
140 "j      c #95F916",
141 "k      c #97F917",
142 "l      c #99F917",
143 "m      c #9BF918",
144 "n      c #9EF818",
145 "o      c #A0F819",
146 "p      c #A2F819",
147 "q      c #A4F81A",
148 "r      c #A7F81A",
149 "s      c #A9F81A",
150 "t      c #ABF81B",
151 "u      c #ADF81B",
152 "v      c #B0F81C",
153 "w      c #B2F71C",
154 "x      c #B4F71D",
155 "y      c #B6F71D",
156 "z      c #B9F71E",
157 "A      c #BBF71E",
158 "B      c #BDF71F",
159 "C      c #BFF71F",
160 "D      c #C2F720",
161 "E      c #C4F720",
162 "F      c #C6F621",
163 "G      c #C8F621",
164 "H      c #CBF622",
165 "I      c #CDF622",
166 "J      c #CFF623",
167 "K      c #D1F623",
168 "L      c #D4F624",
169 "M      c #D6F624",
170 "N      c #D8F524",
171 "O      c #DAF525",
172 "P      c #DDF525",
173 "Q      c #DFF526",
174 "R      c #E1F526",
175 "S      c #E3F527",
176 "T      c #E6F527",
177 "U      c #E8F528",
178 "V      c #EAF528",
179 "W      c #ECF429",
180 "X      c #EFF429",
181 "Y      c #F1F42A",
182 "Z      c #F3F42A",
183 "`      c #F5F42B",
184 " .     c #F8F42B",
185 "..     c #FAF42C",
186 "+.     c #FCF42C",
187 "@.     c #FFF42D",
188 "#.     c #FFF22C",
189 "$.     c #FFF12B",
190 "%.     c #FFF02A",
191 "&.     c #FFEF2A",
192 "*.     c #FFEE29",
193 "=.     c #FFED28",
194 "-.     c #FFEC28",
195 ";.     c #FFEB27",
196 ">.     c #FFE926",
197 ",.     c #FFE826",
198 "'.     c #FFE725",
199 ").     c #FFE624",
200 "!.     c #FFE524",
201 "~.     c #FFE423",
202 "{.     c #FFE322",
203 "].     c #FFE222",
204 "^.     c #FFE021",
205 "/.     c #FFDF20",
206 "(.     c #FFDE20",
207 "_.     c #FFDD1F",
208 ":.     c #FFDC1E",
209 "<.     c #FFDB1E",
210 "[.     c #FFDA1D",
211 "}.     c #FFD91C",
212 "|.     c #FFD71B",
213 "1.     c #FFD61B",
214 "2.     c #FFD51A",
215 "3.     c #FFD419",
216 "4.     c #FFD319",
217 "5.     c #FFD218",
218 "6.     c #FFD117",
219 "7.     c #FFD017",
220 "8.     c #FFCF16",
221 "9.     c #FFCD15",
222 "0.     c #FFCC15",
223 "a.     c #FFCB14",
224 "b.     c #FFCA13",
225 "c.     c #FFC913",
226 "d.     c #FFC812",
227 "e.     c #FFC711",
228 "f.     c #FFC611",
229 "g.     c #FFC410",
230 "h.     c #FFC30F",
231 "i.     c #FFC20F",
232 "j.     c #FFC10E",
233 "k.     c #FFC00D",
234 "l.     c #FFBF0C",
235 "m.     c #FFBE0C",
236 "n.     c #FFBD0B",
237 "o.     c #FFBB0A",
238 "p.     c #FFBA0A",
239 "q.     c #FFB909",
240 "r.     c #FFB808",
241 "s.     c #FFB708",
242 "t.     c #FFB607",
243 "u.     c #FFB506",
244 "v.     c #FFB406",
245 "w.     c #FFB205",
246 "x.     c #FFB104",
247 "y.     c #FFB004",
248 "z.     c #FFAF03",
249 "A.     c #FFAE02",
250 "B.     c #FFAD02",
251 "C.     c #FFAC01",
252 "D.     c #FFAB00",
253 "E.     c #FFA900",
254 "F.     c #F11F00",
255 "G.     c #F21E00",
256 "H.     c #F21C00",
257 "I.     c #F31B00",
258 "J.     c #F31A00",
259 "K.     c #F41800",
260 "L.     c #F41700",
261 "M.     c #F51600",
262 "N.     c #F61400",
263 "O.     c #F61300",
264 "P.     c #F71100",
265 "Q.     c #F71000",
266 "R.     c #F80F00",
267 "S.     c #F90D00",
268 "T.     c #F90C00",
269 "U.     c #FA0B00",
270 "V.     c #FA0900",
271 "W.     c #FB0800",
272 "X.     c #FC0600",
273 "Y.     c #FC0500",
274 "Z.     c #FD0400",
275 "`.     c #FD0200",
276 " +     c #FE0100",
277 ".+     c #FE0000",
278 "++     c #FF0000",
279 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
280 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
281 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
282 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
283 ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z `  ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"};
284
285 /* XPM */
286 static const gchar * v_meter_strip_xpm[] = {
287 "5 250 230 2",
288 "       c None",
289 ".      c #FE0000",
290 "+      c #FF0000",
291 "@      c #FE0100",
292 "#      c #FD0200",
293 "$      c #FD0300",
294 "%      c #FD0400",
295 "&      c #FC0500",
296 "*      c #FC0600",
297 "=      c #FC0700",
298 "-      c #FB0800",
299 ";      c #FA0900",
300 ">      c #FA0A00",
301 ",      c #FA0B00",
302 "'      c #F90C00",
303 ")      c #F90D00",
304 "!      c #F80E00",
305 "~      c #F80F00",
306 "{      c #F71000",
307 "]      c #F71100",
308 "^      c #F61200",
309 "/      c #F61300",
310 "(      c #F61400",
311 "_      c #F51600",
312 ":      c #F41700",
313 "<      c #F41800",
314 "[      c #F31A00",
315 "}      c #F31B00",
316 "|      c #F21C00",
317 "1      c #F21E00",
318 "2      c #F11F00",
319 "3      c #F54A00",
320 "4      c #FFA900",
321 "5      c #FFAB00",
322 "6      c #FFAC01",
323 "7      c #FFAD02",
324 "8      c #FFAE02",
325 "9      c #FFAF03",
326 "0      c #FFB004",
327 "a      c #FFB104",
328 "b      c #FFB205",
329 "c      c #FFB406",
330 "d      c #FFB506",
331 "e      c #FFB607",
332 "f      c #FFB708",
333 "g      c #FFB808",
334 "h      c #FFB909",
335 "i      c #FFBA0A",
336 "j      c #FFBB0A",
337 "k      c #FFBC0A",
338 "l      c #FFBD0B",
339 "m      c #FFBE0C",
340 "n      c #FFBF0C",
341 "o      c #FFC00D",
342 "p      c #FFC10E",
343 "q      c #FFC20F",
344 "r      c #FFC30F",
345 "s      c #FFC410",
346 "t      c #FFC511",
347 "u      c #FFC611",
348 "v      c #FFC711",
349 "w      c #FFC812",
350 "x      c #FFC913",
351 "y      c #FFCA13",
352 "z      c #FFCB14",
353 "A      c #FFCC15",
354 "B      c #FFCD15",
355 "C      c #FFCF16",
356 "D      c #FFD017",
357 "E      c #FFD117",
358 "F      c #FFD218",
359 "G      c #FFD319",
360 "H      c #FFD419",
361 "I      c #FFD51A",
362 "J      c #FFD61B",
363 "K      c #FFD71B",
364 "L      c #FFD81C",
365 "M      c #FFD91C",
366 "N      c #FFDA1D",
367 "O      c #FFDB1E",
368 "P      c #FFDC1E",
369 "Q      c #FFDD1F",
370 "R      c #FFDE20",
371 "S      c #FFDF20",
372 "T      c #FFE021",
373 "U      c #FFE222",
374 "V      c #FFE322",
375 "W      c #FFE423",
376 "X      c #FFE524",
377 "Y      c #FFE624",
378 "Z      c #FFE725",
379 "`      c #FFE826",
380 " .     c #FFE926",
381 "..     c #FFEA26",
382 "+.     c #FFEB27",
383 "@.     c #FFEC28",
384 "#.     c #FFED28",
385 "$.     c #FFEE29",
386 "%.     c #FFEF2A",
387 "&.     c #FFF02A",
388 "*.     c #FFF12B",
389 "=.     c #FFF22C",
390 "-.     c #FFF32D",
391 ";.     c #FFF42D",
392 ">.     c #FDF42C",
393 ",.     c #FBF42C",
394 "'.     c #FAF42C",
395 ").     c #F8F42B",
396 "!.     c #F6F42B",
397 "~.     c #F4F42B",
398 "{.     c #F3F42A",
399 "].     c #F1F42A",
400 "^.     c #F0F429",
401 "/.     c #EEF429",
402 "(.     c #ECF429",
403 "_.     c #EAF528",
404 ":.     c #E9F528",
405 "<.     c #E7F528",
406 "[.     c #E5F527",
407 "}.     c #E3F527",
408 "|.     c #E2F526",
409 "1.     c #E0F526",
410 "2.     c #DFF526",
411 "3.     c #DDF525",
412 "4.     c #DBF525",
413 "5.     c #D9F525",
414 "6.     c #D8F524",
415 "7.     c #D6F624",
416 "8.     c #D5F624",
417 "9.     c #D3F624",
418 "0.     c #D1F623",
419 "a.     c #CFF623",
420 "b.     c #CEF622",
421 "c.     c #CCF622",
422 "d.     c #CBF622",
423 "e.     c #C9F621",
424 "f.     c #C7F621",
425 "g.     c #C5F621",
426 "h.     c #C4F720",
427 "i.     c #C2F720",
428 "j.     c #C0F71F",
429 "k.     c #BEF71F",
430 "l.     c #BDF71F",
431 "m.     c #BBF71E",
432 "n.     c #BAF71E",
433 "o.     c #B8F71E",
434 "p.     c #B6F71D",
435 "q.     c #B5F71D",
436 "r.     c #B3F71D",
437 "s.     c #B2F71C",
438 "t.     c #B0F81C",
439 "u.     c #AEF81B",
440 "v.     c #ACF81B",
441 "w.     c #ABF81B",
442 "x.     c #A9F81A",
443 "y.     c #A8F81A",
444 "z.     c #A6F81A",
445 "A.     c #A4F81A",
446 "B.     c #A2F819",
447 "C.     c #A1F819",
448 "D.     c #9FF819",
449 "E.     c #9EF818",
450 "F.     c #9BF918",
451 "G.     c #9AF917",
452 "H.     c #98F917",
453 "I.     c #97F917",
454 "J.     c #95F916",
455 "K.     c #93F916",
456 "L.     c #91F916",
457 "M.     c #90F915",
458 "N.     c #8EF915",
459 "O.     c #8DF914",
460 "P.     c #8BF914",
461 "Q.     c #89FA14",
462 "R.     c #87FA13",
463 "S.     c #86FA13",
464 "T.     c #84FA13",
465 "U.     c #83FA12",
466 "V.     c #81FA12",
467 "W.     c #7FFA12",
468 "X.     c #7DFA12",
469 "Y.     c #7CFA11",
470 "Z.     c #7AFA11",
471 "`.     c #78FA10",
472 " +     c #76FA10",
473 ".+     c #75FB10",
474 "++     c #73FB0F",
475 "@+     c #72FB0F",
476 "#+     c #70FB0F",
477 "$+     c #6EFB0E",
478 "%+     c #6DFB0E",
479 "&+     c #6BFB0E",
480 "*+     c #6AFB0D",
481 "=+     c #68FB0D",
482 "-+     c #66FB0C",
483 ";+     c #64FB0C",
484 ">+     c #63FB0C",
485 ",+     c #61FC0B",
486 "'+     c #60FC0B",
487 ")+     c #5EFC0B",
488 "!+     c #5CFC0A",
489 "~+     c #5AFC0A",
490 "{+     c #59FC09",
491 "]+     c #57FC09",
492 "^+     c #56FC09",
493 "/+     c #53FC09",
494 "(+     c #52FC08",
495 "_+     c #50FC08",
496 ":+     c #4FFD08",
497 "<+     c #4DFD07",
498 "[+     c #4BFD07",
499 "}+     c #49FD07",
500 "|+     c #48FD06",
501 "1+     c #46FD06",
502 "2+     c #45FD05",
503 "3+     c #43FD05",
504 "4+     c #41FD05",
505 "5+     c #3FFD04",
506 "6+     c #3EFD04",
507 "7+     c #3CFD04",
508 "8+     c #3BFE03",
509 "9+     c #39FE03",
510 "0+     c #37FE02",
511 "a+     c #35FE02",
512 "b+     c #34FE02",
513 "c+     c #32FE01",
514 "d+     c #30FE01",
515 "e+     c #2EFE01",
516 "f+     c #2DFE00",
517 "g+     c #2BFE00",
518 ". . + + + ",
519 ". . + + + ",
520 "@ @ @ @ @ ",
521 "# # # # # ",
522 "$ $ $ $ $ ",
523 "% % % % % ",
524 "& & & & & ",
525 "* * * * * ",
526 "= = = = = ",
527 "- - - - - ",
528 "; ; ; ; ; ",
529 "> > > > > ",
530 ", , , , , ",
531 "' ' ' ' ' ",
532 ") ) ) ) ) ",
533 "! ! ! ! ! ",
534 "~ ~ ~ ~ ~ ",
535 "{ { { { { ",
536 "] ] ] ] ] ",
537 "^ ^ ^ ^ ^ ",
538 "/ / / / / ",
539 "( ( ( ( ( ",
540 "_ _ _ _ _ ",
541 ": : : : : ",
542 ": : : : : ",
543 "< < < < < ",
544 "[ [ [ [ [ ",
545 "} } } } } ",
546 "} } } } } ",
547 "| | | | | ",
548 "1 1 1 1 1 ",
549 "2 2 2 2 2 ",
550 "3 3 3 3 3 ",
551 "4 4 4 4 4 ",
552 "5 5 5 5 5 ",
553 "6 6 6 6 6 ",
554 "6 6 6 6 6 ",
555 "7 7 7 7 7 ",
556 "8 8 8 8 8 ",
557 "9 9 9 9 9 ",
558 "9 9 9 9 9 ",
559 "0 0 0 0 0 ",
560 "a a a a a ",
561 "a a a a a ",
562 "b b b b b ",
563 "c c c c c ",
564 "d d d d d ",
565 "d d d d d ",
566 "e e e e e ",
567 "f f f f f ",
568 "g g g g g ",
569 "g g g g g ",
570 "h h h h h ",
571 "i i i i i ",
572 "j j j j j ",
573 "k k k k k ",
574 "l l l l l ",
575 "m m m m m ",
576 "n n n n n ",
577 "n n n n n ",
578 "o o o o o ",
579 "p p p p p ",
580 "q q q q q ",
581 "q q q q q ",
582 "r r r r r ",
583 "s s s s s ",
584 "t t t t t ",
585 "u u u u u ",
586 "v v v v v ",
587 "w w w w w ",
588 "x x x x x ",
589 "x x x x x ",
590 "y y y y y ",
591 "z z z z z ",
592 "A A A A A ",
593 "A A A A A ",
594 "B B B B B ",
595 "C C C C C ",
596 "D D D D D ",
597 "D D D D D ",
598 "E E E E E ",
599 "F F F F F ",
600 "G G G G G ",
601 "G G G G G ",
602 "H H H H H ",
603 "I I I I I ",
604 "I I I I I ",
605 "J J J J J ",
606 "K K K K K ",
607 "L L L L L ",
608 "M M M M M ",
609 "N N N N N ",
610 "O O O O O ",
611 "P P P P P ",
612 "P P P P P ",
613 "Q Q Q Q Q ",
614 "R R R R R ",
615 "S S S S S ",
616 "S S S S S ",
617 "T T T T T ",
618 "U U U U U ",
619 "V V V V V ",
620 "V V V V V ",
621 "W W W W W ",
622 "X X X X X ",
623 "Y Y Y Y Y ",
624 "Y Y Y Y Y ",
625 "Z Z Z Z Z ",
626 "` ` ` ` ` ",
627 " . . . . .",
628 "..........",
629 "+.+.+.+.+.",
630 "@.@.@.@.@.",
631 "#.#.#.#.#.",
632 "#.#.#.#.#.",
633 "$.$.$.$.$.",
634 "%.%.%.%.%.",
635 "&.&.&.&.&.",
636 "&.&.&.&.&.",
637 "*.*.*.*.*.",
638 "=.=.=.=.=.",
639 "-.-.-.-.-.",
640 ";.;.;.;.;.",
641 ";.;.;.;.;.",
642 ">.>.>.>.>.",
643 ",.,.,.,.,.",
644 "'.'.'.'.'.",
645 ").).).).).",
646 "!.!.!.!.!.",
647 "~.~.~.~.~.",
648 "{.{.{.{.{.",
649 "].].].].].",
650 "^.^.^.^.^.",
651 "/././././.",
652 "(.(.(.(.(.",
653 "_._._._._.",
654 ":.:.:.:.:.",
655 "<.<.<.<.<.",
656 "[.[.[.[.[.",
657 "}.}.}.}.}.",
658 "|.|.|.|.|.",
659 "1.1.1.1.1.",
660 "2.2.2.2.2.",
661 "3.3.3.3.3.",
662 "4.4.4.4.4.",
663 "5.5.5.5.5.",
664 "6.6.6.6.6.",
665 "7.7.7.7.7.",
666 "8.8.8.8.8.",
667 "9.9.9.9.9.",
668 "0.0.0.0.0.",
669 "a.a.a.a.a.",
670 "b.b.b.b.b.",
671 "c.c.c.c.c.",
672 "d.d.d.d.d.",
673 "e.e.e.e.e.",
674 "f.f.f.f.f.",
675 "g.g.g.g.g.",
676 "h.h.h.h.h.",
677 "i.i.i.i.i.",
678 "j.j.j.j.j.",
679 "k.k.k.k.k.",
680 "l.l.l.l.l.",
681 "m.m.m.m.m.",
682 "n.n.n.n.n.",
683 "o.o.o.o.o.",
684 "p.p.p.p.p.",
685 "q.q.q.q.q.",
686 "r.r.r.r.r.",
687 "s.s.s.s.s.",
688 "t.t.t.t.t.",
689 "u.u.u.u.u.",
690 "v.v.v.v.v.",
691 "w.w.w.w.w.",
692 "x.x.x.x.x.",
693 "y.y.y.y.y.",
694 "z.z.z.z.z.",
695 "A.A.A.A.A.",
696 "B.B.B.B.B.",
697 "C.C.C.C.C.",
698 "D.D.D.D.D.",
699 "E.E.E.E.E.",
700 "F.F.F.F.F.",
701 "G.G.G.G.G.",
702 "H.H.H.H.H.",
703 "I.I.I.I.I.",
704 "J.J.J.J.J.",
705 "K.K.K.K.K.",
706 "L.L.L.L.L.",
707 "M.M.M.M.M.",
708 "N.N.N.N.N.",
709 "O.O.O.O.O.",
710 "P.P.P.P.P.",
711 "Q.Q.Q.Q.Q.",
712 "R.R.R.R.R.",
713 "S.S.S.S.S.",
714 "T.T.T.T.T.",
715 "U.U.U.U.U.",
716 "V.V.V.V.V.",
717 "W.W.W.W.W.",
718 "X.X.X.X.X.",
719 "Y.Y.Y.Y.Y.",
720 "Z.Z.Z.Z.Z.",
721 "`.`.`.`.`.",
722 " + + + + +",
723 ".+.+.+.+.+",
724 "++++++++++",
725 "@+@+@+@+@+",
726 "#+#+#+#+#+",
727 "$+$+$+$+$+",
728 "%+%+%+%+%+",
729 "&+&+&+&+&+",
730 "*+*+*+*+*+",
731 "=+=+=+=+=+",
732 "-+-+-+-+-+",
733 ";+;+;+;+;+",
734 ">+>+>+>+>+",
735 ",+,+,+,+,+",
736 "'+'+'+'+'+",
737 ")+)+)+)+)+",
738 "!+!+!+!+!+",
739 "~+~+~+~+~+",
740 "{+{+{+{+{+",
741 "]+]+]+]+]+",
742 "^+^+^+^+^+",
743 "/+/+/+/+/+",
744 "(+(+(+(+(+",
745 "_+_+_+_+_+",
746 ":+:+:+:+:+",
747 "<+<+<+<+<+",
748 "[+[+[+[+[+",
749 "}+}+}+}+}+",
750 "|+|+|+|+|+",
751 "1+1+1+1+1+",
752 "2+2+2+2+2+",
753 "3+3+3+3+3+",
754 "4+4+4+4+4+",
755 "5+5+5+5+5+",
756 "6+6+6+6+6+",
757 "7+7+7+7+7+",
758 "8+8+8+8+8+",
759 "9+9+9+9+9+",
760 "0+0+0+0+0+",
761 "a+a+a+a+a+",
762 "b+b+b+b+b+",
763 "c+c+c+c+c+",
764 "d+d+d+d+d+",
765 "e+e+e+e+e+",
766 "f+f+f+f+f+",
767 "g+g+g+g+g+"};
768
769 static const char* channel_setup_names[] = {
770         "mono",
771         "stereo",
772         "3 channels",
773         "4 channels",
774         "5 channels",
775         "8 channels",
776         "manual setup",
777         0
778 };
779
780 vector<string> channel_combo_strings;
781
782 ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
783
784         : Gtkmm2ext::UI ("ardour", argcp, argvp, rcfile),
785           
786           primary_clock (X_("TransportClockDisplay"), true, false, true),
787           secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
788           preroll_clock (X_("PreRollClock"), true, true),
789           postroll_clock (X_("PostRollClock"), true, true),
790
791           /* adjuster table */
792
793           adjuster_table (3, 3),
794
795           /* preroll stuff */
796
797           preroll_button (_("pre\nroll")),
798           postroll_button (_("post\nroll")),
799
800           /* big clock */
801
802           big_clock ("BigClockDisplay", true),
803
804           /* transport */
805
806           shuttle_units_button (_("% ")),
807           shuttle_style_button (_("spring")),
808
809           punch_in_button (_("punch\nin")),
810           punch_out_button (_("punch\nout")),
811           auto_return_button (_("auto\nreturn")),
812           auto_play_button (_("auto\nplay")),
813           auto_input_button (_("auto\ninput")),
814           click_button (_("click")),
815           follow_button (_("follow\nPH")),
816           auditioning_alert_button (_("AUDITIONING")),
817           solo_alert_button (_("SOLO")),
818           shown_flag (false)
819
820 {
821         using namespace Gtk::Menu_Helpers;
822
823         Gtkmm2ext::init();
824
825         /* actually, its already loaded, but ... */
826
827         cerr << "Loading UI configuration file " << rcfile << endl;
828
829         about = 0;
830
831         if (theArdourUI == 0) {
832                 theArdourUI = this;
833         }
834
835         // allow run-time rebinding of accels
836
837         Settings::get_default()->property_gtk_can_change_accels() = true;
838
839         ActionManager::init ();
840         
841         m_new_session_dialog = 0;
842         m_new_session_dialog_ref = NewSessionDialogFactory::create();
843         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
844         editor = 0;
845         mixer = 0;
846         session = 0;
847         _session_is_new = false;
848         big_clock_window = 0;
849         session_selector_window = 0;
850         last_key_press_time = 0;
851         connection_editor = 0;
852         add_route_dialog = 0;
853         route_params = 0;
854         option_editor = 0;
855         location_ui = 0;
856         open_session_selector = 0;
857         have_configure_timeout = false;
858         have_disk_overrun_displayed = false;
859         have_disk_underrun_displayed = false;
860         _will_create_new_session_automatically = false;
861         session_loaded = false;
862
863
864         last_configure_time.tv_sec = 0;
865         last_configure_time.tv_usec = 0;
866
867         shuttle_grabbed = false;
868         shuttle_fract = 0.0;
869
870         set_shuttle_units (Percentage);
871         set_shuttle_behaviour (Sprung);
872
873         shuttle_style_menu = 0;
874         shuttle_unit_menu = 0;
875
876         gettimeofday (&last_peak_grab, 0);
877         gettimeofday (&last_shuttle_request, 0);
878
879         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
880         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
881         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
882         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
883
884         /* handle pending state with a dialog */
885
886         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
887
888         channel_combo_strings = internationalize (channel_setup_names);
889         
890         /* have to wait for AudioEngine and Configuration before proceeding */
891 }
892
893 void
894 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
895 {
896         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
897         
898         string msg = string_compose (_("\
899 You cannot record-enable\n\
900 track %1\n\
901 because it has no input connections.\n\
902 You would be wasting space recording silence."),
903                               ds->name());
904
905         ArdourMessage message (editor, X_("cannotrecord"), msg);
906 }
907
908 void
909 ARDOUR_UI::set_engine (AudioEngine& e)
910 {
911         engine = &e;
912
913         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
914         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
915         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
916         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
917
918         _tooltips.enable();
919
920         keyboard = new Keyboard;
921         install_keybindings ();
922
923         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
924         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
925
926         if (setup_windows ()) {
927                 throw failed_constructor ();
928         }
929
930         if (GTK_ARDOUR::show_key_actions) {
931                 // GTK2FIX
932                 // show_all_actions ();
933                 exit (0);
934         }
935
936         /* start with timecode, metering enabled
937         */
938         
939         blink_timeout_tag = -1;
940
941         /* this being a GUI and all, we want peakfiles */
942
943         FileSource::set_build_peakfiles (true);
944         FileSource::set_build_missing_peakfiles (true);
945
946         if (Source::start_peak_thread ()) {
947                 throw failed_constructor();
948         }
949
950         /* start the time-of-day-clock */
951         
952         update_wall_clock ();
953         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
954
955         update_disk_space ();
956         update_cpu_load ();
957         update_sample_rate (engine->frame_rate());
958
959         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
960         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
961 }
962
963 ARDOUR_UI::~ARDOUR_UI ()
964 {
965         save_ardour_state ();
966
967         if (keyboard) {
968                 delete keyboard;
969         }
970
971         if (editor) {
972                 delete editor;
973         }
974
975         if (mixer) {
976                 delete mixer;
977         }
978
979         if (add_route_dialog) {
980                 delete add_route_dialog;
981         }
982
983         Source::stop_peak_thread ();
984 }
985
986 gint
987 ARDOUR_UI::configure_timeout ()
988 {
989         struct timeval now;
990         struct timeval diff;
991
992         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
993                 /* no configure events yet */
994                 return TRUE;
995         }
996
997         gettimeofday (&now, 0);
998         timersub (&now, &last_configure_time, &diff);
999
1000         /* force a gap of 0.5 seconds since the last configure event
1001          */
1002
1003         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1004                 return TRUE;
1005         } else {
1006                 have_configure_timeout = false;
1007                 save_ardour_state ();
1008                 return FALSE;
1009         }
1010 }
1011
1012 gboolean
1013 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1014 {
1015         if (have_configure_timeout) {
1016                 gettimeofday (&last_configure_time, 0);
1017         } else {
1018                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1019                 have_configure_timeout = true;
1020         }
1021                 
1022         return FALSE;
1023 }
1024
1025 void
1026 ARDOUR_UI::save_ardour_state ()
1027 {
1028         if (!keyboard || !mixer || !editor) {
1029                 return;
1030         }
1031         
1032         /* XXX this is all a bit dubious. add_extra_xml() uses
1033            a different lifetime model from add_instant_xml().
1034         */
1035
1036         XMLNode* node = new XMLNode (keyboard->get_state());
1037         Config->add_extra_xml (*node);
1038         Config->save_state();
1039
1040         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1041         XMLNode& mnode (mixer->get_state());
1042
1043         if (session) {
1044                 session->add_instant_xml(enode, session->path());
1045                 session->add_instant_xml(mnode, session->path());
1046         } else {
1047                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1048                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1049         }
1050 }
1051
1052 void
1053 ARDOUR_UI::startup ()
1054 {
1055         /* Once the UI is up and running, start the audio engine. Doing
1056            this before the UI is up and running can cause problems
1057            when not running with SCHED_FIFO, because the amount of
1058            CPU and disk work needed to get the UI started can interfere
1059            with the scheduling of the audio thread.
1060         */
1061
1062         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1063 }
1064
1065 void
1066 ARDOUR_UI::finish()
1067 {
1068         if (session && session->dirty()) {
1069                 switch (ask_about_saving_session(_("quit"))) {
1070                 case -1:
1071                         return;
1072                         break;
1073                 case 1:
1074                         /* use the default name */
1075                         if (save_state_canfail ("")) {
1076                                 /* failed - don't quit */
1077                                 ArdourMessage (editor, X_("badsave dialog"),
1078                                                _("\
1079 Ardour was unable to save your session.\n\n\
1080 If you still wish to quit, please use the\n\n\
1081 \"Just quit\" option."));
1082                                 return;
1083                         }
1084                         break;
1085                 case 0:
1086                         break;
1087                 }
1088         }
1089
1090         quit ();
1091 }
1092
1093 int
1094 ARDOUR_UI::ask_about_saving_session (string what)
1095 {
1096         ArdourDialog window (_("ardour: save session?"));
1097         Gtk::Label  prompt_label;
1098         string msg;
1099
1100         msg = string_compose(_("Save and %1"), what);
1101         window.add_button (msg, RESPONSE_ACCEPT);
1102         msg = string_compose(_("Just %1"), what);
1103         window.add_button (msg, RESPONSE_APPLY);
1104         msg = string_compose(_("Don't %1"), what);
1105         window.add_button (msg, RESPONSE_REJECT);
1106
1107         Gtk::Button noquit_button (msg);
1108         noquit_button.set_name ("EditorGTKButton");
1109
1110         string prompt;
1111         string type;
1112
1113         if (session->snap_name() == session->name()) {
1114                 type = _("session");
1115         } else {
1116                 type = _("snapshot");
1117         }
1118         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?"), 
1119                          type, session->snap_name());
1120         
1121         prompt_label.set_text (prompt);
1122         prompt_label.set_alignment (0.5, 0.5);
1123         prompt_label.set_name (X_("PrompterLabel"));
1124         
1125         window.get_vbox()->pack_start (prompt_label);
1126
1127         window.set_name (_("Prompter"));
1128         window.set_position (Gtk::WIN_POS_MOUSE);
1129         window.set_modal (true);
1130         window.show_all ();
1131
1132         save_the_session = 0;
1133
1134         editor->ensure_float (window);
1135
1136         ResponseType r = (ResponseType) window.run();
1137
1138         window.hide ();
1139
1140         switch (r) {
1141         case RESPONSE_ACCEPT: // save and get out of here
1142                 return 1;
1143         case RESPONSE_APPLY:  // get out of here
1144                 return 0;
1145         default:
1146                 break;
1147         }
1148
1149         return -1;
1150 }
1151         
1152 gint
1153 ARDOUR_UI::every_second ()
1154 {
1155         update_cpu_load ();
1156         update_buffer_load ();
1157         update_disk_space ();
1158         // update_disk_rate ();
1159         return TRUE;
1160 }
1161
1162 gint
1163 ARDOUR_UI::every_point_one_seconds ()
1164 {
1165         struct timeval now;
1166         struct timeval diff;
1167         
1168         /* do not attempt to grab peak power more than once per cycle.
1169          */
1170
1171         gettimeofday (&now, 0);
1172         timersub (&now, &last_peak_grab, &diff);
1173
1174         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1175                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1176                 last_peak_grab = now;
1177         } 
1178
1179         update_speed_display ();
1180         RapidScreenUpdate(); /* EMIT_SIGNAL */
1181         return TRUE;
1182 }
1183
1184 gint
1185 ARDOUR_UI::every_point_zero_one_seconds ()
1186 {
1187         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1188         return TRUE;
1189 }
1190
1191 void
1192 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1193 {
1194         char buf[32];
1195
1196         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1197
1198         if (!engine->connected()) {
1199
1200                 snprintf (buf, sizeof (buf), _("disconnected"));
1201
1202         } else {
1203
1204                 jack_nframes_t rate = engine->frame_rate();
1205                 
1206                 if (fmod (rate, 1000.0) != 0.0) {
1207                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
1208                                   (float) rate/1000.0f,
1209                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1210                 } else {
1211                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
1212                                   rate/1000,
1213                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1214                 }
1215         }
1216
1217         sample_rate_label.set_text (buf);
1218 }
1219
1220 void
1221 ARDOUR_UI::update_cpu_load ()
1222 {
1223         char buf[32];
1224         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1225         cpu_load_label.set_text (buf);
1226 }
1227
1228 void
1229 ARDOUR_UI::update_disk_rate ()
1230 {
1231         char buf[64];
1232
1233         if (session) {
1234                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
1235                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1236                 disk_rate_label.set_text (buf);
1237         } else {
1238                 disk_rate_label.set_text ("");
1239         }
1240 }
1241
1242 void
1243 ARDOUR_UI::update_buffer_load ()
1244 {
1245         char buf[64];
1246
1247         if (session) {
1248                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
1249                           session->playback_load(), session->capture_load());
1250                 buffer_load_label.set_text (buf);
1251         } else {
1252                 buffer_load_label.set_text ("");
1253         }
1254 }
1255
1256 void
1257 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1258 {
1259         if (ds.record_enabled()) {
1260                 rec_enabled_diskstreams++;
1261         }
1262 }
1263
1264 void
1265 ARDOUR_UI::update_disk_space()
1266 {
1267         if (session == 0) {
1268                 return;
1269         }
1270
1271         jack_nframes_t frames = session->available_capture_duration();
1272         char buf[64];
1273
1274         if (frames == max_frames) {
1275                 strcpy (buf, _("space: 24hrs+"));
1276         } else {
1277                 int hrs;
1278                 int mins;
1279                 int secs;
1280                 jack_nframes_t fr = session->frame_rate();
1281                 
1282                 if (session->actively_recording()){
1283                         
1284                         rec_enabled_diskstreams = 0;
1285                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1286                         
1287                         if (rec_enabled_diskstreams) {
1288                                 frames /= rec_enabled_diskstreams;
1289                         }
1290                         
1291                 } else {
1292                         
1293                         /* hmmm. shall we divide by the route count? or the diskstream count?
1294                            or what? for now, do nothing ...
1295                         */
1296                         
1297                 }
1298                 
1299                 hrs  = frames / (fr * 3600);
1300                 frames -= hrs * fr * 3600;
1301                 mins = frames / (fr * 60);
1302                 frames -= mins * fr * 60;
1303                 secs = frames / fr;
1304                 
1305                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1306         }
1307
1308         disk_space_label.set_text (buf);
1309 }                 
1310
1311 gint
1312 ARDOUR_UI::update_wall_clock ()
1313 {
1314         time_t now;
1315         struct tm *tm_now;
1316         char buf[16];
1317
1318         time (&now);
1319         tm_now = localtime (&now);
1320
1321         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1322         wall_clock_label.set_text (buf);
1323
1324         return TRUE;
1325 }
1326
1327 void
1328 ARDOUR_UI::toggle_recording_plugins ()
1329 {
1330         /* XXX use toggle_some_session_state */
1331
1332         if (session == 0) {
1333                 return;
1334         }
1335
1336         session->set_recording_plugins (!session->get_recording_plugins());
1337 }
1338         
1339 void
1340 ARDOUR_UI::toggle_auto_play ()
1341
1342 {
1343         toggle_some_session_state (auto_play_button,
1344                                    &Session::get_auto_play,
1345                                    &Session::set_auto_play);
1346 }
1347
1348 void
1349 ARDOUR_UI::toggle_auto_return ()
1350
1351 {
1352         toggle_some_session_state (auto_return_button,
1353                                    &Session::get_auto_return,
1354                                    &Session::set_auto_return);
1355 }
1356
1357 void
1358 ARDOUR_UI::toggle_click ()
1359 {
1360         toggle_some_session_state (click_button,
1361                                    &Session::get_clicking,
1362                                    &Session::set_clicking);
1363 }
1364
1365 void
1366 ARDOUR_UI::follow_changed ()
1367 {
1368         bool x;
1369
1370         if (!editor) {
1371                 return;
1372         }
1373
1374         if (follow_button.get_active() != (x = editor->follow_playhead())) {
1375                 follow_button.set_active (x);
1376         }
1377 }
1378
1379 void
1380 ARDOUR_UI::toggle_follow ()
1381 {
1382         bool x;
1383
1384         if (!editor) {
1385                 return;
1386         }
1387
1388         if (editor->follow_playhead() != (x = follow_button.get_active())) {
1389                 editor->set_follow_playhead (x);
1390         }
1391 }
1392
1393 void
1394 ARDOUR_UI::toggle_session_auto_loop ()
1395 {
1396         if (session) {
1397                 if (session->get_auto_loop()) {
1398                         if (session->transport_rolling()) {
1399                                 transport_roll();
1400                         }
1401                         else {
1402                                 session->request_auto_loop (false);
1403                         }
1404                 }
1405                 else {
1406                         session->request_auto_loop (true);
1407                 }
1408         }
1409 }
1410
1411 void
1412 ARDOUR_UI::toggle_session_punch_in ()
1413 {
1414         if (session) {
1415                 session->set_punch_in (!session->get_punch_in());
1416         }
1417 }
1418
1419 void
1420 ARDOUR_UI::toggle_punch_out ()
1421 {
1422         toggle_some_session_state (punch_out_button,
1423                                    &Session::get_punch_out,
1424                                    &Session::set_punch_out);
1425 }
1426
1427 void
1428 ARDOUR_UI::toggle_punch_in ()
1429 {
1430         toggle_some_session_state (punch_in_button,
1431                                    &Session::get_punch_in,
1432                                    &Session::set_punch_in);
1433 }
1434
1435 void
1436 ARDOUR_UI::map_button_state ()
1437
1438 {
1439         map_some_session_state (auto_return_button,
1440                                 &Session::get_auto_return);
1441         map_some_session_state (auto_play_button,
1442                                 &Session::get_auto_play);
1443         map_some_session_state (auto_input_button,
1444                                 &Session::get_auto_input);
1445         map_some_session_state (punch_in_button,
1446                                 &Session::get_punch_in);
1447         map_some_session_state (punch_out_button,
1448                                 &Session::get_punch_out);
1449         map_some_session_state (click_button,
1450                                 &Session::get_clicking);
1451 }
1452
1453 void
1454 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1455 {
1456         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1457 }
1458
1459 void
1460 ARDOUR_UI::map_control_change (Session::ControlType t)
1461 {
1462         switch (t) {
1463         case Session::AutoPlay:
1464                 map_some_session_state (auto_play_button, &Session::get_auto_play);
1465                 break;
1466
1467         case Session::AutoLoop:
1468                 break;
1469
1470         case Session::AutoReturn:
1471                 map_some_session_state (auto_return_button, &Session::get_auto_return);
1472                 break;
1473
1474         case Session::AutoInput:
1475                 map_some_session_state (auto_input_button, &Session::get_auto_input);
1476                 break;
1477
1478         case Session::PunchOut:
1479                 map_some_session_state (punch_in_button, &Session::get_punch_out);
1480                 break;
1481
1482         case Session::PunchIn:
1483                 map_some_session_state (punch_in_button, &Session::get_punch_in);
1484                 break;
1485
1486         case Session::Clicking:
1487                 map_some_session_state (click_button, &Session::get_clicking);
1488                 break;
1489
1490         case Session::SlaveType:
1491 //              map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1492                 break;
1493
1494         case Session::SendMTC:
1495 //              map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1496                 break;
1497
1498         case Session::SendMMC:
1499 //              map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1500                 break;
1501
1502         case Session::MMCControl:       
1503 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1504                 break;
1505
1506         case Session::MidiFeedback:       
1507 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1508                 break;
1509         case Session::MidiControl:       
1510 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1511                 break;
1512                 
1513         case Session::Live:
1514                 break;
1515
1516         case Session::RecordingPlugins:
1517                 break;
1518
1519         case Session::CrossFadesActive:
1520                 break;
1521                 
1522         case Session::EditingMode:
1523                 break;
1524
1525         case Session::PlayRange:
1526                 break;
1527
1528         case Session::AlignChoice:
1529                 /* don't care, this is handled by the options editor */
1530                 break;
1531         case Session::SeamlessLoop:
1532                 /* don't care, this is handled by the options editor */
1533                 break;
1534                
1535         }
1536 }
1537
1538 void
1539 ARDOUR_UI::control_methods_adjusted ()
1540
1541 {
1542         int which_method;
1543
1544         which_method = (int) online_control_button->adjustment.get_value();
1545         switch (which_method) {
1546         case 0:
1547                 allow_mmc_and_local ();
1548                 break;
1549         case 1:
1550                 allow_mmc_only ();
1551                 break;
1552         case 2:
1553                 allow_local_only ();
1554                 break;
1555         default:
1556                 fatal << _("programming error: impossible control method") << endmsg;
1557         }
1558 }
1559         
1560
1561 void
1562 ARDOUR_UI::mmc_device_id_adjusted ()
1563
1564 {
1565 #if 0
1566         if (mmc) {
1567                 int dev_id = (int) mmc_id_button->adjustment.get_value();
1568                 mmc->set_device_id (dev_id);
1569         }
1570 #endif
1571 }
1572
1573 void
1574 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1575                                    bool (Session::*get)() const)
1576         
1577 {
1578         bool x;
1579
1580         if (session == 0) {
1581                 return;
1582         }
1583         
1584         if (button.get_active() != (x = (session->*get)())) {
1585                 button.set_active (x);
1586         }
1587 }
1588
1589 void
1590 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1591                                       bool (Session::*get)() const,
1592                                       void (Session::*set)(bool))
1593
1594 {
1595         bool button_state;
1596         bool session_state;
1597
1598         if (session == 0) {
1599                 return;
1600         }
1601
1602         button_state = button.get_active ();
1603         session_state = (session->*get)();
1604
1605         if (button_state != session_state) {
1606                 (session->*set) (button_state);
1607 #if 0
1608         
1609                 /* check that it worked, and reverse
1610                    the button state if it didn't
1611                 */
1612
1613                 if ((session->*get)() != button_state) {
1614                         button->set_active (!button_state);
1615                 }
1616 #endif
1617
1618         }
1619 }       
1620
1621 gint
1622 ARDOUR_UI::session_menu (GdkEventButton *ev)
1623 {
1624         session_popup_menu->popup (0, 0);
1625         return TRUE;
1626 }
1627
1628 void
1629 ARDOUR_UI::redisplay_recent_sessions ()
1630 {
1631         vector<string *> *sessions;
1632         vector<string *>::iterator i;
1633         RecentSessionsSorter cmp;
1634         
1635         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1636         recent_session_model->clear ();
1637
1638         RecentSessions rs;
1639         ARDOUR::read_recent_sessions (rs);
1640
1641         if (rs.empty()) {
1642                 recent_session_display.set_model (recent_session_model);
1643                 return;
1644         }
1645
1646         /* sort them alphabetically */
1647         sort (rs.begin(), rs.end(), cmp);
1648         sessions = new vector<string*>;
1649
1650         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1651                 sessions->push_back (new string ((*i).second));
1652         }
1653
1654         for (i = sessions->begin(); i != sessions->end(); ++i) {
1655
1656                 vector<string*>* states;
1657                 vector<const gchar*> item;
1658                 string fullpath = *(*i);
1659                 
1660                 /* remove any trailing / */
1661
1662                 if (fullpath[fullpath.length()-1] == '/') {
1663                         fullpath = fullpath.substr (0, fullpath.length()-1);
1664                 }
1665
1666                 /* now get available states for this session */
1667
1668                 if ((states = Session::possible_states (fullpath)) == 0) {
1669                         /* no state file? */
1670                         continue;
1671                 }
1672
1673                 TreeModel::Row row = *(recent_session_model->append());
1674
1675                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1676                 row[recent_session_columns.fullpath] = fullpath;
1677
1678                 if (states->size() > 1) {
1679
1680                         /* add the children */
1681                         
1682                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1683                                 
1684                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1685
1686                                 child_row[recent_session_columns.visible_name] = **i2;
1687                                 child_row[recent_session_columns.fullpath] = fullpath;
1688
1689                                 delete *i2;
1690                         }
1691                 }
1692
1693                 delete states;
1694         }
1695
1696         recent_session_display.set_model (recent_session_model);
1697         delete sessions;
1698 }
1699
1700 void
1701 ARDOUR_UI::build_session_selector ()
1702 {
1703         session_selector_window = new ArdourDialog ("session selector");
1704         
1705         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1706
1707         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1708         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1709
1710         recent_session_model = TreeStore::create (recent_session_columns);
1711         recent_session_display.set_model (recent_session_model);
1712         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1713         recent_session_display.set_headers_visible (false);
1714
1715         scroller->add (recent_session_display);
1716         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1717
1718         session_selector_window->set_name ("SessionSelectorWindow");
1719         session_selector_window->set_size_request (200, 400);
1720         session_selector_window->get_vbox()->pack_start (*scroller);
1721         session_selector_window->show_all_children();
1722 }
1723
1724 void
1725 ARDOUR_UI::open_recent_session ()
1726 {
1727         /* popup selector window */
1728
1729         if (session_selector_window == 0) {
1730                 build_session_selector ();
1731         }
1732
1733         redisplay_recent_sessions ();
1734
1735         ResponseType r = (ResponseType) session_selector_window->run ();
1736
1737         session_selector_window->hide();
1738
1739         switch (r) {
1740         case RESPONSE_ACCEPT:
1741                 break;
1742         default:
1743                 return;
1744         }
1745
1746         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1747
1748         if (i == recent_session_model->children().end()) {
1749                 return;
1750         }
1751         
1752         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1753         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1754
1755         _session_is_new = false;
1756
1757         load_session (path, state);
1758 }
1759
1760 bool
1761 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1762 {
1763         struct stat statbuf;
1764         
1765         if (stat (info.filename.c_str(), &statbuf) != 0) {
1766                 return false;
1767         }
1768
1769         if (!S_ISDIR(statbuf.st_mode)) {
1770                 return false;
1771         }
1772
1773         string session_file = info.filename;
1774         session_file += '/';
1775         session_file += PBD::basename (info.filename);
1776         session_file += ".ardour";
1777         
1778         if (stat (session_file.c_str(), &statbuf) != 0) {
1779                 return false;
1780         }
1781
1782         return S_ISREG (statbuf.st_mode);
1783 }
1784
1785 void
1786 ARDOUR_UI::open_session ()
1787 {
1788         /* popup selector window */
1789
1790         if (open_session_selector == 0) {
1791                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1792                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1793                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1794                 
1795                 FileFilter filter_ardour;
1796                 filter_ardour.set_name (_("Ardour sessions"));
1797                 filter_ardour.add_pattern("*.ardour");
1798                 open_session_selector->add_filter (filter_ardour);
1799         }
1800
1801         switch (open_session_selector->run ()) {
1802         case RESPONSE_OK:
1803                 break;
1804         default:
1805                 open_session_selector->hide();
1806                 return;
1807         }
1808
1809         open_session_selector->hide();
1810         string session_path = open_session_selector->get_filename();
1811         string path, name;
1812         bool isnew;
1813
1814         if (session_path.length() > 0) {
1815                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1816                         _session_is_new = isnew;
1817                         load_session (path, name);
1818                 }
1819         }
1820 }
1821
1822
1823 void
1824 ARDOUR_UI::session_add_midi_track ()
1825 {
1826         cerr << _("Patience is a virtue.\n");
1827 }
1828
1829 void
1830 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1831 {
1832         Route* route;
1833
1834         if (session == 0) {
1835                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1836                 return;
1837         }
1838
1839         try { 
1840                 if (disk) {
1841                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1842                                 error << _("could not create new audio track") << endmsg;
1843                         }
1844                 } else {
1845                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1846                                 error << _("could not create new audio bus") << endmsg;
1847                         }
1848                 }
1849                 
1850 #if CONTROLOUTS
1851                 if (need_control_room_outs) {
1852                         pan_t pans[2];
1853                         
1854                         pans[0] = 0.5;
1855                         pans[1] = 0.5;
1856                         
1857                         route->set_stereo_control_outs (control_lr_channels);
1858                         route->control_outs()->set_stereo_pan (pans, this);
1859                 }
1860 #endif /* CONTROLOUTS */
1861         }
1862
1863         catch (...) {
1864                 ArdourMessage msg (editor, X_("noport dialog"),
1865                                    _("There are insufficient JACK ports available\n\
1866 to create a new track or bus.\n\
1867 You should save Ardour, exit and\n\
1868 restart JACK with more ports."));
1869         }
1870 }
1871
1872 void
1873 ARDOUR_UI::diskstream_added (DiskStream* ds)
1874 {
1875 }
1876
1877 void
1878 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1879 {
1880         jack_nframes_t _preroll;
1881
1882         if (session) {
1883                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1884
1885                 if (new_position > _preroll) {
1886                         new_position -= _preroll;
1887                 } else {
1888                         new_position = 0;
1889                 }
1890
1891                 session->request_locate (new_position);
1892         }
1893 }
1894
1895 void
1896 ARDOUR_UI::transport_goto_start ()
1897 {
1898         if (session) {
1899                 session->request_locate (0);
1900
1901                 
1902                 /* force displayed area in editor to start no matter
1903                    what "follow playhead" setting is.
1904                 */
1905                 
1906                 if (editor) {
1907                         editor->reposition_x_origin (0);
1908                 }
1909         }
1910 }
1911
1912 void
1913 ARDOUR_UI::transport_goto_end ()
1914 {
1915         if (session) {
1916                 jack_nframes_t frame = session->current_end_frame();
1917                 session->request_locate (frame);
1918
1919                 /* force displayed area in editor to start no matter
1920                    what "follow playhead" setting is.
1921                 */
1922                 
1923                 if (editor) {
1924                         editor->reposition_x_origin (frame);
1925                 }
1926         }
1927 }
1928
1929 gint 
1930 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1931 {
1932
1933
1934         if (session) {
1935                         if (session->transport_stopped()) {
1936                         session->request_locate (session->last_transport_start());
1937                 } else {
1938                         if (session->get_auto_loop()) {
1939                                 session->request_auto_loop (false);
1940                         }
1941
1942                         Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1943                         session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1944                         }
1945         }
1946
1947         return TRUE;
1948 }
1949
1950 gint
1951 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1952 {
1953         transport_roll ();
1954         return TRUE;
1955 }
1956
1957 void
1958 ARDOUR_UI::transport_stop ()
1959 {
1960         if (!session) {
1961                 return;
1962         }
1963
1964         if (session->is_auditioning()) {
1965                 session->cancel_audition ();
1966                 return;
1967         }
1968         
1969         if (session->get_auto_loop()) {
1970                 session->request_auto_loop (false);
1971         }
1972         
1973         session->request_stop ();
1974 }
1975
1976 void
1977 ARDOUR_UI::transport_stop_and_forget_capture ()
1978 {
1979         if (session) {
1980                 session->request_stop (true);
1981         }
1982 }
1983
1984 void
1985 ARDOUR_UI::remove_last_capture()
1986 {
1987         if (editor) {
1988                 editor->remove_last_capture();
1989         }
1990 }
1991
1992 void
1993 ARDOUR_UI::transport_record ()
1994 {
1995         if (session) {
1996                 switch (session->record_status()) {
1997                 case Session::Disabled:
1998                         if (session->ntracks() == 0) {
1999                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
2000                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
2001                                 return;
2002                         }
2003                         session->maybe_enable_record ();
2004                         break;
2005                 case Session::Recording:
2006                 case Session::Enabled:
2007                         session->disable_record ();
2008                 }
2009         }
2010 }
2011
2012 void
2013 ARDOUR_UI::transport_roll ()
2014 {
2015         bool rolling;
2016
2017         if (!session) {
2018                 return;
2019         }
2020
2021         rolling = session->transport_rolling ();
2022
2023         if (session->get_auto_loop()) {
2024                 session->request_auto_loop (false);
2025                 auto_loop_button.set_active (false);
2026                 roll_button.set_active (true);
2027         } else if (session->get_play_range ()) {
2028                 session->request_play_range (false);
2029                 play_selection_button.set_active (false);
2030         } else if (rolling) {
2031                 session->request_locate (session->last_transport_start(), true);
2032         }
2033
2034         session->request_transport_speed (1.0f);
2035 }
2036
2037 void
2038 ARDOUR_UI::transport_loop()
2039 {
2040         if (session) {
2041                 if (session->get_auto_loop()) {
2042                         if (session->transport_rolling()) {
2043                                 Location * looploc = session->locations()->auto_loop_location();
2044                                 if (looploc) {
2045                                         session->request_locate (looploc->start(), true);
2046                                 }
2047                         }
2048                 }
2049                 else {
2050                         session->request_auto_loop (true);
2051                 }
2052         }
2053 }
2054
2055 void
2056 ARDOUR_UI::transport_play_selection ()
2057 {
2058         if (!session) {
2059                 return;
2060         }
2061
2062         if (!session->get_play_range()) {
2063                 session->request_stop ();
2064         }
2065
2066         editor->play_selection ();
2067 }
2068
2069 void
2070 ARDOUR_UI::transport_rewind (int option)
2071 {
2072         float current_transport_speed;
2073  
2074         if (session) {
2075                 current_transport_speed = session->transport_speed();
2076                 
2077                 if (current_transport_speed >= 0.0f) {
2078                         switch (option) {
2079                         case 0:
2080                                 session->request_transport_speed (-1.0f);
2081                                 break;
2082                         case 1:
2083                                 session->request_transport_speed (-4.0f);
2084                                 break;
2085                         case -1:
2086                                 session->request_transport_speed (-0.5f);
2087                                 break;
2088                         }
2089                 } else {
2090                         /* speed up */
2091                         session->request_transport_speed (current_transport_speed * 1.5f);
2092                 }
2093         }
2094 }
2095
2096 void
2097 ARDOUR_UI::transport_forward (int option)
2098 {
2099         float current_transport_speed;
2100         
2101         if (session) {
2102                 current_transport_speed = session->transport_speed();
2103                 
2104                 if (current_transport_speed <= 0.0f) {
2105                         switch (option) {
2106                         case 0:
2107                                 session->request_transport_speed (1.0f);
2108                                 break;
2109                         case 1:
2110                                 session->request_transport_speed (4.0f);
2111                                 break;
2112                         case -1:
2113                                 session->request_transport_speed (0.5f);
2114                                 break;
2115                         }
2116                 } else {
2117                         /* speed up */
2118                         session->request_transport_speed (current_transport_speed * 1.5f);
2119                 }
2120         }
2121 }
2122
2123 void
2124 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2125 {
2126         if (session == 0) {
2127                 return;
2128         }
2129
2130         DiskStream *ds;
2131
2132         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2133                 Port *port = ds->io()->input (0);
2134                 port->request_monitor_input (!port->monitoring_input());
2135         }
2136 }
2137
2138 void
2139 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2140 {
2141         if (session == 0) {
2142                 return;
2143         }
2144
2145         DiskStream *ds;
2146
2147         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2148                 ds->set_record_enabled (!ds->record_enabled(), this);
2149         }
2150 }
2151
2152 void
2153 ARDOUR_UI::queue_transport_change ()
2154 {
2155         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2156 }
2157
2158 void
2159 ARDOUR_UI::map_transport_state ()
2160 {
2161         float sp = session->transport_speed();
2162
2163         if (sp == 1.0f) {
2164                 transport_rolling ();
2165         } else if (sp < 0.0f) {
2166                 transport_rewinding ();
2167         } else if (sp > 0.0f) {
2168                 transport_forwarding ();
2169         } else {
2170                 transport_stopped ();
2171         }
2172 }
2173
2174 void
2175 ARDOUR_UI::send_all_midi_feedback ()
2176 {
2177         if (session) {
2178                 session->send_all_midi_feedback();
2179         }
2180 }
2181
2182 void
2183 ARDOUR_UI::allow_local_only ()
2184 {
2185
2186 }
2187
2188 void
2189 ARDOUR_UI::allow_mmc_only ()
2190 {
2191
2192 }
2193
2194 void
2195 ARDOUR_UI::allow_mmc_and_local ()
2196 {
2197
2198 }
2199
2200 void
2201 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2202 {
2203         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2204                 (int) adj.get_value()].c_str());
2205 }
2206
2207 void
2208 ARDOUR_UI::engine_stopped ()
2209 {
2210         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2211         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2212         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2213 }
2214
2215
2216 void
2217 ARDOUR_UI::engine_running ()
2218 {
2219         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2220         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2221         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2222 }
2223
2224 void
2225 ARDOUR_UI::engine_halted ()
2226 {
2227         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2228
2229         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2230         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2231
2232         update_sample_rate (0);
2233
2234         ArdourMessage msg (editor, X_("halted"),
2235                            _("\
2236 JACK has either been shutdown or it\n\
2237 disconnected Ardour because Ardour\n\
2238 was not fast enough. You can save the\n\
2239 session and/or try to reconnect to JACK ."));
2240 }
2241
2242 int32_t
2243 ARDOUR_UI::do_engine_start ()
2244 {
2245         try { 
2246                 engine->start();
2247         }
2248
2249         catch (AudioEngine::PortRegistrationFailure& err) {
2250                 engine->stop ();
2251                 error << _("Unable to create all required ports")
2252                       << endmsg;
2253                 unload_session ();
2254                 return -1;
2255         }
2256
2257         catch (...) {
2258                 engine->stop ();
2259                 error << _("Unable to start the session running")
2260                       << endmsg;
2261                 unload_session ();
2262                 return -2;
2263         }
2264         
2265         return 0;
2266 }
2267
2268 gint
2269 ARDOUR_UI::start_engine ()
2270 {
2271         if (do_engine_start () == 0) {
2272                 if (session && _session_is_new) {
2273                         /* we need to retain initial visual 
2274                            settings for a new session 
2275                         */
2276                         session->save_state ("");
2277                 }
2278
2279                 /* there is too much going on, in too many threads, for us to 
2280                    end up with a clean session. So wait 1 second after loading,
2281                    and fix it up. its ugly, but until i come across a better
2282                    solution, its what we have.
2283                 */
2284
2285                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2286         }
2287
2288         return FALSE;
2289 }
2290
2291 void
2292 ARDOUR_UI::update_clocks ()
2293 {
2294          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2295 }
2296
2297 void
2298 ARDOUR_UI::start_clocking ()
2299 {
2300         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2301 }
2302
2303 void
2304 ARDOUR_UI::stop_clocking ()
2305 {
2306         clock_signal_connection.disconnect ();
2307 }
2308         
2309 void
2310 ARDOUR_UI::toggle_clocking ()
2311 {
2312 #if 0
2313         if (clock_button.get_active()) {
2314                 start_clocking ();
2315         } else {
2316                 stop_clocking ();
2317         }
2318 #endif
2319 }
2320
2321 gint
2322 ARDOUR_UI::_blink (void *arg)
2323
2324 {
2325         ((ARDOUR_UI *) arg)->blink ();
2326         return TRUE;
2327 }
2328
2329 void
2330 ARDOUR_UI::blink ()
2331 {
2332          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2333 }
2334
2335 void
2336 ARDOUR_UI::start_blinking ()
2337 {
2338         /* Start the blink signal. Everybody with a blinking widget
2339            uses Blink to drive the widget's state.
2340         */
2341
2342         if (blink_timeout_tag < 0) {
2343                 blink_on = false;       
2344                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2345         }
2346 }
2347
2348 void
2349 ARDOUR_UI::stop_blinking ()
2350 {
2351         if (blink_timeout_tag >= 0) {
2352                 gtk_timeout_remove (blink_timeout_tag);
2353                 blink_timeout_tag = -1;
2354         }
2355 }
2356
2357
2358 void
2359 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2360 {
2361         using namespace Gtk;
2362         using namespace Menu_Helpers;
2363
2364         if (dstream.hidden()) {
2365                 return;
2366         }
2367
2368         MenuList& items = diskstream_menu->items();
2369         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2370 }
2371         
2372 void
2373 ARDOUR_UI::diskstream_selected (gint32 id)
2374 {
2375         selected_dstream = id;
2376         Main::quit ();
2377 }
2378
2379 gint32
2380 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2381 {
2382         using namespace Gtk;
2383         using namespace Menu_Helpers;
2384
2385         if (session == 0) {
2386                 return -1;
2387         }
2388
2389         diskstream_menu = new Menu();
2390         diskstream_menu->set_name ("ArdourContextMenu");
2391         using namespace Gtk;
2392         using namespace Menu_Helpers;
2393
2394         MenuList& items = diskstream_menu->items();
2395         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2396
2397         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2398
2399         if (ev) {
2400                 diskstream_menu->popup (ev->button, ev->time);
2401         } else {
2402                 diskstream_menu->popup (0, 0);
2403         }
2404
2405         selected_dstream = -1;
2406
2407         Main::run ();
2408
2409         delete diskstream_menu;
2410
2411         return selected_dstream;
2412 }
2413
2414 void
2415 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2416                           string& buf,
2417                           IO& io,
2418                           bool in)
2419 {
2420         if (in) {
2421                 if (io.n_inputs() == 0) {
2422                         buf = _("none");
2423                         return;
2424                 }
2425                 
2426                 /* XXX we're not handling multiple ports yet. */
2427
2428                 const char **connections = io.input(0)->get_connections();
2429                 
2430                 if (connections == 0 || connections[0] == '\0') {
2431                         buf = _("off");
2432                 } else {
2433                         buf = connections[0];
2434                 }
2435
2436                 free (connections);
2437
2438         } else {
2439
2440                 if (io.n_outputs() == 0) {
2441                         buf = _("none");
2442                         return;
2443                 }
2444                 
2445                 /* XXX we're not handling multiple ports yet. */
2446
2447                 const char **connections = io.output(0)->get_connections();
2448                 
2449                 if (connections == 0 || connections[0] == '\0') {
2450                         buf = _("off");
2451                 } else {
2452                         buf = connections[0];
2453                 }
2454
2455                 free (connections);
2456         }
2457 }
2458
2459 void
2460 ARDOUR_UI::snapshot_session ()
2461 {
2462         ArdourPrompter prompter (true);
2463         string snapname;
2464         string now;
2465         time_t n;
2466
2467         time (&n);
2468         now = ctime (&n);
2469         now = now.substr (0, now.length() - 1);
2470
2471         prompter.set_name ("Prompter");
2472         prompter.set_prompt (_("Name for snapshot"));
2473         prompter.set_initial_text (now);
2474         
2475         switch (prompter.run()) {
2476         case RESPONSE_ACCEPT:
2477                 prompter.get_result (snapname);
2478                 if (snapname.length()){
2479                         save_state (snapname);
2480                 }
2481                 break;
2482
2483         default:
2484                 break;
2485         }
2486 }
2487
2488 void
2489 ARDOUR_UI::save_state (string name)
2490 {
2491         (void) save_state_canfail (name);
2492 }
2493                 
2494 int
2495 ARDOUR_UI::save_state_canfail (string name)
2496 {
2497         if (session) {
2498                 int ret;
2499
2500                 if (name.length() == 0) {
2501                         name = session->snap_name();
2502                 }
2503
2504                 if ((ret = session->save_state (name)) != 0) {
2505                         return ret;
2506                 }
2507         }
2508         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2509         return 0;
2510 }
2511
2512 void
2513 ARDOUR_UI::restore_state (string name)
2514 {
2515         if (session) {
2516                 if (name.length() == 0) {
2517                         name = session->name();
2518                 }
2519                 session->restore_state (name);
2520         }
2521 }
2522
2523 void
2524 ARDOUR_UI::primary_clock_value_changed ()
2525 {
2526         if (session) {
2527                 session->request_locate (primary_clock.current_time ());
2528         }
2529 }
2530
2531 void
2532 ARDOUR_UI::secondary_clock_value_changed ()
2533 {
2534         if (session) {
2535                 session->request_locate (secondary_clock.current_time ());
2536         }
2537 }
2538
2539 void
2540 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2541 {
2542         if (session && dstream && dstream->record_enabled()) {
2543
2544                 Session::RecordState rs;
2545                 
2546                 rs = session->record_status ();
2547
2548                 switch (rs) {
2549                 case Session::Disabled:
2550                 case Session::Enabled:
2551                         if (w->get_state() != STATE_SELECTED) {
2552                                 w->set_state (STATE_SELECTED);
2553                         }
2554                         break;
2555
2556                 case Session::Recording:
2557                         if (w->get_state() != STATE_ACTIVE) {
2558                                 w->set_state (STATE_ACTIVE);
2559                         }
2560                         break;
2561                 }
2562
2563         } else {
2564                 if (w->get_state() != STATE_NORMAL) {
2565                         w->set_state (STATE_NORMAL);
2566                 }
2567         }
2568 }
2569
2570 void
2571 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2572 {
2573         if (session == 0) {
2574                 return;
2575         }
2576         
2577         switch (session->record_status()) {
2578         case Session::Enabled:
2579                 if (onoff) {
2580                         rec_button.set_state (STATE_ACTIVE);
2581                 } else {
2582                         rec_button.set_state (STATE_NORMAL);
2583                 }
2584                 break;
2585
2586         case Session::Recording:
2587                 rec_button.set_state (STATE_ACTIVE);
2588                 break;
2589
2590         default:
2591                 rec_button.set_active (false);
2592                 rec_button.set_state (STATE_NORMAL);
2593                 break;
2594         }
2595 }
2596
2597 gint
2598 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2599 {
2600         window->hide();
2601         Gtk::Main::quit ();
2602         return TRUE;
2603 }
2604
2605 void
2606 ARDOUR_UI::start_keyboard_prefix ()
2607 {
2608         keyboard->start_prefix();
2609 }
2610
2611 void
2612 ARDOUR_UI::save_template ()
2613
2614 {
2615         ArdourPrompter prompter (true);
2616         string name;
2617
2618         prompter.set_name (X_("Prompter"));
2619         prompter.set_prompt (_("Name for mix template:"));
2620         prompter.set_initial_text(session->name() + _("-template"));
2621         
2622         switch (prompter.run()) {
2623         case RESPONSE_ACCEPT:
2624                 prompter.get_result (name);
2625                 
2626                 if (name.length()) {
2627                         session->save_template (name);
2628                 }
2629                 break;
2630
2631         default:
2632                 break;
2633         }
2634 }
2635
2636 void
2637 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2638 {
2639         m_new_session_dialog->show_all();
2640         m_new_session_dialog->set_transient_for(*editor);
2641         m_new_session_dialog->set_name(predetermined_path);
2642
2643         int response = Gtk::RESPONSE_CANCEL;
2644
2645         do {
2646                 response = m_new_session_dialog->run ();
2647         
2648                 if(response == Gtk::RESPONSE_OK) {
2649
2650                         _session_is_new = true;
2651                         
2652                         std::string session_name = m_new_session_dialog->session_name();
2653                         std::string session_path = m_new_session_dialog->session_folder();
2654                         
2655                         /*
2656                           XXX This is needed because session constructor wants a 
2657                           non-existant path. hopefully this will be fixed at some point.
2658                         */
2659                         session_path = Glib::build_filename(session_path, session_name);
2660                         
2661                         std::string template_name = m_new_session_dialog->session_template_name();
2662                         
2663                         if (m_new_session_dialog->use_session_template()) {
2664                                 
2665                                 load_session (session_path, session_name, &template_name);
2666                                 
2667                         } else {
2668                                 
2669                                 uint32_t cchns;
2670                                 uint32_t mchns;
2671                                 Session::AutoConnectOption iconnect;
2672                                 Session::AutoConnectOption oconnect;
2673                                 
2674                                 if (m_new_session_dialog->create_control_bus()) {
2675                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2676                                 } else {
2677                                         cchns = 0;
2678                                 }
2679                                 
2680                                 if (m_new_session_dialog->create_master_bus()) {
2681                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2682                                 } else {
2683                                         mchns = 0;
2684                                 }
2685                                 
2686                                 if (m_new_session_dialog->connect_inputs()) {
2687                                         iconnect = Session::AutoConnectPhysical;
2688                                 } else {
2689                                         iconnect = Session::AutoConnectOption (0);
2690                                 }
2691                                 
2692                                 /// @todo some minor tweaks.
2693
2694                                 if (m_new_session_dialog->connect_outs_to_master()) {
2695                                         oconnect = Session::AutoConnectMaster;
2696                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2697                                         oconnect = Session::AutoConnectPhysical;
2698                                 } else {
2699                                         oconnect = Session::AutoConnectOption (0);
2700                                 } 
2701                                 
2702                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2703                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2704                                 
2705                                 build_session (session_path,
2706                                                session_name,
2707                                                cchns,
2708                                                mchns,
2709                                                iconnect,
2710                                                oconnect,
2711                                                nphysin,
2712                                                nphysout, 
2713                                                engine->frame_rate() * 60 * 5);
2714                         }               
2715                 }
2716
2717         } while(response == Gtk::RESPONSE_HELP);
2718         m_new_session_dialog->hide_all();
2719 }
2720
2721 int
2722 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2723 {
2724         Session *new_session;
2725         int x;
2726         session_loaded = false;
2727         x = unload_session ();
2728
2729         if (x < 0) {
2730                 return -1;
2731         } else if (x > 0) {
2732                 return 0;
2733         }
2734
2735         /* if it already exists, we must have write access */
2736
2737         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2738                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2739 You do not have write access to this session.\n\
2740 This prevents the session from being loaded."));
2741                 return -1;
2742         }
2743
2744         try {
2745                 new_session = new Session (*engine, path, snap_name, mix_template);
2746         }
2747
2748         catch (...) {
2749
2750                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2751                 return -1;
2752         }
2753
2754         connect_to_session (new_session);
2755
2756         //if (engine->running()) {
2757         //mixer->show_window();
2758         //}
2759         session_loaded = true;
2760         return 0;
2761 }
2762
2763 int
2764 ARDOUR_UI::make_session_clean ()
2765 {
2766         if (session) {
2767                 session->set_clean ();
2768         }
2769
2770         return FALSE;
2771 }
2772
2773 int
2774 ARDOUR_UI::build_session (string path, string snap_name, 
2775                           uint32_t control_channels,
2776                           uint32_t master_channels, 
2777                           Session::AutoConnectOption input_connect,
2778                           Session::AutoConnectOption output_connect,
2779                           uint32_t nphysin,
2780                           uint32_t nphysout,
2781                           jack_nframes_t initial_length)
2782 {
2783         Session *new_session;
2784         int x;
2785
2786         session_loaded = false;
2787         x = unload_session ();
2788         if (x < 0) {
2789                 return -1;
2790         } else if (x > 0) {
2791                 return 0;
2792         }
2793         
2794         _session_is_new = true;
2795
2796         try {
2797                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2798                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2799         }
2800
2801         catch (...) {
2802
2803                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2804                 return -1;
2805         }
2806
2807         connect_to_session (new_session);
2808
2809         //if (engine->running()) {
2810         //mixer->show_window();
2811         //}
2812         session_loaded = true;
2813         return 0;
2814 }
2815
2816 void
2817 ARDOUR_UI::show ()
2818 {
2819         if (editor) {
2820                 editor->show_window ();
2821                 shown_flag = true;
2822         }
2823
2824         if (session && mixer) {
2825                 // mixer->show_window ();
2826         }
2827         
2828         if (about) {
2829                 about->present ();
2830         }
2831 }
2832
2833 void
2834 ARDOUR_UI::show_splash ()
2835 {
2836         if (about == 0) {
2837                 about = new About();
2838         }
2839         about->present();
2840 }
2841
2842 void
2843 ARDOUR_UI::hide_splash ()
2844 {
2845         if (about) {
2846                 // about->hide();
2847         }
2848 }
2849
2850 void
2851 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2852 {
2853         size_t removed;
2854
2855         removed = rep.paths.size();
2856
2857         if (removed == 0) {
2858                 ArdourMessage msg (editor, X_("cleanupresults"),
2859                                    _("\
2860 No audio files were ready for cleanup\n\n\
2861 If this seems suprising, check for any existing\n\
2862 snapshots. These may still include regions that\n\
2863 require some unused files to continue to exist."));
2864                 return;
2865         } 
2866
2867         ArdourDialog results (_("ardour: cleanup"), true);
2868         
2869         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2870             CleanupResultsModelColumns() { 
2871                     add (visible_name);
2872                     add (fullpath);
2873             }
2874             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2875             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2876         };
2877
2878         
2879         Glib::RefPtr<Gtk::ListStore> results_model;
2880         CleanupResultsModelColumns results_columns;
2881         Gtk::TreeView results_display;
2882         
2883         results_model = ListStore::create (results_columns);
2884         results_display.set_model (results_model);
2885         results_display.append_column (list_title, results_columns.visible_name);
2886         results_display.set_headers_visible (true);
2887
2888         Gtk::ScrolledWindow list_scroller;
2889         Gtk::Label txt;
2890
2891         if (rep.space < 1048576.0f) {
2892                 if (removed > 1) {
2893                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2894                 } else {
2895                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2896                 }
2897         } else {
2898                 if (removed > 1) {
2899                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2900                 } else {
2901                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2902                 }
2903         }
2904
2905         results.get_vbox()->pack_start (txt, false, false);
2906         
2907         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2908                 TreeModel::Row row = *(results_model->append());
2909                 row[results_columns.visible_name] = *i;
2910                 row[results_columns.fullpath] = *i;
2911         }
2912         
2913         list_scroller.add (results_display);
2914         list_scroller.set_size_request (-1, 250);
2915         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2916         
2917         results.get_vbox()->pack_start (list_scroller, true, true);
2918         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2919         results.set_position (Gtk::WIN_POS_MOUSE);
2920
2921         results.run ();
2922 }
2923
2924 void
2925 ARDOUR_UI::cleanup ()
2926 {
2927         if (session == 0) {
2928                 /* shouldn't happen: menu item is insensitive */
2929                 return;
2930         }
2931
2932         ArdourDialog checker (_("ardour cleanup"));
2933         Gtk::Label label (_("\
2934 Cleanup is a destructive operation.\n\
2935 ALL undo/redo information will be lost if you cleanup.\n\
2936 Unused audio files will be moved to a \"dead sounds\" location."));
2937         
2938         checker.get_vbox()->pack_start (label, false, false);
2939         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2940         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2941
2942         checker.set_name (_("CleanupDialog"));
2943         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2944         checker.set_position (Gtk::WIN_POS_MOUSE);
2945
2946         switch (checker.run()) {
2947         case RESPONSE_ACCEPT:
2948                 break;
2949         default:
2950                 return;
2951         }
2952
2953         Session::cleanup_report rep;
2954
2955         editor->prepare_for_cleanup ();
2956
2957         if (session->cleanup_sources (rep)) {
2958                 return;
2959         }
2960
2961         display_cleanup_results (rep, 
2962                                  _("cleaned files"),
2963                                  _("\
2964 The following %1 %2 were not in use.\n\
2965 The next time you flush the wastebasket\n\
2966 it will release an additional %3 %4bytes\n\
2967 of disk space"
2968                                          ));
2969 }
2970
2971 void
2972 ARDOUR_UI::flush_trash ()
2973 {
2974         if (session == 0) {
2975                 /* shouldn't happen: menu item is insensitive */
2976                 return;
2977         }
2978
2979         Session::cleanup_report rep;
2980
2981         if (session->cleanup_trash_sources (rep)) {
2982                 return;
2983         }
2984
2985         display_cleanup_results (rep, 
2986                                  _("deleted file"),
2987                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2988 }
2989
2990 void
2991 ARDOUR_UI::add_route ()
2992 {
2993         int count;
2994
2995         if (!session) {
2996                 return;
2997         }
2998
2999         if (add_route_dialog == 0) {
3000                 add_route_dialog = new AddRouteDialog;
3001                 editor->ensure_float (*add_route_dialog);
3002         }
3003
3004         if (add_route_dialog->is_visible()) {
3005                 /* we're already doing this */
3006                 return;
3007         }
3008
3009         ResponseType r = (ResponseType) add_route_dialog->run ();
3010         
3011         add_route_dialog->hide();
3012
3013         switch (r) {
3014         case RESPONSE_ACCEPT:
3015                 break;
3016         default:
3017                 return;
3018                 break;
3019         }
3020
3021         if ((count = add_route_dialog->count()) <= 0) {
3022                 return;
3023         }
3024
3025         uint32_t input_chan = add_route_dialog->channels ();
3026         uint32_t output_chan;
3027         string name_template = add_route_dialog->name_template ();
3028         bool track = add_route_dialog->track ();
3029
3030         Session::AutoConnectOption oac = session->get_output_auto_connect();
3031
3032         if (oac & Session::AutoConnectMaster) {
3033                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3034         } else {
3035                 output_chan = input_chan;
3036         }
3037
3038         /* XXX do something with name template */
3039
3040         while (count) {
3041                 if (track) {
3042                         session_add_audio_track (input_chan, output_chan);
3043                 } else {
3044                         session_add_audio_bus (input_chan, output_chan);
3045                 }
3046                 --count;
3047                 
3048                 while (Main::events_pending()) {
3049                         Main::iteration ();
3050                 }
3051         }
3052 }
3053
3054 XMLNode*
3055 ARDOUR_UI::mixer_settings () const
3056 {
3057         XMLNode* node = 0;
3058
3059         if (session) {
3060                 node = session->instant_xml(X_("Mixer"), session->path());
3061         } else {
3062                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3063         }
3064
3065         if (!node) {
3066                 node = new XMLNode (X_("Mixer"));
3067         }
3068
3069         return node;
3070 }
3071
3072 XMLNode*
3073 ARDOUR_UI::editor_settings () const
3074 {
3075         XMLNode* node = 0;
3076
3077         if (session) {
3078                 node = session->instant_xml(X_("Editor"), session->path());
3079         } else {
3080                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3081         }
3082
3083         if (!node) {
3084                 node = new XMLNode (X_("Editor"));
3085         }
3086         return node;
3087 }
3088
3089 XMLNode*
3090 ARDOUR_UI::keyboard_settings () const
3091 {
3092         XMLNode* node = 0;
3093
3094         node = Config->extra_xml(X_("Keyboard"));
3095         
3096         if (!node) {
3097                 node = new XMLNode (X_("Keyboard"));
3098         }
3099         return node;
3100 }
3101
3102 void
3103 ARDOUR_UI::halt_on_xrun_message ()
3104 {
3105         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3106
3107         ArdourMessage msg (editor, X_("haltonxrun"),
3108                            _("Recording was stopped because your system could not keep up."));
3109 }
3110
3111 void 
3112 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3113 {
3114         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3115
3116         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3117                 delete *i;
3118         }
3119
3120         delete deletion_list;
3121 }
3122
3123 void
3124 ARDOUR_UI::disk_overrun_handler ()
3125 {
3126         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3127
3128         if (!have_disk_overrun_displayed) {
3129                 have_disk_overrun_displayed = true;
3130                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3131 The disk system on your computer\n\
3132 was not able to keep up with Ardour.\n\
3133 \n\
3134 Specifically, it failed to write data to disk\n\
3135 quickly enough to keep up with recording.\n"));
3136                 have_disk_overrun_displayed = false;
3137         }
3138 }
3139
3140 void
3141 ARDOUR_UI::disk_underrun_handler ()
3142 {
3143         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3144
3145         if (!have_disk_underrun_displayed) {
3146                 have_disk_underrun_displayed = true;
3147                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3148                         (_("The disk system on your computer\n\
3149 was not able to keep up with Ardour.\n\
3150 \n\
3151 Specifically, it failed to read data from disk\n\
3152 quickly enough to keep up with playback.\n")));
3153                 have_disk_underrun_displayed = false;
3154         } 
3155 }
3156
3157 void
3158 ARDOUR_UI::disk_underrun_message_gone ()
3159 {
3160         have_disk_underrun_displayed = false;
3161 }
3162
3163 void
3164 ARDOUR_UI::disk_overrun_message_gone ()
3165 {
3166         have_disk_underrun_displayed = false;
3167 }
3168
3169 int
3170 ARDOUR_UI::pending_state_dialog ()
3171 {
3172         ArdourDialog dialog ("pending state dialog");
3173         Label  message (_("\
3174 This session appears to have been in\n\
3175 middle of recording when ardour or\n\
3176 the computer was shutdown.\n\
3177 \n\
3178 Ardour can recover any captured audio for\n\
3179 you, or it can ignore it. Please decide\n\
3180 what you would like to do.\n"));
3181
3182         dialog.get_vbox()->pack_start (message);
3183         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3184         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3185
3186         dialog.set_position (WIN_POS_CENTER);
3187         dialog.show_all ();
3188         
3189         switch (dialog.run ()) {
3190         case RESPONSE_ACCEPT:
3191                 break;
3192         default:
3193                 return 1;
3194         }
3195
3196         return 0;
3197 }
3198         
3199         
3200 void
3201 ARDOUR_UI::disconnect_from_jack ()
3202 {
3203         if (engine) {
3204                 if( engine->disconnect_from_jack ()) {
3205                         ArdourMessage msg (editor, X_("nojack dialog"),
3206                                            _("Could not disconnect from JACK"));
3207                 }
3208
3209                 update_sample_rate (0);
3210         }
3211 }
3212
3213 void
3214 ARDOUR_UI::reconnect_to_jack ()
3215 {
3216         if (engine) {
3217                 if (engine->reconnect_to_jack ()) {
3218                         ArdourMessage msg (editor, X_("nojack dialog"),
3219                                            _("Could not reconnect to JACK"));
3220                 }
3221
3222                 update_sample_rate (0);
3223         }
3224 }
3225
3226 void
3227 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3228 {
3229         engine->request_buffer_size (nframes);
3230         update_sample_rate (0);
3231 }
3232
3233 int
3234 ARDOUR_UI::cmdline_new_session (string path)
3235 {
3236         if (path[0] != '/') {
3237                 char buf[PATH_MAX+1];
3238                 string str;
3239
3240                 getcwd (buf, sizeof (buf));
3241                 str = buf;
3242                 str += '/';
3243                 str += path;
3244                 path = str;
3245         }
3246
3247         new_session (false, path);
3248
3249         _will_create_new_session_automatically = false; /* done it */
3250         return FALSE; /* don't call it again */
3251 }