]> git.sesse.net Git - mlt/commitdiff
Presets!
authorDan Dennedy <dan@dennedy.org>
Fri, 13 May 2011 03:12:00 +0000 (20:12 -0700)
committerDan Dennedy <dan@dennedy.org>
Fri, 13 May 2011 03:12:00 +0000 (20:12 -0700)
Put property setters in a file and apply them to a service using
properties=filename. Alternatively, apply a supplied preset using
properties=preset. For example, melt ... -consumer avformat:my.vob
properties=DVD.

16 files changed:
Makefile
presets/consumer/avformat/dv_ntsc/DVD [new file with mode: 0644]
presets/consumer/avformat/dv_ntsc_wide/DVD [new file with mode: 0644]
presets/consumer/avformat/dv_pal/DVD [new file with mode: 0644]
presets/consumer/avformat/dv_pal_wide/DVD [new file with mode: 0644]
setenv
src/framework/mlt_properties.c
src/framework/mlt_properties.h
src/framework/mlt_repository.c
src/framework/mlt_repository.h
src/melt/melt.c
src/mlt++/MltProperties.cpp
src/mlt++/MltProperties.h
src/mlt++/MltRepository.cpp
src/mlt++/MltRepository.h
src/swig/mlt.i

index de66bb7407151d1c12bb9a530442973d726503c2..136171b1d8d86891d2f4332e924a19318a527224 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -35,10 +35,8 @@ install:
        list='$(SUBDIRS)'; \
        for subdir in $$list; do \
                $(MAKE) DESTDIR=$(DESTDIR) -C $$subdir $@ || exit 1; \
-       done; \
-#      if test -z "$(DESTDIR)"; then \
-#        /sbin/ldconfig -n "$(DESTDIR)$(libdir)" 2> /dev/null || true; \
-#      fi
+       done
+       cp -R presets "$(DESTDIR)$(prefix)/share/mlt"
 
 uninstall:
        rm -f "$(DESTDIR)$(bindir)"/mlt-config
diff --git a/presets/consumer/avformat/dv_ntsc/DVD b/presets/consumer/avformat/dv_ntsc/DVD
new file mode 100644 (file)
index 0000000..8fad356
--- /dev/null
@@ -0,0 +1,15 @@
+f=dvd
+vcodec=mpeg2video
+acodec=ac3
+b=6000k
+maxrate=9000k
+minrate=0
+bufsize=1835008
+packetsize=2048
+muxrate=10080000
+ab=192k
+ar=48000
+g=18
+me_range=63
+trellis=1
+
diff --git a/presets/consumer/avformat/dv_ntsc_wide/DVD b/presets/consumer/avformat/dv_ntsc_wide/DVD
new file mode 100644 (file)
index 0000000..8fad356
--- /dev/null
@@ -0,0 +1,15 @@
+f=dvd
+vcodec=mpeg2video
+acodec=ac3
+b=6000k
+maxrate=9000k
+minrate=0
+bufsize=1835008
+packetsize=2048
+muxrate=10080000
+ab=192k
+ar=48000
+g=18
+me_range=63
+trellis=1
+
diff --git a/presets/consumer/avformat/dv_pal/DVD b/presets/consumer/avformat/dv_pal/DVD
new file mode 100644 (file)
index 0000000..6ce9f51
--- /dev/null
@@ -0,0 +1,15 @@
+f=dvd
+vcodec=mpeg2video
+acodec=ac3
+b=5000k
+maxrate=8000k
+minrate=0
+bufsize=1835008
+packetsize=2048
+muxrate=10080000
+ab=192k
+ar=48000
+g=15
+me_range=63
+trellis=1
+
diff --git a/presets/consumer/avformat/dv_pal_wide/DVD b/presets/consumer/avformat/dv_pal_wide/DVD
new file mode 100644 (file)
index 0000000..6ce9f51
--- /dev/null
@@ -0,0 +1,15 @@
+f=dvd
+vcodec=mpeg2video
+acodec=ac3
+b=5000k
+maxrate=8000k
+minrate=0
+bufsize=1835008
+packetsize=2048
+muxrate=10080000
+ab=192k
+ar=48000
+g=15
+me_range=63
+trellis=1
+
diff --git a/setenv b/setenv
index f2f668ddcf027040092346a12408d2fce6ea3df8..162230b37a774160dc0c034b9de352bf4256ecea 100644 (file)
--- a/setenv
+++ b/setenv
@@ -4,6 +4,7 @@
 export MLT_REPOSITORY=`pwd`/src/modules
 export MLT_DATA=`pwd`/src/modules
 export MLT_PROFILES_PATH=`pwd`/profiles
