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