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 <sys/time.h>
00029 #include <sys/types.h>
00030 #include <dirent.h>
00031 #include <pthread.h>
00032
00033 #include "page_trim.h"
00034 #include "avi.h"
00035 #include "error.h"
00036 #include "message.h"
00037 #include "filehandler.h"
00038 #include "frame.h"
00039 #include "commands.h"
00040 #include "page_editor.h"
00041 #include "ieee1394io.h"
00042
00043 #undef PLAY_WITH_STATS
00044
00045 #define TRIM_ADJ_POS 0
00046 #define TRIM_ADJ_IN 1
00047 #define TRIM_ADJ_OUT 2
00048
00049 extern "C"
00050 {
00051 #include "support.h"
00052
00053 extern KinoCommon *common;
00054 extern struct navigate_control g_nav_ctl;
00055 extern char cmd[];
00056 static char lastcmd[ 256 ] = { 0 };
00057 static int _getOneSecond( void );
00058
00059 static void resetThreads( );
00060 static void *readThread( void * info );
00061 static void *videoThread( void * info );
00062 static void *audioThread( void * info );
00063 static pthread_t readthreadTrim;
00064 static pthread_t audiothreadTrim;
00065 static pthread_t videothreadTrim;
00066 static pthread_mutex_t threadlock = PTHREAD_MUTEX_INITIALIZER;
00067 static pthread_mutex_t readlock = PTHREAD_MUTEX_INITIALIZER;
00068 static GtkAdjustment *trim_adj[ 3 ];
00069 static gboolean skipPosUpdate = FALSE;
00070 static GtkSpinButton *spin_in;
00071 static GtkSpinButton *spin_out;
00072 static GtkToggleButton *link_toggle;
00073 static GtkToggleButton *loop_toggle;
00074 static gboolean doScrub = false;
00075 static int newFrame = 0;
00076 static int lastFrame = -1;
00077
00078 #define PLAYBACK_FRAMES 50
00079
00080 static Frame *frameContent[ PLAYBACK_FRAMES ];
00081 extern IEEE1394Writer *writer1394;
00082
00083
00084 gboolean
00085 on_trim_value_changed_event ( GtkWidget * widget,
00086 GdkEventButton * event,
00087 gpointer user_data )
00088 {
00089 int value = ( int ) GTK_ADJUSTMENT( widget ) ->value;
00090 if ( GTK_ADJUSTMENT( widget ) == trim_adj[ TRIM_ADJ_IN ] )
00091 {
00092 int diff = common->getPageTrim() ->getOutPoint() - common->getPageTrim() ->getInPoint() + value;
00093
00094 if ( gtk_toggle_button_get_active( link_toggle ) == TRUE && skipPosUpdate == FALSE )
00095 {
00096 if ( diff <= common->getPageTrim() ->getTotalFrames() )
00097 {
00098 if ( value >= common->getPageTrim() ->getOutPoint() )
00099 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], value );
00100 else
00101 common->getPageTrim() ->setInPoint( value );
00102
00103 skipPosUpdate = TRUE;
00104 gtk_spin_button_set_value( spin_out, ( gfloat ) diff );
00105 skipPosUpdate = TRUE;
00106 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], diff );
00107 }
00108 else
00109 {
00110 skipPosUpdate = TRUE;
00111 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], common->getPageTrim() ->getInPoint() );
00112 }
00113 }
00114 else
00115 {
00116 if ( value > common->getPageTrim() ->getOutPoint() )
00117 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], value );
00118 common->getPageTrim() ->setInPoint( value );
00119 }
00120 skipPosUpdate = TRUE;
00121 common->getPageTrim() ->movedToFrame( value );
00122 gtk_spin_button_set_value( spin_in, ( gfloat ) value );
00123
00124 }
00125 else if ( GTK_ADJUSTMENT( widget ) == trim_adj[ TRIM_ADJ_OUT ] )
00126 {
00127 int diff = common->getPageTrim() ->getInPoint() - common->getPageTrim() ->getOutPoint() + value;
00128
00129 if ( gtk_toggle_button_get_active( link_toggle ) == TRUE && skipPosUpdate == FALSE )
00130 {
00131 if ( diff >= 0 )
00132 {
00133 if ( value <= common->getPageTrim() ->getInPoint() )
00134 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], value - 1 );
00135 common->getPageTrim() ->setOutPoint( value );
00136
00137 skipPosUpdate = TRUE;
00138 gtk_spin_button_set_value( spin_in, ( gfloat ) diff );
00139 skipPosUpdate = TRUE;
00140 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], diff );
00141 }
00142 else
00143 {
00144 skipPosUpdate = TRUE;
00145 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], common->getPageTrim() ->getOutPoint() );
00146 }
00147 }
00148 else
00149 {
00150 if ( value < common->getPageTrim() ->getInPoint() )
00151 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], value );
00152 common->getPageTrim() ->setOutPoint( value );
00153 }
00154 skipPosUpdate = TRUE;
00155 common->getPageTrim() ->movedToFrame( value );
00156 gtk_spin_button_set_value( spin_out, ( gfloat ) value );
00157
00158 }
00159 else if ( skipPosUpdate == FALSE )
00160 {
00161 skipPosUpdate = TRUE;
00162 common->getPageTrim() ->movedToFrame( value );
00163 }
00164 skipPosUpdate = FALSE;
00165 return FALSE;
00166 }
00167
00168 void
00169 on_spinbutton_trim_in_value_changed ( GtkSpinButton * spinbutton,
00170 gpointer user_data )
00171 {
00172 if ( strcmp( gtk_entry_get_text( GTK_ENTRY( spin_in ) ), "" ) )
00173 {
00174 int value = atoi( gtk_entry_get_text( GTK_ENTRY( spin_in ) ) );
00175 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], value );
00176 }
00177 gtk_entry_set_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( spinbutton ), "entry_trim_in" ) ),
00178 common->getTime().parseFramesToString( ( int )gtk_spin_button_get_value( spinbutton ),
00179 common->getTimeFormat() ).c_str() );
00180 }
00181
00182 void
00183 on_spinbutton_trim_out_value_changed ( GtkSpinButton * spinbutton,
00184 gpointer user_data )
00185 {
00186 if ( strcmp( gtk_entry_get_text( GTK_ENTRY( spin_out ) ), "" ) )
00187 {
00188 int value = atoi( gtk_entry_get_text( GTK_ENTRY( spin_out ) ) );
00189 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], value );
00190 }
00191 gtk_entry_set_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( spinbutton ), "entry_trim_out" ) ),
00192 common->getTime().parseFramesToString( ( int )gtk_spin_button_get_value( spinbutton ),
00193 common->getTimeFormat() ).c_str() );
00194 }
00195
00196 void
00197 on_button_trim_in_reset_clicked ( GtkButton * button,
00198 gpointer user_data )
00199 {
00200 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00201 common->getPageTrim() ->resetInPoint();
00202 }
00203
00204 void
00205 on_button_trim_out_reset_clicked ( GtkButton * button,
00206 gpointer user_data )
00207 {
00208 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00209 common->getPageTrim() ->resetOutPoint();
00210 }
00211
00212 void
00213 on_button_trim_in_set_clicked ( GtkButton * button,
00214 gpointer user_data )
00215 {
00216 int value = common->getPageTrim() ->getPosition();
00217 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00218 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], value );
00219 }
00220
00221 void
00222 on_button_trim_out_set_clicked ( GtkButton * button,
00223 gpointer user_data )
00224 {
00225 int value = common->getPageTrim() ->getPosition();
00226 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00227 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], value );
00228 }
00229
00230 void
00231 on_togglebutton_trim_link_toggled ( GtkToggleButton * togglebutton,
00232 gpointer user_data )
00233 {
00234 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( togglebutton ), "eventbox_trim" ) );
00235 GtkImage *image = GTK_IMAGE( lookup_widget( GTK_WIDGET( togglebutton ), "pixmap_trim_link" ) );
00236 if ( gtk_toggle_button_get_active( togglebutton ) )
00237 gtk_image_set_from_file( image, DATADIR "/kino/link.xpm" );
00238 else
00239 gtk_image_set_from_file( image, DATADIR "/kino/link_off.xpm" );
00240 }
00241
00242 gboolean
00243 on_spinbutton_trim_in_focus_in_event ( GtkWidget * widget,
00244 GdkEventFocus * event,
00245 gpointer user_data )
00246 {
00247 g_nav_ctl.escaped = TRUE;
00248 return FALSE;
00249 }
00250
00251 gboolean
00252 on_spinbutton_trim_in_focus_out_event ( GtkWidget * widget,
00253 GdkEventFocus * event,
00254 gpointer user_data )
00255 {
00256 g_nav_ctl.escaped = FALSE;
00257 return FALSE;
00258 }
00259
00260 gboolean
00261 on_spinbutton_trim_out_focus_in_event ( GtkWidget * widget,
00262 GdkEventFocus * event,
00263 gpointer user_data )
00264 {
00265 g_nav_ctl.escaped = TRUE;
00266 return FALSE;
00267 }
00268
00269
00270 gboolean
00271 on_spinbutton_trim_out_focus_out_event ( GtkWidget * widget,
00272 GdkEventFocus * event,
00273 gpointer user_data )
00274 {
00275 g_nav_ctl.escaped = FALSE;
00276 return FALSE;
00277 }
00278
00279 gboolean
00280 on_trim_button_press_event ( GtkWidget * widget,
00281 GdkEventButton * event,
00282 gpointer user_data )
00283 {
00284 doScrub = TRUE;
00285 videoPause();
00286 return FALSE;
00287 }
00288
00289
00290 gboolean
00291 on_trim_button_release_event ( GtkWidget * widget,
00292 GdkEventButton * event,
00293 gpointer user_data )
00294 {
00295 doScrub = FALSE;
00296 return FALSE;
00297 }
00298
00299
00300
00301 gboolean
00302 on_combo_trim_clip_entry_focus_in_event( GtkWidget *widget,
00303 GdkEventFocus *event,
00304 gpointer user_data)
00305 {
00306 g_nav_ctl.escaped = TRUE;
00307 return FALSE;
00308 }
00309
00310 gboolean
00311 on_combo_trim_clip_entry_focus_out_event( GtkWidget *widget,
00312 GdkEventFocus *event,
00313 gpointer user_data)
00314 {
00315 g_nav_ctl.escaped = FALSE;
00316 const gchar* filename = gtk_entry_get_text( GTK_ENTRY( widget ) );
00317 if ( strlen( filename ) )
00318 {
00319 switch ( common->checkFile( ( char* ) filename ) )
00320 {
00321 case AVI:
00322 case RAW_DV:
00323 case QT:
00324 if ( common->getPageTrim()->loadFile( filename ) )
00325 common->getPageTrim()->movedToFrame( common->getPageTrim()->getInPoint() );
00326 break;
00327 default:
00328
00329
00330 break;
00331 }
00332 }
00333 return FALSE;
00334 }
00335
00336 void
00337 on_combo_trim_clip_entry_changed( GtkEditable *editable,
00338 gpointer user_data)
00339 {
00340 if ( g_nav_ctl.escaped == FALSE )
00341 {
00342 const gchar* filename = gtk_entry_get_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( editable ), "entry_trim_clip" ) ) );
00343 if ( strlen( filename ) )
00344 {
00345 switch ( common->checkFile( ( char* ) filename ) )
00346 {
00347 case AVI:
00348 case RAW_DV:
00349 case QT:
00350 if ( common->getPageTrim()->loadFile( filename ) )
00351 {
00352 common->getPageTrim()->movedToFrame( common->getPageTrim()->getInPoint() );
00353 break;
00354 }
00355 default:
00356 {
00357 const std::string& importedFile = common->importFile( filename );
00358 if ( common->getPageTrim()->loadFile( const_cast<char*>( importedFile.c_str() ) ) )
00359 {
00360 gtk_entry_set_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( editable ), "entry_trim_clip" ) ), const_cast<char*>( importedFile.c_str() ) );
00361 common->getPageTrim()->movedToFrame( common->getPageTrim()->getInPoint() );
00362 }
00363 else
00364 {
00365 gtk_entry_set_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( editable ), "entry_trim_clip" ) ), "" );
00366 }
00367 break;
00368 }
00369
00370
00371
00372 }
00373 }
00374 }
00375 }
00376
00377 void
00378 on_button_trim_open_clicked( GtkButton *button,
00379 gpointer user_data)
00380 {
00381 char *filename = common->getFileToOpen( _("Choose a DV file") );
00382 if ( filename && strcmp( filename, "" ) )
00383 {
00384 gtk_entry_set_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( button ), "entry_trim_clip" ) ),
00385 filename );
00386 }
00387 }
00388
00389 void
00390 on_button_trim_insert_before_clicked( GtkButton *button,
00391 gpointer user_data)
00392 {
00393 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00394 common->getPageTrim()->insertScene( TRIM_INSERT_MODE_BEFORE );
00395 }
00396
00397 void
00398 on_button_trim_insert_after_clicked( GtkButton *button,
00399 gpointer user_data)
00400 {
00401 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00402 common->getPageTrim()->insertScene( TRIM_INSERT_MODE_AFTER );
00403 }
00404
00405 void
00406 on_menuitem_trim_update_activate( GtkMenuItem *menuitem,
00407 gpointer user_data)
00408 {
00409 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( menuitem ), "eventbox_trim" ) );
00410 common->getPageTrim()->setMode( PAGE_TRIM_MODE_UPDATE );
00411 }
00412
00413 void
00414 on_menuitem_trim_insert_activate( GtkMenuItem *menuitem,
00415 gpointer user_data)
00416 {
00417 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( menuitem ), "eventbox_trim" ) );
00418 common->getPageTrim()->setMode( PAGE_TRIM_MODE_INSERT );
00419 }
00420
00421 void
00422 on_button_trim_apply_clicked( GtkButton *button,
00423 gpointer user_data)
00424 {
00425 gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00426 processCommand( "Enter" );
00427 }
00428
00429 void
00430 on_entry_trim_in_activate (GtkEntry *entry,
00431 gpointer user_data)
00432 {
00433 common->getTime().parseValueToString( gtk_entry_get_text( entry ), common->getTimeFormat() );
00434 GtkSpinButton *spinbutton = GTK_SPIN_BUTTON( lookup_widget( GTK_WIDGET( entry ), "spinbutton_trim_in" ) );
00435 gtk_spin_button_set_value( spinbutton, common->getTime().getFrames() );
00436 on_spinbutton_trim_in_value_changed( spinbutton, NULL );
00437 }
00438
00439 gboolean
00440 on_entry_trim_in_focus_out_event (GtkWidget *widget,
00441 GdkEventFocus *event,
00442 gpointer user_data)
00443 {
00444 on_entry_trim_in_activate( GTK_ENTRY( widget ), NULL );
00445 g_nav_ctl.escaped = FALSE;
00446 return FALSE;
00447 }
00448
00449 void
00450 on_entry_trim_out_activate (GtkEntry *entry,
00451 gpointer user_data)
00452 {
00453 common->getTime().parseValueToString( gtk_entry_get_text( entry ), common->getTimeFormat() );
00454 GtkSpinButton *spinbutton = GTK_SPIN_BUTTON( lookup_widget( GTK_WIDGET( entry ), "spinbutton_trim_out" ) );
00455 gtk_spin_button_set_value( spinbutton, common->getTime().getFrames() );
00456 on_spinbutton_trim_out_value_changed( spinbutton, NULL );
00457 }
00458
00459 gboolean
00460 on_entry_trim_out_focus_out_event (GtkWidget *widget,
00461 GdkEventFocus *event,
00462 gpointer user_data)
00463 {
00464 on_entry_trim_out_activate( GTK_ENTRY( widget ), NULL );
00465 g_nav_ctl.escaped = FALSE;
00466 return FALSE;
00467 }
00468
00469 }
00470
00475 GArray *scenes = NULL;
00476 PageTrim::PageTrim( KinoCommon *common ) :
00477 start_orig( 0 ), update_start(0), end_orig( 0 ), in_orig( 0 ), out_orig( 0 ), in( 0 ), out( 0 ),
00478 max( 0 ), pos( -1 ), currentScene( 0 ), lastPos( -1 ), mode( PAGE_TRIM_MODE_UNKNOWN ),
00479 changed( false )
00480 {
00481 cerr << "> Creating page trim" << endl;
00482 this->common = common;
00483 this->frameArea = GTK_DRAWING_AREA( lookup_widget( common->getWidget(), "drawingarea_trim" ) );
00484 gtk_widget_set_double_buffered( GTK_WIDGET( frameArea ), FALSE );
00485 this->positionLabelCurrent = GTK_LABEL( lookup_widget( common->getWidget(), "position_label_current" ) );
00486 this->positionLabelTotal = GTK_LABEL( lookup_widget( common->getWidget(), "position_label_total" ) );
00487 spin_in = GTK_SPIN_BUTTON( lookup_widget( common->getWidget(), "spinbutton_trim_in" ) );
00488 spin_out = GTK_SPIN_BUTTON( lookup_widget( common->getWidget(), "spinbutton_trim_out" ) );
00489 link_toggle = GTK_TOGGLE_BUTTON( lookup_widget( common->getWidget(), "togglebutton_trim_link" ) );
00490 loop_toggle = GTK_TOGGLE_BUTTON( lookup_widget( common->getWidget(), "togglebutton_trim_loop" ) );
00491
00492 this->g_copiedPlayList = new PlayList();
00493
00494
00495 trim_adj[ TRIM_ADJ_POS ] = GTK_ADJUSTMENT(
00496 gtk_adjustment_new( 0, 0, 0, 1, 10, 0 ) );
00497 trim_adj[ TRIM_ADJ_IN ] = GTK_ADJUSTMENT(
00498 gtk_adjustment_new( 0, 0, 0, 1, 10, 0 ) );
00499 trim_adj[ TRIM_ADJ_OUT ] = GTK_ADJUSTMENT(
00500 gtk_adjustment_new( 0, 0, 0, 1, 10, 0 ) );
00501 for ( int i = 0; i < 3; i++ )
00502 g_signal_connect ( G_OBJECT ( trim_adj[ i ] ), "value_changed",
00503 G_CALLBACK( on_trim_value_changed_event ), ( gpointer ) i );
00504 trim = gtk_enhanced_scale_new( ( GtkObject** ) trim_adj, 3 );
00505 gtk_widget_set_name ( trim, "trim" );
00506 gtk_widget_ref( trim );
00507 gtk_object_set_data_full ( GTK_OBJECT( common->getWidget() ), "trim", trim,
00508 ( GtkDestroyNotify ) gtk_widget_unref );
00509 GtkWidget *vbox_trim = lookup_widget( common->getWidget(), "vbox_trim_custom" );
00510 gtk_widget_show( trim );
00511 gtk_box_pack_start( GTK_BOX ( vbox_trim ), trim, FALSE, TRUE, 0 );
00512 g_signal_connect( G_OBJECT( trim ), "button_press_event",
00513 G_CALLBACK( on_trim_button_press_event ), NULL );
00514 g_signal_connect( G_OBJECT( trim ), "button_release_event",
00515 G_CALLBACK( on_trim_button_release_event ), NULL );
00516 }
00517
00521 PageTrim::~PageTrim( )
00522 {
00523 cerr << "> Destroying page trim" << endl;
00524 delete this->g_copiedPlayList;
00525 }
00526
00530 void PageTrim::newFile()
00531 {
00532 this->stopNavigator();
00533 }
00534
00538 void PageTrim::start()
00539 {
00540 cerr << ">> Starting Trimmer" << endl;
00541
00542 start_orig = update_start = end_orig = in = in_orig = out = out_orig = max = 0;
00543
00544 for ( int i = 0; i < PLAYBACK_FRAMES; i ++ )
00545 frameContent[ i ] = GetFramePool( ) ->GetFrame( );
00546
00547 this->displayer = new FrameDisplayer();
00548 if ( Preferences::getInstance().dv1394Preview )
00549 {
00550 #ifdef HAVE_IEC61883
00551 AVC avc;
00552 Preferences::getInstance( ).phyID = avc.getNodeId( Preferences::getInstance( ).avcGUID );
00553 Preferences::getInstance( ).phyID = avc.isPhyIDValid( Preferences::getInstance( ).phyID );
00554 if ( !writer1394 )
00555 writer1394 = new iec61883Writer(
00556 ( avc.getPort() < 0 ) ? 0 : avc.getPort(),
00557 Preferences::getInstance().channel,
00558 2 );
00559 #endif
00560 #ifdef HAVE_DV1394
00561 if ( Preferences::getInstance().dvExportDevice > 0 && !writer1394 )
00562 writer1394 = new dv1394Writer(
00563 Preferences::getInstance().dvExportDevice,
00564 Preferences::getInstance().channel,
00565 2,
00566 Preferences::getInstance().cip_n,
00567 Preferences::getInstance().cip_d,
00568 Preferences::getInstance().syt_offset );
00569 #endif
00570 }
00571
00572 if ( ! Preferences::getInstance().trimModeInsert && common->g_currentFrame > -1 )
00573 setMode( PAGE_TRIM_MODE_UPDATE );
00574 else
00575 setMode( PAGE_TRIM_MODE_INSERT );
00576
00577 if ( common->getPlayList() ->GetNumFrames() > 0 )
00578 {
00579
00580 loadScene( common->g_currentFrame );
00581 lastPos = pos = in + common->g_currentFrame - start_orig;
00582 movedToFrame( pos );
00583
00584
00585 GList *items = NULL;
00586 map<string, FileHandler*>::iterator n;
00587 for ( n = GetFileMap()->GetMap().begin(); n != GetFileMap()->GetMap().end(); ++n )
00588 items = g_list_append( items, ( void* ) n->first.c_str() );
00589 g_nav_ctl.escaped = TRUE;
00590 gtk_combo_set_popdown_strings( GTK_COMBO( lookup_widget( common->getWidget(), "combo_trim_clip" ) ), items);
00591 gtk_entry_set_text( GTK_ENTRY( lookup_widget( common->getWidget(), "entry_trim_clip" ) ), "" );
00592 g_nav_ctl.escaped = FALSE;
00593 }
00594
00595 gtk_widget_grab_focus( GTK_WIDGET( frameArea ) );
00596 common->packIt( "packer_trim", "packer_trim_outer" );
00597
00598 gtk_notebook_set_page( GTK_NOTEBOOK( lookup_widget( common->getWidget(), "notebook_keyhelp" ) ), 2 );
00599 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( lookup_widget( common->getWidget(), "menuitem_trim" ) ), TRUE );
00600 }
00601
00605 gulong PageTrim::activate()
00606 {
00607 return EDIT_MENU |
00608 SCENE_LIST |
00609 VIDEO_START_OF_MOVIE |
00610 VIDEO_START_OF_SCENE |
00611 VIDEO_REWIND |
00612 VIDEO_BACK |
00613 VIDEO_PLAY |
00614 VIDEO_PAUSE |
00615 VIDEO_STOP |
00616 VIDEO_FORWARD |
00617 VIDEO_FAST_FORWARD |
00618 VIDEO_NEXT_SCENE |
00619 VIDEO_END_OF_MOVIE |
00620 VIDEO_SHUTTLE |
00621 INFO_FRAME;
00622 }
00623
00627 void PageTrim::clean()
00628 {
00629 cerr << ">> Leaving Trimmer" << endl;
00630 stopNavigator();
00631 delete displayer;
00632 displayer = 0;
00633 delete writer1394;
00634 writer1394 = NULL;
00635 saveScene();
00636 for ( int i = 0; i < PLAYBACK_FRAMES; i ++ )
00637 GetFramePool( ) ->DoneWithFrame( frameContent[ i ] );
00638
00639 cerr << ">> Left Trimmer" << endl;
00640 }
00641
00642
00647 void PageTrim::loadScene( int newScene )
00648 {
00649 char value[ 20 ];
00650 PlayList newPlayList;
00651 playlist = newPlayList;
00652 PlayList *pl = common->getPlayList();
00653 FileHandler *media;
00654
00655 currentScene = newScene;
00656
00657
00658
00659 update_start = start_orig = pl->FindStartOfScene( currentScene );
00660 end_orig = pl->FindEndOfScene( currentScene );
00661
00662
00663
00664 pl->GetPlayList( start_orig, end_orig, playlist );
00665
00666
00667
00668 in = in_orig = lastPos = pos = pl->GetClipBegin( currentScene );
00669
00670
00671 playlist.SetClipBegin( 0, "0" );
00672
00673
00674 playlist.GetMediaObject( playlist.FindEndOfScene( 0 ), &media );
00675
00676
00677
00678
00679 int prevClipEnd = playlist.GetClipEnd( playlist.GetNumFrames() - 1 );
00680 int newClipEnd = media->GetTotalFrames() - 1;
00681 snprintf( value, 19, "%i", newClipEnd );
00682 playlist.SetClipEnd( playlist.GetNumFrames() - 1, value );
00683
00684
00685 max = playlist.GetNumFrames() - 1;
00686
00687
00688
00689 out = out_orig = max - ( newClipEnd - prevClipEnd );
00690
00691
00692 common->setCurrentScene( start_orig );
00693
00694
00695 trim_adj[ TRIM_ADJ_IN ] ->upper = max;
00696 trim_adj[ TRIM_ADJ_IN ] ->value = in;
00697 g_signal_emit_by_name( trim_adj[ TRIM_ADJ_IN ], "changed" );
00698 trim_adj[ TRIM_ADJ_OUT ] ->upper = max;
00699 trim_adj[ TRIM_ADJ_OUT ] ->value = out;
00700 g_signal_emit_by_name( trim_adj[ TRIM_ADJ_OUT ], "changed" );
00701 trim_adj[ TRIM_ADJ_POS ] ->upper = max;
00702 g_signal_emit_by_name( trim_adj[ TRIM_ADJ_POS ], "changed" );
00703
00704
00705 GtkAdjustment *adjust = gtk_spin_button_get_adjustment( spin_in );
00706 adjust->lower = 0;
00707 adjust->upper = max;
00708 adjust->value = in;
00709 g_signal_emit_by_name( adjust, "changed" );
00710 gtk_spin_button_set_value( spin_in, ( gfloat ) in );
00711
00712 adjust = gtk_spin_button_get_adjustment( spin_out );
00713 adjust->lower = 0;
00714 adjust->upper = max;
00715 adjust->value = out;
00716 g_signal_emit_by_name( adjust, "changed" );
00717 gtk_spin_button_set_value( spin_out, ( gfloat ) out );
00718
00719 g_nav_ctl.escaped = TRUE;
00720 gtk_entry_set_text( GTK_ENTRY( lookup_widget( common->getWidget(), "entry_trim_clip" ) ), "" );
00721 g_nav_ctl.escaped = FALSE;
00722
00723 timeFormatChanged();
00724 }
00725
00726
00729 void PageTrim::saveScene()
00730 {
00731 if ( playlist.GetNumFrames() && ( in_orig != in || out_orig != out || changed ) )
00732 {
00733
00734 playlist.Delete( out + 1, max );
00735
00736 playlist.Delete( 0, in - 1 );
00737
00738 common->getPlayList() ->Delete( start_orig, end_orig );
00739
00740
00741 common->getPlayList() ->InsertPlayList( playlist, start_orig );
00742
00743 changed = false;
00744
00745
00746 GetEditorBackup() ->Store( common->getPlayList() );
00747
00748
00749 common->hasListChanged = TRUE;
00750 common->setWindowTitle( );
00751 common->getPageEditor()->DrawBar( common->g_currentFrame );
00752
00753
00754 GList *items = NULL;
00755 map<string, FileHandler*>::iterator n;
00756 for ( n = GetFileMap()->GetMap().begin(); n != GetFileMap()->GetMap().end(); ++n )
00757 items = g_list_append( items, ( void* ) n->first.c_str() );
00758 g_nav_ctl.escaped = TRUE;
00759 gtk_combo_set_popdown_strings( GTK_COMBO( lookup_widget( common->getWidget(), "combo_trim_clip" ) ), items);
00760 g_nav_ctl.escaped = FALSE;
00761 }
00762 }
00763
00764
00770 bool PageTrim::loadFile( const string& filename )
00771 {
00772 PlayList newList;
00773 bool result = true;
00774
00775 try
00776 {
00777 if ( newList.LoadMediaObject( const_cast< char* >( filename.c_str() ) ) )
00778 {
00779 playlist = newList;
00780 start_orig = common->getPlayList()->FindStartOfScene( currentScene );
00781 end_orig = common->getPlayList()->FindEndOfScene( currentScene );
00782 in = in_orig = lastPos = pos = 0;
00783 out = out_orig = max = playlist.GetNumFrames() - 1;
00784 changed = true;
00785
00786 trim_adj[ TRIM_ADJ_IN ] ->upper = max;
00787 trim_adj[ TRIM_ADJ_IN ] ->value = in;
00788 g_signal_emit_by_name( trim_adj[ TRIM_ADJ_IN ], "changed" );
00789 trim_adj[ TRIM_ADJ_OUT ] ->upper = max;
00790 trim_adj[ TRIM_ADJ_OUT ] ->value = out;
00791 g_signal_emit_by_name( trim_adj[ TRIM_ADJ_OUT ], "changed" );
00792 trim_adj[ TRIM_ADJ_POS ] ->upper = max;
00793 g_signal_emit_by_name( trim_adj[ TRIM_ADJ_POS ], "changed" );
00794
00795 GtkAdjustment *adjust = gtk_spin_button_get_adjustment( spin_in );
00796 adjust->lower = 0;
00797 adjust->upper = max;
00798 adjust->value = in;
00799 g_signal_emit_by_name( adjust, "changed" );
00800 gtk_spin_button_set_value( spin_in, ( gfloat ) in );
00801
00802 adjust = gtk_spin_button_get_adjustment( spin_out );
00803 adjust->lower = 0;
00804 adjust->upper = max;
00805 adjust->value = out;
00806 g_signal_emit_by_name( adjust, "changed" );
00807 gtk_spin_button_set_value( spin_out, ( gfloat ) out );
00808
00809 timeFormatChanged();
00810 }
00811 else
00812 {
00813
00814
00815 result = false;
00816 }
00817 }
00818 catch ( string s )
00819 {
00820 cerr << "Could not load file " << filename << ", because an exception has occurred: " << endl;
00821 cerr << s << endl;
00822 result = false;
00823 }
00824
00825 return result;
00826 }
00827
00828
00834 void PageTrim::insertScene( TrimInsertMode insertMode )
00835 {
00836 if ( playlist.GetNumFrames() > 0 )
00837 {
00838 int i = getSceneIndex();
00839
00840 if ( insertMode == TRIM_INSERT_MODE_BEFORE )
00841 {
00842 PlayList tmp;
00843 tmp = playlist;
00844 tmp.Delete( out + 1, max );
00845 tmp.Delete( 0, in - 1 );
00846 common->getPlayList()->InsertPlayList( tmp, start_orig );
00847 }
00848 else if ( insertMode == TRIM_INSERT_MODE_AFTER )
00849 {
00850 PlayList tmp;
00851 tmp = playlist;
00852 tmp.Delete( out + 1, max );
00853 tmp.Delete( 0, in - 1 );
00854 common->getPlayList()->InsertPlayList( tmp, end_orig + 1 );
00855 i++;
00856 }
00857 GetEditorBackup()->Store( common->getPlayList() );
00858 common->hasListChanged = TRUE;
00859 common->setWindowTitle( );
00860 common->getPageEditor()->DrawBar( common->g_currentFrame );
00861 selectScene( i );
00862 common->setCurrentScene( start_orig );
00863
00864
00865 GList *items = NULL;
00866 const char *filename = gtk_entry_get_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( common->getWidget() ), "entry_trim_clip" ) ) );
00867 map<string, FileHandler*>::iterator n;
00868 items = g_list_append( items, ( void* ) filename );
00869 for ( n = GetFileMap()->GetMap().begin(); n != GetFileMap()->GetMap().end(); ++n )
00870 if ( strcmp( n->first.c_str(), filename ) )
00871 items = g_list_append( items, ( void* ) n->first.c_str() );
00872 g_nav_ctl.escaped = TRUE;
00873 gtk_combo_set_popdown_strings( GTK_COMBO( lookup_widget( common->getWidget(), "combo_trim_clip" ) ), items);
00874 g_nav_ctl.escaped = FALSE;
00875 }
00876 }
00877
00878
00879 void PageTrim::setMode( PageTrimMode newMode )
00880 {
00881 if ( newMode != mode )
00882 {
00883 if ( newMode == PAGE_TRIM_MODE_UPDATE && common->getPlayList()->GetNumFrames() > 0 )
00884 {
00885 mode = newMode;
00886 gtk_widget_show( lookup_widget( common->getWidget(), "hbox_trim_update" ) );
00887 gtk_widget_hide( lookup_widget( common->getWidget(), "hbox_trim_insert" ) );
00888
00889
00890 gfloat saved_in = in;
00891 gfloat saved_out = out;
00892 loadScene( update_start );
00893 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], saved_in );
00894 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], saved_out );
00895 }
00896 else if ( newMode == PAGE_TRIM_MODE_INSERT )
00897 {
00898 mode = newMode;
00899 gtk_widget_hide( lookup_widget( common->getWidget(), "hbox_trim_update" ) );
00900 gtk_widget_show( lookup_widget( common->getWidget(), "hbox_trim_insert" ) );
00901 }
00902
00903
00904 gtk_option_menu_set_history( GTK_OPTION_MENU( lookup_widget( common->getWidget(), "optionmenu_trim" ) ), static_cast< int >( mode ) );
00905 }
00906 }
00907
00911 void PageTrim::startNavigator()
00912 {
00913 stopNavigator( );
00914 g_nav_ctl.active = TRUE;
00915 resetThreads( );
00916 pthread_create( &readthreadTrim, NULL, readThread, &g_nav_ctl );
00917 pthread_create( &audiothreadTrim, NULL, audioThread, &g_nav_ctl );
00918 pthread_create( &videothreadTrim, NULL, videoThread, ( gpointer ) & g_nav_ctl );
00919 }
00920
00924 void PageTrim::stopNavigator()
00925 {
00926 if ( g_nav_ctl.active )
00927 {
00928 g_nav_ctl.active = FALSE;
00929 gdk_threads_leave();
00930 pthread_join( readthreadTrim, NULL );
00931 pthread_join( audiothreadTrim, NULL );
00932 pthread_join( videothreadTrim, NULL );
00933 gdk_threads_enter();
00934 getFrameDisplayer()->CloseSound();
00935 }
00936 }
00937
00944 void PageTrim::movedToFrame( int frame )
00945 {
00946 if ( common->hasListChanged == TRUE )
00947 {
00948 common->getPageEditor()->ResetBar();
00949 common->hasListChanged = FALSE;
00950
00951 if ( mode == PAGE_TRIM_MODE_UPDATE &&
00952 common->getPlayList() ->GetNumFrames() > 0 )
00953 {
00954 loadScene( frame );
00955 frame = in;
00956 }
00957 else if ( mode == PAGE_TRIM_MODE_INSERT )
00958 {
00959 const char *file = gtk_entry_get_text( GTK_ENTRY( lookup_widget( GTK_WIDGET( common->getWidget() ), "entry_trim_clip" ) ) );
00960 if ( file && strcmp( file, "" ) )
00961 {
00962 loadFile( file );
00963 frame = pos;
00964 }
00965 }
00966 }
00967 if ( max > 0 )
00968 {
00969 if ( frame > out && gtk_toggle_button_get_active( loop_toggle ) == TRUE )
00970 pos = in;
00971 else if ( frame < in && gtk_toggle_button_get_active( loop_toggle ) == TRUE )
00972 pos = out;
00973 else if ( frame >= 0 && frame <= max )
00974 pos = frame;
00975 else if ( frame >= max )
00976 pos = max;
00977 else if ( frame < 0 && max > 0 )
00978 pos = 0;
00979 else
00980 pos = -1;
00981
00982 if ( g_nav_ctl.active == FALSE )
00983 {
00984 skipPosUpdate = FALSE;
00985 showFrame( pos, ( pos == lastPos ) || ( Preferences::getInstance().audioScrub == FALSE ) );
00986 }
00987 else
00988 {
00989 lastFrame = newFrame = pos;
00990 startNavigator();
00991 }
00992 }
00993 }
00994
01001 void PageTrim::showFrame( int i, gboolean no_audio )
01002 {
01003 if ( max == 0 )
01004 {
01005 common->loadSplash( frameArea );
01006 common->showFrameInfo( -1 );
01007 return ;
01008 }
01009 else if ( i > -1 )
01010 {
01011 Frame & frame = *( GetFramePool( ) ->GetFrame( ) );
01012 if ( i > max )
01013 i = max;
01014 playlist.GetFrame( i, frame );
01015 common->showFrameInfo( i );
01016 if ( writer1394 != NULL )
01017 writer1394->SendFrame( frame, false );
01018 if ( getFrameDisplayer() )
01019 getFrameDisplayer() ->Put( frame, GTK_WIDGET( frameArea ), no_audio );
01020 lastPos = i;
01021 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_POS ], ( gfloat ) i );
01022 GetFramePool( ) ->DoneWithFrame( &frame );
01023 common->g_currentFrame = start_orig + (pos - in_orig);
01024 }
01025 }
01026
01027
01028 void PageTrim::showFrame( int position, Frame& frame )
01029 {
01030 if ( max == 0 )
01031 {
01032 common->loadSplash( frameArea );
01033 }
01034 else
01035 {
01036 getFrameDisplayer() ->Put( frame, GTK_WIDGET( frameArea ), TRUE );
01037 common->showFrameInfo( position );
01038 skipPosUpdate = TRUE;
01039 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_POS ], ( gfloat ) position );
01040 }
01041 }
01042
01043
01047 void PageTrim::videoStartOfMovie()
01048 {
01049 movedToFrame( 0 );
01050 common->toggleComponents( VIDEO_START_OF_MOVIE, false );
01051 }
01052
01056 void PageTrim::videoPreviousScene()
01057 {
01058 movedToFrame( in );
01059 common->toggleComponents( VIDEO_START_OF_SCENE, false );
01060 }
01061
01065 void PageTrim::videoStartOfScene()
01066 {
01067 movedToFrame( in );
01068 common->toggleComponents( VIDEO_START_OF_SCENE, false );
01069 }
01070
01074 void PageTrim::videoRewind()
01075 {
01076 common->toggleComponents( common->getComponentState(), false );
01077
01078
01079 if ( g_nav_ctl.step != -10 )
01080 {
01081 common->toggleComponents( VIDEO_REWIND, true );
01082 g_nav_ctl.step = -10;
01083 g_nav_ctl.rate = 0;
01084 startNavigator();
01085 }
01086 else
01087 {
01088 stopNavigator();
01089 g_nav_ctl.step = 1;
01090 g_nav_ctl.rate = 1;
01091 common->toggleComponents( VIDEO_REWIND, false );
01092 common->toggleComponents( VIDEO_STOP, true );
01093 }
01094 }
01095
01100 void PageTrim::videoBack(int step)
01101 {
01102 common->toggleComponents( common->getComponentState(), false );
01103 if ( g_nav_ctl.active )
01104 {
01105 if ( g_nav_ctl.step != -1 )
01106 {
01107 g_nav_ctl.step = -1;
01108 g_nav_ctl.rate = 1;
01109 common->toggleComponents( VIDEO_BACK, true );
01110 }
01111 else
01112 {
01113 stopNavigator();
01114 g_nav_ctl.step = 1;
01115 g_nav_ctl.rate = 0;
01116 common->toggleComponents( VIDEO_BACK, false );
01117 common->toggleComponents( VIDEO_STOP, true );
01118 }
01119 }
01120 else
01121 {
01122 common->moveByFrames( step );
01123 common->toggleComponents( VIDEO_BACK, false );
01124 common->toggleComponents( VIDEO_STOP, true );
01125 }
01126 }
01127
01131 void PageTrim::videoPlay()
01132 {
01133 common->toggleComponents( common->getComponentState(), false );
01134 if ( g_nav_ctl.active == FALSE || g_nav_ctl.step != 1 )
01135 {
01136 common->toggleComponents( VIDEO_PLAY, true );
01137 g_nav_ctl.step = 1;
01138 startNavigator();
01139 }
01140 else
01141 {
01142 stopNavigator();
01143 common->toggleComponents( VIDEO_PLAY, false );
01144 common->toggleComponents( VIDEO_STOP, true );
01145 }
01146 }
01147
01151 void PageTrim::videoPause()
01152 {
01153 common->toggleComponents( common->getComponentState(), false );
01154 common->toggleComponents( VIDEO_STOP, true );
01155 stopNavigator();
01156 }
01157
01161 void PageTrim::videoStop()
01162 {
01163 common->toggleComponents( common->getComponentState(), false );
01164 common->toggleComponents( VIDEO_STOP, true );
01165 stopNavigator();
01166 }
01167
01172 void PageTrim::videoForward(int step)
01173 {
01174 common->toggleComponents( common->getComponentState(), false );
01175 if ( g_nav_ctl.active && g_nav_ctl.step != 1 )
01176 {
01177 g_nav_ctl.step = 1;
01178 g_nav_ctl.rate = 1;
01179 common->toggleComponents( VIDEO_FORWARD, true );
01180 startNavigator();
01181 }
01182 else
01183 {
01184 stopNavigator();
01185 common->moveByFrames( step );
01186 common->toggleComponents( VIDEO_FORWARD, false );
01187 common->toggleComponents( VIDEO_STOP, true );
01188 }
01189 }
01190
01194 void PageTrim::videoFastForward()
01195 {
01196 common->toggleComponents( common->getComponentState(), false );
01197
01198 if ( g_nav_ctl.step != 10 )
01199 {
01200 common->toggleComponents( VIDEO_FAST_FORWARD, true );
01201 g_nav_ctl.step = 10;
01202 g_nav_ctl.rate = 0;
01203 startNavigator();
01204 }
01205 else
01206 {
01207 stopNavigator();
01208 g_nav_ctl.step = 1;
01209 g_nav_ctl.rate = 1;
01210 common->toggleComponents( VIDEO_FAST_FORWARD, false );
01211 common->toggleComponents( VIDEO_STOP, true );
01212 }
01213 }
01214
01222 void PageTrim::videoShuttle( int angle )
01223 {
01224 int frames_sec = _getOneSecond();
01225 int speedTable[] = {
01226 0,
01227 8, 10, 15, 20, 33, 50, 75,
01228 100,
01229 200, 300, 400, 500, 800, 1200,
01230 ( frames_sec * 100 ) };
01231 char s[ 64 ];
01232
01233 if ( angle < -15 )
01234 angle = -15;
01235 if ( angle > 15 )
01236 angle = 15;
01237
01238 int speed = speedTable[ ( angle < 0 ) ? -angle : angle ] * ( ( angle < 0 ) ? -1 : 1 );
01239 if ( speed == 0 || g_nav_ctl.step != speed / 100 || g_nav_ctl.rate != 100 / speed )
01240 {
01241 stopNavigator( );
01242 if ( speed == 0 )
01243 {
01244 common->keyboardFeedback( "", "" );
01245 common->toggleComponents( VIDEO_STOP, true );
01246 }
01247 else
01248 {
01249 g_nav_ctl.step = speed / 100;
01250 g_nav_ctl.rate = 100 / speed;
01251 g_nav_ctl.subframe = 0;
01252 startNavigator();
01253 snprintf( s, 63, _( "Shuttle %+.1f fps" ), ( float ) speed / 100.0 * frames_sec );
01254 common->keyboardFeedback( "", s );
01255 }
01256 }
01257 }
01258
01262 void PageTrim::videoNextScene()
01263 {
01264 movedToFrame( out );
01265 common->toggleComponents( VIDEO_NEXT_SCENE, false );
01266 }
01267
01271 void PageTrim::videoEndOfScene()
01272 {
01273 movedToFrame( out );
01274 common->toggleComponents( VIDEO_NEXT_SCENE, false );
01275 }
01276
01280 void PageTrim::videoEndOfMovie()
01281 {
01282 common->toggleComponents( common->getComponentState(), false );
01283 common->toggleComponents( VIDEO_END_OF_MOVIE, true );
01284 stopNavigator();
01285 movedToFrame( max );
01286 common->toggleComponents( VIDEO_END_OF_MOVIE, false );
01287 common->toggleComponents( VIDEO_STOP, true );
01288 }
01289
01295 void PageTrim::selectScene( int i )
01296 {
01297 bool restartNavigator = ( g_nav_ctl.active == TRUE );
01298
01299 stopNavigator();
01300
01301 if ( mode == PAGE_TRIM_MODE_UPDATE )
01302
01303 saveScene();
01304
01305
01306 vector <int> scene = common->getPageEditor() ->GetScene();
01307 if ( i >= ( int ) scene.size() )
01308 i = scene.size() - 1;
01309 currentScene = ( i <= 0 ) ? 0 : scene[ i - 1 ];
01310 common->g_currentFrame = currentScene;
01311
01312 if ( mode == PAGE_TRIM_MODE_UPDATE )
01313 {
01314 loadScene( currentScene );
01315 movedToFrame( in );
01316 }
01317 else if ( mode == PAGE_TRIM_MODE_INSERT )
01318 {
01319
01320 start_orig = common->getPlayList()->FindStartOfScene( currentScene );
01321 end_orig = common->getPlayList()->FindEndOfScene( currentScene );
01322
01323 common->setCurrentScene( start_orig );
01324 }
01325
01326 if ( restartNavigator )
01327 startNavigator();
01328 }
01329
01330 int PageTrim::getSceneIndex()
01331 {
01332 int i = 0;
01333 if ( common->getPlayList()->GetNumFrames() > 0 )
01334 {
01335 vector <int> scene = common->getPageEditor() ->GetScene();
01336 for ( i = 0; i < (int) scene.size() - 1; i++ )
01337 if ( currentScene < scene[ i ] )
01338 break;
01339 }
01340 else
01341 {
01342 i = -1;
01343 }
01344 return i;
01345 }
01346
01347 void PageTrim::resetInPoint()
01348 {
01349 in = in_orig;
01350 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], ( gfloat ) in );
01351 gtk_spin_button_set_value( spin_in, ( gfloat ) in );
01352 }
01353
01354
01355 void PageTrim::resetOutPoint()
01356 {
01357 out = out_orig;
01358 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], ( gfloat ) out );
01359 gtk_spin_button_set_value( spin_out, ( gfloat ) out );
01360 }
01361
01367 gboolean PageTrim::processKeyboard( GdkEventKey *event )
01368 {
01369 gboolean ret = FALSE;
01370
01371
01372 if ( g_nav_ctl.escaped == FALSE )
01373 {
01374 if ( strcmp( lastcmd, "alt" ) == 0 )
01375 {
01376 strcpy( lastcmd, "" );
01377 return ret;
01378 }
01379
01380
01381 switch ( event->keyval )
01382 {
01383 case GDK_Home:
01384 strcat( cmd, "gg");
01385 ret = TRUE;
01386 break;
01387 case GDK_End:
01388 strcat( cmd, "G");
01389 ret = TRUE;
01390 break;
01391 case GDK_BackSpace:
01392 case GDK_Left:
01393 strcat( cmd, "h" );
01394 ret = TRUE;
01395 break;
01396 case GDK_Up:
01397 strcat( cmd, "k" );
01398 ret = TRUE;
01399 break;
01400 case GDK_Right:
01401 strcat( cmd, "l" );
01402 ret = TRUE;
01403 break;
01404 case GDK_Return:
01405 if ( cmd[ 0 ] != 0 )
01406 {
01407
01408 strcpy( lastcmd, cmd );
01409
01410
01411 cmd[ 0 ] = 0;
01412 common->setStatusBar( "" );
01413 break;
01414 }
01415 else
01416 {
01417 strcat( cmd, "Enter" );
01418 ret = TRUE;
01419 break;
01420 }
01421 case GDK_Down:
01422 strcat( cmd, "j" );
01423 ret = TRUE;
01424 break;
01425 case GDK_Delete:
01426 strcat( cmd, "x" );
01427 ret = TRUE;
01428 break;
01429 case GDK_Escape:
01430 if ( common->getComponentState() & VIDEO_STOP )
01431 {
01432 common->changePageRequest( PAGE_EDITOR );
01433 return ret;
01434 }
01435 else
01436 {
01437 strcat( cmd, "Esc" );
01438 break;
01439 }
01440 case GDK_Alt_L:
01441 case GDK_Alt_R:
01442 strcpy( lastcmd, "alt" );
01443 return ret;
01444 case GDK_Insert:
01445 case GDK_KP_Insert:
01446 strcat( cmd, "Ins" );
01447 ret = TRUE;
01448 break;
01449 default:
01450 if ( strcmp( event->string, "." ) )
01451 strcat( cmd, event->string );
01452 break;
01453 }
01454
01455 if ( !strcmp( event->string, "." ) )
01456 strcpy( cmd, lastcmd );
01457 else if ( cmd[ 0 ] == 0x12 )
01458 strcpy( cmd, "Ctrl+R" );
01459
01460 #if 0
01461 printf( "send_event: %2.2x\n", event->send_event );
01462 printf( "time : %8.8x\n", event->time );
01463 printf( "state : %8.8x\n", event->state );
01464 printf( "keyval: %8.8x\n", event->keyval );
01465 printf( "length: %8.8x\n", event->length );
01466 printf( "string: %s\n", event->string );
01467 printf( "(hex) : %2.2x\n", event->string[ 0 ] );
01468 printf( "cmd : %s\n", cmd );
01469 printf( "(hex) : %8.8x\n", cmd[ 0 ] );
01470 fflush( stdout );
01471 #endif
01472
01473 processCommand( cmd );
01474 }
01475 return ret;
01476 }
01477
01483 gboolean PageTrim::processCommand( char *command )
01484 {
01485 int end;
01486 int count = 1;
01487 char real[ 256 ] = "";
01488
01489 strcpy( cmd, command );
01490
01491 switch ( sscanf( cmd, "%d%s", &count, real ) )
01492 {
01493 case 1:
01494
01495 if ( strcmp( cmd, "0" ) )
01496 {
01497 common->keyboardFeedback( cmd, "" );
01498 return FALSE;
01499 }
01500 break;
01501 case 0:
01502 sscanf( cmd, "%s", real );
01503 count = 1;
01504 break;
01505 }
01506
01507 if ( strcmp( cmd, "." ) )
01508 strcpy( lastcmd, cmd );
01509
01510
01511
01512
01513
01514 if ( strcmp( cmd, " " ) == 0 )
01515 {
01516 if ( g_nav_ctl.active == TRUE )
01517 {
01518 common->keyboardFeedback( cmd, _( "Pause" ) );
01519 common->videoPause( );
01520 }
01521 else
01522 {
01523 common->keyboardFeedback( cmd, _( "Play" ) );
01524 common->videoPlay( );
01525 }
01526 cmd[ 0 ] = 0;
01527 }
01528
01529 else if ( strcmp( real, "Esc" ) == 0 )
01530 {
01531 common->keyboardFeedback( cmd, _( "Stop" ) );
01532 common->videoStop( );
01533 cmd[ 0 ] = 0;
01534 }
01535
01536 else if ( strcmp( real, "Enter" ) == 0 )
01537 {
01538 if ( mode == PAGE_TRIM_MODE_UPDATE )
01539 {
01540 int pos = common->getPageTrim()->getPosition();
01541 common->keyboardFeedback( cmd, _( "Overwrite" ) );
01542 saveScene();
01543 loadScene( currentScene );
01544 movedToFrame( pos );
01545 }
01546 else if ( mode == PAGE_TRIM_MODE_INSERT )
01547 {
01548 common->keyboardFeedback( cmd, _( "Insert After" ) );
01549 insertScene( TRIM_INSERT_MODE_AFTER );
01550 movedToFrame( in );
01551 }
01552 cmd[ 0 ] = 0;
01553 }
01554
01555 else if ( strcmp( real, ":r" ) == 0 )
01556 {
01557 common->keyboardFeedback( cmd, _( "Insert Before" ) );
01558 insertScene( TRIM_INSERT_MODE_BEFORE );
01559 cmd[ 0 ] = 0;
01560 }
01561
01562 else if ( strcmp( real, ":a" ) == 0 )
01563 {
01564 common->keyboardFeedback( cmd, _( "Insert After" ) );
01565 insertScene( TRIM_INSERT_MODE_AFTER );
01566 cmd[ 0 ] = 0;
01567 }
01568
01569 else if ( strcmp( real, "Ins" ) == 0 )
01570 {
01571 common->keyboardFeedback( cmd, _( "Toggle Insert/Overwrite" ) );
01572 setMode( mode == PAGE_TRIM_MODE_UPDATE ? PAGE_TRIM_MODE_INSERT : PAGE_TRIM_MODE_UPDATE );
01573 cmd[ 0 ] = 0;
01574 }
01575
01576
01577
01578 else if ( strcmp( real, "l" ) == 0 )
01579 {
01580 common->keyboardFeedback( cmd, _( "Move forward" ) );
01581 movedToFrame( pos + count );
01582 cmd[ 0 ] = 0;
01583 }
01584
01585
01586
01587 else if ( strcmp( real, "h" ) == 0 )
01588 {
01589 common->keyboardFeedback( cmd, _( "Move backward" ) );
01590 movedToFrame( pos - count );
01591 cmd[ 0 ] = 0;
01592 }
01593
01594
01595
01596 else if ( strcmp( real, "w" ) == 0 || strcmp( real, "W" ) == 0 ||
01597 strcmp( real, "e" ) == 0 || strcmp( real, "E" ) == 0 )
01598 {
01599 common->keyboardFeedback( cmd, _( "Move forward second" ) );
01600 movedToFrame( pos + count * _getOneSecond() );
01601 cmd[ 0 ] = 0;
01602 }
01603
01604
01605
01606 else if ( ( strcmp( real, "b" ) == 0 ) || ( strcmp( real, "B" ) == 0 ) )
01607 {
01608 common->keyboardFeedback( cmd, _( "Move backwards one second" ) );
01609 moveToFrame( pos - count * _getOneSecond() );
01610 cmd[ 0 ] = 0;
01611 }
01612
01613
01614
01615 else if ( ( strcmp( cmd, "0" ) == 0 ) || ( strcmp( real, "^" ) == 0 ) )
01616 {
01617 common->videoStartOfScene( );
01618 common->keyboardFeedback( cmd, _( "Move to start of scene" ) );
01619 cmd[ 0 ] = 0;
01620 }
01621
01622
01623
01624 else if ( strcmp( real, "$" ) == 0 )
01625 {
01626 common->videoEndOfScene( );
01627 common->keyboardFeedback( cmd, _( "Move to end of scene" ) );
01628 cmd[ 0 ] = 0;
01629 }
01630
01631
01632
01633 else if ( ( strcmp( real, "j" ) == 0 ) || strcmp( real, "+" ) == 0 )
01634 {
01635 selectScene( getSceneIndex() + 1 );
01636 common->keyboardFeedback( cmd, _( "Move to start of next scene" ) );
01637 cmd[ 0 ] = 0;
01638 }
01639
01640
01641
01642 else if ( ( strcmp( real, "k" ) == 0 ) || ( strcmp( real, "-" ) == 0 ) )
01643 {
01644 selectScene( getSceneIndex() - 1 );
01645 common->keyboardFeedback( cmd, _( "Move to start of previous scene" ) );
01646 cmd[ 0 ] = 0;
01647 }
01648
01649
01650
01651 else if ( strcmp( cmd, "gg" ) == 0 )
01652 {
01653 common->videoStartOfMovie( );
01654 common->keyboardFeedback( cmd, _( "Move to first frame" ) );
01655 cmd[ 0 ] = 0;
01656 }
01657
01658
01659
01660 else if ( strcmp( cmd, "G" ) == 0 )
01661 {
01662 common->videoEndOfMovie( );
01663 common->keyboardFeedback( cmd, _( "Move to last frame" ) );
01664 cmd[ 0 ] = 0;
01665 }
01666
01667
01668
01669 else if ( strcmp( real, "dd" ) == 0 )
01670 {
01671 end_orig = start_orig;
01672 for ( ; count >= 1 && end_orig <= common->getPlayList() ->GetNumFrames() - 1; count -- )
01673 {
01674 end_orig = common->getPlayList() ->FindEndOfScene( end_orig );
01675 end_orig ++;
01676 }
01677 common->getPageEditor()->CopyFrames( start_orig, end_orig - 1 );
01678 common->getPageEditor()->DeleteFrames( start_orig, end_orig - 1 );
01679 if ( start_orig > common->getPlayList() ->GetNumFrames() - 1 )
01680 start_orig = common->getPlayList() ->GetNumFrames() - 1;
01681 common->moveToFrame( start_orig );
01682 common->keyboardFeedback( cmd, _( "Cut current scene" ) );
01683 common->getPageEditor()->DrawBar( common->g_currentFrame );
01684 cmd[ 0 ] = 0;
01685 }
01686
01687
01688
01689 else if ( ( strcmp( cmd, "o" ) == 0 ) || ( strcmp( cmd, "d$" ) == 0 ) )
01690 {
01691 out = pos;
01692 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_OUT ], ( gfloat ) out );
01693 common->keyboardFeedback( cmd, _( "Cut to end of scene" ) );
01694 cmd[ 0 ] = 0;
01695 }
01696
01697
01698
01699 else if ( ( strcmp( cmd, "i" ) == 0 ) || ( strcmp( cmd, "d0" ) == 0 ) || strcmp( cmd, "d^" ) == 0 )
01700 {
01701 in = pos;
01702 gtk_adjustment_set_value( trim_adj[ TRIM_ADJ_IN ], ( gfloat ) in );
01703 common->keyboardFeedback( cmd, _( "Cut from start of scene" ) );
01704 cmd[ 0 ] = 0;
01705 }
01706
01707
01708
01709 else if ( ( strcmp( real, "yy" ) == 0 ) || ( strcmp( real, "Y" ) == 0 ) )
01710 {
01711 end_orig = start_orig;
01712 for ( ; count >= 1; count -- )
01713 {
01714 end_orig = common->getPlayList() ->FindEndOfScene( end_orig );
01715 end_orig ++;
01716 }
01717 common->getPageEditor()->CopyFrames( start_orig, end_orig - 1 );
01718 common->keyboardFeedback( cmd, _( "Copy current scene" ) );
01719 cmd[ 0 ] = 0;
01720 }
01721
01722
01723
01724 else if ( strcmp( real, "p" ) == 0 )
01725 {
01726 for ( ; count >= 1; count -- )
01727 common->getPageEditor()->PasteFrames( common->g_currentFrame + 1 );
01728 movedToFrame( pos );
01729 common->keyboardFeedback( cmd, _( "Paste after current frame" ) );
01730 common->getPageEditor()->DrawBar( common->g_currentFrame );
01731 cmd[ 0 ] = 0;
01732 }
01733
01734
01735
01736 else if ( strcmp( real, "P" ) == 0 )
01737 {
01738 for ( ; count >= 1; count -- )
01739 common->getPageEditor()->PasteFrames( common->g_currentFrame );
01740 end_orig = common->getPlayList() ->FindEndOfScene( common->g_currentFrame + 1 );
01741 movedToFrame( pos );
01742 common->keyboardFeedback( cmd, _( "Paste before current frame" ) );
01743 common->getPageEditor()->DrawBar( common->g_currentFrame );
01744 cmd[ 0 ] = 0;
01745 }
01746
01747
01748
01749 else if ( strcmp( cmd, "a" ) == 0 )
01750 {
01751 common->keyboardFeedback( cmd, _( "Capture, insert after frame" ) );
01752 end = common->getPlayList() ->FindEndOfScene( common->g_currentFrame );
01753 common->moveToFrame( end );
01754 FileTracker::GetInstance().SetMode( CAPTURE_FRAME_APPEND );
01755 common->changePageRequest( PAGE_CAPTURE );
01756 cmd[ 0 ] = 0;
01757 }
01758
01759 else if ( strcmp( cmd, "A" ) == 0 )
01760 {
01761 common->keyboardFeedback( cmd, _( "Capture, append to movie" ) );
01762 end = common->getPlayList() ->GetNumFrames();
01763 common->moveToFrame( end );
01764 FileTracker::GetInstance().SetMode( CAPTURE_MOVIE_APPEND );
01765 common->changePageRequest( PAGE_CAPTURE );
01766 cmd[ 0 ] = 0;
01767 }
01768
01769 else if ( strcmp( cmd, "v" ) == 0 )
01770 {
01771 common->keyboardFeedback( cmd, _( "Timeline" ) );
01772 common->changePageRequest( PAGE_TIMELINE );
01773 cmd[ 0 ] = 0;
01774 }
01775
01776 else if ( strcmp( cmd, "C" ) == 0 )
01777 {
01778 common->keyboardFeedback( cmd, _( "FX" ) );
01779 common->changePageRequest( PAGE_MAGICK );
01780 cmd[ 0 ] = 0;
01781 }
01782
01783 else if ( strcmp( cmd, "u" ) == 0 )
01784 {
01785 GetEditorBackup() ->Undo( common->getPlayList() );
01786 common->keyboardFeedback( cmd, _( "Undo" ) );
01787 common->hasListChanged = TRUE;
01788 movedToFrame( 0 );
01789 common->getPageEditor()->DrawBar( common->g_currentFrame );
01790 cmd[ 0 ] = 0;
01791 }
01792
01793 else if ( strcmp( cmd, "Ctrl+R" ) == 0 )
01794 {
01795 GetEditorBackup() ->Redo( common->getPlayList() );
01796 common->keyboardFeedback( cmd, _( "Redo" ) );
01797 common->hasListChanged = TRUE;
01798 movedToFrame( 0 );
01799 common->getPageEditor()->DrawBar( common->g_currentFrame );
01800 cmd[ 0 ] = 0;
01801 }
01802
01803
01804 else if ( strcmp( cmd, "U" ) == 0 )
01805 {
01806 common->keyboardFeedback( cmd, _( "Undo" ) );
01807 resetInPoint();
01808 resetOutPoint();
01809 movedToFrame( pos );
01810 cmd[ 0 ] = 0;
01811 }
01812
01813 else if ( strcmp( cmd, "\\" ) == 0 )
01814 {
01815 common->keyboardFeedback( cmd, _( "Toggle Looping" ) );
01816 gtk_toggle_button_set_active( loop_toggle, ! gtk_toggle_button_get_active( loop_toggle ) );
01817 cmd[ 0 ] = 0;
01818 }
01819
01820 else if ( strcmp( cmd, "=" ) == 0 )
01821 {
01822 common->keyboardFeedback( cmd, _( "Toggle Link" ) );
01823 gtk_toggle_button_set_active( link_toggle, ! gtk_toggle_button_get_active( link_toggle ) );
01824 cmd[ 0 ] = 0;
01825 }
01826
01827
01828
01829 else if ( strcmp( cmd, ":W" ) == 0 )
01830 {
01831 common->keyboardFeedback( cmd, _( "Export" ) );
01832 common->changePageRequest( PAGE_EXPORT );
01833 cmd[ 0 ] = 0;
01834 }
01835
01836 else if ( strcmp( cmd, "F2" ) == 0 )
01837 {
01838 common->keyboardFeedback( cmd, _( "Edit" ) );
01839 common->changePageRequest( PAGE_EDITOR );
01840 cmd[ 0 ] = 0;
01841 }
01842
01843
01844
01845 else if ( strcmp( cmd, ":w" ) == 0 )
01846 {
01847 common->keyboardFeedback( cmd, _( "Write playlist" ) );
01848 common->savePlayList( );
01849 cmd[ 0 ] = 0;
01850 }
01851
01852
01853
01854 else if ( strcmp( cmd, ":q" ) == 0 )
01855 {
01856 common->keyboardFeedback( cmd, _( "quit" ) );
01857 kinoDeactivate();
01858 cmd[ 0 ] = 0;
01859 }
01860
01861 else if ( strcmp( real, "J" ) == 0 )
01862 {
01863 common->keyboardFeedback( cmd, _( "Join scenes" ) );
01864 for ( ; count >= 1 && common->getPlayList() ->JoinScenesAt( common->g_currentFrame ); count -- )
01865 common->hasListChanged = TRUE;
01866 if ( common->hasListChanged == TRUE )
01867 {
01868 GetEditorBackup() ->Store( common->getPlayList() );
01869 movedToFrame( pos );
01870 g_signal_emit_by_name( trim_adj[ TRIM_ADJ_POS ], "value-changed" );
01871 }
01872 cmd[ 0 ] = 0;
01873 }
01874
01875
01876
01877 else if ( strcmp( cmd, "Ctrl+J" ) == 0 && currentScene != -1 )
01878 {
01879 int newScene = getSceneIndex() + 1;
01880 common->keyboardFeedback( cmd, _( "Split scene before frame" ) );
01881 if ( pos >= in && pos <= out &&
01882 common->getPlayList() ->SplitSceneBefore( common->g_currentFrame ) )
01883 {
01884 GetEditorBackup() ->Store( common->getPlayList() );
01885 common->hasListChanged = TRUE;
01886 g_signal_emit_by_name( trim_adj[ TRIM_ADJ_POS ], "value-changed" );
01887 selectScene( newScene );
01888 common->videoStartOfScene( );
01889 }
01890 cmd[ 0 ] = 0;
01891 }
01892
01893
01894 else if ( strncmp( cmd, ":", 1 ) == 0 )
01895 {
01896 int val = 0;
01897 char t[ 132 ] = "";
01898 if ( sscanf( cmd + 1, "%d", &val ) == 1 )
01899 {
01900 common->moveToFrame( val );
01901 sprintf( t, "Move to frame %d", val );
01902 common->keyboardFeedback( cmd, t );
01903 }
01904 else
01905 common->setStatusBar( cmd );
01906 }
01907
01908 else
01909 {
01910
01911 if ( strlen( real ) > 5 )
01912 cmd[ 0 ] = 0;
01913 else if ( strchr( "dgy ", real[ strlen( real ) - 1 ] ) == NULL )
01914 cmd[ 0 ] = 0;
01915
01916 common->keyboardFeedback( cmd, "" );
01917
01918 }
01919
01920 return FALSE;
01921 }
01922
01923
01924 void PageTrim::windowMoved()
01925 {
01926 if ( g_nav_ctl.active == FALSE )
01927 {
01928 if ( max == 0 )
01929 common->clearPreview( frameArea );
01930 else
01931 showFrame( pos, TRUE );
01932 }
01933 }
01934
01935
01936 void PageTrim::showFrameInfo( int i )
01937 {
01938 Frame & frame = *( GetFramePool( ) ->GetFrame( ) );
01939 FileHandler *media;
01940
01941 playlist.GetFrame( i, frame );
01942 playlist.GetMediaObject( i, &media );
01943 common->showFrameMoreInfo( frame, media );
01944 GetFramePool( ) ->DoneWithFrame( &frame );
01945
01946 if ( i < 0 )
01947 {
01948 gtk_label_set_text( positionLabelCurrent, "" );
01949 gtk_label_set_text( positionLabelTotal, "" );
01950 }
01951 else
01952 {
01953 common->getTime().setFramerate( frame.GetFrameRate() );
01954 string tc = "<span size=\"x-large\">" + common->getTime().parseFramesToString( i, common->getTimeFormat() ) + "</span>";
01955 gtk_label_set_markup( positionLabelCurrent, tc.c_str() );
01956 gtk_widget_set_redraw_on_allocate( GTK_WIDGET( positionLabelCurrent ), FALSE );
01957 tc = _("Duration: ") + common->getTime().parseFramesToString( out - in + 1, common->getTimeFormat() );
01958 gtk_label_set_markup( positionLabelTotal, tc.c_str() );
01959 }
01960 }
01961
01962 void PageTrim::timeFormatChanged()
01963 {
01964 on_spinbutton_trim_in_value_changed( GTK_SPIN_BUTTON( lookup_widget( common->getWidget(), "spinbutton_trim_in" ) ), NULL );
01965 on_spinbutton_trim_out_value_changed( GTK_SPIN_BUTTON( lookup_widget( common->getWidget(), "spinbutton_trim_out" ) ), NULL );
01966 }
01967
01968
01969 extern "C"
01970 {
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983 static int frameNumber[ PLAYBACK_FRAMES ];
01984 static int pending = 0;
01985 static int head = -1;
01986 static int tail = -1;
01987 static bool showing = false;
01988 static bool playing = false;
01989
01990 static void resetThreads( )
01991 {
01992 showing = false;
01993 playing = false;
01994 pending = 0;
01995 head = 0;
01996 tail = 0;
01997 }
01998
02008 static void *readThread( void * info )
02009 {
02010 struct navigate_control * ctl = ( struct navigate_control * ) info;
02011 newFrame = 0;
02012 lastFrame = common->getPageTrim() ->getPosition() - 1;
02013 gint totalFrames = common->getPageTrim() ->getTotalFrames();
02014 gint countFrames = 0;
02015 static Preferences &prefs = Preferences::getInstance();
02016 int time_per_frame = 1000000 / _getOneSecond( );
02017
02018
02019
02020
02021 struct timeval start;
02022 struct timeval end;
02023 gettimeofday( &start, NULL );
02024
02025
02026 while ( ctl->active )
02027 {
02028
02029
02030 start.tv_usec += time_per_frame;
02031 if ( start.tv_usec >= 1000000 )
02032 {
02033 start.tv_usec -= 1000000;
02034 start.tv_sec ++;
02035 }
02036
02037 pthread_mutex_lock( &readlock );
02038
02039 newFrame = lastFrame + ctl->step;
02040
02041
02042 if ( ctl->step == 0 )
02043 {
02044 ctl->subframe++;
02045 if ( ctl->rate < 0 )
02046 {
02047 if ( ctl->subframe >= -ctl->rate )
02048 {
02049 newFrame --;
02050 ctl->subframe = 0;
02051 }
02052 }
02053 else
02054 {
02055 if ( ctl->subframe >= ctl->rate )
02056 {
02057 newFrame ++;
02058 ctl->subframe = 0;
02059 }
02060 }
02061 }
02062 pthread_mutex_unlock( &readlock );
02063
02064
02065 if ( newFrame < 0 )
02066 newFrame = totalFrames - 1;
02067 else if ( newFrame > common->getPageTrim() ->getOutPoint() &&
02068 gtk_toggle_button_get_active( loop_toggle ) == TRUE )
02069 newFrame = common->getPageTrim() ->getInPoint();
02070 else if ( newFrame < common->getPageTrim() ->getInPoint() &&
02071 gtk_toggle_button_get_active( loop_toggle ) == TRUE )
02072 newFrame = common->getPageTrim() ->getOutPoint();
02073 else if ( newFrame >= totalFrames )
02074 newFrame = 0;
02075
02076
02077 if ( pending >= PLAYBACK_FRAMES / 2 )
02078 {
02079
02080 playing = true;
02081 struct timespec t =
02082 {
02083 0, 0
02084 };
02085 nanosleep( &t, NULL );
02086 }
02087 else if ( pending < PLAYBACK_FRAMES )
02088 {
02089 pthread_mutex_lock( &threadlock );
02090 int new_head = ( head + 1 ) % PLAYBACK_FRAMES;
02091
02092 pthread_mutex_unlock( &threadlock );
02093
02094 frameNumber[ new_head ] = newFrame;
02095 common->getPageTrim() ->getPlayList().GetFrame( frameNumber[ new_head ], *frameContent[ new_head ] );
02096
02097 pthread_mutex_lock( &threadlock );
02098 pending ++;
02099 head = new_head;
02100 pthread_mutex_unlock( &threadlock );
02101
02102 if ( writer1394 != NULL )
02103 writer1394->SendFrame( *frameContent[ new_head ], false );
02104
02105
02106 playing = true;
02107
02108
02109 if ( ( ! prefs.dropFrame || ! prefs.enableAudio ) && ctl->active )
02110 {
02111
02112
02113 tail = ( tail + 1 ) % PLAYBACK_FRAMES;
02114 pending --;
02115
02116
02117 common->getPageTrim() ->setPosition( frameNumber[ tail ] );
02118
02119
02120 if ( prefs.enableAudio && ( frameNumber[ tail ] != lastFrame || ctl->rate > 1 || ctl->rate < -1 ) )
02121 common->getPageTrim() ->getFrameDisplayer() ->PutSound( *frameContent[ tail ] );
02122
02123
02124 gdk_threads_enter();
02125 common->getPageTrim() ->showFrame( frameNumber[ tail ], *frameContent[ tail ] );
02126 gdk_flush();
02127 gdk_threads_leave();
02128
02129
02130 gettimeofday( &end, NULL );
02131 int difference = ( ( start.tv_sec * 1000000 + start.tv_usec ) - ( end.tv_sec * 1000000 + end.tv_usec ) );
02132
02133 if ( difference > 2000 && difference < time_per_frame )
02134 {
02135
02136 if ( ! prefs.enableAudio )
02137 {
02138 struct timespec t =
02139 {
02140 0, difference * 500
02141 };
02142 nanosleep( &t, NULL );
02143 }
02144 }
02145 else if ( difference < 0 || difference >= time_per_frame )
02146 {
02147 gettimeofday( &start, NULL );
02148 }
02149 }
02150
02151
02152 lastFrame = newFrame;
02153
02154
02155 countFrames ++;
02156 }
02157 }
02158
02159
02160
02161 return NULL;
02162 }
02163
02164 static void *audioThread( void * info )
02165 {
02166
02167 static Preferences & prefs = Preferences::getInstance();
02168 struct navigate_control *ctl = ( struct navigate_control * ) info;
02169 gint lastFrame = common->getPageTrim() ->getPosition() - 1;
02170 int time_per_frame = 1000000 / _getOneSecond( );
02171
02172
02173
02174 while ( ctl->active )
02175 {
02176
02177
02178 if ( prefs.dropFrame && prefs.enableAudio )
02179 {
02180
02181
02182 pthread_mutex_lock( &threadlock );
02183 int new_tail = ( tail + 1 ) % PLAYBACK_FRAMES;
02184
02185 pthread_mutex_unlock( &threadlock );
02186
02187
02188 if ( pending > 0 && playing )
02189 {
02190
02191
02192 common->getPageTrim() ->setPosition( frameNumber[ tail ] );
02193
02194
02195 if ( prefs.enableAudio && ( frameNumber[ tail ] != lastFrame || ctl->rate > 1 || ctl->rate < -1 ) )
02196 {
02197 common->getPageTrim() ->getFrameDisplayer() ->PutSound( *frameContent[ tail ] );
02198 if ( pending < 10 )
02199 {
02200
02201 struct timespec t =
02202 {
02203 0, 0
02204 };
02205 nanosleep( &t, NULL );
02206 }
02207 }
02208 else if ( ctl->step == 0 && !prefs.audioScrub )
02209 {
02210 struct timespec t =
02211 {
02212 0, time_per_frame * 1000
02213 };
02214 nanosleep( &t, NULL );
02215 }
02216
02217
02218 lastFrame = frameNumber[ tail ];
02219
02220
02221 pthread_mutex_lock( &threadlock );
02222 pending --;
02223 tail = new_tail;
02224 pthread_mutex_unlock( &threadlock );
02225
02226
02227 showing = true;
02228
02229 }
02230 else
02231 {
02232 struct timespec t =
02233 {
02234 0, 0
02235 };
02236 nanosleep( &t, NULL );
02237 }
02238 }
02239 else
02240 {
02241
02242
02243 return NULL;
02244 }
02245 }
02246
02247
02248
02249 return NULL;
02250 }
02251
02252 static void *videoThread( void * info )
02253 {
02254
02255 static Preferences & prefs = Preferences::getInstance();
02256 struct navigate_control *ctl = ( struct navigate_control * ) info;
02257 int lastFrame = common->getPageTrim() ->getPosition() - 1;
02258
02259 #ifdef PLAY_WITH_STATS
02260
02261 int dropped = 0;
02262 int count = 0;
02263 #endif
02264
02265
02266
02267 while ( ctl->active )
02268 {
02269
02270
02271 if ( prefs.dropFrame && prefs.enableAudio )
02272 {
02273
02274 if ( showing && pending > 0 )
02275 {
02276
02277
02278 int my_tail = tail;
02279
02280
02281 if ( frameNumber[ my_tail ] != lastFrame || ctl->rate > 1 )
02282 {
02283 #ifdef PLAY_WITH_STATS
02284
02285 if ( ctl->step == 1 )
02286 {
02287 int skipped = frameNumber[ my_tail ] - lastFrame - 1;
02288 count += skipped + 1;
02289 if ( skipped != 0 && lastFrame != 0 && count != 0 )
02290 {
02291 dropped += skipped;
02292 cerr << ">>>> Dropped " << dropped << " in " << count << " frames - " << ( double ) ( ( ( double ) dropped / ( double ) count ) * 100.0 ) << "%" << endl;
02293 }
02294 lastFrame = frameNumber[ my_tail ];
02295 }
02296 #endif
02297
02298
02299 if ( ctl->active )
02300 {
02301 gdk_threads_enter();
02302 common->getPageTrim() ->showFrame( frameNumber[ my_tail ], *frameContent[ my_tail ] );
02303 gdk_flush();
02304 gdk_threads_leave();
02305 }
02306 }
02307 }
02308
02309 struct timespec t = { 0, 0 };
02310 nanosleep( &t, NULL );
02311 }
02312 else
02313 {
02314
02315
02316 return NULL;
02317 }
02318 }
02319
02320 #ifdef PLAY_WITH_STATS
02321 cerr << ">>>> Video stopped: Dropped " << dropped << " in " << count << " frames - " << ( double ) ( ( ( double ) dropped / ( double ) count ) * 100.0 ) << "%" << endl;
02322 #endif
02323
02324
02325
02326 return NULL;
02327 }
02328
02329 static int _getOneSecond( void )
02330 {
02331 Frame & frame = *( GetFramePool() ->GetFrame( ) );
02332 common->getPlayList() ->GetFrame( common->g_currentFrame, frame );
02333 int value = ( frame.IsPAL() ? 25 : 30 );
02334 GetFramePool( ) ->DoneWithFrame( &frame );
02335 return value;
02336 }
02337
02338 }