]> git.sesse.net Git - casparcg/commitdiff
Allow for a scene_producer to expose parameters updateable via CALL
authorHelge Norberg <helge.norberg@svt.se>
Fri, 9 Aug 2013 13:02:36 +0000 (15:02 +0200)
committerHelge Norberg <helge.norberg@svt.se>
Fri, 9 Aug 2013 13:02:36 +0000 (15:02 +0200)
core/producer/binding.h
core/producer/scene/scene_producer.cpp
core/producer/scene/scene_producer.h
core/producer/text/text_producer.cpp
core/producer/text/text_producer.h
modules/psd/psd_scene_producer.cpp
protocol/amcp/AMCPProtocolStrategy.cpp

index 0e02b18830b066749ae1c2c14a3867eff6890c42..68a502d17276632c866299cd2d8bbfc41cbc7c7e 100644 (file)
@@ -145,7 +145,7 @@ private:
                {
                        unbind();
                        depend_on(other);
-                       expression_ = [&]{ return other.get(); }
+                       expression_ = [other]{ return other->get(); };
                        evaluate();
                }
 
@@ -239,6 +239,24 @@ public:
                return composed(other, [](T self, T o) { return self + o; });
        }
 
+       binding<T>& operator++()
+       {
+               T new_value = get();
+               ++new_value;
+
+               set(new_value);
+
+               return *this;
+       }
+
+       binding<T> operator++(int)
+       {
+               binding<T> pre_val(get());
+               ++*this;
+
+               return pre_val;
+       }
+
        binding<T> operator-() const
        {
                return transformed([](T self) { return -self; });
@@ -254,6 +272,24 @@ public:
                return *this + -other;
        }
 
+       binding<T>& operator--()
+       {
+               T new_value = get();
+               --new_value;
+
+               set(new_value);
+
+               return *this;
+       }
+
+       binding<T> operator--(int)
+       {
+               binding<T> pre_val(get());
+               --*this;
+
+               return pre_val;
+       }
+
        binding<T> operator*(T other) const
        {
                return transformed([other](T self) { return self * other; });
index 708fd1428e8e1843ca1567c59cad60447c29644c..bd146fc067446afdec67727bcc6ed54353124047 100644 (file)
@@ -52,6 +52,7 @@ struct scene_producer::impl
        std::list<layer> layers_;
        interaction_aggregator aggregator_;
        binding<int64_t> frame_number_;
+       std::map<std::wstring, std::shared_ptr<parameter_holder_base>> parameters_;
 
        impl(int width, int height)
                : pixel_constraints_(width, height)
@@ -88,6 +89,13 @@ struct scene_producer::impl
                return layers_.back();
        }
 
+       void store_parameter(
+                       const std::wstring& name,
+                       const std::shared_ptr<parameter_holder_base>& param)
+       {
+               parameters_.insert(std::make_pair(boost::to_lower_copy(name), param));
+       }
+
        binding<int64_t> frame()
        {
                return frame_number_;
@@ -127,7 +135,7 @@ struct scene_producer::impl
                        frames.push_back(frame);
                }
 
-               frame_number_.set(frame_number_.get() + 1);
+               ++frame_number_;
 
                return draw_frame(frames);
        }
@@ -167,27 +175,15 @@ struct scene_producer::impl
 
        boost::unique_future<std::wstring> call(const std::vector<std::wstring>& params) 
        {
-               std::wstring result;
-               
-               if(params.size() >= 2)
+               for (int i = 0; i + 1 < params.size(); i += 2)
                {
-                       struct layer_comparer
-                       {
-                               const std::wstring& str;
-                               explicit layer_comparer(const std::wstring& s) : str(s) {}
-                               bool operator()(const layer& val) { return boost::iequals(val.name.get(), str); }
-                       };
+                       auto found = parameters_.find(boost::to_lower_copy(params[i]));
 
-                       auto it = std::find_if(layers_.begin(), layers_.end(), layer_comparer(params[0]));
-                       if(it != layers_.end())
-                       {
-                               auto params2 = params;
-                               params2.erase(params2.cbegin());
-                               (*it).producer.get()->call(params2);
-                       }
+                       if (found != parameters_.end())
+                               found->second->set(params[i + 1]);
                }
 
-               return async(launch::deferred, [=]{return result;});
+               return wrap_as_future(std::wstring(L""));
        }
 
        std::wstring print() const
@@ -295,6 +291,13 @@ void scene_producer::unsubscribe(const monitor::observable::observer_ptr& o)
        impl_->unsubscribe(o);
 }
 
