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,
63 : BC_Toggle(translate_pixel(mwindow, pixel),
65 data ? data : mwindow->theme->label_toggle,
68 this->mwindow = mwindow;
69 this->timebar = timebar;
72 this->position = position;
80 int LabelGUI::get_y(MWindow *mwindow, TimeBar *timebar)
82 return timebar->get_h() -
83 mwindow->theme->label_toggle[0]->get_h();
86 int LabelGUI::translate_pixel(MWindow *mwindow, int pixel)
88 int result = pixel - mwindow->theme->label_toggle[0]->get_w() / 2;
92 void LabelGUI::reposition(int flush)
94 reposition_window(translate_pixel(mwindow, pixel),
98 int LabelGUI::button_press_event()
102 if (this->is_event_win() && get_buttonpress() == 3) {
104 timebar->label_edit->edit_label(label);
107 result = BC_Toggle::button_press_event();
110 set_tooltip(this->label->textstr);
114 int LabelGUI::handle_event()
116 timebar->select_label(position);
121 InPointGUI::InPointGUI(MWindow *mwindow,
128 get_y(mwindow, timebar),
130 mwindow->theme->in_point)
132 //printf("InPointGUI::InPointGUI %d %d\n", pixel, get_y(mwindow, timebar));
134 InPointGUI::~InPointGUI()
137 int InPointGUI::get_y(MWindow *mwindow, TimeBar *timebar)
140 result = timebar->get_h() -
141 mwindow->theme->in_point[0]->get_h();
146 OutPointGUI::OutPointGUI(MWindow *mwindow,
153 get_y(mwindow, timebar),
155 mwindow->theme->out_point)
157 //printf("OutPointGUI::OutPointGUI %d %d\n", pixel, get_y(mwindow, timebar));
159 OutPointGUI::~OutPointGUI()
162 int OutPointGUI::get_y(MWindow *mwindow, TimeBar *timebar)
164 return timebar->get_h() -
165 mwindow->theme->out_point[0]->get_h();
169 PresentationGUI::PresentationGUI(MWindow *mwindow,
173 : LabelGUI(mwindow, timebar, pixel, get_y(mwindow, timebar), position)
176 PresentationGUI::~PresentationGUI()
180 TimeBar::TimeBar(MWindow *mwindow,
186 : BC_SubWindow(x, y, w, h)
188 //printf("TimeBar::TimeBar %d %d %d %d\n", x, y, w, h);
190 this->mwindow = mwindow;
191 label_edit = new LabelEdit(mwindow, mwindow->awindow, 0);
198 if(in_point) delete in_point;
199 if(out_point) delete out_point;
200 if(label_edit) delete label_edit;
201 labels.remove_all_objects();
202 presentations.remove_all_objects();
205 void TimeBar::create_objects()
209 //printf("TimeBar::create_objects %d\n", __LINE__);
210 current_operation = TIMEBAR_NONE;
211 set_cursor(UPRIGHT_ARROW_CURSOR, 0, 0);
216 int64_t TimeBar::position_to_pixel(double position)
219 return (int64_t)(position / time_per_pixel);
223 double TimeBar::pixel_to_position(int pixel)
227 pixel += mwindow->edl->local_session->view_start[pane->number];
230 return (double)pixel *
231 mwindow->edl->local_session->zoom_sample /
232 mwindow->edl->session->sample_rate;
235 void TimeBar::update_labels()
238 EDL *edl = get_edl();
242 for(Label *current = edl->labels->first;
246 int64_t pixel = position_to_pixel(current->position);
248 if(pixel >= 0 && pixel < get_w())
251 if(output >= labels.total)
254 add_subwindow(new_label =
255 new LabelGUI(mwindow,
258 LabelGUI::get_y(mwindow, this),
260 new_label->set_cursor(INHERIT_CURSOR, 0, 0);
261 new_label->set_tooltip(current->textstr);
262 new_label->label = current;
263 labels.append(new_label);
266 // Reposition old label
268 LabelGUI *gui = labels.values[output];
269 if(gui->pixel != pixel)
279 labels.values[output]->position = current->position;
280 labels.values[output]->set_tooltip(current->textstr);
281 labels.values[output]->label = current;
284 if(edl->local_session->get_selectionstart(1) <= current->position &&
285 edl->local_session->get_selectionend(1) >= current->position)
286 labels.values[output]->update(1);
288 if(labels.values[output]->get_value())
289 labels.values[output]->update(0);
296 // Delete excess labels
297 while(labels.total > output)
299 labels.remove_object();
302 // Get the labels to show
306 void TimeBar::update_highlights()
308 for(int i = 0; i < labels.total; i++)
310 LabelGUI *label = labels.values[i];
311 if(mwindow->edl->equivalent(label->position,
312 mwindow->edl->local_session->get_selectionstart(1)) ||
313 mwindow->edl->equivalent(label->position,
314 mwindow->edl->local_session->get_selectionend(1)))
316 if(!label->get_value()) label->update(1);
319 if(label->get_value()) label->update(0);
322 if(mwindow->edl->equivalent(mwindow->edl->local_session->get_inpoint(),
323 mwindow->edl->local_session->get_selectionstart(1)) ||
324 mwindow->edl->equivalent(mwindow->edl->local_session->get_inpoint(),
325 mwindow->edl->local_session->get_selectionend(1)))
327 if(in_point) in_point->update(1);
330 if(in_point) in_point->update(0);
332 if(mwindow->edl->equivalent(mwindow->edl->local_session->get_outpoint(),
333 mwindow->edl->local_session->get_selectionstart(1)) ||
334 mwindow->edl->equivalent(mwindow->edl->local_session->get_outpoint(),
335 mwindow->edl->local_session->get_selectionend(1)))
337 if(out_point) out_point->update(1);
340 if(out_point) out_point->update(0);
343 void TimeBar::update_points()
345 EDL *edl = get_edl();
346 int64_t pixel = !edl ? 0 :
347 position_to_pixel(edl->local_session->get_inpoint());
352 edl->local_session->inpoint_valid() &&
353 pixel >= 0 && pixel < get_w())
355 if(!EQUIV(edl->local_session->get_inpoint(), in_point->position) ||
356 in_point->pixel != pixel)
358 in_point->pixel = pixel;
359 in_point->position = edl->local_session->get_inpoint();
360 in_point->reposition(0);
364 in_point->draw_face(1, 0);
374 if(edl && edl->local_session->inpoint_valid() &&
375 pixel >= 0 && pixel < get_w())
377 add_subwindow(in_point = new InPointGUI(mwindow,
378 this, pixel, edl->local_session->get_inpoint()));
379 in_point->set_cursor(ARROW_CURSOR, 0, 0);
383 position_to_pixel(edl->local_session->get_outpoint());
387 if( edl && edl->local_session->outpoint_valid() &&
388 pixel >= 0 && pixel < get_w())
390 if(!EQUIV(edl->local_session->get_outpoint(), out_point->position) ||
391 out_point->pixel != pixel)
393 out_point->pixel = pixel;
394 out_point->position = edl->local_session->get_outpoint();
395 out_point->reposition(0);
399 out_point->draw_face(1, 0);
410 edl->local_session->outpoint_valid() &&
411 pixel >= 0 && pixel < get_w())
413 add_subwindow(out_point = new OutPointGUI(mwindow,
414 this, pixel, edl->local_session->get_outpoint()));
415 out_point->set_cursor(ARROW_CURSOR, 0, 0);
421 void TimeBar::update_clock(double position)
425 void TimeBar::update(int flush)
428 // Need to redo these when range is drawn to get the background updated.
433 EDL *edl = get_edl();
435 int x = get_relative_cursor_x();
436 // Draw highlight position
438 (highlighted || current_operation == TIMEBAR_DRAG) &&
439 x >= 0 && x < get_w())
441 //printf("TimeBar::update %d %d\n", __LINE__, x);
442 double position = pixel_to_position(x);
444 position = get_edl()->align_to_frame(position, 0);
445 pixel = position_to_pixel(position);
446 update_clock(position);
451 double position = test_highlight();
452 if(position >= 0) pixel = position_to_pixel(position);
456 if(pixel >= 0 && pixel < get_w())
458 set_color(mwindow->theme->timebar_cursor_color);
460 //printf("TimeBar::update %d pane=%d pixel=%jd\n", __LINE__, pane->number, pixel);
461 draw_line(pixel, 0, pixel, get_h());
468 double playback_start = edl->local_session->playback_start;
469 if( playback_start >= 0 ) {
470 int64_t pixel = position_to_pixel(playback_start);
471 set_color(mwindow->theme->timebar_cursor_color ^ 0x0000ff);
472 draw_line(pixel, 0, pixel, get_h());
473 double playback_end = edl->local_session->playback_end;
474 if( playback_end > playback_start ) {
475 pixel = position_to_pixel(playback_end);
476 set_color(mwindow->theme->timebar_cursor_color ^ 0x00ff00);
477 draw_line(pixel, 0, pixel, get_h());
481 double position = edl->local_session->get_selectionstart(1);
482 int64_t pixel = position_to_pixel(position);
483 // Draw insertion point position.
484 set_color(mwindow->theme->timebar_cursor_color);
485 draw_line(pixel, 0, pixel, get_h());
490 // Get the labels to show
493 //printf("TimeBar::update %d this=%p %d\n", __LINE__, this, current_operation);
498 int TimeBar::delete_project()
500 // labels->delete_all();
504 int TimeBar::save(FileXML *xml)
506 // labels->save(xml);
513 void TimeBar::draw_time()
517 EDL* TimeBar::get_edl()
524 void TimeBar::draw_range()
528 //printf("TimeBar::draw_range %d %p\n", __LINE__, get_edl());
529 if(has_preview() && get_edl())
532 get_preview_pixels(x1, x2);
534 //printf("TimeBar::draw_range %f %d %d\n", edl_length, x1, x2);
535 draw_3segmenth(0, 0, x1, mwindow->theme->timebar_view_data);
536 draw_top_background(get_parent(), x1, 0, x2 - x1, get_h());
537 draw_3segmenth(x2, 0, get_w() - x2, mwindow->theme->timebar_view_data);
540 draw_line(x1, 0, x1, get_h());
541 draw_line(x2, 0, x2, get_h());
544 EDL *edl = get_edl();
547 int64_t pixel = position_to_pixel(
548 edl->local_session->get_selectionstart(1));
549 // Draw insertion point position if this timebar belongs to a window which
550 // has something other than the master EDL.
551 set_color(mwindow->theme->timebar_cursor_color);
552 draw_line(pixel, 0, pixel, get_h());
556 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
559 void TimeBar::select_label(double position)
570 double TimeBar::get_edl_length()
576 //printf("TimeBar::get_edl_length 1 %f\n", get_edl()->tracks->total_playable_length());
577 edl_length = get_edl()->tracks->total_playable_length();
580 //printf("TimeBar::get_edl_length 2\n");
581 if(!EQUIV(edl_length, 0))
583 //printf("TimeBar::get_edl_length 3\n");
584 time_per_pixel = edl_length / get_w();
585 //printf("TimeBar::get_edl_length 4\n");
591 //printf("TimeBar::get_edl_length 5\n");
596 int TimeBar::get_preview_pixels(int &x1, int &x2)
605 if(!EQUIV(edl_length, 0))
607 if(get_edl()->local_session->preview_end <= 0 ||
608 get_edl()->local_session->preview_end > edl_length)
609 get_edl()->local_session->preview_end = edl_length;
610 if(get_edl()->local_session->preview_start >
611 get_edl()->local_session->preview_end)
612 get_edl()->local_session->preview_start = 0;
613 x1 = (int)(get_edl()->local_session->preview_start / time_per_pixel);
614 x2 = (int)(get_edl()->local_session->preview_end / time_per_pixel);
622 // printf("TimeBar::get_preview_pixels %f %f %d %d\n",
623 // get_edl()->local_session->preview_start,
624 // get_edl()->local_session->preview_end,
631 int TimeBar::test_preview(int buttonpress)
636 if(get_edl() && cursor_inside() && buttonpress >= 0)
638 int x1, x2, x = get_relative_cursor_x();
639 get_preview_pixels(x1, x2);
640 //printf("TimeBar::test_preview %d %d %d\n", x1, x2, x);
641 // Inside left handle
642 if(x >= x1 - HANDLE_W && x < x1 + HANDLE_W &&
643 // Ignore left handle if both handles are up against the left side
648 current_operation = TIMEBAR_DRAG_LEFT;
649 start_position = get_edl()->local_session->preview_start;
652 else if(get_cursor() != LEFT_CURSOR)
653 set_cursor(LEFT_CURSOR, 0, 1);
656 // Inside right handle
657 else if(x >= x2 - HANDLE_W && x < x2 + HANDLE_W &&
658 // Ignore right handle if both handles are up against the right side
659 x1 < get_w() - HANDLE_W)
663 current_operation = TIMEBAR_DRAG_RIGHT;
664 start_position = get_edl()->local_session->preview_end;
667 else if(get_cursor() != RIGHT_CURSOR)
668 set_cursor(RIGHT_CURSOR, 0, 1);
672 else if(get_button_down() && get_buttonpress() == 3 &&
677 current_operation = TIMEBAR_DRAG_CENTER;
678 starting_start_position = get_edl()->local_session->preview_start;
679 starting_end_position = get_edl()->local_session->preview_end;
682 if(get_cursor() != HSEPARATE_CURSOR)
683 set_cursor(HSEPARATE_CURSOR, 0, 1);
688 if(!result && get_cursor() != ARROW_CURSOR)
689 set_cursor(ARROW_CURSOR, 0, 1);
695 int TimeBar::move_preview(int &redraw)
697 int result = 0, x = get_relative_cursor_x();
699 if(current_operation == TIMEBAR_DRAG_LEFT)
701 get_edl()->local_session->preview_start =
702 start_position + time_per_pixel * (x - start_cursor_x);
703 CLAMP(get_edl()->local_session->preview_start,
705 get_edl()->local_session->preview_end);
709 if(current_operation == TIMEBAR_DRAG_RIGHT)
711 get_edl()->local_session->preview_end =
712 start_position + time_per_pixel * (x - start_cursor_x);
713 CLAMP(get_edl()->local_session->preview_end,
714 get_edl()->local_session->preview_start,
719 if(current_operation == TIMEBAR_DRAG_CENTER)
721 double dt = time_per_pixel * (x - start_cursor_x);
722 get_edl()->local_session->preview_start = starting_start_position + dt;
723 get_edl()->local_session->preview_end = starting_end_position + dt;
724 if(get_edl()->local_session->preview_start < 0)
726 get_edl()->local_session->preview_end -= get_edl()->local_session->preview_start;
727 get_edl()->local_session->preview_start = 0;
730 if(get_edl()->local_session->preview_end > edl_length)
732 get_edl()->local_session->preview_start -= get_edl()->local_session->preview_end - edl_length;
733 get_edl()->local_session->preview_end = edl_length;
738 //printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation);
745 //printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation);
750 void TimeBar::update_preview()
754 int TimeBar::samplemovement()
759 void TimeBar::stop_playback()
763 int TimeBar::button_press_event()
766 if(is_event_win() && cursor_above())
768 if(has_preview() && get_buttonpress() == 3)
770 result = test_preview(1);
772 // Change time format
775 if(get_buttonpress() == 1)
776 mwindow->next_time_format();
778 if(get_buttonpress() == 2)
779 mwindow->prev_time_format();
782 else if(get_buttonpress() == 1)
786 // Select region between two labels
787 if(get_double_click())
789 int x = get_relative_cursor_x();
790 double position = pixel_to_position(x);
792 select_region(position);
797 // Reposition highlight cursor
799 current_operation = TIMEBAR_DRAG;
808 void TimeBar::activate_timeline()
810 mwindow->gui->activate_timeline();
813 int TimeBar::cursor_motion_event()
818 //printf("TimeBar::cursor_motion_event %d %p %d\n", __LINE__, this, current_operation);
819 switch(current_operation)
824 handle_mwindow_drag();
826 //printf("TimeBar::cursor_motion_event %d %d\n", __LINE__, current_operation);
831 case TIMEBAR_DRAG_LEFT:
832 case TIMEBAR_DRAG_RIGHT:
833 case TIMEBAR_DRAG_CENTER:
835 result = move_preview(redraw);
845 //printf("TimeBar::cursor_motion_event 20\n");
847 result = test_preview(0);
848 //printf("TimeBar::cursor_motion_event 30\n");
853 //printf("TimeBar::cursor_motion_event %d %d\n", __LINE__, current_operation);
858 //printf("TimeBar::cursor_motion_event %d %p %d\n", __LINE__, this, current_operation);
863 int TimeBar::cursor_leave_event()
873 int TimeBar::button_release_event()
875 //printf("TimeBar::button_release_event %d %d\n", __LINE__, current_operation);
878 switch(current_operation)
881 mwindow->gui->get_focused_pane()->canvas->stop_dragscroll();
882 current_operation = TIMEBAR_NONE;
888 if(current_operation != TIMEBAR_NONE)
890 current_operation = TIMEBAR_NONE;
896 if((!cursor_above() && highlighted) || need_redraw)
905 // Update the selection cursor during a dragging operation
906 void TimeBar::update_cursor()
910 void TimeBar::handle_mwindow_drag()
914 int TimeBar::select_region(double position)
916 Label *start = 0, *end = 0, *current;
917 for(current = mwindow->edl->labels->first; current; current = NEXT)
919 if(current->position > position)
926 for(current = mwindow->edl->labels->last ; current; current = PREVIOUS)
928 if(current->position <= position)
939 mwindow->edl->local_session->set_selectionstart(0);
941 mwindow->edl->local_session->set_selectionstart(start->position);
944 mwindow->edl->local_session->set_selectionend(mwindow->edl->tracks->total_length());
946 mwindow->edl->local_session->set_selectionend(end->position);
951 mwindow->edl->local_session->set_selectionstart(start->position);
952 mwindow->edl->local_session->set_selectionend(start->position);
956 mwindow->cwindow->update(1, 0, 0);
957 mwindow->gui->hide_cursor(0);
958 mwindow->gui->draw_cursor(1);
959 mwindow->gui->flash_canvas(0);
960 mwindow->gui->activate_timeline();
961 mwindow->gui->zoombar->update();
969 int TimeBar::delete_arrows()
974 double TimeBar::test_highlight()