]> git.sesse.net Git - mlt/blob - src/tests/test_properties/test_properties.cpp
Make animation length optional.
[mlt] / src / tests / test_properties / test_properties.cpp
1 /*
2  * Copyright (C) 2013 Dan Dennedy <dan@dennedy.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with consumer library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <QString>
20 #include <QtTest>
21
22 #include <mlt++/Mlt.h>
23 using namespace Mlt;
24
25 extern "C" {
26 #define __DARWIN__
27 #include <framework/mlt_property.h>
28 #include <framework/mlt_animation.h>
29 }
30 #include <cfloat>
31
32 class TestProperties: public QObject
33 {
34     Q_OBJECT
35     locale_t locale;
36
37 public:
38     TestProperties() {
39 #if defined(__linux__) || defined(__DARWIN__)
40         locale = newlocale( LC_NUMERIC_MASK, "POSIX", NULL );
41 #endif
42     }
43
44 private Q_SLOTS:
45     void InstantiationIsAReference()
46     {
47         Properties p;
48         QCOMPARE(p.ref_count(), 1);
49     }
50
51     void CopyAddsReference()
52     {
53         Properties p;
54         Properties q = p;
55         QCOMPARE(p.ref_count(), 2);
56     }
57
58     void DestructionRemovesReference()
59     {
60         Properties p;
61         Properties* q = new Properties(p);
62         QCOMPARE(p.ref_count(), 2);
63         delete q;
64         QCOMPARE(p.ref_count(), 1);
65     }
66
67     void SetAndGetString()
68     {
69         Properties p;
70         p.set("key", "value");
71         QVERIFY(p.get("key"));
72         QVERIFY(QString(p.get("key")) != QString(""));
73         QCOMPARE(p.get("key"), "value");
74     }
75
76     void SetAndGetInt()
77     {
78         Properties p;
79         int i = 1;
80         p.set("key", i);
81         QCOMPARE(p.get_int("key"), i);
82     }
83
84     void SetAndGetDouble()
85     {
86         Properties p;
87         double d = 1.0;
88         p.set("key", d);
89         QCOMPARE(p.get_double("key"), d);
90     }
91
92     void SetAndGetInt64()
93     {
94         Properties p;
95         int64_t i = 1LL << 32;
96         p.set("key", i);
97         QCOMPARE(p.get_int64("key"), i);
98     }
99
100     void SetAndGetData()
101     {
102         Properties p;
103         const char *value = "value";
104         char* const s = strdup(value);
105         p.set("key", s, strlen(s), free);
106         int size = 0;
107         QCOMPARE((char*) p.get_data("key", size), value);
108         QCOMPARE(size, int(strlen(value)));
109     }
110
111     void IntFromString()
112     {
113         Properties p;
114         const char *s = "-1";
115         int i = -1;
116         p.set("key", i);
117         QCOMPARE(p.get("key"), s);
118         p.set("key", s);
119         QCOMPARE(p.get_int("key"), i);
120     }
121
122     void Int64FromString()
123     {
124         Properties p;
125         const char *s = "-1";
126         int64_t i = -1;
127         p.set("key", i);
128         QCOMPARE(p.get("key"), s);
129         p.set("key", s);
130         QCOMPARE(p.get_int64("key"), i);
131     }
132
133     void DoubleFromString()
134     {
135         Properties p;
136         const char *s = "-1.23456";
137         double d = -1.23456;
138         p.set("key", d);
139         QCOMPARE(p.get("key"), s);
140         p.set("key", s);
141         QCOMPARE(p.get_double("key"), d);
142     }
143
144     void SetNullRemovesProperty()
145     {
146         Properties p;
147         const char *s = NULL;
148         p.set("key", "value");
149         p.set("key", s);
150         QCOMPARE(p.get("key"), s);
151     }
152
153     void SetAndGetHexColor()
154     {
155         Properties p;
156         const char *hexColorString = "0xaabbccdd";
157         int hexColorInt = 0xaabbccdd;
158         p.set("key", hexColorString);
159         QCOMPARE(p.get_int("key"), hexColorInt);
160     }
161
162     void SetAndGetCssColor()
163     {
164         Properties p;
165         const char *cssColorString = "#aabbcc";
166         int cssColorInt = 0xaabbccff;
167         p.set("key", cssColorString);
168         QCOMPARE(p.get_int("key"), cssColorInt);
169
170         const char *cssColorAlphaString = "#00aabbcc";
171         int cssColorAlphaInt = 0xaabbcc00;
172         p.set("key", cssColorAlphaString);
173         QCOMPARE(p.get_int("key"), cssColorAlphaInt);
174     }
175
176     void SetAndGetTimeCode()
177     {
178         Profile profile;
179         Properties p;
180         p.set("_profile", profile.get_profile(), 0);
181         const char *timeString = "11:22:33:04";
182         p.set("key", timeString);
183         QCOMPARE(p.get_int("key"), 1023829);
184         p.set("key", 1023829);
185         QCOMPARE(p.get_time("key", mlt_time_smpte), timeString);
186     }
187
188     void SetAndGetTimeClock()
189     {
190         Profile profile;
191         Properties p;
192         p.set("_profile", profile.get_profile(), 0);
193         const char *timeString = "11:22:33.400";
194         p.set("key", timeString);
195         QCOMPARE(p.get_int("key"), 1023835);
196         p.set("key", 1023835);
197         QCOMPARE(p.get_time("key", mlt_time_clock), timeString);
198     }
199
200     void SetSimpleMathExpression()
201     {
202         Properties p;
203         p.set("key", "@16.0/9.0 *2 +3 -1");
204         QCOMPARE(p.get_int("key"), 5);
205         QCOMPARE(p.get_double("key"), 16.0/9.0 *2 +3 -1);
206     }
207
208     void PassOneProperty()
209     {
210         Properties p[2];
211         const char *s = "value";
212         p[0].set("key", s);
213         QCOMPARE(p[1].get("key"), (void*) 0);
214         p[1].pass_property(p[0], "key");
215         QCOMPARE(p[1].get("key"), s);
216     }
217
218     void PassMultipleByPrefix()
219     {
220         Properties p[2];
221         const char *s = "value";
222         p[0].set("key.one", s);
223         p[0].set("key.two", s);
224         QCOMPARE(p[1].get("key.one"), (void*) 0);
225         QCOMPARE(p[1].get("key.two"), (void*) 0);
226         p[1].pass_values(p[0], "key.");
227         QCOMPARE(p[1].get("one"), s);
228         QCOMPARE(p[1].get("two"), s);
229     }
230
231     void PassMultipleByList()
232     {
233         Properties p[2];
234         const char *s = "value";
235         p[0].set("key.one", s);
236         p[0].set("key.two", s);
237         QCOMPARE(p[1].get("key.one"), (void*) 0);
238         QCOMPARE(p[1].get("key.two"), (void*) 0);
239         p[1].pass_list(p[0], "key.one key.two");
240         QCOMPARE(p[1].get("key.one"), s);
241         QCOMPARE(p[1].get("key.two"), s);
242     }
243
244     void MirrorProperties()
245     {
246         Properties p[2];
247         p[0].mirror(p[1]);
248         p[0].set("key", "value");
249         QCOMPARE(p[1].get("key"), "value");
250     }
251
252     void InheritProperties()
253     {
254         Properties p[2];
255         p[0].set("key", "value");
256         QVERIFY(p[1].get("key") == 0);
257         p[1].inherit(p[0]);
258         QCOMPARE(p[1].get("key"), "value");
259     }
260
261     void ParseString()
262     {
263         Properties p;
264         QCOMPARE(p.get("key"), (void*) 0);
265         p.parse("key=value");
266         QCOMPARE(p.get("key"), "value");
267         p.parse("key=\"new value\"");
268         QCOMPARE(p.get("key"), "new value");
269     }
270
271     void RenameProperty()
272     {
273         Properties p;
274         p.set("key", "value");
275         QVERIFY(p.get("new key") == 0);
276         p.rename("key", "new key");
277         QCOMPARE(p.get("new key"), "value");
278     }
279
280     void SequenceDetected()
281     {
282         Properties p;
283         p.set("1", 1);
284         p.set("2", 2);
285         p.set("3", 3);
286         QVERIFY(p.is_sequence());
287         p.set("four", 4);
288         QVERIFY(!p.is_sequence());
289     }
290
291     void SerializesToYamlTiny()
292     {
293         Properties p[2];
294         p[0].set("key1", "value1");
295         p[0].set("key2", "value2");
296         p[1].set("1", "value3");
297         p[1].set("2", "value4");
298         p[0].set("seq", p[1].get_properties(), 0);
299         QCOMPARE(p[0].serialise_yaml(),
300                 "---\n"
301                 "key1: value1\n"
302                 "key2: value2\n"
303                 "seq:\n"
304                 "  - value3\n"
305                 "  - value4\n"
306                 "...\n");
307     }
308
309     void RadixRespondsToLocale()
310     {
311         Properties p;
312         p.set_lcnumeric("en_US");
313         p.set("key", "0.125");
314         QCOMPARE(p.get_double("key"), double(1) / double(8));
315         p.set_lcnumeric("de_DE");
316         p.set("key", "0,125");
317         QCOMPARE(p.get_double("key"), double(1) / double(8));
318     }
319
320     void DoubleAnimation()
321     {
322         double fps = 25.0;
323         mlt_animation a = mlt_animation_new();
324         struct mlt_animation_item_s item;
325
326         mlt_animation_parse(a, "50=1; 60=60; 100=0", 100, fps, locale);
327         mlt_animation_remove(a, 60);
328         char *a_serialized = mlt_animation_serialize(a);
329         QCOMPARE(a_serialized, "50=1;100=0");
330         if (a_serialized) free(a_serialized);
331         item.property = mlt_property_init();
332
333         mlt_animation_get_item(a, &item, 10);
334         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 1.0);
335         QCOMPARE(item.is_key, 0);
336
337         mlt_animation_get_item(a, &item, 50);
338         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 1.0);
339         QCOMPARE(item.is_key, 1);
340
341         mlt_animation_get_item(a, &item, 75);
342         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.5);
343         QCOMPARE(item.is_key, 0);
344
345         mlt_animation_get_item(a, &item, 100);
346         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.0);
347         QCOMPARE(item.is_key, 1);
348
349         mlt_animation_get_item(a, &item, 110);
350         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.0);
351         QCOMPARE(item.is_key, 0);
352
353         mlt_property_close(item.property);
354         mlt_animation_close(a);
355     }
356
357     void IntAnimation()
358     {
359         double fps = 25.0;
360         mlt_animation a = mlt_animation_new();
361         struct mlt_animation_item_s item;
362
363         mlt_animation_parse(a, "50=100; 60=60; 100=0", 100, fps, locale);
364         mlt_animation_remove(a, 60);
365         char *a_serialized = mlt_animation_serialize(a);
366         QCOMPARE(a_serialized, "50=100;100=0");
367         if (a_serialized) free(a_serialized);
368         item.property = mlt_property_init();
369
370         mlt_animation_get_item(a, &item, 10);
371         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
372         QCOMPARE(item.is_key, 0);
373
374         mlt_animation_get_item(a, &item, 50);
375         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
376         QCOMPARE(item.is_key, 1);
377
378         mlt_animation_get_item(a, &item, 75);
379         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 50);
380         QCOMPARE(item.is_key, 0);
381
382         mlt_animation_get_item(a, &item, 100);
383         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
384         QCOMPARE(item.is_key, 1);
385
386         mlt_animation_get_item(a, &item, 110);
387         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
388         QCOMPARE(item.is_key, 0);
389
390         mlt_property_close(item.property);
391         mlt_animation_close(a);
392     }
393
394     void AnimationWithTimeValueKeyframes()
395     {
396         double fps = 25.0;
397         mlt_animation a = mlt_animation_new();
398         struct mlt_animation_item_s item;
399
400         mlt_animation_parse(a, ":2.0=1; :4.0=0", 100, fps, locale);
401         char *a_serialized = mlt_animation_serialize(a);
402         // Time serializes to frame units :-\.
403         QCOMPARE(a_serialized, "50=1;100=0");
404         if (a_serialized) free(a_serialized);
405         item.property = mlt_property_init();
406
407         mlt_animation_get_item(a, &item, 10);
408         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 1.0);
409         QCOMPARE(item.is_key, 0);
410
411         mlt_animation_get_item(a, &item, 50);
412         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 1.0);
413         QCOMPARE(item.is_key, 1);
414
415         mlt_animation_get_item(a, &item, 75);
416         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.5);
417         QCOMPARE(item.is_key, 0);
418
419         mlt_animation_get_item(a, &item, 100);
420         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.0);
421         QCOMPARE(item.is_key, 1);
422
423         mlt_animation_get_item(a, &item, 110);
424         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.0);
425         QCOMPARE(item.is_key, 0);
426
427         mlt_property_close(item.property);
428         mlt_animation_close(a);
429     }
430
431     void DiscreteIntAnimation()
432     {
433         double fps = 25.0;
434         mlt_animation a = mlt_animation_new();
435         struct mlt_animation_item_s item;
436
437         mlt_animation_parse(a, "50|=100; 60|=60; 100|=0", 100, fps, locale);
438         char *a_serialized = mlt_animation_serialize(a);
439         QCOMPARE(a_serialized, "50|=100;60|=60;100|=0");
440         if (a_serialized) free(a_serialized);
441         item.property = mlt_property_init();
442
443         mlt_animation_get_item(a, &item, 10);
444         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
445         QCOMPARE(item.is_key, 0);
446
447         mlt_animation_get_item(a, &item, 50);
448         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
449         QCOMPARE(item.is_key, 1);
450
451         mlt_animation_get_item(a, &item, 55);
452         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
453         QCOMPARE(item.is_key, 0);
454
455         mlt_animation_get_item(a, &item, 60);
456         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 60);
457         QCOMPARE(item.is_key, 1);
458
459         mlt_animation_get_item(a, &item, 75);
460         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 60);
461         QCOMPARE(item.is_key, 0);
462
463         mlt_animation_get_item(a, &item, 100);
464         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
465         QCOMPARE(item.is_key, 1);
466
467         mlt_animation_get_item(a, &item, 110);
468         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
469         QCOMPARE(item.is_key, 0);
470
471         mlt_property_close(item.property);
472         mlt_animation_close(a);
473     }
474
475     void StringAnimation()
476     {
477         double fps = 25.0;
478         mlt_animation a = mlt_animation_new();
479         struct mlt_animation_item_s item;
480
481         mlt_animation_parse(a, "50=hello world; 60=\"good night\"; 100=bar", 100, fps, locale);
482         char *a_serialized = mlt_animation_serialize(a);
483         QCOMPARE(a_serialized, "50=hello world;60=\"good night\";100=bar");
484         if (a_serialized) free(a_serialized);
485         item.property = mlt_property_init();
486
487         mlt_animation_get_item(a, &item, 10);
488         QCOMPARE(mlt_property_get_string(item.property), "hello world");
489         QCOMPARE(item.is_key, 0);
490
491         mlt_animation_get_item(a, &item, 50);
492         QCOMPARE(mlt_property_get_string(item.property), "hello world");
493         QCOMPARE(item.is_key, 1);
494
495         mlt_animation_get_item(a, &item, 75);
496         QCOMPARE(mlt_property_get_string(item.property), "\"good night\"");
497         QCOMPARE(item.is_key, 0);
498
499         mlt_animation_get_item(a, &item, 100);
500         QCOMPARE(mlt_property_get_string(item.property), "bar");
501         QCOMPARE(item.is_key, 1);
502
503         mlt_animation_get_item(a, &item, 110);
504         QCOMPARE(mlt_property_get_string(item.property), "bar");
505         QCOMPARE(item.is_key, 0);
506
507         mlt_property_close(item.property);
508         mlt_animation_close(a);
509     }
510
511     void test_property_anim_get_double()
512     {
513         double fps = 25.0;
514         int len = 0;
515         mlt_property p = mlt_property_init();
516         mlt_property_set_string(p, "10=100; 20=200");
517         QCOMPARE(mlt_property_get_double(p, fps, locale), 10.0);
518         QCOMPARE(mlt_property_anim_get_double(p, fps, locale,  0, len), 100.0);
519         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 15, len), 150.0);
520         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 20, len), 200.0);
521
522         mlt_property_set_string(p, "1.5");
523         QCOMPARE(mlt_property_get_double(p, fps, locale), 1.5);
524         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 10, 100), 1.5);
525
526         mlt_property_close(p);
527     }
528
529     void test_property_anim_get_int()
530     {
531         double fps = 25.0;
532         int len = 100;
533         mlt_property p = mlt_property_init();
534         mlt_property_set_string(p, "10=100; 20=200");
535         QCOMPARE(mlt_property_get_int(p, fps, locale), 10);
536         QCOMPARE(mlt_property_anim_get_int(p, fps, locale,  0, len), 100);
537         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 15, len), 150);
538         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 20, len), 200);
539
540         mlt_property_set_string(p, "1.5");
541         QCOMPARE(mlt_property_get_int(p, fps, locale), 1);
542         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 10, 100), 1);
543
544         mlt_property_close(p);
545     }
546
547     void SmoothIntAnimation()
548     {
549         double fps = 25.0;
550         mlt_animation a = mlt_animation_new();
551         struct mlt_animation_item_s item;
552
553         mlt_animation_parse(a, "0=80;10~=80; 20~=30; 30~=40; 40~=28; 50=90; 60=0; 70=60; 80=20", 100, fps, locale);
554         item.property = mlt_property_init();
555         char *a_serialized = mlt_animation_serialize(a);
556         QCOMPARE(a_serialized, "0=80;10~=80;20~=30;30~=40;40~=28;50=90;60=0;70=60;80=20");
557         if (a_serialized) free(a_serialized);
558
559         mlt_animation_get_item(a, &item, 10);
560         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 80);
561         QCOMPARE(item.is_key, 1);
562
563         mlt_animation_get_item(a, &item, 50);
564         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 90);
565         QCOMPARE(item.is_key, 1);
566
567         mlt_animation_get_item(a, &item, 55);
568         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 45);
569         QCOMPARE(item.is_key, 0);
570
571         mlt_animation_get_item(a, &item, 60);
572         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
573         QCOMPARE(item.is_key, 1);
574
575         mlt_animation_get_item(a, &item, 75);
576         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 40);
577         QCOMPARE(item.is_key, 0);
578
579         mlt_animation_get_item(a, &item, 100);
580         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 20);
581         QCOMPARE(item.is_key, 0);
582
583         mlt_animation_get_item(a, &item, 110);
584         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 20);
585         QCOMPARE(item.is_key, 0);
586
587         mlt_property_close(item.property);
588         mlt_animation_close(a);
589     }
590
591     void test_property_anim_set_double()
592     {
593         double fps = 25.0;
594         int len = 100;
595         mlt_property p = mlt_property_init();
596         mlt_property_set_string(p, "10=100; 20=200");
597         mlt_property_anim_set_double(p, 1.5, fps, locale, mlt_keyframe_linear, 30, len);
598         QCOMPARE(mlt_property_get_double(p, fps, locale), 10.0);
599         QCOMPARE(mlt_property_anim_get_double(p, fps, locale,  0, len), 100.0);
600         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 15, len), 150.0);
601         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 20, len), 200.0);
602         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 25, len), 100.75);
603         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 30, len), 1.5);
604         mlt_property_close(p);
605     }
606
607     void test_property_anim_set_int()
608     {
609         double fps = 25.0;
610         int len = 0;
611         mlt_property p = mlt_property_init();
612         mlt_property_set_string(p, "10=100; 20=200");
613         mlt_property_anim_set_int(p, 300, fps, locale, mlt_keyframe_linear, 30, len);
614         QCOMPARE(mlt_property_get_int(p, fps, locale), 10);
615         QCOMPARE(mlt_property_anim_get_int(p, fps, locale,  0, len), 100);
616         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 15, len), 150);
617         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 20, len), 200);
618         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 25, len), 250);
619         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 30, len), 300);
620         mlt_property_close(p);
621     }
622
623     void PercentAsRatio()
624     {
625         Properties p;
626         p.set("foo", "12.3%");
627         QCOMPARE(p.get_double("foo"), 0.123);
628         p.set("foo", "456 %");
629         QCOMPARE(p.get_double("foo"), 456.0);
630     }
631
632     void PropertiesAnimInt()
633     {
634         Properties p;
635         p.set_lcnumeric("POSIX");
636
637         // Construct animation from scratch
638         p.anim_set("foo",   0,  0);
639         p.anim_set("foo", 100, 50, -1, mlt_keyframe_smooth);
640         QCOMPARE(p.anim_get_int("foo",  0), 0);
641         QCOMPARE(p.anim_get_int("foo", 25), 50);
642         QCOMPARE(p.anim_get_int("foo", 50), 100);
643         QCOMPARE(p.get("foo"), "0=0;50~=100");
644
645         // Animation from string value
646         p.set("foo", "10=100;20=200");
647         QCOMPARE(p.anim_get_int("foo",  0), 100);
648         QCOMPARE(p.anim_get_int("foo", 15), 150);
649         QCOMPARE(p.anim_get_int("foo", 20), 200);
650
651         // Animation from string using time clock values
652         // Need to set a profile so fps can be used to convert time to frames.
653         Profile profile("dv_pal");
654         p.set("_profile", profile.get_profile(), 0);
655         p.set("foo", ":0.0=100; :2.0=200");
656         QCOMPARE(p.anim_get_int("foo",  0), 100);
657         QCOMPARE(p.anim_get_int("foo", 25), 150);
658         QCOMPARE(p.anim_get_int("foo", 50), 200);
659     }
660
661     void PropertiesAnimDouble()
662     {
663         Properties p;
664         p.set_lcnumeric("POSIX");
665
666         // Construct animation from scratch
667         p.anim_set("foo",   0.0,  0);
668         p.anim_set("foo", 100.0, 50, -1, mlt_keyframe_smooth);
669         QCOMPARE(p.anim_get_double("foo",  0), 0.0);
670         QCOMPARE(p.anim_get_double("foo", 25), 50.0);
671         QCOMPARE(p.anim_get_double("foo", 50), 100.0);
672         QCOMPARE(p.get("foo"), "0=0;50~=100");
673
674         // Animation from string value
675         p.set("foo", "10=100.2;20=200.8");
676         QCOMPARE(p.anim_get_double("foo",  0), 100.2);
677         QCOMPARE(p.anim_get_double("foo", 15), 150.5);
678         QCOMPARE(p.anim_get_double("foo", 20), 200.8);
679
680         // Animation from string using time clock values
681         // Need to set a profile so fps can be used to convert time to frames.
682         Profile profile("dv_pal");
683         p.set("_profile", profile.get_profile(), 0);
684         p.set("foo", ":0.0=100; :2.0=200");
685         QCOMPARE(p.anim_get_double("foo",  0), 100.0);
686         QCOMPARE(p.anim_get_double("foo", 25), 150.0);
687         QCOMPARE(p.anim_get_double("foo", 50), 200.0);
688     }
689
690     void PropertiesStringAnimation()
691     {
692         Properties p;
693         p.anim_set("key", "foo", 10);
694         p.anim_set("key", "bar", 30);
695         QCOMPARE(p.get("key"), "10|=foo;30|=bar");
696         p.set("key", "0=; 10=foo bar; 30=hello world");
697         QCOMPARE(p.anim_get("key",  1), "");
698         QCOMPARE(p.anim_get("key", 15), "foo bar");
699         QCOMPARE(p.anim_get("key", 45), "hello world");
700     }
701
702     void test_mlt_rect()
703     {
704         mlt_property p = mlt_property_init();
705         mlt_rect r = { 1, 2, 3, 4, 5 };
706
707         mlt_property_set_rect( p, r );
708         QCOMPARE(mlt_property_get_string(p), "1 2 3 4 5");
709         r.o = DBL_MIN;
710         mlt_property_set_rect( p, r );
711         QCOMPARE(mlt_property_get_string(p), "1 2 3 4");
712         r.w = DBL_MIN;
713         r.h = DBL_MIN;
714         mlt_property_set_rect( p, r );
715         QCOMPARE(mlt_property_get_string(p), "1 2");
716
717         mlt_property_set_string(p, "1.1/2.2:3.3x4.4:5.5");
718         r = mlt_property_get_rect(p, locale);
719         QCOMPARE(r.x, 1.1);
720         QCOMPARE(r.y, 2.2);
721         QCOMPARE(r.w, 3.3);
722         QCOMPARE(r.h, 4.4);
723         QCOMPARE(r.o, 5.5);
724
725         mlt_property_set_string(p, "1.1 2.2");
726         r = mlt_property_get_rect(p, locale);
727         QCOMPARE(r.x, 1.1);
728         QCOMPARE(r.y, 2.2);
729         QCOMPARE(r.w, DBL_MIN);
730
731         mlt_property_set_int64(p, UINT_MAX);
732         r = mlt_property_get_rect(p, locale);
733         QCOMPARE(r.x, double(UINT_MAX));
734
735         mlt_property_close(p);
736     }
737
738     void SetAndGetRect()
739     {
740         Properties p;
741         mlt_rect r;
742         r.x = 1.1;
743         r.y = 2.2;
744         r.w = 3.3;
745         r.h = 4.4;
746         r.o = 5.5;
747         p.set("key", r);
748         mlt_rect q = p.get_rect("key");
749         QCOMPARE(q.x, 1.1);
750         QCOMPARE(q.y, 2.2);
751         QCOMPARE(q.w, 3.3);
752         QCOMPARE(q.h, 4.4);
753         QCOMPARE(q.o, 5.5);
754         p.set("key", 10, 20, 30, 40);
755         q = p.get_rect("key");
756         QCOMPARE(q.x, 10.0);
757         QCOMPARE(q.y, 20.0);
758         QCOMPARE(q.w, 30.0);
759         QCOMPARE(q.h, 40.0);
760     }
761
762     void RectFromString()
763     {
764         Properties p;
765         p.set_lcnumeric("POSIX");
766         const char *s = "1.1 2.2 3.3 4.4 5.5";
767         mlt_rect r = { 1.1, 2.2, 3.3, 4.4, 5.5 };
768         p.set("key", r);
769         QCOMPARE(p.get("key"), s);
770         p.set("key", s);
771         r = p.get_rect("key");
772         QCOMPARE(r.x, 1.1);
773         QCOMPARE(r.y, 2.2);
774         QCOMPARE(r.w, 3.3);
775         QCOMPARE(r.h, 4.4);
776         QCOMPARE(r.o, 5.5);
777     }
778
779     void RectAnimation()
780     {
781         mlt_rect r1 = { 0, 0, 200, 200, 0 };
782         mlt_rect r2 = { 100, 100, 400, 400, 1.0 };
783         Properties p;
784         p.set_lcnumeric("POSIX");
785
786         // Construct animation from scratch
787         p.anim_set("key", r1,  0);
788         p.anim_set("key", r2, 50);
789         QCOMPARE(p.anim_get_rect("key",  0).x, 0.0);
790         QCOMPARE(p.anim_get_rect("key", 25).x, 50.0);
791         QCOMPARE(p.anim_get_rect("key", 25).y, 50.0);
792         QCOMPARE(p.anim_get_rect("key", 25).w, 300.0);
793         QCOMPARE(p.anim_get_rect("key", 25).h, 300.0);
794         QCOMPARE(p.anim_get_rect("key", 25).o, 0.5);
795         QCOMPARE(p.anim_get_rect("key", 50).x, 100.0);
796         QCOMPARE(p.get("key"), "0=0 0 200 200 0;50=100 100 400 400 1");
797
798         // Animation from string value
799         QCOMPARE(p.anim_get_rect("key",  0).x, 0.0);
800         QCOMPARE(p.anim_get_rect("key",  0).y, 0.0);
801         QCOMPARE(p.anim_get_rect("key",  0).w, 200.0);
802         QCOMPARE(p.anim_get_rect("key",  0).h, 200.0);
803         QCOMPARE(p.anim_get_rect("key",  0).o, 0.0);
804         QCOMPARE(p.anim_get_rect("key", 50).x, 100.0);
805         QCOMPARE(p.anim_get_rect("key", 50).y, 100.0);
806         QCOMPARE(p.anim_get_rect("key", 50).w, 400.0);
807         QCOMPARE(p.anim_get_rect("key", 50).h, 400.0);
808         QCOMPARE(p.anim_get_rect("key", 50).o, 1.0);
809         QCOMPARE(p.anim_get_rect("key", 15).x, 30.0);
810         QCOMPARE(p.anim_get_rect("key", 15).y, 30.0);
811         QCOMPARE(p.anim_get_rect("key", 15).w, 260.0);
812         QCOMPARE(p.anim_get_rect("key", 15).h, 260.0);
813         QCOMPARE(p.anim_get_rect("key", 15).o, 0.3);
814
815         // Smooth animation
816         p.set("key", "0~=0/0:200x200:0; 50=100/100:400x400:1");
817         QCOMPARE(p.anim_get_rect("key",  0).x, 0.0);
818         QCOMPARE(p.anim_get_rect("key",  0).y, 0.0);
819         QCOMPARE(p.anim_get_rect("key",  0).w, 200.0);
820         QCOMPARE(p.anim_get_rect("key",  0).h, 200.0);
821         QCOMPARE(p.anim_get_rect("key",  0).o, 0.0);
822         QCOMPARE(p.anim_get_rect("key", 50).x, 100.0);
823         QCOMPARE(p.anim_get_rect("key", 50).y, 100.0);
824         QCOMPARE(p.anim_get_rect("key", 50).w, 400.0);
825         QCOMPARE(p.anim_get_rect("key", 50).h, 400.0);
826         QCOMPARE(p.anim_get_rect("key", 50).o, 1.0);
827         QCOMPARE(p.anim_get_rect("key", 15).x, 25.8);
828         QCOMPARE(p.anim_get_rect("key", 15).y, 25.8);
829         QCOMPARE(p.anim_get_rect("key", 15).w, 251.6);
830         QCOMPARE(p.anim_get_rect("key", 15).h, 251.6);
831         QCOMPARE(p.anim_get_rect("key", 15).o, 0.258);
832
833         // Using percentages
834         p.set("key", "0=0 0; 50=100% 200%");
835         QCOMPARE(p.anim_get_rect("key", 25).x, 0.5);
836         QCOMPARE(p.anim_get_rect("key", 25).y, 1.0);
837     }
838
839     void ColorFromInt()
840     {
841         Properties p;
842         p.set_lcnumeric("POSIX");
843         p.set("key", (int) 0xaabbccdd);
844         mlt_color color = p.get_color("key");
845         QCOMPARE(color.r, quint8(0xaa));
846         QCOMPARE(color.g, quint8(0xbb));
847         QCOMPARE(color.b, quint8(0xcc));
848         QCOMPARE(color.a, quint8(0xdd));
849         p.set("key", *((int*) &color));
850         QCOMPARE(p.get_int("key"), int(0xddccbbaa));
851     }
852
853     void ColorFromString()
854     {
855         Properties p;
856         p.set_lcnumeric("POSIX");
857         p.set("key", "red");
858         mlt_color color = p.get_color("key");
859         QCOMPARE(color.r, quint8(0xff));
860         QCOMPARE(color.g, quint8(0x00));
861         QCOMPARE(color.b, quint8(0x00));
862         QCOMPARE(color.a, quint8(0xff));
863         p.set("key", "#deadd00d");
864         color = p.get_color("key");
865         QCOMPARE(color.r, quint8(0xad));
866         QCOMPARE(color.g, quint8(0xd0));
867         QCOMPARE(color.b, quint8(0x0d));
868         QCOMPARE(color.a, quint8(0xde));
869     }
870
871     void SetIntAndGetAnim()
872     {
873         Properties p;
874         p.set_lcnumeric("POSIX");
875         p.set("key", 123);
876         QCOMPARE(p.anim_get_int("key", 10, 50), 123);
877         p.set("key", "123");
878         QCOMPARE(p.anim_get_int("key", 10, 50), 123);
879     }
880
881     void SetDoubleAndGetAnim()
882     {
883         Properties p;
884         p.set_lcnumeric("POSIX");
885         p.set("key", 123.0);
886         QCOMPARE(p.anim_get_double("key", 10, 50), 123.0);
887         p.set("key", "123");
888         QCOMPARE(p.anim_get_double("key", 10, 50), 123.0);
889     }
890
891     void AnimNegativeTimevalue()
892     {
893         Properties p;
894         Profile profile("dv_pal");
895         p.set("_profile", profile.get_profile(), 0);
896         p.set_lcnumeric("POSIX");
897         p.set("key", "0=100; -1=200");
898         QCOMPARE(p.anim_get_int("key", 75, 100), 175);
899         p.set("key", "0=100; -1:=200");
900         QCOMPARE(p.anim_get_int("key", 75, 125), 175);
901     }
902 };
903
904 QTEST_APPLESS_MAIN(TestProperties)
905
906 #include "test_properties.moc"