add missing GPL information in guicast program files
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / mwindowgui.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "androidcontrol.h"
23 #include "awindowgui.h"
24 #include "awindow.h"
25 #include "bcdisplayinfo.h"
26 #include "bchash.h"
27 #include "bcsignals.h"
28 #include "clip.h"
29 #include "cwindowgui.h"
30 #include "cwindow.h"
31 #include "channelinfo.h"
32 #include "dbwindow.h"
33 #include "edit.h"
34 #include "editpopup.h"
35 #include "edits.h"
36 #include "edl.h"
37 #include "edlsession.h"
38 #include "filesystem.h"
39 #include "filexml.h"
40 #include "keyframepopup.h"
41 #include "keys.h"
42 #include "language.h"
43 #include "localsession.h"
44 #include "mainclock.h"
45 #include "maincursor.h"
46 #include "mainmenu.h"
47 #include "mainsession.h"
48 #include "mainundo.h"
49 #include "mbuttons.h"
50 #include "mtimebar.h"
51 #include "mwindowgui.h"
52 #include "mwindow.h"
53 #include "panedividers.h"
54 #include "patchbay.h"
55 #include "plugin.h"
56 #include "pluginpopup.h"
57 #include "pluginset.h"
58 #include "preferences.h"
59 #include "proxy.h"
60 #include "record.h"
61 #include "recordgui.h"
62 #include "renderengine.h"
63 #include "remotecontrol.h"
64 #include "resourcethread.h"
65 #include "samplescroll.h"
66 #include "shbtnprefs.h"
67 #include "statusbar.h"
68 #include "swindow.h"
69 #include "theme.h"
70 #include "trackcanvas.h"
71 #include "trackpopup.h"
72 #include "trackscroll.h"
73 #include "tracks.h"
74 #include "transitionpopup.h"
75 #include "vwindowgui.h"
76 #include "vwindow.h"
77 #include "wintv.h"
78 #include "x10tv.h"
79 #include "zoombar.h"
80
81 #define PANE_DRAG_MARGIN MAX(mwindow->theme->pane_w, mwindow->theme->pane_h)
82
83
84 // the main window uses its own private colormap for video
85 MWindowGUI::MWindowGUI(MWindow *mwindow)
86  : BC_Window(_(PROGRAM_NAME ": Program"),
87                 mwindow->session->mwindow_x, mwindow->session->mwindow_y,
88                 mwindow->session->mwindow_w, mwindow->session->mwindow_h,
89                 xS(100), yS(100), 1, 1, 1)
90 {
91         this->mwindow = mwindow;
92 //      samplescroll = 0;
93 //      trackscroll = 0;
94 //      cursor = 0;
95 //      patchbay = 0;
96 //      timebar = 0;
97 //      canvas = 0;
98         focused_pane = TOP_LEFT_PANE;
99         x_divider = 0;
100         y_divider = 0;
101         x_pane_drag = 0;
102         y_pane_drag = 0;
103         dragging_pane = 0;
104         drag_popup = 0;
105
106         render_engine = 0;
107         render_engine_id = -1;
108         for(int i = 0; i < TOTAL_PANES; i++)
109                 pane[i] = 0;
110
111         record = 0;
112         channel_info = 0;
113         swindow = 0;
114         db_window = 0;
115 // subwindows
116         mbuttons = 0;
117         statusbar = 0;
118         zoombar = 0;
119         mainclock = 0;
120         track_menu = 0;
121         edit_menu = 0;
122         plugin_menu = 0;
123         keyframe_menu = 0;
124         keyframe_hide = 0;
125         keyvalue_popup = 0;
126         transition_menu = 0;
127         remote_control = 0;
128         cwindow_remote_handler = 0;
129         record_remote_handler = 0;
130         android_control = 0;
131 // *** CONTEXT_HELP ***
132         context_help_set_keyword("Program Window");
133 }
134
135
136 MWindowGUI::~MWindowGUI()
137 {
138         delete android_control;
139         delete cwindow_remote_handler;
140         delete record_remote_handler;
141         delete remote_control;
142         delete keyvalue_popup;
143 //      delete samplescroll;
144 //      delete trackscroll;
145         for(int i = 0; i < TOTAL_PANES; i++)
146                 if(pane[i]) delete pane[i];
147 //      delete cursor;
148         delete render_engine;
149         delete resource_thread;
150         resource_pixmaps.remove_all_objects();
151         delete swindow;
152 #ifdef HAVE_DVB
153         delete channel_info;
154 #endif
155         delete db_window;
156         delete x_divider;
157         delete y_divider;
158 }
159
160 void MWindowGUI::create_objects()
161 {
162         lock_window("MWindowGUI::create_objects");
163         const int debug = 0;
164
165         resource_thread = new ResourceThread(mwindow);
166         resource_thread->create_objects();
167
168
169         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
170         set_icon(mwindow->theme->get_image("mwindow_icon"));
171         remote_control = new RemoteControl(this);
172         cwindow_remote_handler = 0;
173         record_remote_handler = 0;
174 #ifdef HAVE_X10TV
175 // should be first, use if plugged
176         if( !cwindow_remote_handler && mwindow->x10tv ) {
177                 cwindow_remote_handler = (RemoteHandler*)
178                         new X10TVCWindowHandler(mwindow->x10tv, remote_control);
179                 record_remote_handler = (RemoteHandler*)
180                         new X10TVRecordHandler(mwindow->x10tv, remote_control);
181         }
182 #endif
183 #ifdef HAVE_WINTV
184         if( !cwindow_remote_handler && mwindow->wintv ) {
185                 cwindow_remote_handler = (RemoteHandler*)
186                         new WinTVCWindowHandler(mwindow->wintv, remote_control);
187                 record_remote_handler = (RemoteHandler*)
188                         new WinTVRecordHandler(mwindow->wintv, remote_control);
189         }
190 #endif
191         mwindow->reset_android_remote();
192         if( !cwindow_remote_handler )
193                 cwindow_remote_handler = (RemoteHandler*)
194                         new CWindowKeyEvHandler(mwindow->gui->remote_control);
195         if( !record_remote_handler )
196                 record_remote_handler = (RemoteHandler*)
197                         new RecordKeyEvHandler(mwindow->gui->remote_control);
198         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
199
200         int x1 = get_w() - MainShBtns::calculate_w(-1, 0, -1) - xS(5);
201         add_subwindow(mainshbtns = new MainShBtns(mwindow, x1, -1));
202         mainshbtns->load(mwindow->preferences);
203         int x2 = x1 - mwindow->theme->stack_button_w - xS(5);
204         add_subwindow(stack_button = new StackButton(mwindow, x2, yS(2)));
205         add_subwindow(mainmenu = new MainMenu(mwindow, this, x2));
206         mainmenu->create_objects();
207         mwindow->theme->get_mwindow_sizes(this, get_w(), get_h());
208         mwindow->theme->draw_mwindow_bg(this);
209         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
210
211         add_subwindow(mbuttons = new MButtons(mwindow, this));
212         mbuttons->create_objects();
213         int y1 = mbuttons->get_y()+yS(2);
214         add_subwindow(proxy_toggle = new ProxyToggle(mwindow, mbuttons, x2, y1));
215         add_subwindow(ffmpeg_toggle = new FFMpegToggle(mwindow, mbuttons, x1, y1));
216
217         pane[TOP_LEFT_PANE] = new TimelinePane(mwindow,
218                 TOP_LEFT_PANE,
219                 mwindow->theme->mcanvas_x,
220                 mwindow->theme->mcanvas_y,
221                 mwindow->theme->mcanvas_w,
222                 mwindow->theme->mcanvas_h);
223         pane[TOP_LEFT_PANE]->create_objects();
224
225         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
226         add_subwindow(zoombar = new ZoomBar(mwindow, this));
227         zoombar->create_objects();
228
229
230         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
231         add_subwindow(statusbar = new StatusBar(mwindow, this));
232         statusbar->create_objects();
233
234
235
236         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
237         add_subwindow(mainclock = new MainClock(mwindow,
238                 mwindow->theme->mclock_x, mwindow->theme->mclock_y,
239                 mwindow->theme->mclock_w));
240         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
241         mainclock->update(0);
242
243
244
245 //      if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
246 //      cursor = new MainCursor(mwindow, this);
247 //      cursor->create_objects();
248
249
250         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
251         add_subwindow(track_menu = new TrackPopup(mwindow, this));
252         track_menu->create_objects();
253         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
254         add_subwindow(edit_menu = new EditPopup(mwindow, this));
255         edit_menu->create_objects();
256
257
258         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
259         add_subwindow(plugin_menu = new PluginPopup(mwindow, this));
260         plugin_menu->create_objects();
261
262
263         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
264         add_subwindow(keyframe_menu = new KeyframePopup(mwindow, this));
265         keyframe_menu->create_objects();
266         add_subwindow(keyframe_hide = new KeyframeHidePopup(mwindow, this));
267         keyframe_hide->create_objects();
268
269
270         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
271         add_subwindow(transition_menu = new TransitionPopup(mwindow, this));
272         transition_menu->create_objects();
273
274 #ifdef HAVE_DVB
275         channel_info = new ChannelInfo(mwindow);
276 #endif
277 #ifdef HAVE_COMMERCIAL
278         db_window = new DbWindow(mwindow);
279 #endif
280         swindow = new SWindow(mwindow);
281
282         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
283
284         add_subwindow(pane_button = new PaneButton(mwindow,
285                 get_w() - mwindow->theme->get_image_set("pane")[0]->get_w(),
286                 mwindow->theme->mzoom_y + 1 - mwindow->theme->get_image_set("pane")[0]->get_h()));
287
288         pane[TOP_LEFT_PANE]->canvas->activate();
289
290         if(debug) printf("MWindowGUI::create_objects %d\n", __LINE__);
291         unlock_window();
292 }
293
294 void MWindowGUI::redraw_time_dependancies()
295 {
296         zoombar->redraw_time_dependancies();
297         for(int i = 0; i < TOTAL_PANES; i++)
298                 if(pane[i] && pane[i]->timebar) pane[i]->timebar->update(0);
299         mainclock->update(mwindow->edl->local_session->get_selectionstart(1));
300 }
301
302 int MWindowGUI::focus_in_event()
303 {
304         for(int i = 0; i < TOTAL_PANES; i++)
305                 if(pane[i] && pane[i]->cursor) pane[i]->cursor->focus_in_event();
306         return 1;
307 }
308
309 int MWindowGUI::focus_out_event()
310 {
311         for(int i = 0; i < TOTAL_PANES; i++)
312                 if(pane[i] && pane[i]->cursor) pane[i]->cursor->focus_out_event();
313         return 1;
314 }
315
316
317 int MWindowGUI::resize_event(int w, int h)
318 {
319 //printf("MWindowGUI::resize_event %d\n", __LINE__);
320         mwindow->session->mwindow_w = w;
321         mwindow->session->mwindow_h = h;
322         int x1 = w - MainShBtns::calculate_w(-1, 0, -1) - xS(5);
323         mainshbtns->reposition_window(x1, -1);
324         int x2 = x1 - mwindow->theme->stack_button_w - xS(5);
325         stack_button->reposition_window(x2, stack_button->get_y());
326         mainmenu->resize_event(x2, mainmenu->get_h());
327         mwindow->theme->get_mwindow_sizes(this, w, h);
328         mwindow->theme->draw_mwindow_bg(this);
329         mbuttons->resize_event();
330         int y1 = mbuttons->get_y()+yS(2);
331         proxy_toggle->reposition_window(x2, y1);
332         ffmpeg_toggle->reposition_window(x1, y1);
333         statusbar->resize_event();
334         zoombar->resize_event();
335
336         resource_thread->stop_draw(1);
337
338         if(total_panes() > 1)
339         {
340                 if(horizontal_panes())
341                 {
342 //                      printf("MWindowGUI::resize_event %d %d %d\n",
343 //                              __LINE__,
344 //                              pane[TOP_RIGHT_PANE]->x,
345 //                              mwindow->theme->mcanvas_w -
346 //                                      BC_ScrollBar::get_span(SCROLL_VERT) -
347 //                                      PANE_DRAG_MARGIN);
348                         if(pane[TOP_RIGHT_PANE]->x >= mwindow->theme->mcanvas_w -
349                                 BC_ScrollBar::get_span(SCROLL_VERT) -
350                                 PANE_DRAG_MARGIN)
351                         {
352                                 delete_x_pane(pane[TOP_RIGHT_PANE]->x);
353                                 mwindow->edl->local_session->x_pane = -1;
354                         }
355                 }
356                 else
357                 if(vertical_panes())
358                 {
359                         if(pane[BOTTOM_LEFT_PANE]->y >= mwindow->theme->mzoom_y -
360                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
361                                 PANE_DRAG_MARGIN)
362                         {
363                                 delete_y_pane(pane[BOTTOM_LEFT_PANE]->y);
364                                 mwindow->edl->local_session->y_pane = -1;
365                         }
366                 }
367                 else
368                 {
369                         if(pane[TOP_RIGHT_PANE]->x >= mwindow->theme->mcanvas_w -
370                                         BC_ScrollBar::get_span(SCROLL_VERT) -
371                                         PANE_DRAG_MARGIN)
372                         {
373                                 delete_x_pane(pane[TOP_RIGHT_PANE]->x);
374                                 mwindow->edl->local_session->x_pane = -1;
375                         }
376
377                         if(pane[BOTTOM_LEFT_PANE]->y >= mwindow->theme->mzoom_y -
378                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
379                                 PANE_DRAG_MARGIN)
380                         {
381                                 delete_y_pane(pane[BOTTOM_LEFT_PANE]->y);
382                                 mwindow->edl->local_session->y_pane = -1;
383                         }
384                 }
385         }
386
387         if(total_panes() == 1)
388         {
389                 pane[TOP_LEFT_PANE]->resize_event(
390                         mwindow->theme->mcanvas_x,
391                         mwindow->theme->mcanvas_y,
392                         mwindow->theme->mcanvas_w,
393                         mwindow->theme->mcanvas_h);
394         }
395         else
396         if(horizontal_panes())
397         {
398                 pane[TOP_LEFT_PANE]->resize_event(
399                         pane[TOP_LEFT_PANE]->x,
400                         pane[TOP_LEFT_PANE]->y,
401                         pane[TOP_LEFT_PANE]->w,
402                         mwindow->theme->mcanvas_h);
403                 pane[TOP_RIGHT_PANE]->resize_event(
404                         pane[TOP_RIGHT_PANE]->x,
405                         pane[TOP_RIGHT_PANE]->y,
406                         mwindow->theme->mcanvas_w - pane[TOP_RIGHT_PANE]->x,
407                         mwindow->theme->mcanvas_h);
408         }
409         else
410         if(vertical_panes())
411         {
412                 pane[TOP_LEFT_PANE]->resize_event(
413                         pane[TOP_LEFT_PANE]->x,
414                         pane[TOP_LEFT_PANE]->y,
415                         mwindow->theme->mcanvas_w,
416                         pane[TOP_LEFT_PANE]->h);
417                 pane[BOTTOM_LEFT_PANE]->resize_event(
418                         pane[BOTTOM_LEFT_PANE]->x,
419                         pane[BOTTOM_LEFT_PANE]->y,
420                         mwindow->theme->mcanvas_w,
421                         mwindow->theme->mcanvas_y +
422                                 mwindow->theme->mcanvas_h -
423                                 pane[BOTTOM_LEFT_PANE]->y);
424         }
425         else
426         {
427                 pane[TOP_LEFT_PANE]->resize_event(
428                         pane[TOP_LEFT_PANE]->x,
429                         pane[TOP_LEFT_PANE]->y,
430                         pane[TOP_LEFT_PANE]->w,
431                         pane[TOP_LEFT_PANE]->h);
432                 pane[TOP_RIGHT_PANE]->resize_event(
433                         pane[TOP_RIGHT_PANE]->x,
434                         pane[TOP_RIGHT_PANE]->y,
435                         mwindow->theme->mcanvas_w - pane[TOP_RIGHT_PANE]->x,
436                         pane[TOP_RIGHT_PANE]->h);
437                 pane[BOTTOM_LEFT_PANE]->resize_event(
438                         pane[BOTTOM_LEFT_PANE]->x,
439                         pane[BOTTOM_LEFT_PANE]->y,
440                         pane[BOTTOM_LEFT_PANE]->w,
441                         mwindow->theme->mcanvas_y +
442                                 mwindow->theme->mcanvas_h -
443                                 pane[BOTTOM_LEFT_PANE]->y);
444                 pane[BOTTOM_RIGHT_PANE]->resize_event(
445                         pane[BOTTOM_RIGHT_PANE]->x,
446                         pane[BOTTOM_RIGHT_PANE]->y,
447                         mwindow->theme->mcanvas_w -
448                                 pane[BOTTOM_RIGHT_PANE]->x,
449                         mwindow->theme->mcanvas_y +
450                                 mwindow->theme->mcanvas_h -
451                                 pane[BOTTOM_RIGHT_PANE]->y);
452         }
453
454         update_pane_dividers();
455         pane_button->reposition_window(w - mwindow->theme->get_image_set("pane")[0]->get_w(),
456                 mwindow->theme->mzoom_y + 1 - mwindow->theme->get_image_set("pane")[0]->get_h());
457         resource_thread->start_draw();
458
459         flash(1);
460         return 0;
461 }
462
463 int MWindowGUI::total_panes()
464 {
465         int total = 0;
466         for(int i = 0; i < TOTAL_PANES; i++)
467                 if(pane[i]) total++;
468         return total;
469 }
470
471 int MWindowGUI::vertical_panes()
472 {
473         return total_panes() == 2 &&
474                 pane[TOP_LEFT_PANE] &&
475                 pane[BOTTOM_LEFT_PANE];
476 }
477
478 int MWindowGUI::horizontal_panes()
479 {
480         return total_panes() == 2 &&
481                 pane[TOP_LEFT_PANE] &&
482                 pane[TOP_RIGHT_PANE];
483 }
484
485 TimelinePane* MWindowGUI::get_focused_pane()
486 {
487         if(pane[focused_pane]) return pane[focused_pane];
488         for(int i = 0; i < TOTAL_PANES; i++)
489         {
490                 if(pane[i]) return pane[i];
491         }
492         return 0;
493 }
494
495 void MWindowGUI::activate_timeline()
496 {
497         if(pane[focused_pane])
498         {
499                 pane[focused_pane]->activate();
500         }
501         else
502         {
503                 for(int i = 0; i < TOTAL_PANES; i++)
504                 {
505                         if(pane[i])
506                         {
507                                 pane[i]->activate();
508                                 return;
509                         }
510                 }
511         }
512 }
513
514 void MWindowGUI::deactivate_timeline()
515 {
516         for(int i = 0; i < TOTAL_PANES; i++)
517         {
518                 if(pane[i] && pane[i]->canvas)
519                 {
520                         pane[i]->canvas->deactivate();
521                 }
522         }
523 }
524
525 void MWindowGUI::update_title(char *path)
526 {
527         FileSystem fs;
528         char filename[BCTEXTLEN], string[BCTEXTLEN];
529         fs.extract_name(filename, path);
530         sprintf(string, _(PROGRAM_NAME ": %s"), filename);
531         set_title(string);
532 //printf("MWindowGUI::update_title %s\n", string);
533         flush();
534 }
535
536 void MWindowGUI::draw_overlays(int flash_it)
537 {
538         for(int i = 0; i < TOTAL_PANES; i++)
539         {
540                 if(pane[i] && pane[i]->canvas)
541                 {
542                         pane[i]->canvas->draw_overlays();
543                         if(flash_it) pane[i]->canvas->flash();
544                 }
545         }
546 }
547
548 void MWindowGUI::update_timebar(int flush_it)
549 {
550         for(int i = 0; i < TOTAL_PANES; i++)
551         {
552                 if(pane[i] && pane[i]->timebar)
553                 {
554                         pane[i]->timebar->update(flush_it);
555                 }
556         }
557 }
558
559 void MWindowGUI::update_timebar_highlights()
560 {
561         for(int i = 0; i < TOTAL_PANES; i++)
562         {
563                 if(pane[i] && pane[i]->timebar)
564                 {
565                         pane[i]->timebar->update_highlights();
566                 }
567         }
568 }
569
570
571 void MWindowGUI::update_patchbay()
572 {
573         for(int i = 0; i < TOTAL_PANES; i++)
574         {
575                 if(pane[i] && pane[i]->patchbay)
576                 {
577                         pane[i]->patchbay->update();
578                 }
579         }
580 }
581
582 void MWindowGUI::update_proxy_toggle()
583 {
584         int value = mwindow->edl->session->proxy_state == PROXY_ACTIVE ? 0 : 1;
585         proxy_toggle->set_value(value);
586         if( mwindow->edl->session->proxy_state == PROXY_INACTIVE )
587                 proxy_toggle->hide();
588         else
589                 proxy_toggle->show();
590 }
591
592 void MWindowGUI::update_plugintoggles()
593 {
594         for(int i = 0; i < TOTAL_PANES; i++)
595         {
596                 if(pane[i] && pane[i]->canvas)
597                 {
598                         pane[i]->canvas->refresh_plugintoggles();
599                 }
600         }
601
602 }
603
604 void MWindowGUI::draw_indexes(Indexable *indexable)
605 {
606         for(int i = 0; i < TOTAL_PANES; i++)
607         {
608                 if(pane[i] && pane[i]->canvas)
609                 {
610                         pane[i]->canvas->draw_indexes(indexable);
611                 }
612         }
613 }
614
615 void MWindowGUI::draw_canvas(int redraw, int hide_cursor)
616 {
617         resource_thread->stop_draw(0);
618         int mode = NORMAL_DRAW;
619         if( redraw ) {
620                 mode = FORCE_REDRAW;
621                 resource_pixmaps.remove_all_objects();
622         }
623         for(int i = 0; i < TOTAL_PANES; i++) {
624                 if( pane[i] )
625                         pane[i]->canvas->draw(mode, hide_cursor);
626         }
627
628         resource_thread->start_draw();
629 }
630
631 void MWindowGUI::flash_canvas(int flush)
632 {
633         for(int i = 0; i < TOTAL_PANES; i++)
634         {
635                 if(pane[i] && pane[i]->canvas)
636                 {
637                         pane[i]->canvas->flash(flush);
638                 }
639         }
640 }
641
642 int MWindowGUI::show_window(int flush)
643 {
644         int ret = BC_WindowBase::show_window(flush);
645         stack_button->update();
646         update_proxy_toggle();
647         return ret;
648 }
649
650 void MWindowGUI::draw_cursor(int do_plugintoggles)
651 {
652         for(int i = 0; i < TOTAL_PANES; i++)
653         {
654                 if(pane[i] && pane[i]->cursor)
655                 {
656                         pane[i]->cursor->draw(do_plugintoggles);
657                 }
658         }
659 }
660
661 void MWindowGUI::show_cursor(int do_plugintoggles)
662 {
663         for(int i = 0; i < TOTAL_PANES; i++)
664         {
665                 if(pane[i] && pane[i]->cursor)
666                 {
667                         pane[i]->cursor->show(do_plugintoggles);
668                 }
669         }
670 }
671
672 void MWindowGUI::hide_cursor(int do_plugintoggles)
673 {
674         for(int i = 0; i < TOTAL_PANES; i++)
675         {
676                 if(pane[i] && pane[i]->cursor)
677                 {
678                         pane[i]->cursor->hide(do_plugintoggles);
679                 }
680         }
681 }
682
683 void MWindowGUI::update_cursor()
684 {
685         for(int i = 0; i < TOTAL_PANES; i++)
686         {
687                 if(pane[i] && pane[i]->cursor)
688                 {
689                         pane[i]->cursor->update();
690                 }
691         }
692 }
693
694 void MWindowGUI::set_playing_back(int value)
695 {
696         for(int i = 0; i < TOTAL_PANES; i++)
697         {
698                 if(pane[i] && pane[i]->cursor)
699                 {
700                         pane[i]->cursor->playing_back = value;
701                 }
702         }
703 }
704
705 void MWindowGUI::update_scrollbars(int flush)
706 {
707         for(int i = 0; i < TOTAL_PANES; i++)
708         {
709                 if(pane[i])
710                 {
711                         pane[i]->update(1, NO_DRAW, 0, 0);
712                 }
713         }
714         if(flush) this->flush();
715 }
716
717 void MWindowGUI::reset_meters()
718 {
719         for(int i = 0; i < TOTAL_PANES; i++)
720         {
721                 if(pane[i] && pane[i]->patchbay)
722                 {
723                         pane[i]->patchbay->reset_meters();
724                 }
725         }
726 }
727
728 void MWindowGUI::stop_meters()
729 {
730         for(int i = 0; i < TOTAL_PANES; i++)
731         {
732                 if(pane[i] && pane[i]->patchbay)
733                 {
734                         pane[i]->patchbay->stop_meters();
735                 }
736         }
737 }
738
739 void MWindowGUI::update_meters(ArrayList<double> *module_levels)
740 {
741         for(int i = 0; i < TOTAL_PANES; i++)
742         {
743                 if(pane[i] && pane[i]->patchbay)
744                 {
745                         pane[i]->patchbay->update_meters(module_levels);
746                 }
747         }
748 }
749
750 void MWindowGUI::set_editing_mode(int flush)
751 {
752         for(int i = 0; i < TOTAL_PANES; i++)
753         {
754                 if(pane[i] && pane[i]->canvas)
755                 {
756                         pane[i]->canvas->update_cursor(flush);
757                 }
758         }
759 }
760
761 void MWindowGUI::set_meter_format(int mode, int min, int max)
762 {
763         for(int i = 0; i < TOTAL_PANES; i++)
764         {
765                 if(pane[i] && pane[i]->patchbay)
766                 {
767                         pane[i]->patchbay->set_meter_format(mode, min, max);
768                 }
769         }
770 }
771
772 void MWindowGUI::update(int scrollbars,
773         int do_canvas,
774         int timebar,
775         int zoombar,
776         int patchbay,
777         int clock,
778         int buttonbar)
779 {
780         const int debug = 0;
781         if(debug) PRINT_TRACE
782
783
784
785         mwindow->edl->tracks->update_y_pixels(mwindow->theme);
786
787         if( do_canvas != NO_DRAW && do_canvas != IGNORE_THREAD )
788                 resource_thread->stop_draw(1);
789
790         if( do_canvas == FORCE_REDRAW )
791                 resource_pixmaps.remove_all_objects();
792
793         for(int i = 0; i < TOTAL_PANES; i++)
794         {
795                 if(pane[i]) pane[i]->update(scrollbars,
796                         do_canvas,
797                         timebar,
798                         patchbay);
799         }
800
801         if( do_canvas != NO_DRAW && do_canvas != IGNORE_THREAD )
802                 resource_thread->start_draw();
803
804 //      if(scrollbars) this->get_scrollbars(0);
805 //      if(timebar) this->timebar->update(0);
806         if(zoombar) this->zoombar->update();
807 //      if(patchbay) this->patchbay->update();
808         if(clock) this->mainclock->update(
809                 mwindow->edl->local_session->get_selectionstart(1));
810         if(debug) PRINT_TRACE
811
812
813
814 //      if(do_canvas)
815 //      {
816 //              this->canvas->draw(do_canvas);
817 //              this->cursor->show();
818 //              this->canvas->flash(0);
819 // Activate causes the menubar to deactivate.  Don't want this for
820 // picon thread.
821 //              if(canvas != IGNORE_THREAD) this->canvas->activate();
822 //      }
823         if(debug) PRINT_TRACE
824
825
826
827         if(buttonbar) mbuttons->update();
828         if(debug) PRINT_TRACE
829
830 // Can't age if the cache called this to draw missing picons
831 // or the GUI is updating the status of the draw toggle.
832         if( do_canvas != FORCE_REDRAW && do_canvas != IGNORE_THREAD ) {
833                 unlock_window();
834                 mwindow->age_caches();
835                 lock_window("MWindowGUI::update");
836         }
837
838         flush();
839         if(debug) PRINT_TRACE
840 }
841
842 int MWindowGUI::visible(int64_t x1, int64_t x2, int64_t view_x1, int64_t view_x2)
843 {
844         return (x1 >= view_x1 && x1 < view_x2) ||
845                 (x2 > view_x1 && x2 <= view_x2) ||
846                 (x1 <= view_x1 && x2 >= view_x2);
847 }
848
849
850 void MWindowGUI::show_message(const char *message, int msg_color, int bar_color)
851 {
852         statusbar->show_message(message, msg_color, bar_color);
853 }
854
855 void MWindowGUI::update_default_message()
856 {
857         statusbar->update_default_message();
858 }
859
860 void MWindowGUI::reset_default_message()
861 {
862         statusbar->reset_default_message();
863 }
864
865 void MWindowGUI::default_message()
866 {
867         statusbar->default_message();
868 }
869
870 // Drag motion called from other window
871 int MWindowGUI::drag_motion()
872 {
873         if(get_hidden()) return 0;
874
875         Track *over_track = 0;
876         Edit *over_edit = 0;
877         PluginSet *over_pluginset = 0;
878         Plugin *over_plugin = 0;
879         int redraw = 0;
880
881         if(drag_popup)
882         {
883                 drag_popup->cursor_motion_event();
884         }
885
886
887 // there's no point in drawing highlights has until drag operation has been set
888         if (!mwindow->session->current_operation)
889                 return 0;
890
891         for(int i = 0; i < TOTAL_PANES; i++)
892         {
893                 if(pane[i] && pane[i]->canvas)
894                         pane[i]->canvas->drag_motion(&over_track, &over_edit,
895                                         &over_pluginset, &over_plugin);
896         }
897
898         if(mwindow->session->track_highlighted != over_track)
899         {
900                 mwindow->session->track_highlighted = over_track;
901                 redraw = 1;
902         }
903
904         if(mwindow->session->edit_highlighted != over_edit)
905         {
906                 mwindow->session->edit_highlighted = over_edit;
907                 redraw = 1;
908         }
909
910         if(mwindow->session->pluginset_highlighted != over_pluginset)
911         {
912                 mwindow->session->pluginset_highlighted = over_pluginset;
913                 redraw = 1;
914         }
915
916         if(mwindow->session->plugin_highlighted != over_plugin)
917         {
918                 mwindow->session->plugin_highlighted = over_plugin;
919                 redraw = 1;
920         }
921
922         if( mwindow->session->current_operation == DRAG_ASSET ||
923             mwindow->session->current_operation == DRAG_EDIT ||
924             mwindow->session->current_operation == DRAG_GROUP ||
925             mwindow->session->current_operation == DRAG_AEFFECT_COPY ||
926             mwindow->session->current_operation == DRAG_VEFFECT_COPY ) {
927                 redraw = 1;
928         }
929
930
931 // printf("drag_motion %d %d over_track=%p over_edit=%p\n",
932 // __LINE__,
933 // redraw,
934 // over_track,
935 // over_edit);
936         if(redraw)
937         {
938                 lock_window("MWindowGUI::drag_motion");
939                 draw_overlays(1);
940                 unlock_window();
941         }
942         return 0;
943 }
944
945 int MWindowGUI::drag_stop()
946 {
947         if(get_hidden()) return 0;
948         int result = 0, redraw = 0;
949
950         for(int i = 0; i < TOTAL_PANES; i++)
951         {
952                 if(pane[i] && pane[i]->canvas)
953                         result |= pane[i]->canvas->drag_stop(&redraw);
954         }
955         mwindow->edl->optimize();
956
957 // since we don't have subwindows we have to terminate any drag operation
958         if(result)
959         {
960                 if (mwindow->session->track_highlighted
961                         || mwindow->session->edit_highlighted
962                         || mwindow->session->plugin_highlighted
963                         || mwindow->session->pluginset_highlighted)
964                         redraw = 1;
965                 mwindow->session->track_highlighted = 0;
966                 mwindow->session->edit_highlighted = 0;
967                 mwindow->session->plugin_highlighted = 0;
968                 mwindow->session->pluginset_highlighted = 0;
969                 mwindow->session->current_operation = NO_OPERATION;
970         }
971
972
973 //printf("MWindowGUI::drag_stop %d %d\n", redraw, mwindow->session->current_operation);
974         if(redraw)
975         {
976                 mwindow->edl->tracks->update_y_pixels(mwindow->theme);
977                 update_scrollbars(0);
978                 update_patchbay();
979                 draw_canvas(1, 1);
980                 update_cursor();
981                 flash_canvas(1);
982         }
983
984         if(drag_popup)
985         {
986                 delete drag_popup;
987                 drag_popup = 0;
988         }
989         return result;
990 }
991
992 void MWindowGUI::default_positions()
993 {
994 //printf("MWindowGUI::default_positions 1\n");
995         VWindow *vwindow = mwindow->vwindows.size() > DEFAULT_VWINDOW ?
996                 mwindow->vwindows.get(DEFAULT_VWINDOW) : 0;
997         if( vwindow && !vwindow->is_running() ) vwindow = 0;
998         if( vwindow ) vwindow->gui->lock_window("MWindowGUI::default_positions");
999         mwindow->cwindow->gui->lock_window("MWindowGUI::default_positions");
1000         mwindow->awindow->gui->lock_window("MWindowGUI::default_positions");
1001
1002 // printf("MWindowGUI::default_positions 1 %d %d %d %d\n", mwindow->session->vwindow_x,
1003 // mwindow->session->vwindow_y,
1004 // mwindow->session->vwindow_w,
1005 // mwindow->session->vwindow_h);
1006         reposition_window(mwindow->session->mwindow_x,
1007                 mwindow->session->mwindow_y,
1008                 mwindow->session->mwindow_w,
1009                 mwindow->session->mwindow_h);
1010         if( vwindow ) vwindow->gui->reposition_window(mwindow->session->vwindow_x,
1011                 mwindow->session->vwindow_y,
1012                 mwindow->session->vwindow_w,
1013                 mwindow->session->vwindow_h);
1014         mwindow->cwindow->gui->reposition_window(mwindow->session->cwindow_x,
1015                 mwindow->session->cwindow_y,
1016                 mwindow->session->cwindow_w,
1017                 mwindow->session->cwindow_h);
1018         mwindow->awindow->gui->reposition_window(mwindow->session->awindow_x,
1019                 mwindow->session->awindow_y,
1020                 mwindow->session->awindow_w,
1021                 mwindow->session->awindow_h);
1022 //printf("MWindowGUI::default_positions 1\n");
1023
1024         resize_event(mwindow->session->mwindow_w,
1025                 mwindow->session->mwindow_h);
1026 //printf("MWindowGUI::default_positions 1\n");
1027         if( vwindow ) vwindow->gui->resize_event(mwindow->session->vwindow_w,
1028                 mwindow->session->vwindow_h);
1029 //printf("MWindowGUI::default_positions 1\n");
1030         mwindow->cwindow->gui->resize_event(mwindow->session->cwindow_w,
1031                 mwindow->session->cwindow_h);
1032 //printf("MWindowGUI::default_positions 1\n");
1033         mwindow->awindow->gui->resize_event(mwindow->session->awindow_w,
1034                 mwindow->session->awindow_h);
1035
1036 //printf("MWindowGUI::default_positions 1\n");
1037
1038         flush();
1039         if( vwindow ) vwindow->gui->flush();
1040         mwindow->cwindow->gui->flush();
1041         mwindow->awindow->gui->flush();
1042
1043         if( vwindow ) vwindow->gui->unlock_window();
1044         mwindow->cwindow->gui->unlock_window();
1045         mwindow->awindow->gui->unlock_window();
1046 //printf("MWindowGUI::default_positions 2\n");
1047         mwindow->tile_mixers();
1048 }
1049
1050
1051 int MWindowGUI::repeat_event(int64_t duration)
1052 {
1053 // if(duration == 100)
1054 // mwindow->sync_parameters(CHANGE_ALL);
1055         int result = 0;
1056         for(int i = 0; i < TOTAL_PANES; i++)
1057         {
1058                 if(pane[i] && pane[i]->cursor)
1059                         result = pane[i]->cursor->repeat_event(duration);
1060         }
1061         return result;
1062 }
1063
1064
1065 int MWindowGUI::translation_event()
1066 {
1067 //printf("MWindowGUI::translation_event 1 %d %d\n", get_x(), get_y());
1068         mwindow->session->mwindow_x = get_x();
1069         mwindow->session->mwindow_y = get_y();
1070         return 0;
1071 }
1072
1073
1074 int MWindowGUI::save_defaults(BC_Hash *defaults)
1075 {
1076         defaults->update("MWINDOWWIDTH", get_w());
1077         defaults->update("MWINDOWHEIGHT", get_h());
1078         mainmenu->save_defaults(defaults);
1079         BC_WindowBase::save_defaults(defaults);
1080         return 0;
1081 }
1082
1083 int MWindowGUI::keypress_event()
1084 {
1085 //printf("MWindowGUI::keypress_event 1 %d\n", get_keypress());
1086         int result = mbuttons->keypress_event();
1087         if( result ) return result;
1088
1089         Track *this_track = 0, *first_track = 0;
1090         int packed = 0, overwrite = 0, plugins = 0;
1091         double position = 0;
1092
1093         switch( get_keypress() ) {
1094         case 'A':
1095                 if( !alt_down() ) {
1096                         if( !ctrl_down() || !shift_down() ) break;
1097                         mwindow->edl->tracks->clear_selected_edits();
1098                         draw_overlays(1);
1099                         result = 1;
1100                         break;
1101                 } // fall thru
1102         case 'a':
1103                 if( !alt_down() ) break;
1104                 stop_transport("MWindowGUI::keypress_event 1");
1105                 mwindow->nearest_auto_keyframe(shift_down(),
1106                         !ctrl_down() ? PLAY_FORWARD : PLAY_REVERSE);
1107                 result = 1;
1108                 break;
1109
1110         case '\'':
1111                 if( ctrl_down() && alt_down() ) {
1112                         mwindow->select_edits(1);
1113                         result = 1;
1114                 }
1115                 break;
1116
1117         case 'e':
1118                 if( ctrl_down() || alt_down() ) break;
1119                 mwindow->toggle_editing_mode();
1120                 result = 1;
1121                 break;
1122
1123         case 'k': case 'K':
1124                 if( alt_down() ) break;
1125                 stop_transport("MWindowGUI::keypress_event 2");
1126                 mwindow->nearest_plugin_keyframe(shift_down(),
1127                         !ctrl_down() ? PLAY_FORWARD : PLAY_REVERSE);
1128                 result = 1;
1129                 break;
1130
1131         case 'C':
1132                 packed = 1;
1133         case 'c':
1134                 if( !ctrl_down() || alt_down() ) break;
1135                 mwindow->selected_edits_to_clipboard(packed);
1136                 result = 1;
1137                 break;
1138         case 'P':
1139                 plugins = 1;
1140         case 'b':
1141                 overwrite = -1; // fall thru
1142         case 'v':
1143                 if( !ctrl_down() || alt_down() ) break;
1144                 if( mwindow->session->current_operation == DROP_TARGETING ) {
1145                         mwindow->session->current_operation = NO_OPERATION;
1146                         mwindow->gui->set_editing_mode(1);
1147                         int pane_no = 0;
1148                         for( ; pane_no<TOTAL_PANES; ++pane_no  ) {
1149                                 if( !pane[pane_no] ) continue;
1150                                 first_track = pane[pane_no]->over_track();
1151                                 if( first_track ) break;
1152                         }
1153                         if( first_track ) {
1154                                 int cursor_x = pane[pane_no]->canvas->get_relative_cursor_x();
1155                                 position = mwindow->edl->get_cursor_position(cursor_x, pane_no);
1156                         }
1157                 }
1158                 else
1159                         position = mwindow->edl->local_session->get_selectionstart();
1160                 if( !plugins )
1161                         mwindow->paste(position, first_track, 0, overwrite);
1162                 else
1163                         mwindow->paste_clipboard(first_track, position, 1, 0, 1, 1, 1);
1164                 mwindow->edl->tracks->clear_selected_edits();
1165                 draw_overlays(1);
1166                 result = 1;
1167                 break;
1168         case 'M':
1169                 mwindow->cut_selected_edits(0, 1);
1170                 result = 1;
1171                 break;
1172         case BACKSPACE:
1173         case 'm':
1174                 mwindow->cut_selected_edits(0, 0);
1175                 result = 1;
1176                 break;
1177         case 'z':
1178                 if( !alt_down() ) {
1179                         // z and ctrl-z both are undo, z mainmenu item
1180                         if( mwindow->session->current_operation == NO_OPERATION )
1181                                 mwindow->undo_entry(this);
1182                         result = 1;
1183                 }
1184                 else if( ctrl_down() ) {
1185                         mwindow->cut_selected_edits(1, 1);
1186                         result = 1;
1187                 }
1188                 break;
1189         case 'x':
1190                 if( !ctrl_down() || alt_down() ) break;
1191                 mwindow->cut_selected_edits(1, 0);
1192                 result = 1;
1193                 break;
1194
1195         case '1' ... '8':
1196                 if( !alt_down() || shift_down() ) break;
1197                 if( !mwindow->select_asset(get_keypress()-'1',1) )
1198                         result = 1;
1199                 break;
1200
1201         case LEFT:
1202                 if( !ctrl_down() ) {
1203                         if( alt_down() ) {
1204                                 stop_transport("MWindowGUI::keypress_event 1");
1205                                 mwindow->prev_edit_handle(shift_down());
1206                         }
1207                         else
1208                                 mwindow->move_left();
1209                         result = 1;
1210                 }
1211                 break;
1212
1213         case ',':
1214                 if( !ctrl_down() && !alt_down() ) {
1215                         mwindow->move_left();
1216                         result = 1;
1217                 }
1218                 break;
1219
1220         case RIGHT:
1221                 if( !ctrl_down() ) {
1222                         if( alt_down() ) {
1223                                 stop_transport("MWindowGUI::keypress_event 2");
1224                                 mwindow->next_edit_handle(shift_down());
1225                         }
1226                         else
1227                                 mwindow->move_right();
1228                         result = 1;
1229                 }
1230                 break;
1231
1232         case '.':
1233                 if( !ctrl_down() && !alt_down() ) {
1234                         mwindow->move_right();
1235                         result = 1;
1236                 }
1237                 break;
1238
1239         case '!':
1240                 if( !ctrl_down() || !shift_down() ) break;
1241                 {
1242                         if( mwindow->session->current_operation != NO_OPERATION ) return 1;
1243                         first_track = mwindow->edl->tracks->first;
1244                         double start = mwindow->edl->local_session->get_selectionstart();
1245                         int64_t pos = first_track->to_units(start, 0);
1246                         Edit *edit=first_track->edits->editof(pos, PLAY_FORWARD, 0);
1247                         if( !edit || !edit->asset ) return 1;
1248                         Asset *asset = edit->asset;
1249                         double timecode = asset->timecode != -2 ? asset->timecode :
1250                                 FFMPEG::get_timecode(asset->path,
1251                                         edit->track->data_type, edit->channel,
1252                                         mwindow->edl->session->frame_rate);
1253                         asset->timecode = timecode;
1254                         if( timecode >= 0 ) {
1255                                 int64_t pos = edit->startproject + edit->startsource;
1256                                 double position = edit->track->from_units(pos);
1257                                 mwindow->set_timecode_offset(timecode - position);
1258                         }
1259                         else
1260                                 mwindow->set_timecode_offset(0);
1261                 }
1262                 result = 1;
1263                 break;
1264
1265         case UP:
1266                 if( ctrl_down() && !alt_down() )
1267                         mwindow->expand_y();
1268                 else if( !ctrl_down() && alt_down() )
1269                         mwindow->expand_autos(0,1,1);
1270                 else if( ctrl_down() && alt_down() )
1271                         mwindow->expand_autos(1,1,1);
1272                 else
1273                         mwindow->expand_sample();
1274                 result = 1;
1275                 break;
1276
1277         case DOWN:
1278                 if( ctrl_down() && !alt_down() )
1279                         mwindow->zoom_in_y();
1280                 else if( !ctrl_down() && alt_down() )
1281                         mwindow->shrink_autos(0,1,1);
1282                 else if( ctrl_down() && alt_down() )
1283                         mwindow->shrink_autos(1,1,1);
1284                 else
1285                         mwindow->zoom_in_sample();
1286                 result = 1;
1287                 break;
1288
1289         case PGUP:
1290                 if( !ctrl_down() )
1291                         mwindow->move_up();
1292                 else
1293                         mwindow->expand_t();
1294                 result = 1;
1295                 break;
1296
1297         case PGDN:
1298                 if( !ctrl_down() )
1299                         mwindow->move_down();
1300                 else
1301                         mwindow->zoom_in_t();
1302                 result = 1;
1303                 break;
1304
1305         case TAB:
1306         case LEFTTAB:
1307                 for( int i=0; i<TOTAL_PANES; ++i ) {
1308                         if( !pane[i] ) continue;
1309                         if( (this_track = pane[i]->over_track()) != 0 ) break;
1310                         if( (this_track = pane[i]->over_patchbay()) != 0 ) break;
1311                 }
1312
1313                 if( get_keypress() == TAB ) { // Switch the armed button
1314                         if( this_track )
1315                                 this_track->armed = !this_track->armed ? 1 : 0;
1316                 }
1317                 else {
1318                         int total_selected = mwindow->edl->tracks->total_of(Tracks::RECORD);
1319                         // all selected if nothing previously selected or
1320                         // if this patch was previously the only one selected and armed
1321                         int selected = !total_selected || (total_selected == 1 &&
1322                                 this_track && this_track->armed ) ? 1 : 0;
1323                         mwindow->edl->tracks->select_all(Tracks::RECORD, selected);
1324                         if( !selected && this_track ) this_track->armed = 1;
1325                 }
1326
1327                 update(0, NORMAL_DRAW, 0, 0, 1, 0, 1);
1328                 unlock_window();
1329                 mwindow->cwindow->update(0, 1, 1);
1330                 lock_window("MWindowGUI::keypress_event 3");
1331
1332                 result = 1;
1333                 break;
1334
1335         case KEY_F1 ... KEY_F12:
1336                 resend_event(mwindow->cwindow->gui);
1337                 return 1;
1338         }
1339
1340 // since things under cursor have changed...
1341         if(result)
1342                 cursor_motion_event();
1343
1344         if(!result)
1345                 result = context_help_check_and_show();
1346
1347         return result;
1348 }
1349
1350 int MWindowGUI::keyboard_listener(BC_WindowBase *wp)
1351 {
1352         return key_listener(wp->get_keypress());
1353 }
1354
1355 int MWindowGUI::key_listener(int key)
1356 {
1357         int result = 1;
1358         switch( key ) {
1359         case KPTV:
1360                 if( !record->running() )
1361                         record->start();
1362                 else
1363                         record->record_gui->interrupt_thread->start(0);
1364                 break;
1365         case KPHAND:
1366                 mwindow->quit();
1367                 break;
1368 #ifdef HAVE_DVB
1369         case KPBOOK:
1370                 channel_info->toggle_scan();
1371                 break;
1372 #endif
1373         case KPMENU:
1374                 if( !remote_control->deactivate() )
1375                         remote_control->activate();
1376                 break;
1377         default:
1378                 result = 0;
1379                 break;
1380         }
1381         return result;
1382 }
1383
1384
1385 void MWindowGUI::use_android_remote(int on)
1386 {
1387         if( !on ) {
1388                 delete android_control;
1389                 android_control = 0;
1390                 return;
1391         }
1392         if( android_control ) return;
1393         android_control = new AndroidControl(this);
1394 }
1395 int MWindowGUI::keyev_grab_remote()
1396 {
1397         if( cwindow_remote_handler && cwindow_remote_handler->is_keytv() &&
1398             record_remote_handler  && record_remote_handler->is_keytv() )
1399                 return 0;
1400         delete cwindow_remote_handler;
1401         delete record_remote_handler;
1402         cwindow_remote_handler = (RemoteHandler*)
1403                 new CWindowKeyEvHandler(mwindow->gui->remote_control);
1404         record_remote_handler = (RemoteHandler*)
1405                 new RecordKeyEvHandler(mwindow->gui->remote_control);
1406         return 1;
1407 }
1408
1409 int MWindowGUI::close_event()
1410 {
1411         mainmenu->quit();
1412         return 0;
1413 }
1414
1415 void MWindowGUI::stop_drawing()
1416 {
1417         resource_thread->stop_draw(1);
1418 }
1419
1420 int MWindowGUI::menu_w()
1421 {
1422         return mainmenu->get_w();
1423 }
1424
1425 int MWindowGUI::menu_h()
1426 {
1427         return mainmenu->get_h();
1428 }
1429
1430 void MWindowGUI::start_x_pane_drag()
1431 {
1432         if(!x_pane_drag)
1433         {
1434                 x_pane_drag = new BC_Popup(this,
1435                         get_abs_cursor_x(0) - mwindow->theme->pane_w,
1436                         BC_DisplayInfo::get_top_border() +
1437                                 get_y() +
1438                                 mwindow->theme->mcanvas_y,
1439                         mwindow->theme->pane_w,
1440                         mwindow->theme->mcanvas_h,
1441                         mwindow->theme->drag_pane_color);
1442                 x_pane_drag->draw_3segmentv(0,
1443                         0,
1444                         x_pane_drag->get_h(),
1445                         mwindow->theme->get_image_set("xpane")[BUTTON_DOWNHI]);
1446                 x_pane_drag->flash(1);
1447         }
1448         dragging_pane = 1;
1449 }
1450
1451 void MWindowGUI::start_y_pane_drag()
1452 {
1453         if(!y_pane_drag)
1454         {
1455 //printf("MWindowGUI::start_y_pane_drag %d %d %d\n", __LINE__, get_x(), get_y());
1456                 y_pane_drag = new BC_Popup(this,
1457                         BC_DisplayInfo::get_left_border() +
1458                                 get_x() +
1459                                 mwindow->theme->mcanvas_x,
1460                         get_abs_cursor_y(0) - mwindow->theme->pane_h,
1461                         mwindow->theme->mcanvas_w,
1462                         mwindow->theme->pane_h,
1463                         mwindow->theme->drag_pane_color);
1464                 y_pane_drag->draw_3segmenth(0,
1465                         0,
1466                         y_pane_drag->get_w(),
1467                         mwindow->theme->get_image_set("ypane")[BUTTON_DOWNHI]);
1468                 y_pane_drag->flash(1);
1469         }
1470         dragging_pane = 1;
1471 }
1472
1473 void MWindowGUI::handle_pane_drag()
1474 {
1475         if(dragging_pane)
1476         {
1477                 if(x_pane_drag)
1478                 {
1479                         x_pane_drag->reposition_window(
1480                                 get_abs_cursor_x(0) - mwindow->theme->pane_w,
1481                                 x_pane_drag->get_y());
1482                 }
1483
1484                 if(y_pane_drag)
1485                 {
1486                         y_pane_drag->reposition_window(
1487                                 y_pane_drag->get_x(),
1488                                 get_abs_cursor_y(0) - mwindow->theme->pane_h);
1489                 }
1490         }
1491 }
1492
1493
1494 void MWindowGUI::create_x_pane(int cursor_x)
1495 {
1496         if(total_panes() == 1)
1497         {
1498 // create a horizontal pane
1499 // do this 1st so the resize_event knows there are 2 panes
1500                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] =
1501                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] +
1502                         cursor_x -
1503                         mwindow->theme->patchbay_w;
1504                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1505                         TOP_RIGHT_PANE,
1506                         mwindow->theme->mcanvas_x +
1507                                 cursor_x,
1508                         mwindow->theme->mcanvas_y,
1509                         mwindow->theme->mcanvas_x +
1510                                 mwindow->theme->mcanvas_w -
1511                                 cursor_x,
1512                         mwindow->theme->mcanvas_h);
1513                 pane[TOP_LEFT_PANE]->resize_event(
1514                         mwindow->theme->mcanvas_x,
1515                         mwindow->theme->mcanvas_y,
1516                         cursor_x - mwindow->theme->pane_w,
1517                         mwindow->theme->mcanvas_h);
1518                 pane[TOP_RIGHT_PANE]->create_objects();
1519         }
1520         else
1521         if(vertical_panes())
1522         {
1523 // create 2 horizontal panes
1524                 mwindow->edl->local_session->track_start[TOP_RIGHT_PANE] =
1525                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE];
1526                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1527                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE];
1528                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] =
1529                         mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1530                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] +
1531                         cursor_x -
1532                         mwindow->theme->patchbay_w;
1533                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1534                         TOP_RIGHT_PANE,
1535                         mwindow->theme->mcanvas_x +
1536                                 cursor_x,
1537                         pane[TOP_LEFT_PANE]->y,
1538                         mwindow->theme->mcanvas_x +
1539                                 mwindow->theme->mcanvas_w -
1540                                 cursor_x,
1541                         pane[TOP_LEFT_PANE]->h);
1542                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1543                         BOTTOM_RIGHT_PANE,
1544                         mwindow->theme->mcanvas_x +
1545                                 cursor_x,
1546                         pane[BOTTOM_LEFT_PANE]->y,
1547                         mwindow->theme->mcanvas_x +
1548                                 mwindow->theme->mcanvas_w -
1549                                 cursor_x,
1550                         pane[BOTTOM_LEFT_PANE]->h);
1551                 pane[TOP_LEFT_PANE]->resize_event(
1552                         pane[TOP_LEFT_PANE]->x,
1553                         pane[TOP_LEFT_PANE]->y,
1554                         cursor_x - mwindow->theme->pane_w,
1555                         pane[TOP_LEFT_PANE]->h);
1556                 pane[BOTTOM_LEFT_PANE]->resize_event(
1557                         pane[BOTTOM_LEFT_PANE]->x,
1558                         pane[BOTTOM_LEFT_PANE]->y,
1559                         cursor_x - mwindow->theme->pane_w,
1560                         pane[BOTTOM_LEFT_PANE]->h);
1561                 pane[TOP_RIGHT_PANE]->create_objects();
1562                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1563         }
1564         else
1565         if(horizontal_panes())
1566         {
1567 // resize a horizontal pane
1568                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] +=
1569                         cursor_x -
1570                         pane[TOP_RIGHT_PANE]->x;
1571                 if(mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] < 0)
1572                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] = 0;
1573                 pane[TOP_LEFT_PANE]->resize_event(
1574                         mwindow->theme->mcanvas_x,
1575                         mwindow->theme->mcanvas_y,
1576                         cursor_x - mwindow->theme->pane_w,
1577                         mwindow->theme->mcanvas_h);
1578                 pane[TOP_RIGHT_PANE]->resize_event(
1579                         mwindow->theme->mcanvas_x +
1580                                 cursor_x,
1581                         pane[TOP_RIGHT_PANE]->y,
1582                         mwindow->theme->mcanvas_x +
1583                                 mwindow->theme->mcanvas_w -
1584                                 cursor_x,
1585                         mwindow->theme->mcanvas_h);
1586         }
1587         else
1588         {
1589 // resize 2 horizontal panes
1590                 mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] +=
1591                         cursor_x -
1592                         pane[TOP_RIGHT_PANE]->x;
1593                 if(mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] < 0)
1594                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] = 0;
1595                 mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1596                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE];
1597
1598                 pane[TOP_LEFT_PANE]->resize_event(
1599                         mwindow->theme->mcanvas_x,
1600                         pane[TOP_LEFT_PANE]->y,
1601                         cursor_x - mwindow->theme->pane_w,
1602                         pane[TOP_LEFT_PANE]->h);
1603                 pane[TOP_RIGHT_PANE]->resize_event(
1604                         mwindow->theme->mcanvas_x +
1605                                 cursor_x,
1606                         pane[TOP_RIGHT_PANE]->y,
1607                         mwindow->theme->mcanvas_x +
1608                                 mwindow->theme->mcanvas_w -
1609                                 cursor_x,
1610                         pane[TOP_RIGHT_PANE]->h);
1611                 pane[BOTTOM_LEFT_PANE]->resize_event(
1612                         mwindow->theme->mcanvas_x,
1613                         pane[BOTTOM_LEFT_PANE]->y,
1614                         cursor_x - mwindow->theme->pane_w,
1615                         pane[BOTTOM_LEFT_PANE]->h);
1616                 pane[BOTTOM_RIGHT_PANE]->resize_event(
1617                         mwindow->theme->mcanvas_x +
1618                                 cursor_x,
1619                         pane[BOTTOM_RIGHT_PANE]->y,
1620                         mwindow->theme->mcanvas_x +
1621                                 mwindow->theme->mcanvas_w -
1622                                 cursor_x,
1623                         pane[BOTTOM_RIGHT_PANE]->h);
1624
1625         }
1626 }
1627
1628
1629 void MWindowGUI::delete_x_pane(int cursor_x)
1630 {
1631 // give left panes coordinates of right pane
1632         if(cursor_x < mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1633                 pane[TOP_RIGHT_PANE])
1634         {
1635                 mwindow->edl->local_session->view_start[TOP_LEFT_PANE] =
1636                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE] -
1637                         pane[TOP_RIGHT_PANE]->x + mwindow->theme->patchbay_w;
1638                 if(mwindow->edl->local_session->view_start[TOP_LEFT_PANE] < 0)
1639                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE] = 0;
1640                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1641                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1642         }
1643
1644         switch(total_panes())
1645         {
1646                 case 2:
1647                         if(pane[TOP_LEFT_PANE] && pane[TOP_RIGHT_PANE])
1648                         {
1649 // delete right pane
1650                                 delete pane[TOP_RIGHT_PANE];
1651                                 pane[TOP_RIGHT_PANE] = 0;
1652                                 pane[TOP_LEFT_PANE]->resize_event(
1653                                         mwindow->theme->mcanvas_x,
1654                                         mwindow->theme->mcanvas_y,
1655                                         mwindow->theme->mcanvas_w,
1656                                         mwindow->theme->mcanvas_h);
1657
1658                         }
1659                         break;
1660
1661                 case 4:
1662 // delete right panes
1663                         delete pane[TOP_RIGHT_PANE];
1664                         pane[TOP_RIGHT_PANE] = 0;
1665                         delete pane[BOTTOM_RIGHT_PANE];
1666                         pane[BOTTOM_RIGHT_PANE] = 0;
1667                         pane[TOP_LEFT_PANE]->resize_event(
1668                                 mwindow->theme->mcanvas_x,
1669                                 pane[TOP_LEFT_PANE]->y,
1670                                 mwindow->theme->mcanvas_w,
1671                                 pane[TOP_LEFT_PANE]->h);
1672                         pane[BOTTOM_LEFT_PANE]->resize_event(
1673                                 mwindow->theme->mcanvas_x,
1674                                 pane[BOTTOM_LEFT_PANE]->y,
1675                                 mwindow->theme->mcanvas_w,
1676                                 pane[BOTTOM_LEFT_PANE]->h);
1677                         break;
1678         }
1679 }
1680
1681 void MWindowGUI::create_y_pane(int cursor_y)
1682 {
1683         if(total_panes() == 1)
1684         {
1685                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1686                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1687                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] =
1688                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] +
1689                         cursor_y -
1690                         mwindow->theme->mtimebar_h;
1691 // do this 1st so the resize_event knows there are 2 panes
1692                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1693                         BOTTOM_LEFT_PANE,
1694                         mwindow->theme->mcanvas_x,
1695                         mwindow->theme->mcanvas_y +
1696                                 cursor_y,
1697                         mwindow->theme->mcanvas_w,
1698                         mwindow->theme->mcanvas_h -
1699                                 cursor_y);
1700                 pane[TOP_LEFT_PANE]->resize_event(
1701                         mwindow->theme->mcanvas_x,
1702                         mwindow->theme->mcanvas_y,
1703                         mwindow->theme->mcanvas_w,
1704                         pane[BOTTOM_LEFT_PANE]->y -
1705                                 mwindow->theme->mcanvas_y -
1706                                 mwindow->theme->pane_h);
1707                 pane[BOTTOM_LEFT_PANE]->create_objects();
1708         }
1709         else
1710         if(horizontal_panes())
1711         {
1712 // create 2 panes
1713                 mwindow->edl->local_session->view_start[BOTTOM_LEFT_PANE] =
1714                         mwindow->edl->local_session->view_start[TOP_LEFT_PANE];
1715                 mwindow->edl->local_session->view_start[BOTTOM_RIGHT_PANE] =
1716                         mwindow->edl->local_session->view_start[TOP_RIGHT_PANE];
1717                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] =
1718                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1719                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] +
1720                         cursor_y -
1721                         mwindow->theme->mtimebar_h;
1722
1723                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1724                         BOTTOM_LEFT_PANE,
1725                         pane[TOP_LEFT_PANE]->x,
1726                         mwindow->theme->mcanvas_y +
1727                                 cursor_y,
1728                         pane[TOP_LEFT_PANE]->w,
1729                         mwindow->theme->mcanvas_h -
1730                                 cursor_y);
1731                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1732                         BOTTOM_RIGHT_PANE,
1733                         pane[TOP_RIGHT_PANE]->x,
1734                         mwindow->theme->mcanvas_y +
1735                                 cursor_y,
1736                         pane[TOP_RIGHT_PANE]->w,
1737                         mwindow->theme->mcanvas_h -
1738                                 cursor_y);
1739
1740                 pane[TOP_LEFT_PANE]->resize_event(
1741                         pane[TOP_LEFT_PANE]->x,
1742                         pane[TOP_LEFT_PANE]->y,
1743                         pane[TOP_LEFT_PANE]->w,
1744                         pane[BOTTOM_LEFT_PANE]->y -
1745                                 mwindow->theme->mcanvas_y -
1746                                 mwindow->theme->pane_h);
1747                 pane[TOP_RIGHT_PANE]->resize_event(
1748                         pane[TOP_RIGHT_PANE]->x,
1749                         pane[TOP_RIGHT_PANE]->y,
1750                         pane[TOP_RIGHT_PANE]->w,
1751                         pane[BOTTOM_RIGHT_PANE]->y -
1752                                 mwindow->theme->mcanvas_y -
1753                                 mwindow->theme->pane_h);
1754
1755                 pane[BOTTOM_LEFT_PANE]->create_objects();
1756                 pane[BOTTOM_RIGHT_PANE]->create_objects();
1757         }
1758         else
1759         if(vertical_panes())
1760         {
1761 // resize a pane
1762                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] +=
1763                         cursor_y -
1764                         (pane[BOTTOM_LEFT_PANE]->y - mwindow->theme->mcanvas_y);
1765                 if(mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] < 0)
1766                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] = 0;
1767                 pane[TOP_LEFT_PANE]->resize_event(
1768                         mwindow->theme->mcanvas_x,
1769                         mwindow->theme->mcanvas_y,
1770                         mwindow->theme->mcanvas_w,
1771                         cursor_y - mwindow->theme->pane_h);
1772                 pane[BOTTOM_LEFT_PANE]->resize_event(
1773                         pane[BOTTOM_LEFT_PANE]->x,
1774                         cursor_y +
1775                                 mwindow->theme->mcanvas_y,
1776                         mwindow->theme->mcanvas_w,
1777                         mwindow->theme->mcanvas_h -
1778                                 cursor_y);
1779         }
1780         else
1781         {
1782 // resize 2 panes
1783                 mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] +=
1784                         cursor_y -
1785                         (pane[BOTTOM_LEFT_PANE]->y - mwindow->theme->mcanvas_y);
1786                 if(mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] < 0)
1787                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] = 0;
1788                 mwindow->edl->local_session->track_start[BOTTOM_RIGHT_PANE] =
1789                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE];
1790                 pane[TOP_LEFT_PANE]->resize_event(
1791                         pane[TOP_LEFT_PANE]->x,
1792                         pane[TOP_LEFT_PANE]->y,
1793                         pane[TOP_LEFT_PANE]->w,
1794                         cursor_y - mwindow->theme->pane_h);
1795                 pane[BOTTOM_LEFT_PANE]->resize_event(
1796                         pane[BOTTOM_LEFT_PANE]->x,
1797                         cursor_y +
1798                                 mwindow->theme->mcanvas_y,
1799                         pane[BOTTOM_LEFT_PANE]->w,
1800                         mwindow->theme->mcanvas_h -
1801                                         cursor_y);
1802                 pane[TOP_RIGHT_PANE]->resize_event(
1803                         pane[TOP_RIGHT_PANE]->x,
1804                         pane[TOP_RIGHT_PANE]->y,
1805                         pane[TOP_RIGHT_PANE]->w,
1806                         cursor_y - mwindow->theme->pane_h);
1807                 pane[BOTTOM_RIGHT_PANE]->resize_event(
1808                         pane[BOTTOM_RIGHT_PANE]->x,
1809                         cursor_y +
1810                                 mwindow->theme->mcanvas_y,
1811                         pane[BOTTOM_RIGHT_PANE]->w,
1812                         mwindow->theme->mcanvas_h -
1813                                         cursor_y);
1814         }
1815 }
1816
1817 void MWindowGUI::delete_y_pane(int cursor_y)
1818 {
1819         if(cursor_y < mwindow->theme->mtimebar_h +
1820                 PANE_DRAG_MARGIN &&
1821                 pane[BOTTOM_LEFT_PANE])
1822         {
1823 // give top pane coordinates of bottom pane
1824                 mwindow->edl->local_session->track_start[TOP_LEFT_PANE] =
1825                         mwindow->edl->local_session->track_start[BOTTOM_LEFT_PANE] -
1826                         pane[BOTTOM_LEFT_PANE]->y;
1827                 if(mwindow->edl->local_session->track_start[TOP_LEFT_PANE] < 0)
1828                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE] = 0;
1829                 mwindow->edl->local_session->track_start[TOP_RIGHT_PANE] =
1830                         mwindow->edl->local_session->track_start[TOP_LEFT_PANE];
1831         }
1832
1833 // delete a pane
1834         switch(total_panes())
1835         {
1836                 case 2:
1837                         delete pane[BOTTOM_LEFT_PANE];
1838                         pane[BOTTOM_LEFT_PANE] = 0;
1839                         pane[TOP_LEFT_PANE]->resize_event(
1840                                 mwindow->theme->mcanvas_x,
1841                                 mwindow->theme->mcanvas_y,
1842                                 mwindow->theme->mcanvas_w,
1843                                 mwindow->theme->mcanvas_h);
1844                         break;
1845
1846                 case 4:
1847 // delete bottom 2 panes
1848
1849                         delete pane[BOTTOM_LEFT_PANE];
1850                         pane[BOTTOM_LEFT_PANE] = 0;
1851                         delete pane[BOTTOM_RIGHT_PANE];
1852                         pane[BOTTOM_RIGHT_PANE] = 0;
1853                         pane[TOP_LEFT_PANE]->resize_event(
1854                                 pane[TOP_LEFT_PANE]->x,
1855                                 mwindow->theme->mcanvas_y,
1856                                 pane[TOP_LEFT_PANE]->w,
1857                                 mwindow->theme->mcanvas_h);
1858                         pane[TOP_RIGHT_PANE]->resize_event(
1859                                 pane[TOP_RIGHT_PANE]->x,
1860                                 mwindow->theme->mcanvas_y,
1861                                 pane[TOP_RIGHT_PANE]->w,
1862                                 mwindow->theme->mcanvas_h);
1863                         break;
1864         }
1865 }
1866
1867 void MWindowGUI::stop_pane_drag()
1868 {
1869         if( !dragging_pane ) return;
1870         dragging_pane = 0;
1871         resource_thread->stop_draw(0);
1872
1873         if(x_pane_drag)
1874         {
1875 // cursor position relative to canvas
1876                 int cursor_x = x_pane_drag->get_x() -
1877                         get_x() -
1878                         BC_DisplayInfo::get_left_border() -
1879                         mwindow->theme->mcanvas_x +
1880                         mwindow->theme->pane_w;
1881                 delete x_pane_drag;
1882                 x_pane_drag = 0;
1883
1884
1885                 if(cursor_x >= mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1886                         cursor_x < mwindow->theme->mcanvas_w -
1887                                 BC_ScrollBar::get_span(SCROLL_VERT) -
1888                                 PANE_DRAG_MARGIN)
1889                 {
1890                         create_x_pane(cursor_x);
1891                         mwindow->edl->local_session->x_pane = cursor_x;
1892                 }
1893                 else
1894 // deleted a pane
1895                 {
1896                         delete_x_pane(cursor_x);
1897                         mwindow->edl->local_session->x_pane = -1;
1898                 }
1899
1900
1901         }
1902
1903         if(y_pane_drag)
1904         {
1905 // cursor position relative to canvas
1906                 int cursor_y = y_pane_drag->get_y() -
1907                         get_y() -
1908                         BC_DisplayInfo::get_top_border() -
1909                         mwindow->theme->mcanvas_y +
1910                         mwindow->theme->pane_h;
1911                 delete y_pane_drag;
1912                 y_pane_drag = 0;
1913
1914
1915
1916                 if(cursor_y >= mwindow->theme->mtimebar_h +
1917                                 PANE_DRAG_MARGIN &&
1918                         cursor_y < mwindow->theme->mcanvas_h -
1919                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
1920                                 PANE_DRAG_MARGIN)
1921                 {
1922                         create_y_pane(cursor_y);
1923                         mwindow->edl->local_session->y_pane = cursor_y;
1924                 }
1925                 else
1926                 {
1927                         delete_y_pane(cursor_y);
1928                         mwindow->edl->local_session->y_pane = -1;
1929                 }
1930         }
1931
1932         update_pane_dividers();
1933         update_cursor();
1934 // required to get new widgets to appear
1935         show_window();
1936         resource_thread->start_draw();
1937 }
1938
1939 // create panes from EDL
1940 void MWindowGUI::load_panes()
1941 {
1942         int need_x_panes = 0;
1943         int need_y_panes = 0;
1944 // use names from create functions
1945         int cursor_x = mwindow->edl->local_session->x_pane;
1946         int cursor_y = mwindow->edl->local_session->y_pane;
1947
1948         resource_thread->stop_draw(1);
1949         if(cursor_x >=
1950                 mwindow->theme->patchbay_w + PANE_DRAG_MARGIN &&
1951                 cursor_x <
1952                 mwindow->theme->mcanvas_w -
1953                                 BC_ScrollBar::get_span(SCROLL_VERT) -
1954                                 PANE_DRAG_MARGIN)
1955         {
1956                 need_x_panes = 1;
1957         }
1958
1959         if(cursor_y >=
1960                 mwindow->theme->mtimebar_h + PANE_DRAG_MARGIN &&
1961                 cursor_y <
1962                 mwindow->theme->mcanvas_h -
1963                                 BC_ScrollBar::get_span(SCROLL_HORIZ) -
1964                                 PANE_DRAG_MARGIN)
1965         {
1966                 need_y_panes = 1;
1967         }
1968
1969 //printf("MWindowGUI::load_panes %d %d %d\n", __LINE__, need_x_panes, need_y_panes);
1970
1971
1972         if(need_x_panes)
1973         {
1974                 if(need_y_panes)
1975                 {
1976 // 4 panes
1977                         if(total_panes() == 1)
1978                         {
1979 // create 4 panes
1980 //printf("MWindowGUI::load_panes %d\n", __LINE__);
1981                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
1982                                         TOP_RIGHT_PANE,
1983                                         mwindow->theme->mcanvas_x +
1984                                                 cursor_x,
1985                                         mwindow->theme->mcanvas_y,
1986                                         mwindow->theme->mcanvas_x +
1987                                                 mwindow->theme->mcanvas_w -
1988                                                 cursor_x,
1989                                         cursor_y - mwindow->theme->pane_h);
1990                                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
1991                                         BOTTOM_LEFT_PANE,
1992                                         mwindow->theme->mcanvas_x,
1993                                         mwindow->theme->mcanvas_y +
1994                                                 cursor_y,
1995                                         cursor_x - mwindow->theme->pane_w,
1996                                         mwindow->theme->mcanvas_h -
1997                                                 cursor_y);
1998                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
1999                                         BOTTOM_RIGHT_PANE,
2000                                         pane[TOP_RIGHT_PANE]->x,
2001                                         mwindow->theme->mcanvas_y +
2002                                                 cursor_y,
2003                                         pane[TOP_RIGHT_PANE]->w,
2004                                         mwindow->theme->mcanvas_h -
2005                                                 cursor_y);
2006                                 pane[TOP_LEFT_PANE]->resize_event(
2007                                         pane[TOP_LEFT_PANE]->x,
2008                                         pane[TOP_LEFT_PANE]->y,
2009                                         cursor_x - mwindow->theme->pane_w,
2010                                         cursor_y - mwindow->theme->pane_h);
2011                                 pane[TOP_RIGHT_PANE]->create_objects();
2012                                 pane[BOTTOM_LEFT_PANE]->create_objects();
2013                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
2014                         }
2015                         else
2016                         if(horizontal_panes())
2017                         {
2018 // create vertical panes
2019 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2020                                 pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
2021                                         BOTTOM_LEFT_PANE,
2022                                         mwindow->theme->mcanvas_x,
2023                                         mwindow->theme->mcanvas_y +
2024                                                 cursor_y,
2025                                         cursor_x - mwindow->theme->pane_w,
2026                                         mwindow->theme->mcanvas_h -
2027                                                 cursor_y);
2028                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
2029                                         BOTTOM_RIGHT_PANE,
2030                                         pane[TOP_RIGHT_PANE]->x,
2031                                         mwindow->theme->mcanvas_y +
2032                                                 cursor_y,
2033                                         pane[TOP_RIGHT_PANE]->w,
2034                                         mwindow->theme->mcanvas_h -
2035                                                 cursor_y);
2036                                 pane[TOP_LEFT_PANE]->resize_event(
2037                                         pane[TOP_LEFT_PANE]->x,
2038                                         pane[TOP_LEFT_PANE]->y,
2039                                         cursor_x - mwindow->theme->pane_w,
2040                                         cursor_y - mwindow->theme->pane_h);
2041                                 pane[TOP_RIGHT_PANE]->resize_event(
2042                                         mwindow->theme->mcanvas_x +
2043                                                 cursor_x,
2044                                         mwindow->theme->mcanvas_y,
2045                                         mwindow->theme->mcanvas_x +
2046                                                 mwindow->theme->mcanvas_w -
2047                                                 cursor_x,
2048                                         cursor_y - mwindow->theme->pane_h);
2049                                 pane[BOTTOM_LEFT_PANE]->create_objects();
2050                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
2051                         }
2052                         else
2053                         if(vertical_panes())
2054                         {
2055 // create horizontal panes
2056 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2057                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
2058                                         TOP_RIGHT_PANE,
2059                                         mwindow->theme->mcanvas_x +
2060                                                 cursor_x,
2061                                         mwindow->theme->mcanvas_y,
2062                                         mwindow->theme->mcanvas_x +
2063                                                 mwindow->theme->mcanvas_w -
2064                                                 cursor_x,
2065                                         cursor_y - mwindow->theme->pane_h);
2066                                 pane[BOTTOM_RIGHT_PANE] = new TimelinePane(mwindow,
2067                                         BOTTOM_RIGHT_PANE,
2068                                         pane[TOP_RIGHT_PANE]->x,
2069                                         mwindow->theme->mcanvas_y +
2070                                                 cursor_y,
2071                                         pane[TOP_RIGHT_PANE]->w,
2072                                         mwindow->theme->mcanvas_h -
2073                                                 cursor_y);
2074                                 pane[TOP_LEFT_PANE]->resize_event(
2075                                         pane[TOP_LEFT_PANE]->x,
2076                                         pane[TOP_LEFT_PANE]->y,
2077                                         cursor_x - mwindow->theme->pane_w,
2078                                         cursor_y - mwindow->theme->pane_h);
2079                                 pane[BOTTOM_LEFT_PANE]->resize_event(
2080                                         pane[TOP_LEFT_PANE]->x,
2081                                         mwindow->theme->mcanvas_y +
2082                                                 cursor_y,
2083                                         mwindow->theme->mcanvas_x +
2084                                                 mwindow->theme->mcanvas_w -
2085                                                 cursor_x -  mwindow->theme->pane_w,
2086                                         mwindow->theme->mcanvas_h -
2087                                                 cursor_y);
2088                                 pane[TOP_RIGHT_PANE]->create_objects();
2089                                 pane[BOTTOM_RIGHT_PANE]->create_objects();
2090
2091
2092                         }
2093                         else
2094                         {
2095 // resize all panes
2096 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2097                                 pane[TOP_LEFT_PANE]->resize_event(
2098                                         pane[TOP_LEFT_PANE]->x,
2099                                         pane[TOP_LEFT_PANE]->y,
2100                                         cursor_x - mwindow->theme->pane_w,
2101                                         cursor_y - mwindow->theme->pane_h);
2102                                 pane[TOP_RIGHT_PANE]->resize_event(
2103                                         mwindow->theme->mcanvas_x +
2104                                                 cursor_x,
2105                                         mwindow->theme->mcanvas_y,
2106                                         mwindow->theme->mcanvas_x +
2107                                                 mwindow->theme->mcanvas_w -
2108                                                 cursor_x,
2109                                         cursor_y - mwindow->theme->pane_h);
2110                                 pane[BOTTOM_LEFT_PANE]->resize_event(
2111                                         pane[TOP_LEFT_PANE]->x,
2112                                         mwindow->theme->mcanvas_y +
2113                                                 cursor_y,
2114                                         mwindow->theme->mcanvas_x +
2115                                                 mwindow->theme->mcanvas_w -
2116                                                 cursor_x - mwindow->theme->pane_w,
2117                                         mwindow->theme->mcanvas_h -
2118                                                 cursor_y);
2119                                 pane[BOTTOM_RIGHT_PANE]->resize_event(
2120                                         pane[TOP_RIGHT_PANE]->x,
2121                                         mwindow->theme->mcanvas_y +
2122                                                 cursor_y,
2123                                         pane[TOP_RIGHT_PANE]->w,
2124                                         mwindow->theme->mcanvas_h -
2125                                                 cursor_y);
2126
2127
2128                         }
2129                 }
2130                 else
2131                 {
2132 // 2 X panes
2133                         if(pane[BOTTOM_LEFT_PANE]) delete pane[BOTTOM_LEFT_PANE];
2134                         if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2135                         pane[BOTTOM_LEFT_PANE] = 0;
2136                         pane[BOTTOM_RIGHT_PANE] = 0;
2137
2138                         if(!pane[TOP_RIGHT_PANE])
2139                         {
2140                                 pane[TOP_RIGHT_PANE] = new TimelinePane(mwindow,
2141                                         TOP_RIGHT_PANE,
2142                                         mwindow->theme->mcanvas_x +
2143                                                 cursor_x,
2144                                         mwindow->theme->mcanvas_y,
2145                                         mwindow->theme->mcanvas_x +
2146                                                 mwindow->theme->mcanvas_w -
2147                                                 cursor_x,
2148                                         mwindow->theme->mcanvas_h);
2149                                 pane[TOP_LEFT_PANE]->resize_event(
2150                                         mwindow->theme->mcanvas_x,
2151                                         mwindow->theme->mcanvas_y,
2152                                         cursor_x - mwindow->theme->pane_w,
2153                                         mwindow->theme->mcanvas_h);
2154                                 pane[TOP_RIGHT_PANE]->create_objects();
2155                         }
2156                         else
2157                         {
2158                                 pane[TOP_LEFT_PANE]->resize_event(
2159                                         mwindow->theme->mcanvas_x,
2160                                         mwindow->theme->mcanvas_y,
2161                                         cursor_x - mwindow->theme->pane_w,
2162                                         mwindow->theme->mcanvas_h);
2163                                 pane[TOP_RIGHT_PANE]->resize_event(
2164                                         mwindow->theme->mcanvas_x +
2165                                                 cursor_x,
2166                                         pane[TOP_RIGHT_PANE]->y,
2167                                         mwindow->theme->mcanvas_x +
2168                                                 mwindow->theme->mcanvas_w -
2169                                                 cursor_x,
2170                                         mwindow->theme->mcanvas_h);
2171                         }
2172                 }
2173         }
2174         else
2175         if(need_y_panes)
2176         {
2177 // 2 Y panes
2178                 if(pane[TOP_RIGHT_PANE]) delete pane[TOP_RIGHT_PANE];
2179                 if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2180                 pane[TOP_RIGHT_PANE] = 0;
2181                 pane[BOTTOM_RIGHT_PANE] = 0;
2182
2183                 if(!pane[BOTTOM_LEFT_PANE])
2184                 {
2185 //printf("MWindowGUI::load_panes %d\n", __LINE__);
2186                         pane[BOTTOM_LEFT_PANE] = new TimelinePane(mwindow,
2187                                 BOTTOM_LEFT_PANE,
2188                                 mwindow->theme->mcanvas_x,
2189                                 mwindow->theme->mcanvas_y +
2190                                         cursor_y,
2191                                 mwindow->theme->mcanvas_w,
2192                                 mwindow->theme->mcanvas_h -
2193                                         cursor_y);
2194                         pane[TOP_LEFT_PANE]->resize_event(
2195                                 mwindow->theme->mcanvas_x,
2196                                 mwindow->theme->mcanvas_y,
2197                                 mwindow->theme->mcanvas_w,
2198                                 pane[BOTTOM_LEFT_PANE]->y -
2199                                         mwindow->theme->mcanvas_y -
2200                                         mwindow->theme->pane_h);
2201                         pane[BOTTOM_LEFT_PANE]->create_objects();
2202                 }
2203                 else
2204                 {
2205                         pane[TOP_LEFT_PANE]->resize_event(
2206                                 mwindow->theme->mcanvas_x,
2207                                 mwindow->theme->mcanvas_y,
2208                                 mwindow->theme->mcanvas_w,
2209                                 cursor_y - mwindow->theme->pane_h);
2210                         pane[BOTTOM_LEFT_PANE]->resize_event(
2211                                 pane[BOTTOM_LEFT_PANE]->x,
2212                                 cursor_y +
2213                                         mwindow->theme->mcanvas_y,
2214                                 mwindow->theme->mcanvas_w,
2215                                 mwindow->theme->mcanvas_h -
2216                                         cursor_y);
2217                 }
2218         }
2219         else
2220         {
2221 // 1 pane
2222                 if(pane[TOP_RIGHT_PANE]) delete pane[TOP_RIGHT_PANE];
2223                 if(pane[BOTTOM_RIGHT_PANE]) delete pane[BOTTOM_RIGHT_PANE];
2224                 if(pane[BOTTOM_LEFT_PANE]) delete pane[BOTTOM_LEFT_PANE];
2225                 pane[TOP_RIGHT_PANE] = 0;
2226                 pane[BOTTOM_RIGHT_PANE] = 0;
2227                 pane[BOTTOM_LEFT_PANE] = 0;
2228                 pane[TOP_LEFT_PANE]->resize_event(
2229                         mwindow->theme->mcanvas_x,
2230                         mwindow->theme->mcanvas_y,
2231                         mwindow->theme->mcanvas_w,
2232                         mwindow->theme->mcanvas_h);
2233         }
2234
2235         update_pane_dividers();
2236         show_window();
2237
2238         resource_thread->start_draw();
2239 }
2240
2241 void MWindowGUI::update_pane_dividers()
2242 {
2243
2244         if(horizontal_panes() || total_panes() == 4)
2245         {
2246                 int x = pane[TOP_RIGHT_PANE]->x - mwindow->theme->pane_w;
2247                 int y = mwindow->theme->mcanvas_y;
2248                 int h = mwindow->theme->mcanvas_h;
2249
2250                 if(!x_divider)
2251                 {
2252                         add_subwindow(x_divider = new PaneDivider(
2253                                 mwindow, x, y, h, 1));
2254                         x_divider->create_objects();
2255                 }
2256                 else
2257                 {
2258                         x_divider->reposition_window(x, y, h);
2259                         x_divider->draw(0);
2260                 }
2261         }
2262         else
2263         {
2264                 if(x_divider)
2265                 {
2266                         delete x_divider;
2267                         x_divider = 0;
2268                 }
2269         }
2270
2271         if(vertical_panes() || total_panes() == 4)
2272         {
2273                 int x = mwindow->theme->mcanvas_x;
2274                 int y = pane[BOTTOM_LEFT_PANE]->y -
2275                         mwindow->theme->pane_h;
2276                 int w = mwindow->theme->mcanvas_w;
2277                 if(!y_divider)
2278                 {
2279                         add_subwindow(y_divider = new PaneDivider(
2280                                 mwindow, x, y, w, 0));
2281                         y_divider->create_objects();
2282                 }
2283                 else
2284                 {
2285                         y_divider->reposition_window(x, y, w);
2286                         y_divider->draw(0);
2287                 }
2288         }
2289         else
2290         {
2291                 if(y_divider)
2292                 {
2293                         delete y_divider;
2294                         y_divider = 0;
2295                 }
2296         }
2297 }
2298
2299 void MWindowGUI::draw_samplemovement()
2300 {
2301         draw_canvas(0, 1);
2302         show_cursor(1);
2303         flash_canvas(0);
2304         update_timebar(0);
2305         zoombar->update();
2306         update_scrollbars(1);
2307 }
2308
2309 void MWindowGUI::draw_trackmovement()
2310 {
2311         update_scrollbars(0);
2312         draw_canvas(0, 0);
2313         update_patchbay();
2314         flash_canvas(1);
2315 }
2316
2317
2318 void MWindowGUI::update_mixers(Track *track, int v)
2319 {
2320         for( int i=0; i<TOTAL_PANES;  ++i ) {
2321                 if( !pane[i] ) continue;
2322                 PatchBay *patchbay = pane[i]->patchbay;
2323                 if( !patchbay ) continue;
2324                 for( int j=0; j<patchbay->patches.total; ++j ) {
2325                         PatchGUI *patchgui = patchbay->patches.values[j];
2326                         if( !patchgui->mix ) continue;
2327                         if( !track || patchgui->track == track ) {
2328                                 patchgui->mix->update(v>=0 ? v :
2329                                         mwindow->mixer_track_active(patchgui->track));
2330                         }
2331                 }
2332         }
2333 }
2334
2335 void MWindowGUI::stop_transport(const char *lock_msg)
2336 {
2337         if( !mbuttons->transport->is_stopped() ) {
2338                 if( lock_msg ) unlock_window();
2339                 mbuttons->transport->handle_transport(STOP, 1);
2340                 if( lock_msg ) lock_window(lock_msg);
2341         }
2342 }
2343
2344 void MWindowGUI::close_keyvalue_popup()
2345 {
2346         if( !keyvalue_popup ) return;
2347         delete keyvalue_popup;
2348         keyvalue_popup = 0;
2349 }
2350
2351 void MWindowGUI::open_keyvalue_popup(BC_SubWindow *popup)
2352 {
2353         close_keyvalue_popup();
2354         keyvalue_popup = popup;
2355 }
2356
2357 PaneButton::PaneButton(MWindow *mwindow, int x, int y)
2358  : BC_Button(x, y, mwindow->theme->get_image_set("pane"))
2359 {
2360         this->mwindow = mwindow;
2361 }
2362
2363 int PaneButton::cursor_motion_event()
2364 {
2365         if(get_top_level()->get_button_down() &&
2366                 is_event_win() &&
2367                 get_status() == BUTTON_DOWNHI &&
2368                 !cursor_inside())
2369         {
2370 //              printf("PaneButton::cursor_motion_event %d\n", __LINE__);
2371 // create drag bar
2372                 if(get_cursor_x() < 0 && !mwindow->gui->dragging_pane)
2373                 {
2374                         mwindow->gui->start_x_pane_drag();
2375                 }
2376                 else
2377                 if(get_cursor_y() < 0 && !mwindow->gui->dragging_pane)
2378                 {
2379                         mwindow->gui->start_y_pane_drag();
2380                 }
2381         }
2382
2383         mwindow->gui->handle_pane_drag();
2384
2385         int result = BC_Button::cursor_motion_event();
2386         return result;
2387 }
2388
2389 int PaneButton::button_release_event()
2390 {
2391         if( get_buttonpress() != WHEEL_DOWN && get_buttonpress() != WHEEL_UP )
2392                 mwindow->gui->stop_pane_drag();
2393         int result = BC_Button::button_release_event();
2394         return result;
2395 }
2396
2397
2398 FFMpegToggle::FFMpegToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
2399  : BC_Toggle(x, y, mwindow->theme->ffmpeg_toggle,
2400          mwindow->preferences->get_file_probe_armed("FFMPEG_Early") > 0 ? 1 : 0)
2401 {
2402         this->mwindow = mwindow;
2403         this->mbuttons = mbuttons;
2404         set_tooltip(get_value() ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
2405 // *** CONTEXT_HELP ***
2406         context_help_set_keyword("FFmpeg Early Probe Explanation");
2407 }
2408
2409 FFMpegToggle::~FFMpegToggle()
2410 {
2411 }
2412
2413 int FFMpegToggle::handle_event()
2414 {
2415         int ffmpeg_early_probe = get_value();
2416         set_tooltip(ffmpeg_early_probe ? FFMPEG_EARLY_TIP : FFMPEG_LATE_TIP);
2417         mwindow->preferences->set_file_probe_armed("FFMPEG_Early", ffmpeg_early_probe);
2418         mwindow->preferences->set_file_probe_armed("FFMPEG_Late", !ffmpeg_early_probe);
2419         mwindow->update_preferences(mwindow->preferences);
2420         mwindow->show_warning(&mwindow->preferences->warn_indexes,
2421                 _("Changing the base codecs may require rebuilding indexes."));
2422         return 1;
2423 }
2424
2425
2426 StackButton::StackButton(MWindow *mwindow, int x, int y)
2427  : BC_GenericButton(x, y, mwindow->theme->stack_button_w, "0")
2428 {
2429         this->mwindow = mwindow;
2430         set_tooltip(_("Close EDL"));
2431 // *** CONTEXT_HELP ***
2432         context_help_set_keyword("OpenEDL");
2433 }
2434
2435 int StackButton::handle_event()
2436 {
2437         mwindow->save_backup();
2438         mwindow->stack_pop();
2439         return 1;
2440 }
2441
2442 void StackButton::update()
2443 {
2444         char text[BCSTRLEN];
2445         int i = mwindow->stack.size();
2446         sprintf(text, "%d", i);
2447         set_text(text);
2448         draw_face();
2449 }
2450
2451
2452 ProxyToggle::ProxyToggle(MWindow *mwindow, MButtons *mbuttons, int x, int y)
2453  : BC_Toggle(x, y, ( !mwindow->edl->session->proxy_use_scaler ?
2454                         mwindow->theme->proxy_p_toggle :
2455                         mwindow->theme->proxy_s_toggle ),
2456                 mwindow->edl->session->proxy_state == PROXY_DISABLED)
2457 {
2458         this->mwindow = mwindow;
2459         this->mbuttons = mbuttons;
2460         scaler_images = mwindow->edl->session->proxy_use_scaler;
2461         set_tooltip(mwindow->edl->session->proxy_state!=PROXY_DISABLED ?
2462                 _("Disable proxy") : _("Enable proxy"));
2463 // *** CONTEXT_HELP ***
2464         context_help_set_keyword("Proxy");
2465 }
2466
2467 void ProxyToggle::show()
2468 {
2469         int use_scaler = mwindow->edl->session->proxy_use_scaler;
2470         if( scaler_images != use_scaler )
2471                 set_images(!(scaler_images=use_scaler) ?
2472                         mwindow->theme->proxy_p_toggle :
2473                         mwindow->theme->proxy_s_toggle );
2474         draw_face(1, 0);
2475         if( is_hidden() )
2476                 show_window();
2477 }
2478
2479 void ProxyToggle::hide()
2480 {
2481         if( !is_hidden() )
2482                 hide_window();
2483 }
2484
2485 ProxyToggle::~ProxyToggle()
2486 {
2487 }
2488
2489 int ProxyToggle::handle_event()
2490 {
2491         int disabled = get_value();
2492         mwindow->gui->unlock_window();
2493         if( disabled )
2494                 mwindow->disable_proxy();
2495         else
2496                 mwindow->enable_proxy();
2497         mwindow->gui->lock_window("ProxyToggle::handle_event");
2498         set_tooltip(!disabled ? _("Disable proxy") : _("Enable proxy"));
2499         ProxyDialog *dialog = mwindow->gui->mainmenu->proxy->dialog;
2500         if( dialog && dialog->gui ) {
2501                 dialog->gui->lock_window("ProxyToggle::handle_event");
2502                 dialog->gui->update();
2503                 dialog->gui->unlock_window();
2504         }
2505         return 1;
2506 }
2507
2508 int ProxyToggle::keypress_event()
2509 {
2510         if( ctrl_down() && !shift_down() && !alt_down() ) {
2511                 int key = get_keypress();
2512                 if( key == 'r' ) {
2513                         int value = get_value() ? 0 : 1;
2514                         set_value(value);
2515                         return handle_event();
2516                 }
2517         }
2518         return context_help_check_and_show();
2519 }
2520