]> git.sesse.net Git - casparcg/blob - protocol/clk/clk_commands.cpp
Changed default log level to info and moved logging statements that we always want...
[casparcg] / protocol / clk / clk_commands.cpp
1 /*\r
2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Helge Norberg, helge.norberg@svt.se\r
20 */\r
21 \r
22 #include "../StdAfx.h"\r
23 \r
24 #include <stdexcept>\r
25 #include <sstream>\r
26 #include <future>\r
27 \r
28 #include <boost/lexical_cast.hpp>\r
29 \r
30 #include <common/log.h>\r
31 #include <common/memory.h>\r
32 \r
33 #include <core/video_channel.h>\r
34 #include <core/producer/stage.h>\r
35 #include <core/producer/cg_proxy.h>\r
36 \r
37 #include "clk_commands.h"\r
38 \r
39 namespace caspar { namespace protocol { namespace CLK {\r
40 \r
41 class command_context\r
42 {\r
43         bool                                                                                                    clock_loaded_ = false;\r
44         std::vector<spl::shared_ptr<core::video_channel>>               channels_;\r
45         spl::shared_ptr<core::video_channel>                                    channel_;\r
46         spl::shared_ptr<core::cg_producer_registry>                             cg_registry_;\r
47         spl::shared_ptr<const core::frame_producer_registry>    producer_registry_;\r
48 public:\r
49         command_context(\r
50                         const std::vector<spl::shared_ptr<core::video_channel>>& channels,\r
51                         const spl::shared_ptr<core::video_channel>& channel,\r
52                         const spl::shared_ptr<core::cg_producer_registry>& cg_registry,\r
53                         const spl::shared_ptr<const core::frame_producer_registry>& producer_registry)\r
54                 : channels_(channels)\r
55                 , channel_(channel)\r
56                 , cg_registry_(cg_registry)\r
57                 , producer_registry_(producer_registry)\r
58         {\r
59         }\r
60 \r
61         void send_to_flash(const std::wstring& data)\r
62         {\r
63                 if (!clock_loaded_) \r
64                 {\r
65                         core::frame_producer_dependencies dependencies(channel_->frame_factory(), channels_, channel_->video_format_desc(), producer_registry_);\r
66                         cg_registry_->get_or_create_proxy(channel_, dependencies, core::cg_proxy::DEFAULT_LAYER, L"hawrysklocka/clock")->add(\r
67                                         0, L"hawrysklocka/clock", true, L"", data);\r
68                         clock_loaded_ = true;\r
69                 }\r
70                 else\r
71                 {\r
72                         cg_registry_->get_proxy(channel_, core::cg_proxy::DEFAULT_LAYER)->update(0, data);\r
73                 }\r
74                                 \r
75                 CASPAR_LOG(info) << L"CLK: Clockdata sent: " << data;\r
76         }\r
77 \r
78         void reset()\r
79         {\r
80                 channel_->stage().clear(core::cg_proxy::DEFAULT_LAYER);\r
81                 clock_loaded_ = false;\r
82                 CASPAR_LOG(info) << L"CLK: Recieved and executed reset-command";\r
83         }\r
84 };\r
85 \r
86 template<class T>\r
87 T require_param(\r
88         std::vector<std::wstring>::const_iterator& params_current,\r
89         const std::vector<std::wstring>::const_iterator& params_end,\r
90         const std::string& param_name)\r
91 {\r
92         if (params_current == params_end)\r
93                 throw std::runtime_error(param_name + " required");\r
94 \r
95         T value = boost::lexical_cast<T>(*params_current);\r
96 \r
97         ++params_current;\r
98 \r
99         return std::move(value);\r
100 }\r
101 \r
102 std::wstring get_xml(\r
103         const std::wstring& command_name,\r
104         bool has_clock_id,\r
105         bool has_time,\r
106         const std::vector<std::wstring>& parameters)\r
107 {\r
108         std::wstringstream stream;\r
109 \r
110         stream << L"<templateData>";    \r
111         stream << L"<componentData id=\"command\">";\r
112         stream << L"<command id=\"" << command_name << "\"";\r
113         \r
114         std::vector<std::wstring>::const_iterator it = parameters.begin();\r
115         std::vector<std::wstring>::const_iterator end = parameters.end();\r
116 \r
117         if (has_clock_id)\r
118         {\r
119                 stream << L" clockID=\""\r
120                         << require_param<int>(it, end, "clock id") << L"\"";\r
121         }\r
122 \r
123         if (has_time)\r
124         {\r
125                 stream << L" time=\""\r
126                         << require_param<std::wstring>(it, end, "time") << L"\"";\r
127         }\r
128 \r
129         bool has_parameters = it != end;\r
130 \r
131         stream << (has_parameters ? L">" : L" />");\r
132 \r
133         if (has_parameters)\r
134         {\r
135                 for (; it != end; ++it)\r
136                 {\r
137                         stream << L"<parameter>" << (*it) << L"</parameter>";\r
138                 }\r
139 \r
140                 stream << L"</command>";\r
141         }\r
142 \r
143         stream << L"</componentData>";\r
144         stream << L"</templateData>";\r
145 \r
146         return stream.str();\r
147 }\r
148 \r
149 clk_command_handler create_send_xml_handler(\r
150         const std::wstring& command_name, \r
151         bool expect_clock, \r
152         bool expect_time, \r
153         const spl::shared_ptr<command_context>& context)\r
154 {\r
155         return [=] (const std::vector<std::wstring>& params)\r
156         {\r
157                 context->send_to_flash(get_xml(\r
158                         command_name, expect_clock, expect_time, params));\r
159         };\r
160 }\r
161 \r
162 void add_command_handlers(\r
163         clk_command_processor& processor,\r
164         const std::vector<spl::shared_ptr<core::video_channel>>& channels,\r
165         const spl::shared_ptr<core::video_channel>& channel,\r
166         const spl::shared_ptr<core::cg_producer_registry>& cg_registry,\r
167         const spl::shared_ptr<const core::frame_producer_registry>& producer_registry)\r
168 {\r
169         auto context = spl::make_shared<command_context>(channels, channel, cg_registry, producer_registry);\r
170 \r
171         processor\r
172                 .add_handler(L"DUR", \r
173                         create_send_xml_handler(L"DUR", true, true, context))\r
174                 .add_handler(L"NEWDUR", \r
175                         create_send_xml_handler(L"NEWDUR", true, true, context))\r
176                 .add_handler(L"UNTIL", \r
177                         create_send_xml_handler(L"UNTIL", true, true, context))\r
178                 .add_handler(L"NEXTEVENT", \r
179                         create_send_xml_handler(L"NEXTEVENT", true, false, context))\r
180                 .add_handler(L"STOP", \r
181                         create_send_xml_handler(L"STOP", true, false, context))\r
182                 .add_handler(L"ADD", \r
183                         create_send_xml_handler(L"ADD", true, true, context))\r
184                 .add_handler(L"SUB", \r
185                         create_send_xml_handler(L"SUB", true, true, context))\r
186                 .add_handler(L"TIMELINE_LOAD", \r
187                         create_send_xml_handler(L"TIMELINE_LOAD", false, false, context))\r
188                 .add_handler(L"TIMELINE_PLAY", \r
189                         create_send_xml_handler(L"TIMELINE_PLAY", false, false, context))\r
190                 .add_handler(L"TIMELINE_STOP", \r
191                         create_send_xml_handler(L"TIMELINE_STOP", false, false, context))\r
192                 .add_handler(L"RESET", [=] (const std::vector<std::wstring>& params)\r
193                 {\r
194                         context->reset();\r
195                 })\r
196                 ;\r
197 }\r
198 \r
199 }}}\r