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