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

page_trim.cc

Go to the documentation of this file.
00001 /*
00002 * page_trim.cc Notebook Trim Page Object
00003 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
00004 *
00005 * This program is free software; you can redistribute it and/or modify
00006 * it under the terms of the GNU General Public License as published by
00007 * the Free Software Foundation; either version 2 of the License, or
00008 * (at your option) any later version.
00009 *
00010 * This program is distributed in the hope that it will be useful,
00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 * GNU General Public License for more details.
00014 *
00015 * You should have received a copy of the GNU General Public License
00016 * along with this program; if not, write to the Free Software Foundation,
00017 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023 
00024 #include <iostream>
00025 using std::cerr;
00026 using std::endl;
00027 
00028 #include <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     /* signal callbacks */
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     /* insert mode callbacks */
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                     // XXX: the following is making gtk abort
00329                     //modal_message( _( "Invalid file specified." ) );
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                         // XXX: the following is making gtk abort
00370                         //modal_message( _( "Invalid file specified." ) );
00371 //                      break;
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     // Attach the custom GTK+ Trim control
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         // Load the current scene
00580         loadScene( common->g_currentFrame );
00581         lastPos = pos = in + common->g_currentFrame - start_orig;
00582         movedToFrame( pos );
00583 
00584         // Load the clip combo
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     // first, save begin and end time markers to region of the
00658     // the whole movie that this scene represents
00659     update_start = start_orig = pl->FindStartOfScene( currentScene );
00660     end_orig = pl->FindEndOfScene( currentScene );
00661 
00662     // get a local playlist representing just the scene
00663     // based on time markers in the movie
00664     pl->GetPlayList( start_orig, end_orig, playlist );
00665 
00666     // set the in point and current position to the in point
00667     // of the first clip in the scene
00668     in = in_orig = lastPos = pos = pl->GetClipBegin( currentScene );
00669 
00670     // unwind the clip at the beginning of the scene
00671     playlist.SetClipBegin( 0, "0" );
00672 
00673     // get the clip at the end of the scene
00674     playlist.GetMediaObject( playlist.FindEndOfScene( 0 ), &media );
00675 
00676     // unwind the clip at the end of the scene
00677     // XXX: what about frames deleted from the beginning or middle
00678     // of a multi-clip scene?
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     // get the total number of frames now in the local playlist
00685     max = playlist.GetNumFrames() - 1;
00686 
00687     // set the out point to the difference between out point before
00688     // and after unwinding
00689     out = out_orig = max - ( newClipEnd - prevClipEnd );
00690 
00691     // inform controller of our scene change
00692     common->setCurrentScene( start_orig );
00693 
00694     // update the trim UI
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     // Recalibrate the spinners
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         // commit out point to local playlist
00734         playlist.Delete( out + 1, max );
00735         // commmit in point to local playlist
00736         playlist.Delete( 0, in - 1 );
00737         // delete the original scene from the movie
00738         common->getPlayList() ->Delete( start_orig, end_orig );
00739         // insert the revised scene (local playlist) into the movie
00740         // at the saved begin time marker
00741         common->getPlayList() ->InsertPlayList( playlist, start_orig );
00742 
00743         changed = false;
00744 
00745         // put into undo history
00746         GetEditorBackup() ->Store( common->getPlayList() );
00747 
00748         // update commons and other views (title bar and storyboard)
00749         common->hasListChanged = TRUE;
00750         common->setWindowTitle( );
00751         common->getPageEditor()->DrawBar( common->g_currentFrame );
00752 
00753         // Refresh the combo menu
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             // XXX: the following is making gtk abort
00814             // modal_message( _( "Failed to load media file." ) );
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         // Refresh the combo menu
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             // Load the currently selected scene
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         // initialize insert mode controls for edit mode
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     // Toggle Rewind state
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         // commit the changes and load a new scene
01303         saveScene();
01304 
01305     // figure out what scene I am in
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         // set the insertion points
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     // Only process while not escape mode
01372     if ( g_nav_ctl.escaped == FALSE )
01373     {
01374         if ( strcmp( lastcmd, "alt" ) == 0 )
01375         {
01376             strcpy( lastcmd, "" );
01377             return ret;
01378         }
01379 
01380         // Translate special keys to equivalent command
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                 // Last command is now
01408                 strcpy( lastcmd, cmd );
01409 
01410                 // end the command entry
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