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

page_trim.cc File Reference

#include <iostream>
#include <sys/time.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include "page_trim.h"
#include "avi.h"
#include "error.h"
#include "message.h"
#include "filehandler.h"
#include "frame.h"
#include "commands.h"
#include "page_editor.h"
#include "ieee1394io.h"
#include "support.h"

Include dependency graph for page_trim.cc:

Go to the source code of this file.

Defines

#define TRIM_ADJ_POS   0
#define TRIM_ADJ_IN   1
#define TRIM_ADJ_OUT   2
#define PLAYBACK_FRAMES   50

Functions

static int _getOneSecond (void)
static void resetThreads ()
static void * readThread (void *info)
 This function carries out the read ahead and is responsible for obtaining the each frame.
static void * videoThread (void *info)
static void * audioThread (void *info)
gboolean on_trim_value_changed_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
void on_spinbutton_trim_in_value_changed (GtkSpinButton *spinbutton, gpointer user_data)
void on_spinbutton_trim_out_value_changed (GtkSpinButton *spinbutton, gpointer user_data)
void on_button_trim_in_reset_clicked (GtkButton *button, gpointer user_data)
void on_button_trim_out_reset_clicked (GtkButton *button, gpointer user_data)
void on_button_trim_in_set_clicked (GtkButton *button, gpointer user_data)
void on_button_trim_out_set_clicked (GtkButton *button, gpointer user_data)
void on_togglebutton_trim_link_toggled (GtkToggleButton *togglebutton, gpointer user_data)
gboolean on_spinbutton_trim_in_focus_in_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
gboolean on_spinbutton_trim_in_focus_out_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
gboolean on_spinbutton_trim_out_focus_in_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
gboolean on_spinbutton_trim_out_focus_out_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
gboolean on_trim_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
gboolean on_trim_button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
gboolean on_combo_trim_clip_entry_focus_in_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
gboolean on_combo_trim_clip_entry_focus_out_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
void on_combo_trim_clip_entry_changed (GtkEditable *editable, gpointer user_data)
void on_button_trim_open_clicked (GtkButton *button, gpointer user_data)
void on_button_trim_insert_before_clicked (GtkButton *button, gpointer user_data)
void on_button_trim_insert_after_clicked (GtkButton *button, gpointer user_data)
void on_menuitem_trim_update_activate (GtkMenuItem *menuitem, gpointer user_data)
void on_menuitem_trim_insert_activate (GtkMenuItem *menuitem, gpointer user_data)
void on_button_trim_apply_clicked (GtkButton *button, gpointer user_data)
void on_entry_trim_in_activate (GtkEntry *entry, gpointer user_data)
gboolean on_entry_trim_in_focus_out_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
void on_entry_trim_out_activate (GtkEntry *entry, gpointer user_data)
gboolean on_entry_trim_out_focus_out_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)

Variables

KinoCommoncommon
navigate_control g_nav_ctl
char cmd []
static char lastcmd [256] = { 0 }
static pthread_t readthreadTrim
static pthread_t audiothreadTrim
static pthread_t videothreadTrim
static pthread_mutex_t threadlock = PTHREAD_MUTEX_INITIALIZER
static pthread_mutex_t readlock = PTHREAD_MUTEX_INITIALIZER
static GtkAdjustment * trim_adj [3]
static gboolean skipPosUpdate = FALSE
static GtkSpinButton * spin_in
static GtkSpinButton * spin_out
static GtkToggleButton * link_toggle
static GtkToggleButton * loop_toggle
static gboolean doScrub = false
static int newFrame = 0
static int lastFrame = -1
static FrameframeContent [PLAYBACK_FRAMES]
IEEE1394Writerwriter1394
GArray * scenes = NULL
 Constructor for the trimmer page object.
static int frameNumber [PLAYBACK_FRAMES]
static int pending = 0
static int head = -1
static int tail = -1
static bool showing = false
static bool playing = false


Define Documentation

#define PLAYBACK_FRAMES   50
 

Definition at line 78 of file page_trim.cc.

#define TRIM_ADJ_IN   1
 

Definition at line 46 of file page_trim.cc.

Referenced by PageTrim::loadFile(), PageTrim::loadScene(), on_button_trim_in_set_clicked(), on_spinbutton_trim_in_value_changed(), on_trim_value_changed_event(), PageTrim::PageTrim(), PageTrim::processCommand(), PageTrim::resetInPoint(), and PageTrim::setMode().

