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