]> git.sesse.net Git - mlt/blob - src/framework/mlt_service.c
Yet more sdl hacking, region memory leak fix, mlt_position changed to int32_t, experi...
[mlt] / src / framework / mlt_service.c
1 /*
2  * mlt_service.c -- interface for all service classes
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 "config.h"
22 #include "mlt_service.h"
23 #include "mlt_frame.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 /** IMPORTANT NOTES
29
30         The base service implements a null frame producing service - as such,
31         it is functional without extension and will produce test cards frames 
32         and PAL sized audio frames.
33
34         PLEASE DO NOT CHANGE THIS BEHAVIOUR!!! OVERRIDE THE METHODS THAT 
35         CONTROL THIS IN EXTENDING CLASSES.
36 */
37
38 /** Private service definition.
39 */
40
41 typedef struct
42 {
43         int size;
44         int count;
45         mlt_service *in;
46         mlt_service out;
47 }
48 mlt_service_base;
49
50 /** Friends?
51 */
52
53 static void mlt_service_disconnect( mlt_service this );
54 static void mlt_service_connect( mlt_service this, mlt_service that );
55 static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int index );
56
57 /** Constructor
58 */
59
60 int mlt_service_init( mlt_service this, void *child )
61 {
62         // Initialise everything to NULL
63         memset( this, 0, sizeof( struct mlt_service_s ) );
64
65         // Assign the child
66         this->child = child;
67
68         // Generate private space
69         this->private = calloc( sizeof( mlt_service_base ), 1 );
70
71         // Associate the methods
72         this->get_frame = service_get_frame;
73         
74         // Initialise the properties
75         return mlt_properties_init( &this->parent, this );
76 }
77
78 /** Connect a producer service.
79         Returns: > 0 warning, == 0 success, < 0 serious error
80                          1 = this service does not accept input
81                          2 = the producer is invalid
82                          3 = the producer is already registered with this consumer
83 */
84
85 int mlt_service_connect_producer( mlt_service this, mlt_service producer, int index )
86 {
87         int i = 0;
88
89         // Get the service base
90         mlt_service_base *base = this->private;
91
92         // Does this service accept input?
93         if ( mlt_service_accepts_input( this ) == 0 )
94                 return 1;
95
96         // Does the producer service accept output connections?
97         if ( mlt_service_accepts_output( producer ) == 0 )
98                 return 2;
99
100         // Check if the producer is already registered with this service
101         for ( i = 0; i < base->count; i ++ )
102                 if ( base->in[ i ] == producer )
103                         return 3;
104
105         // Allocate space
106         if ( index >= base->size )
107         {
108                 int new_size = base->size + index + 10;
109                 base->in = realloc( base->in, new_size * sizeof( mlt_service ) );
110                 if ( base->in != NULL )
111                 {
112                         for ( i = base->size; i < new_size; i ++ )
113                                 base->in[ i ] = NULL;
114                         base->size = new_size;
115                 }
116         }
117
118         // If we have space, assign the input
119         if ( base->in != NULL && index >= 0 && index < base->size )
120         {
121                 // Now we disconnect the producer service from its consumer
122                 mlt_service_disconnect( producer );
123                 
124                 // Add the service to index specified
125                 base->in[ index ] = producer;
126                 
127                 // Determine the number of active tracks
128                 if ( index >= base->count )
129                         base->count = index + 1;
130
131                 // Now we connect the producer to its connected consumer
132                 mlt_service_connect( producer, this );
133
134                 // Inform caller that all went well
135                 return 0;
136         }
137         else
138         {
139                 return -1;
140         }
141 }
142
143 /** Disconnect this service from its consumer.
144 */
145
146 void mlt_service_disconnect( mlt_service this )
147 {
148         // Get the service base
149         mlt_service_base *base = this->private;
150
151         // There's a bit more required here...
152         base->out = NULL;
153 }
154
155 /** Associate this service to the its consumer.
156 */
157
158 void mlt_service_connect( mlt_service this, mlt_service that )
159 {
160         // Get the service base
161         mlt_service_base *base = this->private;
162
163         // There's a bit more required here...
164         base->out = that;
165 }
166
167
168 /** Get the first connected producer service.
169 */
170
171 mlt_service mlt_service_get_producer( mlt_service this )
172 {
173         mlt_service producer = NULL;
174
175         // Get the service base
176         mlt_service_base *base = this->private;
177
178         if ( base->in != NULL )
179                 producer = base->in[ 0 ];
180         
181         return producer;
182 }
183  
184
185 /** Get the service state.
186 */
187
188 mlt_service_state mlt_service_get_state( mlt_service this )
189 {
190         mlt_service_state state = mlt_state_unknown;
191         if ( mlt_service_has_input( this ) )
192                 state |= mlt_state_providing;
193         if ( mlt_service_has_output( this ) )
194                 state |= mlt_state_connected;
195         if ( state != ( mlt_state_providing | mlt_state_connected ) )
196                 state |= mlt_state_dormant;
197         return state;
198 }
199
200 /** Get the maximum number of inputs accepted.
201         Returns: -1 for many, 0 for none or n for fixed.
202 */
203
204 int mlt_service_accepts_input( mlt_service this )
205 {
206         if ( this->accepts_input == NULL )
207                 return -1;
208         else
209                 return this->accepts_input( this );
210 }
211
212 /** Get the maximum number of outputs accepted.
213 */
214
215 int mlt_service_accepts_output( mlt_service this )
216 {
217         if ( this->accepts_output == NULL )
218                 return 1;
219         else
220                 return this->accepts_output( this );
221 }
222
223 /** Determines if this service has input
224 */
225
226 int mlt_service_has_input( mlt_service this )
227 {
228         if ( this->has_input == NULL )
229                 return 1;
230         else
231                 return this->has_input( this );
232 }
233
234 /** Determine if this service has output
235 */
236
237 int mlt_service_has_output( mlt_service this )
238 {
239         mlt_service_base *base = this->private;
240         if ( this->has_output == NULL )
241                 return base->out != NULL;
242         else
243                 return this->has_output( this );
244 }
245
246 /** Check if the service is active.
247 */
248
249 int mlt_service_is_active( mlt_service this )
250 {
251         return !( mlt_service_get_state( this ) & mlt_state_dormant );
252 }
253
254 /** Obtain a frame to pass on.
255 */
256
257 static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int index )
258 {
259         mlt_service_base *base = this->private;
260         if ( index < base->count )
261         {
262                 mlt_service producer = base->in[ index ];
263                 if ( producer != NULL )
264                         return mlt_service_get_frame( producer, frame, index );
265         }
266         *frame = mlt_frame_init( );
267         return 0;
268 }
269
270 int mlt_service_get_frame( mlt_service this, mlt_frame_ptr frame, int index )
271 {
272         return this->get_frame( this, frame, index );
273 }
274
275 /** Close the service.
276 */
277
278 void mlt_service_close( mlt_service this )
279 {
280         mlt_service_base *base = this->private;
281         free( base->in );
282         free( base );
283         mlt_properties_close( &this->parent );
284 }
285