#define TRIM_ADJ_OUT   2
 

Definition at line 47 of file page_trim.cc.

Referenced by PageTrim::loadFile(), PageTrim::loadScene(), on_button_trim_out_set_clicked(), on_spinbutton_trim_out_value_changed(), on_trim_value_changed_event(), PageTrim::PageTrim(), PageTrim::processCommand(), PageTrim::resetOutPoint(), and PageTrim::setMode().

#define TRIM_ADJ_POS   0
 

Definition at line 45 of file page_trim.cc.

Referenced by PageTrim::loadFile(), PageTrim::loadScene(), PageTrim::PageTrim(), PageTrim::processCommand(), and PageTrim::showFrame().


Function Documentation

static int _getOneSecond void   )  [static]
 

Definition at line 2329 of file page_trim.cc.

References common, KinoCommon::g_currentFrame, GetFramePool(), KinoCommon::getPlayList(), and Frame::IsPAL().

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     }

static void * audioThread void *  info  )  [static]
 

Definition at line 2164 of file page_trim.cc.

References _getOneSecond(), navigate_control::active, Preferences::audioScrub, common, Preferences::dropFrame, Preferences::enableAudio, frameContent, Preferences::getInstance(), KinoCommon::getPageTrim(), lastFrame, PLAYBACK_FRAMES, navigate_control::rate, navigate_control::step, and threadlock.

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         // cerr << ">>> Starting audio thread" << endl;
02173 
02174         while ( ctl->active )
02175         {
02176 
02177             // Only do this when drop frames is active (otherwise the audio thread takes care of it)
02178             if ( prefs.dropFrame && prefs.enableAudio )
02179             {
02180 
02181                 // Obtain the position of the last released frame
02182                 pthread_mutex_lock( &threadlock );
02183                 int new_tail = ( tail + 1 ) % PLAYBACK_FRAMES;
02184                 //cerr << "playing  pending = " << pending << " head = " << head << " new_tail = " << new_tail << endl;
02185                 pthread_mutex_unlock( &threadlock );
02186 
02187                 // As long as its different to the previous one, then display it
02188                 if ( pending > 0 && playing )
02189                 {
02190 
02191                     // Move the main frame position to our newly derived location
02192                     common->getPageTrim() ->setPosition( frameNumber[ tail ] );
02193 
02194                     // Play the audio
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                             // Give the reader more time
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                     // Last encountered audio frame
02218                     lastFrame = frameNumber[ tail ];
02219 
02220                     // Move the tail
02221                     pthread_mutex_lock( &threadlock );
02222                     pending --;
02223                     tail = new_tail;
02224                     pthread_mutex_unlock( &threadlock );
02225 
02226                     // Start showing frames from this point onwards
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                 // It is safe to cancel the audio thread here since a change to prefs necessitates a restart.
02242                 // cerr << ">>> Audio Thread not needed" << endl;
02243                 return NULL;
02244             }
02245         }
02246 
02247         // cerr << ">>> Ending video thread" << endl;
02248 
02249         return NULL;
02250     }

void on_button_trim_apply_clicked GtkButton *  button,
gpointer  user_data
 

Definition at line 422 of file page_trim.cc.

References lookup_widget(), and processCommand().

00424     {
00425         gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00426         processCommand( "Enter" );
00427     }

void on_button_trim_in_reset_clicked GtkButton *  button,
gpointer  user_data
 

Definition at line 197 of file page_trim.cc.

References KinoCommon::getPageTrim(), and lookup_widget().

00199     {
00200         gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00201         common->getPageTrim() ->resetInPoint();
00202     }

void on_button_trim_in_set_clicked GtkButton *  button,
gpointer  user_data
 

Definition at line 213 of file page_trim.cc.

References KinoCommon::getPageTrim(), lookup_widget(), and TRIM_ADJ_IN.

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     }

void on_button_trim_insert_after_clicked GtkButton *  button,
gpointer  user_data
 

Definition at line 398 of file page_trim.cc.

References KinoCommon::getPageTrim(), lookup_widget(), and TRIM_INSERT_MODE_AFTER.

