00001 #include "automation.h"
00002 #include "bcsignals.h"
00003 #include "cplayback.h"
00004 #include "cwindow.h"
00005 #include "edl.h"
00006 #include "edlsession.h"
00007 #include "intauto.h"
00008 #include "intautos.h"
00009 #include "language.h"
00010 #include "localsession.h"
00011 #include "mainsession.h"
00012 #include "mainundo.h"
00013 #include "mwindow.h"
00014 #include "mwindowgui.h"
00015 #include "patchbay.h"
00016 #include "patchgui.h"
00017 #include "playbackengine.h"
00018 #include "theme.h"
00019 #include "track.h"
00020 #include "trackcanvas.h"
00021 #include "tracks.h"
00022 #include "transportque.h"
00023 #include "vframe.h"
00024
00025
00026
00027 PatchGUI::PatchGUI(MWindow *mwindow,
00028 PatchBay *patchbay,
00029 Track *track,
00030 int x,
00031 int y)
00032 {
00033 this->mwindow = mwindow;
00034 this->patchbay = patchbay;
00035 this->track = track;
00036 this->x = x;
00037 this->y = y;
00038 title = 0;
00039 record = 0;
00040 play = 0;
00041
00042 gang = 0;
00043 draw = 0;
00044 mute = 0;
00045 expand = 0;
00046 nudge = 0;
00047 change_source = 0;
00048 track_id = -1;
00049 if(track) track_id = track->get_id();
00050 }
00051
00052 PatchGUI::~PatchGUI()
00053 {
00054 if(title) delete title;
00055 if(record) delete record;
00056 if(play) delete play;
00057
00058 if(gang) delete gang;
00059 if(draw) delete draw;
00060 if(mute) delete mute;
00061 if(expand) delete expand;
00062 if(nudge) delete nudge;
00063 }
00064
00065 int PatchGUI::create_objects()
00066 {
00067 return update(x, y);
00068 }
00069
00070 int PatchGUI::reposition(int x, int y)
00071 {
00072 int x1 = 0;
00073 int y1 = 0;
00074
00075
00076 if(x != this->x || y != this->y)
00077 {
00078 this->x = x;
00079 this->y = y;
00080
00081 if(title)
00082 {
00083 TRACE("PatchGUI::reposition 1\n");
00084 title->reposition_window(x1, y1 + y);
00085 TRACE("PatchGUI::reposition 2\n");
00086 }
00087 y1 += mwindow->theme->title_h;
00088
00089 if(play)
00090 {
00091 TRACE("PatchGUI::reposition 3\n");
00092 play->reposition_window(x1, y1 + y);
00093 x1 += play->get_w();
00094 TRACE("PatchGUI::reposition 4\n");
00095 record->reposition_window(x1, y1 + y);
00096 x1 += record->get_w();
00097 TRACE("PatchGUI::reposition 5\n");
00098
00099
00100 gang->reposition_window(x1, y1 + y);
00101 x1 += gang->get_w();
00102 TRACE("PatchGUI::reposition 6\n");
00103 draw->reposition_window(x1, y1 + y);
00104 x1 += draw->get_w();
00105 TRACE("PatchGUI::reposition 7\n");
00106 mute->reposition_window(x1, y1 + y);
00107 x1 += mute->get_w();
00108 TRACE("PatchGUI::reposition 8\n");
00109
00110 if(expand)
00111 {
00112 TRACE("PatchGUI::reposition 9\n");
00113 VFrame **expandpatch_data = mwindow->theme->get_image_set("expandpatch_data");
00114 expand->reposition_window(
00115 patchbay->get_w() - 10 - expandpatch_data[0]->get_w(),
00116 y1 + y);
00117 TRACE("PatchGUI::reposition 10\n");
00118 x1 += expand->get_w();
00119 TRACE("PatchGUI::reposition 11\n");
00120 }
00121 }
00122 y1 += mwindow->theme->play_h;
00123 }
00124 else
00125 {
00126 y1 += mwindow->theme->title_h;
00127 y1 += mwindow->theme->play_h;
00128 }
00129
00130 return y1;
00131 }
00132
00133 int PatchGUI::update(int x, int y)
00134 {
00135
00136 reposition(x, y);
00137
00138
00139 int h = track->vertical_span(mwindow->theme);
00140 int y1 = 0;
00141 int x1 = 0;
00142
00143
00144 if(title)
00145 {
00146 if(h - y1 < 0)
00147 {
00148 delete title;
00149 title = 0;
00150 }
00151 else
00152 {
00153 title->update(track->title);
00154 }
00155 }
00156 else
00157 if(h - y1 >= 0)
00158 {
00159 patchbay->add_subwindow(title = new TitlePatch(mwindow, this, x1 + x, y1 + y));
00160 }
00161 y1 += mwindow->theme->title_h;
00162
00163 if(play)
00164 {
00165 if(h - y1 < mwindow->theme->play_h)
00166 {
00167 delete play;
00168 delete record;
00169 delete gang;
00170 delete draw;
00171 delete mute;
00172 delete expand;
00173 play = 0;
00174 record = 0;
00175 draw = 0;
00176 mute = 0;
00177 expand = 0;
00178 }
00179 else
00180 {
00181 play->update(track->play);
00182 record->update(track->record);
00183 gang->update(track->gang);
00184 draw->update(track->draw);
00185 mute->update(mute->get_keyframe(mwindow, this)->value);
00186 expand->update(track->expand_view);
00187 }
00188 }
00189 else
00190 if(h - y1 >= mwindow->theme->play_h)
00191 {
00192 patchbay->add_subwindow(play = new PlayPatch(mwindow, this, x1 + x, y1 + y));
00193
00194 x1 += play->get_w();
00195 patchbay->add_subwindow(record = new RecordPatch(mwindow, this, x1 + x, y1 + y));
00196 x1 += record->get_w();
00197 patchbay->add_subwindow(gang = new GangPatch(mwindow, this, x1 + x, y1 + y));
00198 x1 += gang->get_w();
00199 patchbay->add_subwindow(draw = new DrawPatch(mwindow, this, x1 + x, y1 + y));
00200 x1 += draw->get_w();
00201 patchbay->add_subwindow(mute = new MutePatch(mwindow, this, x1 + x, y1 + y));
00202 x1 += mute->get_w();
00203
00204 VFrame **expandpatch_data = mwindow->theme->get_image_set("expandpatch_data");
00205 patchbay->add_subwindow(expand = new ExpandPatch(mwindow,
00206 this,
00207 patchbay->get_w() - 10 - expandpatch_data[0]->get_w(),
00208 y1 + y));
00209 x1 += expand->get_w();
00210 }
00211 y1 += mwindow->theme->play_h;
00212
00213
00214 return y1;
00215 }
00216
00217
00218 void PatchGUI::toggle_behavior(int type,
00219 int value,
00220 BC_Toggle *toggle,
00221 int *output)
00222 {
00223 if(toggle->shift_down())
00224 {
00225 int total_selected = mwindow->edl->tracks->total_of(type);
00226
00227
00228 if(total_selected == 0)
00229 {
00230 mwindow->edl->tracks->select_all(type,
00231 1);
00232 }
00233 else
00234 if(total_selected == 1)
00235 {
00236
00237 if(*output)
00238 {
00239 mwindow->edl->tracks->select_all(type,
00240 1);
00241 }
00242
00243 else
00244 {
00245 mwindow->edl->tracks->select_all(type,
00246 0);
00247 *output = 1;
00248 }
00249 }
00250 else
00251 if(total_selected > 1)
00252 {
00253 mwindow->edl->tracks->select_all(type,
00254 0);
00255 *output = 1;
00256 }
00257 toggle->set_value(*output);
00258 patchbay->update();
00259 patchbay->drag_operation = type;
00260 patchbay->new_status = 1;
00261 patchbay->button_down = 1;
00262 }
00263 else
00264 {
00265 *output = value;
00266
00267 patchbay->drag_operation = type;
00268 patchbay->new_status = value;
00269 patchbay->button_down = 1;
00270 }
00271
00272 switch(type)
00273 {
00274 case Tracks::PLAY:
00275 mwindow->gui->unlock_window();
00276 mwindow->restart_brender();
00277 mwindow->sync_parameters(CHANGE_EDL);
00278 mwindow->gui->lock_window("PatchGUI::toggle_behavior 1");
00279 mwindow->undo->update_undo(_("play patch"), LOAD_PATCHES);
00280 break;
00281
00282 case Tracks::MUTE:
00283 mwindow->gui->unlock_window();
00284 mwindow->restart_brender();
00285 mwindow->sync_parameters(CHANGE_PARAMS);
00286 mwindow->gui->lock_window("PatchGUI::toggle_behavior 2");
00287 mwindow->undo->update_undo(_("mute patch"), LOAD_PATCHES);
00288 break;
00289
00290
00291 case Tracks::RECORD:
00292 mwindow->cwindow->update(0, 1, 1);
00293 mwindow->undo->update_undo(_("record patch"), LOAD_PATCHES);
00294 break;
00295
00296 case Tracks::GANG:
00297 mwindow->undo->update_undo(_("gang patch"), LOAD_PATCHES);
00298 break;
00299
00300 case Tracks::DRAW:
00301 mwindow->undo->update_undo(_("draw patch"), LOAD_PATCHES);
00302 break;
00303
00304 case Tracks::EXPAND:
00305 mwindow->undo->update_undo(_("expand patch"), LOAD_PATCHES);
00306 break;
00307 }
00308 }
00309
00310
00311 char* PatchGUI::calculate_nudge_text(int *changed)
00312 {
00313 if(changed) *changed = 0;
00314 if(track->edl->session->nudge_seconds)
00315 {
00316 sprintf(string_return, "%.4f", track->from_units(track->nudge));
00317 if(changed && nudge && atof(nudge->get_text()) - atof(string_return) != 0)
00318 *changed = 1;
00319 }
00320 else
00321 {
00322 sprintf(string_return, "%d", track->nudge);
00323 if(changed && nudge && atoi(nudge->get_text()) - atoi(string_return) != 0)
00324 *changed = 1;
00325 }
00326 return string_return;
00327 }
00328
00329
00330 int64_t PatchGUI::calculate_nudge(char *string)
00331 {
00332 if(mwindow->edl->session->nudge_seconds)
00333 {
00334 float result;
00335 sscanf(string, "%f", &result);
00336 return track->to_units(result, 0);
00337 }
00338 else
00339 {
00340 int64_t temp;
00341 sscanf(string, "%lld", &temp);
00342 return temp;
00343 }
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 PlayPatch::PlayPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00358 : BC_Toggle(x,
00359 y,
00360 mwindow->theme->get_image_set("playpatch_data"),
00361 patch->track->play,
00362 "",
00363 0,
00364 0,
00365 0)
00366 {
00367 this->mwindow = mwindow;
00368 this->patch = patch;
00369 set_tooltip(_("Play track"));
00370 set_select_drag(1);
00371 }
00372
00373 int PlayPatch::button_press_event()
00374 {
00375 if(is_event_win() && get_buttonpress() == 1)
00376 {
00377 set_status(BC_Toggle::TOGGLE_DOWN);
00378 update(!get_value());
00379 patch->toggle_behavior(Tracks::PLAY,
00380 get_value(),
00381 this,
00382 &patch->track->play);
00383 return 1;
00384 }
00385 return 0;
00386 }
00387
00388 int PlayPatch::button_release_event()
00389 {
00390 int result = BC_Toggle::button_release_event();
00391 if(patch->patchbay->drag_operation != Tracks::NONE)
00392 {
00393 patch->patchbay->drag_operation = Tracks::NONE;
00394 }
00395 return result;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 RecordPatch::RecordPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00409 : BC_Toggle(x,
00410 y,
00411 mwindow->theme->get_image_set("recordpatch_data"),
00412 patch->track->record,
00413 "",
00414 0,
00415 0,
00416 0)
00417 {
00418 this->mwindow = mwindow;
00419 this->patch = patch;
00420 set_tooltip(_("Arm track"));
00421 set_select_drag(1);
00422 }
00423
00424 int RecordPatch::button_press_event()
00425 {
00426 if(is_event_win() && get_buttonpress() == 1)
00427 {
00428 set_status(BC_Toggle::TOGGLE_DOWN);
00429 update(!get_value());
00430 patch->toggle_behavior(Tracks::RECORD,
00431 get_value(),
00432 this,
00433 &patch->track->record);
00434 return 1;
00435 }
00436 return 0;
00437 }
00438
00439 int RecordPatch::button_release_event()
00440 {
00441 int result = BC_Toggle::button_release_event();
00442 if(patch->patchbay->drag_operation != Tracks::NONE)
00443 {
00444 patch->patchbay->drag_operation = Tracks::NONE;
00445 }
00446 return result;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 GangPatch::GangPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00460 : BC_Toggle(x, y,
00461 mwindow->theme->get_image_set("gangpatch_data"),
00462 patch->track->gang,
00463 "",
00464 0,
00465 0,
00466 0)
00467 {
00468 this->mwindow = mwindow;
00469 this->patch = patch;
00470 set_tooltip(_("Gang faders"));
00471 set_select_drag(1);
00472 }
00473
00474 int GangPatch::button_press_event()
00475 {
00476 if(is_event_win() && get_buttonpress() == 1)
00477 {
00478 set_status(BC_Toggle::TOGGLE_DOWN);
00479 update(!get_value());
00480 patch->toggle_behavior(Tracks::GANG,
00481 get_value(),
00482 this,
00483 &patch->track->gang);
00484 return 1;
00485 }
00486 return 0;
00487 }
00488
00489 int GangPatch::button_release_event()
00490 {
00491 int result = BC_Toggle::button_release_event();
00492 if(patch->patchbay->drag_operation != Tracks::NONE)
00493 {
00494 patch->patchbay->drag_operation = Tracks::NONE;
00495 }
00496 return result;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 DrawPatch::DrawPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00510 : BC_Toggle(x, y,
00511 mwindow->theme->get_image_set("drawpatch_data"),
00512 patch->track->draw,
00513 "",
00514 0,
00515 0,
00516 0)
00517 {
00518 this->mwindow = mwindow;
00519 this->patch = patch;
00520 set_tooltip(_("Draw media"));
00521 set_select_drag(1);
00522 }
00523
00524 int DrawPatch::button_press_event()
00525 {
00526 if(is_event_win() && get_buttonpress() == 1)
00527 {
00528 set_status(BC_Toggle::TOGGLE_DOWN);
00529 update(!get_value());
00530 patch->toggle_behavior(Tracks::DRAW,
00531 get_value(),
00532 this,
00533 &patch->track->draw);
00534 return 1;
00535 }
00536 return 0;
00537 }
00538
00539 int DrawPatch::button_release_event()
00540 {
00541 int result = BC_Toggle::button_release_event();
00542 if(patch->patchbay->drag_operation != Tracks::NONE)
00543 {
00544 patch->patchbay->drag_operation = Tracks::NONE;
00545 }
00546 return result;
00547 }
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 MutePatch::MutePatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00559 : BC_Toggle(x, y,
00560 mwindow->theme->get_image_set("mutepatch_data"),
00561 get_keyframe(mwindow, patch)->value,
00562 "",
00563 0,
00564 0,
00565 0)
00566 {
00567 this->mwindow = mwindow;
00568 this->patch = patch;
00569 set_tooltip(_("Don't send to output"));
00570 set_select_drag(1);
00571 }
00572
00573 int MutePatch::button_press_event()
00574 {
00575 if(is_event_win() && get_buttonpress() == 1)
00576 {
00577 set_status(BC_Toggle::TOGGLE_DOWN);
00578 update(!get_value());
00579 IntAuto *current;
00580 double position = mwindow->edl->local_session->get_selectionstart(1);
00581 Autos *mute_autos = patch->track->automation->autos[AUTOMATION_MUTE];
00582
00583
00584 current = (IntAuto*)mute_autos->get_auto_for_editing(position);
00585 current->value = get_value();
00586
00587 patch->toggle_behavior(Tracks::MUTE,
00588 get_value(),
00589 this,
00590 ¤t->value);
00591
00592
00593 mwindow->undo->update_undo(_("keyframe"), LOAD_AUTOMATION);
00594
00595 if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MUTE])
00596 {
00597 mwindow->gui->canvas->draw_overlays();
00598 mwindow->gui->canvas->flash();
00599 }
00600 return 1;
00601 }
00602 return 0;
00603 }
00604
00605 int MutePatch::button_release_event()
00606 {
00607 int result = BC_Toggle::button_release_event();
00608 if(patch->patchbay->drag_operation != Tracks::NONE)
00609 {
00610 patch->patchbay->drag_operation = Tracks::NONE;
00611 }
00612 return result;
00613 }
00614
00615 IntAuto* MutePatch::get_keyframe(MWindow *mwindow, PatchGUI *patch)
00616 {
00617 Auto *current = 0;
00618 double unit_position = mwindow->edl->local_session->get_selectionstart(1);
00619 unit_position = mwindow->edl->align_to_frame(unit_position, 0);
00620 unit_position = patch->track->to_units(unit_position, 0);
00621 return (IntAuto*)patch->track->automation->autos[AUTOMATION_MUTE]->get_prev_auto(
00622 (int64_t)unit_position,
00623 PLAY_FORWARD,
00624 current);
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 ExpandPatch::ExpandPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00639 : BC_Toggle(x,
00640 y,
00641 mwindow->theme->get_image_set("expandpatch_data"),
00642 patch->track->expand_view,
00643 "",
00644 0,
00645 0,
00646 0)
00647 {
00648 this->mwindow = mwindow;
00649 this->patch = patch;
00650 set_select_drag(1);
00651 }
00652
00653 int ExpandPatch::button_press_event()
00654 {
00655 if(is_event_win() && get_buttonpress() == 1)
00656 {
00657 set_status(BC_Toggle::TOGGLE_DOWN);
00658 update(!get_value());
00659 patch->toggle_behavior(Tracks::EXPAND,
00660 get_value(),
00661 this,
00662 &patch->track->expand_view);
00663 mwindow->trackmovement(mwindow->edl->local_session->track_start);
00664 return 1;
00665 }
00666 return 0;
00667 }
00668
00669 int ExpandPatch::button_release_event()
00670 {
00671 int result = BC_Toggle::button_release_event();
00672 if(patch->patchbay->drag_operation != Tracks::NONE)
00673 {
00674 patch->patchbay->drag_operation = Tracks::NONE;
00675 }
00676 return result;
00677 }
00678
00679
00680
00681
00682
00683 TitlePatch::TitlePatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00684 : BC_TextBox(x,
00685 y,
00686 patch->patchbay->get_w() - 10,
00687 1,
00688 patch->track->title)
00689 {
00690 this->mwindow = mwindow;
00691 this->patch = patch;
00692 }
00693
00694 int TitlePatch::handle_event()
00695 {
00696 strcpy(patch->track->title, get_text());
00697 mwindow->update_plugin_titles();
00698 mwindow->gui->canvas->draw_overlays();
00699 mwindow->gui->canvas->flash();
00700 mwindow->undo->update_undo(_("track title"), LOAD_PATCHES);
00701 return 1;
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 NudgePatch::NudgePatch(MWindow *mwindow,
00713 PatchGUI *patch,
00714 int x,
00715 int y,
00716 int w)
00717 : BC_TextBox(x,
00718 y,
00719 w,
00720 1,
00721 patch->calculate_nudge_text(0))
00722 {
00723 this->mwindow = mwindow;
00724 this->patch = patch;
00725 set_tooltip(_("Nudge"));
00726 }
00727
00728 int NudgePatch::handle_event()
00729 {
00730 set_value(patch->calculate_nudge(get_text()));
00731 return 1;
00732 }
00733
00734 void NudgePatch::set_value(int64_t value)
00735 {
00736 patch->track->nudge = value;
00737
00738 if(patch->track->gang)
00739 patch->patchbay->synchronize_nudge(patch->track->nudge, patch->track);
00740
00741 mwindow->undo->update_undo("nudge", LOAD_AUTOMATION, this);
00742
00743 mwindow->gui->unlock_window();
00744 if(patch->track->data_type == TRACK_VIDEO)
00745 mwindow->restart_brender();
00746 mwindow->sync_parameters(CHANGE_PARAMS);
00747 mwindow->gui->lock_window("NudgePatch::handle_event 2");
00748
00749 mwindow->session->changes_made = 1;
00750 }
00751
00752
00753 int NudgePatch::button_press_event()
00754 {
00755 int result = 0;
00756
00757 if(is_event_win() && cursor_inside())
00758 {
00759 if(get_buttonpress() == 4)
00760 {
00761 int value = patch->calculate_nudge(get_text());
00762 value += calculate_increment();
00763 set_value(value);
00764 update();
00765 result = 1;
00766 }
00767 else
00768 if(get_buttonpress() == 5)
00769 {
00770 int value = patch->calculate_nudge(get_text());
00771 value -= calculate_increment();
00772 set_value(value);
00773 update();
00774 result = 1;
00775 }
00776 else
00777 if(get_buttonpress() == 3)
00778 {
00779 patch->patchbay->nudge_popup->activate_menu(patch);
00780 result = 1;
00781 }
00782 }
00783
00784 if(!result)
00785 return BC_TextBox::button_press_event();
00786 else
00787 return result;
00788 }
00789
00790 int64_t NudgePatch::calculate_increment()
00791 {
00792 if(patch->track->data_type == TRACK_AUDIO)
00793 {
00794 return (int64_t)ceil(patch->track->edl->session->sample_rate / 10);
00795 }
00796 else
00797 {
00798 return (int64_t)ceil(1.0 / patch->track->edl->session->frame_rate);
00799 }
00800 }
00801
00802 void NudgePatch::update()
00803 {
00804 int changed;
00805 char *string = patch->calculate_nudge_text(&changed);
00806 if(changed)
00807 BC_TextBox::update(string);
00808 }
00809
00810
00811
00812