00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include <config.h>
00022 #endif
00023
00024 #include <iostream>
00025 using std::cerr;
00026 using std::endl;
00027
00028
00029 #include "kino_common.h"
00030 #include "page.h"
00031 #include "page_editor.h"
00032 #include "page_capture.h"
00033 #include "page_timeline.h"
00034 #include "page_export.h"
00035 #include "preferences.h"
00036 #include "avi.h"
00037 #include "filehandler.h"
00038 #include "ieee1394io.h"
00039 #include "message.h"
00040 #include "jogshuttle.h"
00041
00042 extern "C"
00043 {
00044
00045 #include <sys/stat.h>
00046 #include <sys/time.h>
00047 #include <gtk/gtk.h>
00048 #include <math.h>
00049
00050 #include "callbacks.h"
00051 #include "support.h"
00052 #include "commands.h"
00053 #include "jogshuttle.h"
00054 #include "gtkenhancedscale.h"
00055
00056 extern struct navigate_control g_nav_ctl;
00057
00058 KinoCommon *common = NULL;
00059
00060 static void getDroppedFiles( GtkWidget * w, GdkDragContext * context,
00061 gint x, gint y, GtkSelectionData * data, guint info,
00062 guint time, gpointer * extra )
00063 {
00064
00065 if ( data->data )
00066 {
00067 gchar** urls = g_strsplit( ( gchar* ) data->data, "\n", 0 );
00068 gchar** tmp = urls;
00069 char *argv[ 2 ];
00070
00071
00072 while ( tmp )
00073 {
00074 if ( strcmp( *tmp, "" ) == 0 )
00075 break;
00076 if ( !strncmp( *tmp, "file:", 5 ) )
00077 {
00078 argv[ 1 ] = *tmp + 5;
00079 argv[ 1 ][ strlen( argv[ 1 ] ) - 1 ] = '\0';
00080 common->bulkLoad( 2, argv );
00081 }
00082 tmp++;
00083 };
00084 g_strfreev( urls );
00085 windowMoved();
00086 gtk_drag_finish( context, TRUE, FALSE, time );
00087 }
00088 gtk_drag_finish( context, FALSE, FALSE, time );
00089 }
00090
00091 void kinoInitialise( GtkWidget * widget )
00092 {
00093 common = new KinoCommon( widget );
00094 common->setWindowTitle( );
00095 JogShuttle::getInstance();
00096 if ( ! Preferences::getInstance().enableV4L )
00097 {
00098 GtkWidget *widget2 = lookup_widget( widget, "menuitem_v4l" );
00099 gtk_container_remove( GTK_CONTAINER( widget2->parent ), widget2 );
00100 gtk_notebook_remove_page( GTK_NOTEBOOK( lookup_widget( widget, "main_notebook" ) ), PAGE_BTTV );
00101 }
00102
00103
00104 static GtkTargetEntry file_targets[] = {
00105 {"text/uri-list", 0, 0}
00106 };
00107
00108 g_signal_connect( G_OBJECT( widget ), "drag_data_received",
00109 G_CALLBACK( getDroppedFiles ), NULL );
00110 gtk_drag_dest_set( GTK_WIDGET( widget ),
00111 ( GtkDestDefaults ) ( GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT |
00112 GTK_DEST_DEFAULT_DROP ), file_targets, 1,
00113 ( GdkDragAction ) ( GDK_ACTION_COPY | GDK_ACTION_MOVE ) );
00114 g_signal_connect( G_OBJECT( lookup_widget( widget, "main_notebook" ) ), "drag_data_received",
00115 G_CALLBACK( getDroppedFiles ), NULL );
00116 gtk_drag_dest_set( GTK_WIDGET( lookup_widget( widget, "main_notebook" ) ),
00117 ( GtkDestDefaults ) ( GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT |
00118 GTK_DEST_DEFAULT_DROP ), file_targets, 1,
00119 ( GdkDragAction ) ( GDK_ACTION_COPY | GDK_ACTION_MOVE ) );
00120 gtk_window_set_default_size( GTK_WINDOW( widget ),
00121 Preferences::getInstance().windowWidth, Preferences::getInstance().windowHeight );
00122 gtk_paned_set_position( GTK_PANED( lookup_widget( widget , "hpaned1" ) ),
00123 Preferences::getInstance().storyboardPosition );
00124
00125 if ( ! Preferences::getInstance().enablePublish )
00126 {
00127 GtkWidget *widget2 = lookup_widget( widget, "button_publish_project" );
00128 gtk_container_remove( GTK_CONTAINER( widget2->parent ), widget2 );
00129 widget2 = lookup_widget( widget, "button_publish_still" );
00130 gtk_container_remove( GTK_CONTAINER( widget2->parent ), widget2 );
00131 widget2 = lookup_widget( widget, "publish_project" );
00132 gtk_container_remove( GTK_CONTAINER( widget2->parent ), widget2 );
00133 widget2 = lookup_widget( widget, "publish_still" );
00134 gtk_container_remove( GTK_CONTAINER( widget2->parent ), widget2 );
00135 }
00136 common->updateRecentFiles();
00137 }
00138
00139 void kinoPostInit()
00140 {
00141 common->setPreviewSize( float( Preferences::getInstance().previewSize ) / 10.0, true );
00142 notebookChangePage( PAGE_EDITOR );
00143 }
00144
00145 gboolean kinoDeactivate()
00146 {
00147 if ( common->exitKino( ) )
00148 {
00149 cerr << "Exiting Kino\n";
00150 gtk_window_get_size( GTK_WINDOW( common->getWidget() ), &Preferences::getInstance().windowWidth,
00151 &Preferences::getInstance().windowHeight );
00152 Preferences::getInstance().storyboardPosition = gtk_paned_get_position( GTK_PANED(
00153 lookup_widget( common->getWidget() , "hpaned1" ) ) );
00154 Preferences::getInstance().Save();
00155 gtk_main_quit();
00156 }
00157 return TRUE;
00158 }
00159
00160 void bulkLoad( int argc, char * argv[] )
00161 {
00162 if ( GetEditorBackup()->Restore( common->getPlayList() ) )
00163 {
00164 common->g_currentFrame = 0;
00165 common->hasListChanged = TRUE;
00166 common->setWindowTitle();
00167 modal_message( _( "Kino has recovered from a crash and restored your undo history!" ) );
00168 }
00169 else
00170 {
00171 common->newFile();
00172 common->bulkLoad( argc, argv );
00173 }
00174 }
00175
00176 void newFile( )
00177 {
00178 common->newFile();
00179 }
00180
00181 void openFile( )
00182 {
00183 common->loadFile();
00184 }
00185
00186 void savePlayListAs( )
00187 {
00188 common->savePlayListAs();
00189 }
00190
00191 void savePlayList( )
00192 {
00193 common->savePlayList();
00194 }
00195
00196 void saveFrame( )
00197 {
00198 common->saveFrame();
00199 }
00200
00201 void insertFile( )
00202 {
00203 common->moveToFrame( common->getPlayList() ->FindStartOfScene( common->g_currentFrame ) );
00204 common->insertFile();
00205 }
00206
00207 void appendFile( )
00208 {
00209 common->moveToFrame( common->getPlayList() ->FindEndOfScene( common->g_currentFrame ) );
00210 common->appendFile();
00211 }
00212
00213 void pageStart( int page )
00214 {
00215 common->setCurrentPage( page );
00216 }
00217
00218 int moveToFrame( int frame )
00219 {
00220 return common->moveToFrame( frame );
00221 }
00222
00223 int moveByFrames( int offs )
00224 {
00225 return common->moveByFrames( offs );
00226 }
00227
00228 void videoStart( )
00229 {
00230 common->videoStartOfMovie();
00231 }
00232
00233 void videoPreviousScene( )
00234 {
00235 common->videoPreviousScene();
00236 }
00237
00238 void videoStartOfScene( )
00239 {
00240 common->videoStartOfScene();
00241 }
00242
00243 void videoRewind( )
00244 {
00245 common->videoRewind();
00246 }
00247
00248 void videoBack()
00249 {
00250 common->videoBack(-1);
00251 }
00252 void videoBackBy(int step)
00253 {
00254 common->videoBack(step);
00255 }
00256
00257 void videoPlay( )
00258 {
00259 common->videoPlay();
00260 }
00261
00262 void videoForward()
00263 {
00264 common->videoForward(1);
00265 }
00266 void videoForwardBy(int step)
00267 {
00268 common->videoForward(step);
00269 }
00270
00271 void videoFastForward( )
00272 {
00273 common->videoFastForward();
00274 }
00275
00276 void videoNextScene( )
00277 {
00278 common->videoNextScene();
00279 }
00280
00281 void videoEndOfScene( )
00282 {
00283 common->videoEndOfScene();
00284 }
00285
00286 void videoEndOfMovie( )
00287 {
00288 common->videoEndOfMovie();
00289 }
00290
00291 void videoStop( )
00292 {
00293 common->videoStop();
00294 }
00295
00296 void videoPause( )
00297 {
00298 common->videoPause();
00299 }
00300
00301 void videoShuttle( int angle )
00302 {
00303 common->videoShuttle( angle );
00304 }
00305
00306 void windowMoved()
00307 {
00308 if ( common )
00309 common->windowMoved();
00310 }
00311
00312 void visibilityChanged( gboolean visible )
00313 {
00314 common->visibilityChanged( visible );
00315 }
00316
00317 void notebookChangePage( int page )
00318 {
00319 common->changePageRequest( page );
00320 }
00321
00322 gboolean processKeyboard( GdkEventKey * event )
00323 {
00324
00325
00326
00327
00328
00329 if ( Preferences::getInstance().disableKeyRepeat && gdk_events_pending() )
00330 return TRUE;
00331
00332 return common->processKeyboard( event );
00333 }
00334
00335 void processCommand( char * command )
00336 {
00337 if ( strcmp( command, "Ctrl+W" ) == 0 )
00338 publishPlayList();
00339 else
00340 common->processCommand( command );
00341 }
00342
00343 void selectScene( int i )
00344 {
00345 common->selectScene( i );
00346 }
00347
00348 void startCapture( void )
00349 {
00350 common->getPageCapture() ->startCapture();
00351 }
00352
00353 void stopCapture( void )
00354 {
00355 common->getPageCapture() ->stopCapture();
00356 }
00357
00358 void setPreviewSize( float factor )
00359 {
00360 common->setPreviewSize( factor );
00361 }
00362
00363 void previewExport( void )
00364 {
00365 common->getPageExport() ->previewExport();
00366 }
00367
00368 void startExport( void )
00369 {
00370 common->getPageExport() ->startExport();
00371 }
00372 void stopExport( void )
00373 {
00374 common->getPageExport() ->stopExport();
00375 }
00376
00377 void pauseExport( void )
00378 {
00379 common->getPageExport() ->pauseExport();
00380 }
00381
00382 void setExportMode( int mode )
00383 {
00384 common->getPageExport() ->setCurrentMode( mode );
00385 }
00386
00387 void RefreshBar( GtkWidget * drawingarea )
00388 {
00389 common->getPageEditor() ->DrawBar( common->g_currentFrame );
00390 }
00391
00392 void setMoreInfo( int state )
00393 {
00394 common->setMoreInfo( state == 1 );
00395 Frame &frame = *( GetFramePool( ) ->GetFrame( ) );
00396 common->showFrameMoreInfo( frame, NULL );
00397 GetFramePool( ) ->DoneWithFrame( &frame );
00398 common->moveToFrame();
00399 }
00400
00401 void setTimeFormat( int format )
00402 {
00403 common->setTimeFormat( static_cast< SMIL::Time::TimeFormat >( format ) );
00404 }
00405
00406 void publishPlayList( void )
00407 {
00408 common->publishPlayList( );
00409 }
00410
00411 void publishFrame( void )
00412 {
00413 common->publishFrame( );
00414 }
00415
00416 void startJogShuttle( void )
00417 {
00418 JogShuttle::getInstance().start();
00419 }
00420
00421 void showHelp( const char *page )
00422 {
00423 extern char* g_help_language;
00424 std::string cmd = "\"" DATADIR "/kino/scripts/help.sh\" \"file://" DATADIR "/kino/help/";
00425 if ( page == NULL || strcmp( page, "" ) == 0 )
00426 page = common->getCurrentPage()->getHelpPage().c_str();
00427 cmd += std::string( g_help_language ) + std::string( "\" \"" ) + std::string( page ) + "\" &";
00428 system( cmd.c_str() );
00429 }
00430
00431 void handleMouseScroll( GdkEvent *event )
00432 {
00433 if ( Preferences::getInstance().enableJogShuttle )
00434 return;
00435
00436 if ( event->scroll.state & GDK_SHIFT_MASK )
00437 {
00438 if ( event->scroll.direction == GDK_SCROLL_UP )
00439 videoBack( );
00440 else if ( event->scroll.direction == GDK_SCROLL_DOWN )
00441 videoForward( );
00442 }
00443 else if ( event->scroll.state & GDK_CONTROL_MASK )
00444 {
00445 int speedTable[] = {
00446 0,
00447 8, 10, 16, 20, 33, 50, 75,
00448 100,
00449 200, 300, 400, 500, 800, 1200,
00450 3001 };
00451 int i = 0;
00452 int speed;
00453 int direction;
00454
00455 if ( g_nav_ctl.active == FALSE )
00456 {
00457 speed = 8;
00458 direction = ( event->scroll.direction == GDK_SCROLL_UP ? -1 : 1 );
00459 }
00460 else if ( g_nav_ctl.step == 0 )
00461 {
00462 speed = 100 / ( g_nav_ctl.rate < 0 ? -g_nav_ctl.rate : g_nav_ctl.rate );
00463 speed = speed == 100 ? 75 : speed;
00464 direction = g_nav_ctl.rate < 0 ? -1 : 1;
00465 }
00466 else
00467 {
00468 speed = ( g_nav_ctl.step < 0 ? -g_nav_ctl.step : g_nav_ctl.step ) * 100;
00469 direction = g_nav_ctl.step < 0 ? -1 : 1;
00470 }
00471
00472 while ( i < 16 && speedTable[ i ] < speed )
00473 ++i;
00474
00475 i *= direction;
00476
00477
00478 if ( event->scroll.direction == GDK_SCROLL_UP )
00479 videoShuttle( -- i );
00480 else if ( event->scroll.direction == GDK_SCROLL_DOWN )
00481 videoShuttle( ++ i );
00482 }
00483 else
00484 {
00485 if ( event->scroll.direction == GDK_SCROLL_UP )
00486 videoBackBy( -10 );
00487 else if ( event->scroll.direction == GDK_SCROLL_DOWN )
00488 videoForwardBy( 10 );
00489 }
00490 }
00491
00492 int kino2raw( char* filename, char* option )
00493 {
00494 try
00495 {
00496 PlayList playlist;
00497 Frame frame;
00498 AudioInfo info;
00499
00500 if ( playlist.LoadPlayList( filename ) )
00501 {
00502 const double outputRate = 32000;
00503 playlist.GetFrame( 0, frame );
00504
00505 if ( option )
00506 {
00507 if ( strcmp( option, "aspect" ) == 0 )
00508 {
00509 std::cout << ( frame.IsWide() ? "16:9" : "4:3" ) << std::endl;
00510 }
00511 else if ( strcmp( option, "normalisation" ) == 0 )
00512 {
00513 std::cout << ( frame.IsPAL() ? "pal" : "ntsc" ) << std::endl;
00514 }
00515 return 0;
00516 }
00517
00518 frame.GetAudioInfo( info );
00519 info.frequency = int( outputRate );
00520
00521 double adjustedRate = 0.0;
00522 {
00523 double seconds = double( playlist.GetNumFrames() ) / frame.GetFrameRate();
00524 int64_t idealSamples = int64_t( seconds * outputRate + 0.5 );
00525 int64_t actualSamples = 0;
00526 int n = -1, frameNum = 0, previousProgress = -1;
00527 AsyncAudioResample<int16_ne_t,int16_le_t> resampler(
00528 AUDIO_RESAMPLE_SRC_SINC_FASTEST, &playlist, outputRate, 0, playlist.GetNumFrames() - 1, 1 );
00529 char buf[ 512 ];
00530
00531
00532 while ( n != 0 )
00533 {
00534 n = resampler.Process( outputRate, frame.CalculateNumberSamples( int( outputRate ), frameNum++ ) );
00535 actualSamples += n;
00536 int progress = int( double( frameNum ) / playlist.GetNumFrames() * 100 );
00537 if ( progress != previousProgress )
00538 {
00539 previousProgress = progress;
00540 snprintf( buf, 512, "\r%s (%02d%%)", _("Locking audio"), progress );
00541 std::cerr << buf;
00542 }
00543 }
00544 adjustedRate = outputRate + ( idealSamples - actualSamples ) / seconds;
00545 std::cerr << std::endl;
00546 }
00547
00548
00549 int16_le_t *audio_buffers[ 4 ];
00550 for ( int c = 0; c < 4; c++ )
00551 audio_buffers[ c ] = new int16_le_t[ 2 * DV_AUDIO_MAX_SAMPLES ];
00552
00553
00554 AsyncAudioResample<int16_ne_t,int16_le_t> resampler(
00555 AUDIO_RESAMPLE_SRC_SINC_BEST_QUALITY, &playlist, adjustedRate, 0, playlist.GetNumFrames() - 1, 1 );
00556 if ( resampler.IsError() )
00557 {
00558 std::cerr << "Resampler error: " << resampler.GetError() << std::endl;
00559 for ( int c = 0; c < 4; c++ )
00560 delete[] audio_buffers[ c ];
00561 return 4;
00562 }
00563
00564 for ( int i = 0; i < playlist.GetNumFrames(); ++i )
00565 {
00566
00567 int requestedSamples = frame.CalculateNumberSamples( int( outputRate ), i );
00568
00569 playlist.GetFrame( i, frame );
00570 info.samples = resampler.Process( adjustedRate, requestedSamples );
00571 if ( info.samples )
00572 {
00573
00574 int16_le_t *p = resampler.GetOutput();
00575 for ( int s = 0; s < info.samples; s++ )
00576 for ( int c = 0; c < info.channels; c++ )
00577 audio_buffers[ c ][ s ] = *p++;
00578
00579 frame.EncodeAudio( info, audio_buffers );
00580 }
00581 if ( !fwrite( frame.data, frame.GetFrameSize(), 1, stdout ) )
00582 {
00583 perror( "Failed to write raw DV" );
00584 for ( int c = 0; c < 4; c++ )
00585 delete[] audio_buffers[ c ];
00586 return 2;
00587 }
00588 }
00589
00590
00591 for ( int c = 0; c < 4; c++ )
00592 delete[] audio_buffers[ c ];
00593 }
00594 }
00595 catch (...)
00596 {
00597 std::cerr << "General Error" << std::endl;
00598 return 3;
00599 }
00600 return 0;
00601 }
00602
00603 }