00400     {
00401         gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00402         common->getPageTrim()->insertScene( TRIM_INSERT_MODE_AFTER );
00403     }

void on_button_trim_insert_before_clicked GtkButton *  button,
gpointer  user_data
 

Definition at line 390 of file page_trim.cc.

References KinoCommon::getPageTrim(), lookup_widget(), and TRIM_INSERT_MODE_BEFORE.

00392     {
00393         gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00394         common->getPageTrim()->insertScene( TRIM_INSERT_MODE_BEFORE );
00395     }

void on_button_trim_open_clicked GtkButton *  button,
gpointer  user_data
 

Definition at line 378 of file page_trim.cc.

References KinoCommon::getFileToOpen(), and lookup_widget().

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     }

void on_button_trim_out_reset_clicked GtkButton *  button,
gpointer  user_data
 

Definition at line 205 of file page_trim.cc.

References KinoCommon::getPageTrim(), and lookup_widget().

00207     {
00208         gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( button ), "eventbox_trim" ) );
00209         common->getPageTrim() ->resetOutPoint();
00210     }

void on_button_trim_out_set_clicked GtkButton *  button,
gpointer  user_data
 

Definition at line 222 of file page_trim.cc.

References KinoCommon::getPageTrim(), lookup_widget(), and TRIM_ADJ_OUT.

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     }

void on_combo_trim_clip_entry_changed GtkEditable *  editable,
gpointer  user_data
 

Definition at line 337 of file page_trim.cc.

References AVI, KinoCommon::checkFile(), navigate_control::escaped, KinoCommon::getPageTrim(), KinoCommon::importFile(), lookup_widget(), QT, and RAW_DV.

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     }

gboolean on_combo_trim_clip_entry_focus_in_event GtkWidget *  widget,
GdkEventFocus *  event,
gpointer  user_data
 

Definition at line 302 of file page_trim.cc.

References navigate_control::escaped.

00305     {
00306         g_nav_ctl.escaped = TRUE;
00307         return FALSE;
00308     }

gboolean on_combo_trim_clip_entry_focus_out_event GtkWidget *  widget,
GdkEventFocus *  event,
gpointer  user_data
 

Definition at line 311 of file page_trim.cc.

References AVI, KinoCommon::checkFile(), navigate_control::escaped, KinoCommon::getPageTrim(), QT, and RAW_DV.

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     }

void on_entry_trim_in_activate GtkEntry *  entry,
gpointer  user_data
 

Definition at line 430 of file page_trim.cc.

References KinoCommon::getTime(), KinoCommon::getTimeFormat(), lookup_widget(), and on_spinbutton_trim_in_value_changed().

Referenced by on_entry_trim_in_focus_out_event().

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     }

gboolean on_entry_trim_in_focus_out_event GtkWidget *  widget,
GdkEventFocus *  event,
gpointer  user_data
 

Definition at line 440 of file page_trim.cc.

References navigate_control::escaped, and on_entry_trim_in_activate().

00443     {
00444         on_entry_trim_in_activate( GTK_ENTRY( widget ), NULL );
00445         g_nav_ctl.escaped = FALSE;
00446         return FALSE;
00447     }

void on_entry_trim_out_activate GtkEntry *  entry,
gpointer  user_data
 

Definition at line 450 of file page_trim.cc.

References KinoCommon::getTime(), KinoCommon::getTimeFormat(), lookup_widget(), and on_spinbutton_trim_out_value_changed().

Referenced by on_entry_trim_out_focus_out_event().

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     }

gboolean on_entry_trim_out_focus_out_event GtkWidget *  widget,
GdkEventFocus *  event,
gpointer  user_data
 

Definition at line 460 of file page_trim.cc.

References navigate_control::escaped, and on_entry_trim_out_activate().

00463     {
00464         on_entry_trim_out_activate( GTK_ENTRY( widget ), NULL );
00465         g_nav_ctl.escaped = FALSE;
00466         return FALSE;
00467     }

void on_menuitem_trim_insert_activate GtkMenuItem *  menuitem,
gpointer  user_data
 

Definition at line 414 of file page_trim.cc.

References KinoCommon::getPageTrim(), lookup_widget(), and PAGE_TRIM_MODE_INSERT.

00416     {
00417         gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( menuitem ), "eventbox_trim" ) );
00418         common->getPageTrim()->setMode( PAGE_TRIM_MODE_INSERT );
00419     }

