X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fpatchbay.C;fp=cinelerra-5.1%2Fcinelerra%2Fpatchbay.C;h=cb6c0c64214084f556587e9a31a28be6c9782dee;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=0000000000000000000000000000000000000000;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/patchbay.C b/cinelerra-5.1/cinelerra/patchbay.C new file mode 100644 index 00000000..cb6c0c64 --- /dev/null +++ b/cinelerra-5.1/cinelerra/patchbay.C @@ -0,0 +1,582 @@ + +/* + * 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 "apatchgui.h" +#include "automation.h" +#include "floatauto.h" +#include "floatautos.h" +#include "clip.h" +#include "edl.h" +#include "edlsession.h" +#include "filexml.h" +#include "intauto.h" +#include "intautos.h" +#include "language.h" +#include "localsession.h" +#include "mainundo.h" +#include "mwindow.h" +#include "mwindowgui.h" +#include "patchbay.h" +#include "patchgui.h" +#include "mainsession.h" +#include "strack.h" +#include "theme.h" +#include "timelinepane.h" +#include "track.h" +#include "trackcanvas.h" +#include "tracks.h" +#include "vpatchgui.h" + + + + + + +NudgePopup::NudgePopup(MWindow *mwindow, PatchBay *patchbay) + : BC_PopupMenu(0, + 0, + 0, + "", + 0) +{ + this->mwindow = mwindow; + this->patchbay = patchbay; +} + +NudgePopup::~NudgePopup() +{ +} + + +void NudgePopup::create_objects() +{ + add_item(seconds_item = new NudgePopupSeconds(this)); + add_item(native_item = new NudgePopupNative(this)); +} + +void NudgePopup::activate_menu(PatchGUI *gui) +{ +// Set checked status + seconds_item->set_checked(mwindow->edl->session->nudge_format ? 1 : 0); + native_item->set_checked(mwindow->edl->session->nudge_format ? 0 : 1); + +// Set native units to track format + native_item->set_text(gui->track->data_type == TRACK_AUDIO ? + (char*)_("Samples") : + (char*)_("Frames")); + +// Show it + BC_PopupMenu::activate_menu(); +} + + + +NudgePopupSeconds::NudgePopupSeconds(NudgePopup *popup) + : BC_MenuItem(_("Seconds")) +{ + this->popup = popup; +} + +int NudgePopupSeconds::handle_event() +{ + popup->mwindow->edl->session->nudge_format = 1; + popup->mwindow->gui->update_patchbay(); + return 1; +} + + + + + +NudgePopupNative::NudgePopupNative(NudgePopup *popup) + : BC_MenuItem("") +{ + this->popup = popup; +} + +int NudgePopupNative::handle_event() +{ + popup->mwindow->edl->session->nudge_format = 0; + popup->mwindow->gui->update_patchbay(); + return 1; +} + + + + + + + + + +PatchBay::PatchBay(MWindow *mwindow, MWindowGUI *gui) + : BC_SubWindow(mwindow->theme->patchbay_x, + mwindow->theme->patchbay_y, + mwindow->theme->patchbay_w, + mwindow->theme->patchbay_h) +{ + this->mwindow = mwindow; + this->gui = gui; + this->pane = 0; + drag_operation = Tracks::NONE; + for(int i = 0; i < TRANSFER_TYPES; i++) mode_icons[i] = 0; +} + +PatchBay::PatchBay(MWindow *mwindow, + TimelinePane *pane, + int x, + int y, + int w, + int h) + : BC_SubWindow(x, + y, + w, + h) +{ + this->mwindow = mwindow; + this->gui = mwindow->gui; + this->pane = pane; + drag_operation = Tracks::NONE; + for(int i = 0; i < TRANSFER_TYPES; i++) mode_icons[i] = 0; +// printf("PatchBay::PatchBay %d %d %d %d %d\n", +// __LINE__, +// x, +// y, +// w, +// h); +} + +PatchBay::~PatchBay() +{ + delete_all_patches(); + for(int i = 0; i < TRANSFER_TYPES; i++) delete mode_icons[i]; +} + + +int PatchBay::delete_all_patches() +{ + patches.remove_all_objects(); + return 0; +} + +void PatchBay::create_objects() +{ + draw_top_background(get_parent(), 0, 0, get_w(), get_h()); + flash(0); + +// Create icons for mode types + static const char *mode_types[] = { + "mode_normal", + "mode_add", + "mode_subtract", + "mode_multiply", + "mode_divide", + "mode_replace", + "mode_max", + "mode_min", + "mode_average", + "mode_darken", + "mode_lighten", + "mode_dst", + "mode_dstatop", + "mode_dstin", + "mode_dstout", + "mode_dstover", + "mode_src", + "mode_srcatop", + "mode_srcin", + "mode_srcout", + "mode_srcover", + "mode_or", + "mode_xor", + }; + for( int mode=0; modetheme->get_image(mode_types[mode]), + PIXMAP_ALPHA); + } + + add_subwindow(nudge_popup = new NudgePopup(mwindow, this)); + nudge_popup->create_objects(); + update(); +} + +BC_Pixmap* PatchBay::mode_to_icon(int mode) +{ + return mode_icons[mode]; +} + +int PatchBay::icon_to_mode(BC_Pixmap *icon) +{ + for(int i = 0; i < TRANSFER_TYPES; i++) + if(icon == mode_icons[i]) return i; + return TRANSFER_NORMAL; +} + +void PatchBay::resize_event() +{ + reposition_window(mwindow->theme->patchbay_x, + mwindow->theme->patchbay_y, + mwindow->theme->patchbay_w, + mwindow->theme->patchbay_h); + draw_top_background(get_parent(), 0, 0, get_w(), get_h()); + update(); + flash(0); +} + +void PatchBay::resize_event(int x, int y, int w, int h) +{ + reposition_window(x, + y, + w, + h); + draw_top_background(get_parent(), 0, 0, w, h); + update(); + flash(0); +} + +int PatchBay::button_press_event() +{ + int result = 0; +// Too much junk to support the wheel + return result; +} + +int PatchBay::cursor_motion_event() +{ + //int cursor_x = get_relative_cursor_x(); + int cursor_y = get_relative_cursor_y(); + int update_gui = 0; + + if(drag_operation != Tracks::NONE) + { + if(cursor_y >= 0 && + cursor_y < get_h()) + { +// Get track we're inside of + for(Track *track = mwindow->edl->tracks->first; + track; + track = track->next) + { + int y = track->y_pixel - mwindow->edl->local_session->track_start[pane->number]; + int h = track->vertical_span(mwindow->theme); + if(cursor_y >= y && cursor_y < y + h) + { + switch(drag_operation) + { + case Tracks::PLAY: + if(track->play != new_status) + { + track->play = new_status; + mwindow->gui->unlock_window(); + mwindow->restart_brender(); + mwindow->sync_parameters(CHANGE_EDL); + mwindow->gui->lock_window(); + update_gui = 1; + } + break; + case Tracks::RECORD: + if(track->record != new_status) + { + track->record = new_status; + update_gui = 1; + } + break; + case Tracks::GANG: + if(track->gang != new_status) + { + track->gang = new_status; + update_gui = 1; + } + break; + case Tracks::DRAW: + if(track->draw != new_status) + { + track->draw = new_status; + update_gui = 1; + } + break; + case Tracks::EXPAND: + if(track->expand_view != new_status) + { + track->expand_view = new_status; + mwindow->edl->tracks->update_y_pixels(mwindow->theme); + gui->draw_trackmovement(); + update_gui = 0; + } + break; + case Tracks::MUTE: + { + IntAuto *current = 0; + Auto *keyframe = 0; + double position = mwindow->edl->local_session->get_selectionstart(1); + Autos *mute_autos = track->automation->autos[AUTOMATION_MUTE]; + + current = (IntAuto*)mute_autos->get_prev_auto(PLAY_FORWARD, + keyframe); + + if(current->value != new_status) + { + +// mwindow->undo->update_undo_before(_("keyframe"), this); + current = (IntAuto*)mute_autos->get_auto_for_editing(position); + + current->value = new_status; + +// mwindow->undo->update_undo_after(_("keyframe"), LOAD_AUTOMATION); + + mwindow->gui->unlock_window(); + mwindow->restart_brender(); + mwindow->sync_parameters(CHANGE_PARAMS); + mwindow->gui->lock_window(); + + if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MUTE]) + { + gui->draw_overlays(1); + } + update_gui = 1; + } + break; + } + } + } + } + } + } + + if(update_gui) + { + gui->update_patchbay(); + } + return 0; +} + +void PatchBay::set_meter_format(int mode, int min, int max) +{ + for(int i = 0; i < patches.total; i++) + { + PatchGUI *patchgui = patches.values[i]; + if(patchgui->data_type == TRACK_AUDIO) + { + APatchGUI *apatchgui = (APatchGUI*)patchgui; + if(apatchgui->meter) + { + apatchgui->meter->change_format(mode, min, max); + } + } + } +} + +void PatchBay::update_meters(ArrayList *module_levels) +{ + for(int level_number = 0, patch_number = 0; + patch_number < patches.total && level_number < module_levels->total; + patch_number++) + { + APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number]; + + if(patchgui->data_type == TRACK_AUDIO) + { + if(patchgui->meter) + { + double level = module_levels->values[level_number]; + patchgui->meter->update(level, level > 1); + } + + level_number++; + } + } +} + +void PatchBay::reset_meters() +{ + for(int patch_number = 0; + patch_number < patches.total; + patch_number++) + { + APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number]; + if(patchgui->data_type == TRACK_AUDIO && patchgui->meter) + { + patchgui->meter->reset_over(); + } + } +} + +void PatchBay::stop_meters() +{ + for(int patch_number = 0; + patch_number < patches.total; + patch_number++) + { + APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number]; + if(patchgui->data_type == TRACK_AUDIO && patchgui->meter) + { + patchgui->meter->reset(); + } + } +} + + +#define PATCH_X 3 + +int PatchBay::update() +{ + int patch_count = 0; + +// Every patch has a GUI regardless of whether or not it is visible. +// Make sure GUI's are allocated for every patch and deleted for non-existant +// patches. + for(Track *current = mwindow->edl->tracks->first; + current; + current = NEXT, patch_count++) + { + PatchGUI *patchgui = 0; + int y = current->y_pixel; + y -= mwindow->edl->local_session->track_start[pane->number]; + +//printf("PatchBay::update %d %d\n", __LINE__, y); + if(patches.total > patch_count) + { + if(patches.values[patch_count]->track_id != current->get_id()) + { + delete patches.values[patch_count]; + + switch(current->data_type) + { + case TRACK_AUDIO: + patchgui = patches.values[patch_count] = new APatchGUI(mwindow, this, (ATrack*)current, PATCH_X, y); + break; + case TRACK_VIDEO: + patchgui = patches.values[patch_count] = new VPatchGUI(mwindow, this, (VTrack*)current, PATCH_X, y); + break; + case TRACK_SUBTITLE: + patchgui = patches.values[patch_count] = new SPatchGUI(mwindow, this, (STrack*)current, PATCH_X, y); + break; + } + patchgui->create_objects(); + } + else + { + patches.values[patch_count]->update(PATCH_X, y); + } + } + else + { + switch(current->data_type) + { + case TRACK_AUDIO: + patchgui = new APatchGUI(mwindow, this, (ATrack*)current, PATCH_X, y); + break; + case TRACK_VIDEO: + patchgui = new VPatchGUI(mwindow, this, (VTrack*)current, PATCH_X, y); + break; + case TRACK_SUBTITLE: + patchgui = new SPatchGUI(mwindow, this, (STrack*)current, PATCH_X, y); + break; + } + patches.append(patchgui); + patchgui->create_objects(); + } + } + + while(patches.total > patch_count) + { + delete patches.values[patches.total - 1]; + patches.remove_number(patches.total - 1); + } + + show_window(0); + return 0; +} + +void PatchBay::synchronize_faders(float change, int data_type, Track *skip) +{ + for(Track *current = mwindow->edl->tracks->first; + current; + current = NEXT) + { + if(current->data_type == data_type && + current->gang && + current->record && + current != skip) + { + FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE]; + double position = mwindow->edl->local_session->get_selectionstart(1); + + + FloatAuto *keyframe = (FloatAuto*)fade_autos->get_auto_for_editing(position); + + float new_value = keyframe->get_value() + change; + if(data_type == TRACK_AUDIO) + CLAMP(new_value, + mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_AUDIO_FADE], + mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_AUDIO_FADE]); + else + CLAMP(new_value, + mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE], + mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE]); + + keyframe->set_value(new_value); + + PatchGUI *patch = get_patch_of(current); + if(patch) patch->update(patch->x, patch->y); + } + } +} + +void PatchBay::synchronize_nudge(int64_t value, Track *skip) +{ + for(Track *current = mwindow->edl->tracks->first; + current; + current = NEXT) + { + if(current->data_type == skip->data_type && + current->gang && + current->record && + current != skip) + { + current->nudge = value; + PatchGUI *patch = get_patch_of(current); + if(patch) patch->update(patch->x, patch->y); + } + } +} + +PatchGUI* PatchBay::get_patch_of(Track *track) +{ + for(int i = 0; i < patches.total; i++) + { + if(patches.values[i]->track == track) + return patches.values[i]; + } + return 0; +} + +int PatchBay::resize_event(int top, int bottom) +{ + reposition_window(mwindow->theme->patchbay_x, + mwindow->theme->patchbay_y, + mwindow->theme->patchbay_w, + mwindow->theme->patchbay_h); + return 0; +} + +