]> git.sesse.net Git - mlt/blob - src/modules/fezzik/producer_fezzik.c
fezzik gets a rhyming dictionary
[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
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                 }
92
93                 // Convert the lookup string to lower case
94                 while ( *p )
95                 {
96                         *p = tolower( *p );
97                         p ++;
98                 }
99
100                 // Iterate through the dictionary
101                 for ( i = 0; result == NULL && i < mlt_properties_count( dictionary ); i ++ )
102                 {
103                         char *name = mlt_properties_get_name( dictionary, i );
104                         if ( fnmatch( name, lookup, 0 ) == 0 )
105                                 result = create_from( file, mlt_properties_get_value( dictionary, i ) );
106                 }
107
108                 free( lookup );
109         }
110
111         return result;
112 }
113
114 static mlt_service create_filter( mlt_tractor tractor, mlt_service last, char *effect )
115 {
116         char *id = strdup( effect );
117         char *arg = strchr( id, ':' );
118         if ( arg != NULL )
119                 *arg ++ = '\0';
120         mlt_filter filter = mlt_factory_filter( id, arg );
121         if ( filter != NULL )
122         {
123                 mlt_filter_connect( filter, last, 0 );
124                 track_service( tractor, filter, ( mlt_destructor )mlt_filter_close );
125                 last = mlt_filter_service( filter );
126         }
127         free( id );
128         return last;
129 }
130
131 mlt_producer producer_fezzik_init( char *arg )
132 {
133         // Create the producer that the tractor will contain
134         mlt_producer producer = NULL;
135
136         if ( arg != NULL )
137                 producer = create_producer( arg );
138
139         // Build the tractor if we have a producer and it isn't already westley'd :-)
140         if ( producer != NULL && mlt_properties_get( mlt_producer_properties( producer ), "westley" ) == NULL )
141         {
142                 // Construct the tractor
143                 mlt_tractor tractor = mlt_tractor_init( );
144
145                 // Sanity check
146                 if ( tractor != NULL )
147                 {
148                         // Extract the tractor properties
149                         mlt_properties properties = mlt_tractor_properties( tractor );
150
151                         // Our producer will be the last service
152                         mlt_service last = mlt_producer_service( producer );
153
154                         // Set the registered count
155                         mlt_properties_set_int( properties, "_registered", 0 );
156
157                         // Register our producer for seeking in the tractor
158                         mlt_properties_set_data( properties, "producer", producer, 0, ( mlt_destructor )mlt_producer_close, NULL );
159
160                         // Now attach normalising filters
161                         last = create_filter( tractor, last, "deinterlace" );
162                         last = create_filter( tractor, last, "rescale" );
163                         last = create_filter( tractor, last, "resize" );
164                         last = create_filter( tractor, last, "resample" );
165
166                         // Connect the tractor to the last
167                         mlt_tractor_connect( tractor, last );
168
169                         // Finally, inherit properties from producer
170                         mlt_properties_inherit( properties, mlt_producer_properties( producer ) );
171
172                         // Now make sure we don't lose our inherited identity
173                         mlt_properties_set_int( properties, "_mlt_service_hidden", 1 );
174
175                         // This is a temporary hack to ensure that westley doesn't dig too deep
176                         // and fezzik doesn't overdo it with throwing rocks...
177                         mlt_properties_set( properties, "westley", "was here" );
178
179                         // We need to ensure that all further properties are mirrored in the producer
180                         mlt_properties_mirror( properties, mlt_producer_properties( producer ) );
181
182                         // Now, we return the producer of the tractor
183                         producer = mlt_tractor_producer( tractor );
184                 }
185         }
186
187         // Return the tractor's producer
188         return producer;
189 }