void on_menuitem_trim_update_activate GtkMenuItem *  menuitem,
gpointer  user_data
 

Definition at line 406 of file page_trim.cc.

References KinoCommon::getPageTrim(), lookup_widget(), and PAGE_TRIM_MODE_UPDATE.

00408     {
00409         gtk_widget_grab_focus( lookup_widget( GTK_WIDGET( menuitem ), "eventbox_trim" ) );
00410         common->getPageTrim()->setMode( PAGE_TRIM_MODE_UPDATE );
00411     }

gboolean on_spinbutton_trim_in_focus_in_event GtkWidget *  widget,
GdkEventFocus *  event,
gpointer  user_data
 

Definition at line 243 of file page_trim.cc.

References navigate_control::escaped.

00246     {
00247         g_nav_ctl.escaped = TRUE;
00248         return FALSE;
00249     }

gboolean on_spinbutton_trim_in_focus_out_event GtkWidget *  widget,
GdkEventFocus *  event,
gpointer  user_data
 

Definition at line 252 of file page_trim.cc.

References navigate_control::escaped.

00255     {
00256         g_nav_ctl.escaped = FALSE;
00257         return FALSE;
00258     }

void on_spinbutton_trim_in_value_changed GtkSpinButton *  spinbutton,
gpointer  user_data
 

Definition at line 169 of file page_trim.cc.

References KinoCommon::getTime(), KinoCommon::getTimeFormat(), lookup_widget(), and TRIM_ADJ_IN.

Referenced by on_entry_trim_in_activate(), and PageTrim::timeFormatChanged().

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     }

gboolean on_spinbutton_trim_out_focus_in_event GtkWidget *  widget,
GdkEventFocus *  event,
gpointer  user_data
 

Definition at line 261 of file page_trim.cc.

References navigate_control::escaped.

00264     {
00265         g_nav_ctl.escaped = TRUE;
00266         return FALSE;
00267     }

gboolean on_spinbutton_trim_out_focus_out_event GtkWidget *  widget,
GdkEventFocus *  event,
gpointer  user_data
 

Definition at line 271 of file page_trim.cc.

References navigate_control::escaped.

00274     {
00275         g_nav_ctl.escaped = FALSE;
00276         return FALSE;
00277     }

void on_spinbutton_trim_out_value_changed GtkSpinButton *  spinbutton,
gpointer  user_data
 

Definition at line 183 of file page_trim.cc.

References KinoCommon::getTime(), KinoCommon::getTimeFormat(), lookup_widget(), and TRIM_ADJ_OUT.

Referenced by on_entry_trim_out_activate(), and PageTrim::timeFormatChanged().

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     }

void on_togglebutton_trim_link_toggled GtkToggleButton *  togglebutton,
gpointer  user_data
 

Definition at line 231 of file page_trim.cc.

References lookup_widget().

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     }

gboolean on_trim_button_press_event GtkWidget *  widget,
GdkEventButton *  event,
gpointer  user_data
 

Definition at line 280 of file page_trim.cc.

References videoPause().

Referenced by PageTrim::PageTrim().

00283     {
00284         doScrub = TRUE;
00285         videoPause();
00286         return FALSE;
00287     }

gboolean on_trim_button_release_event GtkWidget *  widget,
GdkEventButton *  event,
gpointer  user_data
 

Definition at line 291 of file page_trim.cc.

Referenced by PageTrim::PageTrim().

00294     {
00295         doScrub = FALSE;
00296         return FALSE;
00297     }

gboolean on_trim_value_changed_event GtkWidget *  widget,
GdkEventButton *  event,
gpointer  user_data
 

Definition at line 85 of file page_trim.cc.

References KinoCommon::getPageTrim(), TRIM_ADJ_IN, and TRIM_ADJ_OUT.

Referenced by PageTrim::PageTrim().

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     }

static void * readThread void *  info  )  [static]
 

This function carries out the read ahead and is responsible for obtaining the each frame.

audioThread monitors the queue (by checking mainly on pending) and plays the audio of each frame. videoThread picks up the last tail and displays it.

Note that only half of the queue is filled here - this provides the video thread some time to safely use a frame without worrying about it being overwritten.

Definition at line 2008 of file page_trim.cc.

