-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG.\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-* GNU General Public License for more details.\r
-\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
- \r
-#include "..\stdafx.h"\r
-\r
-#include "CLKProtocolStrategy.h"\r
-\r
-#include <modules/flash/producer/cg_producer.h>\r
-\r
-#include <string>\r
-#include <sstream>\r
-#include <algorithm>\r
-\r
-namespace caspar { namespace protocol { namespace CLK {\r
- \r
-CLKProtocolStrategy::CLKProtocolStrategy(const std::vector<safe_ptr<core::channel>>& channels) \r
- : currentState_(ExpectingNewCommand), bClockLoaded_(false), pChannel_(channels.at(0))\r
-{}\r
-\r
-void CLKProtocolStrategy::Parse(const TCHAR* pData, int charCount, IO::ClientInfoPtr pClientInfo) \r
-{\r
- for(int index = 0; index < charCount; ++index) \r
- {\r
- if(currentState_ == ExpectingNewCommand)\r
- currentCommandString_.str(TEXT(""));\r
-\r
- TCHAR currentByte = pData[index];\r
- if(currentByte < 32)\r
- currentCommandString_ << TEXT("<") << (int)currentByte << TEXT(">");\r
- else\r
- currentCommandString_ << currentByte;\r
-\r
- if(currentByte != 0)\r
- {\r
- switch(currentState_)\r
- {\r
- case ExpectingNewCommand:\r
- if(currentByte == 1) \r
- currentState_ = ExpectingCommand; \r
- //just throw anything else away\r
- break;\r
-\r
- case ExpectingCommand:\r
- if(currentByte == 2) \r
- {\r
- if(!currentCommand_.SetCommand()) \r
- {\r
- CASPAR_LOG(error) << "CLK: Failed to interpret command";\r
- currentState_ = ExpectingNewCommand;\r
- currentCommand_.Clear();\r
- }\r
- else \r
- currentState_ = ExpectingClockID; \r
- }\r
- else\r
- currentCommand_.commandString_ += currentByte;\r
- break;\r
-\r
- case ExpectingClockID:\r
- if(currentByte == 2)\r
- currentState_ = currentCommand_.NeedsTime() ? ExpectingTime : ExpectingParameter;\r
- else\r
- currentCommand_.clockID_ = currentByte - TCHAR('0');\r
- break;\r
-\r
- case ExpectingTime:\r
- if(currentByte == 2)\r
- currentState_ = ExpectingParameter;\r
- else\r
- currentCommand_.time_ += currentByte;\r
- break;\r
-\r
- case ExpectingParameter:\r
- //allocate new parameter\r
- if(currentCommand_.parameters_.size() == 0 || currentByte == 2)\r
- currentCommand_.parameters_.push_back(std::wstring());\r
-\r
- //add the character to end end of the last parameter\r
- if(currentByte == TEXT('<'))\r
- currentCommand_.parameters_[currentCommand_.parameters_.size()-1] += TEXT("<");\r
- else if(currentByte == TEXT('>'))\r
- currentCommand_.parameters_[currentCommand_.parameters_.size()-1] += TEXT(">");\r
- else if(currentByte == TEXT('\"'))\r
- currentCommand_.parameters_[currentCommand_.parameters_.size()-1] += TEXT(""");\r
- else\r
- currentCommand_.parameters_[currentCommand_.parameters_.size()-1] += currentByte;\r
-\r
- break;\r
- }\r
- }\r
- else \r
- {\r
- if(currentState_ == ExpectingCommand)\r
- {\r
- if(!currentCommand_.SetCommand())\r
- CASPAR_LOG(error) << "CLK: Failed to interpret command";\r
- }\r
-\r
- if(currentCommand_.command_ == CLKCommand::CLKReset) \r
- {\r
- pChannel_->producer()->clear(cg_producer::DEFAULT_LAYER);\r
- bClockLoaded_ = false;\r
- \r
- CASPAR_LOG(info) << L"CLK: Recieved and executed reset-command";\r
- }\r
- else if(currentCommand_.command_ != CLKCommand::CLKInvalidCommand)\r
- {\r
- if(!bClockLoaded_) \r
- {\r
- get_default_cg_producer(pChannel_)->add(0, TEXT("hawrysklocka/clock.ft"), true, TEXT(""), currentCommand_.GetData());\r
- bClockLoaded_ = true;\r
- }\r
- else \r
- get_default_cg_producer(pChannel_)->update(0, currentCommand_.GetData());\r
- \r
- CASPAR_LOG(debug) << L"CLK: Clockdata sent: " << currentCommand_.GetData();\r
- CASPAR_LOG(debug) << L"CLK: Executed valid command: " << currentCommandString_.str();\r
- }\r
-\r
- currentState_ = ExpectingNewCommand;\r
- currentCommand_.Clear();\r
- }\r
- }\r
-}\r
-\r
-} //namespace CLK\r
-}} //namespace caspar
\ No newline at end of file
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Nicklas P Andersson
+*/
+
+
+#include "../StdAfx.h"
+
+#include "CLKProtocolStrategy.h"
+#include "clk_commands.h"
+
+#include <string>
+#include <algorithm>
+#include <locale>
+#include <vector>
+#include <sstream>
+
+namespace caspar { namespace protocol { namespace CLK {
+
+class CLKProtocolStrategy : public IO::protocol_strategy<wchar_t>
+{
+ enum class ParserState
+ {
+ ExpectingNewCommand,
+ ExpectingCommand,
+ ExpectingParameter
+ };
+
+ ParserState currentState_ = ParserState::ExpectingNewCommand;
+ std::wstringstream currentCommandString_;
+ std::wstring command_name_;
+ std::vector<std::wstring> parameters_;
+ clk_command_processor& command_processor_;
+ IO::client_connection<wchar_t>::ptr client_connection_;
+public:
+ CLKProtocolStrategy(
+ const IO::client_connection<wchar_t>::ptr& client_connection,
+ clk_command_processor& command_processor)
+ : command_processor_(command_processor)
+ , client_connection_(client_connection)
+ {
+ }
+
+ void parse(const std::basic_string<wchar_t>& data)
+ {
+ for (int index = 0; index < data.length(); ++index)
+ {
+ wchar_t currentByte = data[index];
+
+ if (currentByte < 32)
+ currentCommandString_ << L"<" << static_cast<int>(currentByte) << L">";
+ else
+ currentCommandString_ << currentByte;
+
+ if (currentByte != 0)
+ {
+ switch (currentState_)
+ {
+ case ParserState::ExpectingNewCommand:
+ if (currentByte == 1)
+ currentState_ = ParserState::ExpectingCommand;
+ //just throw anything else away
+ break;
+ case ParserState::ExpectingCommand:
+ if (currentByte == 2)
+ currentState_ = ParserState::ExpectingParameter;
+ else
+ command_name_ += currentByte;
+ break;
+ case ParserState::ExpectingParameter:
+ //allocate new parameter
+ if (parameters_.size() == 0 || currentByte == 2)
+ parameters_.push_back(std::wstring());
+
+ //add the character to end end of the last parameter
+ if (currentByte != 2)
+ {
+ //add the character to end end of the last parameter
+ if (currentByte == L'<')
+ parameters_.back() += L"<";
+ else if (currentByte == L'>')
+ parameters_.back() += L">";
+ else if (currentByte == L'\"')
+ parameters_.back() += L""";
+ else
+ parameters_.back() += currentByte;
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ std::transform(
+ command_name_.begin(), command_name_.end(),
+ command_name_.begin(),
+ toupper);
+
+ try
+ {
+ if (!command_processor_.handle(command_name_, parameters_))
+ CASPAR_LOG(error) << "CLK: Unknown command: " << command_name_;
+ else
+ CASPAR_LOG(info) << L"CLK: Executed valid command: "
+ << currentCommandString_.str();
+ }
+ catch (...)
+ {
+ CASPAR_LOG_CURRENT_EXCEPTION();
+ CASPAR_LOG(error) << "CLK: Failed to interpret command: "
+ << currentCommandString_.str();
+ }
+
+ reset();
+ }
+ }
+ }
+private:
+ void reset()
+ {
+ currentState_ = ParserState::ExpectingNewCommand;
+ currentCommandString_.str(L"");
+ command_name_.clear();
+ parameters_.clear();
+ }
+};
+
+clk_protocol_strategy_factory::clk_protocol_strategy_factory(
+ const std::vector<spl::shared_ptr<core::video_channel>>& channels,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry,
+ const spl::shared_ptr<const core::frame_producer_registry>& producer_registry)
+{
+ add_command_handlers(command_processor_, channels, channels.at(0), cg_registry, producer_registry);
+}
+
+IO::protocol_strategy<wchar_t>::ptr clk_protocol_strategy_factory::create(
+ const IO::client_connection<wchar_t>::ptr& client_connection)
+{
+ return spl::make_shared<CLKProtocolStrategy>(client_connection, command_processor_);
+}
+
+}}}