]> git.sesse.net Git - mlt/blob - src/framework/mlt_repository.c
Cleanup license declarations and remove dv1394d references.
[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 library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, 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                 int flags = RTLD_NOW;
89
90                 // Very temporary hack to allow the quicktime plugins to work
91                 // TODO: extend repository to allow this to be used on a case by case basis
92                 if ( !strcmp( service, "kino" ) )
93                         flags |= RTLD_GLOBAL;
94
95                 // Construct the full file
96                 construct_full_file( full_file, prefix, file );
97
98                 // Open the shared object
99                 object = dlopen( full_file, flags );
100                 if ( object != NULL )
101                 {
102                         // Set it on the properties
103                         mlt_properties_set_data( object_properties, "dlopen", object, 0, ( mlt_destructor )dlclose, NULL );
104                 }
105                 else
106                 {
107                         fprintf( stderr, "Failed to load plugin: %s\n", dlerror() );
108                 }
109         }
110
111         // Now check if we have this symbol pointer
112         if ( object != NULL && symbol_ptr == NULL )
113         {
114                 // Construct it now
115                 symbol_ptr = dlsym( object, symbol );
116
117                 // Set it on the properties
118                 mlt_properties_set_data( object_properties, "dlsym", symbol_ptr, 0, NULL, NULL );
119         }
120
121         // Construct the service
122         return symbol_ptr != NULL ? symbol_ptr( service, input ) : NULL;
123 }
124
125 mlt_repository mlt_repository_init( mlt_properties object_list, const char *prefix, const char *data, const char *symbol )
126 {
127         char full_file[ 512 ];
128         FILE *file;
129
130         // Construct the repository
131         mlt_repository this = calloc( sizeof( struct mlt_repository_s ), 1 );
132         mlt_properties_init( &this->parent, this );
133
134         // Add the symbol to THIS repository properties.
135         mlt_properties_set( &this->parent, "_symbol", symbol );
136
137         // Construct full file
138         construct_full_file( full_file, prefix, data );
139         strcat( full_file, ".dat" );
140
141         // Open the file
142         file = fopen( full_file, "r" );
143
144         // Parse the contents
145         if ( file != NULL )
146         {
147                 char full[ 512 ];
148                 char service[ 256 ];
149                 char object[ 256 ];
150
151                 while( fgets( full, 512, file ) )
152                 {
153                         chomp( full );
154
155                         if ( full[ 0 ] != '#' && full[ 0 ] != '\0' && sscanf( full, "%s %s", service, object ) == 2 )
156                         {
157                                 // Get the object properties first
158                                 mlt_properties object_properties = mlt_properties_get_data( object_list, object, NULL );
159
160                                 // If their are no properties, create them now
161                                 if ( object_properties == NULL )
162                                 {
163                                         // Construct the object
164                                         object_properties = construct_object( prefix, object );
165
166                                         // Add it to the object list
167                                         mlt_properties_set_data( object_list, object, object_properties, 0, ( mlt_destructor )mlt_properties_close, NULL );
168                                 }
169
170                                 // Now construct a property for the service
171                                 mlt_properties service_properties = construct_service( object_properties, service );
172
173                                 // Add it to the repository
174                                 mlt_properties_set_data( &this->parent, service, service_properties, 0, ( mlt_destructor )mlt_properties_close, NULL );
175                         }
176                 }
177
178                 // Close the file
179                 fclose( file );
180         }
181
182         return this;
183 }
184
185 void *mlt_repository_fetch( mlt_repository this, const char *service, void *input )
186 {
187         // Get the service properties
188         mlt_properties service_properties = mlt_properties_get_data( &this->parent, service, NULL );
189
190         // If the service exists
191         if ( service_properties != NULL )
192         {
193                 // Get the symbol that is used to generate this service
194                 char *symbol = mlt_properties_get( &this->parent, "_symbol" );
195
196                 // Now get an instance of the service
197                 return construct_instance( service_properties, symbol, input );
198         }
199
200         return NULL;
201 }
202
203 void mlt_repository_close( mlt_repository this )
204 {
205         mlt_properties_close( &this->parent );
206         free( this );
207 }
208
209