r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / recordaudio.C
blobd4e39125a0ab05f0c8b11e4ef7b4e49c2f9480d4
1 #include "assets.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 "meterpanel.h"
11 #include "mwindow.h"
12 #include "mwindowgui.h"
13 #include "preferences.h"
14 #include "record.h"
15 #include "recordaudio.h"
16 #include "recordgui.h"
17 #include "recordengine.h"
18 #include "recordmonitor.h"
19 #include "recordthread.h"
20 #include "renderengine.h"
23 #include <libintl.h>
24 #define _(String) gettext(String)
25 #define gettext_noop(String) String
26 #define N_(String) gettext_noop (String)
29 RecordAudio::RecordAudio(MWindow *mwindow,
30                                 Record *record, 
31                                 RecordThread *record_thread)
32  : Thread()
34         this->mwindow = mwindow;
35         this->record = record;
36         this->record_thread = record_thread; 
37         this->gui = record->record_gui;
38         fragment_position = 0;
41 RecordAudio::~RecordAudio()
45 void RecordAudio::reset_parameters()
47         fragment_position = 0;
48         batch_done = 0;
52 int RecordAudio::arm_recording()
54         reset_parameters();
55 // Fudge buffer sizes
56         record->get_audio_write_length(buffer_size, fragment_size);
57         record_channels = record->default_asset->channels;
59         if(mwindow->edl->session->real_time_record) Thread::set_realtime();
61         timer.update();
62         set_synchronous(1);
63         trigger_lock.lock();
64         Thread::start();
67 void RecordAudio::start_recording()
69         trigger_lock.unlock();
72 int RecordAudio::stop_recording()
74 // Device won't exist if interrupting a cron job
75         if(record->adevice)
76         {
77 //printf("RecordAudio::stop_recording 1\n");
78                 record->adevice->interrupt_crash();
79 //printf("RecordAudio::stop_recording 2\n");
80                 //Thread::join();
81         }
82         return 0;
85 void RecordAudio::run()
87         int channel, buffer;
88         Timer delayer;
89         int total_clipped_samples = 0;
90         int clipped_sample = 0;
91         write_result = 0;
92         grab_result = 0;
94         over = new int[record_channels];
95         max = new double[record_channels];
97 // thread out I/O
98         if(!record_thread->monitor)
99         {
100 // Get a buffer from the file to record into.
101                 input = record->file->get_audio_buffer();
102         }
103         else
104         {
105 // Make up a fake buffer.
106                 input = new double*[record_channels];
108                 for(int i = 0; i < record_channels; i++)
109                 {
110                         input[i] = new double[buffer_size];
111                 }
112         }
114 //printf("RecordAudio::run 1\n");
115         gui->total_clipped_samples = 0;
116         gui->update_clipped_samples(0);
119 // Wait for trigger
120         trigger_lock.lock();
121         trigger_lock.unlock();
124 //printf("RecordAudio::run 2\n");
125         while(!batch_done && 
126                 !write_result)
127         {
128 // Handle data from the audio device.
129 //printf("RecordAudio::run 3\n");
130                         if(!record_thread->monitor)
131                         {
132 // Read into file's buffer for recording.
133 // device needs to write buffer starting at fragment position
134 //printf("RecordAudio::run 2.1\n");
135                                 grab_result = record->adevice->read_buffer(input, 
136                                         fragment_size, 
137                                         record_channels, 
138                                         over, 
139                                         max, 
140                                         fragment_position);
141 //printf("RecordAudio::run 2.2\n");
142                         }
143                         else
144                         {
145 // Read into monitor buffer for monitoring.
146 //printf("RecordAudio::run 1\n");
147                                 grab_result = record->adevice->read_buffer(input, fragment_size, record_channels, over, max, 0);
148 //printf("RecordAudio::run 2 %d\n", grab_result);
149                         }
150 //printf("RecordAudio::run 3 %d\n", fragment_size);
152 // Update timer for synchronization
153                         timer_lock.lock();
154                         
155                         if(!record_thread->monitor)
156                         {
157                                 record->get_current_batch()->current_sample += fragment_size;
158                                 record->get_current_batch()->total_samples = 
159                                         MAX(record->get_current_batch()->current_sample, record->get_current_batch()->total_samples);
160                         }
162                         record->get_current_batch()->session_samples += fragment_size;
163                         timer.update();
164                         timer_lock.unlock();
166 //printf("RecordAudio::run 2\n");
167 // Get clipping status
168                         if(record->monitor_audio || !record_thread->monitor)
169                         {
170                                 clipped_sample = 0;
171                                 for(channel = 0; channel < record_channels; channel++)
172                                 {
173                                         if(over[channel]) clipped_sample = 1;
174                                 }
175                         }
177 // Update meters if monitoring
178 //printf("RecordAudio::run 2 %d %d %d %d\n", record->monitor_audio, record_thread->batch_done(), record_thread->loop_done(), grab_result);
179                         if(record->monitor_audio && 
180                                 !batch_done && 
181                                 !grab_result)
182                         {
183                                 record->record_monitor->window->lock_window();
184                                 for(channel = 0; channel < record_channels; channel++)
185                                 {
186                                         record->record_monitor->window->meters->meters.values[channel]->update(max[channel], over[channel]);
187                                 }
188                                 record->record_monitor->window->unlock_window();
189                         }
192 //printf("RecordAudio::run 2\n");
193 // Write file if writing
194                         if(!record_thread->monitor)
195                         {
196                                 fragment_position += fragment_size;
198                                 if(fragment_position >= buffer_size)
199                                 {
200                                         write_buffer(0);
201                                 }
204 //printf("RecordAudio::run 2 %f\n", record->current_display_position());
205                                 if(!record->default_asset->video_data) 
206                                         gui->update_position(record->current_display_position(),
207                                                 record->current_display_length());
208                                 if(clipped_sample) 
209                                         gui->update_clipped_samples(++total_clipped_samples);
211                                 if(!record_thread->monitor && 
212                                         !batch_done && 
213                                         !write_result && 
214                                         !record->default_asset->video_data)
215                                 {
216 // handle different recording modes
217                                         switch(record->get_current_batch()->record_mode)
218                                         {
219                                                 case RECORD_TIMED:
220                                                         if(record->current_display_position() > *record->current_duration())
221                                                                 batch_done = 1;
222                                                         break;
223                                                 case RECORD_LOOP:
224                                                         if(record->current_display_position() > *record->current_duration())
225                                                                 batch_done = 1;
226                                                         break;
227                                                 case RECORD_SCENETOSCENE:
228                                                         break;
229                                         }
230                                 }
231                         }
232 //printf("RecordAudio::run 4 %d %d\n", batch_done, write_result);
233         }
235 //printf("RecordAudio::run 4\n");
236         if(write_result && !record->default_asset->video_data)
237         {
238                 ErrorBox error_box(PROGRAM_NAME ": Error",
239                         mwindow->gui->get_abs_cursor_x(),
240                         mwindow->gui->get_abs_cursor_y());
241                 error_box.create_objects(_("No space left on disk."));
242                 error_box.run_window();
243                 batch_done = 1;
244         }
245 //printf("RecordAudio::run 10\n");
247         if(!record_thread->monitor)
248         {
249 // write last buffer
250                 write_buffer(1);
251         }
252         else
253         {
254 // Delete the fake buffer.
255                 for(int i = 0; i < record_channels; i++)
256                 {
257                         record->record_monitor->window->meters->meters.values[i]->reset();
258                         delete [] input[i];
259                 }
260                 delete [] input;
261                 input = 0;
262         }
263 //printf("RecordAudio::run 11\n");
265 // reset meter
266         gui->lock_window();
267         for(channel = 0; channel < record_channels; channel++)
268         {
269                 record->record_monitor->window->meters->meters.values[channel]->reset();
270         }
271 //printf("RecordAudio::run 12\n");
273         gui->unlock_window();
274         delete [] max;
275         delete [] over;
276 //printf("RecordAudio::run 5\n");
279 void RecordAudio::write_buffer(int skip_new)
281 // block until buffer is ready for writing
282         write_result = record->file->write_audio_buffer(fragment_position);
283 // Defeat errors if video
284         if(record->default_asset->video_data) write_result = 0;
285         fragment_position = 0;
286         if(!skip_new && !write_result) input = record->file->get_audio_buffer();
289 int64_t RecordAudio::sync_position()
291         int64_t result;
292         if(!batch_done)
293         {
294 //printf("RecordAudio::sync_position 1\n");
295                 timer_lock.lock();
296                 if(!mwindow->edl->session->record_software_position)
297                 {
298 //printf("RecordAudio::sync_position 1\n");
299                         result = record->adevice->current_position();
300                 }
301                 else
302                 {
303 //printf("RecordAudio::sync_position 1 %d\n", record->get_current_batch()->session_samples);
304                         result = record->get_current_batch()->session_samples +
305                                 timer.get_scaled_difference(record->default_asset->sample_rate);
306                 }
307                 timer_lock.unlock();
308 //printf("RecordAudio::sync_position 2\n");
309                 return result;
310         }
311         else
312         return -1;