r136: This commit was manufactured by cvs2svn to create tag 'hv_1_1_8'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / recordaudio.C
blob41e2dec8d26420f87cbb0cd4865a294022e26dab
1 #include "asset.h"
2 #include "audiodevice.h"
3 #include "batch.h"
4 #include "clip.h"
5 #include "edl.h"
6 #include "edlsession.h"
7 #include "errorbox.h"
8 #include "file.h"
9 #include "filethread.h"
10 #include "language.h"
11 #include "meterpanel.h"
12 #include "mwindow.h"
13 #include "mwindowgui.h"
14 #include "preferences.h"
15 #include "record.h"
16 #include "recordaudio.h"
17 #include "recordgui.h"
18 #include "recordengine.h"
19 #include "recordmonitor.h"
20 #include "recordthread.h"
21 #include "renderengine.h"
25 RecordAudio::RecordAudio(MWindow *mwindow,
26                                 Record *record, 
27                                 RecordThread *record_thread)
28  : Thread()
30         this->mwindow = mwindow;
31         this->record = record;
32         this->record_thread = record_thread; 
33         this->gui = record->record_gui;
34         fragment_position = 0;
37 RecordAudio::~RecordAudio()
41 void RecordAudio::reset_parameters()
43         fragment_position = 0;
44         batch_done = 0;
48 int RecordAudio::arm_recording()
50         reset_parameters();
51 // Fudge buffer sizes
52         record->get_audio_write_length(buffer_size, fragment_size);
53         record_channels = record->default_asset->channels;
55         if(mwindow->edl->session->real_time_record) Thread::set_realtime();
57         timer.update();
58         set_synchronous(1);
59         trigger_lock.lock();
60         Thread::start();
63 void RecordAudio::start_recording()
65         trigger_lock.unlock();
68 int RecordAudio::stop_recording()
70 // Device won't exist if interrupting a cron job
71         if(record->adevice)
72         {
73 //printf("RecordAudio::stop_recording 1\n");
74                 record->adevice->interrupt_crash();
75 //printf("RecordAudio::stop_recording 2\n");
76                 //Thread::join();
77         }
78         return 0;
81 void RecordAudio::run()
83         int channel, buffer;
84         Timer delayer;
85         int total_clipped_samples = 0;
86         int clipped_sample = 0;
87         write_result = 0;
88         grab_result = 0;
90         over = new int[record_channels];
91         max = new double[record_channels];
93 // thread out I/O
94         if(!record_thread->monitor)
95         {
96 // Get a buffer from the file to record into.
97                 input = record->file->get_audio_buffer();
98         }
99         else
100         {
101 // Make up a fake buffer.
102                 input = new double*[record_channels];
104                 for(int i = 0; i < record_channels; i++)
105                 {
106                         input[i] = new double[buffer_size];
107                 }
108         }
110 //printf("RecordAudio::run 1\n");
111         gui->total_clipped_samples = 0;
112         gui->update_clipped_samples(0);
115 // Wait for trigger
116         trigger_lock.lock();
117         trigger_lock.unlock();
120 //printf("RecordAudio::run 2\n");
121         while(!batch_done && 
122                 !write_result)
123         {
124 // Handle data from the audio device.
125 //printf("RecordAudio::run 3\n");
126                         if(!record_thread->monitor)
127                         {
128 // Read into file's buffer for recording.
129 // device needs to write buffer starting at fragment position
130 //printf("RecordAudio::run 2.1\n");
131                                 grab_result = record->adevice->read_buffer(input, 
132                                         fragment_size, 
133                                         record_channels, 
134                                         over, 
135                                         max, 
136                                         fragment_position);
137 //printf("RecordAudio::run 2.2\n");
138                         }
139                         else
140                         {
141 // Read into monitor buffer for monitoring.
142 //printf("RecordAudio::run 1\n");
143                                 grab_result = record->adevice->read_buffer(input, fragment_size, record_channels, over, max, 0);
144 //printf("RecordAudio::run 2 %d\n", grab_result);
145                         }
146 //printf("RecordAudio::run 3 %d\n", fragment_size);
148 // Update timer for synchronization
149                         timer_lock.lock();
150                         
151                         if(!record_thread->monitor)
152                         {
153                                 record->get_current_batch()->current_sample += fragment_size;
154                                 record->get_current_batch()->total_samples = 
155                                         MAX(record->get_current_batch()->current_sample, record->get_current_batch()->total_samples);
156                         }
158                         record->get_current_batch()->session_samples += fragment_size;
159                         timer.update();
160                         timer_lock.unlock();
162 //printf("RecordAudio::run 2\n");
163 // Get clipping status
164                         if(record->monitor_audio || !record_thread->monitor)
165                         {
166                                 clipped_sample = 0;
167                                 for(channel = 0; channel < record_channels; channel++)
168                                 {
169                                         if(over[channel]) clipped_sample = 1;
170                                 }
171                         }
173 // Update meters if monitoring
174 //printf("RecordAudio::run 2 %d %d %d %d\n", record->monitor_audio, record_thread->batch_done(), record_thread->loop_done(), grab_result);
175                         if(record->monitor_audio && 
176                                 !batch_done && 
177                                 !grab_result)
178                         {
179                                 record->record_monitor->window->lock_window();
180                                 for(channel = 0; channel < record_channels; channel++)
181                                 {
182                                         record->record_monitor->window->meters->meters.values[channel]->update(max[channel], over[channel]);
183                                 }
184                                 record->record_monitor->window->unlock_window();
185                         }
188 //printf("RecordAudio::run 2\n");
189 // Write file if writing
190                         if(!record_thread->monitor)
191                         {
192                                 fragment_position += fragment_size;
194                                 if(fragment_position >= buffer_size)
195                                 {
196                                         write_buffer(0);
197                                 }
200 //printf("RecordAudio::run 2 %f\n", record->current_display_position());
201                                 if(!record->default_asset->video_data) 
202                                         gui->update_position(record->current_display_position(),
203                                                 record->current_display_length());
204                                 if(clipped_sample) 
205                                         gui->update_clipped_samples(++total_clipped_samples);
207                                 if(!record_thread->monitor && 
208                                         !batch_done && 
209                                         !write_result && 
210                                         !record->default_asset->video_data)
211                                 {
212 // handle different recording modes
213                                         switch(record->get_current_batch()->record_mode)
214                                         {
215                                                 case RECORD_TIMED:
216                                                         if(record->current_display_position() > *record->current_duration())
217                                                                 batch_done = 1;
218                                                         break;
219                                                 case RECORD_LOOP:
220                                                         if(record->current_display_position() > *record->current_duration())
221                                                                 batch_done = 1;
222                                                         break;
223                                                 case RECORD_SCENETOSCENE:
224                                                         break;
225                                         }
226                                 }
227                         }
228 //printf("RecordAudio::run 4 %d %d\n", batch_done, write_result);
229         }
231 //printf("RecordAudio::run 4\n");
232         if(write_result && !record->default_asset->video_data)
233         {
234                 ErrorBox error_box(PROGRAM_NAME ": Error",
235                         mwindow->gui->get_abs_cursor_x(),
236                         mwindow->gui->get_abs_cursor_y());
237                 error_box.create_objects(_("No space left on disk."));
238                 error_box.run_window();
239                 batch_done = 1;
240         }
241 //printf("RecordAudio::run 10\n");
243         if(!record_thread->monitor)
244         {
245 // write last buffer
246                 write_buffer(1);
247         }
248         else
249         {
250 // Delete the fake buffer.
251                 for(int i = 0; i < record_channels; i++)
252                 {
253                         record->record_monitor->window->meters->meters.values[i]->reset();
254                         delete [] input[i];
255                 }
256                 delete [] input;
257                 input = 0;
258         }
259 //printf("RecordAudio::run 11\n");
261 // reset meter
262         gui->lock_window();
263         for(channel = 0; channel < record_channels; channel++)
264         {
265                 record->record_monitor->window->meters->meters.values[channel]->reset();
266         }
267 //printf("RecordAudio::run 12\n");
269         gui->unlock_window();
270         delete [] max;
271         delete [] over;
272 //printf("RecordAudio::run 5\n");
275 void RecordAudio::write_buffer(int skip_new)
277 // block until buffer is ready for writing
278         write_result = record->file->write_audio_buffer(fragment_position);
279 // Defeat errors if video
280         if(record->default_asset->video_data) write_result = 0;
281         fragment_position = 0;
282         if(!skip_new && !write_result) input = record->file->get_audio_buffer();
285 int64_t RecordAudio::sync_position()
287         int64_t result;
288         if(!batch_done)
289         {
290 //printf("RecordAudio::sync_position 1\n");
291                 timer_lock.lock();
292                 if(!mwindow->edl->session->record_software_position)
293                 {
294 //printf("RecordAudio::sync_position 1\n");
295                         result = record->adevice->current_position();
296                 }
297                 else
298                 {
299 //printf("RecordAudio::sync_position 1 %d\n", record->get_current_batch()->session_samples);
300                         result = record->get_current_batch()->session_samples +
301                                 timer.get_scaled_difference(record->default_asset->sample_rate);
302                 }
303                 timer_lock.unlock();
304 //printf("RecordAudio::sync_position 2\n");
305                 return result;
306         }
307         else
308         return -1;