field and playlist provisional implementations
[melted] / 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