+export MLT_PRESETS_PATH=`pwd`/presets
 
 export LD_LIBRARY_PATH=\
 `pwd`/src/framework:\
index a8c2d865d7217cee5dc4447021655c856bdbd2e1..fd674e1aad82b807d4d0aeb20e5c0ddbd3dc74a1 100644 (file)
@@ -26,6 +26,7 @@
 #include "mlt_property.h"
 #include "mlt_deque.h"
 #include "mlt_log.h"
+#include "mlt_factory.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,7 +36,8 @@
 #include <pthread.h>
 #include <sys/types.h>
 #include <dirent.h>
-
+#include <sys/stat.h>
+#include <errno.h>
 
 /** \brief private implementation of the property list */
 
@@ -116,12 +118,54 @@ mlt_properties mlt_properties_new( )
        return self;
 }
 
+static int load_properties( mlt_properties self, const char *filename )
+{
+       // Open the file
+       FILE *file = fopen( filename, "r" );
+
+       // Load contents of file
+       if ( file != NULL )
+       {
+               // Temp string
+               char temp[ 1024 ];
+               char last[ 1024 ] = "";
+
+               // Read each string from the file
+               while( fgets( temp, 1024, file ) )
+               {
+                       // Chomp the string
+                       temp[ strlen( temp ) - 1 ] = '\0';
+
+                       // Check if the line starts with a .
+                       if ( temp[ 0 ] == '.' )
+                       {
+                               char temp2[ 1024 ];
+                               sprintf( temp2, "%s%s", last, temp );
+                               strcpy( temp, temp2 );
+                       }
+                       else if ( strchr( temp, '=' ) )
+                       {
+                               strcpy( last, temp );
+                               *( strchr( last, '=' ) ) = '\0';
+                       }
+
+                       // Parse and set the property
+                       if ( strcmp( temp, "" ) && temp[ 0 ] != '#' )
+                               mlt_properties_parse( self, temp );
+               }
+
+               // Close the file
+               fclose( file );
+       }
+       return file? 0 : errno;
+}
+
 /** Create a properties object by reading a .properties text file.
  *
  * Free the properties object with mlt_properties_close().
  * \deprecated Please start using mlt_properties_parse_yaml().
  * \public \memberof mlt_properties_s
- * \param filename a string contain the absolute file name
+ * \param filename the absolute file name
  * \return a new properties object
  */
 
@@ -131,48 +175,81 @@ mlt_properties mlt_properties_load( const char *filename )
        mlt_properties self = mlt_properties_new( );
 
        if ( self != NULL )
