\r
struct invalid_operation : virtual caspar_exception {};\r
struct operation_failed : virtual caspar_exception {};\r
+struct timed_out : virtual caspar_exception {};\r
\r
struct not_supported : virtual caspar_exception {};\r
struct not_implemented : virtual caspar_exception {};\r
}\r
}\r
\r
- virtual safe_ptr<basic_frame> receive(int hints) override {return (*producer_)->receive(hints);}\r
- virtual safe_ptr<basic_frame> last_frame() const override {return (*producer_)->last_frame();}\r
- virtual std::wstring print() const override {return (*producer_)->print();}\r
- virtual std::wstring call(const std::wstring& str) override {return (*producer_)->call(str);}\r
- virtual safe_ptr<frame_producer> get_following_producer() const override {return (*producer_)->get_following_producer();}\r
- virtual void set_leading_producer(const safe_ptr<frame_producer>& producer) override {(*producer_)->set_leading_producer(producer);}\r
- virtual int64_t nb_frames() const override {return (*producer_)->nb_frames();}\r
+ virtual safe_ptr<basic_frame> receive(int hints) override {return (*producer_)->receive(hints);}\r
+ virtual safe_ptr<basic_frame> last_frame() const override {return (*producer_)->last_frame();}\r
+ virtual std::wstring print() const override {return (*producer_)->print();}\r
+ virtual boost::unique_future<std::wstring> call(const std::wstring& str) override {return (*producer_)->call(str);}\r
+ virtual safe_ptr<frame_producer> get_following_producer() const override {return (*producer_)->get_following_producer();}\r
+ virtual void set_leading_producer(const safe_ptr<frame_producer>& producer) override {(*producer_)->set_leading_producer(producer);}\r
+ virtual int64_t nb_frames() const override {return (*producer_)->nb_frames();}\r
};\r
\r
safe_ptr<core::frame_producer> create_destroy_proxy(safe_ptr<core::frame_producer>&& producer)\r
#include <stdint.h>\r
#include <numeric>\r
\r
+#include <boost/thread/future.hpp>\r
+\r
namespace caspar { \r
\r
class executor;\r
\r
virtual std::wstring print() const = 0; // nothrow\r
\r
- virtual std::wstring call(const std::wstring&) {return L"";}\r
+ virtual boost::unique_future<std::wstring> call(const std::wstring&) \r
+ {\r
+ boost::promise<std::wstring> promise;\r
+ promise.set_value(L"");\r
+ return promise.get_future();\r
+ }\r
\r
virtual safe_ptr<frame_producer> get_following_producer() const {return frame_producer::empty();} // nothrow\r
virtual void set_leading_producer(const safe_ptr<frame_producer>&) {} // nothrow\r
return status;\r
}\r
\r
- std::wstring call(bool foreground, const std::wstring& param)\r
+ boost::unique_future<std::wstring> call(bool foreground, const std::wstring& param)\r
{\r
return (foreground ? foreground_ : background_)->call(param);\r
}\r
safe_ptr<frame_producer> layer::foreground() const { return impl_->foreground_;}\r
safe_ptr<frame_producer> layer::background() const { return impl_->background_;}\r
bool layer::empty() const {return impl_->empty();}\r
-std::wstring layer::call(bool foreground, const std::wstring& param){return impl_->call(foreground, param);}\r
+boost::unique_future<std::wstring> layer::call(bool foreground, const std::wstring& param){return impl_->call(foreground, param);}\r
}}
\ No newline at end of file
#include <common/memory/safe_ptr.h>\r
\r
#include <boost/noncopyable.hpp>\r
+#include <boost/thread/future.hpp>\r
\r
#include <string>\r
\r
void play(); // nothrow\r
void pause(); // nothrow\r
void stop(); // nothrow\r
- std::wstring call(bool foreground, const std::wstring& param);\r
+ boost::unique_future<std::wstring> call(bool foreground, const std::wstring& param);\r
\r
bool is_paused() const;\r
int64_t frame_number() const;\r
{\r
return std::numeric_limits<int>::max();\r
}\r
+ \r
+ virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
+ {\r
+ boost::promise<std::wstring> promise;\r
+ promise.set_value(do_call(param));\r
+ return promise.get_future();\r
+ } \r
\r
- virtual std::wstring call(const std::wstring& param) override\r
+ // playlist_producer\r
+\r
+ std::wstring do_call(const std::wstring& param)\r
{ \r
static const boost::wregex push_front_exp (L"PUSH_FRONT (?<PARAM>.+)"); \r
static const boost::wregex push_back_exp (L"(PUSH_BACK|PUSH) (?<PARAM>.+)");\r
\r
BOOST_THROW_EXCEPTION(invalid_argument());\r
}\r
-\r
- // playlist_producer\r
\r
std::wstring push_front(const std::wstring& str)\r
{\r
\r
safe_ptr<frame_producer> create_playlist_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
{\r
- if(boost::range::find(params, L"PLAYLIST") == params.end())\r
+ if(boost::range::find(params, L"[PLAYLIST]") == params.end())\r
return core::frame_producer::empty();\r
\r
bool loop = boost::range::find(params, L"LOOP") != params.end();\r
}, high_priority);\r
} \r
\r
- std::wstring call(int index, bool foreground, const std::wstring& param)\r
+ boost::unique_future<std::wstring> call(int index, bool foreground, const std::wstring& param)\r
{\r
- return executor_.invoke([&]\r
+ return std::move(*executor_.invoke([&]() -> std::shared_ptr<boost::unique_future<std::wstring>>\r
{\r
- return layers_[index].call(foreground, param);\r
- }, high_priority);\r
+ return std::make_shared<boost::unique_future<std::wstring>>(std::move(layers_[index].call(foreground, param)));\r
+ }, high_priority));\r
}\r
\r
void swap_layer(int index, size_t other_index)\r
safe_ptr<frame_producer> stage::foreground(size_t index) {return impl_->foreground(index);}\r
safe_ptr<frame_producer> stage::background(size_t index) {return impl_->background(index);}\r
void stage::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
-std::wstring stage::call(int index, bool foreground, const std::wstring& param){return impl_->call(index, foreground, param);}\r
+boost::unique_future<std::wstring> stage::call(int index, bool foreground, const std::wstring& param){return impl_->call(index, foreground, param);}\r
}}
\ No newline at end of file
void stop(int index);\r
void clear(int index);\r
void clear(); \r
- std::wstring call(int index, bool foreground, const std::wstring& param);\r
+ boost::unique_future<std::wstring> call(int index, bool foreground, const std::wstring& param);\r
void swap_layer(int index, size_t other_index);\r
void swap_layer(int index, size_t other_index, stage& other);\r
\r
return nb_frames - start_;\r
}\r
\r
- virtual std::wstring call(const std::wstring& param) override\r
+ virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
+ {\r
+ boost::promise<std::wstring> promise;\r
+ promise.set_value(do_call(param));\r
+ return promise.get_future();\r
+ }\r
+ \r
+ virtual std::wstring print() const override\r
+ {\r
+ if(video_decoder_)\r
+ {\r
+ return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"|" \r
+ + boost::lexical_cast<std::wstring>(video_decoder_->width()) + L"x" + boost::lexical_cast<std::wstring>(video_decoder_->height())\r
+ + (video_decoder_->is_progressive() ? L"p" : L"i") + boost::lexical_cast<std::wstring>(video_decoder_->is_progressive() ? video_decoder_->fps() : 2.0 * video_decoder_->fps())\r
+ + L"]";\r
+ }\r
+ \r
+ return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"]";\r
+ }\r
+\r
+ // ffmpeg_producer\r
+ \r
+ std::wstring do_call(const std::wstring& param)\r
{\r
static const boost::wregex loop_exp(L"LOOP\\s*(?<VALUE>\\d?)");\r
static const boost::wregex seek_exp(L"SEEK\\s+(?<VALUE>\\d+)");\r
\r
BOOST_THROW_EXCEPTION(invalid_argument());\r
}\r
- \r
- virtual std::wstring print() const override\r
- {\r
- if(video_decoder_)\r
- {\r
- return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"|" \r
- + boost::lexical_cast<std::wstring>(video_decoder_->width()) + L"x" + boost::lexical_cast<std::wstring>(video_decoder_->height())\r
- + (video_decoder_->is_progressive() ? L"p" : L"i") + boost::lexical_cast<std::wstring>(video_decoder_->is_progressive() ? video_decoder_->fps() : 2.0 * video_decoder_->fps())\r
- + L"]";\r
- }\r
- \r
- return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"]";\r
- }\r
\r
- // ffmpeg_producer\r
- \r
void try_decode_frame(int hints)\r
{\r
std::shared_ptr<AVPacket> pkt;\r
void init()\r
{\r
core::register_producer_factory(create_ct_producer);\r
+ core::register_producer_factory(create_cg_producer);\r
}\r
\r
std::wstring get_cg_version()\r
for(size_t retries = 0; !bCallSuccessful_ && retries < 4; ++retries)\r
spFlash->CallFunction(request, &result);\r
\r
- result2 = result;\r
+ if(bCallSuccessful_)\r
+ result2 = result;\r
\r
return bCallSuccessful_;\r
}\r
: flash_producer_(frame_producer)\r
{}\r
\r
- std::wstring add(int layer, std::wstring filename, bool play_on_load, const std::wstring& label, const std::wstring& data)\r
+ boost::unique_future<std::wstring> add(int layer, std::wstring filename, bool play_on_load, const std::wstring& label, const std::wstring& data)\r
{\r
if(filename.size() > 0 && filename[0] == L'/')\r
filename = filename.substr(1, filename.size()-1);\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring remove(int layer)\r
+ boost::unique_future<std::wstring> remove(int layer)\r
{\r
auto str = (boost::wformat(L"<invoke name=\"Delete\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();\r
CASPAR_LOG(info) << flash_producer_->print() << " Invoking remove-command: " << str;\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring play(int layer)\r
+ boost::unique_future<std::wstring> play(int layer)\r
{\r
auto str = (boost::wformat(L"<invoke name=\"Play\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();\r
CASPAR_LOG(info) << flash_producer_->print() << " Invoking play-command: " << str;\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring stop(int layer, unsigned int)\r
+ boost::unique_future<std::wstring> stop(int layer, unsigned int)\r
{\r
auto str = (boost::wformat(L"<invoke name=\"Stop\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array><number>0</number></arguments></invoke>") % layer).str();\r
CASPAR_LOG(info) << flash_producer_->print() << " Invoking stop-command: " << str;\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring next(int layer)\r
+ boost::unique_future<std::wstring> next(int layer)\r
{\r
auto str = (boost::wformat(L"<invoke name=\"Next\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();\r
CASPAR_LOG(info) << flash_producer_->print() << " Invoking next-command: " << str;\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring update(int layer, const std::wstring& data)\r
+ boost::unique_future<std::wstring> update(int layer, const std::wstring& data)\r
{\r
auto str = (boost::wformat(L"<invoke name=\"SetData\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array><string><![CDATA[%2%]]></string></arguments></invoke>") % layer % data).str();\r
CASPAR_LOG(info) << flash_producer_->print() <<" Invoking update-command: " << str;\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring invoke(int layer, const std::wstring& label)\r
+ boost::unique_future<std::wstring> invoke(int layer, const std::wstring& label)\r
{\r
auto str = (boost::wformat(L"<invoke name=\"Invoke\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array><string>%2%</string></arguments></invoke>") % layer % label).str();\r
CASPAR_LOG(info) << flash_producer_->print() << " Invoking invoke-command: " << str;\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring description(int layer)\r
+ boost::unique_future<std::wstring> description(int layer)\r
{\r
auto str = (boost::wformat(L"<invoke name=\"GetDescription\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();\r
CASPAR_LOG(info) << flash_producer_->print() << " Invoking description-command: " << str;\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring info()\r
+ boost::unique_future<std::wstring> info()\r
{\r
auto str = (boost::wformat(L"<invoke name=\"GetInfo\" returntype=\"xml\"><arguments></arguments></invoke>")).str();\r
CASPAR_LOG(info) << flash_producer_->print() << " Invoking info-command: " << str;\r
return flash_producer_->call(str);\r
}\r
\r
- std::wstring call(const std::wstring& str)\r
+ boost::unique_future<std::wstring> call(const std::wstring& str)\r
{ \r
static const boost::wregex add_exp (L"ADD (?<LAYER>\\d+) (?<FILENAME>[^\\s]+) (?<PLAY_ON_LOAD>\\d)( (?<DATA>.*))?");\r
static const boost::wregex remove_exp (L"REMOVE (?<LAYER>\\d+)");\r
\r
boost::wsmatch what;\r
if(boost::regex_match(str, what, add_exp))\r
- return add(boost::lexical_cast<int>(what["LAYER"].str()), what["FILENAME"].str(), boost::lexical_cast<bool>(what["PLAY_ON_LOAD"].str()), L"", what["DATA"].str()); \r
+ return add(boost::lexical_cast<int>(what["LAYER"].str()), flash::find_template(env::template_folder() + what["FILENAME"].str()), boost::lexical_cast<bool>(what["PLAY_ON_LOAD"].str()), L"", what["DATA"].str()); \r
else if(boost::regex_match(str, what, remove_exp))\r
return remove(boost::lexical_cast<int>(what["LAYER"].str())); \r
else if(boost::regex_match(str, what, stop_exp))\r
{\r
return flash_producer_->print();\r
}\r
+\r
+ std::wstring timed_invoke(int layer, const std::wstring& label)\r
+ {\r
+ auto result = invoke(layer, label);\r
+ if(result.timed_wait(boost::posix_time::seconds(2)))\r
+ return result.get();\r
+ return L"";\r
+ }\r
+ std::wstring timed_description(int layer)\r
+ {\r
+ auto result = description(layer);\r
+ if(result.timed_wait(boost::posix_time::seconds(2)))\r
+ return result.get();\r
+ return L"";\r
+ }\r
+ std::wstring timed_info()\r
+ {\r
+ auto result = info();\r
+ if(result.timed_wait(boost::posix_time::seconds(2)))\r
+ return result.get();\r
+ return L"";\r
+ }\r
};\r
\r
safe_ptr<cg_producer> get_default_cg_producer(const safe_ptr<core::video_channel>& video_channel, int render_layer)\r
\r
if(flash_producer->print().find(L"flash[") == std::string::npos) // UGLY hack\r
{\r
- flash_producer = flash::create_producer(video_channel->mixer(), boost::assign::list_of<std::wstring>()); \r
+ flash_producer = make_safe<cg_producer>(flash::create_producer(video_channel->mixer(), boost::assign::list_of<std::wstring>())); \r
video_channel->stage()->load(render_layer, flash_producer); \r
video_channel->stage()->play(render_layer);\r
}\r
\r
- return make_safe<cg_producer>(flash_producer);\r
+ return static_pointer_cast<cg_producer>(flash_producer);\r
}\r
\r
safe_ptr<core::frame_producer> create_ct_producer(const safe_ptr<core::frame_factory> frame_factory, const std::vector<std::wstring>& params) \r
return producer;\r
}\r
\r
+safe_ptr<core::frame_producer> create_cg_producer(const safe_ptr<core::frame_factory> frame_factory, const std::vector<std::wstring>& params) \r
+{\r
+ if(params.empty() || params.at(0) != L"[CG]")\r
+ return core::frame_producer::empty();\r
+\r
+ return make_safe<cg_producer>(flash::create_producer(frame_factory, boost::assign::list_of<std::wstring>())); \r
+}\r
+\r
cg_producer::cg_producer(const safe_ptr<core::frame_producer>& frame_producer) : impl_(new implementation(frame_producer)){}\r
cg_producer::cg_producer(cg_producer&& other) : impl_(std::move(other.impl_)){}\r
safe_ptr<core::basic_frame> cg_producer::receive(int hints){return impl_->receive(hints);}\r
void cg_producer::stop(int layer, unsigned int mix_out_duration){impl_->stop(layer, mix_out_duration);}\r
void cg_producer::next(int layer){impl_->next(layer);}\r
void cg_producer::update(int layer, const std::wstring& data){impl_->update(layer, data);}\r
-std::wstring cg_producer::invoke(int layer, const std::wstring& label){return impl_->invoke(layer, label);}\r
std::wstring cg_producer::print() const{return impl_->print();}\r
-std::wstring cg_producer::call(const std::wstring& str){return impl_->call(str);}\r
-std::wstring cg_producer::description(int layer){return impl_->description(layer);}\r
-std::wstring cg_producer::info(){return impl_->info();}\r
+boost::unique_future<std::wstring> cg_producer::call(const std::wstring& str){return impl_->call(str);}\r
+std::wstring cg_producer::invoke(int layer, const std::wstring& label){return impl_->timed_invoke(layer, label);}\r
+std::wstring cg_producer::description(int layer){return impl_->timed_description(layer);}\r
+std::wstring cg_producer::info(){return impl_->timed_info();}\r
\r
}}
\ No newline at end of file
#include <core/video_format.h>\r
#include <core/video_channel.h>\r
\r
+#include <boost/thread/future.hpp>\r
+\r
#include <string>\r
\r
namespace caspar { namespace flash {\r
virtual safe_ptr<core::basic_frame> receive(int) override;\r
virtual safe_ptr<core::basic_frame> last_frame() const override;\r
virtual std::wstring print() const override;\r
- virtual std::wstring call(const std::wstring&) override;\r
+ virtual boost::unique_future<std::wstring> call(const std::wstring&) override;\r
\r
//cg_producer\r
\r
safe_ptr<cg_producer> get_default_cg_producer(const safe_ptr<core::video_channel>& video_channel, int layer_index = cg_producer::DEFAULT_LAYER);\r
\r
safe_ptr<core::frame_producer> create_ct_producer(const safe_ptr<core::frame_factory> frame_factory, const std::vector<std::wstring>& params);\r
+safe_ptr<core::frame_producer> create_cg_producer(const safe_ptr<core::frame_factory> frame_factory, const std::vector<std::wstring>& params);\r
\r
}}
\ No newline at end of file
return last_frame_;\r
} \r
\r
- virtual std::wstring call(const std::wstring& param) override\r
+ virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
{ \r
- return context_.invoke([=]() -> std::wstring\r
+ return context_.begin_invoke([=]() -> std::wstring\r
{\r
if(!context_)\r
initialize();\r
for(auto it = std::begin(_parameters2)+2; it != std::end(_parameters2); ++it)\r
param += L" " + *it;\r
\r
- std::wstring result;\r
+ boost::unique_future<std::wstring> result;\r
if(what == L"B")\r
result = GetChannel()->stage()->call(GetLayerIndex(), false, param);\r
else if(what == L"F")\r
else\r
result = GetChannel()->stage()->call(GetLayerIndex(), true, _parameters.at(0) + L" " + param);\r
\r
+ if(!result.timed_wait(boost::posix_time::seconds(2)))\r
+ BOOST_THROW_EXCEPTION(timed_out());\r
+\r
CASPAR_LOG(info) << "Executed call: " << _parameters[0] << TEXT(" successfully");\r
\r
std::wstringstream replyString;\r
- replyString << TEXT("201 CALL OK\r\n") << result << L"\r\n";\r
+ replyString << TEXT("201 CALL OK\r\n") << result.get() << L"\r\n";\r
\r
SetReplyString(replyString.str());\r
\r
{\r
void Send(const std::wstring& data)\r
{\r
- std::wcout << L"#" << data;\r
+ std::wcout << (L"\n--------------------\n" + data + L"--------------------\n");\r
}\r
void Disconnect(){}\r
};\r
\r
decklink::init(); \r
CASPAR_LOG(info) << L"Initialized decklink module.";\r
- \r
- flash::init(); \r
- CASPAR_LOG(info) << L"Initialized flash module.";\r
- \r
+ \r
oal::init(); \r
CASPAR_LOG(info) << L"Initialized oal module.";\r
\r
image::init(); \r
CASPAR_LOG(info) << L"Initialized image module.";\r
\r
+ flash::init(); \r
+ CASPAR_LOG(info) << L"Initialized flash module.";\r
+\r
setup_channels(env::properties());\r
CASPAR_LOG(info) << L"Initialized channels.";\r
\r