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