]> git.sesse.net Git - mlt/blob - src/framework/mlt_field.c
field and playlist provisional implementations
[mlt] / src / framework / mlt_field.c
1 /*
2  * mlt_field.c -- A field for planting multiple transitions and filters
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 "mlt_field.h"
22 #include "mlt_service.h"
23 #include "mlt_filter.h"
24 #include "mlt_transition.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 /** Private structures.
30 */
31
32 struct mlt_field_s
33 {
34         // We extending service here
35         struct mlt_service_s parent;
36
37         // This is the producer we're connected to
38         mlt_service producer;
39 };
40
41 /** Forward declarations
42 */
43
44 static int service_get_frame( mlt_service service, mlt_frame_ptr frame, int index );
45
46 /** Constructor. This service needs to know its producer at construction.
47
48         When the first filter or transition is planted, we connect it immediately to
49         the producer of the field, and all subsequent plants are then connected to the
50         previous plant. This immediate connection requires the producer prior to the first
51         plant.
52         
53         It's a kind of arbitrary decsion - we could generate a dummy service here and 
54         then connect the dummy in the normal connect manner. Behaviour may change in the
55         future (say, constructing a dummy when producer service is NULL). However, the
56         current solution is quite clean, if slightly out of sync with the rest of the
57         mlt framework.
58 */
59
60 mlt_field mlt_field_init( mlt_service producer )
61 {
62         // Initialise the field
63         mlt_field this = calloc( sizeof( struct mlt_field_s ), 1 );
64
65         // Get the service
66         mlt_service service = &this->parent;
67
68         // Initialise the service
69         mlt_service_init( service, this );
70
71         // Override the get_frame method
72         service->get_frame = service_get_frame;
73
74         // Connect to the producer immediately
75         if ( mlt_service_connect_producer( service, producer, 0 ) == 0 )
76                 this->producer = producer;
77
78         // Return this
79         return this;
80 }
81
82 /** Get the service associated to this field.
83 */
84
85 mlt_service mlt_field_service( mlt_field this )
86 {
87         return &this->parent;
88 }
89
90 /** Get the properties associated to this field.
91 */
92
93 mlt_properties mlt_field_properties( mlt_field this )
94 {
95         return mlt_service_properties( &this->parent );
96 }
97
98 /** Plant a filter.
99 */
100
101 int mlt_field_plant_filter( mlt_field this, mlt_filter that, int track )
102 {
103         // Connect the filter to the last producer
104         int result = mlt_filter_connect( that, this->producer, track );
105
106         // If sucessful, then we'll use this for connecting in the future
107         if ( result == 0 )
108         {
109                 // Update last
110                 this->producer = mlt_filter_service( that );
111         }
112
113         return result;
114 }
115
116 /** Plant a transition.
117 */
118
119 int mlt_field_plant_transition( mlt_field this, mlt_transition that, int a_track, int b_track )
120 {
121         // Connect the transition to the last producer
122         int result = mlt_transition_connect( that, this->producer, a_track, b_track );
123
124         // If sucessful, then we'll use this for connecting in the future
125         if ( result == 0 )
126         {
127                 // Update last
128                 this->producer = mlt_transition_service( that );
129         }
130
131         return 0;
132 }
133
134 /** Get a frame.
135 */
136
137 static int service_get_frame( mlt_service service, mlt_frame_ptr frame, int index )
138 {
139         mlt_field this = service->child;
140         return mlt_service_get_frame( this->producer, frame, index );
141 }
142
143 /** Close the field.
144 */
145
146 void mlt_field_close( mlt_field this )
147 {
148         mlt_service_close( &this->parent );
149         free( this );
150 }
151