r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / patchbay.C
blob77b10d4aa3dc44f09fddf07946bb2eba4038dae9
1 #include "apatchgui.h"#include "atrack.inc"
2 #include "automation.h"
3 #include "floatauto.h"
4 #include "floatautos.h"
5 #include "clip.h"
6 #include "edl.h"
7 #include "edlsession.h"
8 #include "filexml.h"
9 #include "intauto.h"
10 #include "intautos.h"
11 #include "localsession.h"
12 #include "mainundo.h"
13 #include "mwindow.h"
14 #include "mwindowgui.h"
15 #include "patchbay.h"
16 #include "patchgui.h"
17 #include "mainsession.h"
18 #include "theme.h"
19 #include "track.h"
20 #include "trackcanvas.h"
21 #include "tracks.h"
22 #include "vpatchgui.h"
23 #include "vtrack.inc"
25 #include <libintl.h>
26 #define _(String) gettext(String)
27 #define gettext_noop(String) String
28 #define N_(String) gettext_noop (String)
31 PatchBay::PatchBay(MWindow *mwindow, MWindowGUI *gui)
32  : BC_SubWindow(mwindow->theme->patchbay_x,
33         mwindow->theme->patchbay_y,
34         mwindow->theme->patchbay_w,
35         mwindow->theme->patchbay_h)
37         this->mwindow = mwindow;
38         this->gui = gui;
39         button_down = 0;
40         reconfigure_trigger = 0;
41         drag_operation = Tracks::NONE;
44 PatchBay::~PatchBay() 
49 int PatchBay::delete_all_patches()
51     patches.remove_all_objects();
52     return 0;
55 int PatchBay::create_objects()
57         draw_top_background(get_parent(), 0, 0, get_w(), get_h());
58         flash();
59         return 0;
62 void PatchBay::resize_event()
64         reposition_window(mwindow->theme->patchbay_x,
65                 mwindow->theme->patchbay_y,
66                 mwindow->theme->patchbay_w,
67                 mwindow->theme->patchbay_h);
68         draw_top_background(get_parent(), 0, 0, get_w(), get_h());
69         update();
70         flash();
73 int PatchBay::button_press_event()
75         int result = 0;
76 // Too much junk to support the wheel
77         return result;
80 int PatchBay::cursor_motion_event()
82         int cursor_x = get_relative_cursor_x();
83         int cursor_y = get_relative_cursor_y();
84         int update_gui = 0;
86         if(drag_operation != Tracks::NONE)
87         {
88                 if(cursor_y >= 0 &&
89                         cursor_y < get_h())
90                 {
91 // Get track we're inside of
92                         for(Track *track = mwindow->edl->tracks->first;
93                                 track;
94                                 track = track->next)
95                         {
96                                 int y = track->y_pixel;
97                                 int h = track->vertical_span(mwindow->theme);
98                                 if(cursor_y >= y && cursor_y < y + h)
99                                 {
100                                         switch(drag_operation)
101                                         {
102                                                 case Tracks::PLAY:
103                                                         if(track->play != new_status)
104                                                         {
105                                                                 track->play = new_status;
106                                                                 mwindow->gui->unlock_window();
107                                                                 mwindow->restart_brender();
108                                                                 mwindow->sync_parameters(CHANGE_EDL);
109                                                                 mwindow->gui->lock_window();
110                                                                 update_gui = 1;
111                                                         }
112                                                         break;
113                                                 case Tracks::RECORD:
114                                                         if(track->record != new_status)
115                                                         {
116                                                                 track->record = new_status;
117                                                                 update_gui = 1;
118                                                         }
119                                                         break;
120                                                 case Tracks::GANG:
121                                                         if(track->gang != new_status)
122                                                         {
123                                                                 track->gang = new_status;
124                                                                 update_gui = 1;
125                                                         }
126                                                         break;
127                                                 case Tracks::DRAW:
128                                                         if(track->draw != new_status)
129                                                         {
130                                                                 track->draw = new_status;
131                                                                 update_gui = 1;
132                                                         }
133                                                         break;
134                                                 case Tracks::EXPAND:
135                                                         if(track->expand_view != new_status)
136                                                         {
137                                                                 track->expand_view = new_status;
138                                                                 mwindow->trackmovement(mwindow->edl->local_session->track_start);
139                                                                 update_gui = 0;
140                                                         }
141                                                         break;
142                                                 case Tracks::MUTE:
143                                                 {
144                                                         IntAuto *current = 0;
145                                                         Auto *keyframe = 0;
146                                                         double position = mwindow->edl->local_session->selectionstart;
147                                                         Autos *mute_autos = track->automation->mute_autos;
149                                                         current = (IntAuto*)mute_autos->get_prev_auto(PLAY_FORWARD, 
150                                                                 keyframe);
152                                                         if(current->value != new_status)
153                                                         {
154                                                                 mwindow->undo->update_undo_before(_("keyframe"), LOAD_AUTOMATION);
156                                                                 current = (IntAuto*)mute_autos->get_auto_for_editing(position);
158                                                                 current->value = new_status;
160                                                                 mwindow->undo->update_undo_after();
162                                                                 mwindow->gui->unlock_window();
163                                                                 mwindow->restart_brender();
164                                                                 mwindow->sync_parameters(CHANGE_PARAMS);
165                                                                 mwindow->gui->lock_window();
167                                                                 if(mwindow->edl->session->auto_conf->mute)
168                                                                 {
169                                                                         mwindow->gui->canvas->draw_overlays();
170                                                                         mwindow->gui->canvas->flash();
171                                                                 }
172                                                                 update_gui = 1;
173                                                         }
174                                                         break;
175                                                 }
176                                         }
177                                 }
178                         }
179                 }
180         }
182         if(update_gui)
183         {
184                 update();
185         }
186         return 0;
189 void PatchBay::change_meter_format(int mode, float min)
191         for(int i = 0; i < patches.total; i++)
192         {
193                 PatchGUI *patchgui = patches.values[i];
194                 if(patchgui->data_type == TRACK_AUDIO)
195                 {
196                         APatchGUI *apatchgui = (APatchGUI*)patchgui;
197                         if(apatchgui->meter)
198                         {
199                                 apatchgui->meter->change_format(mode, min);
200                         }
201                 }
202         }
205 void PatchBay::update_meters(ArrayList<double> *module_levels)
207         for(int level_number = 0, patch_number = 0;
208                 patch_number < patches.total && level_number < module_levels->total;
209                 patch_number++)
210         {
211                 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
213                 if(patchgui->data_type == TRACK_AUDIO)
214                 {
215                         if(patchgui->meter)
216                         {
217                                 double level = module_levels->values[level_number];
218                                 patchgui->meter->update(level, level > 1);
219                         }
221                         level_number++;
222                 }
223         }
226 void PatchBay::reset_meters()
228         for(int patch_number = 0;
229                 patch_number < patches.total;
230                 patch_number++)
231         {
232                 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
233                 if(patchgui->data_type == TRACK_AUDIO && patchgui->meter)
234                 {
235                         patchgui->meter->reset_over();
236                 }
237         }
240 void PatchBay::stop_meters()
242         for(int patch_number = 0;
243                 patch_number < patches.total;
244                 patch_number++)
245         {
246                 APatchGUI *patchgui = (APatchGUI*)patches.values[patch_number];
247                 if(patchgui->data_type == TRACK_AUDIO && patchgui->meter)
248                 {
249                         patchgui->meter->reset();
250                 }
251         }
255 #define PATCH_X 3
257 int PatchBay::update()
259         int patch_count = 0;
261 // Every patch has a GUI regardless of whether or not it is visible.
262 // Make sure GUI's are allocated for every patch and deleted for non-existant
263 // patches.
264         for(Track *current = mwindow->edl->tracks->first;
265                 current;
266                 current = NEXT, patch_count++)
267         {
268                 PatchGUI *patchgui;
269                 int y = current->y_pixel;
271                 if(patches.total > patch_count)
272                 {
273                         if(patches.values[patch_count]->track_id != current->get_id())
274                         {
275                                 delete patches.values[patch_count];
277                                 switch(current->data_type)
278                                 {
279                                         case TRACK_AUDIO:
280                                                 patchgui = patches.values[patch_count] = new APatchGUI(mwindow, this, (ATrack*)current, PATCH_X, y);
281                                                 break;
282                                         case TRACK_VIDEO:
283                                                 patchgui = patches.values[patch_count] = new VPatchGUI(mwindow, this, (VTrack*)current, PATCH_X, y);
284                                                 break;
285                                 }
286                                 patchgui->create_objects();
287                         }
288                         else
289                         {
290                                 patches.values[patch_count]->update(PATCH_X, y);
291                         }
292                 }
293                 else
294                 {
295                         switch(current->data_type)
296                         {
297                                 case TRACK_AUDIO:
298                                         patchgui = new APatchGUI(mwindow, this, (ATrack*)current, PATCH_X, y);
299                                         break;
300                                 case TRACK_VIDEO:
301                                         patchgui = new VPatchGUI(mwindow, this, (VTrack*)current, PATCH_X, y);
302                                         break;
303                         }
304                         patches.append(patchgui);
305                         patchgui->create_objects();
306                 }
307         }
309         while(patches.total > patch_count)
310         {
311                 delete patches.values[patches.total - 1];
312                 patches.remove_number(patches.total - 1);
313         }
315         return 0;
318 void PatchBay::synchronize_faders(float change, int data_type, Track *skip)
320         for(Track *current = mwindow->edl->tracks->first;
321                 current;
322                 current = NEXT)
323         {
324                 if(current->data_type == data_type &&
325                         current->gang && 
326                         current->record && 
327                         current != skip)
328                 {
329                         FloatAutos *fade_autos = current->automation->fade_autos;
330                         double position = mwindow->edl->local_session->selectionstart;
331                         int update_undo = !fade_autos->auto_exists_for_editing(position);
333                         if(update_undo)
334                                 mwindow->undo->update_undo_before(_("fade"), LOAD_AUTOMATION);
336                         FloatAuto *keyframe = (FloatAuto*)fade_autos->get_auto_for_editing(position);
338                         keyframe->value += change;
339                         if(data_type == TRACK_AUDIO)
340                                 CLAMP(keyframe->value, INFINITYGAIN, MAX_AUDIO_FADE);
341                         else
342                                 CLAMP(keyframe->value, 0, MAX_VIDEO_FADE);
343                         if(update_undo)
344                                 mwindow->undo->update_undo_after();
347                         for(int i = 0; i < patches.total; i++)
348                         {
349                                 if(patches.values[i]->track == current)
350                                         patches.values[i]->update(patches.values[i]->x,
351                                                 patches.values[i]->y);
352                         }
353                 }
354         }
359 int PatchBay::resize_event(int top, int bottom)
361         reposition_window(mwindow->theme->patchbay_x,
362                 mwindow->theme->patchbay_y,
363                 mwindow->theme->patchbay_w,
364                 mwindow->theme->patchbay_h);
365         return 0;