prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / virtualaconsole.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 "aedit.h"
23 #include "amodule.h"
24 #include "arender.h"
25 #include "assets.h"
26 #include "atrack.h"
27 #include "audiodevice.h"
28 #include "bcsignals.h"
29 #include "condition.h"
30 #include "edit.h"
31 #include "edits.h"
32 #include "edl.h"
33 #include "edlsession.h"
34 #include "file.h"
35 #include "format.inc"
36 #include "levelwindow.h"
37 #include "playabletracks.h"
38 #include "plugin.h"
39 #include "preferences.h"
40 #include "renderengine.h"
41 #include "samples.h"
42 #include "thread.h"
43 #include "tracks.h"
44 #include "transportque.h"
45 #include "virtualaconsole.h"
46 #include "virtualanode.h"
47 #include "virtualnode.h"
48
49
50 VirtualAConsole::VirtualAConsole(RenderEngine *renderengine, ARender *arender)
51  : VirtualConsole(renderengine, arender, TRACK_AUDIO)
52 {
53         this->arender = arender;
54         output_temp = 0;
55         output_allocation = 0;
56 }
57
58 VirtualAConsole::~VirtualAConsole()
59 {
60         if(output_temp) delete output_temp;
61 }
62
63
64 void VirtualAConsole::get_playable_tracks()
65 {
66         if(!playable_tracks)
67                 playable_tracks = new PlayableTracks(renderengine->get_edl(), 
68                         commonrender->current_position, 
69                         renderengine->command->get_direction(),
70                         TRACK_AUDIO,
71                         1);
72 }
73
74
75 VirtualNode* VirtualAConsole::new_entry_node(Track *track, 
76         Module *module,
77         int track_number)
78 {
79         return new VirtualANode(renderengine,
80                 this, module, 0, track, 0);
81         return 0;
82 }
83
84
85
86 int VirtualAConsole::process_buffer(int64_t len,
87         int64_t start_position)
88 {
89         int result = 0;
90         const int debug = 0;
91 if(debug) printf("VirtualAConsole::process_buffer %d this=%p len=" _LD "\n", 
92   __LINE__, this, len);
93
94
95 // clear output buffers
96         for(int i = 0; i < MAX_CHANNELS; i++)
97         {
98 // if(debug) printf("VirtualAConsole::process_buffer 2 %d %p " _LD "\n", 
99 // i, 
100 // arender->audio_out[i],
101 // len);
102
103                 if(arender->audio_out[i])
104                 {
105                         bzero(arender->audio_out[i]->get_data(), len * sizeof(double));
106                 }
107         }
108
109 // Create temporary output
110         if(output_temp && output_allocation < len)
111         {
112                 delete output_temp;
113                 output_temp = 0;
114         }
115
116         if(!output_temp)
117         {
118                 output_temp = new Samples(len);
119                 output_allocation = len;
120         }
121 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
122
123
124 // Reset plugin rendering status
125         reset_attachments();
126 //printf("VirtualAConsole::process_buffer 1 %p\n", output_temp);
127
128 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
129
130
131 // Render exit nodes
132         for(int i = 0; i < exit_nodes.total; i++)
133         {
134                 VirtualANode *node = (VirtualANode*)exit_nodes.values[i];
135                 Track *track = node->track;
136
137                 result |= node->render(output_temp, 
138                         len,
139                         start_position + track->nudge,
140                         renderengine->get_edl()->session->sample_rate);
141         }
142 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
143
144
145
146 // get peaks and limit volume in the fragment
147         for(int i = 0; i < MAX_CHANNELS; i++)
148         {
149                 if(arender->audio_out[i])
150                 {
151                         double *current_buffer = arender->audio_out[i]->get_data();
152
153
154                         for(int j = 0; j < len; )
155                         {
156                                 int meter_render_end;
157 // Get length to test for meter and limit
158                                 if(renderengine->command->realtime)
159                                         meter_render_end = j + arender->meter_render_fragment;
160                                 else
161                                         meter_render_end = len;
162
163                                 if(meter_render_end > len) 
164                                         meter_render_end =  len;
165
166                                 double peak = 0;
167
168                                 for( ; j < meter_render_end; j++)
169                                 {
170 // Level history comes before clipping to get over status
171                                         double *sample = &current_buffer[j];
172
173
174                                         if(fabs(*sample) > peak) peak = fabs(*sample);
175 // Make the output device clip it
176 //                                      if(*sample > 1) *sample = 1;
177 //                                      else
178 //                                      if(*sample < -1) *sample = -1;
179                                 }
180
181
182                                 if(renderengine->command->realtime)
183                                 {
184                                         arender->level_history[i][arender->current_level[i]] = peak;
185                                         arender->level_samples[arender->current_level[i]] = 
186                                                 renderengine->command->get_direction() == PLAY_REVERSE ? 
187                                                 start_position - j : 
188                                                 start_position + j;
189                                         arender->current_level[i] = arender->get_next_peak(arender->current_level[i]);
190                                 }
191                         }
192                 }
193         }
194
195 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
196
197
198
199
200
201 // Pack channels, fix speed and send to device.
202         if(!renderengine->is_nested &&
203                 renderengine->command->realtime && 
204                 !interrupt)
205         {
206 // speed parameters
207 // length compensated for speed
208                 int real_output_len = 0;
209 // output sample
210                 double sample;
211                 int k;
212                 double *audio_out_packed[MAX_CHANNELS];
213                 int audio_channels = renderengine->get_edl()->session->audio_channels;
214
215                 for(int i = 0, j = 0; 
216                         i < audio_channels; 
217                         i++)
218                 {
219                         audio_out_packed[j++] = arender->audio_out[i]->get_data();
220                 }
221                 for(int i = 0; 
222                         i < audio_channels; 
223                         i++)
224                 {
225                         int in, out;
226
227                         double *current_buffer = audio_out_packed[i];
228
229 // Time stretch the fragment to the real_output size
230                         if(renderengine->command->get_speed() > 1)
231                         {
232 // Number of samples in real output buffer for each to sample rendered.
233                                 int interpolate_len = (int)renderengine->command->get_speed();
234                                 for(in = 0, out = 0; in < len; )
235                                 {
236                                         sample = 0;
237                                         for(k = 0; k < interpolate_len; k++)
238                                         {
239                                                 sample += current_buffer[in++];
240                                         }
241
242                                         sample /= renderengine->command->get_speed();
243                                         current_buffer[out++] = sample;
244                                 }
245                                 real_output_len = out;
246                         }
247                         else
248                         if(renderengine->command->get_speed() < 1)
249                         {
250 // number of samples to skip
251                                 int interpolate_len = (int)(1.0 / renderengine->command->get_speed());
252                                 real_output_len = len * interpolate_len;
253
254                                 for(in = len - 1, out = real_output_len - 1; in >= 0; )
255                                 {
256                                         for(k = 0; k < interpolate_len; k++)
257                                         {
258                                                 current_buffer[out--] = current_buffer[in];
259                                         }
260                                         in--;
261                                 }
262                         }
263                         else
264                                 real_output_len = len;
265                 }
266
267 // Wait until video is ready
268                 if(arender->first_buffer)
269                 {
270                         renderengine->first_frame_lock->lock("VirtualAConsole::process_buffer");
271                         arender->first_buffer = 0;
272                 }
273                 if(!renderengine->audio->get_interrupted())
274                 {
275                         renderengine->audio->write_buffer(audio_out_packed, audio_channels,
276                                 real_output_len);
277                 }
278
279                 if(renderengine->audio->get_interrupted()) interrupt = 1;
280         }
281
282 if(debug) printf("VirtualAConsole::process_buffer %d\n", __LINE__);
283
284
285
286
287
288         return result;
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315 int VirtualAConsole::init_rendering(int duplicate)
316 {
317         return 0;
318 }
319
320
321 int VirtualAConsole::send_last_output_buffer()
322 {
323         renderengine->audio->set_last_buffer();
324         return 0;
325 }
326