3 * \brief the factory method interfaces
5 * Copyright (C) 2003-2009 Ushodaya Enterprises Limited
6 * \author Charles Yates <charles.yates@pandora.be>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "mlt_repository.h"
33 /** the default subdirectory of the libdir for holding modules (plugins) */
34 #define PREFIX_LIB "\\lib\\mlt"
35 /** the default subdirectory of the install prefix for holding module (plugin) data */
36 #define PREFIX_DATA "\\share\\mlt"
37 #elif defined(__DARWIN__) && defined(RELOCATABLE)
38 #include <mach-o/dyld.h>
40 /** the default subdirectory of the libdir for holding modules (plugins) */
41 #define PREFIX_LIB "/lib/mlt"
42 /** the default subdirectory of the install prefix for holding module (plugin) data */
43 #define PREFIX_DATA "/share/mlt"
45 /** the default subdirectory of the libdir for holding modules (plugins) */
46 #define PREFIX_LIB LIBDIR "/mlt"
47 /** the default subdirectory of the install prefix for holding module (plugin) data */
48 #define PREFIX_DATA PREFIX "/share/mlt"
51 /** holds the full path to the modules directory - initialized and retained for the entire session */
52 static char *mlt_directory = NULL;
53 /** a global properties list for holding environment config data and things needing session-oriented cleanup */
54 static mlt_properties global_properties = NULL;
55 /** the global repository singleton */
56 static mlt_repository repository = NULL;
57 /** the events object for the factory events */
58 static mlt_properties event_object = NULL;
59 /** for tracking the unique_id set on each constructed service */
60 static int unique_id = 0;
62 /* Event transmitters. */
64 /** the -create-request event transmitter
72 static void mlt_factory_create_request( mlt_listener listener, mlt_properties owner, mlt_service self, void **args )
74 if ( listener != NULL )
75 listener( owner, self, ( char * )args[ 0 ], ( char * )args[ 1 ], ( mlt_service * )args[ 2 ] );
78 /** the -create-done event transmitter
86 static void mlt_factory_create_done( mlt_listener listener, mlt_properties owner, mlt_service self, void **args )
88 if ( listener != NULL )
89 listener( owner, self, ( char * )args[ 0 ], ( char * )args[ 1 ], ( mlt_service )args[ 2 ] );
92 /** Construct the repository and factories.
94 * The environment variable MLT_PRODUCER is the name of a default producer often used by other services, defaults to "loader".
96 * The environment variable MLT_CONSUMER is the name of a default consumer, defaults to "sdl".
98 * The environment variable MLT_TEST_CARD is the name of a producer or file to be played when nothing is available (all tracks blank).
100 * The environment variable MLT_DATA overrides the default full path to the MLT and module supplemental data files, defaults to \p PREFIX_DATA.
102 * The environment variable MLT_PROFILE defaults to "dv_pal."
104 * The environment variable MLT_REPOSITORY overrides the default location of the plugin modules, defaults to \p PREFIX_LIB.
106 * \param directory an optional full path to a directory containing the modules that overrides the default and
107 * the MLT_REPOSITORY environment variable
108 * \return the repository
111 mlt_repository mlt_factory_init( const char *directory )
113 // Load the system locales
114 setlocale( LC_ALL, "" );
116 if ( ! global_properties )
117 global_properties = mlt_properties_new( );
119 // Allow property refresh on a subsequent initialisation
120 if ( global_properties )
122 mlt_properties_set_or_default( global_properties, "MLT_NORMALISATION", getenv( "MLT_NORMALISATION" ), "PAL" );
123 mlt_properties_set_or_default( global_properties, "MLT_PRODUCER", getenv( "MLT_PRODUCER" ), "loader" );
124 mlt_properties_set_or_default( global_properties, "MLT_CONSUMER", getenv( "MLT_CONSUMER" ), "sdl" );
125 mlt_properties_set( global_properties, "MLT_TEST_CARD", getenv( "MLT_TEST_CARD" ) );
126 mlt_properties_set_or_default( global_properties, "MLT_PROFILE", getenv( "MLT_PROFILE" ), "dv_pal" );
128 mlt_properties_set_or_default( global_properties, "MLT_DATA", getenv( "MLT_DATA" ), PREFIX_DATA );
131 // Only initialise once
132 if ( mlt_directory == NULL )
134 // Allow user over rides
135 if ( directory == NULL || !strcmp( directory, "" ) )
136 directory = getenv( "MLT_REPOSITORY" );
138 // If no directory is specified, default to install directory
139 if ( directory == NULL )
140 directory = PREFIX_LIB;
142 // Store the prefix for later retrieval
145 DWORD size = sizeof( path );
146 GetModuleFileName( NULL, path, &size );
147 #elif defined(__DARWIN__) && defined(RELOCATABLE)
149 uint32_t size = sizeof( path );
150 _NSGetExecutablePath( path, &size );
152 mlt_directory = strdup( directory );
154 #if defined(WIN32) || (defined(__DARWIN__) && defined(RELOCATABLE))
155 if ( global_properties && !getenv( "MLT_DATA" ) )
157 mlt_directory = calloc( 1, size + strlen( PREFIX_DATA ) + 1 );
158 strcpy( mlt_directory, dirname( path ) );
159 strcat( mlt_directory, PREFIX_DATA );
160 mlt_properties_set( global_properties, "MLT_DATA", mlt_directory );
161 free( mlt_directory );
163 mlt_directory = calloc( 1, size + strlen( directory ) + 1 );
164 strcpy( mlt_directory, dirname( path ) );
165 strcat( mlt_directory, directory );
168 // Initialise the pool
171 // Create and set up the events object
172 event_object = mlt_properties_new( );
173 mlt_events_init( event_object );
174 mlt_events_register( event_object, "producer-create-request", ( mlt_transmitter )mlt_factory_create_request );
175 mlt_events_register( event_object, "producer-create-done", ( mlt_transmitter )mlt_factory_create_done );
176 mlt_events_register( event_object, "filter-create-request", ( mlt_transmitter )mlt_factory_create_request );
177 mlt_events_register( event_object, "filter-create-done", ( mlt_transmitter )mlt_factory_create_done );
178 mlt_events_register( event_object, "transition-create-request", ( mlt_transmitter )mlt_factory_create_request );
179 mlt_events_register( event_object, "transition-create-done", ( mlt_transmitter )mlt_factory_create_done );
180 mlt_events_register( event_object, "consumer-create-request", ( mlt_transmitter )mlt_factory_create_request );
181 mlt_events_register( event_object, "consumer-create-done", ( mlt_transmitter )mlt_factory_create_done );
183 // Create the repository of services
184 repository = mlt_repository_init( mlt_directory );
186 // Force a clean up when app closes
187 atexit( mlt_factory_close );
193 /** Fetch the events object.
195 * \return the global factory event object
198 mlt_properties mlt_factory_event_object( )
203 /** Fetch the module directory used in this instance.
205 * \return the full path to the module directory that this session is using
208 const char *mlt_factory_directory( )
210 return mlt_directory;
213 /** Get a value from the environment.
215 * \param name the name of a MLT (runtime configuration) environment variable
216 * \return the value of the variable
219 char *mlt_environment( const char *name )
221 if ( global_properties )
222 return mlt_properties_get( global_properties, name );
227 /** Set a value in the environment.
229 * \param name the name of a MLT environment variable
230 * \param value the value of the variable
231 * \return true on error
234 int mlt_environment_set( const char *name, const char *value )
236 if ( global_properties )
237 return mlt_properties_set( global_properties, name, value );
242 /** Set some properties common to all services.
244 * This sets _unique_id, \p mlt_type, \p mlt_service (unless _mlt_service_hidden), and _profile.
246 * \param properties a service's properties list
247 * \param profile the \p mlt_profile supplied to the factory function
248 * \param type the MLT service class
249 * \param service the name of the service
252 static void set_common_properties( mlt_properties properties, mlt_profile profile, const char *type, const char *service )
254 mlt_properties_set_int( properties, "_unique_id", ++ unique_id );
255 mlt_properties_set( properties, "mlt_type", type );
256 if ( mlt_properties_get_int( properties, "_mlt_service_hidden" ) == 0 )
257 mlt_properties_set( properties, "mlt_service", service );
258 if ( profile != NULL )
259 mlt_properties_set_data( properties, "_profile", profile, 0, NULL, NULL );
262 /** Fetch a producer from the repository.
264 * \param profile the \p mlt_profile to use
265 * \param service the name of the producer (optional, defaults to MLT_PRODUCER)
266 * \param input an optional argument to the producer constructor, typically a string
267 * \return a new producer
270 mlt_producer mlt_factory_producer( mlt_profile profile, const char *service, const void *input )
272 mlt_producer obj = NULL;
274 // Pick up the default normalising producer if necessary
275 if ( service == NULL )
276 service = mlt_environment( "MLT_PRODUCER" );
278 // Offer the application the chance to 'create'
279 mlt_events_fire( event_object, "producer-create-request", service, input, &obj, NULL );
281 // Try to instantiate via the specified service
284 obj = mlt_repository_create( repository, profile, producer_type, service, input );
285 mlt_events_fire( event_object, "producer-create-done", service, input, obj, NULL );
288 mlt_properties properties = MLT_PRODUCER_PROPERTIES( obj );
289 set_common_properties( properties, profile, "producer", service );
295 /** Fetch a filter from the repository.
297 * \param profile the \p mlt_profile to use
298 * \param service the name of the filter
299 * \param input an optional argument to the filter constructor, typically a string
300 * \return a new filter
303 mlt_filter mlt_factory_filter( mlt_profile profile, const char *service, const void *input )
305 mlt_filter obj = NULL;
307 // Offer the application the chance to 'create'
308 mlt_events_fire( event_object, "filter-create-request", service, input, &obj, NULL );
312 obj = mlt_repository_create( repository, profile, filter_type, service, input );
313 mlt_events_fire( event_object, "filter-create-done", service, input, obj, NULL );
318 mlt_properties properties = MLT_FILTER_PROPERTIES( obj );
319 set_common_properties( properties, profile, "filter", service );
324 /** Fetch a transition from the repository.
326 * \param profile the \p mlt_profile to use
327 * \param service the name of the transition
328 * \param input an optional argument to the transition constructor, typically a string
329 * \return a new transition
332 mlt_transition mlt_factory_transition( mlt_profile profile, const char *service, const void *input )
334 mlt_transition obj = NULL;
336 // Offer the application the chance to 'create'
337 mlt_events_fire( event_object, "transition-create-request", service, input, &obj, NULL );
341 obj = mlt_repository_create( repository, profile, transition_type, service, input );
342 mlt_events_fire( event_object, "transition-create-done", service, input, obj, NULL );
347 mlt_properties properties = MLT_TRANSITION_PROPERTIES( obj );
348 set_common_properties( properties, profile, "transition", service );
353 /** Fetch a consumer from the repository.
355 * \param profile the \p mlt_profile to use
356 * \param service the name of the consumer (optional, defaults to MLT_CONSUMER)
357 * \param input an optional argument to the consumer constructor, typically a string
358 * \return a new consumer
361 mlt_consumer mlt_factory_consumer( mlt_profile profile, const char *service, const void *input )
363 mlt_consumer obj = NULL;
365 if ( service == NULL )
366 service = mlt_environment( "MLT_CONSUMER" );
368 // Offer the application the chance to 'create'
369 mlt_events_fire( event_object, "consumer-create-request", service, input, &obj, NULL );
373 obj = mlt_repository_create( repository, profile, consumer_type, service, input );
374 mlt_events_fire( event_object, "consumer-create-done", service, input, obj, NULL );
379 mlt_properties properties = MLT_CONSUMER_PROPERTIES( obj );
380 set_common_properties( properties, profile, "consumer", service );
385 /** Register an object for clean up.
387 * \param ptr an opaque pointer to anything allocated on the heap
388 * \param destructor the function pointer of the deallocation subroutine (e.g., free or \p mlt_pool_release)
391 void mlt_factory_register_for_clean_up( void *ptr, mlt_destructor destructor )
394 sprintf( unique, "%08d", mlt_properties_count( global_properties ) );
395 mlt_properties_set_data( global_properties, unique, ptr, 0, destructor, NULL );
398 /** Close the factory.
400 * Cleanup all resources for the session.
403 void mlt_factory_close( )
405 if ( mlt_directory != NULL )
407 mlt_properties_close( event_object );
409 mlt_properties_close( global_properties );
410 global_properties = NULL;
413 mlt_repository_close( repository );
416 free( mlt_directory );
417 mlt_directory = NULL;
422 mlt_properties mlt_global_properties( )
424 return global_properties;