]> git.sesse.net Git - casparcg/blob - core/producer/binding.h
Merge branch '2.1.0' of https://github.com/CasparCG/Server into 2.1.0
[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
32 #include <boost/lexical_cast.hpp>
33 #include <boost/foreach.hpp>
34
35 namespace caspar { namespace core {
36
37 namespace detail {
38
39 struct impl_base : std::enable_shared_from_this<impl_base>
40 {
41         std::vector<std::shared_ptr<impl_base>> dependencies_;
42         mutable std::vector<std::pair<
43                         std::weak_ptr<void>,
44                         std::function<void ()>>> on_change_;
45
46         virtual ~impl_base()
47         {
48         }
49
50         virtual void evaluate() = 0;
51
52         void depend_on(const std::shared_ptr<impl_base>& dependency)
53         {
54                 auto self = shared_from_this();
55
56                 if (dependency->depends_on(self))
57                         throw std::exception("Can't have circular dependencies between bindings");
58
59                 dependency->on_change(self, [=] { evaluate(); });
60                 dependencies_.push_back(dependency);
61         }
62
63         bool depends_on(const std::shared_ptr<impl_base>& other) const
64         {
65                 BOOST_FOREACH(auto& dependency, dependencies_)
66                 {
67                         if (dependency == other)
68                                 return true;
69                         
70                         if (dependency->depends_on(other))
71                                 return true;            
72                 }
73
74                 return false;
75         }
76
77         void on_change(
78                         const std::weak_ptr<void>& dependant,
79                         const std::function<void ()>& listener) const
80         {
81                 on_change_.push_back(std::make_pair(dependant, listener));
82         }
83 };
84
85 }
86
87 template <typename T>
88 class binding
89 {
90 private:
91
92         struct impl : public detail::impl_base
93         {
94                 T value_;
95                 std::function<T ()> expression_;
96
97                 impl()
98                         : value_()
99                 {
100                 }
101
102                 impl(T value)
103                         : value_(value)
104                 {
105                 }
106
107                 template<typename Expr>
108                 impl(const Expr& expression)
109                         : expression_(expression)
110                 {
111                 }
112
113                 T get() const
114                 {
115                         return value_;
116                 }
117
118                 bool bound() const
119                 {
120                         return static_cast<bool>(expression_);
121                 }
122
123                 void set(T value)
124                 {
125                         if (bound())
126                         {
127                                 throw std::exception("Bound value cannot be set");
128                         }
129
130                         if (value == value_)
131                                 return;
132
133                         value_ = value;
134
135                         on_change();
136                 }
137
138                 void evaluate() override
139                 {
140                         if (expression_)
141                         {
142                                 auto new_value = expression_();
143
144                                 if (new_value != value_)
145                                 {
146                                         value_ = new_value;
147                                         on_change();
148                                 }
149                         }
150                 }
151
152                 using impl_base::on_change;
153                 void on_change()
154                 {
155                         auto copy = on_change_;
156
157                         for (int i = static_cast<int>(copy.size()) - 1; i >= 0; --i)
158                         {
159                                 auto strong = copy[i].first.lock();
160
161                                 if (strong)
162                                         copy[i].second();
163                                 else
164                                         on_change_.erase(on_change_.begin() + i);
165                         }
166                 }
167
168                 void bind(const std::shared_ptr<impl>& other)
169                 {
170                         unbind();
171                         depend_on(other);
172                         expression_ = [other]{ return other->get(); };
173                         evaluate();
174                 }
175
176                 void unbind()
177                 {
178                         if (expression_)
179                         {
180                                 expression_ = std::function<T ()>();
181                                 dependencies_.clear();
182                         }
183                 }
184         };
185
186         template<typename> friend class binding;
187
188         std::shared_ptr<impl> impl_;
189 public:
190         binding()
191                 : impl_(new impl)
192         {
193         }
194
195         explicit binding(T value)
196                 : impl_(new impl(value))
197         {
198         }
199
200         // Expr -> T ()
201         template<typename Expr>
202         explicit binding(const Expr& expression)
203                 : impl_(new impl(expression))
204         {
205                 impl_->evaluate();
206         }
207
208         // Expr -> T ()
209         template<typename Expr, typename T2>
210         binding(const Expr& expression, const binding<T2>& dep)
211                 : impl_(new impl(expression))
212         {
213                 depend_on(dep);
214                 impl_->evaluate();
215         }
216
217         // Expr -> T ()
218         template<typename Expr, typename T2, typename T3>
219         binding(
220                         const Expr& expression,
221                         const binding<T2>& dep1,
222                         const binding<T3>& dep2)
223                 : impl_(new impl(expression))
224         {
225                 depend_on(dep1);
226                 depend_on(dep2);
227                 impl_->evaluate();
228         }
229
230         void* identity() const
231         {
232                 return impl_.get();
233         }
234
235         T get() const
236         {
237                 return impl_->get();
238         }
239
240         void set(T value)
241         {
242                 impl_->set(value);
243         }
244
245         void bind(const binding<T>& other)
246         {
247                 impl_->bind(other.impl_);
248         }
249
250         bool bound() const
251         {
252                 return impl_->bound();
253         }
254
255         template<typename T2>
256         void depend_on(const binding<T2>& other)
257         {
258                 impl_->depend_on(other.impl_);
259         }
260
261         binding<T> operator+(T other) const
262         {
263                 return transformed([other](T self) { return self + other; });
264         }
265
266         binding<T> operator+(const binding<T>& other) const
267         {
268                 return composed(other, [](T self, T o) { return self + o; });
269         }
270
271         binding<T>& operator++()
272         {
273                 T new_value = get();
274                 ++new_value;
275
276                 set(new_value);
277
278                 return *this;
279         }
280
281         binding<T> operator++(int)
282         {
283                 binding<T> pre_val(get());
284                 ++*this;
285
286                 return pre_val;
287         }
288
289         binding<T> operator-() const
290         {
291                 return transformed([](T self) { return -self; });
292         }
293
294         binding<T> operator-(const binding<T>& other) const
295         {
296                 return *this + -other;
297         }
298
299         binding<T> operator-(T other) const
300         {
301                 return *this + -other;
302         }
303
304         binding<T>& operator--()
305         {
306                 T new_value = get();
307                 --new_value;
308
309                 set(new_value);
310
311                 return *this;
312         }
313
314         binding<T> operator--(int)
315         {
316                 binding<T> pre_val(get());
317                 --*this;
318
319                 return pre_val;
320         }
321
322         binding<T> operator*(T other) const
323         {
324                 return transformed([other](T self) { return self * other; });
325         }
326
327         binding<T> operator*(const binding<T>& other) const
328         {
329                 return composed(other, [](T self, T o) { return self * o; });
330         }
331
332         binding<T> operator/(T other) const
333         {
334                 return transformed([other](T self) { return self / other; });
335         }
336
337         binding<T> operator/(const binding<T>& other) const
338         {
339                 return composed(other, [](T self, T o) { return self / o; });
340         }
341
342         binding<T> operator%(T other) const
343         {
344                 return transformed([other](T self) { return self % other; });
345         }
346
347         binding<T> operator%(const binding<T>& other) const
348         {
349                 return composed(other, [](T self, T o) { return self % o; });
350         }
351
352         binding<bool> operator==(T other) const
353         {
354                 return transformed([other](T self) { return self == other; });
355         }
356
357         binding<bool> operator==(const binding<T>& other) const
358         {
359                 return composed(other, [](T self, T o) { return self == o; });
360         }
361
362         binding<bool> operator!=(T other) const
363         {
364                 return transformed([other](T self) { return self != other; });
365         }
366
367         binding<bool> operator!=(const binding<T>& other) const
368         {
369                 return composed(other, [](T self, T o) { return self != o; });
370         }
371
372         binding<bool> operator<(T other) const
373         {
374                 return transformed([other](T self) { return self < other; });
375         }
376
377         binding<bool> operator<(const binding<T>& other) const
378         {
379                 return composed(other, [](T self, T o) { return self < o; });
380         }
381
382         binding<bool> operator>(T other) const
383         {
384                 return transformed([other](T self) { return self > other; });
385         }
386
387         binding<bool> operator>(const binding<T>& other) const
388         {
389                 return composed(other, [](T self, T o) { return self > o; });
390         }
391
392         binding<bool> operator<=(T other) const
393         {
394                 return transformed([other](T self) { return self <= other; });
395         }
396
397         binding<bool> operator<=(const binding<T>& other) const
398         {
399                 return composed(other, [](T self, T o) { return self <= o; });
400         }
401
402         binding<bool> operator>=(T other) const
403         {
404                 return transformed([other](T self) { return self >= other; });
405         }
406
407         binding<bool> operator>=(const binding<T>& other) const
408         {
409                 return composed(other, [](T self, T o) { return self >= o; });
410         }
411
412         template<typename T2>
413         typename std::enable_if<
414                         std::is_same<T, T2>::value,
415                         binding<T2>
416                 >::type as() const
417         {
418                 return *this;
419         }
420
421         template<typename T2>
422         typename std::enable_if<
423                         (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,
424                         binding<T2>
425                 >::type as() const
426         {
427                 return transformed([](T val) { return static_cast<T2>(val); });
428         }
429
430         template<typename T2>
431         typename std::enable_if<
432                         (std::is_same<std::wstring, T>::value || std::is_same<std::wstring, T2>::value) && !std::is_same<T, T2>::value,
433                         binding<T2>
434                 >::type as() const
435         {
436                 return transformed([](T val) { return boost::lexical_cast<T2>(val); });
437         }
438
439         // Func -> R (T self_val)
440         // Returns binding<R>
441         template<typename Func>
442         auto transformed(const Func& func) const -> binding<decltype(func(impl_->value_))>
443         {
444                 typedef decltype(func(impl_->value_)) R;
445                 auto self = impl_;
446
447                 return binding<R>(
448                                 [self, func] { return func(self->get()); },
449                                 *this);
450         }
451
452         // Func -> R (T self_val, T2 other_val)
453         // Returns binding<R>
454         template<typename Func, typename T2>
455         auto composed(const binding<T2> other, const Func& func) const -> binding<decltype(func(impl_->value_, other.impl_->value_))>
456         {
457                 typedef decltype(func(impl_->value_, other.impl_->value_)) R;
458                 auto self = impl_;
459                 auto o = other.impl_;
460
461                 return binding<R>(
462                                 [self, o, func] { return func(self->get(), o->get()); },
463                                 *this,
464                                 other);
465         }
466
467         void unbind()
468         {
469                 impl_->unbind();
470         }
471
472         void on_change(
473                         const std::weak_ptr<void> dependant,
474                         const std::function<void ()>& listener) const
475         {
476                 impl_->on_change(dependant, listener);
477         }
478
479         std::shared_ptr<void> on_change(
480                         const std::function<void ()>& listener) const
481         {
482                 std::shared_ptr<void> subscription(new char);
483
484                 on_change(subscription, listener);
485                 
486                 return subscription;
487         }
488 private:
489         binding(const std::shared_ptr<impl>& self)
490                 : impl_(self)
491         {
492         }
493 };
494
495 static binding<bool> operator||(const binding<bool>& lhs, const binding<bool>& rhs)
496 {
497         return lhs.composed(rhs, [](bool lhs, bool rhs) { return lhs || rhs; });
498 }
499
500 static binding<bool> operator||(const binding<bool>& lhs, bool rhs)
501 {
502         return lhs.transformed([rhs](bool lhs) { return lhs || rhs; });
503 }
504
505 static binding<bool> operator&&(const binding<bool>& lhs, const binding<bool>& rhs)
506 {
507         return lhs.composed(rhs, [](bool lhs, bool rhs) { return lhs && rhs; });
508 }
509
510 static binding<bool> operator&&(const binding<bool>& lhs, bool rhs)
511 {
512         return lhs.transformed([rhs](bool lhs) { return lhs && rhs; });
513 }
514
515 static binding<bool> operator!(const binding<bool>& self)
516 {
517         return self.transformed([](bool self) { return !self; });
518 }
519
520 template<typename T>
521 class ternary_builder
522 {
523         binding<bool> condition_;
524         binding<T> true_result_;
525 public:
526         ternary_builder(
527                         const binding<bool>& condition, const binding<T>& true_result)
528                 : condition_(condition)
529                 , true_result_(true_result)
530         {
531         }
532
533         binding<T> otherwise(const binding<T>& false_result)
534         {
535                 auto condition = condition_;
536                 auto true_result = true_result_;
537
538                 binding<T> result([condition, true_result, false_result]()
539                 {
540                         return condition.get() ? true_result.get() : false_result.get();                
541                 });
542
543                 result.depend_on(condition);
544                 result.depend_on(true_result);
545                 result.depend_on(false_result);
546
547                 return result;
548         }
549
550         binding<T> otherwise(T false_result)
551         {
552                 return otherwise(binding<T>(false_result));
553         }
554 };
555
556 class when
557 {
558         binding<bool> condition_;
559 public:
560         when(const binding<bool>& condition)
561                 : condition_(condition)
562         {
563         }
564
565         template<typename T>
566         ternary_builder<T> then(const binding<T>& true_result)
567         {
568                 return ternary_builder<T>(condition_, true_result);
569         }
570
571         template<typename T>
572         ternary_builder<T> then(T true_result)
573         {
574                 return then(binding<T>(true_result));
575         }
576 };
577
578 template<typename T, typename T2>
579 binding<T> add_tween(
580                 const binding<T>& to_tween,
581                 const binding<T2>& counter,
582                 T destination_value,
583                 T2 duration,
584                 const std::wstring& easing)
585 {
586         tweener tween(easing);
587         
588         double start_val = to_tween.as<double>().get();
589         double destination_val = static_cast<double>(destination_value);
590         double start_time = counter.as<double>().get();
591         double dur = static_cast<double>(duration);
592
593         return when(counter < duration)
594                 .then(counter.as<double>().transformed([=](double t)
595                 {
596                         return tween(t - start_time, start_val, destination_val, dur);
597                 }).as<T>())
598                 .otherwise(destination_value);
599 }
600
601 template<typename T, typename T2>
602 binding<T> delay(
603                 const binding<T>& to_delay,
604                 const binding<T>& after_delay,
605                 const binding<T2>& counter,
606                 T2 duration)
607 {
608         return when(counter < duration)
609                         .then(to_delay)
610                         .otherwise(after_delay);
611 }
612
613 }}