many changes, read the diffs
[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
808           punch_in_button (_("punch\nin")),
809           punch_out_button (_("punch\nout")),
810           auto_return_button (_("auto\nreturn")),
811           auto_play_button (_("auto\nplay")),
812           auto_input_button (_("auto\ninput")),
813           click_button (_("click")),
814           follow_button (_("follow\nPH")),
815           auditioning_alert_button (_("AUDITIONING")),
816           solo_alert_button (_("SOLO")),
817           shown_flag (false)
818
819 {
820         using namespace Gtk::Menu_Helpers;
821
822         Gtkmm2ext::init();
823
824         /* actually, its already loaded, but ... */
825
826         cerr << "Loading UI configuration file " << rcfile << endl;
827
828         about = 0;
829
830         if (theArdourUI == 0) {
831                 theArdourUI = this;
832         }
833
834         ActionManager::init ();
835         
836         m_new_session_dialog = 0;
837         m_new_session_dialog_ref = NewSessionDialogFactory::create();
838         m_new_session_dialog_ref->get_widget_derived (NewSessionDialogFactory::top_level_widget_name(), m_new_session_dialog);
839         editor = 0;
840         mixer = 0;
841         session = 0;
842         _session_is_new = false;
843         big_clock_window = 0;
844         session_selector_window = 0;
845         last_key_press_time = 0;
846         connection_editor = 0;
847         add_route_dialog = 0;
848         route_params = 0;
849         option_editor = 0;
850         location_ui = 0;
851         sfdb = 0;
852         open_session_selector = 0;
853         have_configure_timeout = false;
854         have_disk_overrun_displayed = false;
855         have_disk_underrun_displayed = false;
856         _will_create_new_session_automatically = false;
857         session_loaded = false;
858
859
860         last_configure_time.tv_sec = 0;
861         last_configure_time.tv_usec = 0;
862
863         shuttle_grabbed = false;
864         shuttle_fract = 0.0;
865
866         set_shuttle_units (Percentage);
867         set_shuttle_behaviour (Sprung);
868
869         shuttle_style_menu = 0;
870         shuttle_unit_menu = 0;
871
872         gettimeofday (&last_peak_grab, 0);
873         gettimeofday (&last_shuttle_request, 0);
874
875         ARDOUR::DiskStream::CannotRecordNoInput.connect (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input));
876         ARDOUR::DiskStream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
877         ARDOUR::DiskStream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
878         ARDOUR::DiskStream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
879
880         /* handle pending state with a dialog */
881
882         ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
883
884         channel_combo_strings = internationalize (channel_setup_names);
885         
886         /* have to wait for AudioEngine and Configuration before proceeding */
887 }
888
889 void
890 ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
891 {
892         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::cannot_record_no_input), ds));
893         
894         string msg = string_compose (_("\
895 You cannot record-enable\n\
896 track %1\n\
897 because it has no input connections.\n\
898 You would be wasting space recording silence."),
899                               ds->name());
900
901         ArdourMessage message (editor, X_("cannotrecord"), msg);
902 }
903
904 void
905 ARDOUR_UI::set_engine (AudioEngine& e)
906 {
907         engine = &e;
908
909         engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
910         engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
911         engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
912         engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
913
914         _tooltips.enable();
915
916         keyboard = new Keyboard;
917         install_keybindings ();
918
919         FastMeter::set_vertical_xpm (v_meter_strip_xpm);
920         FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
921
922         if (setup_windows ()) {
923                 throw failed_constructor ();
924         }
925
926         if (GTK_ARDOUR::show_key_actions) {
927                 vector<string> names;
928                 vector<string> paths;
929                 vector<string> keys;
930                 vector<AccelKey> bindings;
931
932                 ActionManager::get_all_actions (names, paths, keys, bindings);
933
934                 vector<string>::iterator n;
935                 vector<string>::iterator k;
936                 for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
937                         cerr << "Action: " << (*n) << " bound to " << (*k) << endl;
938                 }
939
940                 exit (0);
941         }
942
943         /* start with timecode, metering enabled
944         */
945         
946         blink_timeout_tag = -1;
947
948         /* this being a GUI and all, we want peakfiles */
949
950         FileSource::set_build_peakfiles (true);
951         FileSource::set_build_missing_peakfiles (true);
952
953         if (Source::start_peak_thread ()) {
954                 throw failed_constructor();
955         }
956
957         /* start the time-of-day-clock */
958         
959         update_wall_clock ();
960         Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
961
962         update_disk_space ();
963         update_cpu_load ();
964         update_sample_rate (engine->frame_rate());
965
966         starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
967         stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
968 }
969
970 ARDOUR_UI::~ARDOUR_UI ()
971 {
972         save_ardour_state ();
973
974         if (keyboard) {
975                 delete keyboard;
976         }
977
978         if (editor) {
979                 delete editor;
980         }
981
982         if (mixer) {
983                 delete mixer;
984         }
985
986         if (add_route_dialog) {
987                 delete add_route_dialog;
988         }
989
990         Source::stop_peak_thread ();
991 }
992
993 gint
994 ARDOUR_UI::configure_timeout ()
995 {
996         struct timeval now;
997         struct timeval diff;
998
999         if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
1000                 /* no configure events yet */
1001                 return TRUE;
1002         }
1003
1004         gettimeofday (&now, 0);
1005         timersub (&now, &last_configure_time, &diff);
1006
1007         /* force a gap of 0.5 seconds since the last configure event
1008          */
1009
1010         if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
1011                 return TRUE;
1012         } else {
1013                 have_configure_timeout = false;
1014                 save_ardour_state ();
1015                 return FALSE;
1016         }
1017 }
1018
1019 gboolean
1020 ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
1021 {
1022         if (have_configure_timeout) {
1023                 gettimeofday (&last_configure_time, 0);
1024         } else {
1025                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::configure_timeout), 100);
1026                 have_configure_timeout = true;
1027         }
1028                 
1029         return FALSE;
1030 }
1031
1032 void
1033 ARDOUR_UI::save_ardour_state ()
1034 {
1035         if (!keyboard || !mixer || !editor) {
1036                 return;
1037         }
1038         
1039         /* XXX this is all a bit dubious. add_extra_xml() uses
1040            a different lifetime model from add_instant_xml().
1041         */
1042
1043         XMLNode* node = new XMLNode (keyboard->get_state());
1044         Config->add_extra_xml (*node);
1045         Config->save_state();
1046
1047         XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
1048         XMLNode& mnode (mixer->get_state());
1049
1050         if (session) {
1051                 session->add_instant_xml(enode, session->path());
1052                 session->add_instant_xml(mnode, session->path());
1053         } else {
1054                 Config->add_instant_xml(enode, Config->get_user_ardour_path());
1055                 Config->add_instant_xml(mnode, Config->get_user_ardour_path());
1056         }
1057 }
1058
1059 void
1060 ARDOUR_UI::startup ()
1061 {
1062         /* Once the UI is up and running, start the audio engine. Doing
1063            this before the UI is up and running can cause problems
1064            when not running with SCHED_FIFO, because the amount of
1065            CPU and disk work needed to get the UI started can interfere
1066            with the scheduling of the audio thread.
1067         */
1068
1069         Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
1070 }
1071
1072 void
1073 ARDOUR_UI::finish()
1074 {
1075         if (session && session->dirty()) {
1076                 switch (ask_about_saving_session(_("quit"))) {
1077                 case -1:
1078                         return;
1079                         break;
1080                 case 1:
1081                         /* use the default name */
1082                         if (save_state_canfail ("")) {
1083                                 /* failed - don't quit */
1084                                 ArdourMessage (editor, X_("badsave dialog"),
1085                                                _("\
1086 Ardour was unable to save your session.\n\n\
1087 If you still wish to quit, please use the\n\n\
1088 \"Just quit\" option."));
1089                                 return;
1090                         }
1091                         break;
1092                 case 0:
1093                         break;
1094                 }
1095         }
1096
1097         quit ();
1098 }
1099
1100 int
1101 ARDOUR_UI::ask_about_saving_session (const string & what)
1102 {
1103         ArdourDialog window (_("ardour: save session?"));
1104         Gtk::Label  prompt_label;
1105         string msg;
1106
1107         msg = string_compose(_("Save and %1"), what);
1108         window.add_button (msg, RESPONSE_ACCEPT);
1109         msg = string_compose(_("Just %1"), what);
1110         window.add_button (msg, RESPONSE_APPLY);
1111         msg = string_compose(_("Don't %1"), what);
1112         window.add_button (msg, RESPONSE_REJECT);
1113
1114         Gtk::Button noquit_button (msg);
1115         noquit_button.set_name ("EditorGTKButton");
1116
1117         string prompt;
1118         string type;
1119
1120         if (session->snap_name() == session->name()) {
1121                 type = _("session");
1122         } else {
1123                 type = _("snapshot");
1124         }
1125         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?"), 
1126                          type, session->snap_name());
1127         
1128         prompt_label.set_text (prompt);
1129         prompt_label.set_alignment (0.5, 0.5);
1130         prompt_label.set_name (X_("PrompterLabel"));
1131         
1132         window.get_vbox()->pack_start (prompt_label);
1133
1134         window.set_name (_("Prompter"));
1135         window.set_position (Gtk::WIN_POS_MOUSE);
1136         window.set_modal (true);
1137         window.show_all ();
1138
1139         save_the_session = 0;
1140
1141         editor->ensure_float (window);
1142
1143         ResponseType r = (ResponseType) window.run();
1144
1145         window.hide ();
1146
1147         switch (r) {
1148         case RESPONSE_ACCEPT: // save and get out of here
1149                 return 1;
1150         case RESPONSE_APPLY:  // get out of here
1151                 return 0;
1152         default:
1153                 break;
1154         }
1155
1156         return -1;
1157 }
1158         
1159 gint
1160 ARDOUR_UI::every_second ()
1161 {
1162         update_cpu_load ();
1163         update_buffer_load ();
1164         update_disk_space ();
1165         // update_disk_rate ();
1166         return TRUE;
1167 }
1168
1169 gint
1170 ARDOUR_UI::every_point_one_seconds ()
1171 {
1172         struct timeval now;
1173         struct timeval diff;
1174         
1175         /* do not attempt to grab peak power more than once per cycle.
1176          */
1177
1178         gettimeofday (&now, 0);
1179         timersub (&now, &last_peak_grab, &diff);
1180
1181         if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
1182                 IO::GrabPeakPower(); /* EMIT_SIGNAL */
1183                 last_peak_grab = now;
1184         } 
1185
1186         update_speed_display ();
1187         RapidScreenUpdate(); /* EMIT_SIGNAL */
1188         return TRUE;
1189 }
1190
1191 gint
1192 ARDOUR_UI::every_point_zero_one_seconds ()
1193 {
1194         SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
1195         return TRUE;
1196 }
1197
1198 void
1199 ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
1200 {
1201         char buf[32];
1202
1203         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::update_sample_rate), ignored));
1204
1205         if (!engine->connected()) {
1206
1207                 snprintf (buf, sizeof (buf), _("disconnected"));
1208
1209         } else {
1210
1211                 jack_nframes_t rate = engine->frame_rate();
1212                 
1213                 if (fmod (rate, 1000.0) != 0.0) {
1214                         snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), 
1215                                   (float) rate/1000.0f,
1216                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1217                 } else {
1218                         snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), 
1219                                   rate/1000,
1220                                   (engine->frames_per_cycle() / (float) rate) * 1000.0f);
1221                 }
1222         }
1223
1224         sample_rate_label.set_text (buf);
1225 }
1226
1227 void
1228 ARDOUR_UI::update_cpu_load ()
1229 {
1230         char buf[32];
1231         snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
1232         cpu_load_label.set_text (buf);
1233 }
1234
1235 void
1236 ARDOUR_UI::update_disk_rate ()
1237 {
1238         char buf[64];
1239
1240         if (session) {
1241                 snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), 
1242                           session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
1243                 disk_rate_label.set_text (buf);
1244         } else {
1245                 disk_rate_label.set_text ("");
1246         }
1247 }
1248
1249 void
1250 ARDOUR_UI::update_buffer_load ()
1251 {
1252         char buf[64];
1253
1254         if (session) {
1255                 snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), 
1256                           session->playback_load(), session->capture_load());
1257                 buffer_load_label.set_text (buf);
1258         } else {
1259                 buffer_load_label.set_text ("");
1260         }
1261 }
1262
1263 void
1264 ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
1265 {
1266         if (ds.record_enabled()) {
1267                 rec_enabled_diskstreams++;
1268         }
1269 }
1270
1271 void
1272 ARDOUR_UI::update_disk_space()
1273 {
1274         if (session == 0) {
1275                 return;
1276         }
1277
1278         jack_nframes_t frames = session->available_capture_duration();
1279         char buf[64];
1280
1281         if (frames == max_frames) {
1282                 strcpy (buf, _("space: 24hrs+"));
1283         } else {
1284                 int hrs;
1285                 int mins;
1286                 int secs;
1287                 jack_nframes_t fr = session->frame_rate();
1288                 
1289                 if (session->actively_recording()){
1290                         
1291                         rec_enabled_diskstreams = 0;
1292                         session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
1293                         
1294                         if (rec_enabled_diskstreams) {
1295                                 frames /= rec_enabled_diskstreams;
1296                         }
1297                         
1298                 } else {
1299                         
1300                         /* hmmm. shall we divide by the route count? or the diskstream count?
1301                            or what? for now, do nothing ...
1302                         */
1303                         
1304                 }
1305                 
1306                 hrs  = frames / (fr * 3600);
1307                 frames -= hrs * fr * 3600;
1308                 mins = frames / (fr * 60);
1309                 frames -= mins * fr * 60;
1310                 secs = frames / fr;
1311                 
1312                 snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
1313         }
1314
1315         disk_space_label.set_text (buf);
1316 }                 
1317
1318 gint
1319 ARDOUR_UI::update_wall_clock ()
1320 {
1321         time_t now;
1322         struct tm *tm_now;
1323         char buf[16];
1324
1325         time (&now);
1326         tm_now = localtime (&now);
1327
1328         sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
1329         wall_clock_label.set_text (buf);
1330
1331         return TRUE;
1332 }
1333
1334 void
1335 ARDOUR_UI::toggle_recording_plugins ()
1336 {
1337         /* XXX use toggle_some_session_state */
1338
1339         if (session == 0) {
1340                 return;
1341         }
1342
1343         session->set_recording_plugins (!session->get_recording_plugins());
1344 }
1345         
1346 void
1347 ARDOUR_UI::toggle_auto_play ()
1348
1349 {
1350         toggle_some_session_state (auto_play_button,
1351                                    &Session::get_auto_play,
1352                                    &Session::set_auto_play);
1353 }
1354
1355 void
1356 ARDOUR_UI::toggle_auto_return ()
1357
1358 {
1359         toggle_some_session_state (auto_return_button,
1360                                    &Session::get_auto_return,
1361                                    &Session::set_auto_return);
1362 }
1363
1364 void
1365 ARDOUR_UI::toggle_click ()
1366 {
1367         toggle_some_session_state (click_button,
1368                                    &Session::get_clicking,
1369                                    &Session::set_clicking);
1370 }
1371
1372 void
1373 ARDOUR_UI::follow_changed ()
1374 {
1375         bool x;
1376
1377         if (!editor) {
1378                 return;
1379         }
1380
1381         if (follow_button.get_active() != (x = editor->follow_playhead())) {
1382                 follow_button.set_active (x);
1383         }
1384 }
1385
1386 void
1387 ARDOUR_UI::toggle_follow ()
1388 {
1389         bool x;
1390
1391         if (!editor) {
1392                 return;
1393         }
1394
1395         if (editor->follow_playhead() != (x = follow_button.get_active())) {
1396                 editor->set_follow_playhead (x);
1397         }
1398 }
1399
1400 void
1401 ARDOUR_UI::toggle_session_auto_loop ()
1402 {
1403         if (session) {
1404                 if (session->get_auto_loop()) {
1405                         if (session->transport_rolling()) {
1406                                 transport_roll();
1407                         }
1408                         else {
1409                                 session->request_auto_loop (false);
1410                         }
1411                 }
1412                 else {
1413                         session->request_auto_loop (true);
1414                 }
1415         }
1416 }
1417
1418 void
1419 ARDOUR_UI::toggle_session_punch_in ()
1420 {
1421         if (session) {
1422                 session->set_punch_in (!session->get_punch_in());
1423         }
1424 }
1425
1426 void
1427 ARDOUR_UI::toggle_punch_out ()
1428 {
1429         toggle_some_session_state (punch_out_button,
1430                                    &Session::get_punch_out,
1431                                    &Session::set_punch_out);
1432 }
1433
1434 void
1435 ARDOUR_UI::toggle_punch_in ()
1436 {
1437         toggle_some_session_state (punch_in_button,
1438                                    &Session::get_punch_in,
1439                                    &Session::set_punch_in);
1440 }
1441
1442 void
1443 ARDOUR_UI::map_button_state ()
1444
1445 {
1446         map_some_session_state (auto_return_button,
1447                                 &Session::get_auto_return);
1448         map_some_session_state (auto_play_button,
1449                                 &Session::get_auto_play);
1450         map_some_session_state (auto_input_button,
1451                                 &Session::get_auto_input);
1452         map_some_session_state (punch_in_button,
1453                                 &Session::get_punch_in);
1454         map_some_session_state (punch_out_button,
1455                                 &Session::get_punch_out);
1456         map_some_session_state (click_button,
1457                                 &Session::get_clicking);
1458 }
1459
1460 void
1461 ARDOUR_UI::queue_map_control_change (Session::ControlType t)
1462 {
1463         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::map_control_change), t));
1464 }
1465
1466 void
1467 ARDOUR_UI::map_control_change (Session::ControlType t)
1468 {
1469         switch (t) {
1470         case Session::AutoPlay:
1471                 map_some_session_state (auto_play_button, &Session::get_auto_play);
1472                 break;
1473
1474         case Session::AutoLoop:
1475                 break;
1476
1477         case Session::AutoReturn:
1478                 map_some_session_state (auto_return_button, &Session::get_auto_return);
1479                 break;
1480
1481         case Session::AutoInput:
1482                 map_some_session_state (auto_input_button, &Session::get_auto_input);
1483                 break;
1484
1485         case Session::PunchOut:
1486                 map_some_session_state (punch_in_button, &Session::get_punch_out);
1487                 break;
1488
1489         case Session::PunchIn:
1490                 map_some_session_state (punch_in_button, &Session::get_punch_in);
1491                 break;
1492
1493         case Session::Clicking:
1494                 map_some_session_state (click_button, &Session::get_clicking);
1495                 break;
1496
1497         case Session::SlaveType:
1498 //              map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
1499                 break;
1500
1501         case Session::SendMTC:
1502 //              map_some_session_state (send_mtc_button, &Session::get_send_mtc);
1503                 break;
1504
1505         case Session::SendMMC:
1506 //              map_some_session_state (send_mmc_button, &Session::get_send_mmc);
1507                 break;
1508
1509         case Session::MMCControl:       
1510 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1511                 break;
1512
1513         case Session::MidiFeedback:       
1514 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1515                 break;
1516         case Session::MidiControl:       
1517 //              map_some_session_state (mmc_control_button, &Session::get_mmc_control);
1518                 break;
1519                 
1520         case Session::Live:
1521                 break;
1522
1523         case Session::RecordingPlugins:
1524                 break;
1525
1526         case Session::CrossFadesActive:
1527                 break;
1528                 
1529         case Session::EditingMode:
1530                 break;
1531
1532         case Session::PlayRange:
1533                 break;
1534
1535         case Session::AlignChoice:
1536                 /* don't care, this is handled by the options editor */
1537                 break;
1538         case Session::SeamlessLoop:
1539                 /* don't care, this is handled by the options editor */
1540                 break;
1541                
1542         }
1543 }
1544
1545 void
1546 ARDOUR_UI::control_methods_adjusted ()
1547
1548 {
1549         int which_method;
1550
1551         which_method = (int) online_control_button->adjustment.get_value();
1552         switch (which_method) {
1553         case 0:
1554                 allow_mmc_and_local ();
1555                 break;
1556         case 1:
1557                 allow_mmc_only ();
1558                 break;
1559         case 2:
1560                 allow_local_only ();
1561                 break;
1562         default:
1563                 fatal << _("programming error: impossible control method") << endmsg;
1564         }
1565 }
1566         
1567
1568 void
1569 ARDOUR_UI::mmc_device_id_adjusted ()
1570
1571 {
1572 #if 0
1573         if (mmc) {
1574                 int dev_id = (int) mmc_id_button->adjustment.get_value();
1575                 mmc->set_device_id (dev_id);
1576         }
1577 #endif
1578 }
1579
1580 void
1581 ARDOUR_UI::map_some_session_state (ToggleButton& button,
1582                                    bool (Session::*get)() const)
1583         
1584 {
1585         bool x;
1586
1587         if (session == 0) {
1588                 return;
1589         }
1590         
1591         if (button.get_active() != (x = (session->*get)())) {
1592                 button.set_active (x);
1593         }
1594 }
1595
1596 void
1597 ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
1598                                       bool (Session::*get)() const,
1599                                       void (Session::*set)(bool))
1600
1601 {
1602         bool button_state;
1603         bool session_state;
1604
1605         if (session == 0) {
1606                 return;
1607         }
1608
1609         button_state = button.get_active ();
1610         session_state = (session->*get)();
1611
1612         if (button_state != session_state) {
1613                 (session->*set) (button_state);
1614 #if 0
1615         
1616                 /* check that it worked, and reverse
1617                    the button state if it didn't
1618                 */
1619
1620                 if ((session->*get)() != button_state) {
1621                         button->set_active (!button_state);
1622                 }
1623 #endif
1624
1625         }
1626 }       
1627
1628 gint
1629 ARDOUR_UI::session_menu (GdkEventButton *ev)
1630 {
1631         session_popup_menu->popup (0, 0);
1632         return TRUE;
1633 }
1634
1635 void
1636 ARDOUR_UI::redisplay_recent_sessions ()
1637 {
1638         vector<string *> *sessions;
1639         vector<string *>::iterator i;
1640         RecentSessionsSorter cmp;
1641         
1642         recent_session_display.set_model (Glib::RefPtr<TreeModel>(0));
1643         recent_session_model->clear ();
1644
1645         RecentSessions rs;
1646         ARDOUR::read_recent_sessions (rs);
1647
1648         if (rs.empty()) {
1649                 recent_session_display.set_model (recent_session_model);
1650                 return;
1651         }
1652
1653         /* sort them alphabetically */
1654         sort (rs.begin(), rs.end(), cmp);
1655         sessions = new vector<string*>;
1656
1657         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
1658                 sessions->push_back (new string ((*i).second));
1659         }
1660
1661         for (i = sessions->begin(); i != sessions->end(); ++i) {
1662
1663                 vector<string*>* states;
1664                 vector<const gchar*> item;
1665                 string fullpath = *(*i);
1666                 
1667                 /* remove any trailing / */
1668
1669                 if (fullpath[fullpath.length()-1] == '/') {
1670                         fullpath = fullpath.substr (0, fullpath.length()-1);
1671                 }
1672
1673                 /* now get available states for this session */
1674
1675                 if ((states = Session::possible_states (fullpath)) == 0) {
1676                         /* no state file? */
1677                         continue;
1678                 }
1679
1680                 TreeModel::Row row = *(recent_session_model->append());
1681
1682                 row[recent_session_columns.visible_name] = PBD::basename (fullpath);
1683                 row[recent_session_columns.fullpath] = fullpath;
1684
1685                 if (states->size() > 1) {
1686
1687                         /* add the children */
1688                         
1689                         for (vector<string*>::iterator i2 = states->begin(); i2 != states->end(); ++i2) {
1690                                 
1691                                 TreeModel::Row child_row = *(recent_session_model->append (row.children()));
1692
1693                                 child_row[recent_session_columns.visible_name] = **i2;
1694                                 child_row[recent_session_columns.fullpath] = fullpath;
1695
1696                                 delete *i2;
1697                         }
1698                 }
1699
1700                 delete states;
1701         }
1702
1703         recent_session_display.set_model (recent_session_model);
1704         delete sessions;
1705 }
1706
1707 void
1708 ARDOUR_UI::build_session_selector ()
1709 {
1710         session_selector_window = new ArdourDialog ("session selector");
1711         
1712         Gtk::ScrolledWindow *scroller = manage (new Gtk::ScrolledWindow);
1713         
1714         session_selector_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1715         session_selector_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1716
1717         recent_session_model = TreeStore::create (recent_session_columns);
1718         recent_session_display.set_model (recent_session_model);
1719         recent_session_display.append_column (_("Recent Sessions"), recent_session_columns.visible_name);
1720         recent_session_display.set_headers_visible (false);
1721
1722         scroller->add (recent_session_display);
1723         scroller->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
1724
1725         session_selector_window->set_name ("SessionSelectorWindow");
1726         session_selector_window->set_size_request (200, 400);
1727         session_selector_window->get_vbox()->pack_start (*scroller);
1728         session_selector_window->show_all_children();
1729 }
1730
1731 void
1732 ARDOUR_UI::open_recent_session ()
1733 {
1734         /* popup selector window */
1735
1736         if (session_selector_window == 0) {
1737                 build_session_selector ();
1738         }
1739
1740         redisplay_recent_sessions ();
1741
1742         ResponseType r = (ResponseType) session_selector_window->run ();
1743
1744         session_selector_window->hide();
1745
1746         switch (r) {
1747         case RESPONSE_ACCEPT:
1748                 break;
1749         default:
1750                 return;
1751         }
1752
1753         Gtk::TreeModel::iterator i = recent_session_display.get_selection()->get_selected();
1754
1755         if (i == recent_session_model->children().end()) {
1756                 return;
1757         }
1758         
1759         Glib::ustring path = (*i)[recent_session_columns.fullpath];
1760         Glib::ustring state = (*i)[recent_session_columns.visible_name];
1761
1762         _session_is_new = false;
1763
1764         load_session (path, state);
1765 }
1766
1767 bool
1768 ARDOUR_UI::filter_ardour_session_dirs (const FileFilter::Info& info) 
1769 {
1770         struct stat statbuf;
1771
1772         if (stat (info.filename.c_str(), &statbuf) != 0) {
1773                 return false;
1774         }
1775
1776         if (!S_ISDIR(statbuf.st_mode)) {
1777                 return false;
1778         }
1779
1780         string session_file = info.filename;
1781         session_file += '/';
1782         session_file += PBD::basename (info.filename);
1783         session_file += ".ardour";
1784         
1785         if (stat (session_file.c_str(), &statbuf) != 0) {
1786                 return false;
1787         }
1788
1789         return S_ISREG (statbuf.st_mode);
1790 }
1791
1792 void
1793 ARDOUR_UI::open_session ()
1794 {
1795         /* popup selector window */
1796
1797         if (open_session_selector == 0) {
1798
1799                 /* ardour sessions are folders */
1800
1801                 open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
1802                 open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1803                 open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
1804
1805                 FileFilter session_filter;
1806                 session_filter.add_pattern ("*.ardour");
1807                 session_filter.set_name (_("Ardour sessions"));
1808                 open_session_selector->add_filter (session_filter);
1809                 open_session_selector->set_filter (session_filter);
1810         }
1811
1812         int response = open_session_selector->run();
1813         open_session_selector->hide ();
1814
1815         switch (response) {
1816         case RESPONSE_ACCEPT:
1817                 break;
1818         default:
1819                 open_session_selector->hide();
1820                 return;
1821         }
1822
1823         open_session_selector->hide();
1824         string session_path = open_session_selector->get_filename();
1825         string path, name;
1826         bool isnew;
1827
1828         if (session_path.length() > 0) {
1829                 if (Session::find_session (session_path, path, name, isnew) == 0) {
1830                         _session_is_new = isnew;
1831                         load_session (path, name);
1832                 }
1833         }
1834 }
1835
1836
1837 void
1838 ARDOUR_UI::session_add_midi_track ()
1839 {
1840         cerr << _("Patience is a virtue.\n");
1841 }
1842
1843 void
1844 ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
1845 {
1846         Route* route;
1847
1848         if (session == 0) {
1849                 warning << _("You cannot add a track without a session already loaded.") << endmsg;
1850                 return;
1851         }
1852
1853         try { 
1854                 if (disk) {
1855                         if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
1856                                 error << _("could not create new audio track") << endmsg;
1857                         }
1858                 } else {
1859                         if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
1860                                 error << _("could not create new audio bus") << endmsg;
1861                         }
1862                 }
1863                 
1864 #if CONTROLOUTS
1865                 if (need_control_room_outs) {
1866                         pan_t pans[2];
1867                         
1868                         pans[0] = 0.5;
1869                         pans[1] = 0.5;
1870                         
1871                         route->set_stereo_control_outs (control_lr_channels);
1872                         route->control_outs()->set_stereo_pan (pans, this);
1873                 }
1874 #endif /* CONTROLOUTS */
1875         }
1876
1877         catch (...) {
1878                 ArdourMessage msg (editor, X_("noport dialog"),
1879                                    _("There are insufficient JACK ports available\n\
1880 to create a new track or bus.\n\
1881 You should save Ardour, exit and\n\
1882 restart JACK with more ports."));
1883         }
1884 }
1885
1886 void
1887 ARDOUR_UI::diskstream_added (DiskStream* ds)
1888 {
1889 }
1890
1891 void
1892 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
1893 {
1894         jack_nframes_t _preroll;
1895
1896         if (session) {
1897                 _preroll = session->convert_to_frames_at (new_position, session->preroll);
1898
1899                 if (new_position > _preroll) {
1900                         new_position -= _preroll;
1901                 } else {
1902                         new_position = 0;
1903                 }
1904
1905                 session->request_locate (new_position);
1906         }
1907 }
1908
1909 void
1910 ARDOUR_UI::transport_goto_start ()
1911 {
1912         if (session) {
1913                 session->request_locate (0);
1914
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 (0);
1922                 }
1923         }
1924 }
1925
1926 void
1927 ARDOUR_UI::transport_goto_end ()
1928 {
1929         if (session) {
1930                 jack_nframes_t frame = session->current_end_frame();
1931                 session->request_locate (frame);
1932
1933                 /* force displayed area in editor to start no matter
1934                    what "follow playhead" setting is.
1935                 */
1936                 
1937                 if (editor) {
1938                         editor->reposition_x_origin (frame);
1939                 }
1940         }
1941 }
1942
1943 void
1944 ARDOUR_UI::transport_stop ()
1945 {
1946         if (!session) {
1947                 return;
1948         }
1949
1950         if (session->is_auditioning()) {
1951                 session->cancel_audition ();
1952                 return;
1953         }
1954         
1955         if (session->get_auto_loop()) {
1956                 session->request_auto_loop (false);
1957         }
1958         
1959         session->request_stop ();
1960 }
1961
1962 void
1963 ARDOUR_UI::transport_stop_and_forget_capture ()
1964 {
1965         if (session) {
1966                 session->request_stop (true);
1967         }
1968 }
1969
1970 void
1971 ARDOUR_UI::remove_last_capture()
1972 {
1973         if (editor) {
1974                 editor->remove_last_capture();
1975         }
1976 }
1977
1978 void
1979 ARDOUR_UI::transport_record ()
1980 {
1981         if (session) {
1982                 switch (session->record_status()) {
1983                 case Session::Disabled:
1984                         if (session->ntracks() == 0) {
1985                                 string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
1986                                 ArdourMessage msg (editor, X_("cannotrecenable"), txt);
1987                                 return;
1988                         }
1989                         session->maybe_enable_record ();
1990                         break;
1991                 case Session::Recording:
1992                 case Session::Enabled:
1993                         session->disable_record ();
1994                 }
1995         }
1996 }
1997
1998 void
1999 ARDOUR_UI::transport_roll ()
2000 {
2001         bool rolling;
2002
2003         if (!session) {
2004                 return;
2005         }
2006
2007         rolling = session->transport_rolling ();
2008
2009         if (session->get_auto_loop()) {
2010                 session->request_auto_loop (false);
2011                 auto_loop_button.set_active (false);
2012                 roll_button.set_active (true);
2013         } else if (session->get_play_range ()) {
2014                 session->request_play_range (false);
2015                 play_selection_button.set_active (false);
2016         } else if (rolling) {
2017                 session->request_locate (session->last_transport_start(), true);
2018         }
2019
2020         session->request_transport_speed (1.0f);
2021 }
2022
2023 void
2024 ARDOUR_UI::transport_loop()
2025 {
2026         if (session) {
2027                 if (session->get_auto_loop()) {
2028                         if (session->transport_rolling()) {
2029                                 Location * looploc = session->locations()->auto_loop_location();
2030                                 if (looploc) {
2031                                         session->request_locate (looploc->start(), true);
2032                                 }
2033                         }
2034                 }
2035                 else {
2036                         session->request_auto_loop (true);
2037                 }
2038         }
2039 }
2040
2041 void
2042 ARDOUR_UI::transport_play_selection ()
2043 {
2044         if (!session) {
2045                 return;
2046         }
2047
2048         if (!session->get_play_range()) {
2049                 session->request_stop ();
2050         }
2051
2052         editor->play_selection ();
2053 }
2054
2055 void
2056 ARDOUR_UI::transport_rewind (int option)
2057 {
2058         float current_transport_speed;
2059  
2060         if (session) {
2061                 current_transport_speed = session->transport_speed();
2062                 
2063                 if (current_transport_speed >= 0.0f) {
2064                         switch (option) {
2065                         case 0:
2066                                 session->request_transport_speed (-1.0f);
2067                                 break;
2068                         case 1:
2069                                 session->request_transport_speed (-4.0f);
2070                                 break;
2071                         case -1:
2072                                 session->request_transport_speed (-0.5f);
2073                                 break;
2074                         }
2075                 } else {
2076                         /* speed up */
2077                         session->request_transport_speed (current_transport_speed * 1.5f);
2078                 }
2079         }
2080 }
2081
2082 void
2083 ARDOUR_UI::transport_forward (int option)
2084 {
2085         float current_transport_speed;
2086         
2087         if (session) {
2088                 current_transport_speed = session->transport_speed();
2089                 
2090                 if (current_transport_speed <= 0.0f) {
2091                         switch (option) {
2092                         case 0:
2093                                 session->request_transport_speed (1.0f);
2094                                 break;
2095                         case 1:
2096                                 session->request_transport_speed (4.0f);
2097                                 break;
2098                         case -1:
2099                                 session->request_transport_speed (0.5f);
2100                                 break;
2101                         }
2102                 } else {
2103                         /* speed up */
2104                         session->request_transport_speed (current_transport_speed * 1.5f);
2105                 }
2106         }
2107 }
2108
2109 void
2110 ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
2111 {
2112         if (session == 0) {
2113                 return;
2114         }
2115
2116         DiskStream *ds;
2117
2118         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2119                 Port *port = ds->io()->input (0);
2120                 port->request_monitor_input (!port->monitoring_input());
2121         }
2122 }
2123
2124 void
2125 ARDOUR_UI::toggle_record_enable (guint32 dstream)
2126 {
2127         if (session == 0) {
2128                 return;
2129         }
2130
2131         DiskStream *ds;
2132
2133         if ((ds = session->diskstream_by_id (dstream)) != 0) {
2134                 ds->set_record_enabled (!ds->record_enabled(), this);
2135         }
2136 }
2137
2138 void
2139 ARDOUR_UI::queue_transport_change ()
2140 {
2141         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &ARDOUR_UI::map_transport_state));
2142 }
2143
2144 void
2145 ARDOUR_UI::map_transport_state ()
2146 {
2147         float sp = session->transport_speed();
2148
2149         if (sp == 1.0f) {
2150                 transport_rolling ();
2151         } else if (sp < 0.0f) {
2152                 transport_rewinding ();
2153         } else if (sp > 0.0f) {
2154                 transport_forwarding ();
2155         } else {
2156                 transport_stopped ();
2157         }
2158 }
2159
2160 void
2161 ARDOUR_UI::send_all_midi_feedback ()
2162 {
2163         if (session) {
2164                 session->send_all_midi_feedback();
2165         }
2166 }
2167
2168 void
2169 ARDOUR_UI::allow_local_only ()
2170 {
2171
2172 }
2173
2174 void
2175 ARDOUR_UI::allow_mmc_only ()
2176 {
2177
2178 }
2179
2180 void
2181 ARDOUR_UI::allow_mmc_and_local ()
2182 {
2183
2184 }
2185
2186 void
2187 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
2188 {
2189         snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
2190                 (int) adj.get_value()].c_str());
2191 }
2192
2193 void
2194 ARDOUR_UI::engine_stopped ()
2195 {
2196         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_stopped));
2197         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2198         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2199 }
2200
2201
2202 void
2203 ARDOUR_UI::engine_running ()
2204 {
2205         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
2206         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
2207         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
2208 }
2209
2210 void
2211 ARDOUR_UI::engine_halted ()
2212 {
2213         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_halted));
2214
2215         ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
2216         ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
2217
2218         update_sample_rate (0);
2219
2220         ArdourMessage msg (editor, X_("halted"),
2221                            _("\
2222 JACK has either been shutdown or it\n\
2223 disconnected Ardour because Ardour\n\
2224 was not fast enough. You can save the\n\
2225 session and/or try to reconnect to JACK ."));
2226 }
2227
2228 int32_t
2229 ARDOUR_UI::do_engine_start ()
2230 {
2231         try { 
2232                 engine->start();
2233         }
2234
2235         catch (AudioEngine::PortRegistrationFailure& err) {
2236                 engine->stop ();
2237                 error << _("Unable to create all required ports")
2238                       << endmsg;
2239                 unload_session ();
2240                 return -1;
2241         }
2242
2243         catch (...) {
2244                 engine->stop ();
2245                 error << _("Unable to start the session running")
2246                       << endmsg;
2247                 unload_session ();
2248                 return -2;
2249         }
2250         
2251         return 0;
2252 }
2253
2254 gint
2255 ARDOUR_UI::start_engine ()
2256 {
2257         if (do_engine_start () == 0) {
2258                 if (session && _session_is_new) {
2259                         /* we need to retain initial visual 
2260                            settings for a new session 
2261                         */
2262                         session->save_state ("");
2263                 }
2264
2265                 /* there is too much going on, in too many threads, for us to 
2266                    end up with a clean session. So wait 1 second after loading,
2267                    and fix it up. its ugly, but until i come across a better
2268                    solution, its what we have.
2269                 */
2270
2271                 Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::make_session_clean), 1000);
2272         }
2273
2274         return FALSE;
2275 }
2276
2277 void
2278 ARDOUR_UI::update_clocks ()
2279 {
2280          Clock (session->audible_frame()); /* EMIT_SIGNAL */
2281 }
2282
2283 void
2284 ARDOUR_UI::start_clocking ()
2285 {
2286         clock_signal_connection = RapidScreenUpdate.connect (mem_fun(*this, &ARDOUR_UI::update_clocks));
2287 }
2288
2289 void
2290 ARDOUR_UI::stop_clocking ()
2291 {
2292         clock_signal_connection.disconnect ();
2293 }
2294         
2295 void
2296 ARDOUR_UI::toggle_clocking ()
2297 {
2298 #if 0
2299         if (clock_button.get_active()) {
2300                 start_clocking ();
2301         } else {
2302                 stop_clocking ();
2303         }
2304 #endif
2305 }
2306
2307 gint
2308 ARDOUR_UI::_blink (void *arg)
2309
2310 {
2311         ((ARDOUR_UI *) arg)->blink ();
2312         return TRUE;
2313 }
2314
2315 void
2316 ARDOUR_UI::blink ()
2317 {
2318          Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
2319 }
2320
2321 void
2322 ARDOUR_UI::start_blinking ()
2323 {
2324         /* Start the blink signal. Everybody with a blinking widget
2325            uses Blink to drive the widget's state.
2326         */
2327
2328         if (blink_timeout_tag < 0) {
2329                 blink_on = false;       
2330                 blink_timeout_tag = gtk_timeout_add (240, _blink, this);
2331         }
2332 }
2333
2334 void
2335 ARDOUR_UI::stop_blinking ()
2336 {
2337         if (blink_timeout_tag >= 0) {
2338                 gtk_timeout_remove (blink_timeout_tag);
2339                 blink_timeout_tag = -1;
2340         }
2341 }
2342
2343
2344 void
2345 ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
2346 {
2347         using namespace Gtk;
2348         using namespace Menu_Helpers;
2349
2350         if (dstream.hidden()) {
2351                 return;
2352         }
2353
2354         MenuList& items = diskstream_menu->items();
2355         items.push_back (MenuElem (dstream.name(), bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
2356 }
2357         
2358 void
2359 ARDOUR_UI::diskstream_selected (gint32 id)
2360 {
2361         selected_dstream = id;
2362         Main::quit ();
2363 }
2364
2365 gint32
2366 ARDOUR_UI::select_diskstream (GdkEventButton *ev)
2367 {
2368         using namespace Gtk;
2369         using namespace Menu_Helpers;
2370
2371         if (session == 0) {
2372                 return -1;
2373         }
2374
2375         diskstream_menu = new Menu();
2376         diskstream_menu->set_name ("ArdourContextMenu");
2377         using namespace Gtk;
2378         using namespace Menu_Helpers;
2379
2380         MenuList& items = diskstream_menu->items();
2381         items.push_back (MenuElem (_("No Stream"), (bind (mem_fun(*this, &ARDOUR_UI::diskstream_selected), -1))));
2382
2383         session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
2384
2385         if (ev) {
2386                 diskstream_menu->popup (ev->button, ev->time);
2387         } else {
2388                 diskstream_menu->popup (0, 0);
2389         }
2390
2391         selected_dstream = -1;
2392
2393         Main::run ();
2394
2395         delete diskstream_menu;
2396
2397         return selected_dstream;
2398 }
2399
2400 void
2401 ARDOUR_UI::name_io_setup (AudioEngine& engine, 
2402                           string& buf,
2403                           IO& io,
2404                           bool in)
2405 {
2406         if (in) {
2407                 if (io.n_inputs() == 0) {
2408                         buf = _("none");
2409                         return;
2410                 }
2411                 
2412                 /* XXX we're not handling multiple ports yet. */
2413
2414                 const char **connections = io.input(0)->get_connections();
2415                 
2416                 if (connections == 0 || connections[0] == '\0') {
2417                         buf = _("off");
2418                 } else {
2419                         buf = connections[0];
2420                 }
2421
2422                 free (connections);
2423
2424         } else {
2425
2426                 if (io.n_outputs() == 0) {
2427                         buf = _("none");
2428                         return;
2429                 }
2430                 
2431                 /* XXX we're not handling multiple ports yet. */
2432
2433                 const char **connections = io.output(0)->get_connections();
2434                 
2435                 if (connections == 0 || connections[0] == '\0') {
2436                         buf = _("off");
2437                 } else {
2438                         buf = connections[0];
2439                 }
2440
2441                 free (connections);
2442         }
2443 }
2444
2445 void
2446 ARDOUR_UI::snapshot_session ()
2447 {
2448         ArdourPrompter prompter (true);
2449         string snapname;
2450         string now;
2451         time_t n;
2452
2453         time (&n);
2454         now = ctime (&n);
2455         now = now.substr (0, now.length() - 1);
2456
2457         prompter.set_name ("Prompter");
2458         prompter.set_prompt (_("Name for snapshot"));
2459         prompter.set_initial_text (now);
2460         
2461         switch (prompter.run()) {
2462         case RESPONSE_ACCEPT:
2463                 prompter.get_result (snapname);
2464                 if (snapname.length()){
2465                         save_state (snapname);
2466                 }
2467                 break;
2468
2469         default:
2470                 break;
2471         }
2472 }
2473
2474 void
2475 ARDOUR_UI::save_state (const string & name)
2476 {
2477         (void) save_state_canfail (name);
2478 }
2479                 
2480 int
2481 ARDOUR_UI::save_state_canfail (string name)
2482 {
2483         if (session) {
2484                 int ret;
2485
2486                 if (name.length() == 0) {
2487                         name = session->snap_name();
2488                 }
2489
2490                 if ((ret = session->save_state (name)) != 0) {
2491                         return ret;
2492                 }
2493         }
2494         save_ardour_state (); /* XXX cannot fail? yeah, right ... */
2495         return 0;
2496 }
2497
2498 void
2499 ARDOUR_UI::restore_state (string name)
2500 {
2501         if (session) {
2502                 if (name.length() == 0) {
2503                         name = session->name();
2504                 }
2505                 session->restore_state (name);
2506         }
2507 }
2508
2509 void
2510 ARDOUR_UI::primary_clock_value_changed ()
2511 {
2512         if (session) {
2513                 session->request_locate (primary_clock.current_time ());
2514         }
2515 }
2516
2517 void
2518 ARDOUR_UI::secondary_clock_value_changed ()
2519 {
2520         if (session) {
2521                 session->request_locate (secondary_clock.current_time ());
2522         }
2523 }
2524
2525 void
2526 ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
2527 {
2528         if (session && dstream && dstream->record_enabled()) {
2529
2530                 Session::RecordState rs;
2531                 
2532                 rs = session->record_status ();
2533
2534                 switch (rs) {
2535                 case Session::Disabled:
2536                 case Session::Enabled:
2537                         if (w->get_state() != STATE_SELECTED) {
2538                                 w->set_state (STATE_SELECTED);
2539                         }
2540                         break;
2541
2542                 case Session::Recording:
2543                         if (w->get_state() != STATE_ACTIVE) {
2544                                 w->set_state (STATE_ACTIVE);
2545                         }
2546                         break;
2547                 }
2548
2549         } else {
2550                 if (w->get_state() != STATE_NORMAL) {
2551                         w->set_state (STATE_NORMAL);
2552                 }
2553         }
2554 }
2555
2556 void
2557 ARDOUR_UI::transport_rec_enable_blink (bool onoff) 
2558 {
2559         if (session == 0) {
2560                 return;
2561         }
2562         
2563         switch (session->record_status()) {
2564         case Session::Enabled:
2565                 if (onoff) {
2566                         rec_button.set_state (1);
2567                 } else {
2568                         rec_button.set_state (0);
2569                 }
2570                 break;
2571
2572         case Session::Recording:
2573                 rec_button.set_state (2);
2574                 break;
2575
2576         default:
2577                 rec_button.set_state (0);
2578                 break;
2579         }
2580 }
2581
2582 gint
2583 ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
2584 {
2585         window->hide();
2586         Gtk::Main::quit ();
2587         return TRUE;
2588 }
2589
2590 void
2591 ARDOUR_UI::start_keyboard_prefix ()
2592 {
2593         keyboard->start_prefix();
2594 }
2595
2596 void
2597 ARDOUR_UI::save_template ()
2598
2599 {
2600         ArdourPrompter prompter (true);
2601         string name;
2602
2603         prompter.set_name (X_("Prompter"));
2604         prompter.set_prompt (_("Name for mix template:"));
2605         prompter.set_initial_text(session->name() + _("-template"));
2606         
2607         switch (prompter.run()) {
2608         case RESPONSE_ACCEPT:
2609                 prompter.get_result (name);
2610                 
2611                 if (name.length()) {
2612                         session->save_template (name);
2613                 }
2614                 break;
2615
2616         default:
2617                 break;
2618         }
2619 }
2620
2621 void
2622 ARDOUR_UI::new_session (bool startup, std::string predetermined_path)
2623 {
2624         m_new_session_dialog->show_all();
2625         m_new_session_dialog->set_transient_for(*editor);
2626         m_new_session_dialog->set_name(predetermined_path);
2627
2628         int response = Gtk::RESPONSE_CANCEL;
2629
2630         do {
2631                 response = m_new_session_dialog->run ();
2632         
2633                 if(response == Gtk::RESPONSE_OK) {
2634
2635                         _session_is_new = true;
2636                         
2637                         std::string session_name = m_new_session_dialog->session_name();
2638                         std::string session_path = m_new_session_dialog->session_folder();
2639                         
2640                         /*
2641                           XXX This is needed because session constructor wants a 
2642                           non-existant path. hopefully this will be fixed at some point.
2643                         */
2644                         session_path = Glib::build_filename(session_path, session_name);
2645                         
2646                         std::string template_name = m_new_session_dialog->session_template_name();
2647                         
2648                         if (m_new_session_dialog->use_session_template()) {
2649                                 
2650                                 load_session (session_path, session_name, &template_name);
2651                                 
2652                         } else {
2653                                 
2654                                 uint32_t cchns;
2655                                 uint32_t mchns;
2656                                 Session::AutoConnectOption iconnect;
2657                                 Session::AutoConnectOption oconnect;
2658                                 
2659                                 if (m_new_session_dialog->create_control_bus()) {
2660                                         cchns = (uint32_t) m_new_session_dialog->control_channel_count();
2661                                 } else {
2662                                         cchns = 0;
2663                                 }
2664                                 
2665                                 if (m_new_session_dialog->create_master_bus()) {
2666                                         mchns = (uint32_t) m_new_session_dialog->master_channel_count();
2667                                 } else {
2668                                         mchns = 0;
2669                                 }
2670                                 
2671                                 if (m_new_session_dialog->connect_inputs()) {
2672                                         iconnect = Session::AutoConnectPhysical;
2673                                 } else {
2674                                         iconnect = Session::AutoConnectOption (0);
2675                                 }
2676                                 
2677                                 /// @todo some minor tweaks.
2678
2679                                 if (m_new_session_dialog->connect_outs_to_master()) {
2680                                         oconnect = Session::AutoConnectMaster;
2681                                 } else if (m_new_session_dialog->connect_outs_to_physical()) {
2682                                         oconnect = Session::AutoConnectPhysical;
2683                                 } else {
2684                                         oconnect = Session::AutoConnectOption (0);
2685                                 } 
2686                                 
2687                                 uint32_t nphysin = (uint32_t) m_new_session_dialog->input_limit_count();
2688                                 uint32_t nphysout = (uint32_t) m_new_session_dialog->output_limit_count();
2689                                 
2690                                 build_session (session_path,
2691                                                session_name,
2692                                                cchns,
2693                                                mchns,
2694                                                iconnect,
2695                                                oconnect,
2696                                                nphysin,
2697                                                nphysout, 
2698                                                engine->frame_rate() * 60 * 5);
2699                         }               
2700                 }
2701
2702         } while(response == Gtk::RESPONSE_HELP);
2703         m_new_session_dialog->hide_all();
2704 }
2705
2706 int
2707 ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
2708 {
2709         Session *new_session;
2710         int x;
2711         session_loaded = false;
2712         x = unload_session ();
2713
2714         if (x < 0) {
2715                 return -1;
2716         } else if (x > 0) {
2717                 return 0;
2718         }
2719
2720         /* if it already exists, we must have write access */
2721
2722         if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
2723                 ArdourMessage msg (editor, X_("noaccess dialog"), _("\
2724 You do not have write access to this session.\n\
2725 This prevents the session from being loaded."));
2726                 return -1;
2727         }
2728
2729         try {
2730                 new_session = new Session (*engine, path, snap_name, mix_template);
2731         }
2732
2733         catch (...) {
2734
2735                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2736                 return -1;
2737         }
2738
2739         connect_to_session (new_session);
2740
2741         //if (engine->running()) {
2742         //mixer->show_window();
2743         //}
2744         session_loaded = true;
2745         return 0;
2746 }
2747
2748 int
2749 ARDOUR_UI::make_session_clean ()
2750 {
2751         if (session) {
2752                 session->set_clean ();
2753         }
2754
2755         return FALSE;
2756 }
2757
2758 int
2759 ARDOUR_UI::build_session (const string & path, const string & snap_name, 
2760                           uint32_t control_channels,
2761                           uint32_t master_channels, 
2762                           Session::AutoConnectOption input_connect,
2763                           Session::AutoConnectOption output_connect,
2764                           uint32_t nphysin,
2765                           uint32_t nphysout,
2766                           jack_nframes_t initial_length)
2767 {
2768         Session *new_session;
2769         int x;
2770
2771         session_loaded = false;
2772         x = unload_session ();
2773         if (x < 0) {
2774                 return -1;
2775         } else if (x > 0) {
2776                 return 0;
2777         }
2778         
2779         _session_is_new = true;
2780
2781         try {
2782                 new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
2783                                            control_channels, master_channels, nphysin, nphysout, initial_length);
2784         }
2785
2786         catch (...) {
2787
2788                 error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
2789                 return -1;
2790         }
2791
2792         connect_to_session (new_session);
2793
2794         //if (engine->running()) {
2795         //mixer->show_window();
2796         //}
2797         session_loaded = true;
2798         return 0;
2799 }
2800
2801 void
2802 ARDOUR_UI::show ()
2803 {
2804         if (editor) {
2805                 editor->show_window ();
2806                 shown_flag = true;
2807         }
2808
2809         if (session && mixer) {
2810                 // mixer->show_window ();
2811         }
2812         
2813         if (about) {
2814                 about->present ();
2815         }
2816 }
2817
2818 void
2819 ARDOUR_UI::show_splash ()
2820 {
2821         if (about == 0) {
2822                 about = new About();
2823         }
2824         about->present();
2825 }
2826
2827 void
2828 ARDOUR_UI::hide_splash ()
2829 {
2830         if (about) {
2831                 // about->hide();
2832         }
2833 }
2834
2835 void
2836 ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, const string & msg)
2837 {
2838         size_t removed;
2839
2840         removed = rep.paths.size();
2841
2842         if (removed == 0) {
2843                 ArdourMessage msg (editor, X_("cleanupresults"),
2844                                    _("\
2845 No audio files were ready for cleanup\n\n\
2846 If this seems suprising, check for any existing\n\
2847 snapshots. These may still include regions that\n\
2848 require some unused files to continue to exist."));
2849                 return;
2850         } 
2851
2852         ArdourDialog results (_("ardour: cleanup"), true);
2853         
2854         struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
2855             CleanupResultsModelColumns() { 
2856                     add (visible_name);
2857                     add (fullpath);
2858             }
2859             Gtk::TreeModelColumn<Glib::ustring> visible_name;
2860             Gtk::TreeModelColumn<Glib::ustring> fullpath;
2861         };
2862
2863         
2864         Glib::RefPtr<Gtk::ListStore> results_model;
2865         CleanupResultsModelColumns results_columns;
2866         Gtk::TreeView results_display;
2867         
2868         results_model = ListStore::create (results_columns);
2869         results_display.set_model (results_model);
2870         results_display.append_column (list_title, results_columns.visible_name);
2871         results_display.set_headers_visible (true);
2872
2873         Gtk::ScrolledWindow list_scroller;
2874         Gtk::Label txt;
2875
2876         if (rep.space < 1048576.0f) {
2877                 if (removed > 1) {
2878                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
2879                 } else {
2880                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
2881                 }
2882         } else {
2883                 if (removed > 1) {
2884                         txt.set_text (string_compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
2885                 } else {
2886                         txt.set_text (string_compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
2887                 }
2888         }
2889
2890         results.get_vbox()->pack_start (txt, false, false);
2891         
2892         for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
2893                 TreeModel::Row row = *(results_model->append());
2894                 row[results_columns.visible_name] = *i;
2895                 row[results_columns.fullpath] = *i;
2896         }
2897         
2898         list_scroller.add (results_display);
2899         list_scroller.set_size_request (-1, 250);
2900         list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
2901         
2902         results.get_vbox()->pack_start (list_scroller, true, true);
2903         results.add_button (Stock::OK, RESPONSE_ACCEPT);
2904         results.set_position (Gtk::WIN_POS_MOUSE);
2905
2906         results.run ();
2907 }
2908
2909 void
2910 ARDOUR_UI::cleanup ()
2911 {
2912         if (session == 0) {
2913                 /* shouldn't happen: menu item is insensitive */
2914                 return;
2915         }
2916
2917         ArdourDialog checker (_("ardour cleanup"));
2918         Gtk::Label label (_("\
2919 Cleanup is a destructive operation.\n\
2920 ALL undo/redo information will be lost if you cleanup.\n\
2921 Unused audio files will be moved to a \"dead sounds\" location."));
2922         
2923         checker.get_vbox()->pack_start (label, false, false);
2924         checker.add_button (Stock::OK, RESPONSE_ACCEPT);
2925         checker.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2926
2927         checker.set_name (_("CleanupDialog"));
2928         checker.set_wmclass (_("ardour_cleanup"), "Ardour");
2929         checker.set_position (Gtk::WIN_POS_MOUSE);
2930
2931         switch (checker.run()) {
2932         case RESPONSE_ACCEPT:
2933                 break;
2934         default:
2935                 return;
2936         }
2937
2938         Session::cleanup_report rep;
2939
2940         editor->prepare_for_cleanup ();
2941
2942         if (session->cleanup_sources (rep)) {
2943                 return;
2944         }
2945
2946         display_cleanup_results (rep, 
2947                                  _("cleaned files"),
2948                                  _("\
2949 The following %1 %2 were not in use.\n\
2950 The next time you flush the wastebasket\n\
2951 it will release an additional %3 %4bytes\n\
2952 of disk space"
2953                                          ));
2954 }
2955
2956 void
2957 ARDOUR_UI::flush_trash ()
2958 {
2959         if (session == 0) {
2960                 /* shouldn't happen: menu item is insensitive */
2961                 return;
2962         }
2963
2964         Session::cleanup_report rep;
2965
2966         if (session->cleanup_trash_sources (rep)) {
2967                 return;
2968         }
2969
2970         display_cleanup_results (rep, 
2971                                  _("deleted file"),
2972                                  _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
2973 }
2974
2975 void
2976 ARDOUR_UI::add_route ()
2977 {
2978         int count;
2979
2980         if (!session) {
2981                 return;
2982         }
2983
2984         if (add_route_dialog == 0) {
2985                 add_route_dialog = new AddRouteDialog;
2986                 editor->ensure_float (*add_route_dialog);
2987         }
2988
2989         if (add_route_dialog->is_visible()) {
2990                 /* we're already doing this */
2991                 return;
2992         }
2993
2994         ResponseType r = (ResponseType) add_route_dialog->run ();
2995         
2996         add_route_dialog->hide();
2997
2998         switch (r) {
2999         case RESPONSE_ACCEPT:
3000                 break;
3001         default:
3002                 return;
3003                 break;
3004         }
3005
3006         if ((count = add_route_dialog->count()) <= 0) {
3007                 return;
3008         }
3009
3010         uint32_t input_chan = add_route_dialog->channels ();
3011         uint32_t output_chan;
3012         string name_template = add_route_dialog->name_template ();
3013         bool track = add_route_dialog->track ();
3014
3015         Session::AutoConnectOption oac = session->get_output_auto_connect();
3016
3017         if (oac & Session::AutoConnectMaster) {
3018                 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
3019         } else {
3020                 output_chan = input_chan;
3021         }
3022
3023         /* XXX do something with name template */
3024
3025         while (count) {
3026                 if (track) {
3027                         session_add_audio_track (input_chan, output_chan);
3028                 } else {
3029                         session_add_audio_bus (input_chan, output_chan);
3030                 }
3031                 --count;
3032                 
3033                 while (Main::events_pending()) {
3034                         Main::iteration ();
3035                 }
3036         }
3037 }
3038
3039 XMLNode*
3040 ARDOUR_UI::mixer_settings () const
3041 {
3042         XMLNode* node = 0;
3043
3044         if (session) {
3045                 node = session->instant_xml(X_("Mixer"), session->path());
3046         } else {
3047                 node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
3048         }
3049
3050         if (!node) {
3051                 node = new XMLNode (X_("Mixer"));
3052         }
3053
3054         return node;
3055 }
3056
3057 XMLNode*
3058 ARDOUR_UI::editor_settings () const
3059 {
3060         XMLNode* node = 0;
3061
3062         if (session) {
3063                 node = session->instant_xml(X_("Editor"), session->path());
3064         } else {
3065                 node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
3066         }
3067
3068         if (!node) {
3069                 node = new XMLNode (X_("Editor"));
3070         }
3071         return node;
3072 }
3073
3074 XMLNode*
3075 ARDOUR_UI::keyboard_settings () const
3076 {
3077         XMLNode* node = 0;
3078
3079         node = Config->extra_xml(X_("Keyboard"));
3080         
3081         if (!node) {
3082                 node = new XMLNode (X_("Keyboard"));
3083         }
3084         return node;
3085 }
3086
3087 void
3088 ARDOUR_UI::halt_on_xrun_message ()
3089 {
3090         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::halt_on_xrun_message));
3091
3092         ArdourMessage msg (editor, X_("haltonxrun"),
3093                            _("Recording was stopped because your system could not keep up."));
3094 }
3095
3096 void 
3097 ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
3098 {
3099         ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
3100
3101         for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
3102                 delete *i;
3103         }
3104
3105         delete deletion_list;
3106 }
3107
3108 void
3109 ARDOUR_UI::disk_overrun_handler ()
3110 {
3111         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3112
3113         if (!have_disk_overrun_displayed) {
3114                 have_disk_overrun_displayed = true;
3115                 ArdourMessage msg (editor, X_("diskrate dialog"), _("\
3116 The disk system on your computer\n\
3117 was not able to keep up with Ardour.\n\
3118 \n\
3119 Specifically, it failed to write data to disk\n\
3120 quickly enough to keep up with recording.\n"));
3121                 have_disk_overrun_displayed = false;
3122         }
3123 }
3124
3125 void
3126 ARDOUR_UI::disk_underrun_handler ()
3127 {
3128         ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
3129
3130         if (!have_disk_underrun_displayed) {
3131                 have_disk_underrun_displayed = true;
3132                 ArdourMessage msg (editor, X_("diskrate2 dialog"),
3133                         (_("The disk system on your computer\n\
3134 was not able to keep up with Ardour.\n\
3135 \n\
3136 Specifically, it failed to read data from disk\n\
3137 quickly enough to keep up with playback.\n")));
3138                 have_disk_underrun_displayed = false;
3139         } 
3140 }
3141
3142 void
3143 ARDOUR_UI::disk_underrun_message_gone ()
3144 {
3145         have_disk_underrun_displayed = false;
3146 }
3147
3148 void
3149 ARDOUR_UI::disk_overrun_message_gone ()
3150 {
3151         have_disk_underrun_displayed = false;
3152 }
3153
3154 int
3155 ARDOUR_UI::pending_state_dialog ()
3156 {
3157         ArdourDialog dialog ("pending state dialog");
3158         Label  message (_("\
3159 This session appears to have been in\n\
3160 middle of recording when ardour or\n\
3161 the computer was shutdown.\n\
3162 \n\
3163 Ardour can recover any captured audio for\n\
3164 you, or it can ignore it. Please decide\n\
3165 what you would like to do.\n"));
3166
3167         dialog.get_vbox()->pack_start (message);
3168         dialog.add_button (_("Recover from crash"), RESPONSE_ACCEPT);
3169         dialog.add_button (_("Ignore crash data"), RESPONSE_REJECT);
3170
3171         dialog.set_position (WIN_POS_CENTER);
3172         dialog.show_all ();
3173         
3174         switch (dialog.run ()) {
3175         case RESPONSE_ACCEPT:
3176                 break;
3177         default:
3178                 return 1;
3179         }
3180
3181         return 0;
3182 }
3183         
3184         
3185 void
3186 ARDOUR_UI::disconnect_from_jack ()
3187 {
3188         if (engine) {
3189                 if( engine->disconnect_from_jack ()) {
3190                         ArdourMessage msg (editor, X_("nojack dialog"),
3191                                            _("Could not disconnect from JACK"));
3192                 }
3193
3194                 update_sample_rate (0);
3195         }
3196 }
3197
3198 void
3199 ARDOUR_UI::reconnect_to_jack ()
3200 {
3201         if (engine) {
3202                 if (engine->reconnect_to_jack ()) {
3203                         ArdourMessage msg (editor, X_("nojack dialog"),
3204                                            _("Could not reconnect to JACK"));
3205                 }
3206
3207                 update_sample_rate (0);
3208         }
3209 }
3210
3211 void
3212 ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
3213 {
3214         engine->request_buffer_size (nframes);
3215         update_sample_rate (0);
3216 }
3217
3218 int
3219 ARDOUR_UI::cmdline_new_session (string path)
3220 {
3221         if (path[0] != '/') {
3222                 char buf[PATH_MAX+1];
3223                 string str;
3224
3225                 getcwd (buf, sizeof (buf));
3226                 str = buf;
3227                 str += '/';
3228                 str += path;
3229                 path = str;
3230         }
3231
3232         new_session (false, path);
3233
3234         _will_create_new_session_automatically = false; /* done it */
3235         return FALSE; /* don't call it again */
3236 }