]> git.sesse.net Git - mlt/blob - src/tests/test_properties/test_properties.cpp
Fix animation serialization when length is not specified
[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 AnimationInsert()
329     {
330         double fps = 25.0;
331         mlt_animation a = mlt_animation_new();
332         struct mlt_animation_item_s item;
333
334         item.is_key = 1;
335         item.keyframe_type = mlt_keyframe_discrete;
336         item.property = mlt_property_init();
337
338         item.frame = 0;
339         mlt_property_set_string(item.property, "0");
340         mlt_animation_insert(a, &item);
341
342         item.frame = 1;
343         mlt_property_set_string(item.property, "1");
344         mlt_animation_insert(a, &item);
345
346         item.frame = 2;
347         mlt_property_set_string(item.property, "2");
348         mlt_animation_insert(a, &item);
349
350         QCOMPARE(mlt_animation_get_length(a), 2);
351
352         char *a_serialized = mlt_animation_serialize(a);
353         mlt_animation_parse(a, a_serialized, 0, fps, locale);
354         QCOMPARE(a_serialized, "0|=0;1|=1;2|=2");
355         if (a_serialized) free(a_serialized);
356
357         mlt_property_close(item.property);
358         mlt_animation_close(a);
359     }
360
361     void DoubleAnimation()
362     {
363         double fps = 25.0;
364         mlt_animation a = mlt_animation_new();
365         struct mlt_animation_item_s item;
366
367         mlt_animation_parse(a, "50=1; 60=60; 100=0", 100, fps, locale);
368         mlt_animation_remove(a, 60);
369         char *a_serialized = mlt_animation_serialize(a);
370         QCOMPARE(a_serialized, "50=1;100=0");
371         if (a_serialized) free(a_serialized);
372         item.property = mlt_property_init();
373
374         mlt_animation_get_item(a, &item, 10);
375         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 1.0);
376         QCOMPARE(item.is_key, 0);
377
378         mlt_animation_get_item(a, &item, 50);
379         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 1.0);
380         QCOMPARE(item.is_key, 1);
381
382         mlt_animation_get_item(a, &item, 75);
383         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.5);
384         QCOMPARE(item.is_key, 0);
385
386         mlt_animation_get_item(a, &item, 100);
387         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.0);
388         QCOMPARE(item.is_key, 1);
389
390         mlt_animation_get_item(a, &item, 110);
391         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.0);
392         QCOMPARE(item.is_key, 0);
393
394         mlt_property_close(item.property);
395         mlt_animation_close(a);
396     }
397
398     void IntAnimation()
399     {
400         double fps = 25.0;
401         mlt_animation a = mlt_animation_new();
402         struct mlt_animation_item_s item;
403
404         mlt_animation_parse(a, "50=100; 60=60; 100=0", 100, fps, locale);
405         mlt_animation_remove(a, 60);
406         char *a_serialized = mlt_animation_serialize(a);
407         QCOMPARE(a_serialized, "50=100;100=0");
408         if (a_serialized) free(a_serialized);
409         item.property = mlt_property_init();
410
411         mlt_animation_get_item(a, &item, 10);
412         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
413         QCOMPARE(item.is_key, 0);
414
415         mlt_animation_get_item(a, &item, 50);
416         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
417         QCOMPARE(item.is_key, 1);
418
419         mlt_animation_get_item(a, &item, 75);
420         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 50);
421         QCOMPARE(item.is_key, 0);
422
423         mlt_animation_get_item(a, &item, 100);
424         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
425         QCOMPARE(item.is_key, 1);
426
427         mlt_animation_get_item(a, &item, 110);
428         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
429         QCOMPARE(item.is_key, 0);
430
431         mlt_property_close(item.property);
432         mlt_animation_close(a);
433     }
434
435     void AnimationWithTimeValueKeyframes()
436     {
437         double fps = 25.0;
438         mlt_animation a = mlt_animation_new();
439         struct mlt_animation_item_s item;
440
441         mlt_animation_parse(a, ":2.0=1; :4.0=0", 100, fps, locale);
442         char *a_serialized = mlt_animation_serialize(a);
443         // Time serializes to frame units :-\.
444         QCOMPARE(a_serialized, "50=1;100=0");
445         if (a_serialized) free(a_serialized);
446         item.property = mlt_property_init();
447
448         mlt_animation_get_item(a, &item, 10);
449         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 1.0);
450         QCOMPARE(item.is_key, 0);
451
452         mlt_animation_get_item(a, &item, 50);
453         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 1.0);
454         QCOMPARE(item.is_key, 1);
455
456         mlt_animation_get_item(a, &item, 75);
457         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.5);
458         QCOMPARE(item.is_key, 0);
459
460         mlt_animation_get_item(a, &item, 100);
461         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.0);
462         QCOMPARE(item.is_key, 1);
463
464         mlt_animation_get_item(a, &item, 110);
465         QCOMPARE(mlt_property_get_double(item.property, fps, locale), 0.0);
466         QCOMPARE(item.is_key, 0);
467
468         mlt_property_close(item.property);
469         mlt_animation_close(a);
470     }
471
472     void DiscreteIntAnimation()
473     {
474         double fps = 25.0;
475         mlt_animation a = mlt_animation_new();
476         struct mlt_animation_item_s item;
477
478         mlt_animation_parse(a, "50|=100; 60|=60; 100|=0", 100, fps, locale);
479         char *a_serialized = mlt_animation_serialize(a);
480         QCOMPARE(a_serialized, "50|=100;60|=60;100|=0");
481         if (a_serialized) free(a_serialized);
482         item.property = mlt_property_init();
483
484         mlt_animation_get_item(a, &item, 10);
485         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
486         QCOMPARE(item.is_key, 0);
487
488         mlt_animation_get_item(a, &item, 50);
489         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
490         QCOMPARE(item.is_key, 1);
491
492         mlt_animation_get_item(a, &item, 55);
493         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 100);
494         QCOMPARE(item.is_key, 0);
495
496         mlt_animation_get_item(a, &item, 60);
497         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 60);
498         QCOMPARE(item.is_key, 1);
499
500         mlt_animation_get_item(a, &item, 75);
501         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 60);
502         QCOMPARE(item.is_key, 0);
503
504         mlt_animation_get_item(a, &item, 100);
505         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
506         QCOMPARE(item.is_key, 1);
507
508         mlt_animation_get_item(a, &item, 110);
509         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
510         QCOMPARE(item.is_key, 0);
511
512         mlt_property_close(item.property);
513         mlt_animation_close(a);
514     }
515
516     void StringAnimation()
517     {
518         double fps = 25.0;
519         mlt_animation a = mlt_animation_new();
520         struct mlt_animation_item_s item;
521
522         mlt_animation_parse(a, "50=hello world; 60=\"good night\"; 100=bar", 100, fps, locale);
523         char *a_serialized = mlt_animation_serialize(a);
524         QCOMPARE(a_serialized, "50=hello world;60=\"good night\";100=bar");
525         if (a_serialized) free(a_serialized);
526         item.property = mlt_property_init();
527
528         mlt_animation_get_item(a, &item, 10);
529         QCOMPARE(mlt_property_get_string(item.property), "hello world");
530         QCOMPARE(item.is_key, 0);
531
532         mlt_animation_get_item(a, &item, 50);
533         QCOMPARE(mlt_property_get_string(item.property), "hello world");
534         QCOMPARE(item.is_key, 1);
535
536         mlt_animation_get_item(a, &item, 75);
537         QCOMPARE(mlt_property_get_string(item.property), "\"good night\"");
538         QCOMPARE(item.is_key, 0);
539
540         mlt_animation_get_item(a, &item, 100);
541         QCOMPARE(mlt_property_get_string(item.property), "bar");
542         QCOMPARE(item.is_key, 1);
543
544         mlt_animation_get_item(a, &item, 110);
545         QCOMPARE(mlt_property_get_string(item.property), "bar");
546         QCOMPARE(item.is_key, 0);
547
548         mlt_property_close(item.property);
549         mlt_animation_close(a);
550     }
551
552     void test_property_anim_get_double()
553     {
554         double fps = 25.0;
555         int len = 0;
556         mlt_property p = mlt_property_init();
557         mlt_property_set_string(p, "10=100; 20=200");
558         QCOMPARE(mlt_property_get_double(p, fps, locale), 10.0);
559         QCOMPARE(mlt_property_anim_get_double(p, fps, locale,  0, len), 100.0);
560         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 15, len), 150.0);
561         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 20, len), 200.0);
562
563         mlt_property_set_string(p, "1.5");
564         QCOMPARE(mlt_property_get_double(p, fps, locale), 1.5);
565         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 10, 100), 1.5);
566
567         mlt_property_close(p);
568     }
569
570     void test_property_anim_get_int()
571     {
572         double fps = 25.0;
573         int len = 100;
574         mlt_property p = mlt_property_init();
575         mlt_property_set_string(p, "10=100; 20=200");
576         QCOMPARE(mlt_property_get_int(p, fps, locale), 10);
577         QCOMPARE(mlt_property_anim_get_int(p, fps, locale,  0, len), 100);
578         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 15, len), 150);
579         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 20, len), 200);
580
581         mlt_property_set_string(p, "1.5");
582         QCOMPARE(mlt_property_get_int(p, fps, locale), 1);
583         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 10, 100), 1);
584
585         mlt_property_close(p);
586     }
587
588     void SmoothIntAnimation()
589     {
590         double fps = 25.0;
591         mlt_animation a = mlt_animation_new();
592         struct mlt_animation_item_s item;
593
594         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);
595         item.property = mlt_property_init();
596         char *a_serialized = mlt_animation_serialize(a);
597         QCOMPARE(a_serialized, "0=80;10~=80;20~=30;30~=40;40~=28;50=90;60=0;70=60;80=20");
598         if (a_serialized) free(a_serialized);
599
600         mlt_animation_get_item(a, &item, 10);
601         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 80);
602         QCOMPARE(item.is_key, 1);
603
604         mlt_animation_get_item(a, &item, 50);
605         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 90);
606         QCOMPARE(item.is_key, 1);
607
608         mlt_animation_get_item(a, &item, 55);
609         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 45);
610         QCOMPARE(item.is_key, 0);
611
612         mlt_animation_get_item(a, &item, 60);
613         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 0);
614         QCOMPARE(item.is_key, 1);
615
616         mlt_animation_get_item(a, &item, 75);
617         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 40);
618         QCOMPARE(item.is_key, 0);
619
620         mlt_animation_get_item(a, &item, 100);
621         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 20);
622         QCOMPARE(item.is_key, 0);
623
624         mlt_animation_get_item(a, &item, 110);
625         QCOMPARE(mlt_property_get_int(item.property, fps, locale), 20);
626         QCOMPARE(item.is_key, 0);
627
628         mlt_property_close(item.property);
629         mlt_animation_close(a);
630     }
631
632     void test_property_anim_set_double()
633     {
634         double fps = 25.0;
635         int len = 100;
636         mlt_property p = mlt_property_init();
637         mlt_property_set_string(p, "10=100; 20=200");
638         mlt_property_anim_set_double(p, 1.5, fps, locale, 30, len, mlt_keyframe_linear);
639         QCOMPARE(mlt_property_get_double(p, fps, locale), 10.0);
640         QCOMPARE(mlt_property_anim_get_double(p, fps, locale,  0, len), 100.0);
641         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 15, len), 150.0);
642         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 20, len), 200.0);
643         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 25, len), 100.75);
644         QCOMPARE(mlt_property_anim_get_double(p, fps, locale, 30, len), 1.5);
645         mlt_property_close(p);
646     }
647
648     void test_property_anim_set_int()
649     {
650         double fps = 25.0;
651         int len = 0;
652         mlt_property p = mlt_property_init();
653         mlt_property_set_string(p, "10=100; 20=200");
654         mlt_property_anim_set_int(p, 300, fps, locale, 30, len, mlt_keyframe_linear);
655         QCOMPARE(mlt_property_get_int(p, fps, locale), 10);
656         QCOMPARE(mlt_property_anim_get_int(p, fps, locale,  0, len), 100);
657         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 15, len), 150);
658         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 20, len), 200);
659         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 25, len), 250);
660         QCOMPARE(mlt_property_anim_get_int(p, fps, locale, 30, len), 300);
661         mlt_property_close(p);
662     }
663
664     void PercentAsRatio()
665     {
666         Properties p;
667         p.set("foo", "12.3%");
668         QCOMPARE(p.get_double("foo"), 0.123);
669         p.set("foo", "456 %");
670         QCOMPARE(p.get_double("foo"), 456.0);
671     }
672
673     void PropertiesAnimInt()
674     {
675         Properties p;
676         p.set_lcnumeric("POSIX");
677
678         // Construct animation from scratch
679         p.anim_set("foo",   0,  0);
680         p.anim_set("foo", 100, 50, -1, mlt_keyframe_smooth);
681         QCOMPARE(p.anim_get_int("foo",  0), 0);
682         QCOMPARE(p.anim_get_int("foo", 25), 50);
683         QCOMPARE(p.anim_get_int("foo", 50), 100);
684         QCOMPARE(p.get("foo"), "0=0;50~=100");
685
686         // Animation from string value
687         p.set("foo", "10=100;20=200");
688         QCOMPARE(p.anim_get_int("foo",  0), 100);
689         QCOMPARE(p.anim_get_int("foo", 15), 150);
690         QCOMPARE(p.anim_get_int("foo", 20), 200);
691
692         // Animation from string using time clock values
693         // Need to set a profile so fps can be used to convert time to frames.
694         Profile profile("dv_pal");
695         p.set("_profile", profile.get_profile(), 0);
696         p.set("foo", ":0.0=100; :2.0=200");
697         QCOMPARE(p.anim_get_int("foo",  0), 100);
698         QCOMPARE(p.anim_get_int("foo", 25), 150);
699         QCOMPARE(p.anim_get_int("foo", 50), 200);
700     }
701
702     void PropertiesAnimDouble()
703     {
704         Properties p;
705         p.set_lcnumeric("POSIX");
706
707         // Construct animation from scratch
708         p.anim_set("foo",   0.0,  0);
709         p.anim_set("foo", 100.0, 50, -1, mlt_keyframe_smooth);
710         QCOMPARE(p.anim_get_double("foo",  0), 0.0);
711         QCOMPARE(p.anim_get_double("foo", 25), 50.0);
712         QCOMPARE(p.anim_get_double("foo", 50), 100.0);
713         QCOMPARE(p.get("foo"), "0=0;50~=100");
714
715         // Animation from string value
716         p.set("foo", "10=100.2;20=200.8");
717         QCOMPARE(p.anim_get_double("foo",  0), 100.2);
718         QCOMPARE(p.anim_get_double("foo", 15), 150.5);
719         QCOMPARE(p.anim_get_double("foo", 20), 200.8);
720
721         // Animation from string using time clock values
722         // Need to set a profile so fps can be used to convert time to frames.
723         Profile profile("dv_pal");
724         p.set("_profile", profile.get_profile(), 0);
725         p.set("foo", ":0.0=100; :2.0=200");
726         QCOMPARE(p.anim_get_double("foo",  0), 100.0);
727         QCOMPARE(p.anim_get_double("foo", 25), 150.0);
728         QCOMPARE(p.anim_get_double("foo", 50), 200.0);
729     }
730
731     void PropertiesStringAnimation()
732     {
733         Properties p;
734         p.anim_set("key", "foo", 10);
735         p.anim_set("key", "bar", 30);
736         QCOMPARE(p.get("key"), "10|=foo;30|=bar");
737         p.set("key", "0=; 10=foo bar; 30=hello world");
738         QCOMPARE(p.anim_get("key",  1), "");
739         QCOMPARE(p.anim_get("key", 15), "foo bar");
740         QCOMPARE(p.anim_get("key", 45), "hello world");
741     }
742
743     void test_mlt_rect()
744     {
745         mlt_property p = mlt_property_init();
746         mlt_rect r = { 1, 2, 3, 4, 5 };
747
748         mlt_property_set_rect( p, r );
749         QCOMPARE(mlt_property_get_string(p), "1 2 3 4 5");
750         r.o = DBL_MIN;
751         mlt_property_set_rect( p, r );
752         QCOMPARE(mlt_property_get_string(p), "1 2 3 4");
753         r.w = DBL_MIN;
754         r.h = DBL_MIN;
755         mlt_property_set_rect( p, r );
756         QCOMPARE(mlt_property_get_string(p), "1 2");
757
758         mlt_property_set_string(p, "1.1/2.2:3.3x4.4:5.5");
759         r = mlt_property_get_rect(p, locale);
760         QCOMPARE(r.x, 1.1);
761         QCOMPARE(r.y, 2.2);
762         QCOMPARE(r.w, 3.3);
763         QCOMPARE(r.h, 4.4);
764         QCOMPARE(r.o, 5.5);
765
766         mlt_property_set_string(p, "1.1 2.2");
767         r = mlt_property_get_rect(p, locale);
768         QCOMPARE(r.x, 1.1);
769         QCOMPARE(r.y, 2.2);
770         QCOMPARE(r.w, DBL_MIN);
771
772         mlt_property_set_int64(p, UINT_MAX);
773         r = mlt_property_get_rect(p, locale);
774         QCOMPARE(r.x, double(UINT_MAX));
775
776         mlt_property_close(p);
777     }
778
779     void SetAndGetRect()
780     {
781         Properties p;
782         mlt_rect r;
783         r.x = 1.1;
784         r.y = 2.2;
785         r.w = 3.3;
786         r.h = 4.4;
787         r.o = 5.5;
788         p.set("key", r);
789         mlt_rect q = p.get_rect("key");
790         QCOMPARE(q.x, 1.1);
791         QCOMPARE(q.y, 2.2);
792         QCOMPARE(q.w, 3.3);
793         QCOMPARE(q.h, 4.4);
794         QCOMPARE(q.o, 5.5);
795         p.set("key", 10, 20, 30, 40);
796         q = p.get_rect("key");
797         QCOMPARE(q.x, 10.0);
798         QCOMPARE(q.y, 20.0);
799         QCOMPARE(q.w, 30.0);
800         QCOMPARE(q.h, 40.0);
801     }
802
803     void RectFromString()
804     {
805         Properties p;
806         p.set_lcnumeric("POSIX");
807         const char *s = "1.1 2.2 3.3 4.4 5.5";
808         mlt_rect r = { 1.1, 2.2, 3.3, 4.4, 5.5 };
809         p.set("key", r);
810         QCOMPARE(p.get("key"), s);
811         p.set("key", s);
812         r = p.get_rect("key");
813         QCOMPARE(r.x, 1.1);
814         QCOMPARE(r.y, 2.2);
815         QCOMPARE(r.w, 3.3);
816         QCOMPARE(r.h, 4.4);
817         QCOMPARE(r.o, 5.5);
818     }
819
820     void RectAnimation()
821     {
822         mlt_rect r1 = { 0, 0, 200, 200, 0 };
823         mlt_rect r2 = { 100, 100, 400, 400, 1.0 };
824         Properties p;
825         p.set_lcnumeric("POSIX");
826
827         // Construct animation from scratch
828         p.anim_set("key", r1,  0);
829         p.anim_set("key", r2, 50);
830         QCOMPARE(p.anim_get_rect("key",  0).x, 0.0);
831         QCOMPARE(p.anim_get_rect("key", 25).x, 50.0);
832         QCOMPARE(p.anim_get_rect("key", 25).y, 50.0);
833         QCOMPARE(p.anim_get_rect("key", 25).w, 300.0);
834         QCOMPARE(p.anim_get_rect("key", 25).h, 300.0);
835         QCOMPARE(p.anim_get_rect("key", 25).o, 0.5);
836         QCOMPARE(p.anim_get_rect("key", 50).x, 100.0);
837         QCOMPARE(p.get("key"), "0=0 0 200 200 0;50=100 100 400 400 1");
838
839         // Animation from string value
840         QCOMPARE(p.anim_get_rect("key",  0).x, 0.0);
841         QCOMPARE(p.anim_get_rect("key",  0).y, 0.0);
842         QCOMPARE(p.anim_get_rect("key",  0).w, 200.0);
843         QCOMPARE(p.anim_get_rect("key",  0).h, 200.0);
844         QCOMPARE(p.anim_get_rect("key",  0).o, 0.0);
845         QCOMPARE(p.anim_get_rect("key", 50).x, 100.0);
846         QCOMPARE(p.anim_get_rect("key", 50).y, 100.0);
847         QCOMPARE(p.anim_get_rect("key", 50).w, 400.0);
848         QCOMPARE(p.anim_get_rect("key", 50).h, 400.0);
849         QCOMPARE(p.anim_get_rect("key", 50).o, 1.0);
850         QCOMPARE(p.anim_get_rect("key", 15).x, 30.0);
851         QCOMPARE(p.anim_get_rect("key", 15).y, 30.0);
852         QCOMPARE(p.anim_get_rect("key", 15).w, 260.0);
853         QCOMPARE(p.anim_get_rect("key", 15).h, 260.0);
854         QCOMPARE(p.anim_get_rect("key", 15).o, 0.3);
855
856         // Smooth animation
857         p.set("key", "0~=0/0:200x200:0; 50=100/100:400x400:1");
858         QCOMPARE(p.anim_get_rect("key",  0).x, 0.0);
859         QCOMPARE(p.anim_get_rect("key",  0).y, 0.0);
860         QCOMPARE(p.anim_get_rect("key",  0).w, 200.0);
861         QCOMPARE(p.anim_get_rect("key",  0).h, 200.0);
862         QCOMPARE(p.anim_get_rect("key",  0).o, 0.0);
863         QCOMPARE(p.anim_get_rect("key", 50).x, 100.0);
864         QCOMPARE(p.anim_get_rect("key", 50).y, 100.0);
865         QCOMPARE(p.anim_get_rect("key", 50).w, 400.0);
866         QCOMPARE(p.anim_get_rect("key", 50).h, 400.0);
867         QCOMPARE(p.anim_get_rect("key", 50).o, 1.0);
868         QCOMPARE(p.anim_get_rect("key", 15).x, 25.8);
869         QCOMPARE(p.anim_get_rect("key", 15).y, 25.8);
870         QCOMPARE(p.anim_get_rect("key", 15).w, 251.6);
871         QCOMPARE(p.anim_get_rect("key", 15).h, 251.6);
872         QCOMPARE(p.anim_get_rect("key", 15).o, 0.258);
873
874         // Using percentages
875         p.set("key", "0=0 0; 50=100% 200%");
876         QCOMPARE(p.anim_get_rect("key", 25).x, 0.5);
877         QCOMPARE(p.anim_get_rect("key", 25).y, 1.0);
878     }
879
880     void ColorFromInt()
881     {
882         Properties p;
883         p.set_lcnumeric("POSIX");
884         p.set("key", (int) 0xaabbccdd);
885         mlt_color color = p.get_color("key");
886         QCOMPARE(color.r, quint8(0xaa));
887         QCOMPARE(color.g, quint8(0xbb));
888         QCOMPARE(color.b, quint8(0xcc));
889         QCOMPARE(color.a, quint8(0xdd));
890         p.set("key", color);
891         QCOMPARE(p.get_int("key"), int(0xaabbccdd));
892     }
893
894     void ColorFromString()
895     {
896         Properties p;
897         p.set_lcnumeric("POSIX");
898         p.set("key", "red");
899         mlt_color color = p.get_color("key");
900         QCOMPARE(color.r, quint8(0xff));
901         QCOMPARE(color.g, quint8(0x00));
902         QCOMPARE(color.b, quint8(0x00));
903         QCOMPARE(color.a, quint8(0xff));
904         p.set("key", "#deadd00d");
905         color = p.get_color("key");
906         QCOMPARE(color.r, quint8(0xad));
907         QCOMPARE(color.g, quint8(0xd0));
908         QCOMPARE(color.b, quint8(0x0d));
909         QCOMPARE(color.a, quint8(0xde));
910     }
911
912     void SetIntAndGetAnim()
913     {
914         Properties p;
915         p.set_lcnumeric("POSIX");
916         p.set("key", 123);
917         QCOMPARE(p.anim_get_int("key", 10, 50), 123);
918         p.set("key", "123");
919         QCOMPARE(p.anim_get_int("key", 10, 50), 123);
920     }
921
922     void SetDoubleAndGetAnim()
923     {
924         Properties p;
925         p.set_lcnumeric("POSIX");
926         p.set("key", 123.0);
927         QCOMPARE(p.anim_get_double("key", 10, 50), 123.0);
928         p.set("key", "123");
929         QCOMPARE(p.anim_get_double("key", 10, 50), 123.0);
930     }
931
932     void AnimNegativeTimevalue()
933     {
934         Properties p;
935         Profile profile("dv_pal");
936         p.set("_profile", profile.get_profile(), 0);
937         p.set_lcnumeric("POSIX");
938         p.set("key", "0=100; -1=200");
939         QCOMPARE(p.anim_get_int("key", 75, 100), 175);
940         p.set("key", "0=100; -1:=200");
941         QCOMPARE(p.anim_get_int("key", 75, 125), 175);
942     }
943 };
944
945 QTEST_APPLESS_MAIN(TestProperties)
946
947 #include "test_properties.moc"
948