}
}
+bool KillCommand::DoExecute()
+{
+ shutdown_server_now_->set_value(false); //false for not waiting for keypress
+ SetReplyString(TEXT("202 KILL OK\r\n"));
+ return true;
+}
+
} //namespace amcp
}} //namespace caspar
\ No newline at end of file
#include "AMCPCommand.h"
+#include <boost/thread/future.hpp>
#include <core/thumbnail_generator.h>
namespace caspar { namespace protocol {
std::shared_ptr<core::thumbnail_generator> thumb_gen_;
};
+class KillCommand : public AMCPCommandBase<0>
+{
+public:
+ KillCommand(IO::ClientInfoPtr client, boost::promise<bool>& shutdown_server_now) : AMCPCommandBase(client), shutdown_server_now_(&shutdown_server_now) {}
+ std::wstring print() const { return L"KillCommand";}
+ bool DoExecute();
+
+private:
+ boost::promise<bool>* shutdown_server_now_;
+};
+
//class KillCommand : public AMCPCommand
//{
//public:
std::vector<channel_context> channels_;
std::vector<AMCPCommandQueue::ptr_type> commandQueues_;
std::shared_ptr<core::thumbnail_generator> thumb_gen_;
+ boost::promise<bool>& shutdown_server_now_;
public:
- impl(const std::vector<spl::shared_ptr<core::video_channel>>& channels, const std::shared_ptr<core::thumbnail_generator>& thumb_gen) : thumb_gen_(thumb_gen)
+ impl(const std::vector<spl::shared_ptr<core::video_channel>>& channels, const std::shared_ptr<core::thumbnail_generator>& thumb_gen, boost::promise<bool>& shutdown_server_now) : thumb_gen_(thumb_gen), shutdown_server_now_(shutdown_server_now)
{
commandQueues_.push_back(std::make_shared<AMCPCommandQueue>());
else if(s == TEXT("LOCK")) return std::make_shared<LockCommand>(client, channels_);
else if(s == TEXT("LOG")) return std::make_shared<LogCommand>(client);
else if(s == TEXT("THUMBNAIL")) return std::make_shared<ThumbnailCommand>(client, thumb_gen_);
- //else if(s == TEXT("KILL"))
- //{
- // result = AMCPCommandPtr(new KillCommand());
- //}
+ else if(s == TEXT("KILL")) return std::make_shared<KillCommand>(client, shutdown_server_now_);
return nullptr;
}
};
-AMCPProtocolStrategy::AMCPProtocolStrategy(const std::vector<spl::shared_ptr<core::video_channel>>& channels, const std::shared_ptr<core::thumbnail_generator>& thumb_gen) : impl_(spl::make_unique<impl>(channels, thumb_gen)) {}
+AMCPProtocolStrategy::AMCPProtocolStrategy(const std::vector<spl::shared_ptr<core::video_channel>>& channels, const std::shared_ptr<core::thumbnail_generator>& thumb_gen, boost::promise<bool>& shutdown_server_now) : impl_(spl::make_unique<impl>(channels, thumb_gen, shutdown_server_now)) {}
AMCPProtocolStrategy::~AMCPProtocolStrategy() {}
void AMCPProtocolStrategy::Parse(const std::wstring& msg, IO::ClientInfoPtr pClientInfo) { impl_->Parse(msg, pClientInfo); }
#include <common/memory.h>
#include <boost/noncopyable.hpp>
+#include <boost/thread/future.hpp>
#include <string>
class AMCPProtocolStrategy : public IO::IProtocolStrategy, boost::noncopyable
{
public:
- AMCPProtocolStrategy(const std::vector<spl::shared_ptr<core::video_channel>>& channels, const std::shared_ptr<core::thumbnail_generator>& thumb_gen);
+ AMCPProtocolStrategy(
+ const std::vector<spl::shared_ptr<core::video_channel>>& channels,
+ const std::shared_ptr<core::thumbnail_generator>& thumb_gen,
+ boost::promise<bool>& shutdown_server_now);
+
virtual ~AMCPProtocolStrategy();
virtual void Parse(const std::wstring& msg, IO::ClientInfoPtr pClientInfo);
#include <common/env.h>
#include <common/except.h>
-#include <common/except.h>
#include <common/log.h>
#include <common/gl/gl_check.h>
#include <common/os/windows/current_version.h>
#include <boost/foreach.hpp>
#include <boost/locale.hpp>
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/future.hpp>
+#include <boost/algorithm/string/case_conv.hpp>
#include <signal.h>
return EXCEPTION_CONTINUE_EXECUTION;
}
-void run()
+void do_run(server& caspar_server, boost::promise<bool>& shutdown_server_now)
{
- // Create server object which initializes channels, protocols and controllers.
- server caspar_server;
-
- auto server = spl::make_shared<protocol::osc::server>(5253);
- caspar_server.subscribe(server);
-
- //auto console_obs = reactive::make_observer([](const monitor::event& e)
- //{
- // std::stringstream str;
- // str << e;
- // CASPAR_LOG(trace) << str.str().c_str();
- //});
-
- //caspar_server.subscribe(console_obs);
-
// Create a dummy client which prints amcp responses to console.
auto console_client = spl::make_shared<IO::ConsoleClientInfo>();
// Create a amcp parser for console commands.
//protocol::amcp::AMCPProtocolStrategy amcp(caspar_server.channels());
- auto amcp = spl::make_shared<caspar::IO::delimiter_based_chunking_strategy_factory<wchar_t>>(L"\r\n", spl::make_shared<caspar::IO::legacy_strategy_adapter_factory>(spl::make_shared<protocol::amcp::AMCPProtocolStrategy>(caspar_server.channels(), caspar_server.get_thumbnail_generator())))->create(console_client);
+ auto amcp = spl::make_shared<caspar::IO::delimiter_based_chunking_strategy_factory<wchar_t>>(L"\r\n", spl::make_shared<caspar::IO::legacy_strategy_adapter_factory>(spl::make_shared<protocol::amcp::AMCPProtocolStrategy>(caspar_server.channels(), caspar_server.get_thumbnail_generator(), shutdown_server_now)))->create(console_client);
std::wstring wcmd;
while(true)
//boost::to_upper(wcmd);
if(boost::iequals(wcmd, L"EXIT") || boost::iequals(wcmd, L"Q") || boost::iequals(wcmd, L"QUIT") || boost::iequals(wcmd, L"BYE"))
+ {
+ shutdown_server_now.set_value(true); //true to wait for keypress
break;
+ }
try
{
wcmd += L"\r\n";
amcp->parse(wcmd);
- }
- CASPAR_LOG(info) << "Successfully shutdown CasparCG Server.";
+ }
+};
+
+bool run()
+{
+ boost::promise<bool> shutdown_server_now;
+ boost::unique_future<bool> shutdown_server = shutdown_server_now.get_future();
+
+ // Create server object which initializes channels, protocols and controllers.
+ server caspar_server(shutdown_server_now);
+
+ auto server = spl::make_shared<protocol::osc::server>(5253);
+ caspar_server.subscribe(server);
+
+ //auto console_obs = reactive::make_observer([](const monitor::event& e)
+ //{
+ // std::stringstream str;
+ // str << e;
+ // CASPAR_LOG(trace) << str.str().c_str();
+ //});
+
+ //caspar_server.subscribe(console_obs);
+
+
+ // Use separate thread for the blocking console input, will be terminated
+ // anyway when the main thread terminates.
+ boost::thread stdin_thread(std::bind(do_run, std::ref(caspar_server), std::ref(shutdown_server_now))); //compiler didn't like lambda here...
+ stdin_thread.detach();
+ return shutdown_server.get();
}
void on_abort(int)
boost::property_tree::write_xml(str, env::properties(), w);
CASPAR_LOG(info) << L"casparcg.config:\n-----------------------------------------\n" << str.str().c_str() << L"-----------------------------------------";
- run();
+ auto wait = run();
- system("pause");
+ Sleep(500);
+ CASPAR_LOG(info) << "Successfully shutdown CasparCG Server.";
+
+ if(wait) system("pause");
}
catch(boost::property_tree::file_parser_error&)
{
std::vector<spl::shared_ptr<IO::AsyncEventServer>> async_servers_;
std::vector<spl::shared_ptr<video_channel>> channels_;
std::shared_ptr<thumbnail_generator> thumbnail_generator_;
+ boost::promise<bool>& shutdown_server_now_;
- impl()
- : accelerator_(env::properties().get(L"configuration.accelerator", L"auto"))
+ explicit impl(boost::promise<bool>& shutdown_server_now)
+ : accelerator_(env::properties().get(L"configuration.accelerator", L"auto")), shutdown_server_now_(shutdown_server_now)
{
ffmpeg::init();
using namespace IO;
if(boost::iequals(name, L"AMCP"))
- return wrap_legacy_protocol("\r\n", spl::make_shared<amcp::AMCPProtocolStrategy>(channels_, thumbnail_generator_));
+ return wrap_legacy_protocol("\r\n", spl::make_shared<amcp::AMCPProtocolStrategy>(channels_, thumbnail_generator_, shutdown_server_now_));
else if(boost::iequals(name, L"CII"))
return wrap_legacy_protocol("\r\n", spl::make_shared<cii::CIIProtocolStrategy>(channels_));
else if(boost::iequals(name, L"CLOCK"))
};
-server::server() : impl_(new impl()){}
+server::server(boost::promise<bool>& shutdown_server_now) : impl_(new impl(shutdown_server_now)){}
const std::vector<spl::shared_ptr<video_channel>> server::channels() const
{
#include <core/monitor/monitor.h>
#include <boost/noncopyable.hpp>
+#include <boost/thread/future.hpp>
#include <vector>
, boost::noncopyable
{
public:
- server();
+ explicit server(boost::promise<bool>& shutdown_server_now);
const std::vector<spl::shared_ptr<core::video_channel>> channels() const;
std::shared_ptr<core::thumbnail_generator> get_thumbnail_generator() const;
// monitor::observable