]> git.sesse.net Git - mlt/blob - mlt/src/framework/mlt_service.c
Initial revision
[mlt] / 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 /** Return the properties object.
79 */
80
81 mlt_properties mlt_service_properties( mlt_service this )
82 {
83         return &this->parent;
84 }
85
86 /** Connect a producer service.
87         Returns: > 0 warning, == 0 success, < 0 serious error
88                          1 = this service does not accept input
89                          2 = the producer is invalid
90                          3 = the producer is already registered with this consumer
91 */
92
93 int mlt_service_connect_producer( mlt_service this, mlt_service producer, int index )
94 {
95         int i = 0;
96
97         // Get the service base
98         mlt_service_base *base = this->private;
99
100         // Does this service accept input?
101         if ( mlt_service_accepts_input( this ) == 0 )
102                 return 1;
103
104         // Does the producer service accept output connections?
105         if ( mlt_service_accepts_output( producer ) == 0 )
106                 return 2;
107
108         // Check if the producer is already registered with this service
109         for ( i = 0; i < base->count; i ++ )
110                 if ( base->in[ i ] == producer )
111                         return 3;
112
113         // Allocate space
114         if ( index >= base->size )
115         {
116                 int new_size = base->size + index + 10;
117                 base->in = realloc( base->in, new_size * sizeof( mlt_service ) );
118                 if ( base->in != NULL )
119                 {
120                         for ( i = base->size; i < new_size; i ++ )
121                                 base->in[ i ] = NULL;
122                         base->size = new_size;
123                 }
124         }
125
126         // If we have space, assign the input
127         if ( base->in != NULL && index >= 0 && index < base->size )
128         {
129                 // Now we disconnect the producer service from its consumer
130                 mlt_service_disconnect( producer );
131                 
132                 // Add the service to index specified
133                 base->in[ index ] = producer;
134                 
135                 // Determine the number of active tracks
136                 if ( index >= base->count )
137                         base->count = index + 1;
138
139                 // Now we connect the producer to its connected consumer
140                 mlt_service_connect( producer, this );
141
142                 // Inform caller that all went well
143                 return 0;
144         }
145         else
146         {
147                 return -1;
148         }
149 }
150
151 /** Disconnect this service from its consumer.
152 */
153
154 void mlt_service_disconnect( mlt_service this )
155 {
156         // Get the service base
157         mlt_service_base *base = this->private;
158
159         // There's a bit more required here...
160         base->out = NULL;
161 }
162
163 /** Associate this service to the its consumer.
164 */
165
166 void mlt_service_connect( mlt_service this, mlt_service that )
167 {
168         // Get the service base
169         mlt_service_base *base = this->private;
170
171         // There's a bit more required here...
172         base->out = that;
173 }
174
175 /** Get the service state.
176 */
177
178 mlt_service_state mlt_service_get_state( mlt_service this )
179 {
180         mlt_service_state state = mlt_state_unknown;
181         if ( mlt_service_has_input( this ) )
182                 state |= mlt_state_providing;
183         if ( mlt_service_has_output( this ) )
184                 state |= mlt_state_connected;
185         if ( state != ( mlt_state_providing | mlt_state_connected ) )
186                 state |= mlt_state_dormant;
187         return state;
188 }
189
190 /** Get the maximum number of inputs accepted.
191         Returns: -1 for many, 0 for none or n for fixed.
192 */
193
194 int mlt_service_accepts_input( mlt_service this )
195 {
196         if ( this->accepts_input == NULL )
197                 return -1;
198         else
199                 return this->accepts_input( this );
200 }
201
202 /** Get the maximum number of outputs accepted.
203 */
204
205 int mlt_service_accepts_output( mlt_service this )
206 {
207         if ( this->accepts_output == NULL )
208                 return 1;
209         else
210                 return this->accepts_output( this );
211 }
212
213 /** Determines if this service has input
214 */
215
216 int mlt_service_has_input( mlt_service this )
217 {
218         if ( this->has_input == NULL )
219                 return 1;
220         else
221                 return this->has_input( this );
222 }
223
224 /** Determine if this service has output
225 */
226
227 int mlt_service_has_output( mlt_service this )
228 {
229         mlt_service_base *base = this->private;
230         if ( this->has_output == NULL )
231                 return base->out != NULL;
232         else
233                 return this->has_output( this );
234 }
235
236 /** Check if the service is active.
237 */
238
239 int mlt_service_is_active( mlt_service this )
240 {
241         return !( mlt_service_get_state( this ) & mlt_state_dormant );
242 }
243
244 /** Obtain a frame to pass on.
245 */
246
247 static int service_get_frame( mlt_service this, mlt_frame_ptr frame, int index )
248 {
249         mlt_service_base *base = this->private;
250         if ( index < base->count )
251         {
252                 mlt_service producer = base->in[ index ];
253                 if ( producer != NULL )
254                         return mlt_service_get_frame( producer, frame, index );
255         }
256         *frame = mlt_frame_init( );
257         return 0;
258 }
259
260 int mlt_service_get_frame( mlt_service this, mlt_frame_ptr frame, int index )
261 {
262         return this->get_frame( this, frame, index );
263 }
264
265 /** Close the service.
266 */
267
268 void mlt_service_close( mlt_service this )
269 {
270         mlt_service_base *base = this->private;
271         free( base->in );
272         free( base );
273         mlt_properties_close( &this->parent );
274 }
275