4 * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "bcsignals.h"
24 #include "cplayback.h"
28 #include "edlsession.h"
32 #include "labeledit.h"
33 #include "localsession.h"
34 #include "maincursor.h"
38 #include "mwindowgui.h"
40 #include "preferences.h"
41 #include "recordlabel.h"
42 #include "localsession.h"
43 #include "mainsession.h"
46 #include "timelinepane.h"
47 #include "trackcanvas.h"
49 #include "transportque.h"
53 #include "vwindowgui.h"
57 LabelGUI::LabelGUI(MWindow *mwindow, TimeBar *timebar,
59 double position, VFrame **data)
60 : BC_Toggle(translate_pixel(mwindow, pixel), y,
61 data ? data : mwindow->theme->label_toggle, 0)
63 this->mwindow = mwindow;
64 this->timebar = timebar;
67 this->position = position;
75 int LabelGUI::get_y(MWindow *mwindow, TimeBar *timebar)
77 return timebar->get_h() -
78 mwindow->theme->label_toggle[0]->get_h();
81 int LabelGUI::translate_pixel(MWindow *mwindow, int pixel)
83 int result = pixel - mwindow->theme->label_toggle[0]->get_w() / 2;
87 void LabelGUI::reposition(int flush)
89 reposition_window(translate_pixel(mwindow, pixel),
93 int LabelGUI::button_press_event()
97 if( this->is_event_win() && get_buttonpress() == 3 ) {
100 get_abs_cursor_xy(cur_x, cur_y, 0);
101 timebar->label_edit->start(label, cur_x, cur_y);
105 result = BC_Toggle::button_press_event();
108 set_tooltip(this->label->textstr);
112 int LabelGUI::handle_event()
114 timebar->select_label(position);
119 InPointGUI::InPointGUI(MWindow *mwindow, TimeBar *timebar,
120 int64_t pixel, double position)
121 : LabelGUI(mwindow, timebar,
122 pixel, get_y(mwindow, timebar),
123 position, mwindow->theme->in_point)
125 //printf("InPointGUI::InPointGUI %d %d\n", pixel, get_y(mwindow, timebar));
127 InPointGUI::~InPointGUI()
130 int InPointGUI::get_y(MWindow *mwindow, TimeBar *timebar)
133 result = timebar->get_h() -
134 mwindow->theme->in_point[0]->get_h();
139 OutPointGUI::OutPointGUI(MWindow *mwindow, TimeBar *timebar,
140 int64_t pixel, double position)
141 : LabelGUI(mwindow, timebar,
142 pixel, get_y(mwindow, timebar),
143 position, mwindow->theme->out_point)
145 //printf("OutPointGUI::OutPointGUI %d %d\n", pixel, get_y(mwindow, timebar));
147 OutPointGUI::~OutPointGUI()
150 int OutPointGUI::get_y(MWindow *mwindow, TimeBar *timebar)
152 return timebar->get_h() -
153 mwindow->theme->out_point[0]->get_h();
157 PresentationGUI::PresentationGUI(MWindow *mwindow, TimeBar *timebar,
158 int64_t pixel, double position)
159 : LabelGUI(mwindow, timebar, pixel, get_y(mwindow, timebar), position)
162 PresentationGUI::~PresentationGUI()
166 TimeBar::TimeBar(MWindow *mwindow, BC_WindowBase *gui,
167 int x, int y, int w, int h)
168 : BC_SubWindow(x, y, w, h)
170 //printf("TimeBar::TimeBar %d %d %d %d\n", x, y, w, h);
172 this->mwindow = mwindow;
173 label_edit = new LabelEdit(mwindow, mwindow->awindow, 0);
183 labels.remove_all_objects();
184 presentations.remove_all_objects();
187 void TimeBar::create_objects()
191 //printf("TimeBar::create_objects %d\n", __LINE__);
192 current_operation = TIMEBAR_NONE;
193 set_cursor(UPRIGHT_ARROW_CURSOR, 0, 0);
198 int64_t TimeBar::position_to_pixel(double position)
201 return (int64_t)(position / time_per_pixel);
205 double TimeBar::pixel_to_position(int pixel)
208 pixel += mwindow->edl->local_session->view_start[pane->number];
211 return (double)pixel *
212 mwindow->edl->local_session->zoom_sample /
213 mwindow->edl->session->sample_rate;
216 void TimeBar::update_labels()
219 EDL *edl = get_edl();
222 for( Label *current=edl->labels->first; current; current=NEXT ) {
223 int64_t pixel = position_to_pixel(current->position);
224 if( pixel >= 0 && pixel < get_w() ) {
226 if( output >= labels.total ) {
228 add_subwindow(new_label =
229 new LabelGUI(mwindow,
232 LabelGUI::get_y(mwindow, this),
234 new_label->set_cursor(INHERIT_CURSOR, 0, 0);
235 new_label->set_tooltip(current->textstr);
236 new_label->label = current;
237 labels.append(new_label);
240 // Reposition old label
242 LabelGUI *gui = labels.values[output];
243 if( gui->pixel != pixel ) {
251 labels.values[output]->position = current->position;
252 labels.values[output]->set_tooltip(current->textstr);
253 labels.values[output]->label = current;
256 if( edl->local_session->get_selectionstart(1) <= current->position &&
257 edl->local_session->get_selectionend(1) >= current->position )
258 labels.values[output]->update(1);
260 if( labels.values[output]->get_value() )
261 labels.values[output]->update(0);
268 // Delete excess labels
269 while(labels.total > output)
271 labels.remove_object();
274 // Get the labels to show
278 void TimeBar::update_highlights()
280 for( int i = 0; i < labels.total; i++ ) {
281 LabelGUI *label = labels.values[i];
282 if( mwindow->edl->equivalent(label->position,
283 mwindow->edl->local_session->get_selectionstart(1)) ||
284 mwindow->edl->equivalent(label->position,
285 mwindow->edl->local_session->get_selectionend(1)) ) {
286 if( !label->get_value() ) label->update(1);
289 if( label->get_value() ) label->update(0);
292 if( mwindow->edl->equivalent(mwindow->edl->local_session->get_inpoint(),
293 mwindow->edl->local_session->get_selectionstart(1)) ||
294 mwindow->edl->equivalent(mwindow->edl->local_session->get_inpoint(),
295 mwindow->edl->local_session->get_selectionend(1)) ) {
296 if( in_point ) in_point->update(1);
299 if( in_point ) in_point->update(0);
301 if( mwindow->edl->equivalent(mwindow->edl->local_session->get_outpoint(),
302 mwindow->edl->local_session->get_selectionstart(1)) ||
303 mwindow->edl->equivalent(mwindow->edl->local_session->get_outpoint(),
304 mwindow->edl->local_session->get_selectionend(1)) ) {
305 if( out_point ) out_point->update(1);
308 if( out_point ) out_point->update(0);
311 void TimeBar::update_points()
313 EDL *edl = get_edl();
314 int64_t pixel = !edl ? 0 :
315 position_to_pixel(edl->local_session->get_inpoint());
318 if( edl && edl->local_session->inpoint_valid() &&
319 pixel >= 0 && pixel < get_w() ) {
320 if( !EQUIV(edl->local_session->get_inpoint(), in_point->position) ||
321 in_point->pixel != pixel ) {
322 in_point->pixel = pixel;
323 in_point->position = edl->local_session->get_inpoint();
324 in_point->reposition(0);
327 in_point->draw_face(1, 0);
336 if( edl && edl->local_session->inpoint_valid() &&
337 pixel >= 0 && pixel < get_w() ) {
338 add_subwindow(in_point = new InPointGUI(mwindow,
339 this, pixel, edl->local_session->get_inpoint()));
340 in_point->set_cursor(ARROW_CURSOR, 0, 0);
344 position_to_pixel(edl->local_session->get_outpoint());
347 if( edl && edl->local_session->outpoint_valid() &&
348 pixel >= 0 && pixel < get_w()) {
349 if( !EQUIV(edl->local_session->get_outpoint(), out_point->position) ||
350 out_point->pixel != pixel ) {
351 out_point->pixel = pixel;
352 out_point->position = edl->local_session->get_outpoint();
353 out_point->reposition(0);
356 out_point->draw_face(1, 0);
365 if( edl && edl->local_session->outpoint_valid() &&
366 pixel >= 0 && pixel < get_w() ) {
367 add_subwindow(out_point = new OutPointGUI(mwindow,
368 this, pixel, edl->local_session->get_outpoint()));
369 out_point->set_cursor(ARROW_CURSOR, 0, 0);
375 void TimeBar::update_clock(double position)
379 void TimeBar::update(int flush)
382 // Need to redo these when range is drawn to get the background updated.
387 EDL *edl = get_edl();
389 int x = get_relative_cursor_x();
390 // Draw highlight position
391 if( edl && (highlighted || current_operation == TIMEBAR_DRAG) &&
392 x >= 0 && x < get_w() ) {
393 //printf("TimeBar::update %d %d\n", __LINE__, x);
394 double position = pixel_to_position(x);
396 position = get_edl()->align_to_frame(position, 0);
397 pixel = position_to_pixel(position);
398 update_clock(position);
402 double position = test_highlight();
403 if( position >= 0 ) pixel = position_to_pixel(position);
407 if( pixel >= 0 && pixel < get_w() ) {
408 set_color(mwindow->theme->timebar_cursor_color);
410 //printf("TimeBar::update %d pane=%d pixel=%jd\n", __LINE__, pane->number, pixel);
411 draw_line(pixel, 0, pixel, get_h());
417 double playback_start = edl->local_session->playback_start;
418 if( playback_start >= 0 ) {
419 int64_t pixel = position_to_pixel(playback_start);
420 set_color(mwindow->theme->timebar_cursor_color ^ 0x0000ff);
421 draw_line(pixel, 0, pixel, get_h());
422 double playback_end = edl->local_session->playback_end;
423 if( playback_end > playback_start ) {
424 pixel = position_to_pixel(playback_end);
425 set_color(mwindow->theme->timebar_cursor_color ^ 0x00ff00);
426 draw_line(pixel, 0, pixel, get_h());
430 double position = edl->local_session->get_selectionstart(1);
431 int64_t pixel = position_to_pixel(position);
432 // Draw insertion point position.
433 int color = mwindow->theme->timebar_cursor_color;
434 if( mwindow->preferences->forward_render_displacement )
437 draw_line(pixel, 0, pixel, get_h());
442 // Get the labels to show
445 //printf("TimeBar::update %d this=%p %d\n", __LINE__, this, current_operation);
450 int TimeBar::delete_project()
452 // labels->delete_all();
456 int TimeBar::save(FileXML *xml)
458 // labels->save(xml);
465 void TimeBar::draw_time()
469 EDL* TimeBar::get_edl()
476 void TimeBar::draw_range()
480 //printf("TimeBar::draw_range %d %p\n", __LINE__, get_edl());
481 if( has_preview() && get_edl() ) {
483 get_preview_pixels(x1, x2);
485 //printf("TimeBar::draw_range %f %d %d\n", edl_length, x1, x2);
486 draw_3segmenth(0, 0, x1, mwindow->theme->timebar_view_data);
487 draw_top_background(get_parent(), x1, 0, x2 - x1, get_h());
488 draw_3segmenth(x2, 0, get_w() - x2, mwindow->theme->timebar_view_data);
491 draw_line(x1, 0, x1, get_h());
492 draw_line(x2, 0, x2, get_h());
495 EDL *edl = get_edl();
497 int64_t pixel = position_to_pixel(
498 edl->local_session->get_selectionstart(1));
499 // Draw insertion point position if this timebar belongs to a window which
500 // has something other than the master EDL.
501 set_color(mwindow->theme->timebar_cursor_color);
502 draw_line(pixel, 0, pixel, get_h());
506 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
509 void TimeBar::select_label(double position)
520 double TimeBar::get_edl_length()
525 //printf("TimeBar::get_edl_length 1 %f\n", get_edl()->tracks->total_playable_length());
526 edl_length = get_edl()->tracks->total_playable_length();
529 //printf("TimeBar::get_edl_length 2\n");
530 if( !EQUIV(edl_length, 0) ) {
531 //printf("TimeBar::get_edl_length 3\n");
532 time_per_pixel = edl_length / get_w();
533 //printf("TimeBar::get_edl_length 4\n");
538 //printf("TimeBar::get_edl_length 5\n");
543 int TimeBar::get_preview_pixels(int &x1, int &x2)
551 if( !EQUIV(edl_length, 0) ) {
552 if( get_edl()->local_session->preview_end <= 0 ||
553 get_edl()->local_session->preview_end > edl_length )
554 get_edl()->local_session->preview_end = edl_length;
555 if( get_edl()->local_session->preview_start >
556 get_edl()->local_session->preview_end )
557 get_edl()->local_session->preview_start = 0;
558 x1 = (int)(get_edl()->local_session->preview_start / time_per_pixel);
559 x2 = (int)(get_edl()->local_session->preview_end / time_per_pixel);
566 // printf("TimeBar::get_preview_pixels %f %f %d %d\n",
567 // get_edl()->local_session->preview_start,
568 // get_edl()->local_session->preview_end,
575 int TimeBar::test_preview(int buttonpress)
580 if( get_edl() && cursor_inside() && buttonpress >= 0 ) {
581 int x1, x2, x = get_relative_cursor_x();
582 get_preview_pixels(x1, x2);
583 //printf("TimeBar::test_preview %d %d %d\n", x1, x2, x);
584 // Inside left handle
585 if( x >= x1 - HANDLE_W && x < x1 + HANDLE_W &&
586 // Ignore left handle if both handles are up against the left side
589 current_operation = TIMEBAR_DRAG_LEFT;
590 start_position = get_edl()->local_session->preview_start;
593 else if( get_cursor() != LEFT_CURSOR )
594 set_cursor(LEFT_CURSOR, 0, 1);
597 // Inside right handle
598 else if( x >= x2 - HANDLE_W && x < x2 + HANDLE_W &&
599 // Ignore right handle if both handles are up against the right side
600 x1 < get_w() - HANDLE_W ) {
602 current_operation = TIMEBAR_DRAG_RIGHT;
603 start_position = get_edl()->local_session->preview_end;
606 else if( get_cursor() != RIGHT_CURSOR )
607 set_cursor(RIGHT_CURSOR, 0, 1);
611 else if( get_button_down() && get_buttonpress() == 3 &&
612 x >= x1 && x < x2 ) {
614 current_operation = TIMEBAR_DRAG_CENTER;
615 starting_start_position = get_edl()->local_session->preview_start;
616 starting_end_position = get_edl()->local_session->preview_end;
619 if( get_cursor() != HSEPARATE_CURSOR )
620 set_cursor(HSEPARATE_CURSOR, 0, 1);
625 if( !result && get_cursor() != ARROW_CURSOR )
626 set_cursor(ARROW_CURSOR, 0, 1);
632 int TimeBar::move_preview(int &redraw)
634 int result = 0, x = get_relative_cursor_x();
636 if( current_operation == TIMEBAR_DRAG_LEFT ) {
637 get_edl()->local_session->preview_start =
638 start_position + time_per_pixel * (x - start_cursor_x);
639 CLAMP(get_edl()->local_session->preview_start,
641 get_edl()->local_session->preview_end);
645 if( current_operation == TIMEBAR_DRAG_RIGHT ) {
646 get_edl()->local_session->preview_end =
647 start_position + time_per_pixel * (x - start_cursor_x);
648 CLAMP(get_edl()->local_session->preview_end,
649 get_edl()->local_session->preview_start,
654 if( current_operation == TIMEBAR_DRAG_CENTER ) {
655 double dt = time_per_pixel * (x - start_cursor_x);
656 get_edl()->local_session->preview_start = starting_start_position + dt;
657 get_edl()->local_session->preview_end = starting_end_position + dt;
658 if( get_edl()->local_session->preview_start < 0 ) {
659 get_edl()->local_session->preview_end -= get_edl()->local_session->preview_start;
660 get_edl()->local_session->preview_start = 0;
663 if( get_edl()->local_session->preview_end > edl_length ) {
664 get_edl()->local_session->preview_start -= get_edl()->local_session->preview_end - edl_length;
665 get_edl()->local_session->preview_end = edl_length;
670 //printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation);
676 //printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation);
681 void TimeBar::update_preview()
685 int TimeBar::samplemovement()
690 void TimeBar::stop_playback()
694 int TimeBar::button_press_event()
697 if( is_event_win() && cursor_above() ) {
698 if( has_preview() && get_buttonpress() == 3 ) {
699 result = test_preview(1);
701 // Change time format
702 else if( ctrl_down() ) {
703 if( get_buttonpress() == 1 )
704 mwindow->next_time_format();
706 if( get_buttonpress() == 2 )
707 mwindow->prev_time_format();
710 else if( get_buttonpress() == 1 ) {
713 // Select region between two labels
714 if( get_double_click() ) {
715 int x = get_relative_cursor_x();
716 double position = pixel_to_position(x);
718 select_region(position);
722 // Reposition highlight cursor
724 current_operation = TIMEBAR_DRAG;
733 void TimeBar::activate_timeline()
735 mwindow->gui->activate_timeline();
738 int TimeBar::cursor_motion_event()
743 //printf("TimeBar::cursor_motion_event %d %p %d\n", __LINE__, this, current_operation);
744 switch( current_operation )
749 handle_mwindow_drag();
751 //printf("TimeBar::cursor_motion_event %d %d\n", __LINE__, current_operation);
756 case TIMEBAR_DRAG_LEFT:
757 case TIMEBAR_DRAG_RIGHT:
758 case TIMEBAR_DRAG_CENTER:
760 result = move_preview(redraw);
764 if( cursor_above() ) {
769 //printf("TimeBar::cursor_motion_event 20\n");
771 result = test_preview(0);
772 //printf("TimeBar::cursor_motion_event 30\n");
777 //printf("TimeBar::cursor_motion_event %d %d\n", __LINE__, current_operation);
781 //printf("TimeBar::cursor_motion_event %d %p %d\n", __LINE__, this, current_operation);
786 int TimeBar::cursor_leave_event()
795 int TimeBar::button_release_event()
797 //printf("TimeBar::button_release_event %d %d\n", __LINE__, current_operation);
800 switch( current_operation )
803 mwindow->gui->get_focused_pane()->canvas->stop_dragscroll();
804 current_operation = TIMEBAR_NONE;
810 if( current_operation != TIMEBAR_NONE ) {
811 current_operation = TIMEBAR_NONE;
817 if( (!cursor_above() && highlighted) || need_redraw ) {
825 // Update the selection cursor during a dragging operation
826 void TimeBar::update_cursor()
830 void TimeBar::handle_mwindow_drag()
834 int TimeBar::select_region(double position)
836 Label *start = 0, *end = 0, *current;
837 for( current = mwindow->edl->labels->first; current; current = NEXT ) {
838 if( current->position > position ) {
844 for( current = mwindow->edl->labels->last ; current; current = PREVIOUS ) {
845 if( current->position <= position ) {
854 mwindow->edl->local_session->set_selectionstart(0);
856 mwindow->edl->local_session->set_selectionstart(start->position);
859 mwindow->edl->local_session->set_selectionend(mwindow->edl->tracks->total_length());
861 mwindow->edl->local_session->set_selectionend(end->position);
865 mwindow->edl->local_session->set_selectionstart(start->position);
866 mwindow->edl->local_session->set_selectionend(start->position);
870 mwindow->cwindow->update(1, 0, 0);
871 mwindow->gui->hide_cursor(0);
872 mwindow->gui->draw_cursor(1);
873 mwindow->gui->flash_canvas(0);
874 mwindow->gui->activate_timeline();
875 mwindow->gui->zoombar->update();
883 int TimeBar::delete_arrows()
888 double TimeBar::test_highlight()