+void scene_producer::store_parameter(
+               const std::wstring& name,
+               const std::shared_ptr<parameter_holder_base>& param)
+{
+       impl_->store_parameter(name, param);
+}
+
 spl::shared_ptr<frame_producer> create_dummy_scene_producer(const spl::shared_ptr<class frame_factory>& frame_factory, const video_format_desc& format_desc, const std::vector<std::wstring>& params)
 {
        if (params.size() < 1 || !boost::iequals(params.at(0), L"[SCENE]"))
index d8ffd3ef1691a7901a094266f3ffff4dfda3aa9c..c60f9a8b5705aaf4aa6197aab52f823da1495ef9 100644 (file)
@@ -53,6 +53,45 @@ struct layer
        layer(const std::wstring& name, const spl::shared_ptr<frame_producer>& producer);
 };
 
+template<typename T> class parameter_holder;
+
+class parameter_holder_base
+{
+public:
+       virtual ~parameter_holder_base()
+       {
+       }
+
+       virtual void set(const std::wstring& raw_value) = 0;
+
+       template<typename T>
+       binding<T>& value()
+       {
+               return dynamic_cast<parameter_holder<T>>(*this).value();
+       }
+};
+
+template<typename T>
+class parameter_holder : public parameter_holder_base
+{
+       binding<T> value_;
+public:
+       parameter_holder(T initial_value)
+               : value_(initial_value)
+       {
+       }
+
+       binding<T>& value()
+       {
+               return value_;
+       }
+
+       virtual void set(const std::wstring& raw_value)
+       {
+               value_.set(boost::lexical_cast<T>(raw_value));
+       }
+};
+
 class scene_producer : public frame_producer_base
 {
 public:
@@ -75,7 +114,20 @@ public:
                        const spl::shared_ptr<frame_producer>& producer, int x, int y, const std::wstring& name);
        layer& create_layer(const spl::shared_ptr<frame_producer>& producer);
        binding<int64_t> frame();
+
+       template<typename T> binding<T>& create_parameter(const std::wstring& name, T initial_value = T())
+       {
+               auto param = std::make_shared<parameter_holder<T>>(initial_value);
+
+               store_parameter(name, param);
+
+               return param->value();
+       }
 private:
+       void store_parameter(
+                       const std::wstring& name,
+                       const std::shared_ptr<parameter_holder_base>& param);
+
        struct impl;
        std::unique_ptr<impl> impl_;
 };
index 798e076496a70e51126fe0b0cf07ac339bbe5885..cd41705255ba6cf166c1331d6d1477de556f0bab 100644 (file)
@@ -101,7 +101,8 @@ struct text_producer::impl
        constraints constraints_;
        int x_, y_, parent_width_, parent_height_;
        bool standalone_;
-       std::wstring text_;
+       binding<std::wstring> text_;
+       std::shared_ptr<void> text_subscription_;
        draw_frame frame_;
        text::texture_atlas atlas_;
        text::texture_font font_;
@@ -119,8 +120,13 @@ public:
                font_.load_glyphs(text::Latin_1_Supplement, text_info.color);
                font_.load_glyphs(text::Latin_Extended_A, text_info.color);
 
+               text_subscription_ = text_.on_change([this]()
+               {
+                       generate_frame(text_.get());
+               });
+
                //generate frame
-               generate_frame(str);
+               text_.set(str);
 
                CASPAR_LOG(info) << print() << L" Initialized";
        }
@@ -128,7 +134,7 @@ public:
        void generate_frame(const std::wstring& str)
        {
                core::pixel_format_desc pfd(core::pixel_format::bgra);
-               pfd.planes.push_back(core::pixel_format_desc::plane((int)atlas_.width(), (int)atlas_.height(), (int)atlas_.depth()));
+               pfd.planes.push_back(core::pixel_format_desc::plane(static_cast<int>(atlas_.width()), static_cast<int>(atlas_.height()), static_cast<int>(atlas_.depth())));
 
                text::string_metrics metrics;
                std::vector<float> vertex_stream(std::move(font_.create_vertex_stream(str, x_, y_, parent_width_, parent_height_, &metrics)));
@@ -156,7 +162,7 @@ public:
        boost::unique_future<std::wstring> call(const std::vector<std::wstring>& param)
        {
                std::wstring result;
-               generate_frame(param.empty() ? L"" : param[0]);
+               text_.set(param.empty() ? L"" : param[0]);
 
                return async(launch::deferred, [=]{return result;});
        }
@@ -165,10 +171,15 @@ public:
        {
                return constraints_;
        }
+
+       binding<std::wstring>& text()
+       {
+               return text_;
+       }
        
        std::wstring print() const
        {
-               return L"text[" + text_ + L"]";
+               return L"text[" + text_.get() + L"]";
        }
 
        std::wstring name() const
@@ -180,7 +191,7 @@ public:
        {
                boost::property_tree::wptree info;
                info.add(L"type", L"text");
-               info.add(L"text", text_);
+               info.add(L"text", text_.get());
                return info;
        }
 };
