add bluray dv, misc fixes
[goodguy/history.git] / cinelerra-5.1 / cinelerra / recordaudio.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 "asset.h"
23 #include "audiodevice.h"
24 #include "batch.h"
25 #include "bcsignals.h"
26 #include "clip.h"
27 #include "condition.h"
28 #include "edl.h"
29 #include "edlsession.h"
30 #include "errorbox.h"
31 #include "file.h"
32 #include "filethread.h"
33 #include "language.h"
34 #include "meterpanel.h"
35 #include "mutex.h"
36 #include "mwindow.h"
37 #include "mwindowgui.h"
38 #include "preferences.h"
39 #include "record.h"
40 #include "recordaudio.h"
41 #include "recordconfig.h"
42 #include "recordgui.h"
43 #include "recordmonitor.h"
44 #include "renderengine.h"
45 #include "samples.h"
46
47
48 RecordAudio::RecordAudio(MWindow *mwindow, Record *record)
49  : Thread(1, 0, 0)
50 {
51         this->mwindow = mwindow;
52         this->record = record;
53         this->gui = record->record_gui;
54         trigger_lock = new Condition(0, "RecordAudio::trigger_lock");
55         pause_record_lock = new Condition(0, "RecordAudio::pause_record_lock");
56         record_paused_lock = new Condition(0, "RecordAudio::record_paused_lock");
57         reset_parameters();
58 }
59
60 RecordAudio::~RecordAudio()
61 {
62         delete_buffer();
63         delete trigger_lock;
64 }
65
66 void RecordAudio::reset_parameters()
67 {
68         buffer_channels = 0;
69         write_result = 0;
70         grab_result = 0;
71         buffer = 0;
72         input = 0;
73         channels = 0;
74         fragment_samples = 0;
75         fragment_position = 0;
76         buffer_samples = 0;
77         writing_file = 0;
78         write_buffer_samples = 0;
79         recording_paused = 0;
80         pause_record_lock->reset();
81         record_paused_lock->reset();
82         trigger_lock->reset();
83 }
84
85
86 void RecordAudio::arm_recording()
87 {
88         reset_parameters();
89         Thread::start();
90 }
91
92 void RecordAudio::start_recording()
93 {
94         trigger_lock->unlock();
95 }
96
97 void RecordAudio::set_monitoring(int mode)
98 {
99         if( record->adevice )
100                 record->adevice->set_monitoring(mode);
101 }
102
103 int RecordAudio::stop_recording()
104 {
105         done = 1;
106         if( record->adevice )
107                 record->adevice->interrupt_crash();
108         Thread::join();
109         return 0;
110 }
111
112 void RecordAudio::delete_buffer()
113 {
114         if( buffer ) {
115                 for( int i=0; i<buffer_channels; ++i )
116                         delete buffer[i];
117                 delete [] buffer;
118                 buffer = 0;
119                 buffer_channels = 0;
120         }
121         input = 0;
122         fragment_position = 0;
123 }
124
125 void RecordAudio::set_write_buffer_samples(int samples)
126 {
127         write_buffer_samples = samples;
128 }
129
130 Samples **RecordAudio::get_buffer()
131 {
132         Samples **result = 0;
133         fragment_position = 0;
134         record->file_lock->lock();
135         writing_file = record->writing_file > 0 && record->do_audio ? 1 : 0;
136         if( writing_file ) {
137                 channels = record->file->asset->channels;
138                 result = record->file->get_audio_buffer();
139         }
140         record->file_lock->unlock();
141         if( !result ) {
142                 // when not writing, buffer is only one fragment
143                 int new_fragment_samples = record->get_fragment_samples();
144                 if( new_fragment_samples != buffer_samples )
145                         delete_buffer();
146                 int record_channels = record->default_asset->channels;
147                 if( !buffer || buffer_channels != record_channels ) {
148                         int i = 0;
149                         Samples **new_buffer = new Samples *[record_channels];
150                         if( buffer_channels < record_channels ) {
151                                 for( ; i<buffer_channels; ++i )
152                                         new_buffer[i] = buffer[i];
153                                 while( i < record_channels ) // more channels
154                                         new_buffer[i++] = new Samples(new_fragment_samples);
155                         }
156                         else {
157                                 for( ; i<record_channels; ++i )
158                                         new_buffer[i] = buffer[i];
159                                 while( i < buffer_channels ) // fewer channels
160                                         delete buffer[i++];
161                         }
162                         delete buffer;
163                         buffer = new_buffer;
164                         buffer_channels = record_channels;
165                         fragment_samples = new_fragment_samples;
166                         buffer_samples = new_fragment_samples;
167                 }
168                 set_write_buffer_samples(0);
169                 channels = record->default_asset->channels;
170                 result = buffer;
171         }
172         return result;
173 }
174
175
176 void RecordAudio::config_update()
177 {
178         AudioDevice *adevice = record->adevice;
179         adevice->stop_audio(0);
180         adevice->config_update();
181         int channels = adevice->get_ichannels();
182         int sample_rate = adevice->get_irate();
183         int bits = adevice->get_ibits();
184         Asset *rf_asset = SESSION->recording_format;
185         Asset *df_asset = record->default_asset;
186         rf_asset->channels    = df_asset->channels    = channels;
187         rf_asset->sample_rate = df_asset->sample_rate = sample_rate;
188         rf_asset->bits        = df_asset->bits        = bits;
189         adevice->start_recording();
190 }
191
192 void RecordAudio::run()
193 {
194         gui->reset_audio();
195         done = 0;
196
197         trigger_lock->lock("RecordAudio::run");
198
199         while( !done && !write_result ) {
200                 if( recording_paused ) {
201                         set_monitoring(0);
202                         flush_buffer();
203                         delete_buffer();
204                         pause_record_lock->unlock();
205                         record_paused_lock->lock();
206                         set_monitoring(record->monitor_audio);
207                 }
208                 if( done ) break;
209                 AudioDevice *adevice = record->adevice;
210                 if( !input )
211                         input = get_buffer();
212                 if( !input || !channels ) {
213                         printf("RecordAudio::run: no input/channels\n");
214                         Timer::delay(250);
215                         continue;
216                 }
217                 int over[channels];  double max[channels];
218                 grab_result = !input ? 1 :
219                         adevice->read_buffer(input, channels,
220                                 fragment_samples, over, max, fragment_position);
221                 if( done ) break;
222                 if( adevice->config_updated() ) {
223                         flush_buffer();
224                         delete_buffer();
225                         config_update();
226                         record->update_position();
227                         set_monitoring(record->monitor_audio);
228                         record->record_monitor->redraw();
229                         gui->reset_audio();
230                         continue;
231                 }
232                 if( grab_result ) {
233                         int samplerate = record->default_asset->sample_rate;
234                         int delay = samplerate ? (1000 * fragment_samples) / samplerate : 250;
235                         if( delay > 250 ) delay = 250;
236                         Timer::delay(delay);
237                         continue;
238                 }
239                 write_buffer(fragment_samples);
240                 record->current_sample += fragment_samples;
241                 record->total_samples += fragment_samples;
242                 if( !record->writing_file || !record->is_behind() )
243                         gui->update_audio(channels,max,over);
244                 record->check_batch_complete();
245         }
246
247         if( write_result && !record->default_asset->video_data ) {
248                 ErrorBox error_box(_(PROGRAM_NAME ": Error"),
249                         mwindow->gui->get_abs_cursor_x(1),
250                         mwindow->gui->get_abs_cursor_y(1));
251                 error_box.create_objects(_("No space left on disk."));
252                 error_box.run_window();
253                 done = 1;
254         }
255
256         flush_buffer(); // write last buffer
257         delete_buffer();
258 }
259
260 int RecordAudio::flush_buffer()
261 {
262         record->file_lock->lock();
263         if( record->writing_file ) {
264                 record->written_samples += fragment_position;
265                 if( writing_file ) {
266                         write_result = (record->file->write_audio_buffer(fragment_position), 0); // HACK
267                         // defeat audio errors if recording video
268                         if( record->default_asset->video_data ) write_result = 0;
269                 }
270         }
271         record->file_lock->unlock();
272         input = 0;
273         fragment_position = 0;
274         return write_result;
275 }
276
277 int RecordAudio::write_buffer(int samples)
278 {
279         int result = 0;
280         fragment_position += samples;
281         if( fragment_position >= write_buffer_samples )
282                 result = flush_buffer();
283         return result;
284 }
285
286
287 void RecordAudio::pause_recording()
288 {
289         recording_paused = 1;
290         record->adevice->interrupt_recording();
291         pause_record_lock->lock();
292 }
293
294 void RecordAudio::resume_recording()
295 {
296         recording_paused = 0;
297         record->adevice->resume_recording();
298         record_paused_lock->unlock();
299 }
300
301