src/framework/*: improve the doxygen documentation (work in progress). This also...
[melted] / src / framework / mlt_property.c
1 /**
2 * \file mlt_property.c
3 * \brief Property class definition
4 *
5 * Copyright (C) 2003-2008 Ushodaya Enterprises Limited
6 * \author Charles Yates <charles.yates@pandora.be>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include "mlt_property.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29
30 /** Bit pattern used internally to indicated representations available.
31 */
32
33 typedef enum
34 {
35 mlt_prop_none = 0, //!< not set
36 mlt_prop_int = 1, //!< set as an integer
37 mlt_prop_string = 2, //!< set as string or already converted to string
38 mlt_prop_position = 4,//!< set as a position
39 mlt_prop_double = 8, //!< set as a floating point
40 mlt_prop_data = 16, //!< set as opaque binary
41 mlt_prop_int64 = 32 //!< set as a 64-bit integer
42 }
43 mlt_property_type;
44
45 /** \brief Property class
46 *
47 * A property is like a variant or dynamic type. They are used for many things
48 * in MLT, but in particular they are the parameter mechanism for the plugins.
49 */
50
51 struct mlt_property_s
52 {
53 /// Stores a bit pattern of types available for this property
54 mlt_property_type types;
55
56 /// Atomic type handling
57 int prop_int;
58 mlt_position prop_position;
59 double prop_double;
60 int64_t prop_int64;
61
62 /// String handling
63 char *prop_string;
64
65 /// Generic type handling
66 void *data;
67 int length;
68 mlt_destructor destructor;
69 mlt_serialiser serialiser;
70 };
71
72 /** Construct a property and initialize it
73 * \public \memberof mlt_property_s
74 */
75
76 mlt_property mlt_property_init( )
77 {
78 mlt_property this = malloc( sizeof( struct mlt_property_s ) );
79 if ( this != NULL )
80 {
81 this->types = 0;
82 this->prop_int = 0;
83 this->prop_position = 0;
84 this->prop_double = 0;
85 this->prop_int64 = 0;
86 this->prop_string = NULL;
87 this->data = NULL;
88 this->length = 0;
89 this->destructor = NULL;
90 this->serialiser = NULL;
91 }
92 return this;
93 }
94
95 /** Clear (0/null) a property.
96 *
97 * Frees up any associated resources in the process.
98 * \private \memberof mlt_property_s
99 * \param this a property
100 */
101
102 static inline void mlt_property_clear( mlt_property this )
103 {
104 // Special case data handling
105 if ( this->types & mlt_prop_data && this->destructor != NULL )
106 this->destructor( this->data );
107
108 // Special case string handling
109 if ( this->types & mlt_prop_string )
110 free( this->prop_string );
111
112 // Wipe stuff
113 this->types = 0;
114 this->prop_int = 0;
115 this->prop_position = 0;
116 this->prop_double = 0;
117 this->prop_int64 = 0;
118 this->prop_string = NULL;
119 this->data = NULL;
120 this->length = 0;
121 this->destructor = NULL;
122 this->serialiser = NULL;
123 }
124
125 /** Set the property to an integer value.
126 *
127 * \public \memberof mlt_property_s
128 * \param this a property
129 * \param value an integer
130 * \return false
131 */
132
133 int mlt_property_set_int( mlt_property this, int value )
134 {
135 mlt_property_clear( this );
136 this->types = mlt_prop_int;
137 this->prop_int = value;
138 return 0;
139 }
140
141 /** Set the property to a floating point value.
142 *
143 * \public \memberof mlt_property_s
144 * \param this a property
145 * \param value a double precision floating point value
146 * \return false
147 */
148
149 int mlt_property_set_double( mlt_property this, double value )
150 {
151 mlt_property_clear( this );
152 this->types = mlt_prop_double;
153 this->prop_double = value;
154 return 0;
155 }
156
157 /** Set the property to a position value.
158 *
159 * Position is a relative time value in frame units.
160 * \public \memberof mlt_property_s
161 * \param this a property
162 * \param value a position value
163 * \return false
164 */
165
166 int mlt_property_set_position( mlt_property this, mlt_position value )
167 {
168 mlt_property_clear( this );
169 this->types = mlt_prop_position;
170 this->prop_position = value;
171 return 0;
172 }
173
174 /** Set the property to a string value.
175 *
176 * This makes a copy of the string you supply so you do not need to track
177 * a new reference to it.
178 * \public \memberof mlt_property_s
179 * \param this a property
180 * \param value the string to copy to the property
181 * \return true if it failed
182 */
183
184 int mlt_property_set_string( mlt_property this, const char *value )
185 {
186 if ( value != this->prop_string )
187 {
188 mlt_property_clear( this );
189 this->types = mlt_prop_string;
190 if ( value != NULL )
191 this->prop_string = strdup( value );
192 }
193 else
194 {
195 this->types = mlt_prop_string;
196 }
197 return this->prop_string == NULL;
198 }
199
200 /** Set the property to a 64-bit integer value.
201 *
202 * \public \memberof mlt_property_s
203 * \param this a property
204 * \param value a 64-bit integer
205 * \return false
206 */
207
208 int mlt_property_set_int64( mlt_property this, int64_t value )
209 {
210 mlt_property_clear( this );
211 this->types = mlt_prop_int64;
212 this->prop_int64 = value;
213 return 0;
214 }
215
216 /** Set a property to an opaque binary value.
217 *
218 * This does not make a copy of the data. You can use a Properties object
219 * with its reference tracking and the destructor function to control
220 * the lifetime of the data. Otherwise, pass NULL for the destructor
221 * function and control the lifetime yourself.
222 * \public \memberof mlt_property_s
223 * \param this a property
224 * \param value an opaque pointer
225 * \param length the number of bytes pointed to by value (optional)
226 * \param destructor a function to use to destroy this binary data (optional, assuming you manage the resource)
227 * \param serialiser a function to use to convert this binary data to a string (optional)
228 * \return false
229 */
230
231 int mlt_property_set_data( mlt_property this, void *value, int length, mlt_destructor destructor, mlt_serialiser serialiser )
232 {
233 if ( this->data == value )
234 this->destructor = NULL;
235 mlt_property_clear( this );
236 this->types = mlt_prop_data;
237 this->data = value;
238 this->length = length;
239 this->destructor = destructor;
240 this->serialiser = serialiser;
241 return 0;
242 }
243
244 /** Convert a base 10 or base 16 string to an integer.
245 *
246 * The string must begin with '0x' to be interpreted as hexadecimal.
247 * Otherwise, it is interpreted as base 10.
248 * \private \memberof mlt_property_s
249 * \param value a string to convert
250 * \return the resultant integer
251 */
252 static inline int mlt_property_atoi( const char *value )
253 {
254 if ( value == NULL )
255 return 0;
256 else if ( value[0] == '0' && value[1] == 'x' )
257 return strtol( value + 2, NULL, 16 );
258 else
259 return strtol( value, NULL, 10 );
260 }
261
262 /** Get the property as an integer.
263 *
264 * \public \memberof mlt_property_s
265 * \param this a property
266 * \return an integer value
267 */
268
269 int mlt_property_get_int( mlt_property this )
270 {
271 if ( this->types & mlt_prop_int )
272 return this->prop_int;
273 else if ( this->types & mlt_prop_double )
274 return ( int )this->prop_double;
275 else if ( this->types & mlt_prop_position )
276 return ( int )this->prop_position;
277 else if ( this->types & mlt_prop_int64 )
278 return ( int )this->prop_int64;
279 else if ( this->types & mlt_prop_string )
280 return mlt_property_atoi( this->prop_string );
281 return 0;
282 }
283
284 /** Get the property as a floating point.
285 *
286 * \public \memberof mlt_property_s
287 * \param this a property
288 * \return a floating point value
289 */
290
291 double mlt_property_get_double( mlt_property this )
292 {
293 if ( this->types & mlt_prop_double )
294 return this->prop_double;
295 else if ( this->types & mlt_prop_int )
296 return ( double )this->prop_int;
297 else if ( this->types & mlt_prop_position )
298 return ( double )this->prop_position;
299 else if ( this->types & mlt_prop_int64 )
300 return ( double )this->prop_int64;
301 else if ( this->types & mlt_prop_string )
302 return atof( this->prop_string );
303 return 0;
304 }
305
306 /** Get the property as a position.
307 *
308 * A position is an offset time in terms of frame units.
309 * \public \memberof mlt_property_s
310 * \param this a property
311 * \return the position in frames
312 */
313
314 mlt_position mlt_property_get_position( mlt_property this )
315 {
316 if ( this->types & mlt_prop_position )
317 return this->prop_position;
318 else if ( this->types & mlt_prop_int )
319 return ( mlt_position )this->prop_int;
320 else if ( this->types & mlt_prop_double )
321 return ( mlt_position )this->prop_double;
322 else if ( this->types & mlt_prop_int64 )
323 return ( mlt_position )this->prop_int64;
324 else if ( this->types & mlt_prop_string )
325 return ( mlt_position )atol( this->prop_string );
326 return 0;
327 }
328
329 /** Convert a string to a 64-bit integer.
330 *
331 * If the string begins with '0x' it is interpreted as a hexadecimal value.
332 * \private \memberof mlt_property_s
333 * \param value a string
334 * \return a 64-bit integer
335 */
336
337 static inline int64_t mlt_property_atoll( const char *value )
338 {
339 if ( value == NULL )
340 return 0;
341 else if ( value[0] == '0' && value[1] == 'x' )
342 return strtoll( value + 2, NULL, 16 );
343 else
344 return strtoll( value, NULL, 10 );
345 }
346
347 /** Get the property as a signed integer.
348 *
349 * \public \memberof mlt_property_s
350 * \param this a property
351 * \return a 64-bit integer
352 */
353
354 int64_t mlt_property_get_int64( mlt_property this )
355 {
356 if ( this->types & mlt_prop_int64 )
357 return this->prop_int64;
358 else if ( this->types & mlt_prop_int )
359 return ( int64_t )this->prop_int;
360 else if ( this->types & mlt_prop_double )
361 return ( int64_t )this->prop_double;
362 else if ( this->types & mlt_prop_position )
363 return ( int64_t )this->prop_position;
364 else if ( this->types & mlt_prop_string )
365 return mlt_property_atoll( this->prop_string );
366 return 0;
367 }
368
369 /** Get the property as a string.
370 *
371 * The caller is not responsible for deallocating the returned string!
372 * The string is deallocated when the Property is closed.
373 * This tries its hardest to convert the property to string including using
374 * a serialization function for binary data, if supplied.
375 * \public \memberof mlt_property_s
376 * \param this a property
377 * \return a string representation of the property or NULL if failed
378 */
379
380 char *mlt_property_get_string( mlt_property this )
381 {
382 // Construct a string if need be
383 if ( ! ( this->types & mlt_prop_string ) )
384 {
385 if ( this->types & mlt_prop_int )
386 {
387 this->types |= mlt_prop_string;
388 this->prop_string = malloc( 32 );
389 sprintf( this->prop_string, "%d", this->prop_int );
390 }
391 else if ( this->types & mlt_prop_double )
392 {
393 this->types |= mlt_prop_string;
394 this->prop_string = malloc( 32 );
395 sprintf( this->prop_string, "%f", this->prop_double );
396 }
397 else if ( this->types & mlt_prop_position )
398 {
399 this->types |= mlt_prop_string;
400 this->prop_string = malloc( 32 );
401 sprintf( this->prop_string, "%d", (int)this->prop_position ); /* I don't know if this is wanted. -Zach */
402 }
403 else if ( this->types & mlt_prop_int64 )
404 {
405 this->types |= mlt_prop_string;
406 this->prop_string = malloc( 32 );
407 sprintf( this->prop_string, "%lld", this->prop_int64 );
408 }
409 else if ( this->types & mlt_prop_data && this->serialiser != NULL )
410 {
411 this->types |= mlt_prop_string;
412 this->prop_string = this->serialiser( this->data, this->length );
413 }
414 }
415
416 // Return the string (may be NULL)
417 return this->prop_string;
418 }
419
420 /** Get the binary data from a property.
421 *
422 * This only works if you previously put binary data into the property.
423 * This does not return a copy of the data; it returns a pointer to it.
424 * If you supplied a destructor function when setting the binary data,
425 * the destructor is used when the Property is closed to free the memory.
426 * Therefore, only free the returned pointer if you did not supply a
427 * destructor function.
428 * \public \memberof mlt_property_s
429 * \param this a property
430 * \param[out] length the size of the binary object in bytes
431 * \return an opaque data pointer or NULL if not available
432 */
433
434 void *mlt_property_get_data( mlt_property this, int *length )
435 {
436 // Assign length if not NULL
437 if ( length != NULL )
438 *length = this->length;
439
440 // Return the data (note: there is no conversion here)
441 return this->data;
442 }
443
444 /** Destroy a property and free all related resources.
445 *
446 * \public \memberof mlt_property_s
447 * \param this a property
448 */
449
450 void mlt_property_close( mlt_property this )
451 {
452 mlt_property_clear( this );
453 free( this );
454 }
455
456 /** Copy a property.
457 *
458 * A Property holding binary data only copies the data if a serialiser
459 * function was supplied when you set the Property.
460 * \public \memberof mlt_property_s
461 * \author Zach <zachary.drew@gmail.com>
462 * \param this a property
463 * \param that another property
464 */
465 void mlt_property_pass( mlt_property this, mlt_property that )
466 {
467 mlt_property_clear( this );
468
469 this->types = that->types;
470
471 if ( this->types & mlt_prop_int64 )
472 this->prop_int64 = that->prop_int64;
473 else if ( this->types & mlt_prop_int )
474 this->prop_int = that->prop_int;
475 else if ( this->types & mlt_prop_double )
476 this->prop_double = that->prop_double;
477 else if ( this->types & mlt_prop_position )
478 this->prop_position = that->prop_position;
479 else if ( this->types & mlt_prop_string )
480 {
481 if ( that->prop_string != NULL )
482 this->prop_string = strdup( that->prop_string );
483 }
484 else if ( this->types & mlt_prop_data && this->serialiser != NULL )
485 {
486 this->types = mlt_prop_string;
487 this->prop_string = this->serialiser( this->data, this->length );
488 }
489 }