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