00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023
00024 #include <iostream>
00025 using std::cerr;
00026 using std::endl;
00027
00028 #include <gtk/gtk.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <assert.h>
00032
00033 #include "page_export_1394.h"
00034 #include "preferences.h"
00035 #include "ieee1394io.h"
00036 #include "message.h"
00037 #include "frame.h"
00038
00045 Export1394::Export1394( PageExport *_exportPage, KinoCommon *_common ) :
00046 Export( _exportPage, _common ), avc( NULL ), exportWriter( NULL ),
00047 system_loaded( false )
00048 {
00049 cerr << "> Creating Export1394 Page" << endl;
00050 entry_preroll = GTK_ENTRY( lookup_widget( common->getWidget(), "spinbutton_export_1394_preroll" ) );
00051 }
00052
00056 Export1394::~Export1394()
00057 {
00058 cerr << "> Destroying Export1394 Page" << endl;
00059 }
00060
00064 void Export1394::start()
00065 {
00066 static raw1394handle_t handle;
00067 gchar s[ 512 ];
00068
00069 cerr << ">> Starting Export1394" << endl;
00070
00071 sprintf( s, "%d", Preferences::getInstance().dvExportPrerollSec );
00072 gtk_entry_set_text( entry_preroll, s );
00073
00074 if ( ( handle = raw1394_new_handle() ) )
00075 {
00076 if ( raw1394_set_port( handle, 0 ) >= 0 )
00077 {
00078 raw1394_destroy_handle( handle );
00079 handle = NULL;
00080 avc = new AVC();
00081 Preferences::getInstance( ).phyID = avc->getNodeId( Preferences::getInstance( ).avcGUID );
00082 Preferences::getInstance( ).phyID = avc->isPhyIDValid( Preferences::getInstance( ).phyID );
00083 system_loaded = true;
00084 if ( avc->getPort() < 0 )
00085 {
00086 delete avc;
00087 avc = 0;
00088 }
00089 }
00090 else
00091 {
00092 system_loaded = false;
00093 common->setStatusBar( _( "Error setting the IEEE 1394 port (host adapater)." ) );
00094 }
00095 }
00096 #ifdef HAVE_IEC61883
00097 else
00098 {
00099 system_loaded = false;
00100 common->setStatusBar( _( "WARNING: raw1394 kernel module not loaded or failure to read/write /dev/raw1394!" ) );
00101 }
00102 #else
00103 else
00104 {
00105 common->setStatusBar( _( "Failed to open raw1394; you must manually control recording on the device." ) );
00106 }
00107 #endif
00108
00109 #ifdef HAVE_IEC61883
00110 exportWriter = new iec61883Writer( ( avc && avc->getPort() > -1 ) ? avc->getPort() : 0,
00111 Preferences::getInstance().channel,
00112 Preferences::getInstance().dvExportBuffers );
00113 #else
00114 exportWriter = new dv1394Writer(
00115 Preferences::getInstance().dvExportDevice,
00116 Preferences::getInstance().channel,
00117 Preferences::getInstance().dvExportBuffers,
00118 Preferences::getInstance().cip_n,
00119 Preferences::getInstance().cip_d,
00120 Preferences::getInstance().syt_offset
00121 );
00122 system_loaded = exportWriter->isValid();
00123 if ( !system_loaded )
00124 {
00125 common->setStatusBar( _( "WARNING: dv1394 kernel module not loaded or failure to read/write %s." ),
00126 Preferences::getInstance().dvExportDevice );
00127 }
00128 #endif
00129
00130
00131
00132 GtkVBox * tmp
00133 = GTK_VBOX( lookup_widget ( exportPage->getWidget(),
00134 "vbox_export_1394" ) );
00135 if ( system_loaded )
00136 {
00137 gtk_widget_set_sensitive ( GTK_WIDGET ( tmp ), TRUE );
00138 }
00139 else
00140 {
00141 gtk_widget_set_sensitive ( GTK_WIDGET ( tmp ), FALSE );
00142 }
00143 }
00144
00150 gulong Export1394::onActivate()
00151 {
00152 if ( system_loaded )
00153 {
00154 if ( avc )
00155 return EXPORT_PREVIEW | EXPORT_EXPORT | EXPORT_SCENE_LIST;
00156 else
00157 return EXPORT_PREVIEW | EXPORT_SCENE_LIST;
00158 }
00159 return 0;
00160 }
00161
00165 void Export1394::clean()
00166 {
00167 cerr << ">> Leaving Export1394" << endl;
00168 delete exportWriter;
00169 exportWriter = NULL;
00170 delete avc;
00171 avc = NULL;
00172 }
00173
00176 enum export_result
00177 Export1394::doExport( PlayList * playlist, int begin, int end, int every,
00178 bool preview )
00179 {
00180 int i = -1;
00181 Preferences::getInstance().dvExportPrerollSec = atoi( gtk_entry_get_text( entry_preroll ) );
00182 enum export_result result = EXPORT_RESULT_ABORT;
00183 string filename = "";
00184
00185
00186 if ( !preview && avc )
00187 {
00188 avc->Record( Preferences::getInstance().phyID );
00189 }
00190
00191 assert( exportWriter );
00192 if ( exportWriter->isValid() )
00193 {
00194 Frame& frame = *GetFramePool()->GetFrame();
00195
00196 bool resample = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(
00197 lookup_widget( common->getWidget(), "checkbutton_export_1394_resample" ) ) );
00198
00199 int16_le_t *audio_buffers[ 4 ];
00200 AudioInfo info;
00201 AsyncAudioResample<int16_ne_t,int16_le_t>* resampler = 0;
00202 double adjustedRate;
00203 int frameNum = 0;
00204
00205 for ( i = 0; i < 4; i++ )
00206 audio_buffers[ i ] = ( int16_le_t * ) calloc( 2 * DV_AUDIO_MAX_SAMPLES, sizeof( int16_t ) );
00207
00208 innerLoopUpdate( begin, begin, end, every );
00209
00210
00211 playlist->GetFrame( begin, frame );
00212 if ( resample )
00213 {
00214
00215
00216 innerLoopUpdate( begin, begin, end, every );
00217 frame.GetAudioInfo( info );
00218 adjustedRate = calculateAdjustedRate( playlist, info.frequency, i, end, every );
00219 }
00220
00221
00222 for ( i = begin; i <= end && i <= begin +
00223 Preferences::getInstance().dvExportPrerollSec * ( frame.IsPAL() ? 25 : 30 )
00224 && exportPage->isExporting; i++ )
00225 {
00226
00227
00228 frame.GetAudioInfo( info );
00229 info.channels = 2;
00230 frame.EncodeAudio( info, audio_buffers );
00231 if ( !exportWriter->SendFrame( frame ) )
00232 {
00233 exportPage->isExporting = false;
00234 result = EXPORT_RESULT_FAILURE;
00235 }
00236 }
00237
00238
00239 for ( i = begin; i <= end && exportPage->isExporting; i += every, frameNum++ )
00240 {
00241 innerLoopUpdate( i, begin, end, every );
00242 playlist->GetFrame( i, frame );
00243
00244
00245 if ( resample )
00246 {
00247 if ( ! resampler && adjustedRate )
00248 {
00249 frame.GetAudioInfo( info );
00250
00251
00252 resampler = new AsyncAudioResample<int16_ne_t,int16_le_t>(
00253 AUDIO_RESAMPLE_SRC_SINC_MEDIUM_QUALITY, playlist, info.frequency, i, end, every );
00254 if ( ! resampler )
00255 {
00256 result = EXPORT_RESULT_FAILURE;
00257 break;
00258 }
00259 if ( resampler->IsError() )
00260 {
00261 result = EXPORT_RESULT_FAILURE;
00262 std::cerr << ">>> Resampler error: " << resampler->GetError() << std::endl;
00263 break;
00264 }
00265 }
00266 int requestedSamples = frame.CalculateNumberSamples( info.frequency, frameNum );
00267 info.samples = resampler->Process( adjustedRate, requestedSamples );
00268 int16_le_t *p = resampler->GetOutput();
00269 for ( int s = 0; s < info.samples; s++ )
00270 for ( int c = 0; c < info.channels; c++ )
00271 audio_buffers[ c ][ s ] = *p++;
00272 if ( info.samples )
00273 frame.EncodeAudio( info, audio_buffers );
00274 }
00275
00276 if ( !exportWriter->SendFrame( frame ) )
00277 {
00278 result = EXPORT_RESULT_FAILURE;
00279 break;
00280 }
00281 }
00282
00283 if ( result != EXPORT_RESULT_FAILURE && i > end )
00284 result = EXPORT_RESULT_SUCCESS;
00285
00286 for ( i = 0; i < 4; i++ )
00287 free( audio_buffers[ i ] );
00288 delete resampler;
00289
00290 GetFramePool()->DoneWithFrame( &frame );
00291 }
00292
00293 common->setStatusBar( "" );
00294 if ( !preview && avc )
00295 {
00296 avc->Stop( Preferences::getInstance().phyID );
00297 }
00298
00299 return result;
00300 }