in point fix, low latency sdl, minor fixes
[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 }
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 // Ensure that the inner producer ignores the in point
183 mlt_properties_set_int( mlt_producer_properties( producer ), "ignore_points", 1 );
184
185 // Now, we return the producer of the tractor
186 producer = mlt_tractor_producer( tractor );
187 }
188 }
189
190 // Return the tractor's producer
191 return producer;
192 }