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"
27 #include "edlsession.h"
28 #include "localsession.h"
29 #include "mainclock.h"
30 #include "maincursor.h"
31 #include "mainsession.h"
34 #include "mwindowgui.h"
37 #include "preferences.h"
39 #include "trackcanvas.h"
41 #include "transportque.h"
46 MTimeBar::MTimeBar(MWindow *mwindow,
52 : TimeBar(mwindow, gui, x, y, w, h)
56 // *** CONTEXT_HELP ***
57 context_help_set_keyword("Time Format section");
60 MTimeBar::MTimeBar(MWindow *mwindow,
66 : TimeBar(mwindow, mwindow->gui, x, y, w, h)
68 this->gui = mwindow->gui;
70 // *** CONTEXT_HELP ***
71 context_help_set_keyword("Time Format section");
74 void MTimeBar::create_objects()
76 gui->add_subwindow(menu = new TimeBarPopup(mwindow));
77 menu->create_objects();
79 TimeBar::create_objects();
83 double MTimeBar::pixel_to_position(int pixel)
85 return (double)pixel *
86 mwindow->edl->local_session->zoom_sample /
87 mwindow->edl->session->sample_rate +
88 (double)mwindow->edl->local_session->view_start[pane->number] *
89 mwindow->edl->local_session->zoom_sample /
90 mwindow->edl->session->sample_rate;
94 int64_t MTimeBar::position_to_pixel(double position)
96 return (int64_t)(position *
97 mwindow->edl->session->sample_rate /
98 mwindow->edl->local_session->zoom_sample -
99 mwindow->edl->local_session->view_start[pane->number]);
103 void MTimeBar::stop_transport()
105 gui->stop_transport("MTimeBar::stop_transport");
108 #define TEXT_MARGIN xS(4)
109 #define TICK_SPACING xS(5)
110 #define LINE_MARGIN yS(3)
111 #define TICK_MARGIN yS(16)
113 void MTimeBar::draw_time()
116 char string[BCTEXTLEN];
117 int sample_rate = mwindow->edl->session->sample_rate;
118 double frame_rate = mwindow->edl->session->frame_rate;
119 // Seconds between text markings
120 double text_interval = 3600.0;
121 // Seconds between tick marks
122 double tick_interval = 3600.0;
125 // Calculate tick mark spacing, number spacing, and starting point based
126 // on zoom, time format, project settings.
128 // If the time format is for audio, mark round numbers of samples based on
130 // Fow low zoom, mark tens of samples.
132 // If the time format is for video, mark round number of frames based on
134 // For low zoom, mark individual frames.
136 //int64_t windowspan = mwindow->edl->local_session->zoom_sample * get_w();
144 // Number of seconds per pixel
145 double time_per_pixel = (double)mwindow->edl->local_session->zoom_sample /
147 // Seconds in each frame
148 double frame_seconds = (double)1.0 / frame_rate;
149 // Starting time of view in seconds.
150 double view_start = mwindow->edl->local_session->view_start[pane->number] *
152 // Ending time of view in seconds
153 double view_end = (double)(mwindow->edl->local_session->view_start[pane->number] +
154 get_w()) * time_per_pixel;
155 // Get minimum distance between text marks
156 int min_pixels1 = get_text_width(MEDIUMFONT,
157 Units::totext(string,
159 mwindow->edl->session->time_format,
161 mwindow->edl->session->frame_rate,
162 mwindow->edl->session->frames_per_foot)) + TEXT_MARGIN;
163 int min_pixels2 = get_text_width(MEDIUMFONT,
164 Units::totext(string,
166 mwindow->edl->session->time_format,
168 mwindow->edl->session->frame_rate,
169 mwindow->edl->session->frames_per_foot)) + TEXT_MARGIN;
170 int min_pixels = (int)MAX(min_pixels1, min_pixels2);
173 // Minimum seconds between text marks
174 double min_time = (double)min_pixels *
175 mwindow->edl->local_session->zoom_sample /
179 // Get first text mark on or before window start
180 int64_t starting_mark = 0;
184 // Default text spacing
186 double prev_text_interval = 1.0;
188 while(text_interval >= min_time)
190 prev_text_interval = text_interval;
205 text_interval /= 2.5;
210 text_interval = prev_text_interval;
246 text_interval = 1200;
249 text_interval = 1800;
252 text_interval = 3600;
255 switch(mwindow->edl->session->time_format)
257 case TIME_FEET_FRAMES:
259 double foot_seconds = frame_seconds * mwindow->edl->session->frames_per_foot;
260 if(frame_seconds >= min_time)
261 text_interval = frame_seconds;
263 if(foot_seconds / 8.0 > min_time)
264 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 8.0;
266 if(foot_seconds / 4.0 > min_time)
267 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 4.0;
269 if(foot_seconds / 2.0 > min_time)
270 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 2.0;
272 if(foot_seconds > min_time)
273 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot;
275 if(foot_seconds * 2 >= min_time)
276 text_interval = foot_seconds * 2;
278 if(foot_seconds * 5 >= min_time)
279 text_interval = foot_seconds * 5;
283 for(int factor = 10, progression = 0; factor <= 100000; )
285 if(foot_seconds * factor >= min_time)
287 text_interval = foot_seconds * factor;
293 factor = (int)(factor * 2.5);
299 factor = (int)(factor * 2);
305 factor = (int)(factor * 2);
317 // One frame per text mark
318 if(frame_seconds >= min_time)
319 text_interval = frame_seconds;
321 if(frame_seconds * 2 >= min_time)
322 text_interval = frame_seconds * 2;
324 if(frame_seconds * 5 >= min_time)
325 text_interval = frame_seconds * 5;
329 for(int factor = 10, progression = 0; factor <= 100000; )
331 if(frame_seconds * factor >= min_time)
333 text_interval = frame_seconds * factor;
339 factor = (int)(factor * 2.5);
345 factor = (int)(factor * 2);
351 factor = (int)(factor * 2);
364 while(text_interval < min_time)
370 tick_interval = text_interval;
371 double timecode_offset = 0;
373 switch(mwindow->edl->session->time_format)
376 timecode_offset = mwindow->get_timecode_offset(); // fall thru
377 case TIME_FEET_FRAMES:
380 if(frame_seconds / time_per_pixel > TICK_SPACING)
381 tick_interval = frame_seconds;
385 // Get first text mark on or before window start
386 starting_mark = (int64_t)((double)mwindow->edl->local_session->view_start[pane->number] *
387 time_per_pixel / text_interval);
389 double start_position = (double)starting_mark * text_interval;
390 int64_t iteration = 0;
393 //printf("text_interval=%f\n", text_interval);
394 while(start_position + text_interval * iteration < view_end)
396 double position1 = start_position + text_interval * iteration;
397 int pixel = (int64_t)(position1 / time_per_pixel) -
398 mwindow->edl->local_session->view_start[pane->number];
401 Units::totext(string,
403 mwindow->edl->session->time_format,
405 mwindow->edl->session->frame_rate,
406 mwindow->edl->session->frames_per_foot,
408 set_color(get_resources()->default_text_color);
409 set_font(MEDIUMFONT);
411 draw_text(pixel + TEXT_MARGIN, get_text_ascent(MEDIUMFONT), string);
412 draw_line(pixel, LINE_MARGIN, pixel, get_h() - yS(2));
414 double position2 = start_position + text_interval * (iteration + 1);
415 int pixel2 = (int64_t)(position2 / time_per_pixel) -
416 mwindow->edl->local_session->view_start[pane->number];
418 for(double tick_position = position1;
419 tick_position < position2;
420 tick_position += tick_interval)
422 pixel = (int64_t)(tick_position / time_per_pixel) -
423 mwindow->edl->local_session->view_start[pane->number];
424 if(labs(pixel - pixel1) > 1 &&
425 labs(pixel - pixel2) > 1)
426 draw_line(pixel, TICK_MARGIN, pixel, get_h() - yS(2));
434 void MTimeBar::draw_range()
437 if( mwindow->brender_active && mwindow->preferences->use_brender &&
438 mwindow->edl->tracks->total_playable_vtracks() ) {
439 double time_per_pixel = (double)mwindow->edl->local_session->zoom_sample /
440 mwindow->edl->session->sample_rate;
441 x1 = (int)(mwindow->edl->session->brender_start / time_per_pixel) -
442 mwindow->edl->local_session->view_start[pane->number];
443 x2 = (int)(mwindow->session->brender_end / time_per_pixel) -
444 mwindow->edl->local_session->view_start[pane->number];
447 if(x2 > x1 && x1 < get_w() && x2 > 0) {
448 draw_top_background(get_parent(), 0, 0, x1, get_h());
449 draw_3segmenth(x1, 0, x2 - x1, mwindow->theme->get_image("timebar_brender"));
450 draw_top_background(get_parent(), x2, 0, get_w() - x2, get_h());
453 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
456 // int64_t pixel = position_to_pixel(
457 // mwindow->edl->local_session->get_selectionstart(1));
459 // set_color(mwindow->theme->timebar_cursor_colorg);
460 // draw_line(pixel, 0, pixel, get_h());
461 //printf("MTimeBar::draw_range %f %f\n", mwindow->session->brender_end, time_per_pixel);
464 void MTimeBar::select_label(double position)
468 EDL *edl = mwindow->edl;
469 position = edl->align_to_frame(position, 1);
473 if(position > edl->local_session->get_selectionend(1) / 2 +
474 edl->local_session->get_selectionstart(1) / 2)
477 edl->local_session->set_selectionend(position);
481 edl->local_session->set_selectionstart(position);
486 edl->local_session->set_selectionstart(position);
487 edl->local_session->set_selectionend(position);
491 mwindow->cwindow->update(1, 0, 0, 0, 1);
495 gui->flash_canvas(1);
496 gui->zoombar->update();
502 int MTimeBar::resize_event()
504 reposition_window(mwindow->theme->mtimebar_x,
505 mwindow->theme->mtimebar_y,
506 mwindow->theme->mtimebar_w,
507 mwindow->theme->mtimebar_h);
512 int MTimeBar::resize_event(int x, int y, int w, int h)
522 // int MTimeBar::test_preview(int buttonpress)
530 void MTimeBar::handle_mwindow_drag()
532 //printf("TimeBar::cursor_motion_event %d %d\n", __LINE__, current_operation);
533 int relative_cursor_x = pane->canvas->get_relative_cursor_x();
534 if(relative_cursor_x >= pane->canvas->get_w() ||
535 relative_cursor_x < 0)
537 pane->canvas->start_dragscroll();
540 if(relative_cursor_x < pane->canvas->get_w() &&
541 relative_cursor_x >= 0)
543 pane->canvas->stop_dragscroll();
549 void MTimeBar::update(int flush)
551 TimeBar::update(flush);
554 void MTimeBar::update_clock(double position)
556 if(!mwindow->cwindow->playback_engine->is_playing_back)
557 gui->mainclock->update(position);
560 void MTimeBar::update_cursor()
562 int rx = get_relative_cursor_x();
563 double position = pixel_to_position(rx);
565 position = mwindow->edl->align_to_frame(position, 0);
566 position = MAX(0, position);
568 mwindow->select_point(position);
572 double MTimeBar::test_highlight()
574 // Don't crash during initialization
577 if(mwindow->session->current_operation == NO_OPERATION)
579 if(pane->canvas->is_event_win() &&
580 pane->canvas->cursor_inside())
582 int cursor_x = pane->canvas->get_cursor_x();
583 double position = (double)cursor_x *
584 (double)mwindow->edl->local_session->zoom_sample /
585 (double)mwindow->edl->session->sample_rate +
586 (double)mwindow->edl->local_session->view_start[pane->number] *
587 (double)mwindow->edl->local_session->zoom_sample /
588 (double)mwindow->edl->session->sample_rate;
589 pane->canvas->timebar_position = mwindow->edl->align_to_frame(position, 0);
592 //printf("MTimeBar::test_highlight %d %d %f\n", __LINE__, pane->canvas->cursor_inside(), pane->canvas->timebar_position);
593 return pane->canvas->timebar_position;
596 if(mwindow->session->current_operation == SELECT_REGION ||
597 mwindow->session->current_operation == DRAG_EDITHANDLE2)
599 //printf("MTimeBar::test_highlight %d %f\n", __LINE__, mwindow->gui->canvas->timebar_position);
600 return pane->canvas->timebar_position;
611 int MTimeBar::repeat_event(int64_t duration)
613 if(!pane->canvas->drag_scroll) return 0;
614 if(duration != BC_WindowBase::get_resources()->scroll_repeat) return 0;
618 int relative_cursor_x = pane->canvas->get_relative_cursor_x();
619 if(current_operation == TIMEBAR_DRAG)
621 if(relative_cursor_x >= pane->canvas->get_w())
623 distance = relative_cursor_x - pane->canvas->get_w();
627 if(relative_cursor_x < 0)
629 distance = relative_cursor_x;
638 mwindow->samplemovement(
639 mwindow->edl->local_session->view_start[pane->number] + distance,
648 int MTimeBar::button_press_event()
652 if(is_event_win() && cursor_above() && get_buttonpress() == 3)
655 menu->activate_menu();
659 if(!result) return TimeBar::button_press_event();
664 void MTimeBar::activate_timeline()
670 TimeBarPopupItem::TimeBarPopupItem(MWindow *mwindow,
676 this->mwindow = mwindow;
681 int TimeBarPopupItem::handle_event()
683 mwindow->edl->session->time_format = value;
684 mwindow->gui->update(0, NO_DRAW, 1, 0, 0, 1, 0);
685 mwindow->gui->redraw_time_dependancies();
691 TimeBarPopup::TimeBarPopup(MWindow *mwindow)
692 : BC_PopupMenu(0, 0, 0, "", 0)
694 this->mwindow = mwindow;
697 TimeBarPopup::~TimeBarPopup()
702 void TimeBarPopup::create_objects()
704 add_item(items[0] = new TimeBarPopupItem(mwindow,
705 this, TIME_HMS_TEXT, TIME_HMS));
706 add_item(items[1] = new TimeBarPopupItem(mwindow,
707 this, TIME_HMSF_TEXT, TIME_HMSF));
708 add_item(items[2] = new TimeBarPopupItem(mwindow,
709 this, TIME_TIMECODE_TEXT, TIME_TIMECODE));
710 add_item(items[3] = new TimeBarPopupItem(mwindow,
711 this, TIME_FRAMES_TEXT, TIME_FRAMES));
712 add_item(items[4] = new TimeBarPopupItem(mwindow,
713 this, TIME_SAMPLES_TEXT, TIME_SAMPLES));
714 add_item(items[5] = new TimeBarPopupItem(mwindow,
715 this, TIME_SAMPLES_HEX_TEXT, TIME_SAMPLES_HEX));
716 add_item(items[6] = new TimeBarPopupItem(mwindow,
717 this, TIME_SECONDS_TEXT, TIME_SECONDS));
718 add_item(items[7] = new TimeBarPopupItem(mwindow,
719 this, TIME_FEET_FRAMES_TEXT, TIME_FEET_FRAMES));
722 void TimeBarPopup::update()
724 int time_format = mwindow->edl->session->time_format;
725 for( int i=0; i<TOTAL_TIMEFORMATS; ++i ) {
726 items[i]->set_checked(items[i]->value == time_format);