00001 #include "apatchgui.h"
00002 #include "automation.h"
00003 #include "floatauto.h"
00004 #include "floatautos.h"
00005 #include "clip.h"
00006 #include "edl.h"
00007 #include "edlsession.h"
00008 #include "filexml.h"
00009 #include "intauto.h"
00010 #include "intautos.h"
00011 #include "language.h"
00012 #include "localsession.h"
00013 #include "mainundo.h"
00014 #include "mwindow.h"
00015 #include "mwindowgui.h"
00016 #include "patchbay.h"
00017 #include "patchgui.h"
00018 #include "mainsession.h"
00019 #include "theme.h"
00020 #include "track.h"
00021 #include "trackcanvas.h"
00022 #include "tracks.h"
00023 #include "vpatchgui.h"
00024
00025
00026
00027
00028
00029
00030 NudgePopup::NudgePopup(MWindow *mwindow, PatchBay *patchbay)
00031 : BC_PopupMenu(0,
00032 0,
00033 0,
00034 "",
00035 0)
00036 {
00037 this->mwindow = mwindow;
00038 this->patchbay = patchbay;
00039 }
00040
00041 NudgePopup::~NudgePopup()
00042 {
00043 }
00044
00045
00046 void NudgePopup::create_objects()
00047 {
00048 add_item(seconds_item = new NudgePopupSeconds(this));
00049 add_item(native_item = new NudgePopupNative(this));
00050 }
00051
00052 void NudgePopup::activate_menu(PatchGUI *gui)
00053 {
00054
00055 seconds_item->set_checked(mwindow->edl->session->nudge_seconds ? 1 : 0);
00056 native_item->set_checked(mwindow->edl->session->nudge_seconds ? 0 : 1);
00057
00058
00059 native_item->set_text(gui->track->data_type == TRACK_AUDIO ?
00060 (char*)"Samples" :
00061 (char*)"Frames");
00062
00063
00064 BC_PopupMenu::activate_menu();
00065 }
00066
00067
00068
00069 NudgePopupSeconds::NudgePopupSeconds(NudgePopup *popup)
00070 : BC_MenuItem("Seconds")
00071 {
00072 this->popup = popup;
00073 }
00074
00075 int NudgePopupSeconds::handle_event()
00076 {
00077 popup->mwindow->edl->session->nudge_seconds = 1;
00078 popup->patchbay->update();
00079 return 1;
00080 }
00081
00082
00083
00084
00085
00086 NudgePopupNative::NudgePopupNative(NudgePopup *popup)
00087 : BC_MenuItem("")
00088 {
00089 this->popup = popup;
00090 }
00091
00092 int NudgePopupNative::handle_event()
00093 {
00094 popup->mwindow->edl->session->nudge_seconds = 0;
00095 popup->patchbay->update();
00096 return 1;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 PatchBay::PatchBay(MWindow *mwindow, MWindowGUI *gui)
00108 : BC_SubWindow(mwindow->theme->patchbay_x,
00109 mwindow->theme->patchbay_y,
00110 mwindow->theme->patchbay_w,
00111 mwindow->theme->patchbay_h)
00112 {
00113 this->mwindow = mwindow;
00114 this->gui = gui;
00115 button_down = 0;
00116 reconfigure_trigger = 0;
00117 drag_operation = Tracks::NONE;
00118 }
00119
00120 PatchBay::~PatchBay()
00121 {
00122 }
00123
00124
00125 int PatchBay::delete_all_patches()
00126 {
00127 patches.remove_all_objects();
00128 return 0;
00129 }
00130
00131 int PatchBay::create_objects()
00132 {
00133 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
00134 flash();
00135
00136
00137 mode_icons[TRANSFER_NORMAL] = new BC_Pixmap(this,
00138 mwindow->theme->get_image("mode_normal"),
00139 PIXMAP_ALPHA);
00140 mode_icons[TRANSFER_ADDITION] = new BC_Pixmap(this,
00141 mwindow->theme->get_image("mode_add"),
00142 PIXMAP_ALPHA);
00143 mode_icons[TRANSFER_SUBTRACT] = new BC_Pixmap(this,
00144 mwindow->theme->get_image("mode_subtract"),
00145 PIXMAP_ALPHA);
00146 mode_icons[TRANSFER_MULTIPLY] = new BC_Pixmap(this,
00147 mwindow->theme->get_image("mode_multiply"),
00148 PIXMAP_ALPHA);
00149 mode_icons[TRANSFER_DIVIDE] = new BC_Pixmap(this,
00150 mwindow->theme->get_image("mode_divide"),
00151 PIXMAP_ALPHA);
00152 mode_icons[TRANSFER_REPLACE] = new BC_Pixmap(this,
00153 mwindow->theme->get_image("mode_replace"),
00154 PIXMAP_ALPHA);
00155
00156 add_subwindow(nudge_popup = new NudgePopup(mwindow, this));
00157 nudge_popup->create_objects();
00158
00159 return 0;
00160 }
00161
00162 BC_Pixmap* PatchBay::mode_to_icon(int mode)
00163 {
00164 return mode_icons[mode];
00165 }
00166
00167 int PatchBay::icon_to_mode(BC_Pixmap *icon)
00168 {
00169 for(int i = 0; i < TRANSFER_TYPES; i++)
00170 if(icon == mode_icons[i]) return i;
00171 return TRANSFER_NORMAL;
00172 }
00173
00174 void PatchBay::resize_event()
00175 {
00176 reposition_window(mwindow->theme->patchbay_x,
00177 mwindow->theme->patchbay_y,
00178 mwindow->theme->patchbay_w,
00179 mwindow->theme->patchbay_h);
00180 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
00181 update();
00182 flash();
00183 }
00184
00185 int PatchBay::button_press_event()
00186 {
00187 int result = 0;
00188
00189 return result;
00190 }
00191
00192
00193 Track *PatchBay::is_over_track()
00194 {
00195 int cursor_x = get_relative_cursor_x();
00196 int cursor_y = get_relative_cursor_y();
00197 Track *over_track = 0;
00198
00199 if(get_cursor_over_window() &&
00200 cursor_x >= 0 &&
00201 cursor_y >= 0 &&
00202 cursor_x < get_w() &&
00203 cursor_y < get_h())
00204 {
00205
00206 for(Track *track = mwindow->edl->tracks->first;
00207 track;
00208 track = track->next)
00209 {
00210 int y = track->y_pixel;
00211 int h = track->vertical_span(mwindow->theme);
00212 if(cursor_y >= y && cursor_y < y + h)
00213 {
00214 over_track = track;
00215 }
00216 }
00217 }
00218 return (over_track);
00219
00220 }
00221
00222 int PatchBay::cursor_motion_event()
00223 {
00224 int cursor_x = get_relative_cursor_x();
00225 int cursor_y = get_relative_cursor_y();
00226 int update_gui = 0;
00227
00228 if(drag_operation != Tracks::NONE)
00229 {
00230 if(cursor_y >= 0 &&
00231 cursor_y < get_h())
00232 {
00233
00234 for(Track *track = mwindow->edl->tracks->first;
00235 track;
00236 track = track->next)
00237 {
00238 int y = track->y_pixel;
00239 int h = track->vertical_span(mwindow->theme);
00240 if(cursor_y >= y && cursor_y < y + h)
00241 {
00242 switch(drag_operation)
00243 {
00244 case Tracks::PLAY:
00245 if(track->play != new_status)
00246 {
00247 track->play = new_status;
00248 mwindow->gui->unlock_window();
00249 mwindow->restart_brender();
00250 mwindow->sync_parameters(CHANGE_EDL);
00251 mwindow->gui->lock_window();
00252 update_gui = 1;
00253 }
00254 break;
00255 case Tracks::RECORD:
00256 if(track->record != new_status)
00257 {
00258 track->record = new_status;
00259 update_gui = 1;
00260 }
00261 break;
00262 case Tracks::GANG:
00263 if(track->gang != new_status)
00264 {
00265 track->gang = new_status;
00266 update_gui = 1;
00267 }
00268 break;
00269 case Tracks::DRAW:
00270 if(track->draw != new_status)
00271 {
00272 track->draw = new_status;
00273 update_gui = 1;
00274 }
00275 break;
00276 case Tracks::EXPAND:
00277 if(track->expand_view != new_status)
00278 {
00279 track->expand_view = new_status;
00280 mwindow->trackmovement(mwindow->edl->local_session->track_start);
00281 update_gui = 0;
00282 }
00283 break;
00284 case Tracks::MUTE:
00285 {
00286 IntAuto *current = 0;
00287 Auto *keyframe = 0;
00288 double position = mwindow->edl->local_session->get_selectionstart(1);
00289 Autos *mute_autos = track->automation->autos[AUTOMATION_MUTE];
00290
00291 current = (IntAuto*)mute_autos->get_prev_auto(PLAY_FORWARD,
00292 keyframe);
00293
00294 if(current->value != new_status)
00295 {
00296
00297 current = (IntAuto*)mute_autos->get_auto_for_editing(position);
00298
00299 current->value = new_status;
00300
00301 mwindow->undo->update_undo(_("keyframe"), LOAD_AUTOMATION);
00302
00303 mwindow->gui->unlock_window();
00304 mwindow->restart_brender();
00305 mwindow->sync_parameters(CHANGE_PARAMS);
00306 mwindow->gui->lock_window();
00307
00308 if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MUTE])
00309 {
00310 mwindow->gui->canvas->draw_overlays();
00311 mwindow->gui->canvas->flash();
00312 }
00313 update_gui = 1;
00314 }
00315 break;
00316 }
00317 }
00318 }
00319 }
00320 }
00321 }
00322
00323 if(update_gui)
00324 {
00325 update();
00326 }
00327 return 0;
00328 }
00329
00330 void PatchBay::change_meter_format(int mode, int min, int max)
00331 {
00332 for(int i = 0; i < patches.total; i++)
00333 {
00334 PatchGUI *patchgui = patches.values[i];
00335 if(patchgui->data_type == TRACK_AUDIO)
00336 {
00337 APatchGUI *apatchgui = (APatchGUI*)patchgui;
00338 if(apatchgui->meter)
00339 {
00340 apatchgui->meter->change_format(mode, min, max);
00341 }
00342 }
00343 }
00344 }
00345
00346 void PatchBay::update_meters(ArrayList<double> *module_levels)
00347 {
00348 for(int level_number = 0, patch_number = 0;
00349 patch_number < patches.total && level_number < module_levels->total;
00350 patch_number++)
00351 {
00352 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
00353
00354 if(patchgui->data_type == TRACK_AUDIO)
00355 {
00356 if(patchgui->meter)
00357 {
00358 double level = module_levels->values[level_number];
00359 patchgui->meter->update(level, level > 1);
00360 }
00361
00362 level_number++;
00363 }
00364 }
00365 }
00366
00367 void PatchBay::reset_meters()
00368 {
00369 for(int patch_number = 0;
00370 patch_number < patches.total;
00371 patch_number++)
00372 {
00373 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
00374 if(patchgui->data_type == TRACK_AUDIO && patchgui->meter)
00375 {
00376 patchgui->meter->reset_over();
00377 }
00378 }
00379 }
00380
00381 void PatchBay::stop_meters()
00382 {
00383 for(int patch_number = 0;
00384 patch_number < patches.total;
00385 patch_number++)
00386 {
00387 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
00388 if(patchgui->data_type == TRACK_AUDIO && patchgui->meter)
00389 {
00390 patchgui->meter->reset();
00391 }
00392 }
00393 }
00394
00395
00396 #define PATCH_X 3
00397
00398 int PatchBay::update()
00399 {
00400 int patch_count = 0;
00401
00402
00403
00404
00405 for(Track *current = mwindow->edl->tracks->first;
00406 current;
00407 current = NEXT, patch_count++)
00408 {
00409 PatchGUI *patchgui;
00410 int y = current->y_pixel;
00411
00412 if(patches.total > patch_count)
00413 {
00414 if(patches.values[patch_count]->track_id != current->get_id())
00415 {
00416 delete patches.values[patch_count];
00417
00418 switch(current->data_type)
00419 {
00420 case TRACK_AUDIO:
00421 patchgui = patches.values[patch_count] = new APatchGUI(mwindow, this, (ATrack*)current, PATCH_X, y);
00422 break;
00423 case TRACK_VIDEO:
00424 patchgui = patches.values[patch_count] = new VPatchGUI(mwindow, this, (VTrack*)current, PATCH_X, y);
00425 break;
00426 }
00427 patchgui->create_objects();
00428 }
00429 else
00430 {
00431 patches.values[patch_count]->update(PATCH_X, y);
00432 }
00433 }
00434 else
00435 {
00436 switch(current->data_type)
00437 {
00438 case TRACK_AUDIO:
00439 patchgui = new APatchGUI(mwindow, this, (ATrack*)current, PATCH_X, y);
00440 break;
00441 case TRACK_VIDEO:
00442 patchgui = new VPatchGUI(mwindow, this, (VTrack*)current, PATCH_X, y);
00443 break;
00444 }
00445 patches.append(patchgui);
00446 patchgui->create_objects();
00447 }
00448 }
00449
00450 while(patches.total > patch_count)
00451 {
00452 delete patches.values[patches.total - 1];
00453 patches.remove_number(patches.total - 1);
00454 }
00455
00456 return 0;
00457 }
00458
00459 void PatchBay::synchronize_faders(float change, int data_type, Track *skip)
00460 {
00461 for(Track *current = mwindow->edl->tracks->first;
00462 current;
00463 current = NEXT)
00464 {
00465 if(current->data_type == data_type &&
00466 current->gang &&
00467 current->record &&
00468 current != skip)
00469 {
00470 FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE];
00471 double position = mwindow->edl->local_session->get_selectionstart(1);
00472
00473
00474 FloatAuto *keyframe = (FloatAuto*)fade_autos->get_auto_for_editing(position);
00475
00476 keyframe->value += change;
00477 if(data_type == TRACK_AUDIO)
00478 CLAMP(keyframe->value, INFINITYGAIN, MAX_AUDIO_FADE);
00479 else
00480 CLAMP(keyframe->value, 0, MAX_VIDEO_FADE);
00481
00482
00483 PatchGUI *patch = get_patch_of(current);
00484 if(patch) patch->update(patch->x, patch->y);
00485 }
00486 }
00487 }
00488
00489 void PatchBay::synchronize_nudge(int64_t value, Track *skip)
00490 {
00491 for(Track *current = mwindow->edl->tracks->first;
00492 current;
00493 current = NEXT)
00494 {
00495 if(current->data_type == skip->data_type &&
00496 current->gang &&
00497 current->record &&
00498 current != skip)
00499 {
00500 current->nudge = value;
00501 PatchGUI *patch = get_patch_of(current);
00502 if(patch) patch->update(patch->x, patch->y);
00503 }
00504 }
00505 }
00506
00507 PatchGUI* PatchBay::get_patch_of(Track *track)
00508 {
00509 for(int i = 0; i < patches.total; i++)
00510 {
00511 if(patches.values[i]->track == track)
00512 return patches.values[i];
00513 }
00514 return 0;
00515 }
00516
00517 int PatchBay::resize_event(int top, int bottom)
00518 {
00519 reposition_window(mwindow->theme->patchbay_x,
00520 mwindow->theme->patchbay_y,
00521 mwindow->theme->patchbay_w,
00522 mwindow->theme->patchbay_h);
00523 return 0;
00524 }
00525
00526