@@ -199,6 +210,7 @@ std::wstring text_producer::name() const { return impl_->name(); }
 boost::property_tree::wptree text_producer::info() const { return impl_->info(); }
 void text_producer::subscribe(const monitor::observable::observer_ptr& o) {}
 void text_producer::unsubscribe(const monitor::observable::observer_ptr& o) {}
+binding<std::wstring>& text_producer::text() { return impl_->text(); }
 
 spl::shared_ptr<text_producer> text_producer::create(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, const text::text_info& text_info, long parent_width, long parent_height, bool standalone)
 {
@@ -218,10 +230,8 @@ spl::shared_ptr<frame_producer> create_text_producer(const spl::shared_ptr<frame
        }
 
        text::text_info text_info;
-       text_info.font = L"verdana";
-       text_info.size = 30.0f;
        text_info.font = get_param(L"FONT", params, L"verdana");
-       text_info.size = (float)get_param(L"SIZE", params, 30.0);
+       text_info.size = static_cast<float>(get_param(L"SIZE", params, 30.0)); // 30.0f does not seem to work to get as float directly
        
        std::wstring col_str = get_param(L"color", params, L"#ffffffff");
        uint32_t col_val = 0xffffffff;
index db81aca05560dfd461b7ceeb7950731334b2c720..d97d415f03b11ed91f71c7bac7a5c7011f1161db 100644 (file)
@@ -63,6 +63,7 @@ public:
        void subscribe(const monitor::observable::observer_ptr& o) override;
        void unsubscribe(const monitor::observable::observer_ptr& o) override;
 
+       binding<std::wstring>& text();
 private:
        struct impl;
        spl::unique_ptr<impl> impl_;
index 848ce424a80568ea87a3ccda5ed8dc37451db590..000345e5c29381cb7725074cae27746db9ff5083 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <boost/filesystem.hpp>
 #include <boost/foreach.hpp>
+#include <boost/thread/future.hpp>
 
 namespace caspar { namespace psd {
 
@@ -114,7 +115,6 @@ core::text::text_info get_text_info(const boost::property_tree::wptree& ptree)
 
                void calculate()
                {
-                       auto masters_end = masters.end();
                        for(auto it = masters.begin(); it != masters.end(); ++it)
                        {
                                auto& master = (*it);
@@ -190,6 +190,8 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
 
        layer_link_constructor link_constructor;
 
+       std::vector<std::pair<std::wstring, spl::shared_ptr<core::text_producer>>> text_producers_by_layer_name;
+
        auto layers_end = doc.layers().end();
        for(auto it = doc.layers().begin(); it != layers_end; ++it)
        {
@@ -208,6 +210,8 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
 
                        if((*it)->link_group_id() != 0)
                                link_constructor.add(&new_layer, (*it)->link_group_id(), true);
+
+                       text_producers_by_layer_name.push_back(std::make_pair((*it)->name(), text_producer));
                }
                else if((*it)->image() && (*it)->visible())
                {
@@ -230,6 +234,15 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
 
        link_constructor.calculate();
 
+       // Reset all dynamic text fields to empty strings and expose them as a scene parameter.
+       BOOST_FOREACH(auto& text_layer, text_producers_by_layer_name)
+               text_layer.second->text().bind(root->create_parameter<std::wstring>(text_layer.first, L""));
+
+       auto params2 = params;
+       params2.erase(params2.cbegin());
+
+       root->call(params2);
+
        return root;
 }
 
index 18251aacbec196d02337e4456e9894fbc4bb4481..f18008cf089662b636b72473f2539faf592cb1fe 100644 (file)
@@ -340,7 +340,7 @@ std::size_t AMCPProtocolStrategy::TokenizeMessage(const std::wstring& message, s
 
        std::wstring currentToken;
 
-       char inQuote = 0;
+       bool inQuote = false;
        bool getSpecialCode = false;
 
        for(unsigned int charIndex=0; charIndex<message.size(); ++charIndex)
@@ -384,9 +384,9 @@ std::size_t AMCPProtocolStrategy::TokenizeMessage(const std::wstring& message, s
 
                if(message[charIndex]==TEXT('\"'))
                {
-                       inQuote ^= 1;
+                       inQuote = !inQuote;
 
-                       if(currentToken.size()>0)
+                       if(currentToken.size() > 0 || !inQuote)
                        {
                                pTokenVector->push_back(currentToken);
                                currentToken.clear();