4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "audiodevice.h"
25 #include "bcsignals.h"
27 #include "condition.h"
29 #include "edlsession.h"
32 #include "filethread.h"
34 #include "meterpanel.h"
37 #include "mwindowgui.h"
38 #include "preferences.h"
40 #include "recordaudio.h"
41 #include "recordconfig.h"
42 #include "recordgui.h"
43 #include "recordmonitor.h"
44 #include "renderengine.h"
48 RecordAudio::RecordAudio(MWindow *mwindow, Record *record)
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");
60 RecordAudio::~RecordAudio()
66 void RecordAudio::reset_parameters()
75 fragment_position = 0;
78 write_buffer_samples = 0;
80 pause_record_lock->reset();
81 record_paused_lock->reset();
82 trigger_lock->reset();
86 void RecordAudio::arm_recording()
92 void RecordAudio::start_recording()
94 trigger_lock->unlock();
97 void RecordAudio::set_monitoring(int mode)
100 record->adevice->set_monitoring(mode);
103 int RecordAudio::stop_recording()
106 if( record->adevice )
107 record->adevice->interrupt_crash();
112 void RecordAudio::delete_buffer()
115 for( int i=0; i<buffer_channels; ++i )
122 fragment_position = 0;
125 void RecordAudio::set_write_buffer_samples(int samples)
127 write_buffer_samples = samples;
130 Samples **RecordAudio::get_buffer()
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;
137 channels = record->file->asset->channels;
138 result = record->file->get_audio_buffer();
140 record->file_lock->unlock();
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 )
146 int record_channels = record->default_asset->channels;
147 if( !buffer || buffer_channels != record_channels ) {
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);
157 for( ; i<record_channels; ++i )
158 new_buffer[i] = buffer[i];
159 while( i < buffer_channels ) // fewer channels
164 buffer_channels = record_channels;
165 fragment_samples = new_fragment_samples;
166 buffer_samples = new_fragment_samples;
168 set_write_buffer_samples(0);
169 channels = record->default_asset->channels;
176 void RecordAudio::config_update()
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();
192 void RecordAudio::run()
197 trigger_lock->lock("RecordAudio::run");
199 while( !done && !write_result ) {
200 if( recording_paused ) {
204 pause_record_lock->unlock();
205 record_paused_lock->lock();
206 set_monitoring(record->monitor_audio);
209 AudioDevice *adevice = record->adevice;
211 input = get_buffer();
212 if( !input || !channels ) {
213 printf("RecordAudio::run: no input/channels\n");
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);
222 if( adevice->config_updated() ) {
226 record->update_position();
227 set_monitoring(record->monitor_audio);
228 record->record_monitor->redraw();
233 int samplerate = record->default_asset->sample_rate;
234 int delay = samplerate ? (1000 * fragment_samples) / samplerate : 250;
235 if( delay > 250 ) delay = 250;
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();
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();
256 flush_buffer(); // write last buffer
260 int RecordAudio::flush_buffer()
262 record->file_lock->lock();
263 if( record->writing_file ) {
264 record->written_samples += fragment_position;
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;
271 record->file_lock->unlock();
273 fragment_position = 0;
277 int RecordAudio::write_buffer(int samples)
280 fragment_position += samples;
281 if( fragment_position >= write_buffer_samples )
282 result = flush_buffer();
287 void RecordAudio::pause_recording()
289 recording_paused = 1;
290 record->adevice->interrupt_recording();
291 pause_record_lock->lock();
294 void RecordAudio::resume_recording()
296 recording_paused = 0;
297 record->adevice->resume_recording();
298 record_paused_lock->unlock();