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 mode_icons[TRANSFER_MAX] = new BC_Pixmap(this,
00156 mwindow->theme->get_image("mode_max"),
00157 PIXMAP_ALPHA);
00158
00159 add_subwindow(nudge_popup = new NudgePopup(mwindow, this));
00160 nudge_popup->create_objects();
00161
00162 return 0;
00163 }
00164
00165 BC_Pixmap* PatchBay::mode_to_icon(int mode)
00166 {
00167 return mode_icons[mode];
00168 }
00169
00170 int PatchBay::icon_to_mode(BC_Pixmap *icon)
00171 {
00172 for(int i = 0; i < TRANSFER_TYPES; i++)
00173 if(icon == mode_icons[i]) return i;
00174 return TRANSFER_NORMAL;
00175 }
00176
00177 void PatchBay::resize_event()
00178 {
00179 reposition_window(mwindow->theme->patchbay_x,
00180 mwindow->theme->patchbay_y,
00181 mwindow->theme->patchbay_w,
00182 mwindow->theme->patchbay_h);
00183 draw_top_background(get_parent(), 0, 0, get_w(), get_h());
00184 update();
00185 flash();
00186 }
00187
00188 int PatchBay::button_press_event()
00189 {
00190 int result = 0;
00191
00192 return result;
00193 }
00194
00195
00196 Track *PatchBay::is_over_track()
00197 {
00198 int cursor_x = get_relative_cursor_x();
00199 int cursor_y = get_relative_cursor_y();
00200 Track *over_track = 0;
00201
00202 if(get_cursor_over_window() &&
00203 cursor_x >= 0 &&
00204 cursor_y >= 0 &&
00205 cursor_x < get_w() &&
00206 cursor_y < get_h())
00207 {
00208
00209 for(Track *track = mwindow->edl->tracks->first;
00210 track;
00211 track = track->next)
00212 {
00213 int y = track->y_pixel;
00214 int h = track->vertical_span(mwindow->theme);
00215 if(cursor_y >= y && cursor_y < y + h)
00216 {
00217 over_track = track;
00218 }
00219 }
00220 }
00221 return (over_track);
00222
00223 }
00224
00225 int PatchBay::cursor_motion_event()
00226 {
00227 int cursor_x = get_relative_cursor_x();
00228 int cursor_y = get_relative_cursor_y();
00229 int update_gui = 0;
00230
00231 if(drag_operation != Tracks::NONE)
00232 {
00233 if(cursor_y >= 0 &&
00234 cursor_y < get_h())
00235 {
00236
00237 for(Track *track = mwindow->edl->tracks->first;
00238 track;
00239 track = track->next)
00240 {
00241 int y = track->y_pixel;
00242 int h = track->vertical_span(mwindow->theme);
00243 if(cursor_y >= y && cursor_y < y + h)
00244 {
00245 switch(drag_operation)
00246 {
00247 case Tracks::PLAY:
00248 if(track->play != new_status)
00249 {
00250 track->play = new_status;
00251 mwindow->gui->unlock_window();
00252 mwindow->restart_brender();
00253 mwindow->sync_parameters(CHANGE_EDL);
00254 mwindow->gui->lock_window();
00255 update_gui = 1;
00256 }
00257 break;
00258 case Tracks::RECORD:
00259 if(track->record != new_status)
00260 {
00261 track->record = new_status;
00262 update_gui = 1;
00263 }
00264 break;
00265 case Tracks::GANG:
00266 if(track->gang != new_status)
00267 {
00268 track->gang = new_status;
00269 update_gui = 1;
00270 }
00271 break;
00272 case Tracks::DRAW:
00273 if(track->draw != new_status)
00274 {
00275 track->draw = new_status;
00276 update_gui = 1;
00277 }
00278 break;
00279 case Tracks::EXPAND:
00280 if(track->expand_view != new_status)
00281 {
00282 track->expand_view = new_status;
00283 mwindow->trackmovement(mwindow->edl->local_session->track_start);
00284 update_gui = 0;
00285 }
00286 break;
00287 case Tracks::MUTE:
00288 {
00289 IntAuto *current = 0;
00290 Auto *keyframe = 0;
00291 double position = mwindow->edl->local_session->get_selectionstart(1);
00292 Autos *mute_autos = track->automation->autos[AUTOMATION_MUTE];
00293
00294 current = (IntAuto*)mute_autos->get_prev_auto(PLAY_FORWARD,
00295 keyframe);
00296
00297 if(current->value != new_status)
00298 {
00299
00300 current = (IntAuto*)mute_autos->get_auto_for_editing(position);
00301
00302 current->value = new_status;
00303
00304 mwindow->undo->update_undo(_("keyframe"), LOAD_AUTOMATION);
00305
00306 mwindow->gui->unlock_window();
00307 mwindow->restart_brender();
00308 mwindow->sync_parameters(CHANGE_PARAMS);
00309 mwindow->gui->lock_window();
00310
00311 if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MUTE])
00312 {
00313 mwindow->gui->canvas->draw_overlays();
00314 mwindow->gui->canvas->flash();
00315 }
00316 update_gui = 1;
00317 }
00318 break;
00319 }
00320 }
00321 }
00322 }
00323 }
00324 }
00325
00326 if(update_gui)
00327 {
00328 update();
00329 }
00330 return 0;
00331 }
00332
00333 void PatchBay::change_meter_format(int mode, int min, int max)
00334 {
00335 for(int i = 0; i < patches.total; i++)
00336 {
00337 PatchGUI *patchgui = patches.values[i];
00338 if(patchgui->data_type == TRACK_AUDIO)
00339 {
00340 APatchGUI *apatchgui = (APatchGUI*)patchgui;
00341 if(apatchgui->meter)
00342 {
00343 apatchgui->meter->change_format(mode, min, max);
00344 }
00345 }
00346 }
00347 }
00348
00349 void PatchBay::update_meters(ArrayList<double> *module_levels)
00350 {
00351 for(int level_number = 0, patch_number = 0;
00352 patch_number < patches.total && level_number < module_levels->total;
00353 patch_number++)
00354 {
00355 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
00356
00357 if(patchgui->data_type == TRACK_AUDIO)
00358 {
00359 if(patchgui->meter)
00360 {
00361 double level = module_levels->values[level_number];
00362 patchgui->meter->update(level, level > 1);
00363 }
00364
00365 level_number++;
00366 }
00367 }
00368 }
00369
00370 void PatchBay::reset_meters()
00371 {
00372 for(int patch_number = 0;
00373 patch_number < patches.total;
00374 patch_number++)
00375 {
00376 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
00377 if(patchgui->data_type == TRACK_AUDIO && patchgui->meter)
00378 {
00379 patchgui->meter->reset_over();
00380 }
00381 }
00382 }
00383
00384 void PatchBay::stop_meters()
00385 {
00386 for(int patch_number = 0;
00387 patch_number < patches.total;
00388 patch_number++)
00389 {
00390 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
00391 if(patchgui->data_type == TRACK_AUDIO && patchgui->meter)
00392 {
00393 patchgui->meter->reset();
00394 }
00395 }
00396 }
00397
00398
00399 #define PATCH_X 3
00400
00401 int PatchBay::update()
00402 {
00403 int patch_count = 0;
00404
00405
00406
00407
00408 for(Track *current = mwindow->edl->tracks->first;
00409 current;
00410 current = NEXT, patch_count++)
00411 {
00412 PatchGUI *patchgui;
00413 int y = current->y_pixel;
00414
00415 if(patches.total > patch_count)
00416 {
00417 if(patches.values[patch_count]->track_id != current->get_id())
00418 {
00419 delete patches.values[patch_count];
00420
00421 switch(current->data_type)
00422 {
00423 case TRACK_AUDIO:
00424 patchgui = patches.values[patch_count] = new APatchGUI(mwindow, this, (ATrack*)current, PATCH_X, y);
00425 break;
00426 case TRACK_VIDEO:
00427 patchgui = patches.values[patch_count] = new VPatchGUI(mwindow, this, (VTrack*)current, PATCH_X, y);
00428 break;
00429 }
00430 patchgui->create_objects();
00431 }
00432 else
00433 {
00434 patches.values[patch_count]->update(PATCH_X, y);
00435 }
00436 }
00437 else
00438 {
00439 switch(current->data_type)
00440 {
00441 case TRACK_AUDIO:
00442 patchgui = new APatchGUI(mwindow, this, (ATrack*)current, PATCH_X, y);
00443 break;
00444 case TRACK_VIDEO:
00445 patchgui = new VPatchGUI(mwindow, this, (VTrack*)current, PATCH_X, y);
00446 break;
00447 }
00448 patches.append(patchgui);
00449 patchgui->create_objects();
00450 }
00451 }
00452
00453 while(patches.total > patch_count)
00454 {
00455 delete patches.values[patches.total - 1];
00456 patches.remove_number(patches.total - 1);
00457 }
00458
00459 return 0;
00460 }
00461
00462 void PatchBay::synchronize_faders(float change, int data_type, Track *skip)
00463 {
00464 for(Track *current = mwindow->edl->tracks->first;
00465 current;
00466 current = NEXT)
00467 {
00468 if(current->data_type == data_type &&
00469 current->gang &&
00470 current->record &&
00471 current != skip)
00472 {
00473 FloatAutos *fade_autos = (FloatAutos*)current->automation->autos[AUTOMATION_FADE];
00474 double position = mwindow->edl->local_session->get_selectionstart(1);
00475
00476
00477 FloatAuto *keyframe = (FloatAuto*)fade_autos->get_auto_for_editing(position);
00478
00479 keyframe->value += change;
00480 if(data_type == TRACK_AUDIO)
00481 CLAMP(keyframe->value,
00482 mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_AUDIO_FADE],
00483 mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_AUDIO_FADE]);
00484 else
00485 CLAMP(keyframe->value,
00486 mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE],
00487 mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE]);
00488
00489 PatchGUI *patch = get_patch_of(current);
00490 if(patch) patch->update(patch->x, patch->y);
00491 }
00492 }
00493 }
00494
00495 void PatchBay::synchronize_nudge(int64_t value, Track *skip)
00496 {
00497 for(Track *current = mwindow->edl->tracks->first;
00498 current;
00499 current = NEXT)
00500 {
00501 if(current->data_type == skip->data_type &&
00502 current->gang &&
00503 current->record &&
00504 current != skip)
00505 {
00506 current->nudge = value;
00507 PatchGUI *patch = get_patch_of(current);
00508 if(patch) patch->update(patch->x, patch->y);
00509 }
00510 }
00511 }
00512
00513 PatchGUI* PatchBay::get_patch_of(Track *track)
00514 {
00515 for(int i = 0; i < patches.total; i++)
00516 {
00517 if(patches.values[i]->track == track)
00518 return patches.values[i];
00519 }
00520 return 0;
00521 }
00522
00523 int PatchBay::resize_event(int top, int bottom)
00524 {
00525 reposition_window(mwindow->theme->patchbay_x,
00526 mwindow->theme->patchbay_y,
00527 mwindow->theme->patchbay_w,
00528 mwindow->theme->patchbay_h);
00529 return 0;
00530 }
00531
00532