X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=protocol%2Famcp%2FAMCPCommandsImpl.cpp;h=69826476d6e7c443c2ede347314a0bd5c3c0589f;hb=a9baf9ba1e7e4b94b5e08385328441de6607ad23;hp=cc7613facb9ed3c06f8f6c1523dc6cb3d1f9a623;hpb=623472e30864f882aa703c04ca916148d33a77cd;p=casparcg diff --git a/protocol/amcp/AMCPCommandsImpl.cpp b/protocol/amcp/AMCPCommandsImpl.cpp index cc7613fac..69826476d 100644 --- a/protocol/amcp/AMCPCommandsImpl.cpp +++ b/protocol/amcp/AMCPCommandsImpl.cpp @@ -1,1450 +1,3103 @@ -/* -* copyright (c) 2010 Sveriges Television AB -* -* This file is part of CasparCG. -* -* 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 . -* -*/ - -#include "../StdAfx.h" - -#if defined(_MSC_VER) -#pragma warning (push, 1) // TODO: Legacy code, just disable warnings -#endif - -#include "AMCPCommandsImpl.h" -#include "AMCPProtocolStrategy.h" - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* Return codes - -100 [action] Information om att något har hänt -101 [action] Information om att något har hänt, en rad data skickas - -202 [kommando] OK Kommandot har utförts -201 [kommando] OK Kommandot har utförts, och en rad data skickas tillbaka -200 [kommando] OK Kommandot har utförts, och flera rader data skickas tillbaka. Avslutas med tomrad - -400 ERROR Kommandot kunde inte förstås -401 [kommando] ERROR Ogiltig kanal -402 [kommando] ERROR Parameter saknas -403 [kommando] ERROR Ogiltig parameter -404 [kommando] ERROR Mediafilen hittades inte - -500 FAILED Internt configurationfel -501 [kommando] FAILED Internt configurationfel -502 [kommando] FAILED Oläslig mediafil - -600 [kommando] FAILED funktion ej implementerad -*/ - -namespace caspar { namespace protocol { - -using namespace core; - -std::wstring MediaInfo(const boost::filesystem::wpath& path) -{ - if(boost::filesystem::is_regular_file(path)) - { - std::wstring clipttype = TEXT(" N/A "); - std::wstring extension = boost::to_upper_copy(path.extension()); - if(extension == TEXT(".TGA") || extension == TEXT(".COL") || extension == L".PNG" || extension == L".JPEG" || extension == L".JPG" || - extension == L"GIF" || extension == L"BMP") - clipttype = TEXT(" STILL "); - else if(extension == TEXT(".SWF") || extension == TEXT(".DV") || extension == TEXT(".MOV") || extension == TEXT(".MPG") || - extension == TEXT(".AVI") || extension == TEXT(".FLV") || extension == TEXT(".F4V") || extension == TEXT(".MP4") || - extension == L".M2V" || extension == L".H264" || extension == L".MKV" || extension == L".WMV" || extension == L".DIVX" || - extension == L".XVID" || extension == L".OGG" || extension == L".CT") - clipttype = TEXT(" MOVIE "); - else if(extension == TEXT(".WAV") || extension == TEXT(".MP3")) - clipttype = TEXT(" STILL "); - - if(clipttype != TEXT(" N/A ")) - { - auto is_not_digit = [](char c){ return std::isdigit(c) == 0; }; - - auto relativePath = boost::filesystem::wpath(path.file_string().substr(env::media_folder().size()-1, path.file_string().size())); - - auto writeTimeStr = boost::posix_time::to_iso_string(boost::posix_time::from_time_t(boost::filesystem::last_write_time(path))); - writeTimeStr.erase(std::remove_if(writeTimeStr.begin(), writeTimeStr.end(), is_not_digit), writeTimeStr.end()); - auto writeTimeWStr = std::wstring(writeTimeStr.begin(), writeTimeStr.end()); - - auto sizeStr = boost::lexical_cast(boost::filesystem::file_size(path)); - sizeStr.erase(std::remove_if(sizeStr.begin(), sizeStr.end(), is_not_digit), sizeStr.end()); - auto sizeWStr = std::wstring(sizeStr.begin(), sizeStr.end()); - - auto str = relativePath.replace_extension(TEXT("")).external_file_string(); - if(str[0] == '\\' || str[0] == '/') - str = std::wstring(str.begin() + 1, str.end()); - - return std::wstring() + TEXT("\"") + str + - + TEXT("\" ") + clipttype + - + TEXT(" ") + sizeStr + - + TEXT(" ") + writeTimeWStr + - + TEXT("\r\n"); - } - } - return L""; -} - -std::wstring ListMedia() -{ - std::wstringstream replyString; - for (boost::filesystem::wrecursive_directory_iterator itr(env::media_folder()), end; itr != end; ++itr) - replyString << MediaInfo(itr->path()); - - return boost::to_upper_copy(replyString.str()); -} - -std::wstring ListTemplates() -{ - std::wstringstream replyString; - - for (boost::filesystem::wrecursive_directory_iterator itr(env::template_folder()), end; itr != end; ++itr) - { - if(boost::filesystem::is_regular_file(itr->path()) && (itr->path().extension() == L".ft" || itr->path().extension() == L".ct")) - { - auto relativePath = boost::filesystem::wpath(itr->path().file_string().substr(env::template_folder().size()-1, itr->path().file_string().size())); - - auto writeTimeStr = boost::posix_time::to_iso_string(boost::posix_time::from_time_t(boost::filesystem::last_write_time(itr->path()))); - writeTimeStr.erase(std::remove_if(writeTimeStr.begin(), writeTimeStr.end(), [](char c){ return std::isdigit(c) == 0;}), writeTimeStr.end()); - auto writeTimeWStr = std::wstring(writeTimeStr.begin(), writeTimeStr.end()); - - auto sizeStr = boost::lexical_cast(boost::filesystem::file_size(itr->path())); - sizeStr.erase(std::remove_if(sizeStr.begin(), sizeStr.end(), [](char c){ return std::isdigit(c) == 0;}), sizeStr.end()); - - auto sizeWStr = std::wstring(sizeStr.begin(), sizeStr.end()); - - std::wstring dir = relativePath.parent_path().external_directory_string(); - std::wstring file = boost::to_upper_copy(relativePath.filename()); - relativePath = boost::filesystem::wpath(dir + L"/" + file); - - auto str = relativePath.replace_extension(TEXT("")).external_file_string(); - if(str[0] == '\\' || str[0] == '/') - str = std::wstring(str.begin() + 1, str.end()); - - replyString << TEXT("\"") << str - << TEXT("\" ") << sizeWStr - << TEXT(" ") << writeTimeWStr - << TEXT("\r\n"); - } - } - return replyString.str(); -} - -namespace amcp { - -AMCPCommand::AMCPCommand() : channelIndex_(0), scheduling_(Default), layerIndex_(-1) -{} - -void AMCPCommand::SendReply() -{ - if(!pClientInfo_) - return; - - if(replyString_.empty()) - return; - pClientInfo_->Send(replyString_); -} - -void AMCPCommand::Clear() -{ - pChannel_->stage()->clear(); - pClientInfo_.reset(); - channelIndex_ = 0; - _parameters.clear(); -} - -bool DiagnosticsCommand::DoExecute() -{ - try - { - diagnostics::show_graphs(true); - - SetReplyString(TEXT("202 DIAG OK\r\n")); - - return true; - } - catch(...) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("502 DIAG FAILED\r\n")); - return false; - } -} - -bool CallCommand::DoExecute() -{ - //Perform loading of the clip - try - { - auto what = _parameters.at(0); - - std::wstring param = _parameters2.at(1); - for(auto it = std::begin(_parameters2)+2; it != std::end(_parameters2); ++it) - param += L" " + *it; - - boost::unique_future result; - if(what == L"B") - result = GetChannel()->stage()->call(GetLayerIndex(), false, param); - else if(what == L"F") - result = GetChannel()->stage()->call(GetLayerIndex(), true, param); - else - result = GetChannel()->stage()->call(GetLayerIndex(), true, _parameters.at(0) + L" " + param); - - if(!result.timed_wait(boost::posix_time::seconds(2))) - BOOST_THROW_EXCEPTION(timed_out()); - - CASPAR_LOG(info) << "Executed call: " << _parameters[0] << TEXT(" successfully"); - - std::wstringstream replyString; - replyString << TEXT("201 CALL OK\r\n") << result.get() << L"\r\n"; - - SetReplyString(replyString.str()); - - return true; - } - catch(...) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("502 CALL FAILED\r\n")); - return false; - } -} - -bool MixerCommand::DoExecute() -{ - //Perform loading of the clip - try - { - if(_parameters[0] == L"KEYER" || _parameters[0] == L"IS_KEY") - { - bool value = lexical_cast_or_default(_parameters.at(1), false); - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.is_key = value; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform); - } - else if(_parameters[0] == L"OPACITY") - { - int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; - std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - - double value = boost::lexical_cast(_parameters.at(1)); - - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.opacity = value; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); - } - else if(_parameters[0] == L"FILL" || _parameters[0] == L"FILL_RECT") - { - int duration = _parameters.size() > 5 ? lexical_cast_or_default(_parameters[5], 0) : 0; - std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear"; - double x = boost::lexical_cast(_parameters.at(1)); - double y = boost::lexical_cast(_parameters.at(2)); - double x_s = boost::lexical_cast(_parameters.at(3)); - double y_s = boost::lexical_cast(_parameters.at(4)); - - auto transform = [=](frame_transform transform) mutable -> frame_transform - { - transform.fill_translation[0] = x; - transform.fill_translation[1] = y; - transform.fill_scale[0] = x_s; - transform.fill_scale[1] = y_s; - transform.clip_translation[0] = x; - transform.clip_translation[1] = y; - transform.clip_scale[0] = x_s; - transform.clip_scale[1] = y_s; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); - } - else if(_parameters[0] == L"CLIP" || _parameters[0] == L"CLIP_RECT") - { - int duration = _parameters.size() > 5 ? lexical_cast_or_default(_parameters[5], 0) : 0; - std::wstring tween = _parameters.size() > 6 ? _parameters[6] : L"linear"; - double x = boost::lexical_cast(_parameters.at(1)); - double y = boost::lexical_cast(_parameters.at(2)); - double x_s = boost::lexical_cast(_parameters.at(3)); - double y_s = boost::lexical_cast(_parameters.at(4)); - - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.clip_translation[0] = x; - transform.clip_translation[1] = y; - transform.clip_scale[0] = x_s; - transform.clip_scale[1] = y_s; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); - } - else if(_parameters[0] == L"GRID") - { - int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; - std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - int n = boost::lexical_cast(_parameters.at(1)); - double delta = 1.0/static_cast(n); - for(int x = 0; x < n; ++x) - { - for(int y = 0; y < n; ++y) - { - int index = x+y*n+1; - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.fill_translation[0] = x*delta; - transform.fill_translation[1] = y*delta; - transform.fill_scale[0] = delta; - transform.fill_scale[1] = delta; - transform.clip_translation[0] = x*delta; - transform.clip_translation[1] = y*delta; - transform.clip_scale[0] = delta; - transform.clip_scale[1] = delta; - return transform; - }; - GetChannel()->mixer()->apply_frame_transform(index, transform, duration, tween); - } - } - } - else if(_parameters[0] == L"BLEND") - { - auto blend_str = _parameters.at(1); - int layer = GetLayerIndex(); - GetChannel()->mixer()->set_blend_mode(GetLayerIndex(), get_blend_mode(blend_str)); - } - else if(_parameters[0] == L"BRIGHTNESS") - { - auto value = boost::lexical_cast(_parameters.at(1)); - int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; - std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.brightness = value; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); - } - else if(_parameters[0] == L"SATURATION") - { - auto value = boost::lexical_cast(_parameters.at(1)); - int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; - std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.saturation = value; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); - } - else if(_parameters[0] == L"CONTRAST") - { - auto value = boost::lexical_cast(_parameters.at(1)); - int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; - std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.contrast = value; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); - } - else if(_parameters[0] == L"LEVELS") - { - levels value; - value.min_input = boost::lexical_cast(_parameters.at(1)); - value.max_input = boost::lexical_cast(_parameters.at(2)); - value.gamma = boost::lexical_cast(_parameters.at(3)); - value.min_output = boost::lexical_cast(_parameters.at(4)); - value.max_output = boost::lexical_cast(_parameters.at(5)); - int duration = _parameters.size() > 6 ? lexical_cast_or_default(_parameters[6], 0) : 0; - std::wstring tween = _parameters.size() > 7 ? _parameters[7] : L"linear"; - - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.levels = value; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); - } - else if(_parameters[0] == L"VOLUME") - { - int duration = _parameters.size() > 2 ? lexical_cast_or_default(_parameters[2], 0) : 0; - std::wstring tween = _parameters.size() > 3 ? _parameters[3] : L"linear"; - double value = boost::lexical_cast(_parameters[1]); - - auto transform = [=](frame_transform transform) -> frame_transform - { - transform.volume = value; - return transform; - }; - - int layer = GetLayerIndex(); - GetChannel()->mixer()->apply_frame_transform(GetLayerIndex(), transform, duration, tween); - } - else if(_parameters[0] == L"CLEAR") - { - int layer = GetLayerIndex(std::numeric_limits::max()); - if(layer == std::numeric_limits::max()) - GetChannel()->mixer()->clear_transforms(); - else - GetChannel()->mixer()->clear_transforms(layer); - } - else - { - SetReplyString(TEXT("404 MIXER ERROR\r\n")); - return false; - } - - SetReplyString(TEXT("202 MIXER OK\r\n")); - - return true; - } - catch(file_not_found&) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("404 MIXER ERROR\r\n")); - return false; - } - catch(...) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("502 MIXER FAILED\r\n")); - return false; - } -} - -bool SwapCommand::DoExecute() -{ - //Perform loading of the clip - try - { - if(GetLayerIndex(-1) != -1) - { - std::vector strs; - boost::split(strs, _parameters[0], boost::is_any_of("-")); - - auto ch1 = GetChannel(); - auto ch2 = GetChannels().at(boost::lexical_cast(strs.at(0))-1); - - int l1 = GetLayerIndex(); - int l2 = boost::lexical_cast(strs.at(1)); - - ch1->stage()->swap_layer(l1, l2, ch2->stage()); - } - else - { - auto ch1 = GetChannel(); - auto ch2 = GetChannels().at(boost::lexical_cast(_parameters[0])-1); - ch1->stage()->swap_layers(ch2->stage()); - } - - CASPAR_LOG(info) << "Swapped successfully"; - - SetReplyString(TEXT("202 SWAP OK\r\n")); - - return true; - } - catch(file_not_found&) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("404 SWAP ERROR\r\n")); - return false; - } - catch(...) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("502 SWAP FAILED\r\n")); - return false; - } -} - -bool AddCommand::DoExecute() -{ - //Perform loading of the clip - try - { - auto consumer = create_consumer(_parameters); - GetChannel()->output()->add(GetLayerIndex(consumer->index()), consumer); - - CASPAR_LOG(info) << "Added " << _parameters[0] << TEXT(" successfully"); - - SetReplyString(TEXT("202 ADD OK\r\n")); - - return true; - } - catch(file_not_found&) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("404 ADD ERROR\r\n")); - return false; - } - catch(...) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("502 ADD FAILED\r\n")); - return false; - } -} - -bool RemoveCommand::DoExecute() -{ - //Perform loading of the clip - try - { - auto index = GetLayerIndex(std::numeric_limits::min()); - if(index == std::numeric_limits::min()) - index = create_consumer(_parameters)->index(); - - GetChannel()->output()->remove(index); - - SetReplyString(TEXT("202 REMOVE OK\r\n")); - - return true; - } - catch(file_not_found&) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("404 REMOVE ERROR\r\n")); - return false; - } - catch(...) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("502 REMOVE FAILED\r\n")); - return false; - } -} - -bool LoadCommand::DoExecute() -{ - //Perform loading of the clip - try - { - _parameters[0] = _parameters[0]; - auto pFP = create_producer(GetChannel()->mixer(), _parameters); - GetChannel()->stage()->load(GetLayerIndex(), pFP, true); - - CASPAR_LOG(info) << "Loaded " << _parameters[0] << TEXT(" successfully"); - - SetReplyString(TEXT("202 LOAD OK\r\n")); - - return true; - } - catch(file_not_found&) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("404 LOAD ERROR\r\n")); - return false; - } - catch(...) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - SetReplyString(TEXT("502 LOAD FAILED\r\n")); - return false; - } -} - - - -//std::function channel_cg_add_command::parse(const std::wstring& message, const std::vector& channels) -//{ -// static boost::wregex expr(L"^CG\\s(?\\d+)-?(?\\d+)?\\sADD\\s(?\\d+)\\s(?