Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

recordaudio.C

Go to the documentation of this file.
00001 #include "asset.h"
00002 #include "audiodevice.h"
00003 #include "batch.h"
00004 #include "bcsignals.h"
00005 #include "clip.h"
00006 #include "condition.h"
00007 #include "edl.h"
00008 #include "edlsession.h"
00009 #include "errorbox.h"
00010 #include "file.h"
00011 #include "filethread.h"
00012 #include "language.h"
00013 #include "meterpanel.h"
00014 #include "mutex.h"
00015 #include "mwindow.h"
00016 #include "mwindowgui.h"
00017 #include "preferences.h"
00018 #include "record.h"
00019 #include "recordaudio.h"
00020 #include "recordgui.h"
00021 #include "recordengine.h"
00022 #include "recordmonitor.h"
00023 #include "recordthread.h"
00024 #include "renderengine.h"
00025 
00026 
00027 
00028 RecordAudio::RecordAudio(MWindow *mwindow,
00029                                 Record *record, 
00030                                 RecordThread *record_thread)
00031  : Thread(1, 0, 0)
00032 {
00033         this->mwindow = mwindow;
00034         this->record = record;
00035         this->record_thread = record_thread; 
00036         this->gui = record->record_gui;
00037         fragment_position = 0;
00038         timer_lock = new Mutex("RecordAudio::timer_lock");
00039         trigger_lock = new Condition(1, "RecordAudio::trigger_lock");
00040 }
00041 
00042 RecordAudio::~RecordAudio()
00043 {
00044         delete timer_lock;
00045         delete trigger_lock;
00046 }
00047 
00048 void RecordAudio::reset_parameters()
00049 {
00050         fragment_position = 0;
00051         batch_done = 0;
00052 }
00053 
00054 
00055 int RecordAudio::arm_recording()
00056 {
00057         reset_parameters();
00058 // Fudge buffer sizes
00059         record->get_audio_write_length(buffer_size, fragment_size);
00060         record_channels = record->default_asset->channels;
00061 
00062         if(mwindow->edl->session->real_time_record) Thread::set_realtime();
00063 
00064         timer.update();
00065         trigger_lock->lock("RecordAudio::arm_recording");
00066         Thread::start();
00067 }
00068 
00069 void RecordAudio::start_recording()
00070 {
00071         trigger_lock->unlock();
00072 }
00073 
00074 int RecordAudio::stop_recording()
00075 {
00076 // Device won't exist if interrupting a cron job
00077         if(record->adevice)
00078         {
00079                 record->adevice->interrupt_crash();
00080                 //Thread::join();
00081         }
00082         return 0;
00083 }
00084 
00085 void RecordAudio::run()
00086 {
00087         int channel, buffer;
00088         Timer delayer;
00089         int total_clipped_samples = 0;
00090         int clipped_sample = 0;
00091         write_result = 0;
00092         grab_result = 0;
00093 
00094 //printf("RecordAudio::run 1 %d\n", Thread::calculate_realtime());
00095         over = new int[record_channels];
00096         max = new double[record_channels];
00097 
00098 // thread out I/O
00099         if(!record_thread->monitor)
00100         {
00101 // Get a buffer from the file to record into.
00102                 input = record->file->get_audio_buffer();
00103         }
00104         else
00105         {
00106 // Make up a fake buffer.
00107                 input = new double*[record_channels];
00108 
00109                 for(int i = 0; i < record_channels; i++)
00110                 {
00111                         input[i] = new double[buffer_size];
00112                 }
00113         }
00114 
00115 //printf("RecordAudio::run 1\n");
00116         gui->total_clipped_samples = 0;
00117         gui->update_clipped_samples(0);
00118 
00119 
00120 // Wait for trigger
00121         trigger_lock->lock("RecordAudio::run");
00122         trigger_lock->unlock();
00123 
00124 
00125 //printf("RecordAudio::run 2\n");
00126         while(!batch_done && 
00127                 !write_result)
00128         {
00129 // Handle data from the audio device.
00130 //printf("RecordAudio::run 3\n");
00131                         if(!record_thread->monitor)
00132                         {
00133 // Read into file's buffer for recording.
00134 // device needs to write buffer starting at fragment position
00135 //printf("RecordAudio::run 2.1\n");
00136                                 grab_result = record->adevice->read_buffer(input, 
00137                                         fragment_size, 
00138                                         record_channels, 
00139                                         over, 
00140                                         max, 
00141                                         fragment_position);
00142 //printf("RecordAudio::run 2.2\n");
00143                         }
00144                         else
00145                         {
00146 // Read into monitor buffer for monitoring.
00147 //printf("RecordAudio::run 1\n");
00148                                 grab_result = record->adevice->read_buffer(input, 
00149                                         fragment_size, 
00150                                         record_channels, 
00151                                         over, 
00152                                         max, 
00153                                         0);
00154 //printf("RecordAudio::run 2 %d\n", grab_result);
00155                         }
00156 //printf("RecordAudio::run 3 %d %f\n", fragment_size, max);
00157 
00158 // Update timer for synchronization
00159                         timer_lock->lock("RecordAudio::run");
00160                         
00161                         if(!record_thread->monitor)
00162                         {
00163                                 record->get_current_batch()->current_sample += fragment_size;
00164                                 record->get_current_batch()->total_samples = 
00165                                         MAX(record->get_current_batch()->current_sample, record->get_current_batch()->total_samples);
00166                         }
00167 
00168                         record->get_current_batch()->session_samples += fragment_size;
00169                         timer.update();
00170                         timer_lock->unlock();
00171 
00172 //printf("RecordAudio::run 2\n");
00173 // Get clipping status
00174                         if(record->monitor_audio || !record_thread->monitor)
00175                         {
00176                                 clipped_sample = 0;
00177                                 for(channel = 0; channel < record_channels; channel++)
00178                                 {
00179                                         if(over[channel]) clipped_sample = 1;
00180                                 }
00181                         }
00182 
00183 // Update meters if monitoring
00184 //printf("RecordAudio::run 2 %d %d %d %d\n", record->monitor_audio, record_thread->batch_done(), record_thread->loop_done(), grab_result);
00185                         if(record->monitor_audio && 
00186                                 !batch_done && 
00187                                 !grab_result)
00188                         {
00189                                 record->record_monitor->window->lock_window("RecordAudio::run 1");
00190                                 for(channel = 0; channel < record_channels; channel++)
00191                                 {
00192                                         record->record_monitor->window->meters->meters.values[channel]->update(
00193                                                 max[channel], 
00194                                                 over[channel]);
00195                                 }
00196                                 record->record_monitor->window->unlock_window();
00197                         }
00198 
00199 
00200 //printf("RecordAudio::run 2\n");
00201 // Write file if writing
00202                         if(!record_thread->monitor)
00203                         {
00204                                 fragment_position += fragment_size;
00205 
00206                                 if(fragment_position >= buffer_size)
00207                                 {
00208                                         write_buffer(0);
00209                                 }
00210 
00211 
00212 //printf("RecordAudio::run 2 %f\n", record->current_display_position());
00213                                 if(!record->default_asset->video_data) 
00214                                         gui->update_position(record->current_display_position());
00215                                 if(clipped_sample) 
00216                                         gui->update_clipped_samples(++total_clipped_samples);
00217 
00218                                 if(!record_thread->monitor && 
00219                                         !batch_done && 
00220                                         !write_result && 
00221                                         !record->default_asset->video_data)
00222                                 {
00223 // handle different recording modes
00224                                         switch(record->get_current_batch()->record_mode)
00225                                         {
00226                                                 case RECORD_TIMED:
00227                                                         if(record->current_display_position() > *record->current_duration())
00228                                                                 batch_done = 1;
00229                                                         break;
00230                                                 case RECORD_LOOP:
00231                                                         if(record->current_display_position() > *record->current_duration())
00232                                                                 batch_done = 1;
00233                                                         break;
00234                                                 case RECORD_SCENETOSCENE:
00235                                                         break;
00236                                         }
00237                                 }
00238                         }
00239 //printf("RecordAudio::run 4 %d %d\n", batch_done, write_result);
00240         }
00241 
00242 TRACE("RecordAudio::run 4");
00243         if(write_result && !record->default_asset->video_data)
00244         {
00245                 ErrorBox error_box(PROGRAM_NAME ": Error",
00246                         mwindow->gui->get_abs_cursor_x(1),
00247                         mwindow->gui->get_abs_cursor_y(1));
00248                 error_box.create_objects(_("No space left on disk."));
00249                 error_box.run_window();
00250                 batch_done = 1;
00251         }
00252 TRACE("RecordAudio::run 10\n");
00253 
00254         if(!record_thread->monitor)
00255         {
00256 // write last buffer
00257                 write_buffer(1);
00258         }
00259         else
00260         {
00261 // Delete the fake buffer.
00262                 for(int i = 0; i < record_channels; i++)
00263                 {
00264                         record->record_monitor->window->meters->meters.values[i]->reset();
00265                         delete [] input[i];
00266                 }
00267                 delete [] input;
00268                 input = 0;
00269         }
00270 TRACE("RecordAudio::run 11\n");
00271 
00272 // reset meter
00273         gui->lock_window("RecordAudio::run 2");
00274         for(channel = 0; channel < record_channels; channel++)
00275         {
00276                 record->record_monitor->window->meters->meters.values[channel]->reset();
00277         }
00278 TRACE("RecordAudio::run 12\n");
00279 
00280         gui->unlock_window();
00281         delete [] max;
00282         delete [] over;
00283 TRACE("RecordAudio::run 100\n");
00284 }
00285 
00286 void RecordAudio::write_buffer(int skip_new)
00287 {
00288 // block until buffer is ready for writing
00289         write_result = record->file->write_audio_buffer(fragment_position);
00290 // Defeat errors if video
00291         if(record->default_asset->video_data) write_result = 0;
00292         fragment_position = 0;
00293         if(!skip_new && !write_result) input = record->file->get_audio_buffer();
00294 }
00295 
00296 int64_t RecordAudio::sync_position()
00297 {
00298         int64_t result;
00299         if(!batch_done)
00300         {
00301 //printf("RecordAudio::sync_position 1\n");
00302                 timer_lock->lock("RecordAudio::sync_position");
00303                 if(!mwindow->edl->session->record_software_position)
00304                 {
00305 //printf("RecordAudio::sync_position 1\n");
00306                         result = record->adevice->current_position();
00307                 }
00308                 else
00309                 {
00310 //printf("RecordAudio::sync_position 1 %d\n", record->get_current_batch()->session_samples);
00311                         result = record->get_current_batch()->session_samples +
00312                                 timer.get_scaled_difference(record->default_asset->sample_rate);
00313                 }
00314                 timer_lock->unlock();
00315 //printf("RecordAudio::sync_position 2\n");
00316                 return result;
00317         }
00318         else
00319         return -1;
00320 }
00321 

Generated on Sun Jan 8 13:38:59 2006 for Cinelerra-svn by  doxygen 1.4.4