-       {
-               // Open the file
-               FILE *file = fopen( filename, "r" );
+               load_properties( self, filename );
 
-               // Load contents of file
-               if ( file != NULL )
-               {
-                       // Temp string
-                       char temp[ 1024 ];
-                       char last[ 1024 ] = "";
+       // Return the pointer
+       return self;
+}
 
-                       // Read each string from the file
-                       while( fgets( temp, 1024, file ) )
-                       {
-                               // Chomp the string
-                               temp[ strlen( temp ) - 1 ] = '\0';
+/** Set properties from a preset.
+ *
+ * Presets are typically installed to $prefix/share/mlt/presets/{type}/{service}/[{profile}/]{name}.
+ * For example, "/usr/share/mlt/presets/consumer/avformat/dv_ntsc_wide/DVD"
+ * could be an encoding preset for a widescreen NTSC DVD Video.
+ * Do not specify the type and service in the preset name parameter; these are
+ * inferred automatically from the service to which you are applying the preset.
+ * Using the example above and assuming you are calling this function on the
+ * avformat consumer, the name passed to the function should simply be DVD.
+ * Note that the profile portion of the path is optional, but a profile-specific
+ * preset with the same name as a more generic one is given a higher priority.
+ * \todo Look in a user-specific location - somewhere in the home directory.
+ *
+ * \public \memberof mlt_properties_s
+ * \param self a properties list
+ * \param name the name of a preset in a well-known location or the explicit path
+ * \return true if error
+ */
 
-                               // Check if the line starts with a .
-                               if ( temp[ 0 ] == '.' )
-                               {
-                                       char temp2[ 1024 ];
-                                       sprintf( temp2, "%s%s", last, temp );
-                                       strcpy( temp, temp2 );
-                               }
-                               else if ( strchr( temp, '=' ) )
-                               {
-                                       strcpy( last, temp );
-                                       *( strchr( last, '=' ) ) = '\0';
-                               }
+int mlt_properties_preset( mlt_properties self, const char *name )
+{
+       struct stat stat_buff;
 
-                               // Parse and set the property
-                               if ( strcmp( temp, "" ) && temp[ 0 ] != '#' )
-                                       mlt_properties_parse( self, temp );
-                       }
+       // validate input
+       if ( !( self && name && strlen( name ) ) )
+               return 1;
 
-                       // Close the file
-                       fclose( file );
+       // See if name is an explicit file
+       if ( ! stat( name, &stat_buff ) )
+       {
+               return load_properties( self, name );
+       }
+       else
+       {
+               // Look for profile-specific preset before a generic one.
+               char *data          = getenv( "MLT_PRESETS_PATH" );
+               const char *type    = mlt_properties_get( self, "mlt_type" );
+               const char *service = mlt_properties_get( self, "mlt_service" );
+               const char *profile = mlt_environment( "MLT_PROFILE" );
+               int error = 0;
+
+               if ( data )
+               {
+                       data = strdup( data );
+               }
+               else
+               {
+                       data = malloc( strlen( mlt_environment( "MLT_DATA" ) ) + 9 );
+                       strcpy( data, mlt_environment( "MLT_DATA" ) );
+                       strcat( data, "/presets" );
+               }
+               if ( data && type && service )
+               {
+                       char *path = malloc( 5 + strlen(name) + strlen(data) + strlen(type) + strlen(service) + ( profile? strlen(profile) : 0 ) );
+                       sprintf( path, "%s/%s/%s/%s/%s", data, type, service, profile, name );
+                       if ( load_properties( self, path ) )
+                       {
+                               sprintf( path, "%s/%s/%s/%s", data, type, service, name );
+                               error = load_properties( self, path );
+                       }
+                       free( path );
+               }
+               else
+               {
+                       error = 1;
                }
+               free( data );
+               return error;
        }
-
-       // Return the pointer
-       return self;
 }
 
 /** Generate a hash key.
@@ -491,6 +568,11 @@ int mlt_properties_pass_list( mlt_properties self, mlt_properties that, const ch
 
 
 /** Set a property to a string.
+ *
+ * The property name "properties" is reserved to load the preset in \p value.
+ * When the value begins with '@' then it is interpreted as a very simple math
+ * expression containing only the +, -, *, and / operators.
+ * The event "property-changed" is fired after the property has been set.
  *
  * This makes a copy of the string value you supply.
  * \public \memberof mlt_properties_s
@@ -521,6 +603,8 @@ int mlt_properties_set( mlt_properties self, const char *name, const char *value
        {
                error = mlt_property_set_string( property, value );
                mlt_properties_do_mirror( self, name );
+               if ( !strcmp( name, "properties" ) )
+                       mlt_properties_preset( self, value );
        }
        else if ( value[ 0 ] == '@' )
        {
index 55f9b0d6b49da0483a51dbe82ea5c493d130a0e6..5e17b15087906dcfbc3ea92abb034d950730ec26 100644 (file)
@@ -48,6 +48,7 @@ struct mlt_properties_s
 extern int mlt_properties_init( mlt_properties, void *child );
 extern mlt_properties mlt_properties_new( );
 extern mlt_properties mlt_properties_load( const char *file );
+extern int mlt_properties_preset( mlt_properties self, const char *name );
 extern int mlt_properties_inc_ref( mlt_properties self );
 extern int mlt_properties_dec_ref( mlt_properties self );
 extern int mlt_properties_ref_count( mlt_properties self );
index 3d75bcbe8e68cab98e08f120f698fb515919949c..81b80654e33898487167782f632a267ac0a2d4a0 100644 (file)
 #include "mlt_properties.h"
 #include "mlt_tokeniser.h"
 #include "mlt_log.h"
+#include "mlt_factory.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <dlfcn.h>
 #include <string.h>
+#include <limits.h>
+#include <dirent.h>
 
 /** \brief Repository class
  *
@@ -426,3 +429,71 @@ mlt_properties mlt_repository_languages( mlt_repository self )
        mlt_properties_set_data( &self->parent, "languages", languages, 0, ( mlt_destructor )mlt_properties_close, NULL );
        return languages;
 }
+
+static void list_presets( mlt_properties properties, const char *path, const char *dirname )
+{
+       DIR *dir = opendir( dirname );
+
+       if ( dir )
+       {
+               struct dirent *de = readdir( dir );
+               char fullname[ PATH_MAX ];
+
+               while ( de != NULL )
+               {
+                       if ( de->d_name[0] != '.' && de->d_name[strlen( de->d_name ) - 1] != '~' )
+                       {
+                               snprintf( fullname, sizeof(fullname), "%s/%s", dirname, de->d_name );
+                               if ( de->d_type & DT_DIR )
+                               {
+                                       // recurse into subdirectories
+                                       char sub[ PATH_MAX ];
+                                       if ( path )
+                                               snprintf( sub, sizeof(sub), "%s/%s", path, de->d_name );
+                                       else
+                                               strncpy( sub, de->d_name, sizeof(sub) );
+                                       list_presets( properties, sub, fullname );
+                               }
+                               else
+                               {
+                                       // load the preset
+                                       mlt_properties preset = mlt_properties_load( fullname );
+                                       if ( preset && mlt_properties_count( preset ) )
+                                       {
+                                               snprintf( fullname, 1024, "%s/%s", path, de->d_name );
+                                               mlt_properties_set_data( properties, fullname, preset, 0, (mlt_destructor) mlt_properties_close, NULL );
+                                       }
+                               }
+                       }
+                       de = readdir( dir );
+               }
+               closedir( dir );
+       }
+}
+
+/** Get the list of presets.
+ *
+ * \public \memberof mlt_repository_s
+ * \return a properties list of all the presets
+ */
+
+mlt_properties mlt_repository_presets( )
+{
+       mlt_properties result = mlt_properties_new();
+       char *path = getenv( "MLT_PRESETS_PATH" );
+
+       if ( path )
+       {
+               path = strdup( path );
+       }
+       else
+       {
+               path = malloc( strlen( mlt_environment( "MLT_DATA" ) ) + 9 );
+               strcpy( path, mlt_environment( "MLT_DATA" ) );
+               strcat( path, "/presets" );
+       }
+       list_presets( result, NULL, path );
+       free( path );
+
+       return result;
+}
index a653b490cb0e8727b2b82f62b2ec028ba04c04e6..29fb33735636204c8ff7316d36203d0134544aff 100644 (file)
@@ -66,6 +66,7 @@ extern mlt_properties mlt_repository_transitions( mlt_repository self );
 extern void mlt_repository_register_metadata( mlt_repository self, mlt_service_type type, const char *service, mlt_metadata_callback, void *callback_data );
 extern mlt_properties mlt_repository_metadata( mlt_repository self, mlt_service_type type, const char *service );
 extern mlt_properties mlt_repository_languages( mlt_repository self );
+extern mlt_properties mlt_repository_presets( );
 
 #endif
 
index d59672402facf7d22e79d18daecc9badf20d7a85..6028a4391461ede2fb13fbd9344f182244637db5 100644 (file)
@@ -325,6 +325,7 @@ static void show_usage( char *program_name )
 "  -query \"producers\" | \"producer\"=id       List producers or show info about one\n"
 "  -query \"transitions\" | \"transition\"=id   List transitions, show info about one\n"
 "  -query \"profiles\" | \"profile\"=id         List profiles, show info about one\n"
+"  -query \"presets\" | \"preset\"=id           List presets, show info about one\n"
 "  -query \"formats\"                         List audio/video formats\n"
 "  -query \"audio_codecs\"                    List audio codecs\n"
 "  -query \"video_codecs\"                    List video codecs\n"
@@ -468,6 +469,37 @@ static void query_profile( const char *id )
        mlt_properties_close( profiles );
 }
 
