/* * CINELERRA * Copyright (C) 2008 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 "apatchgui.h" #include "autoconf.h" #include "autos.h" #include "bcwindowbase.h" #include "cpanel.h" #include "cwindowgui.h" #include "cwindow.h" #include "edl.h" #include "edlsession.h" #include "filexml.h" #include "gwindow.h" #include "gwindowgui.h" #include "keyframe.h" #include "keyframepopup.h" #include "language.h" #include "localsession.h" #include "maincursor.h" #include "mainmenu.h" #include "mainundo.h" #include "mwindowgui.h" #include "mwindow.h" #include "patchbay.h" #include "patchgui.h" #include "track.h" #include "vpatchgui.h" KeyframePopup::KeyframePopup(MWindow *mwindow, MWindowGUI *gui) : BC_PopupMenu(0, 0, 0, "", 0) { this->mwindow = mwindow; this->gui = gui; key_show = 0; key_delete = 0; key_copy = 0; key_smooth = 0; key_linear = 0; key_free = 0; key_mbar = 0; key_mode_displayed = false; key_edit_displayed = false; } KeyframePopup::~KeyframePopup() { if( !key_mode_displayed ) { delete key_mbar; delete key_smooth; delete key_linear; delete key_free_t; delete key_free; } if( !key_edit_displayed ) { delete key_edit; } } void KeyframePopup::create_objects() { add_item(key_show = new KeyframePopupShow(mwindow, this)); add_item(key_delete = new KeyframePopupDelete(mwindow, this)); add_item(key_copy = new KeyframePopupCopy(mwindow, this)); key_edit = new KeyframePopupEdit(mwindow, this); key_mbar = new BC_MenuItem("-"); key_smooth = new KeyframePopupCurveMode(mwindow, this, FloatAuto::SMOOTH); key_linear = new KeyframePopupCurveMode(mwindow, this, FloatAuto::LINEAR); key_free_t = new KeyframePopupCurveMode(mwindow, this, FloatAuto::TFREE ); key_free = new KeyframePopupCurveMode(mwindow, this, FloatAuto::FREE ); } int KeyframePopup::update(Plugin *plugin, KeyFrame *keyframe) { this->keyframe_plugin = plugin; this->keyframe_auto = keyframe; this->keyframe_autos = 0; this->keyframe_automation = 0; handle_curve_mode(0, 0); return 0; } int KeyframePopup::update(Automation *automation, Autos *autos, Auto *auto_keyframe) { this->keyframe_plugin = 0; this->keyframe_automation = automation; this->keyframe_autos = autos; this->keyframe_auto = auto_keyframe; handle_curve_mode(autos, auto_keyframe); /* snap to cursor */ double current_position = mwindow->edl->local_session->get_selectionstart(1); double new_position = keyframe_automation->track->from_units(keyframe_auto->position); mwindow->edl->local_session->set_selectionstart(new_position); mwindow->edl->local_session->set_selectionend(new_position); if (current_position != new_position) { mwindow->edl->local_session->set_selectionstart(new_position); mwindow->edl->local_session->set_selectionend(new_position); mwindow->gui->lock_window(); mwindow->gui->update(1, 1, 1, 1, 1, 1, 0); mwindow->gui->unlock_window(); } return 0; } void KeyframePopup::handle_curve_mode(Autos *autos, Auto *auto_keyframe) // determines the type of automation node. if floatauto, adds // menu entries showing the curve mode of the node { if( !key_edit_displayed && keyframe_plugin ) { add_item(key_edit); key_edit_displayed = true; } else if( key_edit_displayed && !keyframe_plugin ) { remove_item(key_mbar); key_edit_displayed = false; } if(!key_mode_displayed && autos && autos->get_type() == AUTOMATION_TYPE_FLOAT) { // append additional menu entries showing the curve_mode add_item(key_mbar); add_item(key_smooth); add_item(key_linear); add_item(key_free_t); add_item(key_free); key_mode_displayed = true; } else if(key_mode_displayed && (!autos || autos->get_type() != AUTOMATION_TYPE_FLOAT)) { // remove additional menu entries remove_item(key_free); remove_item(key_free_t); remove_item(key_linear); remove_item(key_smooth); remove_item(key_mbar); key_mode_displayed = false; } if(key_mode_displayed && auto_keyframe) { // set checkmarks to display current mode key_smooth->toggle_mode((FloatAuto*)auto_keyframe); key_linear->toggle_mode((FloatAuto*)auto_keyframe); key_free_t->toggle_mode((FloatAuto*)auto_keyframe); key_free ->toggle_mode((FloatAuto*)auto_keyframe); } } KeyframePopupDelete::KeyframePopupDelete(MWindow *mwindow, KeyframePopup *popup) : BC_MenuItem(_("Delete keyframe")) { this->mwindow = mwindow; this->popup = popup; } KeyframePopupDelete::~KeyframePopupDelete() { } int KeyframePopupDelete::handle_event() { mwindow->undo->update_undo_before(_("delete keyframe"), 0); delete popup->keyframe_auto; mwindow->undo->update_undo_after(_("delete keyframe"), LOAD_ALL); mwindow->save_backup(); mwindow->gui->update(0, 1, // 1 for incremental drawing. 2 for full refresh 0, 0, 0, 0, 0); mwindow->update_plugin_guis(); mwindow->restart_brender(); mwindow->sync_parameters(CHANGE_EDL); return 1; } KeyframePopupShow::KeyframePopupShow(MWindow *mwindow, KeyframePopup *popup) : BC_MenuItem(_("Show keyframe settings")) { this->mwindow = mwindow; this->popup = popup; } KeyframePopupShow::~KeyframePopupShow() { } int KeyframePopupShow::handle_event() { if (popup->keyframe_plugin) { mwindow->update_plugin_guis(); mwindow->show_plugin(popup->keyframe_plugin); } else if( popup->keyframe_automation ) { /* mwindow->cwindow->gui->lock_window(); int show_window = 1; if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos || popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos) { mwindow->cwindow->gui->set_operation(CWINDOW_PROJECTOR); } else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos || popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos) { mwindow->cwindow->gui->set_operation(CWINDOW_CAMERA); } else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos) { // no window to be shown show_window = 0; // first find the appropriate patchgui PatchBay *patchbay = mwindow->gui->patchbay; PatchGUI *patchgui = 0; for (int i = 0; i < patchbay->patches.total; i++) if (patchbay->patches.values[i]->track == popup->keyframe_automation->track) patchgui = patchbay->patches.values[i]; if (patchgui != 0) { // FIXME: repositioning of the listbox needs support in guicast // int cursor_x = popup->get_relative_cursor_x(); // int cursor_y = popup->get_relative_cursor_y(); // vpatchgui->mode->reposition_window(cursor_x, cursor_y); // Open the popup menu VPatchGUI *vpatchgui = (VPatchGUI *)patchgui; vpatchgui->mode->activate_menu(); } } else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos) { mwindow->cwindow->gui->set_operation(CWINDOW_MASK); } else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos) { // no window to be shown show_window = 0; // first find the appropriate patchgui PatchBay *patchbay = mwindow->gui->patchbay; PatchGUI *patchgui = 0; for (int i = 0; i < patchbay->patches.total; i++) if (patchbay->patches.values[i]->track == popup->keyframe_automation->track) patchgui = patchbay->patches.values[i]; if (patchgui != 0) { // Open the popup menu at current mouse position APatchGUI *apatchgui = (APatchGUI *)patchgui; int cursor_x = popup->get_relative_cursor_x(); int cursor_y = popup->get_relative_cursor_y(); apatchgui->pan->activate(cursor_x, cursor_y); } } else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos) { // no window to be shown, so do nothing // IDEA: open window for fading show_window = 0; } else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos) { // no window to be shown, so do nothing // IDEA: directly switch show_window = 0; } else; // ensure bringing to front if (show_window) { ((CPanelToolWindow *)(mwindow->cwindow->gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]))->set_shown(0); ((CPanelToolWindow *)(mwindow->cwindow->gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]))->set_shown(1); } mwindow->cwindow->gui->unlock_window(); */ } return 1; } KeyframePopupCopy::KeyframePopupCopy(MWindow *mwindow, KeyframePopup *popup) : BC_MenuItem(_("Copy keyframe")) { this->mwindow = mwindow; this->popup = popup; } KeyframePopupCopy::~KeyframePopupCopy() { } int KeyframePopupCopy::handle_event() { /* FIXME: we want to copy just keyframe under cursor, NOT all keyframes at this frame - very hard to do, so this is good approximation for now... */ #if 0 if (popup->keyframe_automation) { FileXML file; EDL *edl = mwindow->edl; Track *track = popup->keyframe_automation->track; int64_t position = popup->keyframe_auto->position; AutoConf autoconf; // first find out type of our auto autoconf.set_all(0); if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos) autoconf.projector = 1; else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos) autoconf.pzoom = 1; else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos) autoconf.camera = 1; else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos) autoconf.czoom = 1; else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos) autoconf.mode = 1; else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos) autoconf.mask = 1; else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos) autoconf.pan = 1; else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos) autoconf.fade = 1; else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos) autoconf.mute = 1; // now create a clipboard file.tag.set_title("AUTO_CLIPBOARD"); file.tag.set_property("LENGTH", 0); file.tag.set_property("FRAMERATE", edl->session->frame_rate); file.tag.set_property("SAMPLERATE", edl->session->sample_rate); file.append_tag(); file.append_newline(); file.append_newline(); /* track->copy_automation(position, position, &file, 0, 0); */ file.tag.set_title("TRACK"); // Video or audio track->save_header(&file); file.append_tag(); file.append_newline(); track->automation->copy(position, position, &file, 0, 0, &autoconf); file.tag.set_title("/TRACK"); file.append_tag(); file.append_newline(); file.append_newline(); file.append_newline(); file.append_newline(); file.tag.set_title("/AUTO_CLIPBOARD"); file.append_tag(); file.append_newline(); file.terminate_string(); mwindow->gui->lock_window(); mwindow->gui->get_clipboard()->to_clipboard(file.string, strlen(file.string), SECONDARY_SELECTION); mwindow->gui->unlock_window(); } else #endif mwindow->copy_automation(); return 1; } KeyframePopupCurveMode::KeyframePopupCurveMode( MWindow *mwindow, KeyframePopup *popup, int curve_mode) : BC_MenuItem( get_labeltext(curve_mode)) { this->curve_mode = curve_mode; this->mwindow = mwindow; this->popup = popup; } KeyframePopupCurveMode::~KeyframePopupCurveMode() { } const char* KeyframePopupCurveMode::get_labeltext(int mode) { switch(mode) { case FloatAuto::SMOOTH: return _("smooth curve"); case FloatAuto::LINEAR: return _("linear segments"); case FloatAuto::TFREE: return _("tangent edit"); case FloatAuto::FREE: return _("disjoint edit"); } return "misconfigured"; } void KeyframePopupCurveMode::toggle_mode(FloatAuto *keyframe) { set_checked(curve_mode == keyframe->curve_mode); } int KeyframePopupCurveMode::handle_event() { if (popup->keyframe_autos && popup->keyframe_autos->get_type() == AUTOMATION_TYPE_FLOAT) { mwindow->undo->update_undo_before(_("change keyframe curve mode"), 0); ((FloatAuto*)popup->keyframe_auto)-> change_curve_mode((FloatAuto::t_mode)curve_mode); // if we switched to some "auto" mode, this may imply a // real change to parameters, so this needs to be undoable... mwindow->undo->update_undo_after(_("change keyframe curve mode"), LOAD_ALL); mwindow->save_backup(); mwindow->gui->update(0, 1, 0,0,0,0,0); // incremental redraw for canvas mwindow->cwindow->update(0,0, 1, 0,0); // redraw tool window in compositor mwindow->update_plugin_guis(); mwindow->restart_brender(); mwindow->sync_parameters(CHANGE_EDL); } return 1; } KeyframePopupEdit::KeyframePopupEdit(MWindow *mwindow, KeyframePopup *popup) : BC_MenuItem(_("Edit Params...")) { this->mwindow = mwindow; this->popup = popup; } int KeyframePopupEdit::handle_event() { mwindow->show_keyframe_gui(popup->keyframe_plugin); return 1; } KeyframeHidePopup::KeyframeHidePopup(MWindow *mwindow, MWindowGUI *gui) : BC_PopupMenu(0, 0, 0, "", 0) { this->mwindow = mwindow; this->gui = gui; this->keyframe_autos = 0; } KeyframeHidePopup::~KeyframeHidePopup() { } void KeyframeHidePopup::create_objects() { add_item(new KeyframePopupHide(mwindow, this)); } int KeyframeHidePopup::update(Autos *autos) { this->keyframe_autos = autos; return 0; } KeyframePopupHide::KeyframePopupHide(MWindow *mwindow, KeyframeHidePopup *popup) : BC_MenuItem(_("Hide keyframe type")) { this->mwindow = mwindow; this->popup = popup; } int KeyframePopupHide::handle_event() { // Get the array index of the curve int update_gui = 0; if(popup->keyframe_autos) { if(popup->keyframe_autos->type == Autos::AUTOMATION_TYPE_PLUGIN) { mwindow->edl->session->auto_conf->plugins = 0; update_gui = 1; } else { Track *track = popup->keyframe_autos->track; if(track) { Automation *automation = track->automation; if(automation) { for(int i = 0; i < AUTOMATION_TOTAL; i++) { if(automation->autos[i] == popup->keyframe_autos) { mwindow->edl->session->auto_conf->autos[i] = 0; update_gui = 1; break; } } } } } } if(update_gui) { mwindow->gui->update(0, 1, // 1 for incremental drawing. 2 for full refresh 0, 0, 0, 0, 0); mwindow->gui->mainmenu->update_toggles(1); mwindow->gui->unlock_window(); mwindow->gwindow->gui->update_toggles(1); mwindow->gui->lock_window("KeyframePopupHide::handle_event"); } return 1; }