References _getOneSecond(), navigate_control::active, common, countFrames(), Preferences::dropFrame, Preferences::enableAudio, frameContent, Preferences::getInstance(), KinoCommon::getPageTrim(), lastFrame, loop_toggle, newFrame, PLAYBACK_FRAMES, navigate_control::rate, readlock, IEEE1394Writer::SendFrame(), navigate_control::step, navigate_control::subframe, threadlock, and writer1394.

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         // cerr << ">>> Starting read thread " << endl;
02019 
02020         // Get start of time
02021         struct timeval start;
02022         struct timeval end;
02023         gettimeofday( &start, NULL );
02024 
02025         // Loop while active
02026         while ( ctl->active )
02027         {
02028 
02029             // Calculate time for next frame
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             // Determine the frame to render
02039             newFrame = lastFrame + ctl->step;
02040 
02041             // determine new frame based upon jogshuttle rate
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             // Check the bounds and adjust as necessary
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             // Determine which locations in frameNumber and frameContent we need to use
02077             if ( pending >= PLAYBACK_FRAMES / 2 )
02078             {
02079                 // Queue is full.. do nothing
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                 //cerr << "captured pending = " << pending << " new_head = " << new_head << " tail = " << tail << endl;
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                 // Inform the audio thread that it's got something to work with
02106                 playing = true;
02107 
02108                 // Render all frames if requested
02109                 if ( ( ! prefs.dropFrame || ! prefs.enableAudio ) && ctl->active )
02110                 {
02111 
02112                     // Change the queue position
02113                     tail = ( tail + 1 ) % PLAYBACK_FRAMES;
02114                     pending --;
02115 
02116                     // Set the current position
02117                     common->getPageTrim() ->setPosition( frameNumber[ tail ] );
02118 
02119                     // If audio is enabled and some other conditions
02120                     if ( prefs.enableAudio && ( frameNumber[ tail ] != lastFrame || ctl->rate > 1 || ctl->rate < -1 ) )
02121                         common->getPageTrim() ->getFrameDisplayer() ->PutSound( *frameContent[ tail ] );
02122 
02123                     // Show the corresponding image
02124                     gdk_threads_enter();
02125                     common->getPageTrim() ->showFrame( frameNumber[ tail ], *frameContent[ tail ] );
02126                     gdk_flush();
02127                     gdk_threads_leave();
02128 
02129                     // Determine how far from the next frame we really are
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                         // Sleep for half the remaining time when audio is disabled
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                 // update the lastFrame and lastPos variables
02152                 lastFrame = newFrame;
02153 
02154                 // Incrment the frame count
02155                 countFrames ++;
02156             }
02157         }
02158 
02159         // cerr << ">>> Ending reading thread" << endl;
02160 
02161         return NULL;
02162     }

static void resetThreads  )  [static]
 

Definition at line 1990 of file page_trim.cc.

01991     {
01992         showing = false;
01993         playing = false;
01994         pending = 0;
01995         head = 0;
01996         tail = 0;
01997     }

static void * videoThread void *  info  )  [static]
 

Definition at line 2252 of file page_trim.cc.

References navigate_control::active, common, count, Preferences::dropFrame, Preferences::enableAudio, frameContent, Preferences::getInstance(), KinoCommon::getPageTrim(), lastFrame, navigate_control::rate, and navigate_control::step.

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         // Statistical analysis variables
02261         int dropped = 0;
02262         int count = 0;
02263 #endif
02264 
02265         // cerr << ">>> Starting video thread" << endl;
02266 
02267         while ( ctl->active )
02268         {
02269 
02270             // Only do this when drop frames is active (otherwise the audio thread takes care of it)
02271             if ( prefs.dropFrame && prefs.enableAudio )
02272             {
02273 
02274                 if ( showing && pending > 0 )
02275                 {
02276 
02277                     // Store the current tail
02278                     int my_tail = tail;
02279 
02280                     // As long as its different to the previous one, then display it
02281                     if ( frameNumber[ my_tail ] != lastFrame || ctl->rate > 1 )
02282                     {
02283 #ifdef PLAY_WITH_STATS
02284                         // Statistical analysis of frame playback (useful for limited kinds of tests)
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                         // Show this frame
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                 // Release thread
02309                 struct timespec t = { 0, 0 };
02310