+static void query_presets()
+{
+       mlt_properties presets = mlt_repository_presets();
+       fprintf( stderr, "---\npresets:\n" );
+       if ( presets )
+       {
+               int j;
+               for ( j = 0; j < mlt_properties_count( presets ); j++ )
+                       fprintf( stderr, "  - %s\n", mlt_properties_get_name( presets, j ) );
+       }
+       fprintf( stderr, "...\n" );
+       mlt_properties_close( presets );
+}
+
+static void query_preset( const char *id )
+{
+       mlt_properties presets = mlt_repository_presets();
+       mlt_properties preset = mlt_properties_get_data( presets, id, NULL );
+       if ( preset )
+       {
+               char *s = mlt_properties_serialise_yaml( preset );
+               fprintf( stderr, "%s", s );
+               free( s );
+       }
+       else
+       {
+               fprintf( stderr, "# No metadata for preset \"%s\"\n", id );
+       }
+       mlt_properties_close( presets );
+}
+
 static void query_formats( )
 {
        mlt_consumer consumer = mlt_factory_consumer( NULL, "avformat", NULL );
@@ -580,6 +612,8 @@ int main( int argc, char **argv )
                                        query_services( repo, transition_type );
                                else if ( !strcmp( pname, "profiles" ) || !strcmp( pname, "profile" ) )
                                        query_profiles();
+                               else if ( !strcmp( pname, "presets" ) || !strcmp( pname, "preset" ) )
+                                       query_presets();
                                else if ( !strncmp( pname, "format", 6 ) )
                                        query_formats();
                                else if ( !strncmp( pname, "acodec", 6 ) || !strcmp( pname, "audio_codecs" ) )
@@ -597,6 +631,8 @@ int main( int argc, char **argv )
                                        query_metadata( repo, transition_type, "transition", strchr( pname, '=' ) + 1 );
                                else if ( !strncmp( pname, "profile=", 8 ) )
                                        query_profile( strchr( pname, '=' ) + 1 );
+                               else if ( !strncmp( pname, "preset=", 7 ) )
+                                       query_preset( strchr( pname, '=' ) + 1 );
                                else
                                        goto query_all;
                        }
