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