]> git.sesse.net Git - mlt/blob - src/modules/westley/consumer_westley.c
xml based westley serialisation
[mlt] / src / modules / westley / consumer_westley.c
1 /*
2  * consumer_westley.c -- a libxml2 serialiser of mlt service networks
3  * Copyright (C) 2003-2004 Ushodaya Enterprises Limited
4  * Author: Dan Dennedy <dan@dennedy.org>
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 "consumer_westley.h"
22 #include <framework/mlt.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <pthread.h>
27 #include <libxml/tree.h>
28
29 /** Forward references to static functions.
30 */
31
32 static int consumer_start( mlt_consumer parent );
33
34 /** This is what will be called by the factory - anything can be passed in
35         via the argument, but keep it simple.
36 */
37
38 mlt_consumer consumer_westley_init( char *arg )
39 {
40         // Create the consumer object
41         mlt_consumer this = calloc( sizeof( struct mlt_consumer_s ), 1 );
42
43         // If no malloc'd and consumer init ok
44         if ( this != NULL && mlt_consumer_init( this, NULL ) == 0 )
45         {
46                 // We have stuff to clean up, so override the close method
47                 //parent->close = consumer_close;
48
49                 // Allow thread to be started/stopped
50                 this->start = consumer_start;
51
52                 // Return the consumer produced
53                 return this;
54         }
55
56         // malloc or consumer init failed
57         free( this );
58
59         // Indicate failure
60         return NULL;
61 }
62
63
64 // This maintains counters for adding ids to elements
65 struct serialise_context_s
66 {
67         int producer_count;
68         int multitrack_count;
69         int playlist_count;
70         int tractor_count;
71         int filter_count;
72         int transition_count;
73 };
74 typedef struct serialise_context_s* serialise_context;
75
76
77 static inline void serialise_properties( mlt_properties properties, xmlNode *node )
78 {
79         int i;
80         xmlNode *p;
81         
82         // Enumerate the properties
83         for ( i = 0; i < mlt_properties_count( properties ); i++ )
84         {
85 #if 0
86                 p = xmlNewChild( node, NULL, "prop", NULL );
87 #else
88                 p = node;
89 #endif
90                 xmlNewProp( p, mlt_properties_get_name( properties, i ), mlt_properties_get_value( properties, i ) );
91         }
92 }
93
94 static xmlNode* serialise_service( serialise_context context, mlt_service service, xmlNode *node )
95 {
96         int i;
97         xmlNode *child = node;
98         char id[ 31 ];
99         id[ 30 ] = '\0';
100         
101         // Iterate over consumer/producer connections
102         while ( service != NULL )
103         {
104                 mlt_properties properties = mlt_service_properties( service );
105                 char *mlt_type = mlt_properties_get( properties, "mlt_type" );
106                 
107                 // Tell about the producer
108                 if ( strcmp( mlt_type, "producer" ) == 0 )
109                 {
110                         child = xmlNewChild( node, NULL, "producer", NULL );
111
112                         // Set the id
113                         if ( mlt_properties_get( properties, "id" ) != NULL )
114                                 xmlNewProp( child, "id", mlt_properties_get( properties, "mlt_service" ) );
115                         else
116                         {
117                                 snprintf( id, 30, "producer%d", context->producer_count++ );
118                                 xmlNewProp( child, "id", id );
119                         }
120                         
121                         //xmlNewProp( child, "type", mlt_properties_get( properties, "mlt_service" ) );
122                         //xmlNewProp( child, "src", mlt_properties_get( properties, "resource" ) );
123             serialise_properties( properties, child );
124                 }
125
126                 // Tell about the framework container producers
127                 else if ( strcmp( mlt_type, "mlt_producer" ) == 0 )
128                 {
129                         // Recurse on multitrack's tracks
130                         if ( strcmp( mlt_properties_get( properties, "resource" ), "<multitrack>" ) == 0 )
131                         {
132                                 child = xmlNewChild( node, NULL, "multitrack", NULL );
133                                 
134                                 // Set the id
135                                 if ( mlt_properties_get( properties, "id" ) != NULL )
136                                         xmlNewProp( child, "id", mlt_properties_get( properties, "mlt_service" ) );
137                                 else
138                                 {
139                                         snprintf( id, 30, "multitrack%d", context->multitrack_count++ );
140                                         xmlNewProp( child, "id", id );
141                                 }
142
143                                 // Iterate over the tracks
144                                 for ( i = 0; i < mlt_multitrack_count( MLT_MULTITRACK( service ) ); i++ )
145                                 {
146                                         xmlNode *track = xmlNewChild( child, NULL, "track", NULL );
147                                         serialise_service( context, MLT_SERVICE( mlt_multitrack_track( MLT_MULTITRACK( service ), i ) ), track );
148                                 }
149                                 break;
150                         }
151                         
152                         // Recurse on playlist's clips
153                         else if ( strcmp( mlt_properties_get( properties, "resource" ), "<playlist>" ) == 0 )
154                         {
155                                 mlt_playlist_clip_info info;
156                                 child = xmlNewChild( node, NULL, "playlist", NULL );
157                                 
158                                 // Set the id
159                                 if ( mlt_properties_get( properties, "id" ) != NULL )
160                                         xmlNewProp( child, "id", mlt_properties_get( properties, "mlt_service" ) );
161                                 else
162                                 {
163                                         snprintf( id, 30, "playlist%d", context->playlist_count++ );
164                                         xmlNewProp( child, "id", id );
165                                 }
166
167                                 xmlNewProp( child, "in", mlt_properties_get( properties, "in" ) );
168                                 xmlNewProp( child, "out", mlt_properties_get( properties, "out" ) );
169
170                                 // Iterate over the playlist entries
171                                 for ( i = 0; i < mlt_playlist_count( MLT_PLAYLIST( service ) ); i++ )
172                                 {
173                                         if ( ! mlt_playlist_get_clip_info( MLT_PLAYLIST( service ), &info, i ) )
174                                         {
175                                                 if ( strcmp( mlt_properties_get( mlt_producer_properties( info.producer ), "mlt_service" ), "blank" ) == 0 )
176                                                 {
177                                                         char length[ 20 ];
178                                                         length[ 19 ] = '\0';
179                                                         xmlNode *entry = xmlNewChild( child, NULL, "blank", NULL );
180                                                         snprintf( length, 19, "%lld", info.length );
181                                                         xmlNewProp( entry, "length", length );
182                                                 }
183                                                 else
184                                                 {
185                                                         xmlNode *entry = xmlNewChild( child, NULL, "entry", NULL );
186                                                         serialise_service( context, MLT_SERVICE( info.producer ), entry );
187                                                 }
188                                         }
189                                 }
190                         }
191                         
192                         // Recurse on tractor's producer
193                         else if ( strcmp( mlt_properties_get( properties, "resource" ), "<tractor>" ) == 0 )
194                         {
195                                 child = xmlNewChild( node, NULL, "tractor", NULL );
196
197                                 // Set the id
198                                 if ( mlt_properties_get( properties, "id" ) != NULL )
199                                         xmlNewProp( child, "id", mlt_properties_get( properties, "mlt_service" ) );
200                                 else
201                                 {
202                                         snprintf( id, 30, "tractor%d", context->tractor_count++ );
203                                         xmlNewProp( child, "id", id );
204                                 }
205
206                                 // Recurse on connected producer
207                                 serialise_service( context, mlt_service_get_producer( service ), child );
208                                 
209                                 break;
210                         }
211                 }
212                 
213                 // Tell about a filter
214                 else if ( strcmp( mlt_type, "filter" ) == 0 )
215                 {
216                         // Recurse on connected producer
217                         child = serialise_service( context, MLT_SERVICE( MLT_FILTER( service )->producer ), node );
218
219                         // sanity check
220                         if ( child == NULL )
221                                 break;
222
223                         node = xmlNewChild( child, NULL, "filter", NULL );
224
225                         // Set the id
226                         if ( mlt_properties_get( properties, "id" ) != NULL )
227                                 xmlNewProp( node, "id", mlt_properties_get( properties, "mlt_service" ) );
228                         else
229                         {
230                                 snprintf( id, 30, "filter%d", context->filter_count++ );
231                                 xmlNewProp( node, "id", id );
232                         }
233
234                         //xmlNewProp( node, "type", mlt_properties_get( properties, "mlt_service" ) );
235
236                         serialise_properties( properties, node );
237
238                         break;
239                 }
240                 
241                 // Tell about a transition
242                 else if ( strcmp( mlt_type, "transition" ) == 0 )
243                 {
244                         // Recurse on connected producer
245                         child = serialise_service( context, MLT_SERVICE( MLT_TRANSITION( service )->producer ), node );
246
247                         // sanity check
248                         if ( child == NULL )
249                                 break;
250
251                         node = xmlNewChild( child, NULL, "transition", NULL );
252                         
253                         // Set the id
254                         if ( mlt_properties_get( properties, "id" ) != NULL )
255                                 xmlNewProp( node, "id", mlt_properties_get( properties, "mlt_service" ) );
256                         else
257                         {
258                                 snprintf( id, 30, "transition%d", context->transition_count++ );
259                                 xmlNewProp( node, "id", id );
260                         }
261
262                         //xmlNewProp( node, "type", mlt_properties_get( properties, "mlt_service" ) );
263
264                         serialise_properties( properties, node );
265                         
266                         break;
267                 }
268                 
269                 // Get the next connected service
270                 service = mlt_service_get_producer( service );
271         }
272         return child;
273 }
274
275 static int consumer_start( mlt_consumer this )
276 {
277         mlt_service inigo = NULL;
278         xmlDoc *doc = xmlNewDoc( "1.0" );
279         xmlNode *root = xmlNewNode( NULL, "westley" );
280         xmlDocSetRootElement( doc, root );
281         
282         // Get the producer service
283         mlt_service service = mlt_service_get_producer( mlt_consumer_service( this ) );
284         if ( service != NULL )
285         {
286                 struct serialise_context_s context;
287                 memset( &context, 0, sizeof( struct serialise_context_s ) );
288                 
289                 // Remember inigo
290                 if ( mlt_properties_get( mlt_service_properties( service ), "mlt_service" ) != NULL &&
291                                 strcmp( mlt_properties_get( mlt_service_properties( service ), "mlt_service" ), "inigo" ) == 0 )
292                 {
293                         inigo = service;
294
295                         // Turn inigo's producer into a framework producer
296                         mlt_properties_set( mlt_service_properties( service ), "mlt_type", "mlt_producer" );
297                 }
298                         
299                 serialise_service( &context, service, root );
300                 xmlDocFormatDump( stderr, doc, 1 );
301         }
302
303         xmlFreeDoc( doc );
304         mlt_consumer_stop( this );
305
306         // Tell inigo, enough already!
307         if ( inigo != NULL )
308                 mlt_properties_set_int( mlt_service_properties( inigo ), "done", 1 );
309         
310         return 0;
311 }
312