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