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