]> git.sesse.net Git - casparcg/blob - protocol/clk/clk_commands.cpp
* Upgraded to Visual Studio 2013
[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 \r
32 #include <modules/flash/producer/cg_proxy.h>\r
33 \r
34 #include "clk_commands.h"\r
35 \r
36 namespace caspar { namespace protocol { namespace CLK {\r
37 \r
38 class command_context\r
39 {\r
40         bool clock_loaded_;\r
41         spl::shared_ptr<core::video_channel> channel_;\r
42 public:\r
43         command_context(const spl::shared_ptr<core::video_channel>& channel)\r
44                 : clock_loaded_(false)\r
45                 , channel_(channel)\r
46         {\r
47         }\r
48 \r
49         void send_to_flash(const std::wstring& data)\r
50         {\r
51                 if (!clock_loaded_) \r
52                 {\r
53                         flash::create_cg_proxy(channel_).add(\r
54                                 0, L"hawrysklocka/clock.ft", true, L"", data);\r
55                         clock_loaded_ = true;\r
56                 }\r
57                 else\r
58                 {\r
59                         flash::create_cg_proxy(channel_).update(0, data);\r
60                 }\r
61                                 \r
62                 CASPAR_LOG(debug) << L"CLK: Clockdata sent: " << data;\r
63         }\r
64 \r
65         void reset()\r
66         {\r
67                 channel_->stage().clear(flash::cg_proxy::DEFAULT_LAYER);\r
68                 clock_loaded_ = false;\r
69                 CASPAR_LOG(info) << L"CLK: Recieved and executed reset-command";\r
70         }\r
71 };\r
72 \r
73 template<class T>\r
74 T require_param(\r
75         std::vector<std::wstring>::const_iterator& params_current,\r
76         const std::vector<std::wstring>::const_iterator& params_end,\r
77         const std::string& param_name)\r
78 {\r
79         if (params_current == params_end)\r
80                 throw std::runtime_error(param_name + " required");\r
81 \r
82         T value = boost::lexical_cast<T>(*params_current);\r
83 \r
84         ++params_current;\r
85 \r
86         return std::move(value);\r
87 }\r
88 \r
89 std::wstring get_xml(\r
90         const std::wstring& command_name,\r
91         bool has_clock_id,\r
92         bool has_time,\r
93         const std::vector<std::wstring>& parameters)\r
94 {\r
95         std::wstringstream stream;\r
96 \r
97         stream << L"<templateData>";    \r
98         stream << L"<componentData id=\"command\">";\r
99         stream << L"<command id=\"" << command_name << "\"";\r
100         \r
101         std::vector<std::wstring>::const_iterator it = parameters.begin();\r
102         std::vector<std::wstring>::const_iterator end = parameters.end();\r
103 \r
104         if (has_clock_id)\r
105         {\r
106                 stream << L" clockID=\""\r
107                         << require_param<int>(it, end, "clock id") << L"\"";\r
108         }\r
109 \r
110         if (has_time)\r
111         {\r
112                 stream << L" time=\""\r
113                         << require_param<std::wstring>(it, end, "time") << L"\"";\r
114         }\r
115 \r
116         bool has_parameters = it != end;\r
117 \r
118         stream << (has_parameters ? L">" : L" />");\r
119 \r
120         if (has_parameters)\r
121         {\r
122                 for (; it != end; ++it)\r
123                 {\r
124                         stream << L"<parameter>" << (*it) << L"</parameter>";\r
125                 }\r
126 \r
127                 stream << L"</command>";\r
128         }\r
129 \r
130         stream << L"</componentData>";\r
131         stream << L"</templateData>";\r
132 \r
133         return stream.str();\r
134 }\r
135 \r
136 clk_command_handler create_send_xml_handler(\r
137         const std::wstring& command_name, \r
138         bool expect_clock, \r
139         bool expect_time, \r
140         const spl::shared_ptr<command_context>& context)\r
141 {\r
142         return [=] (const std::vector<std::wstring>& params)\r
143         {\r
144                 context->send_to_flash(get_xml(\r
145                         command_name, expect_clock, expect_time, params));\r
146         };\r
147 }\r
148 \r
149 void add_command_handlers(\r
150         clk_command_processor& processor, \r
151         const spl::shared_ptr<core::video_channel>& channel)\r
152 {\r
153         auto context = spl::make_shared<command_context>(channel);\r
154 \r
155         processor\r
156                 .add_handler(L"DUR", \r
157                         create_send_xml_handler(L"DUR", true, true, context))\r
158                 .add_handler(L"NEWDUR", \r
159                         create_send_xml_handler(L"NEWDUR", true, true, context))\r
160                 .add_handler(L"UNTIL", \r
161                         create_send_xml_handler(L"UNTIL", true, true, context))\r
162                 .add_handler(L"NEXTEVENT", \r
163                         create_send_xml_handler(L"NEXTEVENT", true, false, context))\r
164                 .add_handler(L"STOP", \r
165                         create_send_xml_handler(L"STOP", true, false, context))\r
166                 .add_handler(L"ADD", \r
167                         create_send_xml_handler(L"ADD", true, true, context))\r
168                 .add_handler(L"SUB", \r
169                         create_send_xml_handler(L"SUB", true, true, context))\r
170                 .add_handler(L"TIMELINE_LOAD", \r
171                         create_send_xml_handler(L"TIMELINE_LOAD", false, false, context))\r
172                 .add_handler(L"TIMELINE_PLAY", \r
173                         create_send_xml_handler(L"TIMELINE_PLAY", false, false, context))\r
174                 .add_handler(L"TIMELINE_STOP", \r
175                         create_send_xml_handler(L"TIMELINE_STOP", false, false, context))\r
176                 .add_handler(L"RESET", [=] (const std::vector<std::wstring>& params)\r
177                 {\r
178                         context->reset();\r
179                 })\r
180                 ;\r
181 }\r
182 \r
183 }}}\r