Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

page_export_1394.cc

Go to the documentation of this file.
00001 /*
00002 * page_export_1394.cc Notebook Firewire/AVI/Still Frame Export Page Object
00003 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
00004 *
00005 * This program is free software; you can redistribute it and/or modify
00006 * it under the terms of the GNU General Public License as published by
00007 * the Free Software Foundation; either version 2 of the License, or
00008 * (at your option) any later version.
00009 *
00010 * This program is distributed in the hope that it will be useful,
00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 * GNU General Public License for more details.
00014 *
00015 * You should have received a copy of the GNU General Public License
00016 * along with this program; if not, write to the Free Software Foundation,
00017 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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     /* Change the sensitivity of the hosting widget according to
00131        wheter the system loaded or not */
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     // Only for export, NOT for preview.
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         // Calculate resample rate for locked audio
00211         playlist->GetFrame( begin, frame );
00212         if ( resample )
00213         {
00214             // first call to innerLoopUpdate initializes progress tracker, which
00215             // we want to do because calculateAdjustedRate generates paused time.
00216             innerLoopUpdate( begin, begin, end, every );
00217             frame.GetAudioInfo( info );
00218             adjustedRate = calculateAdjustedRate( playlist, info.frequency, i, end, every );
00219         }
00220 
00221         /* pre-roll */
00222         for ( i = begin; i <= end && i <= begin +
00223                 Preferences::getInstance().dvExportPrerollSec * ( frame.IsPAL() ? 25 : 30 )
00224                 && exportPage->isExporting; i++ )
00225         {
00226 
00227             /* re-encode the audio to ensure consistent 16bit bitstream */
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         /* Iterate over all frames in selection */
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             /* resample audio */
00245             if ( resample )
00246             {
00247                 if ( ! resampler && adjustedRate )
00248                 {
00249                     frame.GetAudioInfo( info );
00250 
00251                     // Determine correct amount of audio for duration
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 }

Generated on Sun Mar 11 22:11:46 2007 for Kino by  doxygen 1.4.2