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 mwindow->gui->update(0, 1, 0, 0, 0, 0, 0);
00303 break;
00304
00305 case Tracks::EXPAND:
00306 mwindow->undo->update_undo(_("expand patch"), LOAD_PATCHES);
00307 break;
00308 }
00309 }
00310
00311
00312 char* PatchGUI::calculate_nudge_text(int *changed)
00313 {
00314 if(changed) *changed = 0;
00315 if(track->edl->session->nudge_seconds)
00316 {
00317 sprintf(string_return, "%.4f", track->from_units(track->nudge));
00318 if(changed && nudge && atof(nudge->get_text()) - atof(string_return) != 0)
00319 *changed = 1;
00320 }
00321 else
00322 {
00323 sprintf(string_return, "%d", track->nudge);
00324 if(changed && nudge && atoi(nudge->get_text()) - atoi(string_return) != 0)
00325 *changed = 1;
00326 }
00327 return string_return;
00328 }
00329
00330
00331 int64_t PatchGUI::calculate_nudge(char *string)
00332 {
00333 if(mwindow->edl->session->nudge_seconds)
00334 {
00335 float result;
00336 sscanf(string, "%f", &result);
00337 return track->to_units(result, 0);
00338 }
00339 else
00340 {
00341 int64_t temp;
00342 sscanf(string, "%lld", &temp);
00343 return temp;
00344 }
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 PlayPatch::PlayPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00359 : BC_Toggle(x,
00360 y,
00361 mwindow->theme->get_image_set("playpatch_data"),
00362 patch->track->play,
00363 "",
00364 0,
00365 0,
00366 0)
00367 {
00368 this->mwindow = mwindow;
00369 this->patch = patch;
00370 set_tooltip(_("Play track"));
00371 set_select_drag(1);
00372 }
00373
00374 int PlayPatch::button_press_event()
00375 {
00376 if(is_event_win() && get_buttonpress() == 1)
00377 {
00378 set_status(BC_Toggle::TOGGLE_DOWN);
00379 update(!get_value());
00380 patch->toggle_behavior(Tracks::PLAY,
00381 get_value(),
00382 this,
00383 &patch->track->play);
00384 return 1;
00385 }
00386 return 0;
00387 }
00388
00389 int PlayPatch::button_release_event()
00390 {
00391 int result = BC_Toggle::button_release_event();
00392 if(patch->patchbay->drag_operation != Tracks::NONE)
00393 {
00394 patch->patchbay->drag_operation = Tracks::NONE;
00395 }
00396 return result;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 RecordPatch::RecordPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00410 : BC_Toggle(x,
00411 y,
00412 mwindow->theme->get_image_set("recordpatch_data"),
00413 patch->track->record,
00414 "",
00415 0,
00416 0,
00417 0)
00418 {
00419 this->mwindow = mwindow;
00420 this->patch = patch;
00421 set_tooltip(_("Arm track"));
00422 set_select_drag(1);
00423 }
00424
00425 int RecordPatch::button_press_event()
00426 {
00427 if(is_event_win() && get_buttonpress() == 1)
00428 {
00429 set_status(BC_Toggle::TOGGLE_DOWN);
00430 update(!get_value());
00431 patch->toggle_behavior(Tracks::RECORD,
00432 get_value(),
00433 this,
00434 &patch->track->record);
00435 return 1;
00436 }
00437 return 0;
00438 }
00439
00440 int RecordPatch::button_release_event()
00441 {
00442 int result = BC_Toggle::button_release_event();
00443 if(patch->patchbay->drag_operation != Tracks::NONE)
00444 {
00445 patch->patchbay->drag_operation = Tracks::NONE;
00446 }
00447 return result;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 GangPatch::GangPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00461 : BC_Toggle(x, y,
00462 mwindow->theme->get_image_set("gangpatch_data"),
00463 patch->track->gang,
00464 "",
00465 0,
00466 0,
00467 0)
00468 {
00469 this->mwindow = mwindow;
00470 this->patch = patch;
00471 set_tooltip(_("Gang faders"));
00472 set_select_drag(1);
00473 }
00474
00475 int GangPatch::button_press_event()
00476 {
00477 if(is_event_win() && get_buttonpress() == 1)
00478 {
00479 set_status(BC_Toggle::TOGGLE_DOWN);
00480 update(!get_value());
00481 patch->toggle_behavior(Tracks::GANG,
00482 get_value(),
00483 this,
00484 &patch->track->gang);
00485 return 1;
00486 }
00487 return 0;
00488 }
00489
00490 int GangPatch::button_release_event()
00491 {
00492 int result = BC_Toggle::button_release_event();
00493 if(patch->patchbay->drag_operation != Tracks::NONE)
00494 {
00495 patch->patchbay->drag_operation = Tracks::NONE;
00496 }
00497 return result;
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 DrawPatch::DrawPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00511 : BC_Toggle(x, y,
00512 mwindow->theme->get_image_set("drawpatch_data"),
00513 patch->track->draw,
00514 "",
00515 0,
00516 0,
00517 0)
00518 {
00519 this->mwindow = mwindow;
00520 this->patch = patch;
00521 set_tooltip(_("Draw media"));
00522 set_select_drag(1);
00523 }
00524
00525 int DrawPatch::button_press_event()
00526 {
00527 if(is_event_win() && get_buttonpress() == 1)
00528 {
00529 set_status(BC_Toggle::TOGGLE_DOWN);
00530 update(!get_value());
00531 patch->toggle_behavior(Tracks::DRAW,
00532 get_value(),
00533 this,
00534 &patch->track->draw);
00535 return 1;
00536 }
00537 return 0;
00538 }
00539
00540 int DrawPatch::button_release_event()
00541 {
00542 int result = BC_Toggle::button_release_event();
00543 if(patch->patchbay->drag_operation != Tracks::NONE)
00544 {
00545 patch->patchbay->drag_operation = Tracks::NONE;
00546 }
00547 return result;
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 MutePatch::MutePatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00560 : BC_Toggle(x, y,
00561 mwindow->theme->get_image_set("mutepatch_data"),
00562 get_keyframe(mwindow, patch)->value,
00563 "",
00564 0,
00565 0,
00566 0)
00567 {
00568 this->mwindow = mwindow;
00569 this->patch = patch;
00570 set_tooltip(_("Don't send to output"));
00571 set_select_drag(1);
00572 }
00573
00574 int MutePatch::button_press_event()
00575 {
00576 if(is_event_win() && get_buttonpress() == 1)
00577 {
00578 set_status(BC_Toggle::TOGGLE_DOWN);
00579 update(!get_value());
00580 IntAuto *current;
00581 double position = mwindow->edl->local_session->get_selectionstart(1);
00582 Autos *mute_autos = patch->track->automation->autos[AUTOMATION_MUTE];
00583
00584
00585 current = (IntAuto*)mute_autos->get_auto_for_editing(position);
00586 current->value = get_value();
00587
00588 patch->toggle_behavior(Tracks::MUTE,
00589 get_value(),
00590 this,
00591 ¤t->value);
00592
00593
00594 mwindow->undo->update_undo(_("keyframe"), LOAD_AUTOMATION);
00595
00596 if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MUTE])
00597 {
00598 mwindow->gui->canvas->draw_overlays();
00599 mwindow->gui->canvas->flash();
00600 }
00601 return 1;
00602 }
00603 return 0;
00604 }
00605
00606 int MutePatch::button_release_event()
00607 {
00608 int result = BC_Toggle::button_release_event();
00609 if(patch->patchbay->drag_operation != Tracks::NONE)
00610 {
00611 patch->patchbay->drag_operation = Tracks::NONE;
00612 }
00613 return result;
00614 }
00615
00616 IntAuto* MutePatch::get_keyframe(MWindow *mwindow, PatchGUI *patch)
00617 {
00618 Auto *current = 0;
00619 double unit_position = mwindow->edl->local_session->get_selectionstart(1);
00620 unit_position = mwindow->edl->align_to_frame(unit_position, 0);
00621 unit_position = patch->track->to_units(unit_position, 0);
00622 return (IntAuto*)patch->track->automation->autos[AUTOMATION_MUTE]->get_prev_auto(
00623 (int64_t)unit_position,
00624 PLAY_FORWARD,
00625 current);
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 ExpandPatch::ExpandPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00640 : BC_Toggle(x,
00641 y,
00642 mwindow->theme->get_image_set("expandpatch_data"),
00643 patch->track->expand_view,
00644 "",
00645 0,
00646 0,
00647 0)
00648 {
00649 this->mwindow = mwindow;
00650 this->patch = patch;
00651 set_select_drag(1);
00652 }
00653
00654 int ExpandPatch::button_press_event()
00655 {
00656 if(is_event_win() && get_buttonpress() == 1)
00657 {
00658 set_status(BC_Toggle::TOGGLE_DOWN);
00659 update(!get_value());
00660 patch->toggle_behavior(Tracks::EXPAND,
00661 get_value(),
00662 this,
00663 &patch->track->expand_view);
00664 mwindow->trackmovement(mwindow->edl->local_session->track_start);
00665 return 1;
00666 }
00667 return 0;
00668 }
00669
00670 int ExpandPatch::button_release_event()
00671 {
00672 int result = BC_Toggle::button_release_event();
00673 if(patch->patchbay->drag_operation != Tracks::NONE)
00674 {
00675 patch->patchbay->drag_operation = Tracks::NONE;
00676 }
00677 return result;
00678 }
00679
00680
00681
00682
00683
00684 TitlePatch::TitlePatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
00685 : BC_TextBox(x,
00686 y,
00687 patch->patchbay->get_w() - 10,
00688 1,
00689 patch->track->title)
00690 {
00691 this->mwindow = mwindow;
00692 this->patch = patch;
00693 }
00694
00695 int TitlePatch::handle_event()
00696 {
00697 strcpy(patch->track->title, get_text());
00698 mwindow->update_plugin_titles();
00699 mwindow->gui->canvas->draw_overlays();
00700 mwindow->gui->canvas->flash();
00701 mwindow->undo->update_undo(_("track title"), LOAD_PATCHES);
00702 return 1;
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 NudgePatch::NudgePatch(MWindow *mwindow,
00714 PatchGUI *patch,
00715 int x,
00716 int y,
00717 int w)
00718 : BC_TextBox(x,
00719 y,
00720 w,
00721 1,
00722 patch->calculate_nudge_text(0))
00723 {
00724 this->mwindow = mwindow;
00725 this->patch = patch;
00726 set_tooltip(_("Nudge"));
00727 }
00728
00729 int NudgePatch::handle_event()
00730 {
00731 set_value(patch->calculate_nudge(get_text()));
00732 return 1;
00733 }
00734
00735 void NudgePatch::set_value(int64_t value)
00736 {
00737 patch->track->nudge = value;
00738
00739 if(patch->track->gang)
00740 patch->patchbay->synchronize_nudge(patch->track->nudge, patch->track);
00741
00742 mwindow->undo->update_undo("nudge", LOAD_AUTOMATION, this);
00743
00744 mwindow->gui->unlock_window();
00745 if(patch->track->data_type == TRACK_VIDEO)
00746 mwindow->restart_brender();
00747 mwindow->sync_parameters(CHANGE_PARAMS);
00748 mwindow->gui->lock_window("NudgePatch::handle_event 2");
00749
00750 mwindow->session->changes_made = 1;
00751 }
00752
00753
00754 int NudgePatch::button_press_event()
00755 {
00756 int result = 0;
00757
00758 if(is_event_win() && cursor_inside())
00759 {
00760 if(get_buttonpress() == 4)
00761 {
00762 int value = patch->calculate_nudge(get_text());
00763 value += calculate_increment();
00764 set_value(value);
00765 update();
00766 result = 1;
00767 }
00768 else
00769 if(get_buttonpress() == 5)
00770 {
00771 int value = patch->calculate_nudge(get_text());
00772 value -= calculate_increment();
00773 set_value(value);
00774 update();
00775 result = 1;
00776 }
00777 else
00778 if(get_buttonpress() == 3)
00779 {
00780 patch->patchbay->nudge_popup->activate_menu(patch);
00781 result = 1;
00782 }
00783 }
00784
00785 if(!result)
00786 return BC_TextBox::button_press_event();
00787 else
00788 return result;
00789 }
00790
00791 int64_t NudgePatch::calculate_increment()
00792 {
00793 if(patch->track->data_type == TRACK_AUDIO)
00794 {
00795 return (int64_t)ceil(patch->track->edl->session->sample_rate / 10);
00796 }
00797 else
00798 {
00799 return (int64_t)ceil(1.0 / patch->track->edl->session->frame_rate);
00800 }
00801 }
00802
00803 void NudgePatch::update()
00804 {
00805 int changed;
00806 char *string = patch->calculate_nudge_text(&changed);
00807 if(changed)
00808 BC_TextBox::update(string);
00809 }
00810
00811
00812
00813