]> git.sesse.net Git - casparcg/blob - core/producer/binding.h
[version.tmpl] Changed tag to Beta 1
[casparcg] / core / producer / binding.h
1 /*
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
3 *
4 * This file is part of CasparCG (www.casparcg.com).
5 *
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * Author: Helge Norberg, helge.norberg@svt.se
20 */
21
22 #pragma once
23
24 #include <functional>
25 #include <memory>
26 #include <vector>
27 #include <string>
28 #include <map>
29 #include <algorithm>
30 #include <type_traits>
31 #include <stdexcept>
32
33 #include <boost/lexical_cast.hpp>
34
35 #include <common/tweener.h>
36 #include <common/except.h>
37
38 namespace caspar { namespace core {
39
40 namespace detail {
41
42 struct impl_base : std::enable_shared_from_this<impl_base>
43 {
44         std::vector<std::shared_ptr<impl_base>> dependencies_;
45         mutable std::vector<std::pair<
46                         std::weak_ptr<void>,
47                         std::function<void ()>>> on_change_;
48
49         virtual ~impl_base()
50         {
51         }
52
53         virtual void evaluate() const = 0;
54
55         void depend_on(const std::shared_ptr<impl_base>& dependency)
56         {
57                 auto self = shared_from_this();
58
59                 if (dependency->depends_on(self))
60                         CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("Can't have circular dependencies between bindings"));
61
62                 dependency->on_change(self, [=] { evaluate(); });
63                 dependencies_.push_back(dependency);
64         }
65
66         bool depends_on(const std::shared_ptr<impl_base>& other) const
67         {
68                 for (auto& dependency : dependencies_)
69                 {
70                         if (dependency == other)
71                                 return true;
72                         
73                         if (dependency->depends_on(other))
74                                 return true;            
75                 }
76
77                 return false;
78         }
79
80         void on_change(
81                         const std::weak_ptr<void>& dependant,
82                         const std::function<void ()>& listener) const
83         {
84                 on_change_.push_back(std::make_pair(dependant, listener));
85         }
86 };
87
88 }
89
90 template <typename T>
91 class binding
92 {
93 private:
94
95         struct impl : public detail::impl_base
96         {
97                 mutable T                       value_;
98                 std::function<T ()> expression_;
99                 mutable bool            evaluated_              = false;
100
101                 impl()
102                         : value_()
103                 {
104                 }
105
106                 impl(T value)
107                         : value_(value)
108                 {
109                 }
110
111                 template<typename Expr>
112                 impl(const Expr& expression)
113                         : expression_(expression)
114                 {
115                 }
116
117                 T get() const
118                 {
119                         if (!evaluated_)
120                                 evaluate();
121
122                         return value_;
123                 }
124
125                 bool bound() const
126                 {
127                         return static_cast<bool>(expression_);
128                 }
129
130                 void set(T value)
131                 {
132                         if (bound())
133                                 CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Bound value cannot be set"));
134
135                         if (value == value_)
136                                 return;
137
138                         value_ = value;
139
140                         on_change();
141                 }
142
143                 void evaluate() const override
144                 {
145                         if (expression_)
146                         {
147                                 auto new_value = expression_();
148
149                                 if (new_value != value_)
150                                 {
151                                         value_ = new_value;
152                                         on_change();
153                                 }
154                         }
155
156                         evaluated_ = true;
157                 }
158
159                 using impl_base::on_change;
160                 void on_change() const
161                 {
162                         auto copy = on_change_;
163
164                         for (int i = static_cast<int>(copy.size()) - 1; i >= 0; --i)
165                         {
166                                 auto strong = copy[i].first.lock();
167
168                                 if (strong)
169                                         copy[i].second();
170                                 else
171                                         on_change_.erase(on_change_.begin() + i);
172                         }
173                 }
174
175                 void bind(const std::shared_ptr<impl>& other)
176                 {
177                         unbind();
178                         depend_on(other);
179                         expression_ = [other]{ return other->get(); };
180                         //evaluate();
181                 }
182
183                 void unbind()
184                 {
185                         if (expression_)
186                         {
187                                 expression_ = std::function<T ()>();
188                                 dependencies_.clear();
189                         }
190                 }
191         };
192
193         template<typename> friend class binding;
194
195         std::shared_ptr<impl> impl_;
196 public:
197         binding()
198                 : impl_(new impl)
199         {
200         }
201
202         explicit binding(T value)
203                 : impl_(new impl(value))
204         {
205         }
206
207         // Expr -> T ()
208         template<typename Expr>
209         explicit binding(const Expr& expression)
210                 : impl_(new impl(expression))
211         {
212                 //impl_->evaluate();
213         }
214
215         // Expr -> T ()
216         template<typename Expr, typename T2>
217         binding(const Expr& expression, const binding<T2>& dep)
218                 : impl_(new impl(expression))
219         {
220                 depend_on(dep);
221                 //impl_->evaluate();
222         }
223
224         // Expr -> T ()
225         template<typename Expr, typename T2, typename T3>
226         binding(
227                         const Expr& expression,
228                         const binding<T2>& dep1,
229                         const binding<T3>& dep2)
230                 : impl_(new impl(expression))
231         {
232                 depend_on(dep1);
233                 depend_on(dep2);
234                 //impl_->evaluate();
235         }
236
237         void* identity() const
238         {
239                 return impl_.get();
240         }
241
242         T get() const
243         {
244                 return impl_->get();
245         }
246
247         void set(T value)
248         {
249                 impl_->set(value);
250         }
251
252         void bind(const binding<T>& other)
253         {
254                 impl_->bind(other.impl_);
255         }
256
257         bool bound() const
258         {
259                 return impl_->bound();
260         }
261
262         template<typename T2>
263         void depend_on(const binding<T2>& other)
264         {
265                 impl_->depend_on(other.impl_);
266         }
267
268         binding<T> operator+(T other) const
269         {
270                 return transformed([other](T self) { return self + other; });
271         }
272
273         binding<T> operator+(const binding<T>& other) const
274         {
275                 return composed(other, [](T self, T o) { return self + o; });
276         }
277
278         binding<T>& operator++()
279         {
280                 T new_value = get();
281                 ++new_value;
282
283                 set(new_value);
284
285                 return *this;
286         }
287
288         binding<T> operator++(int)
289         {
290                 binding<T> pre_val(get());
291                 ++*this;
292
293                 return pre_val;
294         }
295
296         binding<T> operator-() const
297         {
298                 return transformed([](T self) { return -self; });
299         }
300
301         binding<T> operator-(const binding<T>& other) const
302         {
303                 return *this + -other;
304         }
305
306         binding<T> operator-(T other) const
307         {
308                 return *this + -other;
309         }
310
311         binding<T>& operator--()
312         {
313                 T new_value = get();
314                 --new_value;
315
316                 set(new_value);
317
318                 return *this;
319         }
320
321         binding<T> operator--(int)
322         {
323                 binding<T> pre_val(get());
324                 --*this;
325
326                 return pre_val;
327         }
328
329         binding<T> operator*(T other) const
330         {
331                 return transformed([other](T self) { return self * other; });
332         }
333
334         binding<T> operator*(const binding<T>& other) const
335         {
336                 return composed(other, [](T self, T o) { return self * o; });
337         }
338
339         binding<T> operator/(T other) const
340         {
341                 return transformed([other](T self) { return self / other; });
342         }
343
344         binding<T> operator/(const binding<T>& other) const
345         {
346                 return composed(other, [](T self, T o) { return self / o; });
347         }
348
349         binding<T> operator%(T other) const
350         {
351                 return transformed([other](T self) { return self % other; });
352         }
353
354         binding<T> operator%(const binding<T>& other) const
355         {
356                 return composed(other, [](T self, T o) { return self % o; });
357         }
358
359         binding<bool> operator==(T other) const
360         {
361                 return transformed([other](T self) { return self == other; });
362         }
363
364         binding<bool> operator==(const binding<T>& other) const
365         {
366                 return composed(other, [](T self, T o) { return self == o; });
367         }
368
369         binding<bool> operator!=(T other) const
370         {
371                 return transformed([other](T self) { return self != other; });
372         }
373
374         binding<bool> operator!=(const binding<T>& other) const
375         {
376                 return composed(other, [](T self, T o) { return self != o; });
377         }
378
379         binding<bool> operator<(T other) const
380         {
381                 return transformed([other](T self) { return self < other; });
382         }
383
384         binding<bool> operator<(const binding<T>& other) const
385         {
386                 return composed(other, [](T self, T o) { return self < o; });
387         }
388
389         binding<bool> operator>(T other) const
390         {
391                 return transformed([other](T self) { return self > other; });
392         }
393
394         binding<bool> operator>(const binding<T>& other) const
395         {
396                 return composed(other, [](T self, T o) { return self > o; });
397         }
398
399         binding<bool> operator<=(T other) const
400         {
401                 return transformed([other](T self) { return self <= other; });
402         }
403
404         binding<bool> operator<=(const binding<T>& other) const
405         {
406                 return composed(other, [](T self, T o) { return self <= o; });
407         }
408
409         binding<bool> operator>=(T other) const
410         {
411                 return transformed([other](T self) { return self >= other; });
412         }
413
414         binding<bool> operator>=(const binding<T>& other) const
415         {
416                 return composed(other, [](T self, T o) { return self >= o; });
417         }
418
419         template<typename T2>
420         typename std::enable_if<
421                         std::is_same<T, T2>::value,
422                         binding<T2>
423                 >::type as() const
424         {
425                 return *this;
426         }
427
428         template<typename T2>
429         typename std::enable_if<
430                         (std::is_arithmetic<T>::value || std::is_same<bool, T>::value) && (std::is_arithmetic<T2>::value || std::is_same<bool, T2>::value) && !std::is_same<T, T2>::value,
431                         binding<T2>
432                 >::type as() const
433         {
434                 return transformed([](T val) { return static_cast<T2>(val); });
435         }
436
437         template<typename T2>
438         typename std::enable_if<
439                         (std::is_same<std::wstring, T>::value || std::is_same<std::wstring, T2>::value) && !std::is_same<T, T2>::value,
440                         binding<T2>
441                 >::type as() const
442         {
443                 return transformed([](T val) { return boost::lexical_cast<T2>(val); });
444         }
445
446         // Func -> R (T self_val)
447         // Returns binding<R>
448         template<typename Func>
449         auto transformed(const Func& func) const -> binding<decltype(func(impl_->value_))>
450         {
451                 typedef decltype(func(impl_->value_)) R;
452                 auto self = impl_;
453
454                 return binding<R>(
455                                 [self, func] { return func(self->get()); },
456                                 *this);
457         }
458
459         // Func -> R (T self_val, T2 other_val)
460         // Returns binding<R>
461         template<typename Func, typename T2>
462         auto composed(const binding<T2>& other, const Func& func) const -> binding<decltype(func(impl_->value_, other.impl_->value_))>
463         {
464                 typedef decltype(func(impl_->value_, other.impl_->value_)) R;
465                 auto self = impl_;
466                 auto o = other.impl_;
467
468                 return binding<R>(
469                                 [self, o, func] { return func(self->get(), o->get()); },
470                                 *this,
471                                 other);
472         }
473
474         template<typename TweenerFunc, typename FrameCounter>
475         binding<T> animated(
476                         const binding<FrameCounter>& frame_counter,
477                         const binding<FrameCounter>& duration,
478                         const binding<TweenerFunc>& tweener_func) const
479         {
480                 auto self                                       = impl_;
481                 auto f                                          = frame_counter.impl_;
482                 auto d                                          = duration.impl_;
483                 auto tw                                         = tweener_func.impl_;
484                 FrameCounter start_frame        = frame_counter.get();
485                 FrameCounter current_frame      = start_frame;
486                 T current_source                        = get();
487                 T current_destination           = current_source;
488                 T current_result                        = current_source;
489
490                 auto result = binding<T>(
491                         [=] () mutable
492                         {
493                                 auto frame_diff         = f->get() - current_frame;
494                                 bool new_frame          = f->get() != current_frame;
495
496                                 if (!new_frame)
497                                         return current_result;
498
499                                 bool new_tween          = current_destination != self->get();
500                                 auto time                       = current_frame - start_frame + (new_tween ? frame_diff : 0) + 1;
501                                 auto dur                        = d->get();
502                                 current_frame           = f->get();
503
504                                 current_source          = new_tween ? tw->get()(time, current_source, current_destination - current_source, dur) : current_source;
505                                 current_destination     = self->get();
506
507                                 if (new_tween)
508                                         start_frame             = current_frame;
509
510                                 time                            = current_frame - start_frame;
511
512                                 if (time < dur)
513                                         current_result = tw->get()(time, current_source, current_destination - current_source, dur);
514                                 else
515                                 {
516                                         current_result = current_destination;
517                                         current_source = current_destination;
518                                 }
519
520                                 return current_result;
521                         });
522
523                 result.depend_on(*this);
524                 result.depend_on(frame_counter);
525                 result.depend_on(tweener_func);
526
527                 return result;
528         }
529
530         void unbind()
531         {
532                 impl_->unbind();
533         }
534
535         void on_change(
536                         const std::weak_ptr<void>& dependant,
537                         const std::function<void ()>& listener) const
538         {
539                 impl_->on_change(dependant, listener);
540         }
541
542         std::shared_ptr<void> on_change(
543                         const std::function<void ()>& listener) const
544         {
545                 std::shared_ptr<void> subscription(new char);
546
547                 on_change(subscription, listener);
548                 
549                 return subscription;
550         }
551 private:
552         binding(const std::shared_ptr<impl>& self)
553                 : impl_(self)
554         {
555         }
556 };
557
558 static binding<bool> operator||(const binding<bool>& lhs, const binding<bool>& rhs)
559 {
560         return lhs.composed(rhs, [](bool lhs, bool rhs) { return lhs || rhs; });
561 }
562
563 static binding<bool> operator||(const binding<bool>& lhs, bool rhs)
564 {
565         return lhs.transformed([rhs](bool lhs) { return lhs || rhs; });
566 }
567
568 static binding<bool> operator&&(const binding<bool>& lhs, const binding<bool>& rhs)
569 {
570         return lhs.composed(rhs, [](bool lhs, bool rhs) { return lhs && rhs; });
571 }
572
573 static binding<bool> operator&&(const binding<bool>& lhs, bool rhs)
574 {
575         return lhs.transformed([rhs](bool lhs) { return lhs && rhs; });
576 }
577
578 static binding<bool> operator!(const binding<bool>& self)
579 {
580         return self.transformed([](bool self) { return !self; });
581 }
582
583 template<typename T>
584 class ternary_builder
585 {
586         binding<bool> condition_;
587         binding<T> true_result_;
588 public:
589         ternary_builder(
590                         const binding<bool>& condition, const binding<T>& true_result)
591                 : condition_(condition)
592                 , true_result_(true_result)
593         {
594         }
595
596         binding<T> otherwise(const binding<T>& false_result)
597         {
598                 auto condition = condition_;
599                 auto true_result = true_result_;
600
601                 binding<T> result([condition, true_result, false_result]()
602                 {
603                         return condition.get() ? true_result.get() : false_result.get();                
604                 });
605
606                 result.depend_on(condition);
607                 result.depend_on(true_result);
608                 result.depend_on(false_result);
609
610                 return result;
611         }
612
613         binding<T> otherwise(T false_result)
614         {
615                 return otherwise(binding<T>(false_result));
616         }
617 };
618
619 class when
620 {
621         binding<bool> condition_;
622 public:
623         when(const binding<bool>& condition)
624                 : condition_(condition)
625         {
626         }
627
628         template<typename T>
629         ternary_builder<T> then(const binding<T>& true_result)
630         {
631                 return ternary_builder<T>(condition_, true_result);
632         }
633
634         template<typename T>
635         ternary_builder<T> then(T true_result)
636         {
637                 return then(binding<T>(true_result));
638         }
639 };
640
641 /*template<typename T, typename T2>
642 binding<T> add_tween(
643                 const binding<T>& to_tween,
644                 const binding<T2>& counter,
645                 T destination_value,
646                 T2 duration,
647                 const std::wstring& easing)
648 {
649         tweener tween(easing);
650         
651         double start_val = to_tween.as<double>().get();
652         double destination_val = static_cast<double>(destination_value);
653         double start_time = counter.as<double>().get();
654         double dur = static_cast<double>(duration);
655
656         return when(counter < duration)
657                 .then(counter.as<double>().transformed([=](double t)
658                 {
659                         return tween(t - start_time, start_val, destination_val, dur);
660                 }).as<T>())
661                 .otherwise(destination_value);
662 }*/
663
664 template<typename T, typename T2>
665 binding<T> delay(
666                 const binding<T>& to_delay,
667                 const binding<T>& after_delay,
668                 const binding<T2>& counter,
669                 T2 duration)
670 {
671         return when(counter < duration)
672                         .then(to_delay)
673                         .otherwise(after_delay);
674 }
675
676 }}