Fourth set of 50 GPL attribution for CV-Contributors added +
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / timebar.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  * Copyright (C) 2003-2016 Cinelerra CV contributors
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include "awindow.h"
24 #include "awindowgui.h"
25 #include "bcsignals.h"
26 #include "clip.h"
27 #include "cplayback.h"
28 #include "cursors.h"
29 #include "cwindow.h"
30 #include "cwindowgui.h"
31 #include "edl.h"
32 #include "edlsession.h"
33 #include "filexml.h"
34 #include "fonts.h"
35 #include "labels.h"
36 #include "labeledit.h"
37 #include "localsession.h"
38 #include "maincursor.h"
39 #include "mainundo.h"
40 #include "mbuttons.h"
41 #include "mwindow.h"
42 #include "mwindowgui.h"
43 #include "patchbay.h"
44 #include "preferences.h"
45 #include "recordlabel.h"
46 #include "localsession.h"
47 #include "mainsession.h"
48 #include "theme.h"
49 #include "timebar.h"
50 #include "timelinepane.h"
51 #include "trackcanvas.h"
52 #include "tracks.h"
53 #include "transportque.h"
54 #include "units.h"
55 #include "vframe.h"
56 #include "vwindow.h"
57 #include "vwindowgui.h"
58 #include "zoombar.h"
59
60
61 LabelGUI::LabelGUI(MWindow *mwindow, TimeBar *timebar,
62         int64_t pixel, int y,
63         double position, VFrame **data)
64  : BC_Toggle(translate_pixel(mwindow, pixel), y,
65                 data ? data : mwindow->theme->label_toggle, 0)
66 {
67         this->mwindow = mwindow;
68         this->timebar = timebar;
69         this->gui = 0;
70         this->pixel = pixel;
71         this->position = position;
72         this->label = 0;
73 }
74
75 LabelGUI::~LabelGUI()
76 {
77         if( timebar->drag_label == this )
78                 timebar->drag_label = 0;
79 }
80
81 int LabelGUI::get_y(MWindow *mwindow, TimeBar *timebar)
82 {
83         return timebar->get_h() -
84                 mwindow->theme->label_toggle[0]->get_h();
85 }
86
87 int LabelGUI::translate_pixel(MWindow *mwindow, int pixel)
88 {
89         int result = pixel - mwindow->theme->label_toggle[0]->get_w() / 2;
90         return result;
91 }
92
93 void LabelGUI::reposition(int flush)
94 {
95         reposition_window(translate_pixel(mwindow, pixel),
96                 BC_Toggle::get_y());
97 }
98
99 int LabelGUI::button_press_event()
100 {
101         int result = test_drag_label(1);
102
103         if( this->is_event_win() && get_buttonpress() == 3 ) {
104                 if( label ) {
105                         int cur_x, cur_y;
106                         get_abs_cursor(cur_x, cur_y, 0);
107                         timebar->label_edit->start(label, cur_x, cur_y);
108                 }
109                 result = 1;
110         } else {
111                 result = BC_Toggle::button_press_event();
112         }
113         if( label )
114                 set_tooltip(this->label->textstr);
115         return result;
116 }
117
118 int LabelGUI::button_release_event()
119 {
120         int ret = BC_Toggle::button_release_event();
121         test_drag_label(0);
122         return ret;
123 }
124
125 int LabelGUI::test_drag_label(int press)
126 {
127         if( is_event_win() && get_buttonpress() == 1 ) {
128                 switch( timebar->current_operation ) {
129                 case TIMEBAR_NONE:
130                         if( press && get_value() ) {
131                                 timebar->current_operation = TIMEBAR_DRAG_LABEL;
132                                 timebar->drag_label = this;
133                                 set_cursor(HSEPARATE_CURSOR, 0, 0);
134                                 mwindow->undo->update_undo_before(_("drag label"), this);
135                                 return 1;
136                         }
137                         break;
138                 case TIMEBAR_DRAG_LABEL:
139                         if( !press ) {
140                                 timebar->current_operation = TIMEBAR_NONE;
141                                 timebar->drag_label = 0;
142                                 set_cursor(ARROW_CURSOR, 0, 0);
143                                 mwindow->undo->update_undo_after(_("drag label"), LOAD_TIMEBAR);
144                                 mwindow->awindow->gui->async_update_assets(); // labels folder
145                         }
146                         break;
147                 }
148         }
149         return 0;
150 }
151
152 int LabelGUI::handle_event()
153 {
154         timebar->select_label(position);
155         return 1;
156 }
157
158 void LabelGUI::update_value()
159 {
160         EDL *edl = timebar->get_edl();
161         double start = edl->local_session->get_selectionstart(1);
162         double end = edl->local_session->get_selectionend(1);
163         int v = ( label->position >= start && end >= label->position ) ||
164             edl->equivalent(label->position, start) ||
165             edl->equivalent(label->position, end) ||
166             timebar->drag_label == this ? 1 : 0;
167         update(v);
168 }
169
170
171 InPointGUI::InPointGUI(MWindow *mwindow, TimeBar *timebar,
172         int64_t pixel, double position)
173  : LabelGUI(mwindow, timebar,
174         pixel, get_y(mwindow, timebar),
175         position, mwindow->theme->in_point)
176 {
177 //printf("InPointGUI::InPointGUI %d %d\n", pixel, get_y(mwindow, timebar));
178 }
179 InPointGUI::~InPointGUI()
180 {
181 }
182 int InPointGUI::get_y(MWindow *mwindow, TimeBar *timebar)
183 {
184         int result;
185         result = timebar->get_h() -
186                 mwindow->theme->in_point[0]->get_h();
187         return result;
188 }
189
190
191 OutPointGUI::OutPointGUI(MWindow *mwindow, TimeBar *timebar,
192         int64_t pixel, double position)
193  : LabelGUI(mwindow, timebar,
194         pixel, get_y(mwindow, timebar),
195         position, mwindow->theme->out_point)
196 {
197 //printf("OutPointGUI::OutPointGUI %d %d\n", pixel, get_y(mwindow, timebar));
198 }
199 OutPointGUI::~OutPointGUI()
200 {
201 }
202 int OutPointGUI::get_y(MWindow *mwindow, TimeBar *timebar)
203 {
204         return timebar->get_h() -
205                 mwindow->theme->out_point[0]->get_h();
206 }
207
208
209 PresentationGUI::PresentationGUI(MWindow *mwindow, TimeBar *timebar,
210         int64_t pixel, double position)
211  : LabelGUI(mwindow, timebar, pixel, get_y(mwindow, timebar), position)
212 {
213 }
214 PresentationGUI::~PresentationGUI()
215 {
216 }
217
218 TimeBar::TimeBar(MWindow *mwindow, BC_WindowBase *gui,
219         int x, int y, int w, int h)
220  : BC_SubWindow(x, y, w, h)
221 {
222 //printf("TimeBar::TimeBar %d %d %d %d\n", x, y, w, h);
223         this->gui = gui;
224         this->mwindow = mwindow;
225         this->drag_label = 0;
226         label_edit = new LabelEdit(mwindow, mwindow->awindow, 0);
227         pane = 0;
228         highlighted = 0;
229 }
230
231 TimeBar::~TimeBar()
232 {
233         delete in_point;
234         delete out_point;
235         delete label_edit;
236         labels.remove_all_objects();
237         presentations.remove_all_objects();
238 }
239
240 void TimeBar::create_objects()
241 {
242         in_point = 0;
243         out_point = 0;
244 //printf("TimeBar::create_objects %d\n", __LINE__);
245         current_operation = TIMEBAR_NONE;
246         set_cursor(UPRIGHT_ARROW_CURSOR, 0, 0);
247         update(0);
248 }
249
250
251 int64_t TimeBar::position_to_pixel(double position)
252 {
253         get_edl_length();
254         return (int64_t)(position / time_per_pixel);
255 }
256
257
258 double TimeBar::pixel_to_position(int pixel)
259 {
260         if( pane ) {
261                 pixel += get_edl()->local_session->view_start[pane->number];
262         }
263
264         return (double)pixel *
265                 get_edl()->local_session->zoom_sample /
266                 get_edl()->session->sample_rate;
267 }
268
269 void TimeBar::update_labels()
270 {
271         int output = 0;
272         EDL *edl = get_edl();
273
274         if( edl ) {
275                 for( Label *current=edl->labels->first; current; current=NEXT ) {
276                         int64_t pixel = position_to_pixel(current->position);
277                         if( pixel >= 0 && pixel < get_w()  ) {
278 // Create new label
279                                 if( output >= labels.total ) {
280                                         LabelGUI *new_label;
281                                         add_subwindow(new_label = new LabelGUI(mwindow, this,
282                                                         pixel, LabelGUI::get_y(mwindow, this),
283                                                         current->position));
284                                         new_label->set_cursor(INHERIT_CURSOR, 0, 0);
285                                         new_label->set_tooltip(current->textstr);
286                                         new_label->label = current;
287                                         labels.append(new_label);
288                                 }
289 // Reposition old label
290                                 else {
291                                         LabelGUI *gui = labels.values[output];
292                                         if( gui->pixel != pixel ) {
293                                                 gui->pixel = pixel;
294                                                 gui->reposition(0);
295                                         }
296 //                                      else {
297 //                                              gui->draw_face(1,0);
298 //                                      }
299
300                                         labels.values[output]->position = current->position;
301                                         labels.values[output]->set_tooltip(current->textstr);
302                                         labels.values[output]->label = current;
303                                 }
304
305                                 labels.values[output++]->update_value();
306                         }
307                 }
308         }
309
310 // Delete excess labels
311         while(labels.total > output)
312         {
313                 labels.remove_object();
314         }
315
316 // Get the labels to show
317         show_window(0);
318 }
319
320 void TimeBar::update_highlights()
321 {
322         EDL *edl = get_edl();
323         if( !edl ) return;
324         for( int i = 0; i < labels.total; i++ ) {
325                 labels.values[i]->update_value();
326         }
327
328         if( edl->equivalent(edl->local_session->get_inpoint(),
329                         edl->local_session->get_selectionstart(1)) ||
330                 edl->equivalent(edl->local_session->get_inpoint(),
331                         edl->local_session->get_selectionend(1)) ) {
332                 if( in_point ) in_point->update(1);
333         }
334         else
335                 if( in_point ) in_point->update(0);
336
337         if( edl->equivalent(edl->local_session->get_outpoint(),
338                         edl->local_session->get_selectionstart(1)) ||
339                 edl->equivalent(edl->local_session->get_outpoint(),
340                         edl->local_session->get_selectionend(1)) ) {
341                 if( out_point ) out_point->update(1);
342         }
343         else
344                 if( out_point ) out_point->update(0);
345
346         draw_inout_highlight();
347 }
348
349 void TimeBar::draw_inout_highlight()
350 {
351         EDL *edl = get_edl();
352         if( !edl->local_session->inpoint_valid() ) return;
353         if( !edl->local_session->outpoint_valid() ) return;
354         double in_position = edl->local_session->get_inpoint();
355         double out_position = edl->local_session->get_outpoint();
356         if( in_position >= out_position ) return;
357         int in_x = position_to_pixel(in_position);
358         int out_x = position_to_pixel(out_position);
359         CLAMP(in_x, 0, get_w());
360         CLAMP(out_x, 0, get_w());
361         set_color(mwindow->theme->inout_highlight_color);
362         int lw = xS(5);
363         set_line_width(lw);
364         set_inverse();
365         draw_line(in_x, get_h()-2*lw, out_x, get_h()-2*lw);
366         set_opaque();
367         set_line_width(1);
368 }
369
370 void TimeBar::update_points()
371 {
372         EDL *edl = get_edl();
373         int64_t pixel = !edl ? 0 :
374                 position_to_pixel(edl->local_session->get_inpoint());
375
376         if( in_point ) {
377                 if( edl && edl->local_session->inpoint_valid() &&
378                     pixel >= 0 && pixel < get_w() ) {
379                         if( !EQUIV(edl->local_session->get_inpoint(), in_point->position) ||
380                             in_point->pixel != pixel ) {
381                                 in_point->pixel = pixel;
382                                 in_point->position = edl->local_session->get_inpoint();
383                                 in_point->reposition(0);
384                         }
385                         else {
386                                 in_point->draw_face(1, 0);
387                         }
388                 }
389                 else {
390                         delete in_point;
391                         in_point = 0;
392                 }
393         }
394         else
395         if( edl && edl->local_session->inpoint_valid() &&
396             pixel >= 0 && pixel < get_w() ) {
397                 add_subwindow(in_point = new InPointGUI(mwindow,
398                         this, pixel, edl->local_session->get_inpoint()));
399                 in_point->set_cursor(ARROW_CURSOR, 0, 0);
400         }
401
402         pixel = !edl ? 0 :
403                  position_to_pixel(edl->local_session->get_outpoint());
404
405         if( out_point ) {
406                 if( edl && edl->local_session->outpoint_valid() &&
407                     pixel >= 0 && pixel < get_w()) {
408                         if( !EQUIV(edl->local_session->get_outpoint(), out_point->position) ||
409                             out_point->pixel != pixel ) {
410                                 out_point->pixel = pixel;
411                                 out_point->position = edl->local_session->get_outpoint();
412                                 out_point->reposition(0);
413                         }
414                         else {
415                                 out_point->draw_face(1, 0);
416                         }
417                 }
418                 else {
419                         delete out_point;
420                         out_point = 0;
421                 }
422         }
423         else
424         if( edl && edl->local_session->outpoint_valid() &&
425             pixel >= 0 && pixel < get_w() ) {
426                 add_subwindow(out_point = new OutPointGUI(mwindow,
427                         this, pixel, edl->local_session->get_outpoint()));
428                 out_point->set_cursor(ARROW_CURSOR, 0, 0);
429         }
430
431 //      flush();
432 }
433
434 void TimeBar::update_clock(double position)
435 {
436 }
437
438 void TimeBar::update(int flush)
439 {
440         draw_time();
441 // Need to redo these when range is drawn to get the background updated.
442         update_labels();
443         update_points();
444
445
446         EDL *edl = get_edl();
447         int64_t pixel = -1;
448         int x = get_relative_cursor_x();
449 // Draw highlight position
450         if( edl && (highlighted || current_operation == TIMEBAR_DRAG) &&
451             x >= 0 && x < get_w() ) {
452 //printf("TimeBar::update %d %d\n", __LINE__, x);
453                 double position = pixel_to_position(x);
454
455                 position = mwindow->edl->align_to_frame(position, 0);
456                 pixel = position_to_pixel(position);
457                 update_clock(position);
458         }
459
460         if( pixel < 0 ) {
461                 double position = test_highlight();
462                 if( position >= 0 ) pixel = position_to_pixel(position);
463         }
464
465
466         if( pixel >= 0 && pixel < get_w() ) {
467                 set_color(mwindow->theme->timebar_cursor_color);
468                 set_line_dashes(1);
469 //printf("TimeBar::update %d pane=%d pixel=%jd\n", __LINE__, pane->number, pixel);
470                 draw_line(pixel, 0, pixel, get_h());
471                 set_line_dashes(0);
472         }
473
474
475         if( edl ) {
476                 double playback_start = edl->local_session->playback_start;
477                 if( playback_start >= 0 ) {
478                         int64_t pixel = position_to_pixel(playback_start);
479                         set_color(mwindow->theme->timebar_cursor_color ^ 0x0000ff);
480                         draw_line(pixel, 0, pixel, get_h());
481                         double playback_end = edl->local_session->playback_end;
482                         if( playback_end > playback_start ) {
483                                 pixel = position_to_pixel(playback_end);
484                                 set_color(mwindow->theme->timebar_cursor_color ^ 0x00ff00);
485                                 draw_line(pixel, 0, pixel, get_h());
486                         }
487                 }
488
489                 double position = edl->local_session->get_selectionstart(1);
490                 int64_t pixel = position_to_pixel(position);
491 // Draw insertion point position.
492                 int color = mwindow->theme->timebar_cursor_color;
493                 if( mwindow->preferences->forward_render_displacement )
494                         color ^= 0x00ffff;
495                 set_color(color);
496                 draw_line(pixel, 0, pixel, get_h());
497         }
498
499         update_highlights();
500
501 // Get the labels to show
502         show_window(0);
503         flash(flush);
504 //printf("TimeBar::update %d this=%p %d\n", __LINE__, this, current_operation);
505 }
506
507
508
509 int TimeBar::delete_project()
510 {
511 //      labels->delete_all();
512         return 0;
513 }
514
515 int TimeBar::save(FileXML *xml)
516 {
517 //      labels->save(xml);
518         return 0;
519 }
520
521
522
523
524 void TimeBar::draw_time()
525 {
526 }
527
528 EDL* TimeBar::get_edl()
529 {
530         return mwindow->edl;
531 }
532
533
534
535 void TimeBar::draw_range()
536 {
537 //printf("TimeBar::draw_range %d %p\n", __LINE__, get_edl());
538         if( has_preview() && get_edl() ) {
539                 int x1, x2;
540                 get_preview_pixels(x1, x2);
541                 draw_3segmenth(0, 0, x1, mwindow->theme->timebar_view_data);
542                 draw_top_background(get_parent(), x1, 0, x2 - x1, get_h());
543                 draw_3segmenth(x2, 0, get_w() - x2, mwindow->theme->timebar_view_data);
544
545                 set_color(BLACK);
546                 draw_line(x1, 0, x1, get_h());
547                 draw_line(x2, 0, x2, get_h());
548
549
550                 EDL *edl = get_edl();
551                 if( edl ) {
552                         int64_t pixel = position_to_pixel(
553                                 edl->local_session->get_selectionstart(1));
554 // Draw insertion point position if this timebar belongs to a window which
555 // has something other than the master EDL.
556                         set_color(mwindow->theme->timebar_cursor_color);
557                         draw_line(pixel, 0, pixel, get_h());
558                 }
559         }
560         else
561                 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
562 }
563
564 void TimeBar::select_label(double position)
565 {
566 }
567
568
569
570 int TimeBar::draw()
571 {
572         return 0;
573 }
574
575 double TimeBar::get_edl_length()
576 {
577         edl_length = get_edl() ? get_edl()->tracks->total_length() : 0;
578         int w1 = get_w()-1;
579         time_per_pixel = !EQUIV(edl_length, 0) ? edl_length/w1 : w1;
580         return edl_length;
581 }
582
583 int TimeBar::get_preview_pixels(int &x1, int &x2)
584 {
585         x1 = 0;  x2 = get_w();
586         get_edl_length();
587         EDL *edl = get_edl();
588         if( edl && !EQUIV(edl_length, 0) ) {
589                 double preview_start = edl->local_session->preview_start;
590                 double preview_end = edl->local_session->preview_end;
591                 if( preview_end < 0 || preview_end > edl_length )
592                         preview_end = edl_length;
593                 if( preview_end >= preview_start ) {
594                         x1 = (int)(preview_start / time_per_pixel);
595                         x2 = (int)(preview_end / time_per_pixel);
596                 }
597         }
598         return 0;
599 }
600
601
602 int TimeBar::test_preview(int buttonpress)
603 {
604         int result = 0;
605
606
607         if( get_edl() && cursor_inside() && buttonpress >= 0 ) {
608                 int x1, x2, x = get_relative_cursor_x();
609                 get_preview_pixels(x1, x2);
610 //printf("TimeBar::test_preview %d %d %d\n", x1, x2, x);
611 // Inside left handle
612                 if( x >= x1 - HANDLE_W && x < x1 + HANDLE_W &&
613 // Ignore left handle if both handles are up against the left side
614                     x2 > HANDLE_W ) {
615                         if( buttonpress ) {
616                                 current_operation = TIMEBAR_DRAG_LEFT;
617                                 start_position = get_edl()->local_session->preview_start;
618                                 start_cursor_x = x;
619                         }
620                         else if( get_cursor() != LEFT_CURSOR )
621                                 set_cursor(LEFT_CURSOR, 0, 1);
622                         result = 1;
623                 }
624 // Inside right handle
625                 else if( x >= x2 - HANDLE_W && x < x2 + HANDLE_W &&
626 // Ignore right handle if both handles are up against the right side
627                     x1 < get_w() - HANDLE_W ) {
628                         if( buttonpress ) {
629                                 current_operation = TIMEBAR_DRAG_RIGHT;
630                                 start_position = get_edl()->local_session->preview_end;
631                                 if( start_position < 0 || start_position > edl_length )
632                                         start_position = edl_length;
633                                 start_cursor_x = x;
634                         }
635                         else if( get_cursor() != RIGHT_CURSOR )
636                                 set_cursor(RIGHT_CURSOR, 0, 1);
637                         result = 1;
638                 }
639 // Inside preview
640                 else if( get_button_down() && get_buttonpress() == 3 &&
641                     x >= x1 && x < x2 ) {
642                         if( buttonpress ) {
643                                 current_operation = TIMEBAR_DRAG_CENTER;
644                                 starting_start_position = get_edl()->local_session->preview_start;
645                                 starting_end_position = get_edl()->local_session->preview_end;
646                                 if( starting_end_position < 0 || starting_end_position > edl_length )
647                                         starting_end_position = edl_length;
648                                 start_cursor_x = x;
649                         }
650                         if( get_cursor() != HSEPARATE_CURSOR )
651                                 set_cursor(HSEPARATE_CURSOR, 0, 1);
652                         result = 1;
653                 }
654         }
655
656         if( !result && get_cursor() != ARROW_CURSOR )
657                 set_cursor(ARROW_CURSOR, 0, 1);
658
659
660         return result;
661 }
662
663 int TimeBar::move_preview(int &redraw)
664 {
665         int result = 0, x = get_relative_cursor_x();
666         switch( current_operation ) {
667         case TIMEBAR_DRAG_LEFT: {
668                 get_edl()->local_session->preview_start =
669                         start_position + time_per_pixel * (x - start_cursor_x);
670                 double preview_end = get_edl()->local_session->preview_end;
671                 if( preview_end < 0 || preview_end > edl_length )
672                         preview_end = get_edl()->local_session->preview_end = edl_length;
673                 CLAMP(get_edl()->local_session->preview_start, 0, preview_end);
674                 result = 1;
675                 break; }
676         case TIMEBAR_DRAG_RIGHT: {
677                 double preview_end = get_edl()->local_session->preview_end =
678                         start_position + time_per_pixel * (x - start_cursor_x);
679                 double preview_start = get_edl()->local_session->preview_start;
680                 if( preview_end >= edl_length && !preview_start ) {
681                         get_edl()->local_session->preview_end = -1;
682                         if( preview_start > preview_end )
683                                 preview_start = get_edl()->local_session->preview_start = preview_end;
684                 }
685                 else
686                         CLAMP(get_edl()->local_session->preview_end, preview_start, edl_length);
687                 result = 1;
688                 break; }
689         case TIMEBAR_DRAG_CENTER: {
690                 double dt = time_per_pixel * (x - start_cursor_x);
691                 get_edl()->local_session->preview_start = starting_start_position + dt;
692                 get_edl()->local_session->preview_end = starting_end_position + dt;
693                 if( get_edl()->local_session->preview_start < 0 ) {
694                         get_edl()->local_session->preview_end -= get_edl()->local_session->preview_start;
695                         get_edl()->local_session->preview_start = 0;
696                 }
697                 else
698                 if( get_edl()->local_session->preview_end > edl_length ) {
699                         get_edl()->local_session->preview_start -= get_edl()->local_session->preview_end - edl_length;
700                         get_edl()->local_session->preview_end = edl_length;
701                 }
702                 result = 1;
703                 break; }
704         }
705
706 //printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation);
707
708         if( result ) {
709                 update_preview();
710                 redraw = 1;
711         }
712 //printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation);
713
714         return result;
715 }
716
717 void TimeBar::update_preview()
718 {
719 }
720
721 int TimeBar::samplemovement()
722 {
723         return 0;
724 }
725
726 void TimeBar::stop_playback()
727 {
728 }
729
730 int TimeBar::button_press_event()
731 {
732         int result = 0;
733         if( is_event_win() && cursor_above() ) {
734                 if( has_preview() && get_buttonpress() == 3 ) {
735                         result = test_preview(1);
736                 }
737 // Change time format
738                 else if( !is_vwindow() && ctrl_down() ) {
739                         if( get_buttonpress() == 1 )
740                                 mwindow->next_time_format();
741                         else
742                         if( get_buttonpress() == 2 )
743                                 mwindow->prev_time_format();
744                         result = 1;
745                 }
746                 else if( get_buttonpress() == 1 ) {
747                         stop_playback();
748
749 // Select region between two labels
750                         if( !is_vwindow() && get_double_click() &&
751                             get_edl()->labels->first ) {
752                                 int x = get_relative_cursor_x();
753                                 double position = pixel_to_position(x);
754 // Test labels
755                                 select_region(position);
756                         }
757                         else {
758
759 // Reposition highlight cursor
760                                 update_cursor();
761                                 current_operation = TIMEBAR_DRAG;
762                                 activate_timeline();
763                         }
764                         result = 1;
765                 }
766         }
767         return result;
768 }
769
770 void TimeBar::activate_timeline()
771 {
772         mwindow->gui->activate_timeline();
773 }
774
775 int TimeBar::cursor_motion_event()
776 {
777         int result = 0;
778         int redraw = 0;
779
780         switch( current_operation ) {
781         case TIMEBAR_DRAG_LEFT:
782         case TIMEBAR_DRAG_RIGHT:
783         case TIMEBAR_DRAG_CENTER:
784                 if( has_preview() )
785                         result = move_preview(redraw);
786                 break;
787
788         case TIMEBAR_DRAG_LABEL:
789                 if( drag_label ) {
790                         EDL *edl = get_edl();
791                         int pixel = get_relative_cursor_x();
792                         double position = pixel_to_position(pixel);
793                         if( drag_label->label )
794                                 drag_label->label->position = position;
795                         else if( drag_label == in_point ) {
796                                 if( out_point && edl->local_session->outpoint_valid() ) {
797                                         double out_pos = edl->local_session->get_outpoint();
798                                         if( position > out_pos ) {
799                                                 edl->local_session->set_outpoint(position);
800                                                 drag_label = out_point;
801                                                 position = out_pos;
802                                         }
803                                 }
804                                 edl->local_session->set_inpoint(position);
805                         }
806                         else if( drag_label == out_point ) {
807                                 if( in_point && edl->local_session->inpoint_valid() ) {
808                                         double in_pos = edl->local_session->get_inpoint();
809                                         if( position < in_pos ) {
810                                                 edl->local_session->set_inpoint(position);
811                                                 drag_label = in_point;
812                                                 position = in_pos;
813                                         }
814                                 }
815                                 edl->local_session->set_outpoint(position);
816                         }
817                 }
818         // fall thru
819         case TIMEBAR_DRAG:
820                 update_cursor();
821                 handle_mwindow_drag();
822                 result = 1;
823                 break;
824
825         default:
826                 if( has_preview() )
827                         result = test_preview(0);
828                 break;
829         }
830
831
832         if( redraw ) {
833                 update(1);
834         }
835
836         return result;
837 }
838
839 int TimeBar::cursor_leave_event()
840 {
841         if( highlighted ) {
842                 highlighted = 0;
843                 update(1);
844         }
845         return 0;
846 }
847
848 int TimeBar::button_release_event()
849 {
850 //printf("TimeBar::button_release_event %d %d\n", __LINE__, current_operation);
851         int result = 0;
852         int need_redraw = 0;
853         switch( current_operation ) {
854         case TIMEBAR_DRAG: {
855                 mwindow->gui->get_focused_pane()->canvas->stop_dragscroll();
856                 current_operation = TIMEBAR_NONE;
857                 need_redraw = 1;
858                 CWindowCanvas *canvas = mwindow->cwindow->gui->canvas;
859                 canvas->draw_scope(canvas->refresh_frame, -1);
860                 result = 1;
861                 break; }
862         default:
863                 if( current_operation != TIMEBAR_NONE ) {
864                         current_operation = TIMEBAR_NONE;
865                         result = 1;
866                 }
867                 break;
868         }
869
870         if( (!cursor_above() && highlighted) || need_redraw ) {
871                 highlighted = 0;
872                 update(1);
873         }
874
875         return result;
876 }
877
878 // Update the selection cursor during a dragging operation
879 void TimeBar::update_cursor()
880 {
881 }
882
883 void TimeBar::handle_mwindow_drag()
884 {
885 }
886
887 int TimeBar::select_region(double position)
888 {
889         Label *start = 0, *end = 0, *current;
890         for( current = get_edl()->labels->first; current; current = NEXT ) {
891                 if( current->position > position ) {
892                         end = current;
893                         break;
894                 }
895         }
896
897         for( current = get_edl()->labels->last ; current; current = PREVIOUS ) {
898                 if( current->position <= position ) {
899                         start = current;
900                         break;
901                 }
902         }
903
904 // Select region
905         if( end != start ) {
906                 if( !start )
907                         get_edl()->local_session->set_selectionstart(0);
908                 else
909                         get_edl()->local_session->set_selectionstart(start->position);
910
911                 if( !end )
912                         get_edl()->local_session->set_selectionend(get_edl()->tracks->total_length());
913                 else
914                         get_edl()->local_session->set_selectionend(end->position);
915         }
916         else
917         if( end || start ) {
918                 get_edl()->local_session->set_selectionstart(start->position);
919                 get_edl()->local_session->set_selectionend(start->position);
920         }
921
922 // Que the CWindow
923         unlock_window();
924         mwindow->cwindow->update(1, 0, 0);
925         mwindow->gui->lock_window("TimeBar::select_region 3");
926         mwindow->gui->hide_cursor(0);
927         mwindow->gui->draw_cursor(1);
928         mwindow->gui->flash_canvas(0);
929         mwindow->gui->activate_timeline();
930         mwindow->gui->zoombar->update();
931         mwindow->gui->unlock_window();
932         lock_window("TimeBar::select_region 4");
933         update_highlights();
934         return 0;
935 }
936
937
938 int TimeBar::delete_arrows()
939 {
940         return 0;
941 }
942
943 double TimeBar::test_highlight()
944 {
945         return -1;
946 }
947
948