inigo.c: fix querying on specific filter or transition
[melted] / src / inigo / inigo.c
index 291e1a4..5adfc44 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * inigo.c -- MLT command line utility
+ * Copyright (C) 2002-2003 Ushodaya Enterprises Limited
+ * Author: Charles Yates <charles.yates@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -136,18 +156,16 @@ static void transport_action( mlt_producer producer, char *value )
        mlt_properties_set_int( properties, "stats_off", 0 );
 }
 
-static mlt_consumer create_consumer( char *id, mlt_producer producer )
+static mlt_consumer create_consumer( mlt_profile profile, char *id )
 {
        char *arg = id != NULL ? strchr( id, ':' ) : NULL;
        if ( arg != NULL )
                *arg ++ = '\0';
-       mlt_consumer consumer = mlt_factory_consumer( id, arg );
+       mlt_consumer consumer = mlt_factory_consumer( profile, id, arg );
        if ( consumer != NULL )
        {
                mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
                mlt_properties_set_data( properties, "transport_callback", transport_action, 0, NULL, NULL );
-               mlt_properties_set_data( properties, "transport_producer", producer, 0, NULL, NULL );
-               mlt_properties_set_data( MLT_PRODUCER_PROPERTIES( producer ), "transport_consumer", consumer, 0, NULL, NULL );
        }
        return consumer;
 }
@@ -183,11 +201,14 @@ 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 };
+       int total_length = mlt_producer_get_length( producer );
+       int last_position = 0;
 
        if ( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) )
        {
-               if ( !silent )
+               if ( !silent && !progress )
                {
                        term_init( );
 
@@ -205,7 +226,7 @@ static void transport( mlt_producer producer, mlt_consumer consumer )
 
                while( mlt_properties_get_int( properties, "done" ) == 0 && !mlt_consumer_is_stopped( consumer ) )
                {
-                       int value = silent ? -1 : term_read( );
+                       int value = ( silent || progress )? -1 : term_read( );
 
                        if ( value != -1 )
                        {
@@ -218,7 +239,22 @@ static void transport( mlt_producer producer, mlt_consumer consumer )
 #endif
 
                        if ( !silent && mlt_properties_get_int( properties, "stats_off" ) == 0 )
-                               fprintf( stderr, "Current Position: %10d\r", (int)mlt_producer_position( producer ) );
+                       {
+                               if ( progress )
+                               {
+                                       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 );
+                                               last_position = current_position;
+                                       }
+                               }
+                               else
+                               {
+                                       fprintf( stderr, "Current Position: %10d\r", (int)mlt_producer_position( producer ) );
+                               }
+                       }
 
                        if ( silent )
                                nanosleep( &tm, NULL );
@@ -229,6 +265,56 @@ static void transport( mlt_producer producer, mlt_consumer consumer )
        }
 }
 
