]> git.sesse.net Git - casparcg/blob - protocol/clk/CLKProtocolStrategy.cpp
[ffmpeg_producer] Recognize .mkv and .mxf files as playable without probing
[casparcg] / protocol / clk / CLKProtocolStrategy.cpp
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: Nicklas P Andersson
20 */
21
22  
23 #include "../StdAfx.h"
24
25 #include "CLKProtocolStrategy.h"
26 #include "clk_commands.h"
27
28 #include <string>
29 #include <algorithm>
30 #include <locale>
31 #include <vector>
32 #include <sstream>
33
34 namespace caspar { namespace protocol { namespace CLK {
35
36 class CLKProtocolStrategy : public IO::protocol_strategy<wchar_t>
37 {
38         enum class ParserState
39         {
40                 ExpectingNewCommand,
41                 ExpectingCommand,
42                 ExpectingParameter
43         };
44
45         ParserState     currentState_                                                           = ParserState::ExpectingNewCommand;
46         std::wstringstream currentCommandString_;
47         std::wstring command_name_;
48         std::vector<std::wstring> parameters_;
49         clk_command_processor& command_processor_;
50         IO::client_connection<wchar_t>::ptr client_connection_;
51 public:
52         CLKProtocolStrategy(
53                         const IO::client_connection<wchar_t>::ptr& client_connection,
54                         clk_command_processor& command_processor) 
55                 : command_processor_(command_processor)
56                 , client_connection_(client_connection)
57         {
58         }
59
60         void parse(const std::basic_string<wchar_t>& data)
61         {
62                 for (int index = 0; index < data.length(); ++index) 
63                 {
64                         wchar_t currentByte = data[index];
65
66                         if (currentByte < 32)
67                                 currentCommandString_ << L"<" << static_cast<int>(currentByte) << L">";
68                         else
69                                 currentCommandString_ << currentByte;
70
71                         if (currentByte != 0)
72                         {
73                                 switch (currentState_)
74                                 {
75                                         case ParserState::ExpectingNewCommand:
76                                                 if (currentByte == 1) 
77                                                         currentState_ = ParserState::ExpectingCommand;
78                                                 //just throw anything else away
79                                                 break;
80                                         case ParserState::ExpectingCommand:
81                                                 if (currentByte == 2) 
82                                                         currentState_ = ParserState::ExpectingParameter;
83                                                 else
84                                                         command_name_ += currentByte;
85                                                 break;
86                                         case ParserState::ExpectingParameter:
87                                                 //allocate new parameter
88                                                 if (parameters_.size() == 0 || currentByte == 2)
89                                                         parameters_.push_back(std::wstring());
90
91                                                 //add the character to end end of the last parameter
92                                                 if (currentByte != 2)
93                                                 {
94                                                         //add the character to end end of the last parameter
95                                                         if (currentByte == L'<')
96                                                                 parameters_.back() += L"&lt;";
97                                                         else if (currentByte == L'>')
98                                                                 parameters_.back() += L"&gt;";
99                                                         else if (currentByte == L'\"')
100                                                                 parameters_.back() += L"&quot;";
101                                                         else
102                                                                 parameters_.back() += currentByte;
103                                                 }
104
105                                                 break;
106                                 }
107                         }
108                         else
109                         {
110                                 std::transform(
111                                         command_name_.begin(), command_name_.end(), 
112                                         command_name_.begin(), 
113                                         toupper);
114
115                                 try
116                                 {
117                                         if (!command_processor_.handle(command_name_, parameters_))
118                                                 CASPAR_LOG(error) << "CLK: Unknown command: " << command_name_;
119                                         else
120                                                 CASPAR_LOG(info) << L"CLK: Executed valid command: " 
121                                                         << currentCommandString_.str();
122                                 } 
123                                 catch (...)
124                                 {
125                                         CASPAR_LOG_CURRENT_EXCEPTION();
126                                         CASPAR_LOG(error) << "CLK: Failed to interpret command: " 
127                                                 << currentCommandString_.str();
128                                 }
129
130                                 reset();
131                         }
132                 }
133         }
134 private:
135         void reset()
136         {
137                 currentState_ = ParserState::ExpectingNewCommand;
138                 currentCommandString_.str(L"");
139                 command_name_.clear();
140                 parameters_.clear();
141         }
142 };
143
144 clk_protocol_strategy_factory::clk_protocol_strategy_factory(
145                 const std::vector<spl::shared_ptr<core::video_channel>>& channels,
146                 const spl::shared_ptr<core::cg_producer_registry>& cg_registry,
147                 const spl::shared_ptr<const core::frame_producer_registry>& producer_registry)
148 {
149         add_command_handlers(command_processor_, channels, channels.at(0), cg_registry, producer_registry);
150 }
151
152 IO::protocol_strategy<wchar_t>::ptr clk_protocol_strategy_factory::create(
153                 const IO::client_connection<wchar_t>::ptr& client_connection)
154 {
155         return spl::make_shared<CLKProtocolStrategy>(client_connection, command_processor_);
156 }
157
158 }}}