index 8317294c285f3850e795c80b9d3f5bcc271dbd82..b2ae778cd20fe7fb2c9040fc2022e1733e5016ee 100644 (file)
@@ -316,3 +316,9 @@ char *Properties::serialise_yaml( )
 {
        return mlt_properties_serialise_yaml( get_properties( ) );
 }
+
+int Properties::preset( const char *name )
+{
+       return mlt_properties_preset( get_properties(), name );
+}
+
index fce173ff0adf3d6a55aff030b6f83ba4a96a664f..8956a56c5032c230405eea9a1da115db8421eaf5 100644 (file)
@@ -93,6 +93,7 @@ namespace Mlt
                        bool is_sequence( );
                        static Properties *parse_yaml( const char *file );
                        char *serialise_yaml( );
+                       int preset( const char *name );
        };
 }
 
index 387607968b85b57916103bed62f3d72550a12bb8..00e4b4c64e116d1fb89815649ae0741127c5fd00 100644 (file)
@@ -84,3 +84,8 @@ Properties *Repository::languages( ) const
 {
        return new Properties( mlt_repository_languages( instance ) );
 }
+
+Properties *Repository::presets( )
+{
+       return new Properties( mlt_repository_presets( ) );
+}
index efce9f29c59cf339372c0dbce7133945ccc2ad2d..53e529e639e4a7042e5c7f050f5b34636117d70e 100644 (file)
@@ -52,6 +52,7 @@ namespace Mlt
                        void register_metadata( mlt_service_type type, const char *service, mlt_metadata_callback, void *callback_data );
                        Properties *metadata( mlt_service_type type, const char *service ) const;
                        Properties *languages( ) const;
+                       static Properties *presets();
        };
 }
 
index f453f1e064f2d009a3245d24e24c0f93406dd00f..20434e448ce86ce3b664b874e22c8518a6091b54 100644 (file)
@@ -61,6 +61,7 @@ namespace Mlt {
 %newobject Repository::metadata( mlt_service_type, const char * );
 %newobject Repository::languages( );
 %newobject Profile::list();
+%newobject Repository::presets();
 }
 
 /** Classes to wrap.