prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / arender.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2009 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 "amodule.h"
23 #include "arender.h"
24 #include "atrack.h"
25 #include "audiodevice.h"
26 #include "auto.h"
27 #include "autos.h"
28 #include "bcsignals.h"
29 #include "cache.h"
30 #include "condition.h"
31 #include "edit.h"
32 #include "edl.h"
33 #include "edlsession.h"
34 #include "format.inc"
35 #include "levelwindow.h"
36 #include "mainsession.h"
37 #include "playabletracks.h"
38 #include "playbackengine.h"
39 #include "preferences.h"
40 #include "renderengine.h"
41 #include "samples.h"
42 #include "tracks.h"
43 #include "transportque.h"
44 #include "virtualaconsole.h"
45 #include "virtualconsole.h"
46 #include "virtualnode.h"
47
48 ARender::ARender(RenderEngine *renderengine)
49  : CommonRender(renderengine)
50 {
51 // Clear output buffers
52         for(int i = 0; i < MAXCHANNELS; i++)
53         {
54                 buffer[i] = 0;
55                 audio_out[i] = 0;
56                 buffer_allocated[i] = 0;
57                 level_history[i] = 0;
58         }
59         level_samples = 0;
60         total_peaks = 0;
61
62         data_type = TRACK_AUDIO;
63 }
64
65 ARender::~ARender()
66 {
67         for(int i = 0; i < MAXCHANNELS; i++)
68         {
69                 if(buffer[i]) delete buffer[i];
70                 if(level_history[i]) delete [] level_history[i];
71         }
72         if(level_samples) delete [] level_samples;
73 }
74
75 void ARender::arm_command()
76 {
77 // Need the meter history now so AModule can allocate its own history
78         calculate_history_size();
79         CommonRender::arm_command();
80         asynchronous = 1;
81         init_meters();
82 }
83
84
85 int ARender::get_total_tracks()
86 {
87         return renderengine->get_edl()->tracks->total_audio_tracks();
88 }
89
90 Module* ARender::new_module(Track *track)
91 {
92         return new AModule(renderengine, this, 0, track);
93 }
94
95 int ARender::calculate_history_size()
96 {
97         if(total_peaks > 0)
98                 return total_peaks;
99         else
100         {
101                 meter_render_fragment = renderengine->fragment_len;
102 // This number and the timer in tracking.C determine the rate
103                 while(meter_render_fragment > 
104                         renderengine->get_edl()->session->sample_rate / TRACKING_RATE) 
105                         meter_render_fragment /= 2;
106                 total_peaks = 16 * 
107                         renderengine->fragment_len / 
108                         meter_render_fragment;
109                 return total_peaks;
110         }
111 }
112
113 int ARender::init_meters()
114 {
115 // not providing enough peaks results in peaks that are ahead of the sound
116         if(level_samples) delete [] level_samples;
117         calculate_history_size();
118         level_samples = new int64_t[total_peaks];
119
120         for(int i = 0; i < MAXCHANNELS;i++)
121         {
122                 current_level[i] = 0;
123                 if(buffer[i] && !level_history[i]) 
124                         level_history[i] = new double[total_peaks];
125         }
126
127         for(int i = 0; i < total_peaks; i++)
128         {
129                 level_samples[i] = -1;
130         }
131         
132         for(int j = 0; j < MAXCHANNELS; j++)
133         {
134                 if(buffer[j])
135                         for(int i = 0; i < total_peaks; i++)
136                                 level_history[j][i] = 0;
137         }
138         return 0;
139 }
140
141 void ARender::allocate_buffers(int samples)
142 {
143         for(int i = 0; i < MAXCHANNELS; i++)
144         {
145 // Reset the output buffers in case speed changed
146                 if(buffer_allocated[i] < samples)
147                 {
148                         delete buffer[i];
149                         buffer[i] = 0;
150                 }
151
152                 if(i < renderengine->get_edl()->session->audio_channels)
153                 {
154                         buffer[i] = new Samples(samples);
155                         buffer_allocated[i] = samples;
156                         audio_out[i] = buffer[i];
157                 }
158         }
159 }
160
161 void ARender::init_output_buffers()
162 {
163         allocate_buffers(renderengine->adjusted_fragment_len);
164 }
165
166
167 VirtualConsole* ARender::new_vconsole_object() 
168
169         return new VirtualAConsole(renderengine, this);
170 }
171
172 int64_t ARender::tounits(double position, int round)
173 {
174         if(round)
175                 return Units::round(position * renderengine->get_edl()->session->sample_rate);
176         else
177                 return (int64_t)(position * renderengine->get_edl()->session->sample_rate);
178 }
179
180 double ARender::fromunits(int64_t position)
181 {
182         return (double)position / renderengine->get_edl()->session->sample_rate;
183 }
184
185
186 int ARender::process_buffer(Samples **buffer_out, 
187         int64_t input_len,
188         int64_t input_position)
189 {
190         int result = 0;
191
192         int64_t fragment_position = 0;
193         int64_t fragment_len = input_len;
194         int reconfigure = 0;
195         current_position = input_position;
196
197 // Process in fragments
198         int start_offset = buffer_out[0]->get_offset();
199         while(fragment_position < input_len)
200         {
201 // Set pointers for destination data
202                 for(int i = 0; i < MAXCHANNELS; i++)
203                 {
204                         if(buffer_out[i])
205                         {
206                                 this->audio_out[i] = buffer_out[i];
207                                 this->audio_out[i]->set_offset(start_offset + fragment_position);
208                         }
209                         else
210                                 this->audio_out[i] = 0;
211                 }
212
213                 fragment_len = input_len;
214                 if(fragment_position + fragment_len > input_len)
215                         fragment_len = input_len - fragment_position;
216
217                 reconfigure = vconsole->test_reconfigure(input_position, 
218                         fragment_len);
219
220 //printf("ARender::process_buffer 1 " _LD " %d\n", input_position, reconfigure);
221
222                 if(reconfigure) restart_playback();
223
224                 result = process_buffer(fragment_len, input_position);
225
226                 fragment_position += fragment_len;
227                 input_position += fragment_len;
228                 current_position = input_position;
229         }
230
231 // Reset offsets
232         for(int i = 0; i < MAXCHANNELS; i++)
233         {
234                 if(buffer_out[i]) buffer_out[i]->set_offset(start_offset);
235         }
236
237
238
239         return result;
240 }
241
242
243 int ARender::process_buffer(int64_t input_len, int64_t input_position)
244 {
245         int result = ((VirtualAConsole*)vconsole)->process_buffer(input_len,
246                 input_position);
247         return result;
248 }
249
250 int ARender::get_history_number(int64_t *table, int64_t position)
251 {
252 // Get the entry closest to position
253         int result = 0;
254         int64_t min_difference = 0x7fffffff;
255         for(int i = 0; i < total_peaks; i++)
256         {
257
258 //printf("" _LD " ", table[i]);
259                 if(labs(table[i] - position) < min_difference)
260                 {
261                         min_difference = labs(table[i] - position);
262                         result = i;
263                 }
264         }
265 //printf("\n");
266 //printf("ARender::get_history_number " _LD " %d\n", position, result);
267         return result;
268 }
269
270 void ARender::send_last_buffer()
271 {
272         if( renderengine->audio )
273                 renderengine->audio->set_last_buffer();
274 }
275
276 int ARender::stop_audio(int wait)
277 {
278         if( renderengine->audio )
279                 renderengine->audio->stop_audio(wait);
280         return 0;
281 }
282
283 void ARender::interrupt_playback()
284 {
285 //printf("ARender::interrupt_playback\n");
286         interrupt = 1;
287         if( renderengine->audio )
288                 renderengine->audio->interrupt_playback();
289 }
290
291 void ARender::run()
292 {
293         int64_t current_input_length;
294         int reconfigure = 0;
295 const int debug = 0;
296
297         first_buffer = 1;
298
299         start_lock->unlock();
300 if(debug) printf("ARender::run %d %d\n", __LINE__, Thread::calculate_realtime());
301
302         while(!done && !interrupt)
303         {
304                 float speed = renderengine->command->get_speed();
305                 current_input_length = (int64_t)(renderengine->fragment_len * speed +0.5) ;
306
307 if(debug) printf("ARender::run %d " _LD " " _LD "\n", __LINE__, current_position, current_input_length);
308                 get_boundaries(current_input_length);
309
310 if(debug) printf("ARender::run %d " _LD " " _LD "\n", __LINE__, current_position, current_input_length);
311                 if(current_input_length)
312                 {
313                         reconfigure = vconsole->test_reconfigure(current_position, 
314                                 current_input_length);
315                         if(reconfigure) restart_playback();
316                 }
317 if(debug) printf("ARender::run %d " _LD " " _LD "\n", __LINE__, current_position, current_input_length);
318
319
320 // Update tracking if no video is playing.
321                 if(renderengine->command->realtime && 
322                         renderengine->playback_engine &&
323                         !renderengine->do_video)
324                 {
325                         double position = (double)renderengine->audio->current_position() / 
326                                 renderengine->get_edl()->session->sample_rate * speed;
327
328                         if(renderengine->command->get_direction() == PLAY_FORWARD) 
329                                 position += renderengine->command->playbackstart;
330                         else
331                                 position = renderengine->command->playbackstart - position;
332
333 // This number is not compensated for looping.  It's compensated in 
334 // PlaybackEngine::get_tracking_position when interpolation also happens.
335                         renderengine->playback_engine->update_tracking(position);
336                 }
337
338
339 if(debug) printf("ARender::run %d " _LD "\n", __LINE__, current_input_length);
340
341
342
343                 process_buffer(current_input_length, current_position);
344 if(debug) printf("ARender::run %d\n", __LINE__);
345
346
347                 advance_position(current_input_length);
348 if(debug) printf("ARender::run %d\n", __LINE__);
349
350
351                 if(vconsole->interrupt) interrupt = 1;
352         }
353
354 if(debug) printf("ARender::run %d\n", __LINE__);
355         if(!interrupt) send_last_buffer();
356         if(renderengine->command->realtime)
357                 stop_audio(interrupt ? 0 : 1);
358         vconsole->stop_rendering(0);
359         stop_plugins();
360 }
361
362
363 int ARender::get_next_peak(int current_peak)
364 {
365         current_peak++;
366         if(current_peak >= total_peaks) current_peak = 0;
367         return current_peak;
368 }
369
370
371
372
373
374
375
376
377