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"
36 #include "preferences.h"
38 #include "trackcanvas.h"
40 #include "transportque.h"
45 MTimeBar::MTimeBar(MWindow *mwindow,
51 : TimeBar(mwindow, gui, x, y, w, h)
57 MTimeBar::MTimeBar(MWindow *mwindow,
63 : TimeBar(mwindow, mwindow->gui, x, y, w, h)
65 this->gui = mwindow->gui;
69 void MTimeBar::create_objects()
71 gui->add_subwindow(menu = new TimeBarPopup(mwindow));
72 menu->create_objects();
74 TimeBar::create_objects();
78 double MTimeBar::pixel_to_position(int pixel)
80 return (double)pixel *
81 mwindow->edl->local_session->zoom_sample /
82 mwindow->edl->session->sample_rate +
83 (double)mwindow->edl->local_session->view_start[pane->number] *
84 mwindow->edl->local_session->zoom_sample /
85 mwindow->edl->session->sample_rate;
89 int64_t MTimeBar::position_to_pixel(double position)
91 return (int64_t)(position *
92 mwindow->edl->session->sample_rate /
93 mwindow->edl->local_session->zoom_sample -
94 mwindow->edl->local_session->view_start[pane->number]);
98 void MTimeBar::stop_playback()
100 gui->unlock_window();
101 gui->mbuttons->transport->handle_transport(STOP, 1, 0, 0);
105 #define TEXT_MARGIN 4
106 #define TICK_SPACING 5
107 #define LINE_MARGIN 3
108 #define TICK_MARGIN 16
109 void MTimeBar::draw_time()
112 char string[BCTEXTLEN];
113 int sample_rate = mwindow->edl->session->sample_rate;
114 double frame_rate = mwindow->edl->session->frame_rate;
115 // Seconds between text markings
116 double text_interval = 3600.0;
117 // Seconds between tick marks
118 double tick_interval = 3600.0;
121 // Calculate tick mark spacing, number spacing, and starting point based
122 // on zoom, time format, project settings.
124 // If the time format is for audio, mark round numbers of samples based on
126 // Fow low zoom, mark tens of samples.
128 // If the time format is for video, mark round number of frames based on
130 // For low zoom, mark individual frames.
132 //int64_t windowspan = mwindow->edl->local_session->zoom_sample * get_w();
140 // Number of seconds per pixel
141 double time_per_pixel = (double)mwindow->edl->local_session->zoom_sample /
143 // Seconds in each frame
144 double frame_seconds = (double)1.0 / frame_rate;
145 // Starting time of view in seconds.
146 double view_start = mwindow->edl->local_session->view_start[pane->number] *
148 // Ending time of view in seconds
149 double view_end = (double)(mwindow->edl->local_session->view_start[pane->number] +
150 get_w()) * time_per_pixel;
151 // Get minimum distance between text marks
152 int min_pixels1 = get_text_width(MEDIUMFONT,
153 Units::totext(string,
155 mwindow->edl->session->time_format,
157 mwindow->edl->session->frame_rate,
158 mwindow->edl->session->frames_per_foot)) + TEXT_MARGIN;
159 int min_pixels2 = get_text_width(MEDIUMFONT,
160 Units::totext(string,
162 mwindow->edl->session->time_format,
164 mwindow->edl->session->frame_rate,
165 mwindow->edl->session->frames_per_foot)) + TEXT_MARGIN;
166 int min_pixels = (int)MAX(min_pixels1, min_pixels2);
169 // Minimum seconds between text marks
170 double min_time = (double)min_pixels *
171 mwindow->edl->local_session->zoom_sample /
175 // Get first text mark on or before window start
176 int64_t starting_mark = 0;
180 // Default text spacing
182 double prev_text_interval = 1.0;
184 while(text_interval >= min_time)
186 prev_text_interval = text_interval;
201 text_interval /= 2.5;
206 text_interval = prev_text_interval;
242 text_interval = 1200;
245 text_interval = 1800;
248 text_interval = 3600;
251 switch(mwindow->edl->session->time_format)
253 case TIME_FEET_FRAMES:
255 double foot_seconds = frame_seconds * mwindow->edl->session->frames_per_foot;
256 if(frame_seconds >= min_time)
257 text_interval = frame_seconds;
259 if(foot_seconds / 8.0 > min_time)
260 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 8.0;
262 if(foot_seconds / 4.0 > min_time)
263 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 4.0;
265 if(foot_seconds / 2.0 > min_time)
266 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot / 2.0;
268 if(foot_seconds > min_time)
269 text_interval = frame_seconds * mwindow->edl->session->frames_per_foot;
271 if(foot_seconds * 2 >= min_time)
272 text_interval = foot_seconds * 2;
274 if(foot_seconds * 5 >= min_time)
275 text_interval = foot_seconds * 5;
279 for(int factor = 10, progression = 0; factor <= 100000; )
281 if(foot_seconds * factor >= min_time)
283 text_interval = foot_seconds * factor;
289 factor = (int)(factor * 2.5);
295 factor = (int)(factor * 2);
301 factor = (int)(factor * 2);
312 // One frame per text mark
313 if(frame_seconds >= min_time)
314 text_interval = frame_seconds;
316 if(frame_seconds * 2 >= min_time)
317 text_interval = frame_seconds * 2;
319 if(frame_seconds * 5 >= min_time)
320 text_interval = frame_seconds * 5;
324 for(int factor = 10, progression = 0; factor <= 100000; )
326 if(frame_seconds * factor >= min_time)
328 text_interval = frame_seconds * factor;
334 factor = (int)(factor * 2.5);
340 factor = (int)(factor * 2);
346 factor = (int)(factor * 2);
359 while(text_interval < min_time)
365 tick_interval = text_interval;
367 switch(mwindow->edl->session->time_format)
370 case TIME_FEET_FRAMES:
372 if(frame_seconds / time_per_pixel > TICK_SPACING)
373 tick_interval = frame_seconds;
377 // Get first text mark on or before window start
378 starting_mark = (int64_t)((double)mwindow->edl->local_session->view_start[pane->number] *
379 time_per_pixel / text_interval);
381 double start_position = (double)starting_mark * text_interval;
382 int64_t iteration = 0;
385 //printf("text_interval=%f\n", text_interval);
386 while(start_position + text_interval * iteration < view_end)
388 double position1 = start_position + text_interval * iteration;
389 int pixel = (int64_t)(position1 / time_per_pixel) -
390 mwindow->edl->local_session->view_start[pane->number];
393 Units::totext(string,
395 mwindow->edl->session->time_format,
397 mwindow->edl->session->frame_rate,
398 mwindow->edl->session->frames_per_foot);
399 set_color(get_resources()->default_text_color);
400 set_font(MEDIUMFONT);
402 draw_text(pixel + TEXT_MARGIN, get_text_ascent(MEDIUMFONT), string);
403 draw_line(pixel, LINE_MARGIN, pixel, get_h() - 2);
405 double position2 = start_position + text_interval * (iteration + 1);
406 int pixel2 = (int64_t)(position2 / time_per_pixel) -
407 mwindow->edl->local_session->view_start[pane->number];
409 for(double tick_position = position1;
410 tick_position < position2;
411 tick_position += tick_interval)
413 pixel = (int64_t)(tick_position / time_per_pixel) -
414 mwindow->edl->local_session->view_start[pane->number];
415 if(labs(pixel - pixel1) > 1 &&
416 labs(pixel - pixel2) > 1)
417 draw_line(pixel, TICK_MARGIN, pixel, get_h() - 2);
425 void MTimeBar::draw_range()
428 if(mwindow->edl->tracks->total_playable_vtracks() &&
429 mwindow->preferences->use_brender)
431 double time_per_pixel = (double)mwindow->edl->local_session->zoom_sample /
432 mwindow->edl->session->sample_rate;
433 x1 = (int)(mwindow->edl->session->brender_start / time_per_pixel) -
434 mwindow->edl->local_session->view_start[pane->number];
435 x2 = (int)(mwindow->session->brender_end / time_per_pixel) -
436 mwindow->edl->local_session->view_start[pane->number];
443 draw_top_background(get_parent(), 0, 0, x1, get_h());
445 draw_3segmenth(x1, 0, x2 - x1, mwindow->theme->get_image("timebar_brender"));
447 draw_top_background(get_parent(), x2, 0, get_w() - x2, get_h());
451 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
455 // int64_t pixel = position_to_pixel(
456 // mwindow->edl->local_session->get_selectionstart(1));
458 // set_color(mwindow->theme->timebar_cursor_colorg);
459 // draw_line(pixel, 0, pixel, get_h());
460 //printf("MTimeBar::draw_range %f %f\n", mwindow->session->brender_end, time_per_pixel);
463 void MTimeBar::select_label(double position)
465 EDL *edl = mwindow->edl;
467 gui->unlock_window();
468 gui->mbuttons->transport->handle_transport(STOP, 1, 0, 0);
471 position = mwindow->edl->align_to_frame(position, 1);
475 if(position > edl->local_session->get_selectionend(1) / 2 +
476 edl->local_session->get_selectionstart(1) / 2)
479 edl->local_session->set_selectionend(position);
483 edl->local_session->set_selectionstart(position);
488 edl->local_session->set_selectionstart(position);
489 edl->local_session->set_selectionend(position);
493 mwindow->cwindow->update(1, 0, 0, 0, 1);
497 gui->flash_canvas(1);
498 gui->zoombar->update();
504 int MTimeBar::resize_event()
506 reposition_window(mwindow->theme->mtimebar_x,
507 mwindow->theme->mtimebar_y,
508 mwindow->theme->mtimebar_w,
509 mwindow->theme->mtimebar_h);
514 int MTimeBar::resize_event(int x, int y, int w, int h)
524 // int MTimeBar::test_preview(int buttonpress)
532 void MTimeBar::handle_mwindow_drag()
534 //printf("TimeBar::cursor_motion_event %d %d\n", __LINE__, current_operation);
535 int relative_cursor_x = pane->canvas->get_relative_cursor_x();
536 if(relative_cursor_x >= pane->canvas->get_w() ||
537 relative_cursor_x < 0)
539 pane->canvas->start_dragscroll();
542 if(relative_cursor_x < pane->canvas->get_w() &&
543 relative_cursor_x >= 0)
545 pane->canvas->stop_dragscroll();
551 void MTimeBar::update(int flush)
553 TimeBar::update(flush);
556 void MTimeBar::update_clock(double position)
558 if(!mwindow->cwindow->playback_engine->is_playing_back)
559 gui->mainclock->update(position);
562 void MTimeBar::update_cursor()
564 int rx = get_relative_cursor_x();
565 double position = pixel_to_position(rx);
567 position = mwindow->edl->align_to_frame(position, 0);
568 position = MAX(0, position);
570 mwindow->select_point(position);
574 double MTimeBar::test_highlight()
576 // Don't crash during initialization
579 if(mwindow->session->current_operation == NO_OPERATION)
581 if(pane->canvas->is_event_win() &&
582 pane->canvas->cursor_inside())
584 int cursor_x = pane->canvas->get_cursor_x();
585 double position = (double)cursor_x *
586 (double)mwindow->edl->local_session->zoom_sample /
587 (double)mwindow->edl->session->sample_rate +
588 (double)mwindow->edl->local_session->view_start[pane->number] *
589 (double)mwindow->edl->local_session->zoom_sample /
590 (double)mwindow->edl->session->sample_rate;
591 pane->canvas->timebar_position = mwindow->edl->align_to_frame(position, 0);
594 //printf("MTimeBar::test_highlight %d %d %f\n", __LINE__, pane->canvas->cursor_inside(), pane->canvas->timebar_position);
595 return pane->canvas->timebar_position;
598 if(mwindow->session->current_operation == SELECT_REGION ||
599 mwindow->session->current_operation == DRAG_EDITHANDLE2)
601 //printf("MTimeBar::test_highlight %d %f\n", __LINE__, mwindow->gui->canvas->timebar_position);
602 return pane->canvas->timebar_position;
613 int MTimeBar::repeat_event(int64_t duration)
615 if(!pane->canvas->drag_scroll) return 0;
616 if(duration != BC_WindowBase::get_resources()->scroll_repeat) return 0;
620 int relative_cursor_x = pane->canvas->get_relative_cursor_x();
621 if(current_operation == TIMEBAR_DRAG)
623 if(relative_cursor_x >= pane->canvas->get_w())
625 distance = relative_cursor_x - pane->canvas->get_w();
629 if(relative_cursor_x < 0)
631 distance = relative_cursor_x;
640 mwindow->samplemovement(
641 mwindow->edl->local_session->view_start[pane->number] + distance,
650 int MTimeBar::button_press_event()
654 if(is_event_win() && cursor_above() && get_buttonpress() == 3)
657 menu->activate_menu();
661 if(!result) return TimeBar::button_press_event();
666 void MTimeBar::activate_timeline()
676 TimeBarPopupItem::TimeBarPopupItem(MWindow *mwindow,
682 this->mwindow = mwindow;
687 int TimeBarPopupItem::handle_event()
689 mwindow->edl->session->time_format = value;
690 mwindow->gui->update(0, 0, 1, 0, 0, 1, 0);
691 mwindow->gui->redraw_time_dependancies();
697 TimeBarPopup::TimeBarPopup(MWindow *mwindow)
704 this->mwindow = mwindow;
707 TimeBarPopup::~TimeBarPopup()
712 void TimeBarPopup::create_objects()
714 add_item(items[0] = new TimeBarPopupItem(mwindow,
718 add_item(items[1] = new TimeBarPopupItem(mwindow,
722 add_item(items[2] = new TimeBarPopupItem(mwindow,
726 add_item(items[3] = new TimeBarPopupItem(mwindow,
730 add_item(items[4] = new TimeBarPopupItem(mwindow,
732 TIME_SAMPLES_HEX_TEXT,
734 add_item(items[5] = new TimeBarPopupItem(mwindow,
738 add_item(items[6] = new TimeBarPopupItem(mwindow,
740 TIME_FEET_FRAMES_TEXT,
744 void TimeBarPopup::update()
746 for(int i = 0; i < TOTAL_TIMEFORMATS; i++)
748 if(items[i]->value == mwindow->edl->session->time_format)
750 items[i]->set_checked(1);
754 items[i]->set_checked(0);