+static void query_metadata( mlt_repository repo, mlt_service_type type, char *typestr, char *id )
+{
+       mlt_properties metadata = mlt_repository_metadata( repo, type, id );
+       if ( metadata )
+       {
+               char *s = mlt_properties_serialise_yaml( metadata );
+               fprintf( stderr, "%s", s );
+               free( s );
+       }
+       else
+       {
+               fprintf( stderr, "# No metadata for %s \"%s\"\n", typestr, id );
+       }
+}
+
+static void query_services( mlt_repository repo, mlt_service_type type )
+{
+       mlt_properties services = NULL;
+       char *typestr = NULL;
+       switch ( type )
+       {
+               case consumer_type:
+                       services = mlt_repository_consumers( repo );
+                       typestr = "consumers";
+                       break;
+               case filter_type:
+                       services = mlt_repository_filters( repo );
+                       typestr = "filters";
+                       break;
+               case producer_type:
+                       services = mlt_repository_producers( repo );
+                       typestr = "producers";
+                       break;
+               case transition_type:
+                       services = mlt_repository_transitions( repo );
+                       typestr = "transitions";
+                       break;
+               default:
+                       return;
+       }
+       fprintf( stderr, "---\n%s:\n", typestr );
+       if ( services )
+       {
+               int j;
+               for ( j = 0; j < mlt_properties_count( services ); j++ )
+                       fprintf( stderr, "  - %s\n", mlt_properties_get_name( services, j ) );
+       }
+       fprintf( stderr, "...\n" );
+}
+
 int main( int argc, char **argv )
 {
        int i;
@@ -237,6 +323,7 @@ int main( int argc, char **argv )
        FILE *store = NULL;
        char *name = NULL;
        struct sched_param scp;
+       mlt_profile profile = NULL;
 
        // Use realtime scheduling if possible
        memset( &scp, '\0', sizeof( scp ) );
@@ -246,43 +333,114 @@ int main( int argc, char **argv )
 #endif
 
        // Construct the factory
-       mlt_factory_init( NULL );
+       mlt_repository repo = mlt_factory_init( NULL );
 
-       // Check for serialisation switch first
        for ( i = 1; i < argc; i ++ )
        {
+               // Check for serialisation switch
                if ( !strcmp( argv[ i ], "-serialise" ) )
                {
                        name = argv[ ++ i ];
-                       if ( strstr( name, ".inigo" ) )
+                       if ( name != NULL && strstr( name, ".inigo" ) )
                                store = fopen( name, "w" );
+                       else
+                       {
+                               if ( name == NULL || name[0] == '-' )
+                                       store = stdout;
+                               name = NULL;
+                       }
+               }
+               // Look for the profile option
+               else if ( !strcmp( argv[ i ], "-profile" ) )
+               {
+                       const char *pname = argv[ ++ i ];
+                       if ( pname && pname[0] != '-' )
+                               profile = mlt_profile_init( pname );
+               }
+               // Look for the query option
+               else if ( !strcmp( argv[ i ], "-query" ) )
+               {
+                       const char *pname = argv[ ++ i ];
+                       if ( pname && pname[0] != '-' )
+                       {
+                               if ( !strcmp( pname, "consumers" ) || !strcmp( pname, "consumer" ) )
+                                       query_services( repo, consumer_type );
+                               else if ( !strcmp( pname, "filters" ) || !strcmp( pname, "filter" ) )
+                                       query_services( repo, filter_type );
+                               else if ( !strcmp( pname, "producers" ) || !strcmp( pname, "producer" ) )
+                                       query_services( repo, producer_type );
+                               else if ( !strcmp( pname, "transitions" ) || !strcmp( pname, "transition" ) )
+                                       query_services( repo, transition_type );
+                               
+                               else if ( !strncmp( pname, "consumer=", 9 ) )
+                                       query_metadata( repo, consumer_type, "consumer", strchr( pname, '=' ) + 1 );
+                               else if ( !strncmp( pname, "filter=", 7 ) )
+                                       query_metadata( repo, filter_type, "filter", strchr( pname, '=' ) + 1 );
+                               else if ( !strncmp( pname, "producer=", 9 ) )
+                                       query_metadata( repo, producer_type, "producer", strchr( pname, '=' ) + 1 );
+                               else if ( !strncmp( pname, "transition=", 11 ) )
+                                       query_metadata( repo, transition_type, "transition", strchr( pname, '=' ) + 1 );
+                               else
+                                       goto query_all;
+                       }
+                       else
+                       {
+query_all:
+                               query_services( repo, consumer_type );
+                               query_services( repo, filter_type );
+                               query_services( repo, producer_type );
+                               query_services( repo, transition_type );
+                               fprintf( stderr, "# You can query the metadata for a specific service using:\n"
+                                       "# -query <type>=<identifer>\n"
+                                       "# where <type> is one of: consumer, filter, producer, or transition.\n" );
+                       }
+                       goto exit_factory;
                }
        }
 
+       // Create profile if not set explicitly
+       if ( profile == NULL )
+               profile = mlt_profile_init( NULL );
+
+       // Look for the consumer option
+       for ( i = 1; i < argc; i ++ )
+       {
+               if ( !strcmp( argv[ i ], "-consumer" ) )
+               {
+                       consumer = create_consumer( profile, argv[ ++ i ] );
+                       if ( consumer )
+                       {
+                               mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
+                               while ( argv[ i + 1 ] != NULL && strstr( argv[ i + 1 ], "=" ) )
+                                       mlt_properties_parse( properties, argv[ ++ i ] );
+                       }
+               }
+       }
+
+       // If we have no consumer, default to sdl
+       if ( store == NULL && consumer == NULL )
+               consumer = create_consumer( profile, NULL );
+
        // Get inigo producer
        if ( argc > 1 )
-               inigo = mlt_factory_producer( "inigo", &argv[ 1 ] );
+               inigo = mlt_factory_producer( profile, "inigo", &argv[ 1 ] );
 
-       if ( argc > 1 && inigo != NULL && mlt_producer_get_length( inigo ) > 0 )
+       // Set transport properties on consumer and produder
+       if ( consumer != NULL && inigo != NULL )
        {
-               // Get inigo's properties
-               mlt_properties inigo_props = MLT_PRODUCER_PROPERTIES( inigo );
-
-               // Get the last group
-               mlt_properties group = mlt_properties_get_data( inigo_props, "group", 0 );
+               mlt_properties_set_data( MLT_CONSUMER_PROPERTIES( consumer ), "transport_producer", inigo, 0, NULL, NULL );
+               mlt_properties_set_data( MLT_PRODUCER_PROPERTIES( inigo ), "transport_consumer", consumer, 0, NULL, NULL );
+       }
 
+       if ( argc > 1 && inigo != NULL && mlt_producer_get_length( inigo ) > 0 )
+       {
                // Parse the arguments
                for ( i = 1; i < argc; i ++ )
                {
-                       if ( !strcmp( argv[ i ], "-consumer" ) )
+                       if ( !strcmp( argv[ i ], "-serialise" ) )
                        {
-                               consumer = create_consumer( argv[ ++ i ], inigo );
-                               while ( argv[ i + 1 ] != NULL && strstr( argv[ i + 1 ], "=" ) )
-                                       mlt_properties_parse( group, argv[ ++ i ] );
-                       }
-                       else if ( !strcmp( argv[ i ], "-serialise" ) )
-                       {
-                               i ++;
+                               if ( store != stdout )
+                                       i ++;
                        }
                        else
                        {
@@ -302,12 +460,14 @@ int main( int argc, char **argv )
                        }
                }
 
-               // If we have no consumer, default to sdl
-               if ( store == NULL && consumer == NULL )
-                       consumer = create_consumer( NULL, inigo );
-
                if ( consumer != NULL && store == NULL )
                {
+                       // Get inigo's properties
+                       mlt_properties inigo_props = MLT_PRODUCER_PROPERTIES( inigo );
+       
+                       // Get the last group
+                       mlt_properties group = mlt_properties_get_data( inigo_props, "group", 0 );
+       
                        // Apply group settings
                        mlt_properties properties = MLT_CONSUMER_PROPERTIES( consumer );
                        mlt_properties_inherit( properties, group );
@@ -324,7 +484,7 @@ int main( int argc, char **argv )
                        // Stop the consumer
                        mlt_consumer_stop( consumer );
                }
-               else if ( store != NULL )
+               else if ( store != NULL && store != stdout && name != NULL )
                {
                        fprintf( stderr, "Project saved as %s.\n", name );
                        fclose( store );
@@ -332,18 +492,22 @@ int main( int argc, char **argv )
        }
        else
        {
-               fprintf( stderr, "Usage: inigo [ -group [ name=value ]* ]\n"
-                                                "             [ -consumer id[:arg] [ name=value ]* ]\n"
-                                                "             [ -filter filter[:arg] [ name=value ] * ]\n"
-                                                "             [ -attach filter[:arg] [ name=value ] * ]\n"
+               fprintf( stderr, "Usage: inigo [ -profile name ]\n"
+                                                "             [ -query [ consumers | filters | producers | transitions |\n"
+                                                "                      type=identifer ] ]\n"
+                                                "             [ -serialise [ filename.inigo ] ]\n"
+                                                "             [ -group [ name=value ]* ]\n"
+                                                "             [ -consumer id[:arg] [ name=value ]* [ silent=1 ] [ progress=1 ] ]\n"
+                                                "             [ -filter filter[:arg] [ name=value ]* ]\n"
+                                                "             [ -attach filter[:arg] [ name=value ]* ]\n"
                                                 "             [ -mix length [ -mixer transition ]* ]\n"
-                                                "             [ -transition id[:arg] [ name=value ] * ]\n"
+                                                "             [ -transition id[:arg] [ name=value ]* ]\n"
                                                 "             [ -blank frames ]\n"
                                                 "             [ -track ]\n"
                                                 "             [ -split relative-frame ]\n"
                                                 "             [ -join clips ]\n"
                                                 "             [ -repeat times ]\n"
-                                                "             [ producer [ name=value ] * ]+\n" );
+                                                "             [ producer [ name=value ]* ]+\n" );
        }
 
        // Close the consumer
@@ -355,6 +519,10 @@ int main( int argc, char **argv )
                mlt_producer_close( inigo );
 
        // Close the factory
+       mlt_profile_close( profile );
+
+exit_factory:
+               
        mlt_factory_close( );
 
        return 0;