X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmelt%2Fmelt.c;h=4526090d9ab148d49276944c523da1814a66fb87;hb=6f8293d53fc21742d9d43f94f0e590e1bfcb8ee0;hp=5ff487ea1e94cf0690e383baf4628370269e5ef8;hpb=641389092e8f7a12c438813317adfabe0725bd2a;p=mlt diff --git a/src/melt/melt.c b/src/melt/melt.c index 5ff487ea..4526090d 100644 --- a/src/melt/melt.c +++ b/src/melt/melt.c @@ -1,6 +1,6 @@ /* * melt.c -- MLT command line utility - * Copyright (C) 2002-2011 Ushodaya Enterprises Limited + * Copyright (C) 2002-2013 Ushodaya Enterprises Limited * Authors: Charles Yates * Dan Dennedy * @@ -29,22 +29,43 @@ #include #include #include +#include #include -#if defined(__DARWIN__) || defined(WIN32) +#if (defined(__DARWIN__) || defined(WIN32)) && !defined(MELT_NOSDL) #include #endif #include "io.h" +static mlt_producer melt = NULL; + +static void stop_handler(int signum) +{ + if ( melt ) + { + mlt_properties properties = MLT_PRODUCER_PROPERTIES( melt ); + mlt_properties_set_int( properties, "done", 1 ); + } +} + +static void abnormal_exit_handler(int signum) +{ + // The process is going down hard. Restore the terminal first. + term_exit(); + // Reset the default handler so the core gets dumped. + signal( signum, SIG_DFL ); + raise( signum ); +} + static void transport_action( mlt_producer producer, char *value ) { mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); mlt_multitrack multitrack = mlt_properties_get_data( properties, "multitrack", NULL ); mlt_consumer consumer = mlt_properties_get_data( properties, "transport_consumer", NULL ); mlt_properties jack = mlt_properties_get_data( MLT_CONSUMER_PROPERTIES( consumer ), "jack_filter", NULL ); - mlt_position position = mlt_producer_position( producer ); + mlt_position position = producer? mlt_producer_position( producer ) : 0; mlt_properties_set_int( properties, "stats_off", 1 ); @@ -79,6 +100,7 @@ static void transport_action( mlt_producer producer, char *value ) case '5': mlt_producer_set_speed( producer, 0 ); mlt_consumer_purge( consumer ); + mlt_producer_seek( producer, mlt_consumer_position( consumer ) + 1 ); mlt_events_fire( jack, "jack-stop", NULL ); break; case '6': @@ -262,7 +284,59 @@ static mlt_consumer create_consumer( mlt_profile profile, char *id ) static void load_consumer( mlt_consumer *consumer, mlt_profile profile, int argc, char **argv ) { int i; - for ( i = 1; i < argc; i ++ ) + int multi = 0; + int qglsl = 0; + + for ( i = 1; i < argc; i ++ ) { + // See if we need multi consumer. + multi += !strcmp( argv[i], "-consumer" ); + // Seee if we need the qglsl variant of multi consumer. + if ( !strncmp( argv[i], "glsl.", 5 ) || !strncmp( argv[i], "movit.", 6 ) ) + qglsl = 1; + } + // Disable qglsl if xgl is being used! + for ( i = 1; qglsl && i < argc; i ++ ) + if ( !strcmp( argv[i], "xgl" ) ) + qglsl = 0; + + if ( multi > 1 || qglsl ) + { + // If there is more than one -consumer use the 'multi' consumer. + int k = 0; + char key[20]; + + if ( *consumer ) + mlt_consumer_close( *consumer ); + *consumer = create_consumer( profile, ( qglsl? "qglsl" : "multi" ) ); + mlt_properties properties = MLT_CONSUMER_PROPERTIES( *consumer ); + for ( i = 1; i < argc; i ++ ) + { + if ( !strcmp( argv[ i ], "-consumer" ) && argv[ i + 1 ]) + { + // Create a properties object for each sub-consumer + mlt_properties new_props = mlt_properties_new(); + snprintf( key, sizeof(key), "%d", k++ ); + mlt_properties_set_data( properties, key, new_props, 0, + (mlt_destructor) mlt_properties_close, NULL ); + if ( strchr( argv[i + 1], ':' ) ) + { + char *temp = strdup( argv[++i] ); + char *service = temp; + char *target = strchr( temp, ':' ); + *target++ = 0; + mlt_properties_set( new_props, "mlt_service", service ); + mlt_properties_set( new_props, "target", target ); + } + else + { + mlt_properties_set( new_props, "mlt_service", argv[ ++i ] ); + } + while ( argv[ i + 1 ] && strchr( argv[ i + 1 ], '=' ) ) + mlt_properties_parse( new_props, argv[ ++ i ] ); + } + } + } + else for ( i = 1; i < argc; i ++ ) { if ( !strcmp( argv[ i ], "-consumer" ) ) { @@ -272,14 +346,14 @@ static void load_consumer( mlt_consumer *consumer, mlt_profile profile, int argc if ( *consumer ) { mlt_properties properties = MLT_CONSUMER_PROPERTIES( *consumer ); - while ( argv[ i + 1 ] != NULL && strstr( argv[ i + 1 ], "=" ) ) + while ( argv[ i + 1 ] != NULL && strchr( argv[ i + 1 ], '=' ) ) mlt_properties_parse( properties, argv[ ++ i ] ); } } } } -#if defined(__DARWIN__) || defined(WIN32) +#if (defined(__DARWIN__) || defined(WIN32)) && !defined(MELT_NOSDL) static void event_handling( mlt_producer producer, mlt_consumer consumer ) { @@ -311,7 +385,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer ); int silent = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( consumer ), "silent" ); int progress = mlt_properties_get_int( MLT_CONSUMER_PROPERTIES( consumer ), "progress" ); - struct timespec tm = { 0, 40000 }; + struct timespec tm = { 0, 40000000 }; int total_length = mlt_producer_get_length( producer ); int last_position = 0; @@ -343,7 +417,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) transport_action( producer, string ); } -#if defined(__DARWIN__) || defined(WIN32) +#if (defined(__DARWIN__) || defined(WIN32)) && !defined(MELT_NOSDL) event_handling( producer, consumer ); #endif @@ -354,8 +428,9 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) int current_position = mlt_producer_position( producer ); if ( current_position > last_position ) { - fprintf( stderr, "Current Frame: %10d, percentage: %10d\r", - current_position, 100 * current_position / total_length ); + fprintf( stderr, "Current Frame: %10d, percentage: %10d%c", + current_position, 100 * current_position / total_length, + progress == 2 ? '\n' : '\r' ); last_position = current_position; } } @@ -363,6 +438,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer ) { fprintf( stderr, "Current Position: %10d\r", (int)mlt_consumer_position( consumer ) ); } + fflush( stderr ); } if ( silent || progress ) @@ -610,15 +686,13 @@ static void query_vcodecs( ) static void on_fatal_error( mlt_properties owner, mlt_consumer consumer ) { - mlt_consumer_stop( consumer ); - exit( EXIT_FAILURE ); + mlt_properties_set_int( MLT_CONSUMER_PROPERTIES(consumer), "done", 1 ); } int main( int argc, char **argv ) { int i; mlt_consumer consumer = NULL; - mlt_producer melt = NULL; FILE *store = NULL; char *name = NULL; mlt_profile profile = NULL; @@ -626,10 +700,15 @@ int main( int argc, char **argv ) int is_silent = 0; mlt_profile backup_profile; + // Handle abnormal exit situations. + signal( SIGSEGV, abnormal_exit_handler ); + signal( SIGILL, abnormal_exit_handler ); + signal( SIGABRT, abnormal_exit_handler ); + // Construct the factory mlt_repository repo = mlt_factory_init( NULL ); -#ifdef WIN32 +#if defined(WIN32) && !defined(MELT_NOSDL) is_silent = 1; #endif @@ -659,6 +738,10 @@ int main( int argc, char **argv ) { is_progress = 1; } + else if ( !strcmp( argv[ i ], "-progress2" ) ) + { + is_progress = 2; + } // Look for the query option else if ( !strcmp( argv[ i ], "-query" ) ) { @@ -722,8 +805,8 @@ query_all: } else if ( !strcmp( argv[ i ], "-version" ) || !strcmp( argv[ i ], "--version" ) ) { - fprintf( stdout, "MLT %s " VERSION "\n" - "Copyright (C) 2002-2011 Ushodaya Enterprises Limited\n" + fprintf( stdout, "%s " VERSION "\n" + "Copyright (C) 2002-2013 Ushodaya Enterprises Limited\n" "\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", @@ -735,7 +818,7 @@ query_all: mlt_log_set_level( MLT_LOG_DEBUG ); } } - if ( !is_silent && !isatty( STDIN_FILENO ) ) + if ( !is_silent && !isatty( STDIN_FILENO ) && !is_progress ) is_progress = 1; // Create profile if not set explicitly @@ -780,6 +863,18 @@ query_all: // The producer or auto-profile could have changed the profile. load_consumer( &consumer, profile, argc, argv ); + // See if producer has consumer already attached + if ( !store && !consumer ) + { + consumer = MLT_CONSUMER( mlt_service_consumer( MLT_PRODUCER_SERVICE( melt ) ) ); + if ( consumer ) + { + mlt_properties_inc_ref( MLT_CONSUMER_PROPERTIES(consumer) ); // because we explicitly close it + mlt_properties_set_data( MLT_CONSUMER_PROPERTIES(consumer), + "transport_callback", transport_action, 0, NULL, NULL ); + } + } + // If we have no consumer, default to sdl if ( store == NULL && consumer == NULL ) consumer = create_consumer( profile, NULL ); @@ -847,6 +942,14 @@ query_all: mlt_events_listen( properties, consumer, "consumer-fatal-error", ( mlt_listener )on_fatal_error ); if ( mlt_consumer_start( consumer ) == 0 ) { + // Try to exit gracefully upon these signals + signal( SIGINT, stop_handler ); + signal( SIGTERM, stop_handler ); +#ifndef WIN32 + signal( SIGHUP, stop_handler ); + signal( SIGPIPE, stop_handler ); +#endif + // Transport functionality transport( melt, consumer ); @@ -865,6 +968,13 @@ query_all: show_usage( argv[0] ); } + // Disconnect producer from consumer to prevent ref cycles from closing services + if ( consumer ) + { + mlt_consumer_connect( consumer, NULL ); + mlt_events_fire( MLT_CONSUMER_PROPERTIES(consumer), "consumer-cleanup", NULL); + } + // Close the producer if ( melt != NULL ) mlt_producer_close( melt ); @@ -877,8 +987,11 @@ query_all: mlt_profile_close( profile ); exit_factory: - + +// Workaround qmelt on OS X from crashing at exit. +#if !defined(__MACH__) || !defined(QT_GUI_LIB) mlt_factory_close( ); +#endif return 0; }