stock icons, transport controls as proxies, make ActionManager::get_action() work
[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 }
1722
1723 void
1724 ARDOUR_UI::open_recent_session ()
1725 {
1726         /* popup selector window */
1727
1728         if (session_selector_window == 0) {
1729                 build_session_selector ();
1730         }
1731
1732         redisplay_recent_sessions ();
1733
1734         ResponseType r = (ResponseType) session_selector_window->run ();
1735
1736         session_selector_window->hide();
1737
1738         switch (r) {
1739         case RESPONSE_ACCEPT:
1740                 break;
1741         default:
1742                 return;
1743         }
1744
1745         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1746
1747         if (i == recent_session_model->children().end()) {
1748                 return;
1749         }
1750         
1751         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1752         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1753
1754         _session_is_new = false;
1755
1756         load_session (path, state);
1757 }
1758
1759 bool
1760 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1761 {
1762         struct stat statbuf;
1763         
1764         if (stat (info.filename.c_str(), &statbuf) != 0) {
1765                 return false;
1766         }
1767
1768         if (!S_ISDIR(statbuf.st_mode)) {
1769                 return false;
1770         }
1771
1772         string session_file = info.filename;
1773         session_file += '/';
1774         session_file += PBD::basename (info.filename);
1775         session_file += ".ardour";
1776         
1777         if (stat (session_file.c_str(), &statbuf) != 0) {
1778                 return false;
1779         }
1780
1781         return S_ISREG (statbuf.st_mode);
1782 }
1783
1784 void
1785 ARDOUR_UI::open_session ()
1786 {
1787         /* popup selector window */
1788
1789         if (open_session_selector == 0) {
1790                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1791                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1792                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
1793                 
1794                 FileFilter filter_ardour;
1795                 filter_ardour.set_name (_("Ardour sessions"));
1796                 filter_ardour.add_pattern("*.ardour");
1797                 open_session_selector->add_filter (filter_ardour);
1798         }
1799
1800         switch (open_session_selector->run ()) {
1801         case RESPONSE_OK:
1802                 break;
1803         default:
1804                 return;
1805         }
1806
1807         string session_path = open_session_selector->get_filename();
1808         string path, name;
1809         bool isnew;
1810
1811         if (session_path.length() > 0) {
1812                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1813                         _session_is_new = isnew;
1814                         load_session (path, name);
1815                 }
1816         }
1817 }
1818
1819
1820 void
1821 ARDOUR_UI::session_add_midi_track ()
1822 {
1823         cerr << _("Patience is a virtue.\n");
1824 }
1825
1826 void
1827 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1828 {
1829         Route* route;
1830
1831         if (session == 0) {
1832                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1833                 return;
1834         }
1835
1836         try { 
1837                 if (disk) {
1838                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1839                                 error << _("could not create new audio track") << endmsg;
1840                         }
1841                 } else {
1842                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1843                                 error << _("could not create new audio bus") << endmsg;
1844                         }
1845                 }
1846                 
1847 #if CONTROLOUTS
1848                 if (need_control_room_outs) {
1849                         pan_t pans[2];
1850                         
1851                         pans[0] = 0.5;
1852                         pans[1] = 0.5;
1853                         
1854                         route->set_stereo_control_outs (control_lr_channels);
1855                         route->control_outs()->set_stereo_pan (pans, this);
1856                 }
1857 #endif /* CONTROLOUTS */
1858         }
1859
1860         catch (...) {
1861                 ArdourMessage msg (editor, X_("noport dialog"),
1862                                    _("There are insufficient JACK ports available\n\
1863 to create a new track or bus.\n\
1864 You should save Ardour, exit and\n\
1865 restart JACK with more ports."));
1866         }
1867 }
1868
1869 void
1870 ARDOUR_UI::diskstream_added (DiskStream* ds)
1871 {
1872 }
1873
1874 void
1875 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1876 {
1877         jack_nframes_t _preroll;
1878
1879         if (session) {
1880                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1881
1882                 if (new_position > _preroll) {
1883                         new_position -= _preroll;
1884                 } else {
1885                         new_position = 0;
1886                 }
1887
1888                 session->request_locate (new_position);
1889         }
1890 }
1891
1892 void
1893 ARDOUR_UI::transport_goto_start ()
1894 {
1895         if (session) {
1896                 session->request_locate (0);
1897
1898                 
1899                 /* force displayed area in editor to start no matter
1900                    what "follow playhead" setting is.
1901                 */
1902                 
1903                 if (editor) {
1904                         editor->reposition_x_origin (0);
1905                 }
1906         }
1907 }
1908
1909 void
1910 ARDOUR_UI::transport_goto_end ()
1911 {
1912         if (session) {
1913                 jack_nframes_t frame = session->current_end_frame();
1914                 session->request_locate (frame);
1915
1916                 /* force displayed area in editor to start no matter
1917                    what "follow playhead" setting is.
1918                 */
1919                 
1920                 if (editor) {
1921                         editor->reposition_x_origin (frame);
1922                 }
1923         }
1924 }
1925
1926 gint 
1927 ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
1928 {
1929
1930
1931         if (session) {
1932                         if (session->transport_stopped()) {
1933                         session->request_locate (session->last_transport_start());
1934                 } else {
1935                         if (session->get_auto_loop()) {
1936                                 session->request_auto_loop (false);
1937                         }
1938
1939                         Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
1940                         session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
1941                         }
1942         }
1943
1944         return TRUE;
1945 }
1946
1947 gint
1948 ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
1949 {
1950         transport_roll ();
1951         return TRUE;
1952 }
1953
1954 void
1955 ARDOUR_UI::transport_stop ()
1956 {
1957         if (!session) {
1958                 return;
1959         }
1960
1961         if (session->is_auditioning()) {
1962                 session->cancel_audition ();
1963                 return;
1964         }
1965         
1966         if (session->get_auto_loop()) {
1967                 session->request_auto_loop (false);
1968         }
1969         
1970         session->request_stop ();
1971 }
1972
1973 void
1974 ARDOUR_UI::transport_stop_and_forget_capture ()
1975 {
1976         if (session) {
1977                 session->request_stop (true);
1978         }
1979 }
1980
1981 void
1982 ARDOUR_UI::remove_last_capture()
1983 {
1984         if (editor) {
1985                 editor->remove_last_capture();
1986         }
1987 }
1988
1989 void
1990 ARDOUR_UI::transport_record ()
1991 {
1992         if (session) {
1993                 switch (session->record_status()) {
1994                 case Session::Disabled:
1995                         if (session->ntracks() == 0) {
1996                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1997                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1998                                 return;
1999                         }
2000                         session->maybe_enable_record ();
2001                         break;
2002                 case Session::Recording:
2003                 case Session::Enabled:
2004                         session->disable_record ();
2005                 }
2006         }
2007 }
2008
2009 void
2010 ARDOUR_UI::transport_roll ()
2011 {
2012         bool rolling;
2013
2014         if (!session) {
2015                 return;
2016         }
2017
2018         rolling = session->transport_rolling ();
2019
2020         if (session->get_auto_loop()) {
2021                 session->request_auto_loop (false);
2022                 auto_loop_button.set_active (false);
2023                 roll_button.set_active (true);
2024         } else if (session->get_play_range ()) {
2025                 session->request_play_range (false);
2026                 play_selection_button.set_active (false);
2027         } else if (rolling) {
2028                 session->request_locate (session->last_transport_start(), true);
2029         }
2030
2031         session->request_transport_speed (1.0f);
2032 }
2033
2034 void
2035 ARDOUR_UI::transport_loop()
2036 {
2037         if (session) {
2038                 if (session->get_auto_loop()) {
2039                         if (session->transport_rolling()) {
2040                                 Location * looploc = session->locations()->auto_loop_location();
2041                                 if (looploc) {
2042                                         session->request_locate (looploc->start(), true);
2043                                 }
2044                         }
2045                 }
2046                 else {
2047                         session->request_auto_loop (true);
2048                 }
2049         }
2050 }
2051
2052 void
2053 ARDOUR_UI::transport_play_selection ()
2054 {
2055         if (!session) {
2056                 return;
2057         }
2058
2059         if (!session->get_play_range()) {
2060                 session->request_stop ();
2061         }
2062
2063         editor->play_selection ();
2064 }
2065
2066 void
2067 ARDOUR_UI::transport_rewind (int option)
2068 {
2069         float current_transport_speed;
2070  
2071         if (session) {
2072                 current_transport_speed = session->transport_speed();
2073                 
2074                 if (current_transport_speed >= 0.0f) {
2075                         switch (option) {
2076                         case 0:
2077                                 session->request_transport_speed (-1.0f);
2078                                 break;
2079                         case 1:
2080                                 session->request_transport_speed (-4.0f);
2081                                 break;
2082                         case -1:
2083                                 session->request_transport_speed (-0.5f);
2084                                 break;
2085                         }
2086                 } else {
2087                         /* speed up */
2088                         session->request_transport_speed (current_transport_speed * 1.5f);
2089                 }
2090         }
2091 }
2092
2093 void
2094 ARDOUR_UI::transport_forward (int option)
2095 {
2096         float current_transport_speed;
2097         
2098         if (session) {
2099                 current_transport_speed = session->transport_speed();
2100                 
2101                 if (current_transport_speed <= 0.0f) {
2102                         switch (option) {
2103                         case 0:
2104                                 session->request_transport_speed (1.0f);
2105                                 break;
2106                         case 1:
2107                                 session->request_transport_speed (4.0f);
2108                                 break;
2109                         case -1:
2110                                 session->request_transport_speed (0.5f);
2111                                 break;
2112                         }
2113                 } else {
2114                         /* speed up */
2115                         session->request_transport_speed (current_transport_speed * 1.5f);
2116                 }
2117         }
2118 }
2119
2120 void
2121 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2122 {
2123         if (session == 0) {
2124                 return;
2125         }
2126
2127         DiskStream *ds;
2128
2129         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2130                 Port *port = ds->io()->input (0);
2131                 port->request_monitor_input (!port->monitoring_input());
2132         }
2133 }
2134
2135 void
2136 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2137 {
2138         if (session == 0) {
2139                 return;
2140         }
2141
2142         DiskStream *ds;
2143
2144         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2145                 ds->set_record_enabled (!ds->record_enabled(), this);
2146         }
2147 }
2148
2149 void
2150 ARDOUR_UI::queue_transport_change ()
2151 {
2152         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2153 }
2154
2155 void
2156 ARDOUR_UI::map_transport_state ()
2157 {
2158         float sp = session->transport_speed();
2159
2160         if (sp == 1.0f) {
2161                 transport_rolling ();
2162         } else if (sp < 0.0f) {
2163                 transport_rewinding ();
2164         } else if (sp > 0.0f) {
2165                 transport_forwarding ();
2166         } else {
2167                 transport_stopped ();
2168         }
2169 }
2170
2171 void
2172 ARDOUR_UI::send_all_midi_feedback ()
2173 {
2174         if (session) {
2175                 session->send_all_midi_feedback();
2176         }
2177 }
2178
2179 void
2180 ARDOUR_UI::allow_local_only ()
2181 {
2182
2183 }
2184
2185 void
2186 ARDOUR_UI::allow_mmc_only ()
2187 {
2188
2189 }
2190
2191 void
2192 ARDOUR_UI::allow_mmc_and_local ()
2193 {
2194
2195 }
2196
2197 void
2198 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2199 {
2200         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2201                 (int) adj.get_value()].c_str());
2202 }
2203
2204 void
2205 ARDOUR_UI::engine_stopped ()
2206 {
2207         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2208         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2209         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2210 }
2211
2212
2213 void
2214 ARDOUR_UI::engine_running ()
2215 {
2216         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2217         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2218         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2219 }
2220
2221 void
2222 ARDOUR_UI::engine_halted ()
2223 {
2224         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2225
2226         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2227         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2228
2229         update_sample_rate (0);
2230
2231         ArdourMessage msg (editor, X_("halted"),
2232                            _("\
2233 JACK has either been shutdown or it\n\
2234 disconnected Ardour because Ardour\n\
2235 was not fast enough. You can save the\n\
2236 session and/or try to reconnect to JACK ."));
2237 }
2238
2239 int32_t
2240 ARDOUR_UI::do_engine_start ()
2241 {
2242         try { 
2243                 engine->start();
2244         }
2245
2246         catch (AudioEngine::PortRegistrationFailure& err) {
2247                 engine->stop ();
2248                 error << _("Unable to create all required ports")
2249                       << endmsg;
2250                 unload_session ();
2251                 return -1;
2252         }
2253
2254         catch (...) {
2255                 engine->stop ();
2256                 error << _("Unable to start the session running")
2257                       << endmsg;
2258                 unload_session ();
2259                 return -2;
2260         }
2261         
2262         return 0;
2263 }
2264
2265 gint
2266 ARDOUR_UI::start_engine ()
2267 {
2268         if (do_engine_start () == 0) {
2269                 if (session && _session_is_new) {
2270                         /* we need to retain initial visual 
2271                            settings for a new session 
2272                         */
2273                         session->save_state ("");
2274                 }
2275
2276                 /* there is too much going on, in too many threads, for us to 
2277                    end up with a clean session. So wait 1 second after loading,
2278                    and fix it up. its ugly, but until i come across a better
2279                    solution, its what we have.
2280                 */
2281
2282                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2283         }
2284
2285         return FALSE;
2286 }
2287
2288 void
2289 ARDOUR_UI::update_clocks ()
2290 {
2291          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2292 }
2293
2294 void
2295 ARDOUR_UI::start_clocking ()
2296 {
2297         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2298 }
2299
2300 void
2301 ARDOUR_UI::stop_clocking ()
2302 {
2303         clock_signal_connection.disconnect ();
2304 }
2305         
2306 void
2307 ARDOUR_UI::toggle_clocking ()
2308 {
2309 #if 0
2310         if (clock_button.get_active()) {
2311                 start_clocking ();
2312         } else {
2313                 stop_clocking ();
2314         }
2315 #endif
2316 }
2317
2318 gint
2319 ARDOUR_UI::_blink (void *arg)
2320
2321 {
2322         ((ARDOUR_UI *) arg)->blink ();
2323         return TRUE;
2324 }
2325
2326 void
2327 ARDOUR_UI::blink ()
2328 {
2329          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2330 }
2331
2332 void
2333 ARDOUR_UI::start_blinking ()
2334 {
2335         /* Start the blink signal. Everybody with a blinking widget
2336            uses Blink to drive the widget's state.
2337         */
2338
2339         if (blink_timeout_tag < 0) {
2340                 blink_on = false;       
2341                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2342         }
2343 }
2344
2345 void
2346 ARDOUR_UI::stop_blinking ()
2347 {
2348         if (blink_timeout_tag >= 0) {
2349                 gtk_timeout_remove (blink_timeout_tag);
2350                 blink_timeout_tag = -1;
2351         }
2352 }
2353
2354
2355 void
2356 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2357 {
2358         using namespace Gtk;
2359         using namespace Menu_Helpers;
2360
2361         if (dstream.hidden()) {
2362                 return;
2363         }
2364
2365         MenuList& items = diskstream_menu->items();
2366         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2367 }
2368         
2369 void
2370 ARDOUR_UI::diskstream_selected (gint32 id)
2371 {
2372         selected_dstream = id;
2373         Main::quit ();
2374 }
2375
2376 gint32
2377 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2378 {
2379         using namespace Gtk;
2380         using namespace Menu_Helpers;
2381
2382         if (session == 0) {
2383                 return -1;
2384         }
2385
2386         diskstream_menu = new Menu();
2387         diskstream_menu->set_name ("ArdourContextMenu");
2388         using namespace Gtk;
2389         using namespace Menu_Helpers;
2390
2391         MenuList& items = diskstream_menu->items();
2392         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2393
2394         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2395
2396         if (ev) {
2397                 diskstream_menu->popup (ev->button, ev->time);
2398         } else {
2399                 diskstream_menu->popup (0, 0);
2400         }
2401
2402         selected_dstream = -1;
2403
2404         Main::run ();
2405
2406         delete diskstream_menu;
2407
2408         return selected_dstream;
2409 }
2410
2411 void
2412 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2413                           string& buf,
2414                           IO& io,
2415                           bool in)
2416 {
2417         if (in) {
2418                 if (io.n_inputs() == 0) {
2419                         buf = _("none");
2420                         return;
2421                 }
2422                 
2423                 /* XXX we're not handling multiple ports yet. */
2424
2425                 const char **connections = io.input(0)->get_connections();
2426                 
2427                 if (connections == 0 || connections[0] == '\0') {
2428                         buf = _("off");
2429                 } else {
2430                         buf = connections[0];
2431                 }
2432
2433                 free (connections);
2434
2435         } else {
2436
2437                 if (io.n_outputs() == 0) {
2438                         buf = _("none");
2439                         return;
2440                 }
2441                 
2442                 /* XXX we're not handling multiple ports yet. */
2443
2444                 const char **connections = io.output(0)->get_connections();
2445                 
2446                 if (connections == 0 || connections[0] == '\0') {
2447                         buf = _("off");
2448                 } else {
2449                         buf = connections[0];
2450                 }
2451
2452                 free (connections);
2453         }
2454 }
2455
2456 void
2457 ARDOUR_UI::snapshot_session ()
2458 {
2459         ArdourPrompter prompter (true);
2460         string snapname;
2461         string now;
2462         time_t n;
2463
2464         time (&n);
2465         now = ctime (&n);
2466         now = now.substr (0, now.length() - 1);
2467
2468         prompter.set_name ("Prompter");
2469         prompter.set_prompt (_("Name for snapshot"));
2470         prompter.set_initial_text (now);
2471         
2472         switch (prompter.run()) {
2473         case RESPONSE_ACCEPT:
2474                 prompter.get_result (snapname);
2475                 if (snapname.length()){
2476                         save_state (snapname);
2477                 }
2478                 break;
2479
2480         default:
2481                 break;
2482         }
2483 }
2484
2485 void
2486 ARDOUR_UI::save_state (string name)
2487 {
2488         (void) save_state_canfail (name);
2489 }
2490                 
2491 int
2492 ARDOUR_UI::save_state_canfail (string name)
2493 {
2494         if (session) {
2495                 int ret;
2496
2497                 if (name.length() == 0) {
2498                         name = session->snap_name();
2499                 }
2500
2501                 if ((ret = session->save_state (name)) != 0) {
2502                         return ret;
2503                 }
2504         }
2505         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2506         return 0;
2507 }
2508
2509 void
2510 ARDOUR_UI::restore_state (string name)
2511 {
2512         if (session) {
2513                 if (name.length() == 0) {
2514                         name = session->name();
2515                 }
2516                 session->restore_state (name);
2517         }
2518 }
2519
2520 void
2521 ARDOUR_UI::primary_clock_value_changed ()
2522 {
2523         if (session) {
2524                 session->request_locate (primary_clock.current_time ());
2525         }
2526 }
2527
2528 void
2529 ARDOUR_UI::secondary_clock_value_changed ()
2530 {
2531         if (session) {
2532                 session->request_locate (secondary_clock.current_time ());
2533         }
2534 }
2535
2536 void
2537 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2538 {
2539         if (session && dstream && dstream->record_enabled()) {
2540
2541                 Session::RecordState rs;
2542                 
2543                 rs = session->record_status ();
2544
2545                 switch (rs) {
2546                 case Session::Disabled:
2547                 case Session::Enabled:
2548                         if (w->get_state() != STATE_SELECTED) {
2549                                 w->set_state (STATE_SELECTED);
2550                         }
2551                         break;
2552
2553                 case Session::Recording:
2554                         if (w->get_state() != STATE_ACTIVE) {
2555                                 w->set_state (STATE_ACTIVE);
2556                         }
2557                         break;
2558                 }
2559
2560         } else {
2561                 if (w->get_state() != STATE_NORMAL) {
2562                         w->set_state (STATE_NORMAL);
2563                 }
2564         }
2565 }
2566
2567 void
2568 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2569 {
2570         if (session == 0) {
2571                 return;
2572         }
2573         
2574         switch (session->record_status()) {
2575         case Session::Enabled:
2576                 if (onoff) {
2577                         rec_button.set_state (STATE_ACTIVE);
2578                 } else {
2579                         rec_button.set_state (STATE_NORMAL);
2580                 }
2581                 break;
2582
2583         case Session::Recording:
2584                 rec_button.set_state (STATE_ACTIVE);
2585                 break;
2586
2587         default:
2588                 rec_button.set_active (false);
2589                 rec_button.set_state (STATE_NORMAL);
2590                 break;
2591         }
2592 }
2593
2594 gint
2595 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2596 {
2597         window->hide();
2598         Gtk::Main::quit ();
2599         return TRUE;
2600 }
2601
2602 void
2603 ARDOUR_UI::start_keyboard_prefix ()
2604 {
2605         keyboard->start_prefix();
2606 }
2607
2608 void
2609 ARDOUR_UI::save_template ()
2610
2611 {
2612         ArdourPrompter prompter (true);
2613         string name;
2614
2615         prompter.set_name (X_("Prompter"));
2616         prompter.set_prompt (_("Name for mix template:"));
2617         prompter.set_initial_text(session->name() + _("-template"));
2618         
2619         switch (prompter.run()) {
2620         case RESPONSE_ACCEPT:
2621                 prompter.get_result (name);
2622                 
2623                 if (name.length()) {
2624                         session->save_template (name);
2625                 }
2626                 break;
2627
2628         default:
2629                 break;
2630         }
2631 }
2632
2633 void
2634 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2635 {
2636         m_new_session_dialog->show_all();
2637         m_new_session_dialog->set_transient_for(*editor);
2638         m_new_session_dialog->set_name(predetermined_path);
2639
2640         int response = Gtk::RESPONSE_CANCEL;
2641
2642         do {
2643                 response = m_new_session_dialog->run ();
2644         
2645                 if(response == Gtk::RESPONSE_OK) {
2646
2647                         _session_is_new = true;
2648                         
2649                         std::string session_name = m_new_session_dialog->session_name();
2650                         std::string session_path = m_new_session_dialog->session_folder();
2651                         
2652                         /*
2653                           XXX This is needed because session constructor wants a 
2654                           non-existant path. hopefully this will be fixed at some point.
2655                         */
2656                         session_path = Glib::build_filename(session_path, session_name);
2657                         
2658                         std::string template_name = m_new_session_dialog->session_template_name();
2659                         
2660                         if (m_new_session_dialog->use_session_template()) {
2661                                 
2662                                 load_session (session_path, session_name, &template_name);
2663                                 
2664                         } else {
2665                                 
2666                                 uint32_t cchns;
2667                                 uint32_t mchns;
2668                                 Session::AutoConnectOption iconnect;
2669                                 Session::AutoConnectOption oconnect;
2670                                 
2671                                 if (m_new_session_dialog->create_control_bus()) {
2672                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2673                                 } else {
2674                                         cchns = 0;
2675                                 }
2676                                 
2677                                 if (m_new_session_dialog->create_master_bus()) {
2678                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2679                                 } else {
2680                                         mchns = 0;
2681                                 }
2682                                 
2683                                 if (m_new_session_dialog->connect_inputs()) {
2684                                         iconnect = Session::AutoConnectPhysical;
2685                                 } else {
2686                                         iconnect = Session::AutoConnectOption (0);
2687                                 }
2688                                 
2689                                 /// @todo some minor tweaks.
2690
2691                                 if (m_new_session_dialog->connect_outs_to_master()) {
2692                                         oconnect = Session::AutoConnectMaster;
2693                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2694                                         oconnect = Session::AutoConnectPhysical;
2695                                 } else {
2696                                         oconnect = Session::AutoConnectOption (0);
2697                                 } 
2698                                 
2699                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2700                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2701                                 
2702                                 build_session (session_path,
2703                                                session_name,
2704                                                cchns,
2705                                                mchns,
2706                                                iconnect,
2707                                                oconnect,
2708                                                nphysin,
2709                                                nphysout, 
2710                                                engine->frame_rate() * 60 * 5);
2711                         }               
2712                 }
2713
2714         } while(response == Gtk::RESPONSE_HELP);
2715         m_new_session_dialog->hide_all();
2716 }
2717
2718 int
2719 ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
2720 {
2721         Session *new_session;
2722         int x;
2723         session_loaded = false;
2724         x = unload_session ();
2725
2726         if (x < 0) {
2727                 return -1;
2728         } else if (x > 0) {
2729                 return 0;
2730         }
2731
2732         /* if it already exists, we must have write access */
2733
2734         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2735                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2736 You do not have write access to this session.\n\
2737 This prevents the session from being loaded."));
2738                 return -1;
2739         }
2740
2741         try {
2742                 new_session = new Session (*engine, path, snap_name, mix_template);
2743         }
2744
2745         catch (...) {
2746
2747                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2748                 return -1;
2749         }
2750
2751         connect_to_session (new_session);
2752
2753         //if (engine->running()) {
2754         //mixer->show_window();
2755         //}
2756         session_loaded = true;
2757         return 0;
2758 }
2759
2760 int
2761 ARDOUR_UI::make_session_clean ()
2762 {
2763         if (session) {
2764                 session->set_clean ();
2765         }
2766
2767         return FALSE;
2768 }
2769
2770 int
2771 ARDOUR_UI::build_session (string path, string snap_name, 
2772                           uint32_t control_channels,
2773                           uint32_t master_channels, 
2774                           Session::AutoConnectOption input_connect,
2775                           Session::AutoConnectOption output_connect,
2776                           uint32_t nphysin,
2777                           uint32_t nphysout,
2778                           jack_nframes_t initial_length)
2779 {
2780         Session *new_session;
2781         int x;
2782
2783         session_loaded = false;
2784         x = unload_session ();
2785         if (x < 0) {
2786                 return -1;
2787         } else if (x > 0) {
2788                 return 0;
2789         }
2790         
2791         _session_is_new = true;
2792
2793         try {
2794                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2795                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2796         }
2797
2798         catch (...) {
2799
2800                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2801                 return -1;
2802         }
2803
2804         connect_to_session (new_session);
2805
2806         //if (engine->running()) {
2807         //mixer->show_window();
2808         //}
2809         session_loaded = true;
2810         return 0;
2811 }
2812
2813 void
2814 ARDOUR_UI::show ()
2815 {
2816         if (editor) {
2817                 editor->show_window ();
2818                 shown_flag = true;
2819         }
2820
2821         if (session && mixer) {
2822                 // mixer->show_window ();
2823         }
2824         
2825         if (about) {
2826                 about->present ();
2827         }
2828 }
2829
2830 void
2831 ARDOUR_UI::show_splash ()
2832 {
2833         if (about == 0) {
2834                 about = new About();
2835         }
2836         about->present();
2837 }
2838
2839 void
2840 ARDOUR_UI::hide_splash ()
2841 {
2842         if (about) {
2843                 // about->hide();
2844         }
2845 }
2846
2847 void
2848 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
2849 {
2850         size_t removed;
2851
2852         removed = rep.paths.size();
2853
2854         if (removed == 0) {
2855                 ArdourMessage msg (editor, X_("cleanupresults"),
2856                                    _("\
2857 No audio files were ready for cleanup\n\n\
2858 If this seems suprising, check for any existing\n\
2859 snapshots. These may still include regions that\n\
2860 require some unused files to continue to exist."));
2861                 return;
2862         } 
2863
2864         ArdourDialog results (_("ardour: cleanup"), true);
2865         
2866         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2867             CleanupResultsModelColumns() { 
2868                     add (visible_name);
2869                     add (fullpath);
2870             }
2871             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2872             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2873         };
2874
2875         
2876         Glib::RefPtr<Gtk::ListStore> results_model;
2877         CleanupResultsModelColumns results_columns;
2878         Gtk::TreeView results_display;
2879         
2880         results_model = ListStore::create (results_columns);
2881         results_display.set_model (results_model);
2882         results_display.append_column (list_title, results_columns.visible_name);
2883         results_display.set_headers_visible (true);
2884
2885         Gtk::ScrolledWindow list_scroller;
2886         Gtk::Label txt;
2887
2888         if (rep.space < 1048576.0f) {
2889                 if (removed > 1) {
2890                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2891                 } else {
2892                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2893                 }
2894         } else {
2895                 if (removed > 1) {
2896                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2897                 } else {
2898                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2899                 }
2900         }
2901
2902         results.get_vbox()->pack_start (txt, false, false);
2903         
2904         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2905                 TreeModel::Row row = *(results_model->append());
2906                 row[results_columns.visible_name] = *i;
2907                 row[results_columns.fullpath] = *i;
2908         }
2909         
2910         list_scroller.add (results_display);
2911         list_scroller.set_size_request (-1, 250);
2912         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2913         
2914         results.get_vbox()->pack_start (list_scroller, true, true);
2915         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2916         results.set_position (Gtk::WIN_POS_MOUSE);
2917
2918         results.run ();
2919 }
2920
2921 void
2922 ARDOUR_UI::cleanup ()
2923 {
2924         if (session == 0) {
2925                 /* shouldn't happen: menu item is insensitive */
2926                 return;
2927         }
2928
2929         ArdourDialog checker (_("ardour cleanup"));
2930         Gtk::Label label (_("\
2931 Cleanup is a destructive operation.\n\
2932 ALL undo/redo information will be lost if you cleanup.\n\
2933 Unused audio files will be moved to a \"dead sounds\" location."));
2934         
2935         checker.get_vbox()->pack_start (label, false, false);
2936         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2937         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2938
2939         checker.set_name (_("CleanupDialog"));
2940         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2941         checker.set_position (Gtk::WIN_POS_MOUSE);
2942
2943         switch (checker.run()) {
2944         case RESPONSE_ACCEPT:
2945                 break;
2946         default:
2947                 return;
2948         }
2949
2950         Session::cleanup_report rep;
2951
2952         editor->prepare_for_cleanup ();
2953
2954         if (session->cleanup_sources (rep)) {
2955                 return;
2956         }
2957
2958         display_cleanup_results (rep, 
2959                                  _("cleaned files"),
2960                                  _("\
2961 The following %1 %2 were not in use.\n\
2962 The next time you flush the wastebasket\n\
2963 it will release an additional %3 %4bytes\n\
2964 of disk space"
2965                                          ));
2966 }
2967
2968 void
2969 ARDOUR_UI::flush_trash ()
2970 {
2971         if (session == 0) {
2972                 /* shouldn't happen: menu item is insensitive */
2973                 return;
2974         }
2975
2976         Session::cleanup_report rep;
2977
2978         if (session->cleanup_trash_sources (rep)) {
2979                 return;
2980         }
2981
2982         display_cleanup_results (rep, 
2983                                  _("deleted file"),
2984                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2985 }
2986
2987 void
2988 ARDOUR_UI::add_route ()
2989 {
2990         int count;
2991
2992         if (!session) {
2993                 return;
2994         }
2995
2996         if (add_route_dialog == 0) {
2997                 add_route_dialog = new AddRouteDialog;
2998                 editor->ensure_float (*add_route_dialog);
2999         }
3000
3001         if (add_route_dialog->is_visible()) {
3002                 /* we're already doing this */
3003                 return;
3004         }
3005
3006         ResponseType r = (ResponseType) add_route_dialog->run ();
3007         
3008         add_route_dialog->hide();
3009
3010         switch (r) {
3011         case RESPONSE_ACCEPT:
3012                 break;
3013         default:
3014                 return;
3015                 break;
3016         }
3017
3018         if ((count = add_route_dialog->count()) <= 0) {
3019                 return;
3020         }
3021
3022         uint32_t input_chan = add_route_dialog->channels ();
3023         uint32_t output_chan;
3024         string name_template = add_route_dialog->name_template ();
3025         bool track = add_route_dialog->track ();
3026
3027         Session::AutoConnectOption oac = session->get_output_auto_connect();
3028
3029         if (oac & Session::AutoConnectMaster) {
3030                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3031         } else {
3032                 output_chan = input_chan;
3033         }
3034
3035         /* XXX do something with name template */
3036
3037         while (count) {
3038                 if (track) {
3039                         session_add_audio_track (input_chan, output_chan);
3040                 } else {
3041                         session_add_audio_bus (input_chan, output_chan);
3042                 }
3043                 --count;
3044                 
3045                 while (Main::events_pending()) {
3046                         Main::iteration ();
3047                 }
3048         }
3049 }
3050
3051 XMLNode*
3052 ARDOUR_UI::mixer_settings () const
3053 {
3054         XMLNode* node = 0;
3055
3056         if (session) {
3057                 node = session->instant_xml(X_("Mixer"), session->path());
3058         } else {
3059                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3060         }
3061
3062         if (!node) {
3063                 node = new XMLNode (X_("Mixer"));
3064         }
3065
3066         return node;
3067 }
3068
3069 XMLNode*
3070 ARDOUR_UI::editor_settings () const
3071 {
3072         XMLNode* node = 0;
3073
3074         if (session) {
3075                 node = session->instant_xml(X_("Editor"), session->path());
3076         } else {
3077                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3078         }
3079
3080         if (!node) {
3081                 node = new XMLNode (X_("Editor"));
3082         }
3083         return node;
3084 }
3085
3086 XMLNode*
3087 ARDOUR_UI::keyboard_settings () const
3088 {
3089         XMLNode* node = 0;
3090
3091         node = Config->extra_xml(X_("Keyboard"));
3092         
3093         if (!node) {
3094                 node = new XMLNode (X_("Keyboard"));
3095         }
3096         return node;
3097 }
3098
3099 void
3100 ARDOUR_UI::halt_on_xrun_message ()
3101 {
3102         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3103
3104         ArdourMessage msg (editor, X_("haltonxrun"),
3105                            _("Recording was stopped because your system could not keep up."));
3106 }
3107
3108 void 
3109 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3110 {
3111         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3112
3113         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3114                 delete *i;
3115         }
3116
3117         delete deletion_list;
3118 }
3119
3120 void
3121 ARDOUR_UI::disk_overrun_handler ()
3122 {
3123         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3124
3125         if (!have_disk_overrun_displayed) {
3126                 have_disk_overrun_displayed = true;
3127                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3128 The disk system on your computer\n\
3129 was not able to keep up with Ardour.\n\
3130 \n\
3131 Specifically, it failed to write data to disk\n\
3132 quickly enough to keep up with recording.\n"));
3133                 have_disk_overrun_displayed = false;
3134         }
3135 }
3136
3137 void
3138 ARDOUR_UI::disk_underrun_handler ()
3139 {
3140         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3141
3142         if (!have_disk_underrun_displayed) {
3143                 have_disk_underrun_displayed = true;
3144                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3145                         (_("The disk system on your computer\n\
3146 was not able to keep up with Ardour.\n\
3147 \n\
3148 Specifically, it failed to read data from disk\n\
3149 quickly enough to keep up with playback.\n")));
3150                 have_disk_underrun_displayed = false;
3151         } 
3152 }
3153
3154 void
3155 ARDOUR_UI::disk_underrun_message_gone ()
3156 {
3157         have_disk_underrun_displayed = false;
3158 }
3159
3160 void
3161 ARDOUR_UI::disk_overrun_message_gone ()
3162 {
3163         have_disk_underrun_displayed = false;
3164 }
3165
3166 int
3167 ARDOUR_UI::pending_state_dialog ()
3168 {
3169         ArdourDialog dialog ("pending state dialog");
3170         Label  message (_("\
3171 This session appears to have been in\n\
3172 middle of recording when ardour or\n\
3173 the computer was shutdown.\n\
3174 \n\
3175 Ardour can recover any captured audio for\n\
3176 you, or it can ignore it. Please decide\n\
3177 what you would like to do.\n"));
3178
3179         dialog.get_vbox()->pack_start (message);
3180         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3181         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3182
3183         dialog.set_position (WIN_POS_CENTER);
3184         dialog.show_all ();
3185         
3186         switch (dialog.run ()) {
3187         case RESPONSE_ACCEPT:
3188                 break;
3189         default:
3190                 return 1;
3191         }
3192
3193         return 0;
3194 }
3195         
3196         
3197 void
3198 ARDOUR_UI::disconnect_from_jack ()
3199 {
3200         if (engine) {
3201                 if( engine->disconnect_from_jack ()) {
3202                         ArdourMessage msg (editor, X_("nojack dialog"),
3203                                            _("Could not disconnect from JACK"));
3204                 }
3205
3206                 update_sample_rate (0);
3207         }
3208 }
3209
3210 void
3211 ARDOUR_UI::reconnect_to_jack ()
3212 {
3213         if (engine) {
3214                 if (engine->reconnect_to_jack ()) {
3215                         ArdourMessage msg (editor, X_("nojack dialog"),
3216                                            _("Could not reconnect to JACK"));
3217                 }
3218
3219                 update_sample_rate (0);
3220         }
3221 }
3222
3223 void
3224 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3225 {
3226         engine->request_buffer_size (nframes);
3227         update_sample_rate (0);
3228 }
3229
3230 int
3231 ARDOUR_UI::cmdline_new_session (string path)
3232 {
3233         if (path[0] != '/') {
3234                 char buf[PATH_MAX+1];
3235                 string str;
3236
3237                 getcwd (buf, sizeof (buf));
3238                 str = buf;
3239                 str += '/';
3240                 str += path;
3241                 path = str;
3242         }
3243
3244         new_session (false, path);
3245
3246         _will_create_new_session_automatically = false; /* done it */
3247         return FALSE; /* don't call it again */
3248 }