/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+* Copyright 2013 Sveriges Television AB http://casparcg.com/\r
*\r
* This file is part of CasparCG (www.casparcg.com).\r
*\r
#include <common/os/windows/system_info.h>\r
#include <common/utility/string.h>\r
#include <common/utility/utf8conv.h>\r
+#include <common/utility/base64.h>\r
\r
#include <core/producer/frame_producer.h>\r
#include <core/video_format.h>\r
\r
/* Return codes\r
\r
-100 [action] Information om att något har hänt \r
-101 [action] Information om att något har hänt, en rad data skickas \r
+100 [action] Information om att n�got har h�nt \r
+101 [action] Information om att n�got har h�nt, en rad data skickas \r
\r
-202 [kommando] OK Kommandot har utförts \r
-201 [kommando] OK Kommandot har utförts, och en rad data skickas tillbaka \r
-200 [kommando] OK Kommandot har utförts, och flera rader data skickas tillbaka. Avslutas med tomrad \r
+202 [kommando] OK Kommandot har utf�rts \r
+201 [kommando] OK Kommandot har utf�rts, och en rad data skickas tillbaka \r
+200 [kommando] OK Kommandot har utf�rts, och flera rader data skickas tillbaka. Avslutas med tomrad \r
\r
-400 ERROR Kommandot kunde inte förstås \r
+400 ERROR Kommandot kunde inte f�rst�s \r
401 [kommando] ERROR Ogiltig kanal \r
402 [kommando] ERROR Parameter saknas \r
403 [kommando] ERROR Ogiltig parameter \r
\r
500 FAILED Internt configurationfel \r
501 [kommando] FAILED Internt configurationfel \r
-502 [kommando] FAILED Oläslig mediafil \r
+502 [kommando] FAILED Ol�slig mediafil \r
\r
600 [kommando] FAILED funktion ej implementerad\r
*/\r
if (!filestream)\r
return L"";\r
\r
- // From http://www.webbiscuit.co.uk/2012/04/02/base64-encoder-and-boost/\r
- \r
- typedef\r
- insert_linebreaks< // insert line breaks every 76 characters\r
- base64_from_binary< // convert binary values to base64 characters\r
- transform_width< // retrieve 6 bit integers from a sequence of 8 bit bytes\r
- const unsigned char *,\r
- 6,\r
- 8\r
- >\r
- >,\r
- 76\r
- >\r
- base64_iterator; // compose all the above operations in to a new iterator\r
auto length = boost::filesystem::file_size(file);\r
std::vector<char> bytes;\r
bytes.resize(length);\r
filestream.read(bytes.data(), length);\r
\r
- int padding = 0;\r
-\r
- while (bytes.size() % 3 != 0)\r
- {\r
- ++padding;\r
- bytes.push_back(0x00);\r
- }\r
-\r
- std::string result(base64_iterator(bytes.data()), base64_iterator(bytes.data() + length - padding));\r
- result.insert(result.end(), padding, '=');\r
-\r
- return widen(result);\r
+ return widen(to_base64(bytes.data(), length));\r
}\r
\r
std::wstring read_utf8_file(const boost::filesystem::wpath& file)\r
int index = 1;\r
auto self = GetChannels().back();\r
\r
- std::vector<std::wstring> params;\r
+ core::parameters params;\r
params.push_back(L"SCREEN");\r
params.push_back(L"NAME");\r
params.push_back(L"Channel Grid Window");\r
auto what = _parameters.at(0);\r
\r
boost::unique_future<std::wstring> result;\r
+ auto& params_orig = _parameters.get_original();\r
if(what == L"B" || what == L"F")\r
{\r
std::wstring param;\r
- for(auto it = std::begin(_parameters2)+1; it != std::end(_parameters2); ++it, param += L" ")\r
+ for(auto it = std::begin(params_orig)+1; it != std::end(params_orig); ++it, param += L" ")\r
param += *it;\r
result = GetChannel()->stage()->call(GetLayerIndex(), what == L"F", boost::trim_copy(param));\r
}\r
else\r
{\r
std::wstring param;\r
- for(auto it = std::begin(_parameters2); it != std::end(_parameters2); ++it, param += L" ")\r
+ for(auto it = std::begin(params_orig); it != std::end(params_orig); ++it, param += L" ")\r
param += *it;\r
result = GetChannel()->stage()->call(GetLayerIndex(), true, boost::trim_copy(param));\r
}\r
// UGLY HACK\r
tbb::concurrent_unordered_map<int, std::vector<stage::transform_tuple_t>> deferred_transforms;\r
\r
+core::frame_transform MixerCommand::get_current_transform()\r
+{\r
+ return GetChannel()->stage()->get_current_transform(GetLayerIndex());\r
+}\r
+\r
bool MixerCommand::DoExecute()\r
-{ \r
+{\r
+ using boost::lexical_cast;\r
//Perform loading of the clip\r
try\r
{ \r
\r
if(_parameters[0] == L"KEYER" || _parameters[0] == L"IS_KEY")\r
{\r
+ if (_parameters.size() == 1)\r
+ return reply_value([](const frame_transform& t) { return t.is_key ? 1 : 0; });\r
+\r
bool value = boost::lexical_cast<int>(_parameters.at(1));\r
transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
}\r
else if(_parameters[0] == L"OPACITY")\r
{\r
+ if (_parameters.size() == 1)\r
+ return reply_value([](const frame_transform& t) { return t.opacity; });\r
+\r
int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
\r
}\r
else if(_parameters[0] == L"FILL" || _parameters[0] == L"FILL_RECT")\r
{\r
+ if (_parameters.size() == 1)\r
+ {\r
+ auto transform = get_current_transform();\r
+ auto translation = transform.fill_translation;\r
+ auto scale = transform.fill_scale;\r
+ SetReplyString(\r
+ L"201 MIXER OK\r\n" \r
+ + lexical_cast<std::wstring>(translation[0]) + L" "\r
+ + lexical_cast<std::wstring>(translation[1]) + L" "\r
+ + lexical_cast<std::wstring>(scale[0]) + L" "\r
+ + lexical_cast<std::wstring>(scale[1]) + L"\r\n");\r
+ return true;\r
+ }\r
+\r
int duration = _parameters.size() > 5 ? boost::lexical_cast<int>(_parameters[5]) : 0;\r
std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear";\r
double x = boost::lexical_cast<double>(_parameters.at(1));\r
transform.fill_translation[1] = y;\r
transform.fill_scale[0] = x_s;\r
transform.fill_scale[1] = y_s;\r
- transform.clip_translation[0] = x;\r
- transform.clip_translation[1] = y;\r
- transform.clip_scale[0] = x_s;\r
- transform.clip_scale[1] = y_s;\r
return transform;\r
}, duration, tween));\r
}\r
else if(_parameters[0] == L"CLIP" || _parameters[0] == L"CLIP_RECT")\r
{\r
+ if (_parameters.size() == 1)\r
+ {\r
+ auto transform = get_current_transform();\r
+ auto translation = transform.clip_translation;\r
+ auto scale = transform.clip_scale;\r
+ SetReplyString(\r
+ L"201 MIXER OK\r\n" \r
+ + lexical_cast<std::wstring>(translation[0]) + L" "\r
+ + lexical_cast<std::wstring>(translation[1]) + L" "\r
+ + lexical_cast<std::wstring>(scale[0]) + L" "\r
+ + lexical_cast<std::wstring>(scale[1]) + L"\r\n");\r
+ return true;\r
+ }\r
+\r
int duration = _parameters.size() > 5 ? boost::lexical_cast<int>(_parameters[5]) : 0;\r
std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear";\r
double x = boost::lexical_cast<double>(_parameters.at(1));\r
double y = boost::lexical_cast<double>(_parameters.at(2));\r
double x_s = boost::lexical_cast<double>(_parameters.at(3));\r
double y_s = boost::lexical_cast<double>(_parameters.at(4));\r
+ if(x_s < 0 || y_s < 0)\r
+ {\r
+ SetReplyString(L"403 MIXER ERROR\r\n");\r
+ return false;\r
+ }\r
\r
transforms.push_back(stage::transform_tuple_t(GetLayerIndex(), [=](frame_transform transform) -> frame_transform\r
{\r
}\r
else if(_parameters[0] == L"BLEND")\r
{\r
+ if (_parameters.size() == 1)\r
+ {\r
+ auto blend_mode = GetChannel()->mixer()->get_blend_mode(GetLayerIndex());\r
+ SetReplyString(L"201 MIXER OK\r\n" \r
+ + lexical_cast<std::wstring>(get_blend_mode(blend_mode)) \r
+ + L"\r\n");\r
+ return true;\r
+ }\r
+\r
auto blend_str = _parameters.at(1); \r
int layer = GetLayerIndex();\r
- GetChannel()->mixer()->set_blend_mode(GetLayerIndex(), get_blend_mode(blend_str)); \r
+ blend_mode::type && blend = get_blend_mode(blend_str);\r
+ GetChannel()->mixer()->set_blend_mode(GetLayerIndex(), blend); \r
}\r
+ else if(_parameters[0] == L"CHROMA")\r
+ {\r
+ if (_parameters.size() == 1)\r
+ {\r
+ auto chroma = GetChannel()->mixer()->get_chroma(GetLayerIndex());\r
+ SetReplyString(L"201 MIXER OK\r\n" \r
+ + get_chroma_mode(chroma.key)\r
+ + (chroma.key == chroma::none\r
+ ? L""\r
+ : L" "\r
+ + lexical_cast<std::wstring>(chroma.threshold) + L" "\r
+ + lexical_cast<std::wstring>(chroma.softness))\r
+ + L"\r\n");\r
+ // Add the rest when they are actually used and documented\r
+ return true;\r
+ }\r
+\r
+ int layer = GetLayerIndex();\r
+ chroma chroma;\r
+ chroma.key = get_chroma_mode(_parameters[1]);\r
+\r
+ if (chroma.key != chroma::none)\r
+ {\r
+ chroma.threshold = boost::lexical_cast<double>(_parameters[2]);\r
+ chroma.softness = boost::lexical_cast<double>(_parameters[3]);\r
+ chroma.spill = _parameters.size() > 4 ? boost::lexical_cast<double>(_parameters[4]) : 0.0f;\r
+ chroma.blur = _parameters.size() > 5 ? boost::lexical_cast<double>(_parameters[5]) : 0.0f;\r
+ chroma.show_mask = _parameters.size() > 6 ? bool(boost::lexical_cast<int>(_parameters[6])) : false;\r
+ }\r
+\r
+ GetChannel()->mixer()->set_chroma(GetLayerIndex(), chroma);\r
+ }\r
else if(_parameters[0] == L"MASTERVOLUME")\r
{\r
+ if (_parameters.size() == 1)\r
+ {\r
+ auto volume = GetChannel()->mixer()->get_master_volume();\r
+ SetReplyString(L"201 MIXER OK\r\n" \r
+ + lexical_cast<std::wstring>(volume) + L"\r\n");\r
+ return true;\r
+ }\r
+\r
float master_volume = boost::lexical_cast<float>(_parameters.at(1));\r
GetChannel()->mixer()->set_master_volume(master_volume);\r
}\r
else if(_parameters[0] == L"BRIGHTNESS")\r
{\r
+ if (_parameters.size() == 1)\r
+ return reply_value([](const frame_transform& t) { return t.brightness; });\r
+\r
auto value = boost::lexical_cast<double>(_parameters.at(1));\r
int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
}\r
else if(_parameters[0] == L"SATURATION")\r
{\r
+ if (_parameters.size() == 1)\r
+ return reply_value([](const frame_transform& t) { return t.saturation; });\r
+\r
auto value = boost::lexical_cast<double>(_parameters.at(1));\r
int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
}\r
else if(_parameters[0] == L"CONTRAST")\r
{\r
+ if (_parameters.size() == 1)\r
+ return reply_value([](const frame_transform& t) { return t.contrast; });\r
+\r
auto value = boost::lexical_cast<double>(_parameters.at(1));\r
int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
}\r
else if(_parameters[0] == L"LEVELS")\r
{\r
+ if (_parameters.size() == 1)\r
+ {\r
+ auto levels = get_current_transform().levels;\r
+ SetReplyString(L"201 MIXER OK\r\n"\r
+ + lexical_cast<std::wstring>(levels.min_input) + L" "\r
+ + lexical_cast<std::wstring>(levels.max_input) + L" "\r
+ + lexical_cast<std::wstring>(levels.gamma) + L" "\r
+ + lexical_cast<std::wstring>(levels.min_output) + L" "\r
+ + lexical_cast<std::wstring>(levels.max_output) + L"\r\n");\r
+ return true;\r
+ }\r
+\r
levels value;\r
value.min_input = boost::lexical_cast<double>(_parameters.at(1));\r
value.max_input = boost::lexical_cast<double>(_parameters.at(2));\r
}\r
else if(_parameters[0] == L"VOLUME")\r
{\r
+ if (_parameters.size() == 1)\r
+ return reply_value([](const frame_transform& t) { return t.volume; });\r
+\r
int duration = _parameters.size() > 2 ? boost::lexical_cast<int>(_parameters[2]) : 0;\r
std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear";\r
double value = boost::lexical_cast<double>(_parameters[1]);\r
//Perform loading of the clip\r
try\r
{\r
- _parameters[0] = _parameters[0];\r
auto pFP = create_producer(GetChannel()->mixer(), _parameters); \r
GetChannel()->stage()->load(GetLayerIndex(), pFP, true);\r
\r
//Perform loading of the clip\r
try\r
{\r
- _parameters[0] = _parameters[0];\r
auto pFP = create_producer(GetChannel()->mixer(), _parameters);\r
if(pFP == frame_producer::empty())\r
BOOST_THROW_EXCEPTION(file_not_found() << msg_info(_parameters.size() > 0 ? narrow(_parameters[0]) : ""));\r
}\r
catch(file_not_found&)\r
{ \r
- std::wstring params2;\r
- for(auto it = _parameters.begin(); it != _parameters.end(); ++it)\r
- params2 += L" " + *it;\r
- CASPAR_LOG(error) << L"File not found. No match found for parameters. Check syntax:" << params2;\r
+ CASPAR_LOG(error) << L"File not found. No match found for parameters. Check syntax:" << _parameters.get_original_string();\r
SetReplyString(TEXT("404 LOADBG ERROR\r\n"));\r
return false;\r
}\r
lbg.SetChannelIndex(GetChannelIndex());\r
lbg.SetLayerIntex(GetLayerIndex());\r
lbg.SetClientInfo(GetClientInfo());\r
- for(auto it = _parameters.begin(); it != _parameters.end(); ++it)\r
- lbg.AddParameter(*it);\r
+ lbg.SetParameters(_parameters);\r
if(!lbg.Execute())\r
throw std::exception();\r
}\r
\r
bool PrintCommand::DoExecute()\r
{\r
- GetChannel()->output()->add(create_consumer(boost::assign::list_of(L"IMAGE")));\r
+ parameters params;\r
+ params.push_back(L"IMAGE");\r
+ GetChannel()->output()->add(create_consumer(params));\r
\r
SetReplyString(TEXT("202 PRINT OK\r\n"));\r
\r
\r
if(_parameters[3].length() > 1) \r
{ //read label\r
- label = _parameters2[3];\r
+ label = _parameters.at_original(3);\r
++dataIndex;\r
\r
if(_parameters.size() > 4 && _parameters[4].length() > 0) //read play-on-load-flag\r
std::wstring dataFromFile;\r
if(_parameters.size() > dataIndex) \r
{ //read data\r
- const std::wstring& dataString = _parameters2[dataIndex];\r
+ const std::wstring& dataString = _parameters.at_original(dataIndex);\r
\r
if(dataString[0] == TEXT('<')) //the data is an XML-string\r
pDataString = dataString.c_str();\r
return false;\r
}\r
\r
- std::wstring dataString = _parameters2.at(2); \r
+ std::wstring dataString = _parameters.at_original(2);\r
if(dataString.at(0) != TEXT('<'))\r
{\r
//The data is not an XML-string, it must be a filename\r
return false;\r
}\r
int layer = _ttoi(_parameters[1].c_str());\r
- auto result = flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->invoke(layer, _parameters2[2]);\r
+ auto result = flash::get_default_cg_producer(safe_ptr<core::video_channel>(GetChannel()), GetLayerIndex(flash::cg_producer::DEFAULT_LAYER))->invoke(layer, _parameters.at_original(2));\r
replyString << result << TEXT("\r\n"); \r
}\r
else \r
}\r
\r
datafile << static_cast<wchar_t>(65279); // UTF-8 BOM character\r
- datafile << _parameters2[2] << std::flush;\r
+ datafile << _parameters.at_original(2) << std::flush;\r
datafile.close();\r
\r
std::wstring replyString = TEXT("202 DATA STORE OK\r\n");\r
std::wstringstream file_contents_stream(file_contents);\r
std::wstring line;\r
bool bFirstLine = true;\r
+ \r
while(std::getline(file_contents_stream, line))\r
{\r
if(!bFirstLine)\r
- reply << "\\n";\r
+ reply << "\n";\r
else\r
bFirstLine = false;\r
\r
}\r
else\r
{\r
- SetReplyString(L"500 THUMBNAIL GENERATE ERROR\r\n");\r
+ SetReplyString(L"501 THUMBNAIL GENERATE ERROR\r\n");\r
return false;\r
}\r
}\r
}\r
else\r
{\r
- SetReplyString(L"500 THUMBNAIL GENERATE_ALL ERROR\r\n");\r
+ SetReplyString(L"501 THUMBNAIL GENERATE_ALL ERROR\r\n");\r
return false;\r
}\r
}\r
\r
bool KillCommand::DoExecute()\r
{\r
- GetShutdownServerNow().set_value(false); // False for not waiting until a key is pressed before terminating.\r
+ GetShutdownServerNow().set_value(false); // False for not attempting to restart.\r
+ return true;\r
+}\r
+\r
+bool RestartCommand::DoExecute()\r
+{\r
+ GetShutdownServerNow().set_value(true); // True for attempting to restart\r
return true;\r
}\r
\r
} //namespace amcp\r
-}} //namespace caspar
\ No newline at end of file
+}} //namespace caspar\r