color coded keyframe curves, keyframe popups, cwin scrollbar fixes
[goodguy/history.git] / cinelerra-5.1 / cinelerra / apatchgui.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "apatchgui.h"
23 #include "atrack.h"
24 #include "autoconf.h"
25 #include "automation.h"
26 #include "edl.h"
27 #include "edlsession.h"
28 #include "floatauto.h"
29 #include "floatautos.h"
30 #include "gwindowgui.h"
31 #include "intauto.h"
32 #include "intautos.h"
33 #include "language.h"
34 #include "localsession.h"
35 #include "mainundo.h"
36 #include "mwindow.h"
37 #include "mwindowgui.h"
38 #include "panauto.h"
39 #include "panautos.h"
40 #include "patchbay.h"
41 #include "theme.h"
42 #include "trackcanvas.h"
43
44
45
46
47 APatchGUI::APatchGUI(MWindow *mwindow,
48         PatchBay *patchbay,
49         ATrack *track,
50         int x,
51         int y)
52  : PatchGUI(mwindow,
53         patchbay,
54         track,
55         x,
56         y)
57 {
58         data_type = TRACK_AUDIO;
59         this->atrack = track;
60         meter = 0;
61         pan = 0;
62         fade = 0;
63 }
64
65 APatchGUI::~APatchGUI()
66 {
67         if(fade) delete fade;
68         if(meter) delete meter;
69         if(pan) delete pan;
70 }
71
72 void APatchGUI::create_objects()
73 {
74         update(x, y);
75 }
76
77 int APatchGUI::reposition(int x, int y)
78 {
79         int y1 = PatchGUI::reposition(x, y);
80
81         if(fade) fade->reposition_window(fade->get_x(),
82                 y1 + y);
83         y1 += mwindow->theme->fade_h;
84
85         if(meter) meter->reposition_window(meter->get_x(),
86                 y1 + y,
87                 -1,
88                 meter->get_w());
89         y1 += mwindow->theme->meter_h;
90
91         if(pan) pan->reposition_window(pan->get_x(),
92                 y1 + y);
93
94         if(nudge) nudge->reposition_window(nudge->get_x(),
95                 y1 + y);
96
97         y1 += mwindow->theme->pan_h;
98         return y1;
99 }
100
101 int APatchGUI::update(int x, int y)
102 {
103         int h = track->vertical_span(mwindow->theme);
104         int x1 = 0;
105         int y1 = PatchGUI::update(x, y);
106
107         if(fade)
108         {
109                 if(h - y1 < mwindow->theme->fade_h)
110                 {
111                         delete fade;
112                         fade = 0;
113                 }
114                 else
115                 {
116                         FloatAuto *previous = 0, *next = 0;
117                         double unit_position = mwindow->edl->local_session->get_selectionstart(1);
118                         unit_position = mwindow->edl->align_to_frame(unit_position, 0);
119                         unit_position = atrack->to_units(unit_position, 0);
120                         FloatAutos *ptr = (FloatAutos*)atrack->automation->autos[AUTOMATION_FADE];
121                         float value = ptr->get_value(
122                                 (long)unit_position,
123                                 PLAY_FORWARD, 
124                                 previous,
125                                 next);
126                         fade->update(fade->get_w(),
127                                      value,
128                                      mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_AUDIO_FADE],
129                                      mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_AUDIO_FADE]);
130                 }
131         }
132         else
133         if(h - y1 >= mwindow->theme->fade_h)
134         {
135                 patchbay->add_subwindow(fade = new AFadePatch(mwindow,
136                         this,
137                         x1 + x,
138                         y1 + y,
139                         patchbay->get_w() - 10));
140         }
141         y1 += mwindow->theme->fade_h;
142
143         if(meter)
144         {
145                 if(h - y1 < mwindow->theme->meter_h)
146                 {
147                         delete meter;
148                         meter = 0;
149                 }
150         }
151         else
152         if(h - y1 >= mwindow->theme->meter_h)
153         {
154                 patchbay->add_subwindow(meter = new AMeterPatch(mwindow,
155                         this,
156                         x1 + x,
157                         y1 + y));
158         }
159         y1 += mwindow->theme->meter_h;
160         x1 += 10;
161
162         if(pan)
163         {
164                 if(h - y1 < mwindow->theme->pan_h)
165                 {
166                         delete pan;
167                         pan = 0;
168                         delete nudge;
169                         nudge = 0;
170                 }
171                 else
172                 {
173                         if(pan->get_total_values() != mwindow->edl->session->audio_channels)
174                         {
175                                 pan->change_channels(mwindow->edl->session->audio_channels,
176                                         mwindow->edl->session->achannel_positions);
177                         }
178                         else
179                         {
180                                 int handle_x, handle_y;
181                                 PanAuto *previous = 0, *next = 0;
182                                 double unit_position = mwindow->edl->local_session->get_selectionstart(1);
183                                 unit_position = mwindow->edl->align_to_frame(unit_position, 0);
184                                 unit_position = atrack->to_units(unit_position, 0);
185                                 PanAutos *ptr = (PanAutos*)atrack->automation->autos[AUTOMATION_PAN];
186                                 ptr->get_handle(handle_x,
187                                         handle_y,
188                                         (long)unit_position,
189                                         PLAY_FORWARD,
190                                         previous,
191                                         next);
192                                 pan->update(handle_x, handle_y);
193                         }
194                         nudge->update();
195                 }
196         }
197         else
198         if(h - y1 >= mwindow->theme->pan_h)
199         {
200                 patchbay->add_subwindow(pan = new APanPatch(mwindow,
201                         this,
202                         x1 + x,
203                         y1 + y));
204                 x1 += pan->get_w() + 10;
205                 patchbay->add_subwindow(nudge = new NudgePatch(mwindow,
206                         this,
207                         x1 + x,
208                         y1 + y,
209                         patchbay->get_w() - x1 - 10));
210         }
211         y1 += mwindow->theme->pan_h;
212
213         return y1;
214 }
215
216 void APatchGUI::synchronize_fade(float value_change)
217 {
218         if(fade && !change_source)
219         {
220                 fade->update(fade->get_value() + value_change);
221                 fade->update_edl();
222         }
223 }
224
225
226
227 AFadePatch::AFadePatch(MWindow *mwindow, APatchGUI *patch, int x, int y, int w)
228  : BC_FSlider(x, y, 0, w, w,
229         mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_AUDIO_FADE],
230         mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_AUDIO_FADE],
231         mwindow->get_float_auto(patch, AUTOMATION_FADE)->get_value())
232 {
233         this->mwindow = mwindow;
234         this->patch = patch;
235 }
236
237 float AFadePatch::update_edl()
238 {
239         FloatAuto *current;
240         double position = mwindow->edl->local_session->get_selectionstart(1);
241         Autos *fade_autos = patch->atrack->automation->autos[AUTOMATION_FADE];
242         int need_undo = !fade_autos->auto_exists_for_editing(position);
243
244         mwindow->undo->update_undo_before(_("fade"), need_undo ? 0 : this);
245
246         current = (FloatAuto*)fade_autos->get_auto_for_editing(position);
247
248         float result = get_value() - current->get_value();
249         current->set_value(this->get_value());
250
251         mwindow->undo->update_undo_after(_("fade"), LOAD_AUTOMATION);
252
253         return result;
254 }
255
256
257 int AFadePatch::handle_event()
258 {
259         if(shift_down()) 
260         {
261                 update(0.0);
262                 set_tooltip(get_caption());
263         }
264
265         patch->change_source = 1;
266         float change = update_edl();
267         if(patch->track->gang && patch->track->record) 
268                 patch->patchbay->synchronize_faders(change, TRACK_AUDIO, patch->track);
269         patch->change_source = 0;
270
271         mwindow->sync_parameters(CHANGE_PARAMS);
272
273         if(mwindow->edl->session->auto_conf->autos[AUTOMATION_FADE])
274         {
275                 mwindow->gui->draw_overlays(1);
276         }
277         return 1;
278 }
279
280 AKeyFadePatch::AKeyFadePatch(MWindow *mwindow, APatchGUI *patch, int x, int y)
281  : BC_SubWindow(x,y, patch->patchbay->get_w(),20,
282         GWindowGUI::auto_colors[AUTOMATION_FADE])
283 {
284         this->mwindow = mwindow;
285         this->patch = patch;
286 }
287
288 void AKeyFadePatch::create_objects()
289 {
290         akey_fade_value = new AKeyFadeValue(this);
291         add_subwindow(akey_fade_value);
292         akey_fade_value->activate();
293         show_window();
294 }
295
296 AKeyFadeValue::AKeyFadeValue(AKeyFadePatch *akey_fade_patch)
297  : AFadePatch(akey_fade_patch->mwindow, akey_fade_patch->patch,
298         0,0, akey_fade_patch->get_w())
299 {
300         this->akey_fade_patch = akey_fade_patch;
301 }
302
303 int AKeyFadeValue::button_release_event()
304 {
305         AFadePatch::button_release_event();
306         return 0;
307 }
308
309 int AKeyFadeValue::handle_event()
310 {
311         APatchGUI *patch = akey_fade_patch->patch;
312         int ret = AFadePatch::handle_event();
313         AFadePatch *fade = patch->fade;
314         if( fade )
315                 fade->update(get_value());
316         return ret;
317 }
318
319
320 APanPatch::APanPatch(MWindow *mwindow, APatchGUI *patch, int x, int y)
321  : BC_Pan(x, y, PAN_RADIUS, MAX_PAN,
322         mwindow->edl->session->audio_channels,
323         mwindow->edl->session->achannel_positions,
324         mwindow->get_pan_auto(patch)->handle_x,
325         mwindow->get_pan_auto(patch)->handle_y,
326         mwindow->get_pan_auto(patch)->values)
327 {
328         this->mwindow = mwindow;
329         this->patch = patch;
330         set_tooltip(_("Pan"));
331 }
332
333 int APanPatch::handle_event()
334 {
335         PanAuto *current;
336         double position = mwindow->edl->local_session->get_selectionstart(1);
337         Autos *pan_autos = patch->atrack->automation->autos[AUTOMATION_PAN];
338         int need_undo = !pan_autos->auto_exists_for_editing(position);
339
340         mwindow->undo->update_undo_before(_("pan"), need_undo ? 0 : this);
341         
342         current = (PanAuto*)pan_autos->get_auto_for_editing(position);
343
344         current->handle_x = get_stick_x();
345         current->handle_y = get_stick_y();
346         memcpy(current->values, get_values(), sizeof(float) * mwindow->edl->session->audio_channels);
347
348         mwindow->undo->update_undo_after(_("pan"), LOAD_AUTOMATION);
349
350         mwindow->sync_parameters(CHANGE_PARAMS);
351
352         if(need_undo && mwindow->edl->session->auto_conf->autos[AUTOMATION_PAN])
353         {
354                 mwindow->gui->draw_overlays(1);
355         }
356         return 1;
357 }
358
359 AKeyPanPatch::AKeyPanPatch(MWindow *mwindow, APatchGUI *patch)
360  : APanPatch(mwindow, patch, -1,-1)
361 {
362 }
363
364 int AKeyPanPatch::button_release_event()
365 {
366         APanPatch::button_release_event();
367         return 0;
368 }
369
370 int AKeyPanPatch::handle_event()
371 {
372         int ret = APanPatch::handle_event();
373         APanPatch *pan = patch->pan;
374         if( pan )
375                 pan->update(get_stick_x(), get_stick_y());
376         return ret;
377 }
378
379
380 AMeterPatch::AMeterPatch(MWindow *mwindow, APatchGUI *patch, int x, int y)
381  : BC_Meter(x, 
382                         y, 
383                         METER_HORIZ, 
384                         patch->patchbay->get_w() - 10, 
385                         mwindow->edl->session->min_meter_db, 
386                         mwindow->edl->session->max_meter_db, 
387                         mwindow->edl->session->meter_format, 
388                         0,
389                         -1)
390 {
391         this->mwindow = mwindow;
392         this->patch = patch;
393         set_delays(TRACKING_RATE * 10,
394                         TRACKING_RATE);
395 }
396
397 int AMeterPatch::button_press_event()
398 {
399         if(cursor_inside() && is_event_win() && get_buttonpress() == 1)
400         {
401                 mwindow->reset_meters();
402                 return 1;
403         }
404
405         return 0;
406 }
407