r753: Add raise_window() commands when making various windows
[cinelerra_cv/mob.git] / cinelerra / patchgui.C
blob34e3dcbe1d347e840aca019bee035a503da17354
1 #include "automation.h"
2 #include "bcsignals.h"
3 #include "cplayback.h"
4 #include "cwindow.h"
5 #include "edl.h"
6 #include "edlsession.h"
7 #include "intauto.h"
8 #include "intautos.h"
9 #include "language.h"
10 #include "localsession.h"
11 #include "mainsession.h"
12 #include "mainundo.h"
13 #include "mwindow.h"
14 #include "mwindowgui.h"
15 #include "patchbay.h"
16 #include "patchgui.h"
17 #include "playbackengine.h"
18 #include "theme.h"
19 #include "track.h"
20 #include "trackcanvas.h"
21 #include "tracks.h"
22 #include "transportque.h"
23 #include "vframe.h"
27 PatchGUI::PatchGUI(MWindow *mwindow, 
28                 PatchBay *patchbay, 
29                 Track *track, 
30                 int x, 
31                 int y)
33         this->mwindow = mwindow;
34         this->patchbay = patchbay;
35         this->track = track;
36         this->x = x;
37         this->y = y;
38         title = 0;
39         record = 0;
40         play = 0;
41 //      automate = 0;
42         gang = 0;
43         draw = 0;
44         mute = 0;
45         expand = 0;
46         nudge = 0;
47         change_source = 0;
48         track_id = -1;
49         if(track) track_id = track->get_id();
52 PatchGUI::~PatchGUI()
54         if(title) delete title;
55         if(record) delete record;
56         if(play) delete play;
57 //      if(automate) delete automate;
58         if(gang) delete gang;
59         if(draw) delete draw;
60         if(mute) delete mute;
61         if(expand) delete expand;
62         if(nudge) delete nudge;
65 int PatchGUI::create_objects()
67         return update(x, y);
70 int PatchGUI::reposition(int x, int y)
72         int x1 = 0;
73         int y1 = 0;
76         if(x != this->x || y != this->y)
77         {
78                 this->x = x;
79                 this->y = y;
81                 if(title)
82                 {
83 TRACE("PatchGUI::reposition 1\n");
84                         title->reposition_window(x1, y1 + y);
85 TRACE("PatchGUI::reposition 2\n");
86                 }
87                 y1 += mwindow->theme->title_h;
89                 if(play)
90                 {
91 TRACE("PatchGUI::reposition 3\n");
92                         play->reposition_window(x1, y1 + y);
93                         x1 += play->get_w();
94 TRACE("PatchGUI::reposition 4\n");
95                         record->reposition_window(x1, y1 + y);
96                         x1 += record->get_w();
97 TRACE("PatchGUI::reposition 5\n");
98 //                      automate->reposition_window(x1, y1 + y);
99 //                      x1 += automate->get_w();
100                         gang->reposition_window(x1, y1 + y);
101                         x1 += gang->get_w();
102 TRACE("PatchGUI::reposition 6\n");
103                         draw->reposition_window(x1, y1 + y);
104                         x1 += draw->get_w();
105 TRACE("PatchGUI::reposition 7\n");
106                         mute->reposition_window(x1, y1 + y);
107                         x1 += mute->get_w();
108 TRACE("PatchGUI::reposition 8\n");
110                         if(expand)
111                         {
112 TRACE("PatchGUI::reposition 9\n");
113                                 VFrame **expandpatch_data = mwindow->theme->get_image_set("expandpatch_data");
114                                 expand->reposition_window(
115                                         patchbay->get_w() - 10 - expandpatch_data[0]->get_w(), 
116                                         y1 + y);
117 TRACE("PatchGUI::reposition 10\n");
118                                 x1 += expand->get_w();
119 TRACE("PatchGUI::reposition 11\n");
120                         }
121                 }
122                 y1 += mwindow->theme->play_h;
123         }
124         else
125         {
126                 y1 += mwindow->theme->title_h;
127                 y1 += mwindow->theme->play_h;
128         }
130         return y1;
133 int PatchGUI::update(int x, int y)
135 //TRACE("PatchGUI::update 1");
136         reposition(x, y);
137 //TRACE("PatchGUI::update 10");
139         int h = track->vertical_span(mwindow->theme);
140         int y1 = 0;
141         int x1 = 0;
142 //printf("PatchGUI::update 10\n");
144         if(title)
145         {
146                 if(h - y1 < 0)
147                 {
148                         delete title;
149                         title = 0;
150                 }
151                 else
152                 {
153                         title->update(track->title);
154                 }
155         }
156         else
157         if(h - y1 >= 0)
158         {
159                 patchbay->add_subwindow(title = new TitlePatch(mwindow, this, x1 + x, y1 + y));
160         }
161         y1 += mwindow->theme->title_h;
163         if(play)
164         {
165                 if(h - y1 < mwindow->theme->play_h)
166                 {
167                         delete play;
168                         delete record;
169                         delete gang;
170                         delete draw;
171                         delete mute;
172                         delete expand;
173                         play = 0;
174                         record = 0;
175                         draw = 0;
176                         mute = 0;
177                         expand = 0;
178                 }
179                 else
180                 {
181                         play->update(track->play);
182                         record->update(track->record);
183                         gang->update(track->gang);
184                         draw->update(track->draw);
185                         mute->update(mute->get_keyframe(mwindow, this)->value);
186                         expand->update(track->expand_view);
187                 }
188         }
189         else
190         if(h - y1 >= mwindow->theme->play_h)
191         {
192                 patchbay->add_subwindow(play = new PlayPatch(mwindow, this, x1 + x, y1 + y));
193 //printf("PatchGUI::update 1 %p %p\n", play, &play->status);
194                 x1 += play->get_w();
195                 patchbay->add_subwindow(record = new RecordPatch(mwindow, this, x1 + x, y1 + y));
196                 x1 += record->get_w();
197                 patchbay->add_subwindow(gang = new GangPatch(mwindow, this, x1 + x, y1 + y));
198                 x1 += gang->get_w();
199                 patchbay->add_subwindow(draw = new DrawPatch(mwindow, this, x1 + x, y1 + y));
200                 x1 += draw->get_w();
201                 patchbay->add_subwindow(mute = new MutePatch(mwindow, this, x1 + x, y1 + y));
202                 x1 += mute->get_w();
204                 VFrame **expandpatch_data = mwindow->theme->get_image_set("expandpatch_data");
205                 patchbay->add_subwindow(expand = new ExpandPatch(mwindow, 
206                         this, 
207                         patchbay->get_w() - 10 - expandpatch_data[0]->get_w(), 
208                         y1 + y));
209                 x1 += expand->get_w();
210         }
211         y1 += mwindow->theme->play_h;
213 //UNTRACE
214         return y1;
218 void PatchGUI::toggle_behavior(int type, 
219                 int value,
220                 BC_Toggle *toggle,
221                 int *output)
223         if(toggle->shift_down())
224         {
225                 int total_selected = mwindow->edl->tracks->total_of(type);
227 // nothing previously selected
228                 if(total_selected == 0)
229                 {
230                         mwindow->edl->tracks->select_all(type,
231                                 1);
232                 }
233                 else
234                 if(total_selected == 1)
235                 {
236 // this patch was previously the only one on
237                         if(*output)
238                         {
239                                 mwindow->edl->tracks->select_all(type,
240                                         1);
241                         }
242 // another patch was previously the only one on
243                         else
244                         {
245                                 mwindow->edl->tracks->select_all(type,
246                                         0);
247                                 *output = 1;
248                         }
249                 }
250                 else
251                 if(total_selected > 1)
252                 {
253                         mwindow->edl->tracks->select_all(type,
254                                 0);
255                         *output = 1;
256                 }
257                 toggle->set_value(*output);
258                 patchbay->update();
259                 patchbay->drag_operation = type;
260                 patchbay->new_status = 1;
261                 patchbay->button_down = 1;
262         }
263         else
264         {
265                 *output = value;
266 // Select + drag behavior
267                 patchbay->drag_operation = type;
268                 patchbay->new_status = value;
269                 patchbay->button_down = 1;
270         }
272         switch(type)
273         {
274                 case Tracks::PLAY:
275                         mwindow->gui->unlock_window();
276                         mwindow->restart_brender();
277                         mwindow->sync_parameters(CHANGE_EDL);
278                         mwindow->gui->lock_window("PatchGUI::toggle_behavior 1");
279                         mwindow->undo->update_undo(_("play patch"), LOAD_PATCHES);
280                         break;
282                 case Tracks::MUTE:
283                         mwindow->gui->unlock_window();
284                         mwindow->restart_brender();
285                         mwindow->sync_parameters(CHANGE_PARAMS);
286                         mwindow->gui->lock_window("PatchGUI::toggle_behavior 2");
287                         mwindow->undo->update_undo(_("mute patch"), LOAD_PATCHES);
288                         break;
290 // Update affected tracks in cwindow
291                 case Tracks::RECORD:
292                         mwindow->cwindow->update(0, 1, 1);
293                         mwindow->undo->update_undo(_("record patch"), LOAD_PATCHES);
294                         break;
296                 case Tracks::GANG:
297                         mwindow->undo->update_undo(_("gang patch"), LOAD_PATCHES);
298                         break;
300                 case Tracks::DRAW:
301                         mwindow->undo->update_undo(_("draw patch"), LOAD_PATCHES);
302                         break;
304                 case Tracks::EXPAND:
305                         mwindow->undo->update_undo(_("expand patch"), LOAD_PATCHES);
306                         break;
307         }
311 char* PatchGUI::calculate_nudge_text(int *changed)
313         if(changed) *changed = 0;
314         if(track->edl->session->nudge_seconds)
315         {
316                 sprintf(string_return, "%.4f", track->from_units(track->nudge));
317                 if(changed && nudge && atof(nudge->get_text()) - atof(string_return) != 0)
318                         *changed = 1;
319         }
320         else
321         {
322                 sprintf(string_return, "%d", track->nudge);
323                 if(changed && nudge && atoi(nudge->get_text()) - atoi(string_return) != 0)
324                         *changed = 1;
325         }
326         return string_return;
330 int64_t PatchGUI::calculate_nudge(char *string)
332         if(mwindow->edl->session->nudge_seconds)
333         {
334                 float result;
335                 sscanf(string, "%f", &result);
336                 return track->to_units(result, 0);
337         }
338         else
339         {
340                 int64_t temp;
341                 sscanf(string, "%lld", &temp);
342                 return temp;
343         }
357 PlayPatch::PlayPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
358  : BC_Toggle(x, 
359                 y, 
360                 mwindow->theme->get_image_set("playpatch_data"),
361                 patch->track->play, 
362                 "",
363                 0,
364                 0,
365                 0)
367         this->mwindow = mwindow;
368         this->patch = patch;
369         set_tooltip(_("Play track"));
370         set_select_drag(1);
373 int PlayPatch::button_press_event()
375         if(is_event_win() && get_buttonpress() == 1)
376         {
377                 set_status(BC_Toggle::TOGGLE_DOWN);
378                 update(!get_value());
379                 patch->toggle_behavior(Tracks::PLAY,
380                         get_value(),
381                         this,
382                         &patch->track->play);
383                 return 1;
384         }
385         return 0;
388 int PlayPatch::button_release_event()
390         int result = BC_Toggle::button_release_event();
391         if(patch->patchbay->drag_operation != Tracks::NONE)
392         {
393                 patch->patchbay->drag_operation = Tracks::NONE;
394         }
395         return result;
408 RecordPatch::RecordPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
409  : BC_Toggle(x, 
410                 y, 
411                 mwindow->theme->get_image_set("recordpatch_data"),
412                 patch->track->record, 
413                 "",
414                 0,
415                 0,
416                 0)
418         this->mwindow = mwindow;
419         this->patch = patch;
420         set_tooltip(_("Arm track"));
421         set_select_drag(1);
424 int RecordPatch::button_press_event()
426         if(is_event_win() && get_buttonpress() == 1)
427         {
428                 set_status(BC_Toggle::TOGGLE_DOWN);
429                 update(!get_value());
430                 patch->toggle_behavior(Tracks::RECORD,
431                         get_value(),
432                         this,
433                         &patch->track->record);
434                 return 1;
435         }
436         return 0;
439 int RecordPatch::button_release_event()
441         int result = BC_Toggle::button_release_event();
442         if(patch->patchbay->drag_operation != Tracks::NONE)
443         {
444                 patch->patchbay->drag_operation = Tracks::NONE;
445         }
446         return result;
459 GangPatch::GangPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
460  : BC_Toggle(x, y, 
461                 mwindow->theme->get_image_set("gangpatch_data"),
462                 patch->track->gang, 
463                 "",
464                 0,
465                 0,
466                 0)
468         this->mwindow = mwindow;
469         this->patch = patch;
470         set_tooltip(_("Gang faders"));
471         set_select_drag(1);
474 int GangPatch::button_press_event()
476         if(is_event_win() && get_buttonpress() == 1)
477         {
478                 set_status(BC_Toggle::TOGGLE_DOWN);
479                 update(!get_value());
480                 patch->toggle_behavior(Tracks::GANG,
481                         get_value(),
482                         this,
483                         &patch->track->gang);
484                 return 1;
485         }
486         return 0;
489 int GangPatch::button_release_event()
491         int result = BC_Toggle::button_release_event();
492         if(patch->patchbay->drag_operation != Tracks::NONE)
493         {
494                 patch->patchbay->drag_operation = Tracks::NONE;
495         }
496         return result;
509 DrawPatch::DrawPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
510  : BC_Toggle(x, y, 
511                 mwindow->theme->get_image_set("drawpatch_data"),
512                 patch->track->draw, 
513                 "",
514                 0,
515                 0,
516                 0)
518         this->mwindow = mwindow;
519         this->patch = patch;
520         set_tooltip(_("Draw media"));
521         set_select_drag(1);
524 int DrawPatch::button_press_event()
526         if(is_event_win() && get_buttonpress() == 1)
527         {
528                 set_status(BC_Toggle::TOGGLE_DOWN);
529                 update(!get_value());
530                 patch->toggle_behavior(Tracks::DRAW,
531                         get_value(),
532                         this,
533                         &patch->track->draw);
534                 return 1;
535         }
536         return 0;
539 int DrawPatch::button_release_event()
541         int result = BC_Toggle::button_release_event();
542         if(patch->patchbay->drag_operation != Tracks::NONE)
543         {
544                 patch->patchbay->drag_operation = Tracks::NONE;
545         }
546         return result;
558 MutePatch::MutePatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
559  : BC_Toggle(x, y, 
560                 mwindow->theme->get_image_set("mutepatch_data"),
561                 get_keyframe(mwindow, patch)->value, 
562                 "",
563                 0,
564                 0,
565                 0)
567         this->mwindow = mwindow;
568         this->patch = patch;
569         set_tooltip(_("Don't send to output"));
570         set_select_drag(1);
573 int MutePatch::button_press_event()
575         if(is_event_win() && get_buttonpress() == 1)
576         {
577                 set_status(BC_Toggle::TOGGLE_DOWN);
578                 update(!get_value());
579                 IntAuto *current;
580                 double position = mwindow->edl->local_session->get_selectionstart(1);
581                 Autos *mute_autos = patch->track->automation->autos[AUTOMATION_MUTE];
584                 current = (IntAuto*)mute_autos->get_auto_for_editing(position);
585                 current->value = get_value();
587                 patch->toggle_behavior(Tracks::MUTE,
588                         get_value(),
589                         this,
590                         &current->value);
593                 mwindow->undo->update_undo(_("keyframe"), LOAD_AUTOMATION);
595                 if(mwindow->edl->session->auto_conf->autos[AUTOMATION_MUTE])
596                 {
597                         mwindow->gui->canvas->draw_overlays();
598                         mwindow->gui->canvas->flash();
599                 }
600                 return 1;
601         }
602         return 0;
605 int MutePatch::button_release_event()
607         int result = BC_Toggle::button_release_event();
608         if(patch->patchbay->drag_operation != Tracks::NONE)
609         {
610                 patch->patchbay->drag_operation = Tracks::NONE;
611         }
612         return result;
615 IntAuto* MutePatch::get_keyframe(MWindow *mwindow, PatchGUI *patch)
617         Auto *current = 0;
618         double unit_position = mwindow->edl->local_session->get_selectionstart(1);
619         unit_position = mwindow->edl->align_to_frame(unit_position, 0);
620         unit_position = patch->track->to_units(unit_position, 0);
621         return (IntAuto*)patch->track->automation->autos[AUTOMATION_MUTE]->get_prev_auto(
622                 (int64_t)unit_position, 
623                 PLAY_FORWARD,
624                 current);
638 ExpandPatch::ExpandPatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
639  : BC_Toggle(x, 
640                 y, 
641                 mwindow->theme->get_image_set("expandpatch_data"),
642                 patch->track->expand_view, 
643                 "",
644                 0,
645                 0,
646                 0)
648         this->mwindow = mwindow;
649         this->patch = patch;
650         set_select_drag(1);
653 int ExpandPatch::button_press_event()
655         if(is_event_win() && get_buttonpress() == 1)
656         {
657                 set_status(BC_Toggle::TOGGLE_DOWN);
658                 update(!get_value());
659                 patch->toggle_behavior(Tracks::EXPAND,
660                         get_value(),
661                         this,
662                         &patch->track->expand_view);
663                 mwindow->trackmovement(mwindow->edl->local_session->track_start);
664                 return 1;
665         }
666         return 0;
669 int ExpandPatch::button_release_event()
671         int result = BC_Toggle::button_release_event();
672         if(patch->patchbay->drag_operation != Tracks::NONE)
673         {
674                 patch->patchbay->drag_operation = Tracks::NONE;
675         }
676         return result;
683 TitlePatch::TitlePatch(MWindow *mwindow, PatchGUI *patch, int x, int y)
684  : BC_TextBox(x, 
685                 y, 
686                 patch->patchbay->get_w() - 10, 
687                 1,
688                 patch->track->title)
690         this->mwindow = mwindow;
691         this->patch = patch;
694 int TitlePatch::handle_event()
696         strcpy(patch->track->title, get_text());
697         mwindow->update_plugin_titles();
698         mwindow->gui->canvas->draw_overlays();
699         mwindow->gui->canvas->flash();
700         mwindow->undo->update_undo(_("track title"), LOAD_PATCHES);
701         return 1;
712 NudgePatch::NudgePatch(MWindow *mwindow, 
713         PatchGUI *patch, 
714         int x, 
715         int y, 
716         int w)
717  : BC_TextBox(x,
718         y,
719         w,
720         1,
721         patch->calculate_nudge_text(0))
723         this->mwindow = mwindow;
724         this->patch = patch;
725         set_tooltip(_("Nudge"));
728 int NudgePatch::handle_event()
730         set_value(patch->calculate_nudge(get_text()));
731         return 1;
734 void NudgePatch::set_value(int64_t value)
736         patch->track->nudge = value;
738         if(patch->track->gang)
739                 patch->patchbay->synchronize_nudge(patch->track->nudge, patch->track);
741         mwindow->undo->update_undo("nudge", LOAD_AUTOMATION, this);
743         mwindow->gui->unlock_window();
744         if(patch->track->data_type == TRACK_VIDEO)
745                 mwindow->restart_brender();
746         mwindow->sync_parameters(CHANGE_PARAMS);
747         mwindow->gui->lock_window("NudgePatch::handle_event 2");
749         mwindow->session->changes_made = 1;
753 int NudgePatch::button_press_event()
755         int result = 0;
757         if(is_event_win() && cursor_inside())
758         {
759                 if(get_buttonpress() == 4)
760                 {
761                         int value = patch->calculate_nudge(get_text());
762                         value += calculate_increment();
763                         set_value(value);
764                         update();
765                         result = 1;
766                 }
767                 else
768                 if(get_buttonpress() == 5)
769                 {
770                         int value = patch->calculate_nudge(get_text());
771                         value -= calculate_increment();
772                         set_value(value);
773                         update();
774                         result = 1;
775                 }
776                 else
777                 if(get_buttonpress() == 3)
778                 {
779                         patch->patchbay->nudge_popup->activate_menu(patch);
780                         result = 1;
781                 }
782         }
784         if(!result)
785                 return BC_TextBox::button_press_event();
786         else
787                 return result;
790 int64_t NudgePatch::calculate_increment()
792         if(patch->track->data_type == TRACK_AUDIO)
793         {
794                 return (int64_t)ceil(patch->track->edl->session->sample_rate / 10);
795         }
796         else
797         {
798                 return (int64_t)ceil(1.0 / patch->track->edl->session->frame_rate);
799         }
802 void NudgePatch::update()
804         int changed;
805         char *string = patch->calculate_nudge_text(&changed);
806         if(changed)
807                 BC_TextBox::update(string);