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"
34 /** the default subdirectory of the libdir for holding modules (plugins) */
35 #define PREFIX_LIB "\\lib\\mlt"
36 /** the default subdirectory of the install prefix for holding module (plugin) data */
37 #define PREFIX_DATA "\\share\\mlt"
38 #elif defined(__DARWIN__) && defined(RELOCATABLE)
39 #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 MLTDATADIR "/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 char *path2 = strdup( path );
156 char *exedir = dirname( path2 );
157 if ( global_properties && !getenv( "MLT_DATA" ) )
159 mlt_directory = calloc( 1, size + strlen( PREFIX_DATA ) + 1 );
160 strcpy( mlt_directory, exedir );
161 strcat( mlt_directory, PREFIX_DATA );
162 mlt_properties_set( global_properties, "MLT_DATA", mlt_directory );
163 free( mlt_directory );
165 mlt_directory = calloc( 1, size + strlen( directory ) + 1 );
166 strcpy( mlt_directory, exedir );
167 strcat( mlt_directory, directory );
171 // Initialise the pool
174 // Create and set up the events object
175 event_object = mlt_properties_new( );
176 mlt_events_init( event_object );
177 mlt_events_register( event_object, "producer-create-request", ( mlt_transmitter )mlt_factory_create_request );
178 mlt_events_register( event_object, "producer-create-done", ( mlt_transmitter )mlt_factory_create_done );
179 mlt_events_register( event_object, "filter-create-request", ( mlt_transmitter )mlt_factory_create_request );
180 mlt_events_register( event_object, "filter-create-done", ( mlt_transmitter )mlt_factory_create_done );
181 mlt_events_register( event_object, "transition-create-request", ( mlt_transmitter )mlt_factory_create_request );
182 mlt_events_register( event_object, "transition-create-done", ( mlt_transmitter )mlt_factory_create_done );
183 mlt_events_register( event_object, "consumer-create-request", ( mlt_transmitter )mlt_factory_create_request );
184 mlt_events_register( event_object, "consumer-create-done", ( mlt_transmitter )mlt_factory_create_done );
186 // Create the repository of services
187 repository = mlt_repository_init( mlt_directory );
189 // Force a clean up when app closes
190 atexit( mlt_factory_close );
196 /** Fetch the events object.
198 * \return the global factory event object
201 mlt_properties mlt_factory_event_object( )
206 /** Fetch the module directory used in this instance.
208 * \return the full path to the module directory that this session is using
211 const char *mlt_factory_directory( )
213 return mlt_directory;
216 /** Get a value from the environment.
218 * \param name the name of a MLT (runtime configuration) environment variable
219 * \return the value of the variable
222 char *mlt_environment( const char *name )
224 if ( global_properties )
225 return mlt_properties_get( global_properties, name );
230 /** Set a value in the environment.
232 * \param name the name of a MLT environment variable
233 * \param value the value of the variable
234 * \return true on error
237 int mlt_environment_set( const char *name, const char *value )
239 if ( global_properties )
240 return mlt_properties_set( global_properties, name, value );
245 /** Set some properties common to all services.
247 * This sets _unique_id, \p mlt_type, \p mlt_service (unless _mlt_service_hidden), and _profile.
249 * \param properties a service's properties list
250 * \param profile the \p mlt_profile supplied to the factory function
251 * \param type the MLT service class
252 * \param service the name of the service
255 static void set_common_properties( mlt_properties properties, mlt_profile profile, const char *type, const char *service )
257 mlt_properties_set_int( properties, "_unique_id", ++ unique_id );
258 mlt_properties_set( properties, "mlt_type", type );
259 if ( mlt_properties_get_int( properties, "_mlt_service_hidden" ) == 0 )
260 mlt_properties_set( properties, "mlt_service", service );
261 if ( profile != NULL )
262 mlt_properties_set_data( properties, "_profile", profile, 0, NULL, NULL );
265 /** Fetch a producer from the repository.
267 * \param profile the \p mlt_profile to use
268 * \param service the name of the producer (optional, defaults to MLT_PRODUCER)
269 * \param input an optional argument to the producer constructor, typically a string
270 * \return a new producer
273 mlt_producer mlt_factory_producer( mlt_profile profile, const char *service, const void *input )
275 mlt_producer obj = NULL;
277 // Pick up the default normalising producer if necessary
278 if ( service == NULL )
279 service = mlt_environment( "MLT_PRODUCER" );
281 // Offer the application the chance to 'create'
282 mlt_events_fire( event_object, "producer-create-request", service, input, &obj, NULL );
284 // Try to instantiate via the specified service
287 obj = mlt_repository_create( repository, profile, producer_type, service, input );
288 mlt_events_fire( event_object, "producer-create-done", service, input, obj, NULL );
291 mlt_properties properties = MLT_PRODUCER_PROPERTIES( obj );
292 set_common_properties( properties, profile, "producer", service );
298 /** Fetch a filter from the repository.
300 * \param profile the \p mlt_profile to use
301 * \param service the name of the filter
302 * \param input an optional argument to the filter constructor, typically a string
303 * \return a new filter
306 mlt_filter mlt_factory_filter( mlt_profile profile, const char *service, const void *input )
308 mlt_filter obj = NULL;
310 // Offer the application the chance to 'create'
311 mlt_events_fire( event_object, "filter-create-request", service, input, &obj, NULL );
315 obj = mlt_repository_create( repository, profile, filter_type, service, input );
316 mlt_events_fire( event_object, "filter-create-done", service, input, obj, NULL );
321 mlt_properties properties = MLT_FILTER_PROPERTIES( obj );
322 set_common_properties( properties, profile, "filter", service );
327 /** Fetch a transition from the repository.
329 * \param profile the \p mlt_profile to use
330 * \param service the name of the transition
331 * \param input an optional argument to the transition constructor, typically a string
332 * \return a new transition
335 mlt_transition mlt_factory_transition( mlt_profile profile, const char *service, const void *input )
337 mlt_transition obj = NULL;
339 // Offer the application the chance to 'create'
340 mlt_events_fire( event_object, "transition-create-request", service, input, &obj, NULL );
344 obj = mlt_repository_create( repository, profile, transition_type, service, input );
345 mlt_events_fire( event_object, "transition-create-done", service, input, obj, NULL );
350 mlt_properties properties = MLT_TRANSITION_PROPERTIES( obj );
351 set_common_properties( properties, profile, "transition", service );
356 /** Fetch a consumer from the repository.
358 * \param profile the \p mlt_profile to use
359 * \param service the name of the consumer (optional, defaults to MLT_CONSUMER)
360 * \param input an optional argument to the consumer constructor, typically a string
361 * \return a new consumer
364 mlt_consumer mlt_factory_consumer( mlt_profile profile, const char *service, const void *input )
366 mlt_consumer obj = NULL;
368 if ( service == NULL )
369 service = mlt_environment( "MLT_CONSUMER" );
371 // Offer the application the chance to 'create'
372 mlt_events_fire( event_object, "consumer-create-request", service, input, &obj, NULL );
376 obj = mlt_repository_create( repository, profile, consumer_type, service, input );
377 mlt_events_fire( event_object, "consumer-create-done", service, input, obj, NULL );
382 mlt_properties properties = MLT_CONSUMER_PROPERTIES( obj );
383 set_common_properties( properties, profile, "consumer", service );
388 /** Register an object for clean up.
390 * \param ptr an opaque pointer to anything allocated on the heap
391 * \param destructor the function pointer of the deallocation subroutine (e.g., free or \p mlt_pool_release)
394 void mlt_factory_register_for_clean_up( void *ptr, mlt_destructor destructor )
397 sprintf( unique, "%08d", mlt_properties_count( global_properties ) );
398 mlt_properties_set_data( global_properties, unique, ptr, 0, destructor, NULL );
401 /** Close the factory.
403 * Cleanup all resources for the session.
406 void mlt_factory_close( )
408 if ( mlt_directory != NULL )
410 mlt_properties_close( event_object );
412 mlt_properties_close( global_properties );
413 global_properties = NULL;
416 mlt_repository_close( repository );
419 free( mlt_directory );
420 mlt_directory = NULL;
425 mlt_properties mlt_global_properties( )
427 return global_properties;