00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024
00025 #include <iostream>
00026
00027 #include <gtk/gtk.h>
00028 #include <math.h>
00029 #include <limits.h>
00030 #include <unistd.h>
00031
00032 #include "page_capture.h"
00033 #include "riff.h"
00034 #include "avi.h"
00035 #include "playlist.h"
00036 #include "filehandler.h"
00037 #include "ieee1394io.h"
00038 #include "framedisplayer.h"
00039 #include "message.h"
00040 #include "error.h"
00041 #include "frame.h"
00042 #include "page_editor.h"
00043
00044 static FrameDisplayer *displayer = NULL;
00045
00046 extern "C"
00047 {
00048 #include "support.h"
00049 #include "callbacks.h"
00050 #include "commands.h"
00051
00052 #include <pthread.h>
00053
00054 extern struct navigate_control g_nav_ctl;
00055
00056
00057
00058 IEEE1394Reader *reader = NULL;
00059 AVC *avc = NULL;
00060 static FileHandler *writer = NULL;
00061 extern char cmd[];
00062 static char lastcmd[ 256 ];
00063 static gchar lastPreferenceFilename[ 512 ];
00064 extern KinoCommon *common;
00065 static quadlet_t avcStatus;
00066 char timecode[ 256 ];
00067
00068
00069
00070
00071
00072 static void *captureThread( void * p );
00073 static void *avcThread( void * p );
00074 static void *videoThread( void * p );
00075 static pthread_t capturethread;
00076 static pthread_t avcthread;
00077 static pthread_t videothread;
00078 static gboolean audioOn = FALSE;
00079 static pthread_mutex_t writerlock = PTHREAD_MUTEX_INITIALIZER;
00080
00081
00082 #define BUFFERED_FRAMES 25
00083
00084
00085 static int framePosition = -1;
00086 static Frame *frameBuffer[ BUFFERED_FRAMES ];
00087 static int frameCount = 0;
00088 static void TriggerAction( );
00089 static int framesCaptured = 0;
00090 static int prevFramesWritten = 0;
00091 }
00092
00098 PageCapture::PageCapture( KinoCommon *common ) : isCapturing( false ), captureMutex( false ),
00099 avc_enabled( false ), driver_locked( false )
00100 {
00101 std::cerr << "> Creating Capture Page" << std::endl;
00102 this->common = common;
00103 this->frameArea = GTK_DRAWING_AREA( lookup_widget( common->getWidget(), "capture_drawingarea" ) );
00104 gtk_widget_set_double_buffered( GTK_WIDGET( frameArea ), FALSE );
00105 this->avcButton = GTK_TOGGLE_BUTTON( lookup_widget( common->getWidget(), "capture_page_avc_button" ) );
00106 this->recordButton = GTK_TOGGLE_BUTTON( lookup_widget( common->getWidget(), "capture_page_record_button" ) );
00107 this->stopButton = GTK_TOGGLE_BUTTON( lookup_widget( common->getWidget(), "capture_page_stop_button" ) );
00108 this->muteButton = GTK_TOGGLE_BUTTON( lookup_widget( common->getWidget(), "capture_page_mute_button" ) );
00109 this->snapshotButton = GTK_BUTTON( lookup_widget( common->getWidget(), "capture_page_snapshot_button" ) );
00110 this->fileEntry = GTK_ENTRY( lookup_widget( common->getWidget(), "entry_capture_file" ) );
00111 this->timecodeLabel = GTK_LABEL( lookup_widget( common->getWidget(), "position_label_current" ) );
00112 lastPreferenceFilename[ 0 ] = 0;
00113 memset( timecode, 0, sizeof( timecode ) );
00114 }
00115
00119 PageCapture::~PageCapture()
00120 {
00121 std::cerr << "> Destroying Capture Page" << std::endl;
00122 delete reader;
00123 reader = NULL;
00124 }
00125
00129 void PageCapture::newFile( )
00130 {
00131 strcpy( lastPreferenceFilename, "" );
00132 }
00133
00137 void PageCapture::start()
00138 {
00139 std::cerr << ">> Starting Capture" << std::endl;
00140
00141
00142 driver_available = false;
00143 check_phyid = true;
00144 avc_enabled = false;
00145 validComponents = 0;
00146 gui_state_was = -1;
00147
00148 gtk_toggle_button_set_active( avcButton, Preferences::getInstance().enableAVC );
00149 GtkLabel *label = GTK_LABEL( lookup_widget( common->getWidget(), "position_label_total" ) );
00150 gtk_label_set_text( label, "" );
00151
00152
00153 #ifdef HAVE_IEC61883
00154 reader = new iec61883Reader( Preferences::getInstance().channel,
00155 Preferences::getInstance().dvCaptureBuffers );
00156 #else
00157 reader = new dv1394Reader( Preferences::getInstance().channel,
00158 Preferences::getInstance().dvCaptureBuffers );
00159 #endif
00160
00161
00162 avc = new AVC();
00163
00164
00165
00166
00167
00168 string capture_file_name = Preferences::getInstance().file;
00169 if ( capture_file_name[ 0 ] != '/' )
00170 capture_file_name = common->getPlayList( ) ->GetProjectDirectory( ) + "/" + capture_file_name;
00171
00172
00173
00174 if ( capture_file_name != lastPreferenceFilename )
00175 {
00176 strcpy( lastPreferenceFilename, capture_file_name.c_str( ) );
00177 gtk_entry_set_text( fileEntry, capture_file_name.c_str( ) );
00178 }
00179
00180
00181 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00182
00183
00184 displayer = new FrameDisplayer;
00185
00186
00187 g_nav_ctl.capture_active = TRUE;
00188 pthread_create( &capturethread, NULL, captureThread, this );
00189 pthread_create( &avcthread, NULL, avcThread, this );
00190 pthread_create( &videothread, NULL, videoThread, lookup_widget( common->getWidget(), "capture_drawingarea" ) );
00191
00192 common->activateWidgets();
00193 gtk_label_set_text( timecodeLabel, "" );
00194 common->packIt( "packer_capture", "packer_capture_outer" );
00195 common->toggleComponents( VIDEO_STOP, false );
00196 common->commitComponentState();
00197
00198 gtk_notebook_set_page( GTK_NOTEBOOK( lookup_widget( common->getWidget(), "notebook_keyhelp" ) ), 1 );
00199 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( lookup_widget( common->getWidget(), "menuitem_capture" ) ), TRUE );
00200 }
00201
00205 void PageCapture::CheckDevices( )
00206 {
00207 static int avcRetry = 0;
00208
00209 if ( driver_locked == true )
00210 {
00211 std::cerr << "Stopping thread" << std::endl;
00212 reader->StopThread( );
00213 driver_locked = false;
00214 driver_available = false;
00215 avc_enabled = false;
00216 check_phyid = true;
00217 TriggerAction( );
00218 }
00219 else if ( driver_available == false )
00220 {
00221
00222 Preferences::getInstance( ).phyID = avc->getNodeId( Preferences::getInstance( ).avcGUID );
00223 Preferences::getInstance( ).phyID = avc->isPhyIDValid( Preferences::getInstance( ).phyID );
00224 check_phyid = Preferences::getInstance( ).phyID < 0;
00225
00226
00227
00228 if ( reader->StartThread( ( avc->getPort() < 0 ) ? 0 : avc->getPort() ) )
00229 {
00230
00231 driver_available = true;
00232 avc_enabled = false;
00233 }
00234 TriggerAction( );
00235 }
00236 else if ( check_phyid )
00237 {
00238
00239 Preferences::getInstance( ).phyID = avc->isPhyIDValid( Preferences::getInstance( ).phyID );
00240 check_phyid = Preferences::getInstance( ).phyID < 0;
00241 avc_enabled = false;
00242 TriggerAction( );
00243 }
00244 else if ( avc_enabled )
00245 {
00246 quadlet_t status = avc->TransportStatus( Preferences::getInstance().phyID );
00247
00248 if ( ( int ) status < 0 )
00249 {
00250 cerr << ">>> AVC status error" << std::endl;
00251 if ( ++avcRetry > 2 )
00252 {
00253 avcRetry = 0;
00254 avc_enabled = false;
00255 check_phyid = true;
00256 }
00257 }
00258 else
00259 {
00260 char t[ 12 ];
00261
00262 avcStatus = status;
00263 avcRetry = 0;
00264
00265 if ( !isCapturing && avc->Timecode( Preferences::getInstance().phyID, t ) )
00266 {
00267 strncpy( timecode, t, 12 );
00268 }
00269 TriggerAction();
00270 }
00271 }
00272 else
00273 {
00274 avc_enabled = Preferences::getInstance().enableAVC;
00275 gtk_toggle_button_set_active( this->avcButton, avc_enabled );
00276 avc->Noop();
00277 }
00278 }
00279
00282 void PageCapture::applyAVCState( quadlet_t newAVCState )
00283 {
00284 if ( driver_available == false )
00285 {
00286 if ( gui_state_was != 0 )
00287 {
00288 gtk_widget_set_sensitive( GTK_WIDGET( avcButton ), false );
00289 gtk_widget_set_sensitive( GTK_WIDGET( recordButton ), false );
00290 gtk_widget_set_sensitive( GTK_WIDGET( stopButton ), false );
00291 gtk_widget_set_sensitive( GTK_WIDGET( snapshotButton ), false );
00292 gtk_widget_set_sensitive( GTK_WIDGET( muteButton ), false );
00293 validComponents = 0;
00294 common->activateWidgets( );
00295 common->commitComponentState();
00296 #ifdef HAVE_IEC61883
00297 common->setStatusBar( _( "WARNING: raw1394 kernel module not loaded or failure to read/write /dev/raw1394!" ) );
00298 #else
00299 common->setStatusBar( _( "WARNING: dv1394 kernel module not loaded or failure to read/write %s" ),
00300 Preferences::getInstance().dvCaptureDevice );
00301 #endif
00302 }
00303 gui_state_was = 0;
00304 }
00305 else if ( check_phyid == true )
00306 {
00307 if ( gui_state_was != 1 )
00308 {
00309 gtk_widget_set_sensitive( GTK_WIDGET( avcButton ), false );
00310 gtk_widget_set_sensitive( GTK_WIDGET( recordButton ), true );
00311 gtk_widget_set_sensitive( GTK_WIDGET( stopButton ), true );
00312 gtk_widget_set_sensitive( GTK_WIDGET( snapshotButton ), true );
00313 gtk_widget_set_sensitive( GTK_WIDGET( muteButton ), true );
00314 validComponents = 0;
00315 common->activateWidgets( );
00316 common->commitComponentState();
00317 common->setStatusBar( _( "No AV/C compliant cam connected or not switched on?" ) );
00318 }
00319 gui_state_was = 1;
00320 }
00321 else if ( avc_enabled )
00322 {
00323 if ( gui_state_was != 2 )
00324 {
00325 gtk_widget_set_sensitive( GTK_WIDGET( avcButton ), true );
00326 gtk_widget_set_sensitive( GTK_WIDGET( recordButton ), true );
00327 gtk_widget_set_sensitive( GTK_WIDGET( stopButton ), true );
00328 gtk_widget_set_sensitive( GTK_WIDGET( snapshotButton ), true );
00329 gtk_widget_set_sensitive( GTK_WIDGET( muteButton ), true );
00330
00331 validComponents = VIDEO_REWIND |
00332 VIDEO_PLAY |
00333 VIDEO_STOP |
00334 VIDEO_FAST_FORWARD |
00335 VIDEO_FORWARD |
00336 VIDEO_BACK |
00337 VIDEO_NEXT_SCENE |
00338 VIDEO_START_OF_SCENE |
00339 VIDEO_START_OF_MOVIE |
00340 VIDEO_SHUTTLE |
00341 VIDEO_END_OF_MOVIE |
00342 INFO_FRAME;
00343
00344 common->activateWidgets( );
00345
00346 gui_state_was = 2;
00347
00348 common->setStatusBar( "AV/C Controls Enabled" );
00349 cerr << ">>> AVC enabled " << std::endl;
00350
00351
00352 avcState = true;
00353 }
00354
00355 if ( avcState != newAVCState )
00356 {
00357 quadlet_t resp2 = AVC1394_MASK_RESPONSE_OPERAND( newAVCState, 2 );
00358 quadlet_t resp3 = AVC1394_MASK_RESPONSE_OPERAND( newAVCState, 3 );
00359 this->avcState = newAVCState;
00360
00361 common->toggleComponents( common->getComponentState(), false );
00362 g_nav_ctl.active = FALSE;
00363
00364 if ( resp2 == AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY )
00365 {
00366 if ( resp3 >= AVC1394_VCR_OPERAND_PLAY_FAST_FORWARD_1
00367 && resp3 <= AVC1394_VCR_OPERAND_PLAY_FASTEST_FORWARD )
00368 {
00369 common->toggleComponents( VIDEO_FAST_FORWARD, true );
00370 g_nav_ctl.active = TRUE;
00371 }
00372 else if ( resp3 >= AVC1394_VCR_OPERAND_PLAY_FAST_REVERSE_1
00373 && resp3 <= AVC1394_VCR_OPERAND_PLAY_FASTEST_REVERSE )
00374 {
00375 common->toggleComponents( VIDEO_REWIND, true );
00376 g_nav_ctl.active = TRUE;
00377 }
00378 else if ( resp3 == AVC1394_VCR_OPERAND_PLAY_FORWARD_PAUSE )
00379 {
00380 common->toggleComponents( VIDEO_PLAY, false );
00381 }
00382 else
00383 {
00384 common->toggleComponents( VIDEO_PLAY, true );
00385 g_nav_ctl.active = TRUE;
00386 }
00387 }
00388 else if ( resp2 == AVC1394_VCR_RESPONSE_TRANSPORT_STATE_WIND )
00389 {
00390 if ( resp3 == AVC1394_VCR_OPERAND_WIND_HIGH_SPEED_REWIND )
00391 {
00392 common->toggleComponents( VIDEO_START_OF_MOVIE, true );
00393 }
00394 else if ( resp3 == AVC1394_VCR_OPERAND_WIND_STOP )
00395 {
00396 stopCapture();
00397 common->toggleComponents( VIDEO_STOP, true );
00398 }
00399 else if ( resp3 == AVC1394_VCR_OPERAND_WIND_REWIND )
00400 {
00401 common->toggleComponents( VIDEO_START_OF_MOVIE, true );
00402 }
00403 else if ( resp3 == AVC1394_VCR_OPERAND_WIND_FAST_FORWARD )
00404 {
00405 common->toggleComponents( VIDEO_END_OF_MOVIE, true );
00406 }
00407 else
00408 {
00409 std::cerr << "AVC Status: Unkown winding" << std::endl;
00410 }
00411 }
00412 else if ( resp2 == AVC1394_VCR_RESPONSE_TRANSPORT_STATE_RECORD )
00413 {
00414 if ( resp3 == AVC1394_VCR_OPERAND_RECORD_PAUSE )
00415 {
00416 common->toggleComponents( VIDEO_PLAY, false );
00417 }
00418 else
00419 {
00420 common->toggleComponents( VIDEO_PLAY, true );
00421 g_nav_ctl.active = TRUE;
00422 }
00423 }
00424 else
00425 {
00426 std::cerr << "AVC Status: Unknown state" << std::endl;
00427 }
00428 common->commitComponentState();
00429 }
00430 }
00431 else
00432 {
00433 if ( gui_state_was != 3 )
00434 {
00435 gtk_widget_set_sensitive( GTK_WIDGET( avcButton ), true );
00436 gtk_widget_set_sensitive( GTK_WIDGET( recordButton ), true );
00437 gtk_widget_set_sensitive( GTK_WIDGET( stopButton ), true );
00438 gtk_widget_set_sensitive( GTK_WIDGET( snapshotButton ), true );
00439 gtk_widget_set_sensitive( GTK_WIDGET( muteButton ), true );
00440 validComponents = 0;
00441 common->activateWidgets( );
00442 common->commitComponentState();
00443 if ( !isCapturing )
00444 common->setStatusBar( _( "AV/C Controls Not Enabled." ) );
00445 gui_state_was = 3;
00446 }
00447 }
00448 }
00449
00453 gulong PageCapture::activate()
00454 {
00455 return this->validComponents | SCENE_LIST;
00456 }
00457
00461 void PageCapture::clean()
00462 {
00463 std::cerr << ">> Leaving Capture" << std::endl;
00464
00465 if ( g_nav_ctl.capture_active == TRUE )
00466 {
00467
00468 stopCapture();
00469
00470
00471 if ( avc_enabled && Preferences::getInstance( ).phyID >= 0 )
00472 videoStop();
00473
00474
00475 g_nav_ctl.active = FALSE;
00476 g_nav_ctl.capture_active = FALSE;
00477
00478
00479 reader->TriggerAction();
00480 pthread_join( capturethread, NULL );
00481 pthread_join( avcthread, NULL );
00482
00483
00484 gdk_threads_leave();
00485 pthread_join( videothread, NULL );
00486 gdk_threads_enter();
00487
00488
00489 reader->StopThread();
00490 }
00491
00492 common->setStatusBar( "" );
00493
00494
00495 delete displayer;
00496 displayer = NULL;
00497 delete reader;
00498 reader = NULL;
00499 delete avc;
00500 avc = NULL;
00501 }
00502
00503
00507 void PageCapture::videoStartOfMovie()
00508 {
00509 if ( avc_enabled )
00510 {
00511 audioOn = FALSE;
00512 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00513 common->toggleComponents( VIDEO_START_OF_MOVIE, avc_enabled );
00514 if ( avc->Stop( Preferences::getInstance().phyID ) >= 0 )
00515 avc->Rewind( Preferences::getInstance().phyID );
00516 }
00517 }
00518
00522 void PageCapture::videoPreviousScene()
00523 {
00524 if ( avc_enabled )
00525 {
00526 audioOn = FALSE;
00527 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00528 common->toggleComponents( VIDEO_START_OF_SCENE, avc_enabled );
00529 if ( avc->Pause( Preferences::getInstance().phyID ) >= 0 )
00530 avc->PreviousScene( Preferences::getInstance().phyID );
00531 }
00532 }
00533
00537 void PageCapture::videoStartOfScene()
00538 {
00539 if ( avc_enabled )
00540 {
00541 audioOn = FALSE;
00542 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00543 common->toggleComponents( VIDEO_START_OF_SCENE, avc_enabled );
00544 if ( avc->Pause( Preferences::getInstance().phyID ) >= 0 )
00545 avc->PreviousScene( Preferences::getInstance().phyID );
00546 }
00547 }
00548
00552 void PageCapture::videoRewind()
00553 {
00554 if ( avc_enabled )
00555 {
00556 audioOn = FALSE;
00557 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00558 common->toggleComponents( VIDEO_REWIND, avc_enabled );
00559 if ( avc->Pause( Preferences::getInstance().phyID ) >= 0 )
00560 avc->Rewind( Preferences::getInstance().phyID );
00561 }
00562 }
00563
00567 void PageCapture::videoBack()
00568 {
00569 if ( avc_enabled )
00570 {
00571 audioOn = FALSE;
00572 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00573 common->toggleComponents( VIDEO_BACK, avc_enabled );
00574 if ( avc->Pause( Preferences::getInstance().phyID ) >= 0 )
00575 avc->Back( Preferences::getInstance().phyID );
00576 }
00577 }
00578
00582 void PageCapture::videoPlay()
00583 {
00584 if ( avc_enabled )
00585 {
00586 if ( g_nav_ctl.active == TRUE )
00587 {
00588 audioOn = FALSE;
00589 gtk_toggle_button_set_active( this->muteButton, TRUE );
00590 common->toggleComponents( VIDEO_PLAY, false );
00591 avc->Pause( Preferences::getInstance().phyID );
00592 }
00593 else
00594 {
00595 audioOn = TRUE;
00596 gtk_toggle_button_set_active( this->muteButton, FALSE );
00597 common->toggleComponents( VIDEO_PLAY, true );
00598 avc->Play( Preferences::getInstance().phyID );
00599 }
00600 }
00601 }
00602
00606 void PageCapture::videoPause()
00607 {
00608 if ( avc_enabled )
00609 {
00610 audioOn = FALSE;
00611 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00612 avc->Pause( Preferences::getInstance().phyID );
00613 }
00614 }
00615
00619 void PageCapture::videoStop()
00620 {
00621 if ( avc_enabled )
00622 {
00623 audioOn = FALSE;
00624 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00625 common->toggleComponents( VIDEO_STOP, avc_enabled );
00626 avc->Stop( Preferences::getInstance().phyID );
00627 }
00628 }
00629
00633 void PageCapture::videoForward()
00634 {
00635 if ( avc_enabled )
00636 {
00637 audioOn = FALSE;
00638 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00639 common->toggleComponents( VIDEO_FORWARD, avc_enabled );
00640 if ( avc->Pause( Preferences::getInstance().phyID ) >= 0 )
00641 avc->Forward( Preferences::getInstance().phyID );
00642 }
00643 }
00644
00648 void PageCapture::videoFastForward()
00649 {
00650 if ( avc_enabled )
00651 {
00652 audioOn = FALSE;
00653 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00654 common->toggleComponents( VIDEO_FAST_FORWARD, avc_enabled );
00655 if ( avc->Pause( Preferences::getInstance().phyID ) >= 0 )
00656 avc->FastForward( Preferences::getInstance().phyID );
00657 }
00658 }
00659
00663 void PageCapture::videoNextScene()
00664 {
00665 if ( avc_enabled )
00666 {
00667 audioOn = FALSE;
00668 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00669 common->toggleComponents( VIDEO_NEXT_SCENE, avc_enabled );
00670 if ( avc->Pause( Preferences::getInstance().phyID ) >= 0 )
00671 avc->NextScene( Preferences::getInstance().phyID );
00672 }
00673 }
00674
00678 void PageCapture::videoEndOfScene()
00679 {
00680 if ( avc_enabled )
00681 {
00682 audioOn = FALSE;
00683 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00684 common->toggleComponents( VIDEO_NEXT_SCENE, avc_enabled );
00685 if ( avc->Pause( Preferences::getInstance().phyID ) >= 0 )
00686 avc->NextScene( Preferences::getInstance().phyID );
00687 }
00688 }
00689
00693 void PageCapture::videoEndOfMovie()
00694 {
00695 if ( avc_enabled )
00696 {
00697 audioOn = FALSE;
00698 gtk_toggle_button_set_active( this->muteButton, !audioOn );
00699 common->toggleComponents( VIDEO_END_OF_MOVIE, avc_enabled );
00700 if ( avc->Stop( Preferences::getInstance().phyID ) >= 0 )
00701 avc->FastForward( Preferences::getInstance().phyID );
00702 }
00703 }
00704
00712 void PageCapture::videoShuttle( int angle )
00713 {
00714 if ( avc_enabled )
00715 {
00716 audioOn = FALSE;
00717 if ( angle != 0 )
00718 avc->Shuttle( Preferences::getInstance().phyID, angle * 2 );
00719 else
00720 avc->Pause( Preferences::getInstance().phyID );
00721 }
00722 }
00723
00724
00730 gboolean PageCapture::processKeyboard( GdkEventKey *event )
00731 {
00732 gboolean ret = FALSE;
00733
00734
00735 if ( g_nav_ctl.escaped == FALSE )
00736 {
00737 if ( strcmp( lastcmd, "alt" ) == 0 )
00738 {
00739 strcpy( lastcmd, "" );
00740 return ret;
00741 }
00742
00743
00744 switch ( event->keyval )
00745 {
00746 case GDK_Home:
00747 strcat( cmd, "gg");
00748 ret = TRUE;
00749 break;
00750 case GDK_End:
00751 strcat( cmd, "G");
00752 ret = TRUE;
00753 break;
00754 case GDK_BackSpace:
00755 case GDK_Left:
00756 strcat( cmd, "h" );
00757 ret = TRUE;
00758 break;
00759 case GDK_Up:
00760 strcat( cmd, "k" );
00761 ret = TRUE;
00762 break;
00763 case GDK_Right:
00764 strcat( cmd, "l" );
00765 ret = TRUE;
00766 break;
00767 case GDK_Return:
00768 startCapture();
00769 cmd[ 0 ] = 0;
00770 break;
00771 case GDK_Down:
00772 strcat( cmd, "j" );
00773 ret = TRUE;
00774 break;
00775 case GDK_Escape:
00776 if ( this->isCapturing )
00777 {
00778 common->keyboardFeedback( "Esc", _( "Stop Capture" ) );
00779 stopCapture();
00780 }
00781 else if ( common->getComponentState() & VIDEO_STOP )
00782 {
00783 common->changePageRequest( PAGE_EDITOR );
00784 }
00785 else if ( avc_enabled && Preferences::getInstance( ).phyID >= 0 )
00786 {
00787 common->keyboardFeedback( "Esc", _( "Stop" ) );
00788 common->videoStop( );
00789 }
00790 else
00791 {
00792 common->changePageRequest( PAGE_EDITOR );
00793 }
00794 cmd[ 0 ] = 0;
00795 return TRUE;
00796 case GDK_Alt_L:
00797 case GDK_Alt_R:
00798 strcpy( lastcmd, "alt" );
00799 return ret;
00800 default:
00801 strcat( cmd, event->string );
00802 break;
00803 }
00804
00805 if ( !strcmp( cmd, "." ) )
00806 strcpy( cmd, lastcmd );
00807
00808 processCommand( cmd );
00809
00810 }
00811 else if ( event->keyval == GDK_Return || event->keyval == GDK_Escape )
00812 {
00813 g_nav_ctl.escaped = FALSE;
00814 gtk_entry_set_editable( fileEntry, FALSE );
00815 gtk_widget_grab_focus( common->getWidget() );
00816 }
00817 return ret;
00818 }
00819
00825 gboolean PageCapture::processCommand( char *command )
00826 {
00827 int count = 1;
00828 char real[ 256 ] = "";
00829
00830 strcpy( cmd, command );
00831
00832 switch ( sscanf( cmd, "%d%s", &count, real ) )
00833 {
00834 case 1:
00835
00836 if ( strcmp( cmd, "0" ) )
00837 {
00838 common->keyboardFeedback( cmd, "" );
00839 return FALSE;
00840 }
00841 break;
00842 case 0:
00843 sscanf( cmd, "%s", real );
00844 count = 1;
00845 break;
00846 }
00847
00848 strcpy( lastcmd, cmd );
00849
00850
00851
00852 if ( strcmp( cmd, "t" ) == 0 )
00853 {
00854 common->keyboardFeedback( cmd, _( "Trim" ) );
00855 common->changePageRequest( PAGE_TRIM );
00856 cmd[ 0 ] = 0;
00857 }
00858
00859 else if ( strcmp( cmd, "v" ) == 0 )
00860 {
00861 common->keyboardFeedback( cmd, _( "Timeline" ) );
00862 common->changePageRequest( PAGE_TIMELINE );
00863 cmd[ 0 ] = 0;
00864 }
00865
00866 else if ( strcmp( cmd, "C" ) == 0 )
00867 {
00868 common->keyboardFeedback( cmd, _( "FX" ) );
00869 common->changePageRequest( PAGE_MAGICK );
00870 cmd[ 0 ] = 0;
00871 }
00872
00873
00874
00875 else if ( strcmp( cmd, ":W" ) == 0 )
00876 {
00877 common->keyboardFeedback( cmd, _( "Export" ) );
00878 common->changePageRequest( PAGE_EXPORT );
00879 cmd[ 0 ] = 0;
00880 }
00881
00882 else if ( strcmp( cmd, "F2" ) == 0 )
00883 {
00884 common->keyboardFeedback( cmd, _( "Edit" ) );
00885 common->changePageRequest( PAGE_EDITOR );
00886 cmd[ 0 ] = 0;
00887 }
00888
00889
00890
00891 else if ( strcmp( cmd, ":w" ) == 0 )
00892 {
00893 common->keyboardFeedback( cmd, _( "Write playlist" ) );
00894 common->savePlayList( );
00895 cmd[ 0 ] = 0;
00896 }
00897
00898
00899
00900 else if ( strcmp( cmd, ":q" ) == 0 )
00901 {
00902 common->keyboardFeedback( cmd, _( "quit" ) );
00903 kinoDeactivate();
00904 cmd[ 0 ] = 0;
00905 }
00906
00907 else if ( strcmp( real, "Enter" ) == 0 && ! isCapturing )
00908 {
00909 common->keyboardFeedback( cmd, _( "Start Capture" ) );
00910 startCapture();
00911 cmd[ 0 ] = 0;
00912 }
00913
00914 else if ( strcmp( real, "Esc" ) == 0 )
00915 {
00916 if ( this->isCapturing )
00917 {
00918 common->keyboardFeedback( "Esc", _( "Stop Capture" ) );
00919 stopCapture();
00920 }
00921 else if ( avc_enabled && Preferences::getInstance( ).phyID >= 0 )
00922 {
00923 common->keyboardFeedback( "Esc", _( "Stop" ) );
00924 common->videoStop( );
00925 }
00926 cmd[ 0 ] = 0;
00927 }
00928
00929
00930
00931 if ( validComponents == 0 || Preferences::getInstance( ).phyID < 0 )
00932 return FALSE;
00933
00934
00935
00936 if ( strcmp( cmd, " " ) == 0 )
00937 {
00938 if ( g_nav_ctl.active == FALSE )
00939 {
00940 common->keyboardFeedback( cmd, _( "Play" ) );
00941 common->videoPlay( );
00942 }
00943 else
00944 {
00945 common->keyboardFeedback( cmd, _( "Pause" ) );
00946 common->videoPause( );
00947 }
00948 cmd[ 0 ] = 0;
00949 }
00950
00951
00952
00953 else if ( strcmp( real, "l" ) == 0 )
00954 {
00955 common->keyboardFeedback( cmd, _( "Move forward" ) );
00956 common->videoForward();
00957 cmd[ 0 ] = 0;
00958 }
00959
00960
00961
00962 else if ( strcmp( real, "h" ) == 0 )
00963 {
00964 common->keyboardFeedback( cmd, _( "Move backward" ) );
00965 common->videoBack();
00966 cmd[ 0 ] = 0;
00967 }
00968
00969
00970
00971 else if ( ( strcmp( real, "w" ) == 0 || strcmp( real, "W" ) == 0 ||
00972 strcmp( real, "e" ) == 0 || strcmp( real, "E" ) == 0 ) )
00973 {
00974 common->keyboardFeedback( cmd, _( "Fast Forward" ) );
00975 common->videoFastForward();
00976 cmd[ 0 ] = 0;
00977 }
00978
00979
00980
00981 else if ( ( strcmp( real, "b" ) == 0 || strcmp( real, "B" ) == 0 ) )
00982 {
00983 common->keyboardFeedback( cmd, _( "Rewind" ) );
00984 common->videoRewind();
00985 cmd[ 0 ] = 0;
00986 }
00987
00988
00989
00990 else if ( ( strcmp( cmd, "0" ) == 0 || strcmp( real, "^" ) == 0 ) )
00991 {
00992 common->videoStartOfScene( );
00993 for ( ; count > 1; count -- )
00994 {
00995 common->g_currentFrame --;
00996 videoStartOfScene( );
00997 }
00998 common->keyboardFeedback( cmd, _( "Move to start of scene" ) );
00999 cmd[ 0 ] = 0;
01000 }
01001
01002
01003
01004 else if ( strcmp( real, "$" ) == 0 )
01005 {
01006 common->videoEndOfScene( );
01007 for ( ; count > 1; count -- )
01008 {
01009 common->g_currentFrame ++;
01010 videoEndOfScene( );
01011 }
01012 common->keyboardFeedback( cmd, _( "Move to end of scene" ) );
01013 cmd[ 0 ] = 0;
01014 }
01015
01016
01017
01018 else if ( ( strcmp( real, "j" ) == 0 || strcmp( real, "+" ) == 0 ) )
01019 {
01020 for ( ; count >= 1; count -- )
01021 common->videoNextScene( );
01022 common->keyboardFeedback( cmd, _( "Move to start of next scene" ) );
01023 cmd[ 0 ] = 0;
01024 }
01025
01026
01027
01028 else if ( ( strcmp( real, "k" ) == 0 || strcmp( real, "-" ) == 0 ) )
01029 {
01030 for ( ; count >= 1; count -- )
01031 common->videoPreviousScene( );
01032 common->keyboardFeedback( cmd, _( "Move to start of previous scene" ) );
01033 cmd[ 0 ] = 0;
01034 }
01035
01036
01037
01038 else if ( strcmp( cmd, "gg" ) == 0 )
01039 {
01040 common->videoStartOfMovie( );
01041 common->keyboardFeedback( cmd, _( "Move to first frame" ) );
01042 cmd[ 0 ] = 0;
01043 }
01044
01045
01046
01047 else if ( strcmp( cmd, "G" ) == 0 )
01048 {
01049 common->videoEndOfMovie( );
01050 common->keyboardFeedback( cmd, _( "Move to last frame" ) );
01051 cmd[ 0 ] = 0;
01052 }
01053
01054 else
01055 {
01056
01057 if ( strlen( real ) > 3 )
01058 cmd[ 0 ] = 0;
01059 else if ( strchr( "dgy ", real[ strlen( real ) - 1 ] ) == NULL )
01060 cmd[ 0 ] = 0;
01061
01062 common->keyboardFeedback( cmd, "" );
01063
01064 #if 0
01065
01066 printf( "send_event: %2.2x\n", event->send_event );
01067 printf( "time : %8.8x\n", event->time );
01068 printf( "state : %8.8x\n", event->state );
01069 printf( "keyval: %8.8x\n", event->keyval );
01070 printf( "length: %8.8x\n", event->length );
01071 printf( "string: %s\n", event->string );
01072 printf( "(hex) : %2.2x\n", event->string[ 0 ] );
01073 printf( "cmd : %s\n", cmd );
01074 #endif
01075
01076 }
01077
01078 return FALSE;
01079 }
01080
01086 void PageCapture::startCapture()
01087 {
01088 if ( !captureMutex && !isCapturing )
01089 {
01090 captureMutex = true;
01091 isCapturing = true;
01092 gtk_toggle_button_set_active( recordButton, true );
01093 gtk_toggle_button_set_active( stopButton, false );
01094 gtk_widget_set_sensitive( GTK_WIDGET( snapshotButton ), false );
01095 gtk_widget_set_sensitive( GTK_WIDGET( avcButton ), false );
01096 captureMutex = false;
01097
01098 char filename[ 512 ];
01099 strcpy( filename, gtk_entry_get_text( fileEntry ) );
01100
01101 if ( !strcmp( filename, "" ) )
01102 {
01103 common->setStatusBar( _( "You must enter a filename to capture." ) );
01104 captureMutex = true;
01105 gtk_toggle_button_set_active( recordButton, false );
01106 gtk_toggle_button_set_active( stopButton, true );
01107 gtk_widget_set_sensitive( GTK_WIDGET( snapshotButton ), true );
01108 gtk_widget_set_sensitive( GTK_WIDGET( avcButton ), true );
01109 captureMutex = false;
01110 isCapturing = false;
01111
01112 }
01113 else
01114 {
01115 Frame *frame = NULL;
01116 int retry;
01117 const int MAX_RETRIES = 10;
01118 struct timespec t =
01119 {
01120 1, 0UL
01121 };
01122
01123 if ( avc_enabled )
01124 {
01125 g_nav_ctl.active = FALSE;
01126 videoPlay();
01127 g_nav_ctl.active = TRUE;
01128 gui_state_was = 2;
01129 validComponents = 0;
01130 common->activateWidgets( );
01131 common->commitComponentState();
01132 gtk_widget_set_sensitive( GTK_WIDGET( recordButton ), true );
01133 gtk_widget_set_sensitive( GTK_WIDGET( stopButton ), true );
01134 gtk_widget_set_sensitive( GTK_WIDGET( muteButton ), true );
01135 gtk_widget_set_sensitive( GTK_WIDGET( avcButton ), false );
01136 gtk_widget_set_sensitive( GTK_WIDGET( snapshotButton ), false );
01137 }
01138
01139 FileHandler *handler = NULL;
01140
01141 switch ( Preferences::getInstance().fileFormat )
01142 {
01143 case RAW_FORMAT:
01144 handler = new RawHandler();
01145 break;
01146 #ifdef HAVE_LIBQUICKTIME
01147
01148 case QT_FORMAT:
01149 handler = new QtHandler();
01150 break;
01151 #endif
01152
01153 case AVI_DV1_FORMAT:
01154 case AVI_DV2_FORMAT:
01155 AVIHandler *aviWriter = new AVIHandler( Preferences::getInstance().fileFormat );
01156 handler = aviWriter;
01157 aviWriter->SetOpenDML( Preferences::getInstance().isOpenDML ||
01158 Preferences::getInstance().maxFileSize == 0 ||
01159 Preferences::getInstance().maxFileSize > 1000 );
01160 break;
01161 }
01162
01163
01164
01165 handler->SetMaxFrameCount( Preferences::getInstance().frames );
01166 handler->SetAutoSplit( Preferences::getInstance().autoSplit );
01167 handler->SetTimeStamp( Preferences::getInstance().timeStamp );
01168 handler->SetEveryNthFrame( Preferences::getInstance().every );
01169 handler->SetMaxFileSize( ( off_t ) Preferences::getInstance().maxFileSize * ( off_t ) ( 1024 * 1024 ) );
01170 handler->SetBaseName( filename );
01171
01172
01173
01174 for ( retry = MAX_RETRIES; retry > 0 && isCapturing; --retry )
01175 {
01176 frame = frameBuffer[ framePosition ];
01177
01178 if ( frame != NULL )
01179 {
01180
01181 if ( frame->IsNormalSpeed() )
01182 {
01183 reader->ResetDroppedFrames();
01184 if ( handler->WriteFrame( *frame ) == false )
01185 {
01186 delete handler;
01187 captureMutex = false;
01188 stopCapture();
01189 modal_message( _( "Failed to write to file. Is file name OK?" ) );
01190 }
01191 else
01192 {
01193 pthread_mutex_lock( &writerlock );
01194 writer = handler;
01195 pthread_mutex_unlock( &writerlock );
01196 common->setStatusBar( ( string( _( "Capturing " ) ) + handler->GetFilename() ).c_str() );
01197 }
01198 break;
01199 }
01200 }
01201 common->setStatusBar( _( "Waiting for DV %s%d ..." ),
01202 ( avc_enabled ? "" : _( "(press play on camera) " ) ), retry );
01203 while ( gtk_events_pending() )
01204 gtk_main_iteration();
01205 nanosleep( &t, NULL );
01206 }
01207 if ( retry == 0 && isCapturing )
01208 {
01209
01210 this->stopCapture();
01211 common->setStatusBar( _( "Capture failed." ) );
01212 }
01213 else if ( !isCapturing )
01214 common->setStatusBar( _( "Capture stopped." ) );
01215 }
01216 }
01217 else if ( !captureMutex )
01218 {
01219 captureMutex = true;
01220 gtk_toggle_button_set_active( recordButton, true );
01221 captureMutex = false;
01222 }
01223 }
01224
01230 void PageCapture::stopCapture()
01231 {
01232
01233 if ( !captureMutex && isCapturing )
01234 {
01235 captureMutex = true;
01236
01237 pthread_mutex_lock( &writerlock );
01238 if ( writer != NULL )
01239 {
01240 writer->Close();
01241 delete writer;
01242 writer = NULL;
01243 }
01244 pthread_mutex_unlock( &writerlock );
01245
01246 gtk_toggle_button_set_active( recordButton, false );
01247 gtk_toggle_button_set_active( stopButton, true );
01248 gtk_widget_set_sensitive( GTK_WIDGET( snapshotButton ), true );
01249 gtk_widget_set_sensitive( GTK_WIDGET( avcButton ), true );
01250
01251 audioOn = FALSE;
01252 gtk_toggle_button_set_active( this->muteButton, !audioOn );
01253
01254 if ( avc_enabled )
01255 {
01256 gtk_toggle_button_set_active( avcButton, avc_enabled );
01257 gui_state_was = -1;
01258 videoPause( );
01259 }
01260 common->setStatusBar( "" );
01261 isCapturing = false;
01262 captureMutex = false;
01263 }
01264 else if ( !captureMutex )
01265 {
01266 captureMutex = true;
01267 gtk_toggle_button_set_active( stopButton, true );
01268 captureMutex = false;
01269 }
01270
01271
01272 for ( unsigned int index = 0; index < FileTracker::GetInstance().Size(); index ++ )
01273 {
01274 char *file = FileTracker::GetInstance().Get( ( int ) index );
01275 switch ( FileTracker::GetInstance().GetMode() )
01276 {
01277 case CAPTURE_IGNORE:
01278
01279 break;
01280 case CAPTURE_FRAME_INSERT:
01281 common->loadMediaObject( file, common->g_currentFrame == -1 ? 0 : common->g_currentFrame );
01282 break;
01283 case CAPTURE_FRAME_APPEND:
01284 common->loadMediaObject( file, common->g_currentFrame + 1 );
01285 break;
01286 case CAPTURE_MOVIE_APPEND:
01287 common->loadMediaObject( file, common->getPlayList() ->GetNumFrames() );
01288 break;
01289 }
01290 common->hasListChanged = TRUE;
01291 }
01292
01293
01294 FileTracker::GetInstance().Clear();
01295
01296
01297 if ( common->hasListChanged )
01298 {
01299 GetEditorBackup()->Store( common->getPlayList() );
01300 common->setWindowTitle( );
01301 common->getPageEditor()->DrawBar( common->g_currentFrame );
01302 if ( common->g_currentFrame == -1 )
01303 common->g_currentFrame = 0;
01304 }
01305
01306 }
01307
01308
01311 void PageCapture::saveFrame()
01312 {
01313 Frame * frame = frameBuffer[ framePosition ];
01314
01315 if ( frame != NULL )
01316 {
01317 unsigned char pixels[ FRAME_MAX_WIDTH * FRAME_MAX_HEIGHT * 4 ];
01318 GError *gerror = NULL;
01319
01320 frame->ExtractPreviewRGB( pixels );
01321 GdkPixbuf *im = gdk_pixbuf_new_from_data
01322 ( pixels, GDK_COLORSPACE_RGB, FALSE, 8,
01323 frame->GetWidth(), frame->GetHeight(),
01324 frame->GetWidth() * 3, NULL, NULL );
01325
01326
01327 {
01328 int width = frame->GetWidth();
01329 if ( frame->IsWide() )
01330 width = frame->IsPAL() ? 1024 : 854;
01331 AspectRatioCalculator calc( width, frame->GetHeight(),
01332 frame->GetWidth(), frame->GetHeight(),
01333 frame->IsPAL(), frame->IsWide() );
01334 GdkPixbuf *scaled = gdk_pixbuf_scale_simple( im, calc.width, calc.height, GDK_INTERP_HYPER );
01335 g_object_unref( im );
01336 im = scaled;
01337 }
01338
01339 char *filename = common->getFileToSave( _( "Save Still Frame" ) );
01340 if ( strcmp( filename, "" ) )
01341 {
01342 const std::string FileName( filename );
01343 const std::string suffix( FileName.begin() + FileName.rfind( "." ), FileName.end() );
01344 if ( suffix == ".png" )
01345 gdk_pixbuf_save( im, filename, "png", &gerror, NULL );
01346 else
01347 gdk_pixbuf_save( im, filename, "jpeg", &gerror, "quality", "80", NULL );
01348 if ( gerror != NULL )
01349 {
01350 modal_message( gerror->message );
01351 g_error_free( gerror );
01352 }
01353 }
01354
01355 g_object_unref( im );
01356 }
01357 }
01358
01359 void PageCapture::windowMoved()
01360 {
01361 if ( frameBuffer[ framePosition ] == NULL )
01362 common->clearPreview( frameArea );
01363 else
01364 displayer->Put( *frameBuffer[ framePosition ], GTK_WIDGET( frameArea ), TRUE );
01365 }
01366
01367
01370 void PageCapture::showFrameInfo( int i )
01371 {
01372 GtkLabel *total = GTK_LABEL( lookup_widget( common->getWidget(), "position_label_total" ) );
01373 string tc;
01374 char msg[ 128 ] = "";
01375 Frame *frame = getFrame();
01376
01377 if ( isCapturing && frame )
01378 {
01379 common->getTime().setFramerate( frame->GetFrameRate() );
01380 string tc = "<span size=\"x-large\">" + common->getTime().parseFramesToString( i, common->getTimeFormat() ) + "</span>";
01381 gtk_label_set_markup( timecodeLabel, tc.c_str() );
01382 gtk_widget_set_redraw_on_allocate( GTK_WIDGET( timecodeLabel ), FALSE );
01383 snprintf( msg, 128, "%s %d", _("Dropped:"), reader->GetDroppedFrames() );
01384 gtk_label_set_markup( total, msg );
01385 }
01386 else if ( avc_enabled && common->getTimeFormat() != SMIL::Time::TIME_FORMAT_NONE )
01387 {
01388 snprintf( msg, 128, "<span size=\"x-large\">%s</span>", timecode );
01389 gtk_label_set_markup( timecodeLabel, msg );
01390 gtk_widget_set_redraw_on_allocate( GTK_WIDGET( timecodeLabel ), FALSE );
01391 gtk_label_set_markup( total, "" );
01392 }
01393 }
01394
01397 Frame* PageCapture::getFrame()
01398 {
01399 return frameBuffer[ framePosition ];
01400 }
01401
01402
01403 void PageCapture::collectFiles( )
01404 {
01405 string file;
01406
01407
01408 for ( unsigned int index = 0; index < FileTracker::GetInstance().Size(); index ++ )
01409 {
01410 file = FileTracker::GetInstance().Get( ( int ) index );
01411 if ( index == FileTracker::GetInstance().Size() - 1 )
01412 break;
01413 cerr << ">>> File " << file << " returned from tracker" << endl;
01414 switch ( FileTracker::GetInstance().GetMode() )
01415 {
01416 case CAPTURE_IGNORE:
01417
01418 break;
01419 case CAPTURE_FRAME_INSERT:
01420 common->loadMediaObject( const_cast< char* >( file.c_str() ), common->g_currentFrame == -1 ? 0 : common->g_currentFrame );
01421 break;
01422 case CAPTURE_FRAME_APPEND:
01423 common->loadMediaObject( const_cast< char* >( file.c_str() ), common->g_currentFrame + 1 );
01424 break;
01425 case CAPTURE_MOVIE_APPEND:
01426 common->loadMediaObject( const_cast< char* >( file.c_str() ), common->getPlayList() ->GetNumFrames() );
01427 break;
01428 }
01429 common->hasListChanged = TRUE;
01430 }
01431
01432
01433 FileTracker::GetInstance().Clear();
01434
01435 if ( file.length() )
01436 FileTracker::GetInstance().Add( file.c_str() );
01437
01438
01439 if ( common->hasListChanged )
01440 {
01441 gdk_threads_enter();
01442 common->getPageEditor()->DrawBar( common->g_currentFrame );
01443 gdk_threads_leave();
01444 }
01445 }
01446
01447
01448
01449
01450
01451 extern "C"
01452 {
01453
01454
01455
01456
01457 static pthread_mutex_t condition_mutex = PTHREAD_MUTEX_INITIALIZER;
01458 static pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
01459
01460 static int WaitForAction( int lastPosition )
01461 {
01462 if ( framePosition == lastPosition )
01463 {
01464 pthread_mutex_lock( &condition_mutex );
01465 pthread_cond_wait( &condition, &condition_mutex );
01466 pthread_mutex_unlock( &condition_mutex );
01467 }
01468
01469 return framePosition;
01470 }
01471
01472 static void TriggerAction( )
01473 {
01474 pthread_mutex_lock( &condition_mutex );
01475 pthread_cond_signal( &condition );
01476 pthread_mutex_unlock( &condition_mutex );
01477 }
01478
01479 static void *captureThread( void * p )
01480 {
01481 Frame * frame = NULL;
01482
01483
01484 for ( int index = 0; index < BUFFERED_FRAMES; index ++ )
01485 frameBuffer[ index ] = NULL;
01486
01487 framesCaptured = 0;
01488
01489
01490 while ( g_nav_ctl.capture_active )
01491 {
01492
01493 reader->WaitForAction( );
01494
01495
01496 frame = reader->GetFrame();
01497
01498
01499 bool critical_mass = reader->GetOutQueueSize( ) > reader->GetInQueueSize( );
01500
01501
01502 if ( frame != NULL && frameCount == BUFFERED_FRAMES )
01503 {
01504 int oldest = ( framePosition + 1 ) % BUFFERED_FRAMES;
01505 frameBuffer[ oldest ] = NULL;
01506 frameCount --;
01507 }
01508
01509
01510
01511 if ( frame != NULL && !critical_mass )
01512 {
01513
01514 int newest = ( framePosition + 1 ) % BUFFERED_FRAMES;
01515 frameBuffer[ newest ] = frame;
01516 frameCount ++;
01517 framePosition = newest;
01518 TriggerAction( );
01519 }
01520
01521
01522 if ( frame != NULL )
01523 {
01524 TimeCode tc;
01525 frame->GetTimeCode( tc );
01526 if ( frame->IsNormalSpeed() &&
01527 ! ( tc.hour == 0 && tc.min == 0 && tc.sec == 0 && tc.frame == 0 ) )
01528 {
01529
01530 if ( audioOn && !critical_mass )
01531 if ( writer == NULL || ( writer != NULL && Preferences::getInstance().preview_capture ) )
01532 displayer->PutSound( *frame );
01533
01534
01535 pthread_mutex_lock( &writerlock );
01536 if ( writer != NULL )
01537 {
01538 if ( !writer->WriteFrame( *frame ) )
01539 {
01540 pthread_mutex_unlock( &writerlock );
01541 gdk_threads_enter();
01542 common->getPageCapture() ->stopCapture();
01543 common->setStatusBar( _( "WARNING: Capture stopped. Disk full?" ) );
01544 gdk_threads_leave();
01545 }
01546 framesCaptured++;
01547 }
01548 pthread_mutex_unlock( &writerlock );
01549 }
01550
01551 reader->DoneWithFrame( frame );
01552
01553 }
01554 }
01555
01556
01557 frameCount = 0;
01558 framePosition = -1;
01559
01560 g_nav_ctl.capture_active = FALSE;
01561
01562 TriggerAction( );
01563
01564 return NULL;
01565 }
01566
01567
01568 static void *videoThread( gpointer p )
01569 {
01570 int lastPosition = -1;
01571
01572 GtkWidget *drawingarea = ( GtkWidget* ) p;
01573 prevFramesWritten = 0;
01574
01575 while ( g_nav_ctl.capture_active )
01576 {
01577 int position = WaitForAction( lastPosition );
01578
01579
01580 gdk_threads_enter();
01581
01582
01583 if ( g_nav_ctl.capture_active && position != -1 && position != lastPosition )
01584 {
01585
01586
01587
01588 if ( ( displayer != NULL && frameBuffer[ position ] != NULL ) )
01589 {
01590 if ( writer == NULL || ( writer != NULL && Preferences::getInstance().preview_capture ) )
01591 {
01592 displayer->Put( *frameBuffer[ position ], drawingarea, TRUE );
01593 }
01594 }
01595
01596
01597 lastPosition = position;
01598 }
01599
01600
01601 common->getPageCapture() ->applyAVCState( avcStatus );
01602 common->getPageCapture()->showFrameInfo( framesCaptured );
01603
01604 gdk_flush();
01605 gdk_threads_leave();
01606
01607 pthread_mutex_lock( &writerlock );
01608 if ( writer )
01609 {
01610 int framesWritten = writer->GetFramesWritten();
01611 string filename = writer->GetFilename();
01612 pthread_mutex_unlock( &writerlock );
01613
01614 if ( framesWritten < prevFramesWritten )
01615 {
01616 gdk_threads_enter();
01617 common->setStatusBar( ( string( _( "Capturing " ) ) + filename ).c_str() );
01618 gdk_threads_leave();
01619 common->getPageCapture()->collectFiles();
01620 }
01621 prevFramesWritten = framesWritten;
01622 }
01623 else
01624 {
01625 pthread_mutex_unlock( &writerlock );
01626 }
01627
01628
01629 struct timespec t = { 0, 0 };
01630 nanosleep( &t, NULL );
01631 }
01632
01633 return NULL;
01634 }
01635
01636 static void *avcThread( gpointer p )
01637 {
01638 while ( g_nav_ctl.capture_active )
01639 {
01640
01641 common->getPageCapture() ->CheckDevices( );
01642
01643
01644 struct timespec t =
01645 {
01646 0, ( unsigned long ) Preferences::getInstance().avcPollIntervalMs
01647 * 1000000UL
01648 };
01649 nanosleep( &t, NULL );
01650 }
01651
01652 return NULL;
01653 }
01654
01655 void
01656 on_capture_page_record_button_clicked ( GtkButton * button,
01657 gpointer user_data )
01658 {
01659 startCapture();
01660 }
01661
01662
01663 void
01664 on_capture_page_stop_button_clicked ( GtkButton * button,
01665 gpointer user_data )
01666 {
01667 stopCapture();
01668 }
01669
01670 void
01671 on_capture_page_snapshot_button_clicked ( GtkButton * button,
01672 gpointer user_data )
01673 {
01674 saveFrame();
01675 }
01676
01677 gboolean
01678 on_entry_capture_file_focus_in_event (GtkWidget *widget,
01679 GdkEventFocus *event,
01680 gpointer user_data)
01681 {
01682 gtk_entry_set_editable( GTK_ENTRY( widget ), TRUE );
01683 g_nav_ctl.escaped = TRUE;
01684 return FALSE;
01685 }
01686
01687
01688 gboolean
01689 on_entry_capture_file_focus_out_event (GtkWidget *widget,
01690 GdkEventFocus *event,
01691 gpointer user_data)
01692 {
01693 gtk_entry_set_editable( GTK_ENTRY( widget ), FALSE );
01694 g_nav_ctl.escaped = FALSE;
01695 return FALSE;
01696 }
01697
01698
01699 void
01700 on_capture_file_button_clicked (GtkButton *button,
01701 gpointer user_data)
01702 {
01703 g_nav_ctl.escaped = TRUE;
01704 gtk_entry_set_editable( GTK_ENTRY( lookup_widget( GTK_WIDGET( button ), "entry_capture_file" ) ), TRUE );
01705 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "entry_capture_file" ) );
01706 const char *filename = common->getFileToSave( _("Choose a DV file") );
01707 if ( strcmp( filename, "" ) )
01708 gtk_entry_set_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( button ), "entry_capture_file" ) ), filename );
01709 }
01710
01711 void
01712 on_entry_capture_file_grab_focus ( GtkWidget * widget,
01713 gpointer user_data )
01714 {
01715 gtk_entry_set_editable( GTK_ENTRY( widget ), TRUE );
01716 g_nav_ctl.escaped = TRUE;
01717 }
01718
01719
01720 static bool buttonGuard = true;
01721 void
01722 on_capture_page_button_pressed ( GtkButton * button,
01723 gpointer user_data )
01724 {
01725 buttonGuard = false;
01726 }
01727
01728
01729 void
01730 on_capture_page_button_released ( GtkButton * button,
01731 gpointer user_data )
01732 {
01733 buttonGuard = true;
01734 }
01735
01736
01737 void
01738 on_capture_page_mute_button_toggled ( GtkToggleButton * togglebutton,
01739 gpointer user_data )
01740 {
01741 if ( ! buttonGuard )
01742 {
01743 audioOn = ! audioOn;
01744 buttonGuard = true;
01745 gtk_toggle_button_set_active( togglebutton, !audioOn );
01746 }
01747 }
01748
01749 void
01750 on_capture_page_avc_button_clicked( GtkButton *button,
01751 gpointer user_data)
01752 {
01753 avcStatus = !avcStatus;
01754 Preferences::getInstance().enableAVC = common->getPageCapture( ) ->avc_enabled = !common->getPageCapture( ) ->avc_enabled;
01755 std::cerr << ">> AV/C " << ( common->getPageCapture( ) ->avc_enabled ? _( "Enabled" ) : _( "Disabled" ) ) << std::endl;
01756 TriggerAction( );
01757 }
01758 }