]> git.sesse.net Git - mlt/blob - src/framework/mlt_repository.c
45a2e9258afed7c946a0d699df812bfa6f45e201
[mlt] / src / framework / mlt_repository.c
1 /*
2  * repository.c -- provides a map between service and shared objects
3  * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4  * Author: Charles Yates <charles.yates@pandora.be>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include "mlt_repository.h"
22 #include "mlt_properties.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <dlfcn.h>
27 #include <string.h>
28
29 struct mlt_repository_s
30 {
31         struct mlt_properties_s parent;
32 };
33
34 static char *construct_full_file( char *output, const char *prefix, const char *file )
35 {
36         strcpy( output, prefix );
37         if ( prefix[ strlen( prefix ) - 1 ] != '/' )
38                 strcat( output, "/" );
39         strcat( output, file );
40         return output;
41 }
42
43 static char *chomp( char *input )
44 {
45         if ( input[ strlen( input ) - 1 ] == '\n' )
46                 input[ strlen( input ) - 1 ] = '\0';
47         return input;
48 }
49
50 static mlt_properties construct_object( const char *prefix, const char *id )
51 {
52         mlt_properties output = mlt_properties_new( );
53         mlt_properties_set( output, "prefix", prefix );
54         mlt_properties_set( output, "id", id );
55         return output;
56 }
57
58 static mlt_properties construct_service( mlt_properties object, const char *id )
59 {
60         mlt_properties output = mlt_properties_new( );
61         mlt_properties_set_data( output, "object", object, 0, NULL, NULL );
62         mlt_properties_set( output, "id", id );
63         return output;
64 }
65
66 static void *construct_instance( mlt_properties service_properties, const char *symbol, void *input )
67 {
68         // Extract the service
69         char *service = mlt_properties_get( service_properties, "id" );
70
71         // Get the object properties
72         void *object_properties = mlt_properties_get_data( service_properties, "object", NULL );
73
74         // Get the dlopen'd object
75         void *object = mlt_properties_get_data( object_properties, "dlopen", NULL );
76
77         // Get the dlsym'd symbol
78         void *( *symbol_ptr )( const char *, void * ) = mlt_properties_get_data( object_properties, symbol, NULL );
79
80         // Check that we have object and open if we don't
81         if ( object == NULL )
82         {
83                 char full_file[ 512 ];
84
85                 // Get the prefix and id of the shared object
86                 char *prefix = mlt_properties_get( object_properties, "prefix" );
87                 char *file = mlt_properties_get( object_properties, "id" );
88
89                 // Construct the full file
90                 construct_full_file( full_file, prefix, file );
91
92                 // Open the shared object
93                 object = dlopen( full_file, RTLD_NOW | RTLD_GLOBAL );
94                 if ( object != NULL )
95                 {
96                         // Set it on the properties
97                         mlt_properties_set_data( object_properties, "dlopen", object, 0, ( mlt_destructor )dlclose, NULL );
98                 }
99                 else
100                 {
101                         fprintf( stderr, "Failed to load plugin: %s\n", dlerror() );
102                 }
103         }
104
105         // Now check if we have this symbol pointer
106         if ( object != NULL && symbol_ptr == NULL )
107         {
108                 // Construct it now
109                 symbol_ptr = dlsym( object, symbol );
110
111                 // Set it on the properties
112                 mlt_properties_set_data( object_properties, "dlsym", symbol_ptr, 0, NULL, NULL );
113         }
114
115         // Construct the service
116         return symbol_ptr != NULL ? symbol_ptr( service, input ) : NULL;
117 }
118
119 mlt_repository mlt_repository_init( mlt_properties object_list, const char *prefix, const char *data, const char *symbol )
120 {
121         char full_file[ 512 ];
122         FILE *file;
123
124         // Construct the repository
125         mlt_repository this = calloc( sizeof( struct mlt_repository_s ), 1 );
126         mlt_properties_init( &this->parent, this );
127
128         // Add the symbol to THIS repository properties.
129         mlt_properties_set( &this->parent, "_symbol", symbol );
130
131         // Construct full file
132         construct_full_file( full_file, prefix, data );
133         strcat( full_file, ".dat" );
134
135         // Open the file
136         file = fopen( full_file, "r" );
137
138         // Parse the contents
139         if ( file != NULL )
140         {
141                 char full[ 512 ];
142                 char service[ 256 ];
143                 char object[ 256 ];
144
145                 while( fgets( full, 512, file ) )
146                 {
147                         chomp( full );
148
149                         if ( full[ 0 ] != '#' && full[ 0 ] != '\0' && sscanf( full, "%s %s", service, object ) == 2 )
150                         {
151                                 // Get the object properties first
152                                 mlt_properties object_properties = mlt_properties_get_data( object_list, object, NULL );
153
154                                 // If their are no properties, create them now
155                                 if ( object_properties == NULL )
156                                 {
157                                         // Construct the object
158                                         object_properties = construct_object( prefix, object );
159
160                                         // Add it to the object list
161                                         mlt_properties_set_data( object_list, object, object_properties, 0, ( mlt_destructor )mlt_properties_close, NULL );
162                                 }
163
164                                 // Now construct a property for the service
165                                 mlt_properties service_properties = construct_service( object_properties, service );
166
167                                 // Add it to the repository
168                                 mlt_properties_set_data( &this->parent, service, service_properties, 0, ( mlt_destructor )mlt_properties_close, NULL );
169                         }
170                 }
171
172                 // Close the file
173                 fclose( file );
174         }
175
176         return this;
177 }
178
179 void *mlt_repository_fetch( mlt_repository this, const char *service, void *input )
180 {
181         // Get the service properties
182         mlt_properties service_properties = mlt_properties_get_data( &this->parent, service, NULL );
183
184         // If the service exists
185         if ( service_properties != NULL )
186         {
187                 // Get the symbol that is used to generate this service
188                 char *symbol = mlt_properties_get( &this->parent, "_symbol" );
189
190                 // Now get an instance of the service
191                 return construct_instance( service_properties, symbol, input );
192         }
193
194         return NULL;
195 }
196
197 void mlt_repository_close( mlt_repository this )
198 {
199         mlt_properties_close( &this->parent );
200         free( this );
201 }
202
203