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