X-Git-Url: https://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Ftimebar.C;fp=cinelerra-5.1%2Fcinelerra%2Ftimebar.C;h=a09257bc1b502dd04f6e0b8f6428f6895d18e58f;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=0000000000000000000000000000000000000000;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/timebar.C b/cinelerra-5.1/cinelerra/timebar.C new file mode 100644 index 00000000..a09257bc --- /dev/null +++ b/cinelerra-5.1/cinelerra/timebar.C @@ -0,0 +1,979 @@ + +/* + * CINELERRA + * Copyright (C) 1997-2014 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "bcsignals.h" +#include "clip.h" +#include "cplayback.h" +#include "cursors.h" +#include "cwindow.h" +#include "edl.h" +#include "edlsession.h" +#include "filexml.h" +#include "fonts.h" +#include "labels.h" +#include "labeledit.h" +#include "localsession.h" +#include "maincursor.h" +#include "mainundo.h" +#include "mbuttons.h" +#include "mwindow.h" +#include "mwindowgui.h" +#include "patchbay.h" +#include "preferences.h" +#include "recordlabel.h" +#include "localsession.h" +#include "mainsession.h" +#include "theme.h" +#include "timebar.h" +#include "timelinepane.h" +#include "trackcanvas.h" +#include "tracks.h" +#include "transportque.h" +#include "units.h" +#include "vframe.h" +#include "vwindow.h" +#include "vwindowgui.h" +#include "zoombar.h" + + +LabelGUI::LabelGUI(MWindow *mwindow, + TimeBar *timebar, + int64_t pixel, + int y, + double position, + VFrame **data) + : BC_Toggle(translate_pixel(mwindow, pixel), + y, + data ? data : mwindow->theme->label_toggle, + 0) +{ + this->mwindow = mwindow; + this->timebar = timebar; + this->gui = 0; + this->pixel = pixel; + this->position = position; + this->label = 0; +} + +LabelGUI::~LabelGUI() +{ +} + +int LabelGUI::get_y(MWindow *mwindow, TimeBar *timebar) +{ + return timebar->get_h() - + mwindow->theme->label_toggle[0]->get_h(); +} + +int LabelGUI::translate_pixel(MWindow *mwindow, int pixel) +{ + int result = pixel - mwindow->theme->label_toggle[0]->get_w() / 2; + return result; +} + +void LabelGUI::reposition(int flush) +{ + reposition_window(translate_pixel(mwindow, pixel), + BC_Toggle::get_y()); +} + +int LabelGUI::button_press_event() +{ + int result = 0; + + if (this->is_event_win() && get_buttonpress() == 3) { + if (label) + timebar->label_edit->edit_label(label); + result = 1; + } else { + result = BC_Toggle::button_press_event(); + } + if (label) + set_tooltip(this->label->textstr); + return result; +} + +int LabelGUI::handle_event() +{ + timebar->select_label(position); + return 1; +} + + +InPointGUI::InPointGUI(MWindow *mwindow, + TimeBar *timebar, + int64_t pixel, + double position) + : LabelGUI(mwindow, + timebar, + pixel, + get_y(mwindow, timebar), + position, + mwindow->theme->in_point) +{ +//printf("InPointGUI::InPointGUI %d %d\n", pixel, get_y(mwindow, timebar)); +} +InPointGUI::~InPointGUI() +{ +} +int InPointGUI::get_y(MWindow *mwindow, TimeBar *timebar) +{ + int result; + result = timebar->get_h() - + mwindow->theme->in_point[0]->get_h(); + return result; +} + + +OutPointGUI::OutPointGUI(MWindow *mwindow, + TimeBar *timebar, + int64_t pixel, + double position) + : LabelGUI(mwindow, + timebar, + pixel, + get_y(mwindow, timebar), + position, + mwindow->theme->out_point) +{ +//printf("OutPointGUI::OutPointGUI %d %d\n", pixel, get_y(mwindow, timebar)); +} +OutPointGUI::~OutPointGUI() +{ +} +int OutPointGUI::get_y(MWindow *mwindow, TimeBar *timebar) +{ + return timebar->get_h() - + mwindow->theme->out_point[0]->get_h(); +} + + +PresentationGUI::PresentationGUI(MWindow *mwindow, + TimeBar *timebar, + int64_t pixel, + double position) + : LabelGUI(mwindow, timebar, pixel, get_y(mwindow, timebar), position) +{ +} +PresentationGUI::~PresentationGUI() +{ +} + +TimeBar::TimeBar(MWindow *mwindow, + BC_WindowBase *gui, + int x, + int y, + int w, + int h) + : BC_SubWindow(x, y, w, h) +{ +//printf("TimeBar::TimeBar %d %d %d %d\n", x, y, w, h); + this->gui = gui; + this->mwindow = mwindow; + label_edit = new LabelEdit(mwindow, mwindow->awindow, 0); + pane = 0; + highlighted = 0; +} + +TimeBar::~TimeBar() +{ + if(in_point) delete in_point; + if(out_point) delete out_point; + if(label_edit) delete label_edit; + labels.remove_all_objects(); + presentations.remove_all_objects(); +} + +void TimeBar::create_objects() +{ + in_point = 0; + out_point = 0; +//printf("TimeBar::create_objects %d\n", __LINE__); + current_operation = TIMEBAR_NONE; + set_cursor(UPRIGHT_ARROW_CURSOR, 0, 0); + update(0); +} + + +int64_t TimeBar::position_to_pixel(double position) +{ + get_edl_length(); + return (int64_t)(position / time_per_pixel); +} + + +double TimeBar::pixel_to_position(int pixel) +{ + if(pane) + { + pixel += mwindow->edl->local_session->view_start[pane->number]; + } + + return (double)pixel * + mwindow->edl->local_session->zoom_sample / + mwindow->edl->session->sample_rate; +} + +void TimeBar::update_labels() +{ + int output = 0; + EDL *edl = get_edl(); + + if(edl) + { + for(Label *current = edl->labels->first; + current; + current = NEXT) + { + int64_t pixel = position_to_pixel(current->position); + + if(pixel >= 0 && pixel < get_w()) + { +// Create new label + if(output >= labels.total) + { + LabelGUI *new_label; + add_subwindow(new_label = + new LabelGUI(mwindow, + this, + pixel, + LabelGUI::get_y(mwindow, this), + current->position)); + new_label->set_cursor(INHERIT_CURSOR, 0, 0); + new_label->set_tooltip(current->textstr); + new_label->label = current; + labels.append(new_label); + } + else +// Reposition old label + { + LabelGUI *gui = labels.values[output]; + if(gui->pixel != pixel) + { + gui->pixel = pixel; + gui->reposition(0); + } + else + { + gui->draw_face(1,0); + } + + labels.values[output]->position = current->position; + labels.values[output]->set_tooltip(current->textstr); + labels.values[output]->label = current; + } + + if(edl->local_session->get_selectionstart(1) <= current->position && + edl->local_session->get_selectionend(1) >= current->position) + labels.values[output]->update(1); + else + if(labels.values[output]->get_value()) + labels.values[output]->update(0); + + output++; + } + } + } + +// Delete excess labels + while(labels.total > output) + { + labels.remove_object(); + } + +// Get the labels to show + show_window(0); +} + +void TimeBar::update_highlights() +{ + for(int i = 0; i < labels.total; i++) + { + LabelGUI *label = labels.values[i]; + if(mwindow->edl->equivalent(label->position, + mwindow->edl->local_session->get_selectionstart(1)) || + mwindow->edl->equivalent(label->position, + mwindow->edl->local_session->get_selectionend(1))) + { + if(!label->get_value()) label->update(1); + } + else + if(label->get_value()) label->update(0); + } + + if(mwindow->edl->equivalent(mwindow->edl->local_session->get_inpoint(), + mwindow->edl->local_session->get_selectionstart(1)) || + mwindow->edl->equivalent(mwindow->edl->local_session->get_inpoint(), + mwindow->edl->local_session->get_selectionend(1))) + { + if(in_point) in_point->update(1); + } + else + if(in_point) in_point->update(0); + + if(mwindow->edl->equivalent(mwindow->edl->local_session->get_outpoint(), + mwindow->edl->local_session->get_selectionstart(1)) || + mwindow->edl->equivalent(mwindow->edl->local_session->get_outpoint(), + mwindow->edl->local_session->get_selectionend(1))) + { + if(out_point) out_point->update(1); + } + else + if(out_point) out_point->update(0); +} + +void TimeBar::update_points() +{ + EDL *edl = get_edl(); + int64_t pixel = !edl ? 0 : + position_to_pixel(edl->local_session->get_inpoint()); + + if(in_point) + { + if(edl && + edl->local_session->inpoint_valid() && + pixel >= 0 && pixel < get_w()) + { + if(!EQUIV(edl->local_session->get_inpoint(), in_point->position) || + in_point->pixel != pixel) + { + in_point->pixel = pixel; + in_point->position = edl->local_session->get_inpoint(); + in_point->reposition(0); + } + else + { + in_point->draw_face(1, 0); + } + } + else + { + delete in_point; + in_point = 0; + } + } + else + if(edl && edl->local_session->inpoint_valid() && + pixel >= 0 && pixel < get_w()) + { + add_subwindow(in_point = new InPointGUI(mwindow, + this, pixel, edl->local_session->get_inpoint())); + in_point->set_cursor(ARROW_CURSOR, 0, 0); + } + + pixel = !edl ? 0 : + position_to_pixel(edl->local_session->get_outpoint()); + + if(out_point) + { + if( edl && edl->local_session->outpoint_valid() && + pixel >= 0 && pixel < get_w()) + { + if(!EQUIV(edl->local_session->get_outpoint(), out_point->position) || + out_point->pixel != pixel) + { + out_point->pixel = pixel; + out_point->position = edl->local_session->get_outpoint(); + out_point->reposition(0); + } + else + { + out_point->draw_face(1, 0); + } + } + else + { + delete out_point; + out_point = 0; + } + } + else + if(edl && + edl->local_session->outpoint_valid() && + pixel >= 0 && pixel < get_w()) + { + add_subwindow(out_point = new OutPointGUI(mwindow, + this, pixel, edl->local_session->get_outpoint())); + out_point->set_cursor(ARROW_CURSOR, 0, 0); + } + +// flush(); +} + +void TimeBar::update_clock(double position) +{ +} + +void TimeBar::update(int flush) +{ + draw_time(); +// Need to redo these when range is drawn to get the background updated. + update_labels(); + update_points(); + + + EDL *edl = get_edl(); + int64_t pixel = -1; + int x = get_relative_cursor_x(); +// Draw highlight position + if(edl && + (highlighted || current_operation == TIMEBAR_DRAG) && + x >= 0 && x < get_w()) + { +//printf("TimeBar::update %d %d\n", __LINE__, x); + double position = pixel_to_position(x); + + position = get_edl()->align_to_frame(position, 0); + pixel = position_to_pixel(position); + update_clock(position); + } + + if(pixel < 0) + { + double position = test_highlight(); + if(position >= 0) pixel = position_to_pixel(position); + } + + + if(pixel >= 0 && pixel < get_w()) + { + set_color(mwindow->theme->timebar_cursor_color); + set_line_dashes(1); +//printf("TimeBar::update %d pane=%d pixel=%jd\n", __LINE__, pane->number, pixel); + draw_line(pixel, 0, pixel, get_h()); + set_line_dashes(0); + } + + + if(edl) + { + double playback_start = edl->local_session->playback_start; + if( playback_start >= 0 ) { + int64_t pixel = position_to_pixel(playback_start); + set_color(mwindow->theme->timebar_cursor_color ^ 0x0000ff); + draw_line(pixel, 0, pixel, get_h()); + double playback_end = edl->local_session->playback_end; + if( playback_end > playback_start ) { + pixel = position_to_pixel(playback_end); + set_color(mwindow->theme->timebar_cursor_color ^ 0x00ff00); + draw_line(pixel, 0, pixel, get_h()); + } + } + + double position = edl->local_session->get_selectionstart(1); + int64_t pixel = position_to_pixel(position); +// Draw insertion point position. + set_color(mwindow->theme->timebar_cursor_color); + draw_line(pixel, 0, pixel, get_h()); + } + + update_highlights(); + +// Get the labels to show + show_window(0); + flash(flush); +//printf("TimeBar::update %d this=%p %d\n", __LINE__, this, current_operation); +} + + + +int TimeBar::delete_project() +{ +// labels->delete_all(); + return 0; +} + +int TimeBar::save(FileXML *xml) +{ +// labels->save(xml); + return 0; +} + + + + +void TimeBar::draw_time() +{ +} + +EDL* TimeBar::get_edl() +{ + return mwindow->edl; +} + + + +void TimeBar::draw_range() +{ + + +//printf("TimeBar::draw_range %d %p\n", __LINE__, get_edl()); + if(has_preview() && get_edl()) + { + int x1, x2; + get_preview_pixels(x1, x2); + +//printf("TimeBar::draw_range %f %d %d\n", edl_length, x1, x2); + draw_3segmenth(0, 0, x1, mwindow->theme->timebar_view_data); + draw_top_background(get_parent(), x1, 0, x2 - x1, get_h()); + draw_3segmenth(x2, 0, get_w() - x2, mwindow->theme->timebar_view_data); + + set_color(BLACK); + draw_line(x1, 0, x1, get_h()); + draw_line(x2, 0, x2, get_h()); + + + EDL *edl = get_edl(); + if(edl) + { + int64_t pixel = position_to_pixel( + edl->local_session->get_selectionstart(1)); +// Draw insertion point position if this timebar belongs to a window which +// has something other than the master EDL. + set_color(mwindow->theme->timebar_cursor_color); + draw_line(pixel, 0, pixel, get_h()); + } + } + else + draw_top_background(get_parent(), 0, 0, get_w(), get_h()); +} + +void TimeBar::select_label(double position) +{ +} + + + +int TimeBar::draw() +{ + return 0; +} + +double TimeBar::get_edl_length() +{ + edl_length = 0; + + if(get_edl()) + { +//printf("TimeBar::get_edl_length 1 %f\n", get_edl()->tracks->total_playable_length()); + edl_length = get_edl()->tracks->total_playable_length(); + } + +//printf("TimeBar::get_edl_length 2\n"); + if(!EQUIV(edl_length, 0)) + { +//printf("TimeBar::get_edl_length 3\n"); + time_per_pixel = edl_length / get_w(); +//printf("TimeBar::get_edl_length 4\n"); + } + else + { + time_per_pixel = 0; + } +//printf("TimeBar::get_edl_length 5\n"); + + return edl_length; +} + +int TimeBar::get_preview_pixels(int &x1, int &x2) +{ + x1 = 0; + x2 = 0; + + get_edl_length(); + + if(get_edl()) + { + if(!EQUIV(edl_length, 0)) + { + if(get_edl()->local_session->preview_end <= 0 || + get_edl()->local_session->preview_end > edl_length) + get_edl()->local_session->preview_end = edl_length; + if(get_edl()->local_session->preview_start > + get_edl()->local_session->preview_end) + get_edl()->local_session->preview_start = 0; + x1 = (int)(get_edl()->local_session->preview_start / time_per_pixel); + x2 = (int)(get_edl()->local_session->preview_end / time_per_pixel); + } + else + { + x1 = 0; + x2 = get_w(); + } + } +// printf("TimeBar::get_preview_pixels %f %f %d %d\n", +// get_edl()->local_session->preview_start, +// get_edl()->local_session->preview_end, +// x1, +// x2); + return 0; +} + + +int TimeBar::test_preview(int buttonpress) +{ + int result = 0; + + + if(get_edl() && cursor_inside() && buttonpress >= 0) + { + int x1, x2, x = get_relative_cursor_x(); + get_preview_pixels(x1, x2); +//printf("TimeBar::test_preview %d %d %d\n", x1, x2, x); +// Inside left handle + if(x >= x1 - HANDLE_W && x < x1 + HANDLE_W && +// Ignore left handle if both handles are up against the left side + x2 > HANDLE_W) + { + if(buttonpress) + { + current_operation = TIMEBAR_DRAG_LEFT; + start_position = get_edl()->local_session->preview_start; + start_cursor_x = x; + } + else if(get_cursor() != LEFT_CURSOR) + set_cursor(LEFT_CURSOR, 0, 1); + result = 1; + } +// Inside right handle + else if(x >= x2 - HANDLE_W && x < x2 + HANDLE_W && +// Ignore right handle if both handles are up against the right side + x1 < get_w() - HANDLE_W) + { + if(buttonpress) + { + current_operation = TIMEBAR_DRAG_RIGHT; + start_position = get_edl()->local_session->preview_end; + start_cursor_x = x; + } + else if(get_cursor() != RIGHT_CURSOR) + set_cursor(RIGHT_CURSOR, 0, 1); + result = 1; + } +// Inside preview + else if(get_button_down() && get_buttonpress() == 3 && + x >= x1 && x < x2) + { + if(buttonpress) + { + current_operation = TIMEBAR_DRAG_CENTER; + starting_start_position = get_edl()->local_session->preview_start; + starting_end_position = get_edl()->local_session->preview_end; + start_cursor_x = x; + } + if(get_cursor() != HSEPARATE_CURSOR) + set_cursor(HSEPARATE_CURSOR, 0, 1); + result = 1; + } + } + + if(!result && get_cursor() != ARROW_CURSOR) + set_cursor(ARROW_CURSOR, 0, 1); + + + return result; +} + +int TimeBar::move_preview(int &redraw) +{ + int result = 0, x = get_relative_cursor_x(); + + if(current_operation == TIMEBAR_DRAG_LEFT) + { + get_edl()->local_session->preview_start = + start_position + time_per_pixel * (x - start_cursor_x); + CLAMP(get_edl()->local_session->preview_start, + 0, + get_edl()->local_session->preview_end); + result = 1; + } + else + if(current_operation == TIMEBAR_DRAG_RIGHT) + { + get_edl()->local_session->preview_end = + start_position + time_per_pixel * (x - start_cursor_x); + CLAMP(get_edl()->local_session->preview_end, + get_edl()->local_session->preview_start, + edl_length); + result = 1; + } + else + if(current_operation == TIMEBAR_DRAG_CENTER) + { + double dt = time_per_pixel * (x - start_cursor_x); + get_edl()->local_session->preview_start = starting_start_position + dt; + get_edl()->local_session->preview_end = starting_end_position + dt; + if(get_edl()->local_session->preview_start < 0) + { + get_edl()->local_session->preview_end -= get_edl()->local_session->preview_start; + get_edl()->local_session->preview_start = 0; + } + else + if(get_edl()->local_session->preview_end > edl_length) + { + get_edl()->local_session->preview_start -= get_edl()->local_session->preview_end - edl_length; + get_edl()->local_session->preview_end = edl_length; + } + result = 1; + } + +//printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation); + + if(result) + { + update_preview(); + redraw = 1; + } +//printf("TimeBar::move_preview %d %d\n", __LINE__, current_operation); + + return result; +} + +void TimeBar::update_preview() +{ +} + +int TimeBar::samplemovement() +{ + return 0; +} + +void TimeBar::stop_playback() +{ +} + +int TimeBar::button_press_event() +{ + int result = 0; + if(is_event_win() && cursor_above()) + { + if(has_preview() && get_buttonpress() == 3) + { + result = test_preview(1); + } +// Change time format + else if(ctrl_down()) + { + if(get_buttonpress() == 1) + mwindow->next_time_format(); + else + if(get_buttonpress() == 2) + mwindow->prev_time_format(); + result = 1; + } + else if(get_buttonpress() == 1) + { + stop_playback(); + +// Select region between two labels + if(get_double_click()) + { + int x = get_relative_cursor_x(); + double position = pixel_to_position(x); +// Test labels + select_region(position); + } + else + { + +// Reposition highlight cursor + update_cursor(); + current_operation = TIMEBAR_DRAG; + activate_timeline(); + } + result = 1; + } + } + return result; +} + +void TimeBar::activate_timeline() +{ + mwindow->gui->activate_timeline(); +} + +int TimeBar::cursor_motion_event() +{ + int result = 0; + int redraw = 0; + +//printf("TimeBar::cursor_motion_event %d %p %d\n", __LINE__, this, current_operation); + switch(current_operation) + { + case TIMEBAR_DRAG: + { + update_cursor(); + handle_mwindow_drag(); + result = 1; +//printf("TimeBar::cursor_motion_event %d %d\n", __LINE__, current_operation); + break; + } + + + case TIMEBAR_DRAG_LEFT: + case TIMEBAR_DRAG_RIGHT: + case TIMEBAR_DRAG_CENTER: + if(has_preview()) + result = move_preview(redraw); + break; + + default: + if(cursor_above()) + { + highlighted = 1; + redraw = 1; + } + +//printf("TimeBar::cursor_motion_event 20\n"); + if(has_preview()) + result = test_preview(0); +//printf("TimeBar::cursor_motion_event 30\n"); + break; + } + + +//printf("TimeBar::cursor_motion_event %d %d\n", __LINE__, current_operation); + if(redraw) + { + update(1); + } +//printf("TimeBar::cursor_motion_event %d %p %d\n", __LINE__, this, current_operation); + + return result; +} + +int TimeBar::cursor_leave_event() +{ + if(highlighted) + { + highlighted = 0; + update(1); + } + return 0; +} + +int TimeBar::button_release_event() +{ +//printf("TimeBar::button_release_event %d %d\n", __LINE__, current_operation); + int result = 0; + int need_redraw = 0; + switch(current_operation) + { + case TIMEBAR_DRAG: + mwindow->gui->get_focused_pane()->canvas->stop_dragscroll(); + current_operation = TIMEBAR_NONE; + need_redraw = 1; + result = 1; + break; + + default: + if(current_operation != TIMEBAR_NONE) + { + current_operation = TIMEBAR_NONE; + result = 1; + } + break; + } + + if((!cursor_above() && highlighted) || need_redraw) + { + highlighted = 0; + update(1); + } + + return result; +} + +// Update the selection cursor during a dragging operation +void TimeBar::update_cursor() +{ +} + +void TimeBar::handle_mwindow_drag() +{ +} + +int TimeBar::select_region(double position) +{ + Label *start = 0, *end = 0, *current; + for(current = mwindow->edl->labels->first; current; current = NEXT) + { + if(current->position > position) + { + end = current; + break; + } + } + + for(current = mwindow->edl->labels->last ; current; current = PREVIOUS) + { + if(current->position <= position) + { + start = current; + break; + } + } + +// Select region + if(end != start) + { + if(!start) + mwindow->edl->local_session->set_selectionstart(0); + else + mwindow->edl->local_session->set_selectionstart(start->position); + + if(!end) + mwindow->edl->local_session->set_selectionend(mwindow->edl->tracks->total_length()); + else + mwindow->edl->local_session->set_selectionend(end->position); + } + else + if(end || start) + { + mwindow->edl->local_session->set_selectionstart(start->position); + mwindow->edl->local_session->set_selectionend(start->position); + } + +// Que the CWindow + mwindow->cwindow->update(1, 0, 0); + mwindow->gui->hide_cursor(0); + mwindow->gui->draw_cursor(1); + mwindow->gui->flash_canvas(0); + mwindow->gui->activate_timeline(); + mwindow->gui->zoombar->update(); + update_highlights(); + return 0; +} + + + + +int TimeBar::delete_arrows() +{ + return 0; +} + +double TimeBar::test_highlight() +{ + return -1; +} + +