]> git.sesse.net Git - mlt/blobdiff - src/framework/mlt_repository.c
Factory implementation
[mlt] / src / framework / mlt_repository.c
index 9c41bf92da85cc21367446b652a0ad77eff27141..0928b371965bbef65d248e795ffc34e7b891345a 100644 (file)
  */
 
 #include "mlt_repository.h"
+#include "mlt_properties.h"
+
+#include <stdio.h>
 #include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
 
 struct mlt_repository_s
 {
+       struct mlt_properties_s parent;
+       mlt_properties object_list;
 };
 
-mlt_repository mlt_repository_init( char *file, char *symbol )
+static char *construct_full_file( char *output, char *prefix, char *file )
 {
-       return NULL;
+       strcpy( output, prefix );
+       if ( prefix[ strlen( prefix ) - 1 ] != '/' )
+               strcat( output, "/" );
+       strcat( output, file );
+       return output;
+}
+
+static char *chomp( char *input )
+{
+       if ( input[ strlen( input ) - 1 ] == '\n' )
+               input[ strlen( input ) - 1 ] = '\0';
+       return input;
+}
+
+static mlt_properties construct_object( char *prefix, char *id )
+{
+       mlt_properties output = calloc( sizeof( struct mlt_properties_s ), 1 );
+       mlt_properties_init( output, NULL );
+       mlt_properties_set( output, "prefix", prefix );
+       mlt_properties_set( output, "id", id );
+       return output;
+}
+
+static mlt_properties construct_service( mlt_properties object, char *id )
+{
+       mlt_properties output = calloc( sizeof( struct mlt_properties_s ), 1 );
+       mlt_properties_init( output, NULL );
+       mlt_properties_set_data( output, "object", object, 0, NULL, NULL );
+       mlt_properties_set( output, "id", id );
+       return output;
+}
+
+void *construct_instance( mlt_properties service_properties, char *symbol, void *input )
+{
+       // Extract the service
+       char *service = mlt_properties_get( service_properties, "id" );
+
+       // Get the object properties
+       void *object_properties = mlt_properties_get_data( service_properties, "object", NULL );
+
+       // Get the dlopen'd object
+       void *object = mlt_properties_get_data( object_properties, "dlopen", NULL );
+
+       // Get the dlsym'd symbol
+       void *( *symbol_ptr )( char *, void * ) = mlt_properties_get_data( object_properties, symbol, NULL );
+
+       // Check that we have object and open if we don't
+       if ( object == NULL )
+       {
+               char full_file[ 512 ];
+
+               // Get the prefix and id of the shared object
+               char *prefix = mlt_properties_get( object_properties, "prefix" );
+               char *file = mlt_properties_get( object_properties, "id" );
+
+               // Construct the full file
+               construct_full_file( full_file, prefix, file );
+
+               // Open the shared object
+               object = dlopen( full_file, RTLD_NOW | RTLD_GLOBAL );
+
+               // Set it on the properties
+               mlt_properties_set_data( object_properties, "dlopen", object, 0, ( void (*)( void * ) )dlclose, NULL );
+       }
+
+       // Now check if we have this symbol pointer
+       if ( object != NULL && symbol_ptr == NULL )
+       {
+               // Construct it now
+               symbol_ptr = dlsym( object, symbol );
+
+               // Set it on the properties
+               mlt_properties_set_data( object_properties, "dlsym", symbol_ptr, 0, NULL, NULL );
+       }
+
+       // Construct the service
+       return symbol_ptr != NULL ? symbol_ptr( service, input ) : NULL;
+}
+
+void destroy_properties( void *arg )
+{
+       mlt_properties_close( arg );
+       free( arg );
+}
+
+mlt_repository mlt_repository_init( mlt_properties object_list, char *prefix, char *data, char *symbol )
+{
+       char full_file[ 512 ];
+       FILE *file;
+
+       // Construct the repository
+       mlt_repository this = calloc( sizeof( struct mlt_repository_s ), 1 );
+       mlt_properties_init( &this->parent, NULL );
+
+       // Add the symbol to THIS repository properties.
+       mlt_properties_set( &this->parent, "_symbol", symbol );
+
+       // Asociate the repository to the global object_list
+       this->object_list = object_list;
+
+       // Construct full file
+       construct_full_file( full_file, prefix, data );
+
+       // Open the file
+       file = fopen( full_file, "r" );
+
+       // Parse the contents
+       if ( file != NULL )
+       {
+               char full[ 512 ];
+               char service[ 256 ];
+               char object[ 256 ];
+
+               while( fgets( full, 512, file ) )
+               {
+                       chomp( full );
+
+                       if ( full[ 0 ] != '#' && full[ 0 ] != '\0' && sscanf( full, "%s %s", service, object ) == 2 )
+                       {
+                               // Get the object properties first
+                               mlt_properties object_properties = mlt_properties_get_data( object_list, object, NULL );
+
+                               // If their are no properties, create them now
+                               if ( object_properties == NULL )
+                               {
+                                       // Construct the object
+                                       object_properties = construct_object( prefix, object );
+
+                                       // Add it to the object list
+                                       mlt_properties_set_data( object_list, object, object_properties, 0, destroy_properties, NULL );
+                               }
+
+                               // Now construct a property for the service
+                               mlt_properties service_properties = construct_service( object_properties, service );
+
+                               // Add it to the repository
+                               mlt_properties_set_data( &this->parent, service, service_properties, 0, destroy_properties, NULL );
+                       }
+               }
+
+               // Close the file
+               fclose( file );
+       }
+
+       return this;
 }
 
 void *mlt_repository_fetch( mlt_repository this, char *service, void *input )
 {
+       // Get the service properties
+       mlt_properties service_properties = mlt_properties_get_data( &this->parent, service, NULL );
+
+       // If the service exists
+       if ( service_properties != NULL )
+       {
+               // Get the symbol that is used to generate this service
+               char *symbol = mlt_properties_get( &this->parent, "_symbol" );
+
+               // Now get an instance of the service
+               return construct_instance( service_properties, symbol, input );
+       }
+
        return NULL;
 }
 
 void mlt_repository_close( mlt_repository this )
 {
+       mlt_properties_close( &this->parent );
+       free( this );
 }