pooling and properties checks; dv decoder stack; factory cleanup registering
[melted] / src / modules / fezzik / producer_fezzik.c
1 /*
2 * producer_fezzik.c -- a normalising filter
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 "producer_fezzik.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <fnmatch.h>
28
29 #include <framework/mlt.h>
30
31 static mlt_properties dictionary = NULL;
32
33 static void track_service( mlt_tractor tractor, void *service, mlt_destructor destructor )
34 {
35 mlt_properties properties = mlt_tractor_properties( tractor );
36 int registered = mlt_properties_get_int( properties, "_registered" );
37 char *key = mlt_properties_get( properties, "_registered" );
38 char *real = malloc( strlen( key ) + 2 );
39 sprintf( real, "_%s", key );
40 mlt_properties_set_data( properties, real, service, 0, destructor, NULL );
41 mlt_properties_set_int( properties, "_registered", ++ registered );
42 free( real );
43 }
44
45 static mlt_producer create_from( char *file, char *services )
46 {
47 mlt_producer producer = NULL;
48 char *temp = strdup( services );
49 char *service = temp;
50 do
51 {
52 char *p = strchr( service, ',' );
53 if ( p != NULL )
54 *p ++ = '\0';
55 producer = mlt_factory_producer( service, file );
56 service = p;
57 }
58 while ( producer == NULL && service != NULL );
59 free( temp );
60 return producer;
61 }
62
63 static mlt_producer create_producer( char *file )
64 {
65 mlt_producer result = NULL;
66
67 // 1st Line - check for service:resource handling
68 if ( strchr( file, ':' ) )
69 {
70 char *temp = strdup( file );
71 char *service = temp;
72 char *resource = strchr( temp, ':' );
73 *resource ++ = '\0';
74 result = mlt_factory_producer( service, resource );
75 free( temp );
76 }
77
78 // 2nd Line preferences
79 if ( result == NULL )
80 {
81 int i = 0;
82 char *lookup = strdup( file );
83 char *p = lookup;
84
85 // We only need to load the dictionary once
86 if ( dictionary == NULL )
87 {
88 char temp[ 1024 ];
89 sprintf( temp, "%s/fezzik.dict", mlt_factory_prefix( ) );
90 dictionary = mlt_properties_load( temp );
91 mlt_factory_register_for_clean_up( dictionary, ( mlt_destructor )mlt_properties_close );
92 }
93
94 // Convert the lookup string to lower case
95 while ( *p )
96 {
97 *p = tolower( *p );
98 p ++;
99 }
100
101 // Iterate through the dictionary
102 for ( i = 0; result == NULL && i < mlt_properties_count( dictionary ); i ++ )
103 {
104 char *name = mlt_properties_get_name( dictionary, i );
105 if ( fnmatch( name, lookup, 0 ) == 0 )
106 result = create_from( file, mlt_properties_get_value( dictionary, i ) );
107 }
108
109 free( lookup );
110 }
111
112 // Finally, try just loading as service
113 if ( result == NULL )
114 result = mlt_factory_producer( file, NULL );
115
116 return result;
117 }
118
119 static mlt_service create_filter( mlt_tractor tractor, mlt_service last, char *effect )
120 {
121 char *id = strdup( effect );
122 char *arg = strchr( id, ':' );
123 if ( arg != NULL )
124 *arg ++ = '\0';
125 mlt_filter filter = mlt_factory_filter( id, arg );
126 if ( filter != NULL )
127 {
128 mlt_filter_connect( filter, last, 0 );
129 track_service( tractor, filter, ( mlt_destructor )mlt_filter_close );
130 last = mlt_filter_service( filter );
131 }
132 free( id );
133 return last;
134 }
135
136 mlt_producer producer_fezzik_init( char *arg )
137 {
138 // Create the producer that the tractor will contain
139 mlt_producer producer = NULL;
140
141 if ( arg != NULL )
142 producer = create_producer( arg );
143
144 // Build the tractor if we have a producer and it isn't already westley'd :-)
145 if ( producer != NULL && mlt_properties_get( mlt_producer_properties( producer ), "westley" ) == NULL )
146 {
147 // Construct the tractor
148 mlt_tractor tractor = mlt_tractor_init( );
149
150 // Sanity check
151 if ( tractor != NULL )
152 {
153 // Extract the tractor properties
154 mlt_properties properties = mlt_tractor_properties( tractor );
155
156 // Our producer will be the last service
157 mlt_service last = mlt_producer_service( producer );
158
159 // Set the registered count
160 mlt_properties_set_int( properties, "_registered", 0 );
161
162 // Register our producer for seeking in the tractor
163 mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
164
165 // Now attach normalising filters
166 last = create_filter( tractor, last, "deinterlace" );
167 last = create_filter( tractor, last, "rescale" );
168 last = create_filter( tractor, last, "resize" );
169 last = create_filter( tractor, last, "resample" );
170
171 // Connect the tractor to the last
172 mlt_tractor_connect( tractor, last );
173
174 // Finally, inherit properties from producer
175 mlt_properties_inherit( properties, mlt_producer_properties( producer ) );
176
177 // Now make sure we don't lose our inherited identity
178 mlt_properties_set_int( properties, "_mlt_service_hidden", 1 );
179
180 // This is a temporary hack to ensure that westley doesn't dig too deep
181 // and fezzik doesn't overdo it with throwing rocks...
182 mlt_properties_set( properties, "westley", "was here" );
183
184 // We need to ensure that all further properties are mirrored in the producer
185 mlt_properties_mirror( properties, mlt_producer_properties( producer ) );
186
187 // Ensure that the inner producer ignores the in point
188 mlt_properties_set_int( mlt_producer_properties( producer ), "ignore_points", 1 );
189
190 // Now, we return the producer of the tractor
191 producer = mlt_tractor_producer( tractor );
192 }
193 }
194
195 // Return the tractor's producer
196 return producer;
197 }