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