* Removed hard dependencies to flash module from AMCP, CLK and CII protocol implementations, using the above mentioned abstractions.
producer/transition/transition_producer.cpp
+ producer/cg_proxy.cpp
producer/frame_producer.cpp
producer/layer.cpp
producer/stage.cpp
producer/transition/transition_producer.h
producer/binding.h
+ producer/cg_proxy.h
producer/frame_producer.h
producer/layer.h
producer/stage.h
struct call_context
{
- int video_channel = -1;
- int layer = -1;
+ int video_channel = -1;
+ int layer = -1;
static call_context& for_thread();
};
class scoped_call_context : boost::noncopyable
{
- call_context saved_ = call_context::for_thread();
+ call_context saved_ = call_context::for_thread();
public:
~scoped_call_context()
{
--- /dev/null
+/*
+* 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: Helge Norberg, helge.norberg@svt.se
+*/
+
+#include "../StdAfx.h"
+
+#include "cg_proxy.h"
+
+#include "frame_producer.h"
+#include "stage.h"
+#include "../video_channel.h"
+#include "../diagnostics/call_context.h"
+
+#include <common/env.h>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/lock_guard.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/optional.hpp>
+
+#include <future>
+#include <vector>
+
+namespace caspar { namespace core {
+
+const spl::shared_ptr<cg_proxy>& cg_proxy::empty()
+{
+ class empty_proxy : public cg_proxy
+ {
+ void add(int, const std::wstring&, bool, const std::wstring&, const std::wstring&) override {}
+ void remove(int) override {}
+ void play(int) override {}
+ void stop(int, unsigned int) override {}
+ void next(int) override {}
+ void update(int, const std::wstring&) override {}
+ std::wstring invoke(int, const std::wstring&) override { return L""; }
+ std::wstring description(int) override { return L"empty cg producer"; }
+ std::wstring template_host_info() override { return L"empty cg producer"; }
+ };
+
+ static spl::shared_ptr<cg_proxy> instance = spl::make_shared<empty_proxy>();
+ return instance;
+}
+
+using namespace boost::multi_index;
+
+struct cg_producer_registry::impl
+{
+private:
+ struct record
+ {
+ std::wstring name;
+ std::set<std::wstring> file_extensions;
+ meta_info_extractor info_extractor;
+ cg_proxy_factory proxy_factory;
+ cg_producer_factory producer_factory;
+ bool reusable_producer_instance;
+ };
+
+ struct name {};
+ struct extension {};
+
+ mutable boost::mutex mutex_;
+ std::vector<record> records_;
+public:
+ void register_cg_producer(
+ std::wstring cg_producer_name,
+ std::set<std::wstring> file_extensions,
+ meta_info_extractor info_extractor,
+ cg_proxy_factory proxy_factory,
+ cg_producer_factory producer_factory,
+ bool reusable_producer_instance)
+ {
+ boost::lock_guard<boost::mutex> lock(mutex_);
+
+ records_.push_back(
+ {
+ std::move(cg_producer_name),
+ std::move(file_extensions),
+ std::move(info_extractor),
+ std::move(proxy_factory),
+ std::move(producer_factory),
+ reusable_producer_instance
+ });
+ }
+
+ spl::shared_ptr<frame_producer> create_producer(
+ const spl::shared_ptr<video_channel>& video_channel,
+ const std::wstring& filename) const
+ {
+ auto found = find_record(filename);
+
+ if (!found)
+ return frame_producer::empty();
+
+ return found->producer_factory(
+ video_channel->frame_factory(),
+ video_channel->video_format_desc(),
+ filename);
+ }
+
+ spl::shared_ptr<cg_proxy> get_proxy(const spl::shared_ptr<frame_producer>& producer) const
+ {
+ auto producer_name = producer->name();
+
+ boost::lock_guard<boost::mutex> lock(mutex_);
+
+ for (auto& elem : records_)
+ {
+ if (elem.name == producer_name)
+ return elem.proxy_factory(producer);
+ }
+
+ return cg_proxy::empty();
+ }
+
+ spl::shared_ptr<cg_proxy> get_proxy(
+ const spl::shared_ptr<class video_channel>& video_channel,
+ int render_layer) const
+ {
+ auto producer = spl::make_shared_ptr(video_channel->stage().foreground(render_layer).get());
+
+ return get_proxy(producer);
+ }
+
+ spl::shared_ptr<cg_proxy> get_or_create_proxy(
+ const spl::shared_ptr<class video_channel>& video_channel,
+ int render_layer,
+ const std::wstring& filename) const
+ {
+ using namespace boost::filesystem;
+
+ auto found = find_record(filename);
+
+ if (!found)
+ return cg_proxy::empty();
+
+ auto producer = spl::make_shared_ptr(video_channel->stage().foreground(render_layer).get());
+ auto current_producer_name = producer->name();
+ bool create_new = current_producer_name != found->name || !found->reusable_producer_instance;
+
+ if (create_new)
+ {
+ diagnostics::scoped_call_context save;
+ diagnostics::call_context::for_thread().video_channel = video_channel->index();
+ diagnostics::call_context::for_thread().layer = render_layer;
+
+ producer = found->producer_factory(
+ video_channel->frame_factory(),
+ video_channel->video_format_desc(),
+ filename);
+ video_channel->stage().load(render_layer, producer);
+ video_channel->stage().play(render_layer);
+ }
+
+ return found->proxy_factory(producer);
+ }
+
+ std::string read_meta_info(const std::wstring& filename) const
+ {
+ using namespace boost::filesystem;
+
+ auto basepath = path(env::template_folder()) / path(filename);
+
+ boost::lock_guard<boost::mutex> lock(mutex_);
+
+ for (auto& rec : records_)
+ {
+ for (auto& file_extension : rec.file_extensions)
+ {
+ auto p = path(basepath.wstring() + file_extension);
+
+ if (exists(p))
+ {
+ return rec.info_extractor(filename);
+ }
+ }
+ }
+
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(L"No meta info extractor for " + filename));
+ }
+
+ bool is_cg_extension(const std::wstring& extension) const
+ {
+ boost::lock_guard<boost::mutex> lock(mutex_);
+
+ for (auto& rec : records_)
+ {
+ for (auto& file_extension : rec.file_extensions)
+ {
+ if (boost::algorithm::iequals(file_extension, extension))
+ return true;
+ }
+ }
+
+ return false;
+ }
+private:
+ boost::optional<record> find_record(const std::wstring& filename) const
+ {
+ using namespace boost::filesystem;
+
+ auto basepath = path(env::template_folder()) / path(filename);
+
+ boost::lock_guard<boost::mutex> lock(mutex_);
+
+ for (auto& rec : records_)
+ {
+ for (auto& file_extension : rec.file_extensions)
+ {
+ auto p = path(basepath.wstring() + file_extension);
+
+ if (exists(p))
+ return rec;
+ }
+ }
+
+ return boost::none;
+ }
+};
+
+cg_producer_registry::cg_producer_registry() : impl_(new impl) { }
+
+void cg_producer_registry::register_cg_producer(
+ std::wstring cg_producer_name,
+ std::set<std::wstring> file_extensions,
+ meta_info_extractor info_extractor,
+ cg_proxy_factory proxy_factory,
+ cg_producer_factory producer_factory,
+ bool reusable_producer_instance)
+{
+ impl_->register_cg_producer(
+ std::move(cg_producer_name),
+ std::move(file_extensions),
+ std::move(info_extractor),
+ std::move(proxy_factory),
+ std::move(producer_factory),
+ reusable_producer_instance);
+}
+
+spl::shared_ptr<frame_producer> cg_producer_registry::create_producer(
+ const spl::shared_ptr<video_channel>& video_channel,
+ const std::wstring& filename) const
+{
+ return impl_->create_producer(video_channel, filename);
+}
+
+spl::shared_ptr<cg_proxy> cg_producer_registry::get_proxy(
+ const spl::shared_ptr<frame_producer>& producer) const
+{
+ return impl_->get_proxy(producer);
+}
+
+spl::shared_ptr<cg_proxy> cg_producer_registry::get_proxy(
+ const spl::shared_ptr<video_channel>& video_channel,
+ int render_layer) const
+{
+ return impl_->get_proxy(video_channel, render_layer);
+}
+
+spl::shared_ptr<cg_proxy> cg_producer_registry::get_or_create_proxy(
+ const spl::shared_ptr<video_channel>& video_channel,
+ int render_layer,
+ const std::wstring& filename) const
+{
+ return impl_->get_or_create_proxy(video_channel, render_layer, filename);
+}
+
+std::string cg_producer_registry::read_meta_info(const std::wstring& filename) const
+{
+ return impl_->read_meta_info(filename);
+}
+
+bool cg_producer_registry::is_cg_extension(const std::wstring& extension) const
+{
+ return impl_->is_cg_extension(extension);
+}
+
+}}
--- /dev/null
+/*
+* 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: Robert Nagy, ronag89@gmail.com
+*/
+
+#pragma once
+
+#include "frame_producer.h"
+
+#include <common/memory.h>
+
+#include <string>
+#include <functional>
+#include <set>
+
+#include <boost/noncopyable.hpp>
+
+namespace caspar { namespace core {
+
+class cg_proxy
+{
+public:
+ static const unsigned int DEFAULT_LAYER = 9999;
+
+ virtual ~cg_proxy() {}
+
+ virtual void add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& start_from_label = L"", const std::wstring& data = L"") = 0;
+ virtual void remove(int layer) = 0;
+ virtual void play(int layer) = 0;
+ virtual void stop(int layer, unsigned int mix_out_duration) = 0;
+ virtual void next(int layer) = 0;
+ virtual void update(int layer, const std::wstring& data) = 0;
+ virtual std::wstring invoke(int layer, const std::wstring& label) = 0;
+ virtual std::wstring description(int layer) = 0;
+ virtual std::wstring template_host_info() = 0;
+
+ static const spl::shared_ptr<cg_proxy>& empty();
+};
+
+typedef std::function<spl::shared_ptr<cg_proxy>(
+ const spl::shared_ptr<frame_producer>& producer
+ )> cg_proxy_factory;
+typedef std::function<spl::shared_ptr<frame_producer>(
+ const spl::shared_ptr<class frame_factory>& factory,
+ const video_format_desc& format_desc,
+ const std::wstring& filename
+ )> cg_producer_factory;
+typedef std::function<std::string(const std::wstring& filename)> meta_info_extractor;
+
+class cg_producer_registry : boost::noncopyable
+{
+public:
+ cg_producer_registry();
+
+ void register_cg_producer(
+ std::wstring cg_producer_name,
+ std::set<std::wstring> file_extensions,
+ meta_info_extractor info_extractor,
+ cg_proxy_factory proxy_factory,
+ cg_producer_factory producer_factory,
+ bool reusable_producer_instance);
+
+ spl::shared_ptr<frame_producer> create_producer(
+ const spl::shared_ptr<class video_channel>& video_channel,
+ const std::wstring& filename) const;
+ spl::shared_ptr<cg_proxy> get_proxy(
+ const spl::shared_ptr<frame_producer>& producer) const;
+ spl::shared_ptr<cg_proxy> get_proxy(
+ const spl::shared_ptr<class video_channel>& video_channel,
+ int render_layer) const;
+ spl::shared_ptr<cg_proxy> get_or_create_proxy(
+ const spl::shared_ptr<class video_channel>& video_channel,
+ int render_layer,
+ const std::wstring& filename) const;
+ std::string read_meta_info(const std::wstring& filename) const;
+ bool is_cg_extension(const std::wstring& extension) const;
+private:
+ struct impl;
+ spl::shared_ptr<impl> impl_;
+};
+
+
+}}
set(SOURCES
interop/Flash9e_i.c
- producer/cg_proxy.cpp
producer/FlashAxContainer.cpp
producer/flash_producer.cpp
interop/axflash.h
interop/TimerHelper.h
- producer/cg_proxy.h
producer/FlashAxContainer.h
producer/flash_producer.h
#include "StdAfx.h"
#include "flash.h"
+#include "util/swf.h"
-#include "producer/cg_proxy.h"
#include "producer/flash_producer.h"
#include <common/env.h>
#include <core/producer/media_info/media_info.h>
#include <core/producer/media_info/media_info_repository.h>
+#include <core/producer/cg_proxy.h>
#include <core/system_info_provider.h>
+#include <core/frame/frame_factory.h>
+#include <core/video_format.h>
#include <boost/property_tree/ptree.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/filesystem.hpp>
#include <string>
+#include <future>
namespace caspar { namespace flash {
std::wstring version();
std::wstring cg_version();
+std::wstring get_absolute(const std::wstring& filename)
+{
+ return (boost::filesystem::path(env::template_folder()) / filename).wstring();
+}
+
+class flash_cg_proxy : public core::cg_proxy, boost::noncopyable
+{
+ spl::shared_ptr<core::frame_producer> flash_producer_;
+ std::wstring base_folder_;
+public:
+ explicit flash_cg_proxy(const spl::shared_ptr<core::frame_producer>& producer, std::wstring base_folder = env::template_folder())
+ : flash_producer_(producer)
+ , base_folder_(base_folder)
+ {
+ }
+
+ //cg_proxy
+
+ void add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& label, const std::wstring& data) override
+ {
+ auto filename = template_name;
+
+ if (filename.size() > 0 && filename[0] == L'/')
+ filename = filename.substr(1, filename.size() - 1);
+
+ filename = (boost::filesystem::path(base_folder_) / filename).wstring();
+ filename = find_template(filename);
+
+ auto str = (boost::wformat(L"<invoke name=\"Add\" returntype=\"xml\"><arguments><number>%1%</number><string>%2%</string>%3%<string>%4%</string><string><![CDATA[%5%]]></string></arguments></invoke>") % layer % filename % (play_on_load ? L"<true/>" : L"<false/>") % label % data).str();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking add-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ flash_producer_->call(std::move(params));
+ }
+
+ void remove(int layer) override
+ {
+ auto str = (boost::wformat(L"<invoke name=\"Delete\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking remove-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ flash_producer_->call(std::move(params));
+ }
+
+ void play(int layer) override
+ {
+ auto str = (boost::wformat(L"<invoke name=\"Play\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking play-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ flash_producer_->call(std::move(params));
+ }
+
+ void stop(int layer, unsigned int) override
+ {
+ 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();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking stop-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ flash_producer_->call(std::move(params));
+ }
+
+ void next(int layer) override
+ {
+ auto str = (boost::wformat(L"<invoke name=\"Next\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking next-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ flash_producer_->call(std::move(params));
+ }
+
+ void update(int layer, const std::wstring& data) override
+ {
+ 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();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking update-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ flash_producer_->call(std::move(params));
+ }
+
+ std::wstring invoke(int layer, const std::wstring& label) override
+ {
+ 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();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking invoke-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ // TODO: because of std::async deferred timed waiting does not work so for now we have to block
+ return flash_producer_->call(std::move(params)).get();
+ }
+
+ std::wstring description(int layer) override
+ {
+ auto str = (boost::wformat(L"<invoke name=\"GetDescription\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking description-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ // TODO: because of std::async deferred timed waiting does not work so for now we have to block
+ return flash_producer_->call(std::move(params)).get();
+ }
+
+ std::wstring template_host_info() override
+ {
+ auto str = (boost::wformat(L"<invoke name=\"GetInfo\" returntype=\"xml\"><arguments></arguments></invoke>")).str();
+ CASPAR_LOG(info) << flash_producer_->print() << " Invoking info-command: " << str;
+ std::vector<std::wstring> params;
+ params.push_back(std::move(str));
+ // TODO: because of std::async deferred timed waiting does not work so for now we have to block
+ return flash_producer_->call(std::move(params)).get();
+ }
+};
+
+spl::shared_ptr<core::frame_producer> create_ct_producer(
+ const spl::shared_ptr<core::frame_factory> frame_factory,
+ const core::video_format_desc& format_desc,
+ const std::vector<std::wstring>& params)
+{
+ auto flash_producer = flash::create_producer(frame_factory, format_desc, {});
+ auto producer = flash_producer;
+ flash_cg_proxy(producer, env::media_folder()).add(0, params[0], true, L"", L"");
+
+ return producer;
+}
+
void init(
const spl::shared_ptr<core::media_info_repository>& media_info_repo,
- const spl::shared_ptr<core::system_info_provider_repository>& info_provider_repo)
+ const spl::shared_ptr<core::system_info_provider_repository>& info_provider_repo,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
{
core::register_producer_factory(create_ct_producer);
core::register_producer_factory(create_swf_producer);
});
info_provider_repo->register_version_provider(L"FLASH", &version);
info_provider_repo->register_version_provider(L"TEMPLATEHOST", &cg_version);
+ cg_registry->register_cg_producer(
+ L"flash",
+ { L".ft", L".ct" },
+ [](const std::wstring& filename)
+ {
+ return read_template_meta_info(get_absolute(filename) + L".ft");
+ },
+ [](const spl::shared_ptr<core::frame_producer>& producer)
+ {
+ return spl::make_shared<flash_cg_proxy>(producer);
+ },
+ [](const spl::shared_ptr<core::frame_factory>& ff, const core::video_format_desc& f, const std::wstring&)
+ {
+ return flash::create_producer(ff, f, { });
+ },
+ true
+ );
}
std::wstring cg_version()
struct media_info_repository;
class system_info_provider_repository;
+class cg_producer_registry;
}
void init(
const spl::shared_ptr<core::media_info_repository>& media_info_repo,
- const spl::shared_ptr<core::system_info_provider_repository>& info_provider_repo);
+ const spl::shared_ptr<core::system_info_provider_repository>& info_provider_repo,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry);
}}
\ No newline at end of file
+++ /dev/null
-/*
-* 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: Robert Nagy, ronag89@gmail.com
-*/
-
-#include "../StdAfx.h"
-
-#include "cg_proxy.h"
-
-#include "flash_producer.h"
-
-#include <common/env.h>
-
-#include <core/mixer/mixer.h>
-#include <core/diagnostics/call_context.h>
-
-#include <boost/filesystem.hpp>
-#include <boost/format.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/regex.hpp>
-#include <boost/property_tree/ptree.hpp>
-
-#include <future>
-
-namespace caspar { namespace flash {
-
-struct cg_proxy::impl : boost::noncopyable
-{
- spl::shared_ptr<core::frame_producer> flash_producer_;
-public:
- impl(const spl::shared_ptr<core::frame_producer>& frame_producer)
- : flash_producer_(frame_producer)
- {}
-
- std::future<std::wstring> add(int layer, std::wstring filename, bool play_on_load, const std::wstring& label, const std::wstring& data)
- {
- if(filename.size() > 0 && filename[0] == L'/')
- filename = filename.substr(1, filename.size()-1);
-
- if(boost::filesystem::wpath(filename).extension() == L"")
- filename += L".ft";
-
- auto str = (boost::wformat(L"<invoke name=\"Add\" returntype=\"xml\"><arguments><number>%1%</number><string>%2%</string>%3%<string>%4%</string><string><![CDATA[%5%]]></string></arguments></invoke>") % layer % filename % (play_on_load?L"<true/>":L"<false/>") % label % data).str();
- CASPAR_LOG(info) << flash_producer_->print() << " Invoking add-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::future<std::wstring> remove(int layer)
- {
- auto str = (boost::wformat(L"<invoke name=\"Delete\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();
- CASPAR_LOG(info) << flash_producer_->print() << " Invoking remove-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::future<std::wstring> play(int layer)
- {
- auto str = (boost::wformat(L"<invoke name=\"Play\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();
- CASPAR_LOG(info) << flash_producer_->print() << " Invoking play-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::future<std::wstring> stop(int layer, unsigned int)
- {
- 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();
- CASPAR_LOG(info) << flash_producer_->print() << " Invoking stop-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::future<std::wstring> next(int layer)
- {
- auto str = (boost::wformat(L"<invoke name=\"Next\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();
- CASPAR_LOG(info) << flash_producer_->print() << " Invoking next-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::future<std::wstring> update(int layer, const std::wstring& data)
- {
- 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();
- CASPAR_LOG(info) << flash_producer_->print() <<" Invoking update-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::future<std::wstring> invoke(int layer, const std::wstring& label)
- {
- 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();
- CASPAR_LOG(info) << flash_producer_->print() << " Invoking invoke-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::future<std::wstring> description(int layer)
- {
- auto str = (boost::wformat(L"<invoke name=\"GetDescription\" returntype=\"xml\"><arguments><array><property id=\"0\"><number>%1%</number></property></array></arguments></invoke>") % layer).str();
- CASPAR_LOG(info) << flash_producer_->print() << " Invoking description-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::future<std::wstring> template_host_info()
- {
- auto str = (boost::wformat(L"<invoke name=\"GetInfo\" returntype=\"xml\"><arguments></arguments></invoke>")).str();
- CASPAR_LOG(info) << flash_producer_->print() << " Invoking info-command: " << str;
- std::vector<std::wstring> params;
- params.push_back(std::move(str));
- return flash_producer_->call(std::move(params));
- }
-
- std::wstring timed_invoke(int layer, const std::wstring& label)
- {
- auto result = invoke(layer, label);
- // TODO: because of std::async deferred timed waiting does not work
- //if (result.wait_for(std::chrono::seconds(2)) != std::future_status::timeout)
- return result.get();
- //return L"";
- }
- std::wstring timed_description(int layer)
- {
- auto result = description(layer);
- // TODO: because of std::async deferred timed waiting does not work
- //if (result.wait_for(std::chrono::seconds(2)) != std::future_status::timeout)
- return result.get();
- //return L"";
- }
- std::wstring timed_template_host_info()
- {
- auto result = template_host_info();
- // TODO: because of std::async deferred timed waiting does not work
- //if (result.wait_for(std::chrono::seconds(2)) != std::future_status::timeout)
- return result.get();
- //return L"";
- }
-
- core::monitor::subject& monitor_output()
- {
- return flash_producer_->monitor_output();
- }
-};
-
-cg_proxy create_cg_proxy(const spl::shared_ptr<core::video_channel>& video_channel, int render_layer)
-{
- auto flash_producer = spl::make_shared_ptr(video_channel->stage().foreground(render_layer).get());
-
- try
- {
- if(flash_producer->name() != L"flash")
- {
- core::diagnostics::scoped_call_context save;
- core::diagnostics::call_context::for_thread().video_channel = video_channel->index();
- core::diagnostics::call_context::for_thread().layer = render_layer;
-
- flash_producer = flash::create_producer(video_channel->frame_factory(), video_channel->video_format_desc(), {});
- video_channel->stage().load(render_layer, flash_producer);
- video_channel->stage().play(render_layer);
- }
- }
- catch(...)
- {
- CASPAR_LOG_CURRENT_EXCEPTION();
- throw;
- }
-
- return cg_proxy(std::move(flash_producer));
-}
-
-spl::shared_ptr<core::frame_producer> create_cg_producer_and_autoplay_file(
- const spl::shared_ptr<core::frame_factory> frame_factory,
- const core::video_format_desc& format_desc,
- const std::vector<std::wstring>& params,
- const std::wstring& filename)
-{
- if(!boost::filesystem::exists(filename))
- return core::frame_producer::empty();
-
- boost::filesystem::path path(filename);
- path = boost::filesystem::complete(path);
- auto filename2 = path.wstring();
-
- auto flash_producer = flash::create_producer(frame_factory, format_desc, {});
- auto producer = flash_producer;
- cg_proxy(producer).add(0, filename2, 1);
-
- return producer;
-}
-
-spl::shared_ptr<core::frame_producer> create_ct_producer(const spl::shared_ptr<core::frame_factory> frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
-{
- return create_cg_producer_and_autoplay_file(
- frame_factory, format_desc, params, env::media_folder() + L"\\" + params[0] + L".ct");
-}
-
-cg_proxy::cg_proxy(const spl::shared_ptr<core::frame_producer>& frame_producer) : impl_(new impl(frame_producer)){}
-cg_proxy::cg_proxy(cg_proxy&& other) : impl_(std::move(other.impl_)){}
-void cg_proxy::add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& startFromLabel, const std::wstring& data){impl_->add(layer, template_name, play_on_load, startFromLabel, data);}
-void cg_proxy::remove(int layer){impl_->remove(layer);}
-void cg_proxy::play(int layer){impl_->play(layer);}
-void cg_proxy::stop(int layer, unsigned int mix_out_duration){impl_->stop(layer, mix_out_duration);}
-void cg_proxy::next(int layer){impl_->next(layer);}
-void cg_proxy::update(int layer, const std::wstring& data){impl_->update(layer, data);}
-std::wstring cg_proxy::invoke(int layer, const std::wstring& label){return impl_->timed_invoke(layer, label);}
-std::wstring cg_proxy::description(int layer){return impl_->timed_description(layer);}
-std::wstring cg_proxy::template_host_info(){return impl_->timed_template_host_info();}
-core::monitor::subject& cg_proxy::monitor_output(){return impl_->monitor_output();}
-
-}}
\ No newline at end of file
+++ /dev/null
-/*
-* 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: Robert Nagy, ronag89@gmail.com
-*/
-
-#pragma once
-
-#include <core/producer/frame_producer.h>
-#include <core/producer/stage.h>
-#include <core/video_format.h>
-#include <core/video_channel.h>
-
-#include <boost/thread/future.hpp>
-
-#include <string>
-
-namespace caspar { namespace flash {
-
-class cg_proxy
-{
-public:
- static const unsigned int DEFAULT_LAYER = 9999;
-
- explicit cg_proxy(const spl::shared_ptr<core::frame_producer>& producer);
- cg_proxy(cg_proxy&& other);
-
- //cg_proxy
-
- void add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& start_from_label = L"", const std::wstring& data = L"");
- void remove(int layer);
- void play(int layer);
- void stop(int layer, unsigned int mix_out_duration);
- void next(int layer);
- void update(int layer, const std::wstring& data);
- std::wstring invoke(int layer, const std::wstring& label);
- std::wstring description(int layer);
- std::wstring template_host_info();
- core::monitor::subject& monitor_output();
-
-private:
- struct impl;
- std::shared_ptr<impl> impl_;
-};
-cg_proxy create_cg_proxy(const spl::shared_ptr<core::video_channel>& video_channel, int layer_index = cg_proxy::DEFAULT_LAYER);
-
-spl::shared_ptr<core::frame_producer> create_ct_producer(const spl::shared_ptr<core::frame_factory> frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
-
-}}
source_group(sources\\util util/*)
source_group(sources ./*)
-target_link_libraries(protocol common core flash reroute)
+target_link_libraries(protocol common core reroute)
#include <core/system_info_provider.h>
#include <modules/reroute/producer/reroute_producer.h>
-#include <modules/flash/flash.h>
-#include <modules/flash/util/swf.h>
-#include <modules/flash/producer/flash_producer.h>
-#include <modules/flash/producer/cg_proxy.h>
#include <algorithm>
#include <locale>
return boost::to_upper_copy(replyString.str());
}
-std::wstring ListTemplates()
+std::wstring ListTemplates(const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
{
std::wstringstream replyString;
for (boost::filesystem::recursive_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"))
+ if(boost::filesystem::is_regular_file(itr->path()) && cg_registry->is_cg_extension(itr->path().extension().wstring()))
{
auto relativePath = boost::filesystem::wpath(itr->path().wstring().substr(env::template_folder().size()-1, itr->path().wstring().size()));
auto sizeWStr = std::wstring(sizeStr.begin(), sizeStr.end());
- std::wstring dir = relativePath.parent_path().generic_wstring();
- std::wstring file = boost::to_upper_copy(relativePath.filename().wstring());
- relativePath = boost::filesystem::wpath(dir + L"/" + file);
+ auto dir = relativePath.parent_path();
+ auto file = boost::to_upper_copy(relativePath.filename().wstring());
+ relativePath = dir / file;
auto str = relativePath.replace_extension(L"").generic_wstring();
boost::trim_if(str, boost::is_any_of("\\/"));
}
}
-
-
-//std::function<std::wstring()> channel_cg_add_command::parse(const std::wstring& message, const std::vector<renderer::render_device_ptr>& channels)
-//{
-// static boost::wregex expr(L"^CG\\s(?<video_channel>\\d+)-?(?<LAYER>\\d+)?\\sADD\\s(?<FLASH_LAYER>\\d+)\\s(?<TEMPLATE>\\S+)\\s?(?<START_LABEL>\\S\\S+)?\\s?(?<PLAY_ON_LOAD>\\d)?\\s?(?<DATA>.*)?");
-//
-// boost::wsmatch what;
-// if(!boost::regex_match(message, what, expr))
-// return nullptr;
-//
-// auto info = channel_info::parse(what, channels);
-//
-// int flash_layer_index = boost::lexical_cast<int>(what["FLASH_LAYER"].str());
-//
-// std::wstring templatename = what["TEMPLATE"].str();
-// bool play_on_load = what["PLAY_ON_LOAD"].matched ? what["PLAY_ON_LOAD"].str() != L"0" : 0;
-// std::wstring start_label = what["START_LABEL"].str();
-// std::wstring data = get_data(what["DATA"].str());
-//
-// boost::replace_all(templatename, "\"", "");
-//
-// return [=]() -> std::wstring
-// {
-// std::wstring fullFilename = flash::flash_producer::find_template(server::template_folder() + templatename);
-// if(fullFilename.empty())
-// CASPAR_THROW_EXCEPTION(file_not_found());
-//
-// std::wstring extension = boost::filesystem::wpath(fullFilename).extension();
-// std::wstring filename = templatename;
-// filename.append(extension);
-//
-// flash::flash::create_cg_proxy(info.video_channel, std::max<int>(DEFAULT_CHANNEL_LAYER+1, info.layer_index))
-// ->add(flash_layer_index, filename, play_on_load, start_label, data);
-//
-// CASPAR_LOG(info) << L"Executed [amcp_channel_cg_add]";
-// return L"";
-// };
-
bool LoadbgCommand::DoExecute()
{
transition_info transitionInfo;
}
}
- std::wstring fullFilename = flash::find_template(env::template_folder() + parameters()[2]);
- if(!fullFilename.empty())
- {
- std::wstring extension = boost::filesystem::path(fullFilename).extension().wstring();
- std::wstring filename = parameters()[2];
- filename.append(extension);
+ auto filename = parameters()[2];
+ auto proxy = cg_registry_->get_or_create_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER), filename);
- flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).add(layer, filename, bDoStart, label, (pDataString!=0) ? pDataString : L"");
- SetReplyString(L"202 CG OK\r\n");
- }
- else
+ if (proxy == core::cg_proxy::empty())
{
CASPAR_LOG(warning) << "Could not find template " << parameters()[2];
SetReplyString(L"404 CG ERROR\r\n");
}
+ else
+ {
+ proxy->add(layer, filename, bDoStart, label, (pDataString != 0) ? pDataString : L"");
+ }
+
return true;
}
return false;
}
int layer = boost::lexical_cast<int>(parameters()[1]);
- flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).play(layer);
+ cg_registry_->get_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER))->play(layer);
}
else
{
return false;
}
int layer = boost::lexical_cast<int>(parameters()[1]);
- flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).stop(layer, 0);
+ cg_registry_->get_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER))->stop(layer, 0);
}
else
{
}
int layer = boost::lexical_cast<int>(parameters()[1]);
- flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).next(layer);
+ cg_registry_->get_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER))->next(layer);
}
else
{
}
int layer = boost::lexical_cast<int>(parameters()[1]);
- flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).remove(layer);
+ cg_registry_->get_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER))->remove(layer);
}
else
{
bool CGCommand::DoExecuteClear()
{
- channel()->stage().clear(layer_index(flash::cg_proxy::DEFAULT_LAYER));
+ channel()->stage().clear(layer_index(core::cg_proxy::DEFAULT_LAYER));
SetReplyString(L"202 CG OK\r\n");
return true;
}
}
int layer = boost::lexical_cast<int>(parameters()[1]);
- flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).update(layer, dataString);
+ cg_registry_->get_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER))->update(layer, dataString);
}
catch(...)
{
return false;
}
int layer = boost::lexical_cast<int>(parameters()[1]);
- auto result = flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).invoke(layer, parameters()[2]);
+ auto result = cg_registry_->get_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER))->invoke(layer, parameters()[2]);
replyString << result << L"\r\n";
}
else
}
int layer = boost::lexical_cast<int>(parameters()[1]);
- auto desc = flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).description(layer);
+ auto desc = cg_registry_->get_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER))->description(layer);
replyString << desc << L"\r\n";
}
else
{
- auto info = flash::create_cg_proxy(spl::shared_ptr<core::video_channel>(channel()), layer_index(flash::cg_proxy::DEFAULT_LAYER)).template_host_info();
+ auto info = cg_registry_->get_proxy(channel(), layer_index(core::cg_proxy::DEFAULT_LAYER))->template_host_info();
replyString << info << L"\r\n";
}
auto path = itr->path();
auto file = path.replace_extension(L"").filename();
if(boost::iequals(file.wstring(), parameters().at(0)))
- info += MediaInfo(itr->path(), repo_) + L"\r\n";
+ info += MediaInfo(itr->path(), system_info_repo_) + L"\r\n";
}
if(info.empty())
{
replyString << L"201 INFO TEMPLATE OK\r\n";
- // Needs to be extended for any file, not just flash.
-
- auto filename = flash::find_template(env::template_folder() + parameters().at(1));
+ auto filename = parameters().at(1);
std::wstringstream str;
- str << u16(flash::read_template_meta_info(filename));
+ str << u16(cg_registry_->read_meta_info(filename));
boost::property_tree::wptree info;
boost::property_tree::xml_parser::read_xml(str, info, boost::property_tree::xml_parser::trim_whitespace | boost::property_tree::xml_parser::no_comments);
info.add(L"system.os.description", caspar::os_description());
info.add(L"system.cpu", caspar::cpu_info());
- repo_->fill_information(info);
+ system_info_repo_->fill_information(info);
boost::property_tree::write_xml(replyString, info, w);
}
bool ClsCommand::DoExecute()
{
-/*
- wav = audio
- mp3 = audio
- swf = movie
- dv = movie
- tga = still
- col = still
- */
try
{
std::wstringstream replyString;
replyString << L"200 CLS OK\r\n";
- replyString << ListMedia(repo_);
+ replyString << ListMedia(system_info_repo_);
replyString << L"\r\n";
SetReplyString(boost::to_upper_copy(replyString.str()));
}
std::wstringstream replyString;
replyString << L"200 TLS OK\r\n";
- replyString << ListTemplates();
+ replyString << ListTemplates(cg_registry_);
replyString << L"\r\n";
SetReplyString(replyString.str());
if (parameters().size() > 0 && !boost::iequals(parameters()[0], L"SERVER"))
{
- auto version = repo_->get_version(parameters().at(0));
+ auto version = system_info_repo_->get_version(parameters().at(0));
if (version.empty())
replyString = L"403 VERSION ERROR\r\n";
#include <core/thumbnail_generator.h>
#include <core/producer/media_info/media_info_repository.h>
+#include <core/producer/cg_proxy.h>
#include <core/system_info_provider.h>
#include <future>
class CGCommand : public AMCPChannelCommandBase<1>
{
public:
- CGCommand(IO::ClientInfoPtr client, const channel_context& channel, unsigned int channel_index, int layer_index) : AMCPChannelCommandBase(client, channel, channel_index, layer_index)
- {}
+ CGCommand(
+ IO::ClientInfoPtr client,
+ const channel_context& channel,
+ unsigned int channel_index,
+ int layer_index,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
+ : AMCPChannelCommandBase(client, channel, channel_index, layer_index)
+ , cg_registry_(cg_registry)
+ {
+ }
private:
std::wstring print() const { return L"CGCommand";}
bool DoExecuteUpdate();
bool DoExecuteInvoke();
bool DoExecuteInfo();
+private:
+ spl::shared_ptr<core::cg_producer_registry> cg_registry_;
};
class DataCommand : public AMCPCommandBase<1>
class ClsCommand : public AMCPCommandBase<0>
{
public:
- explicit ClsCommand(IO::ClientInfoPtr client, const spl::shared_ptr<core::media_info_repository>& repo)
+ explicit ClsCommand(IO::ClientInfoPtr client, const spl::shared_ptr<core::media_info_repository>& system_info_repo)
: AMCPCommandBase(client)
- , repo_(repo)
+ , system_info_repo_(system_info_repo)
{}
std::wstring print() const { return L"ClsCommand";}
bool DoExecute();
private:
- spl::shared_ptr<core::media_info_repository> repo_;
+ spl::shared_ptr<core::media_info_repository> system_info_repo_;
};
class TlsCommand : public AMCPCommandBase<0>
{
public:
- explicit TlsCommand(IO::ClientInfoPtr client) : AMCPCommandBase(client) {}
+ explicit TlsCommand(
+ IO::ClientInfoPtr client,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
+ : AMCPCommandBase(client)
+ , cg_registry_(cg_registry)
+ {}
std::wstring print() const { return L"TlsCommand";}
bool DoExecute();
+private:
+ spl::shared_ptr<core::cg_producer_registry> cg_registry_;
};
class CinfCommand : public AMCPCommandBase<1>
{
public:
- explicit CinfCommand(IO::ClientInfoPtr client, const spl::shared_ptr<core::media_info_repository>& repo)
+ explicit CinfCommand(IO::ClientInfoPtr client, const spl::shared_ptr<core::media_info_repository>& system_info_repo)
: AMCPCommandBase(client)
- , repo_(repo)
+ , system_info_repo_(system_info_repo)
{}
std::wstring print() const { return L"CinfCommand";}
bool DoExecute();
private:
- spl::shared_ptr<core::media_info_repository> repo_;
+ spl::shared_ptr<core::media_info_repository> system_info_repo_;
};
class InfoCommand : public AMCPCommandBase<0>, AMCPChannelsAwareCommand
{
public:
- InfoCommand(IO::ClientInfoPtr client, const std::vector<channel_context>& channels, const spl::shared_ptr<core::system_info_provider_repository>& repo)
+ InfoCommand(
+ IO::ClientInfoPtr client,
+ const std::vector<channel_context>& channels,
+ const spl::shared_ptr<core::system_info_provider_repository>& system_info_repo,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
: AMCPChannelsAwareCommand(channels)
, AMCPCommandBase(client)
- , repo_(repo)
+ , system_info_repo_(system_info_repo)
+ , cg_registry_(cg_registry)
{}
std::wstring print() const { return L"InfoCommand";}
bool DoExecute();
private:
- spl::shared_ptr<core::system_info_provider_repository> repo_;
+ spl::shared_ptr<core::system_info_provider_repository> system_info_repo_;
+ spl::shared_ptr<core::cg_producer_registry> cg_registry_;
};
class VersionCommand : public AMCPCommandBase<0>
{
public:
- explicit VersionCommand(IO::ClientInfoPtr client, const spl::shared_ptr<core::system_info_provider_repository>& repo)
+ explicit VersionCommand(IO::ClientInfoPtr client, const spl::shared_ptr<core::system_info_provider_repository>& system_info_repo)
: AMCPCommandBase(client)
- , repo_(repo)
+ , system_info_repo_(system_info_repo)
{}
std::wstring print() const { return L"VersionCommand";}
bool DoExecute();
private:
- spl::shared_ptr<core::system_info_provider_repository> repo_;
+ spl::shared_ptr<core::system_info_provider_repository> system_info_repo_;
};
class ByeCommand : public AMCPCommandBase<0>
std::shared_ptr<core::thumbnail_generator> thumb_gen_;
spl::shared_ptr<core::media_info_repository> media_info_repo_;
spl::shared_ptr<core::system_info_provider_repository> system_info_provider_repo_;
+ spl::shared_ptr<core::cg_producer_registry> cg_registry_;
std::promise<bool>& shutdown_server_now_;
public:
const std::shared_ptr<core::thumbnail_generator>& thumb_gen,
const spl::shared_ptr<core::media_info_repository>& media_info_repo,
const spl::shared_ptr<core::system_info_provider_repository>& system_info_provider_repo,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry,
std::promise<bool>& shutdown_server_now)
: thumb_gen_(thumb_gen)
, media_info_repo_(media_info_repo)
, system_info_provider_repo_(system_info_provider_repo)
+ , cg_registry_(cg_registry)
, shutdown_server_now_(shutdown_server_now)
{
commandQueues_.push_back(std::make_shared<AMCPCommandQueue>());
else if (s == L"CHANNEL_GRID") return std::make_shared<ChannelGridCommand>(client, channels_);
else if (s == L"DATA") return std::make_shared<DataCommand>(client);
else if (s == L"CINF") return std::make_shared<CinfCommand>(client, media_info_repo_);
- else if (s == L"INFO") return std::make_shared<InfoCommand>(client, channels_, system_info_provider_repo_);
+ else if (s == L"INFO") return std::make_shared<InfoCommand>(client, channels_, system_info_provider_repo_, cg_registry_);
else if (s == L"CLS") return std::make_shared<ClsCommand>(client, media_info_repo_);
- else if (s == L"TLS") return std::make_shared<TlsCommand>(client);
+ else if (s == L"TLS") return std::make_shared<TlsCommand>(client, cg_registry_);
else if (s == L"VERSION") return std::make_shared<VersionCommand>(client, system_info_provider_repo_);
else if (s == L"BYE") return std::make_shared<ByeCommand>(client);
else if (s == L"LOCK") return std::make_shared<LockCommand>(client, channels_);
{
std::wstring s = boost::to_upper_copy(str);
- if (s == L"MIXER") return std::make_shared<MixerCommand>(client, channel, channel_index, layer_index);
- else if(s == L"CALL") return std::make_shared<CallCommand>(client, channel, channel_index, layer_index);
- else if(s == L"SWAP") return std::make_shared<SwapCommand>(client, channel, channel_index, layer_index, channels_);
- else if(s == L"LOAD") return std::make_shared<LoadCommand>(client, channel, channel_index, layer_index);
- else if(s == L"LOADBG") return std::make_shared<LoadbgCommand>(client, channel, channel_index, layer_index, channels_);
- else if(s == L"ADD") return std::make_shared<AddCommand>(client, channel, channel_index, layer_index);
- else if(s == L"REMOVE") return std::make_shared<RemoveCommand>(client, channel, channel_index, layer_index);
- else if(s == L"PAUSE") return std::make_shared<PauseCommand>(client, channel, channel_index, layer_index);
- else if(s == L"PLAY") return std::make_shared<PlayCommand>(client, channel, channel_index, layer_index, channels_);
- else if(s == L"STOP") return std::make_shared<StopCommand>(client, channel, channel_index, layer_index);
- else if(s == L"CLEAR") return std::make_shared<ClearCommand>(client, channel, channel_index, layer_index);
- else if(s == L"PRINT") return std::make_shared<PrintCommand>(client, channel, channel_index, layer_index);
- else if(s == L"CG") return std::make_shared<CGCommand>(client, channel, channel_index, layer_index);
- else if(s == L"SET") return std::make_shared<SetCommand>(client, channel, channel_index, layer_index);
+ if ( s == L"MIXER") return std::make_shared<MixerCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"CALL") return std::make_shared<CallCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"SWAP") return std::make_shared<SwapCommand>(client, channel, channel_index, layer_index, channels_);
+ else if (s == L"LOAD") return std::make_shared<LoadCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"LOADBG") return std::make_shared<LoadbgCommand>(client, channel, channel_index, layer_index, channels_);
+ else if (s == L"ADD") return std::make_shared<AddCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"REMOVE") return std::make_shared<RemoveCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"PAUSE") return std::make_shared<PauseCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"PLAY") return std::make_shared<PlayCommand>(client, channel, channel_index, layer_index, channels_);
+ else if (s == L"STOP") return std::make_shared<StopCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"CLEAR") return std::make_shared<ClearCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"PRINT") return std::make_shared<PrintCommand>(client, channel, channel_index, layer_index);
+ else if (s == L"CG") return std::make_shared<CGCommand>(client, channel, channel_index, layer_index, cg_registry_);
+ else if (s == L"SET") return std::make_shared<SetCommand>(client, channel, channel_index, layer_index);
return nullptr;
}
const std::shared_ptr<core::thumbnail_generator>& thumb_gen,
const spl::shared_ptr<core::media_info_repository>& media_info_repo,
const spl::shared_ptr<core::system_info_provider_repository>& system_info_provider_repo,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry,
std::promise<bool>& shutdown_server_now)
- : impl_(spl::make_unique<impl>(channels, thumb_gen, media_info_repo, system_info_provider_repo, shutdown_server_now))
+ : impl_(spl::make_unique<impl>(
+ channels,
+ thumb_gen,
+ media_info_repo,
+ system_info_provider_repo,
+ cg_registry,
+ shutdown_server_now))
{
}
AMCPProtocolStrategy::~AMCPProtocolStrategy() {}
#include <core/video_channel.h>
#include <core/thumbnail_generator.h>
#include <core/producer/media_info/media_info_repository.h>
+#include <core/producer/cg_proxy.h>
#include <core/system_info_provider.h>
#include <common/memory.h>
const std::shared_ptr<core::thumbnail_generator>& thumb_gen,
const spl::shared_ptr<core::media_info_repository>& media_info_repo,
const spl::shared_ptr<core::system_info_provider_repository>& system_info_provider_repo,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry,
std::promise<bool>& shutdown_server_now);
virtual ~AMCPProtocolStrategy();
virtual void Parse(const std::wstring& msg, IO::ClientInfoPtr pClientInfo);
- virtual std::string GetCodepage() { return "UTF-8"; }
+ virtual std::string GetCodepage() const { return "UTF-8"; }
private:
struct impl;
#include "CIIProtocolStrategy.h"
#include "CIICommandsImpl.h"
+
+#include <core/producer/cg_proxy.h>
+
#include <sstream>
#include <algorithm>
-#include <modules/flash/producer/cg_proxy.h>
+
#include <boost/locale.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
{
// HACK fix. The data sent is UTF8, however the protocol is implemented for ISO-8859-1. Instead of doing risky changes we simply convert into proper encoding when leaving protocol code.
auto xmlData2 = boost::locale::conv::utf_to_utf<wchar_t, char>(std::string(xmlData_.begin(), xmlData_.end()));
- flash::create_cg_proxy(pCIIStrategy_->GetChannel()).add(layer_, filename_, false, L"", xmlData2);
+ auto proxy = pCIIStrategy_->get_cg_registry()->get_or_create_proxy(
+ pCIIStrategy_->GetChannel(),
+ core::cg_proxy::DEFAULT_LAYER,
+ filename_);
+ proxy->add(layer_, filename_, false, L"", xmlData2);
}
}
// KeydataCommand
void KeydataCommand::Execute()
{
- if(state_ == 0)
+ auto proxy = pCIIStrategy_->get_cg_registry()->get_proxy(
+ pCIIStrategy_->GetChannel(), casparLayer_);
+
+ if (state_ == 0)
pCIIStrategy_->DisplayTemplate(titleName_);
-
//TODO: Need to be checked for validity
else if(state_ == 1)
- flash::create_cg_proxy(pCIIStrategy_->GetChannel(), casparLayer_).stop(layer_, 0);
+ proxy->stop(layer_, 0);
else if(state_ == 2)
pCIIStrategy_->GetChannel()->stage().clear();
else if(state_ == 3)
- flash::create_cg_proxy(pCIIStrategy_->GetChannel(), casparLayer_).play(layer_);
+ proxy->play(layer_);
}
void KeydataCommand::Setup(const std::vector<std::wstring>& parameters) {
state_ = 0;
}
- casparLayer_ = flash::cg_proxy::DEFAULT_LAYER;
+ casparLayer_ = core::cg_proxy::DEFAULT_LAYER;
if(parameters.size() > 2)
{
//The layer parameter now supports casparlayers.
}
catch(...)
{
- casparLayer_ = flash::cg_proxy::DEFAULT_LAYER;
+ casparLayer_ = core::cg_proxy::DEFAULT_LAYER;
layer_ = 0;
}
}
#include <algorithm>
#include "CIIProtocolStrategy.h"
#include "CIICommandsImpl.h"
-#include <modules/flash/producer/flash_producer.h>
#include <core/producer/transition/transition_producer.h>
#include <core/mixer/mixer.h>
#include <core/diagnostics/call_context.h>
const std::wstring CIIProtocolStrategy::MessageDelimiter = L"\r\n";
const wchar_t CIIProtocolStrategy::TokenDelimiter = L'\\';
-CIIProtocolStrategy::CIIProtocolStrategy(const std::vector<spl::shared_ptr<core::video_channel>>& channels) : pChannel_(channels.at(0)), executor_(L"CIIProtocolStrategy")
+CIIProtocolStrategy::CIIProtocolStrategy(
+ const std::vector<spl::shared_ptr<core::video_channel>>& channels,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
+ : executor_(L"CIIProtocolStrategy")
+ , pChannel_(channels.at(0))
+ , cg_registry_(cg_registry)
{
}
void CIIProtocolStrategy::WriteTemplateData(const std::wstring& templateName, const std::wstring& titleName, const std::wstring& xmlData)
{
- std::wstring fullTemplateFilename = env::template_folder();
- if(currentProfile_.size() > 0)
- {
- fullTemplateFilename += currentProfile_;
- fullTemplateFilename += L"\\";
- }
- fullTemplateFilename += templateName;
- fullTemplateFilename = flash::find_template(fullTemplateFilename);
- if(fullTemplateFilename.empty())
- {
- CASPAR_LOG(error) << "Failed to save instance of " << templateName << L" as " << titleName << L", template " << fullTemplateFilename << " not found";
- return;
- }
+ std::wstring fullTemplateFilename = templateName;
+
+ if (!currentProfile_.empty())
+ fullTemplateFilename = currentProfile_ + L"/" + templateName;
+
core::diagnostics::scoped_call_context save;
core::diagnostics::call_context::for_thread().video_channel = 1;
core::diagnostics::call_context::for_thread().layer = 0;
+ auto producer = cg_registry_->create_producer(GetChannel(), fullTemplateFilename);
- auto producer = flash::create_producer(this->GetChannel()->frame_factory(), this->GetChannel()->video_format_desc(), { env::template_folder() + L"CG.fth" });
+ if (producer == core::frame_producer::empty())
+ {
+ CASPAR_LOG(error) << "Failed to save instance of " << templateName << L" as " << titleName << L", template " << fullTemplateFilename << L"not found";
+ return;
+ }
- std::wstringstream flashParam;
- flashParam << L"<invoke name=\"Add\" returntype=\"xml\"><arguments><number>1</number><string>" << currentProfile_ << '/' << templateName << L"</string><number>0</number><true/><string> </string><string><![CDATA[ " << xmlData << L" ]]></string></arguments></invoke>";
- std::vector<std::wstring> params;
- params.push_back(flashParam.str());
- producer->call(std::move(params));
+ cg_registry_->get_proxy(producer)->add(1, fullTemplateFilename, true, L"", xmlData);
CASPAR_LOG(info) << "Saved an instance of " << templateName << L" as " << titleName ;
#include "CIICommand.h"
#include <core/producer/stage.h>
+#include <core/producer/cg_proxy.h>
#include <common/executor.h>
+#include <common/memory.h>
#include <string>
class CIIProtocolStrategy : public IO::IProtocolStrategy
{
public:
- CIIProtocolStrategy(const std::vector<spl::shared_ptr<core::video_channel>>& channels);
+ CIIProtocolStrategy(const std::vector<spl::shared_ptr<core::video_channel>>& channels, const spl::shared_ptr<core::cg_producer_registry>& cg_registry);
void Parse(const std::wstring& message, IO::ClientInfoPtr pClientInfo);
- std::string GetCodepage() {return "ISO-8859-1";} //ISO 8859-1
+ std::string GetCodepage() const { return "ISO-8859-1"; } //ISO 8859-1
void SetProfile(const std::wstring& profile) {currentProfile_ = profile;}
- spl::shared_ptr<core::video_channel> GetChannel() const{return this->pChannel_;}
+ spl::shared_ptr<core::video_channel> GetChannel() const { return pChannel_; }
+ spl::shared_ptr<core::cg_producer_registry> get_cg_registry() const { return cg_registry_; }
void DisplayMediaFile(const std::wstring& filename);
void DisplayTemplate(const std::wstring& titleName);
std::wstring currentProfile_;
spl::shared_ptr<core::video_channel> pChannel_;
+ spl::shared_ptr<core::cg_producer_registry> cg_registry_;
};
}}}
#include "CLKProtocolStrategy.h"
#include "clk_commands.h"
-#include <modules/flash/producer/cg_proxy.h>
-
#include <string>
#include <algorithm>
#include <locale>
};
clk_protocol_strategy_factory::clk_protocol_strategy_factory(
- const std::vector<spl::shared_ptr<core::video_channel>>& channels)
+ const std::vector<spl::shared_ptr<core::video_channel>>& channels,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry)
{
- add_command_handlers(command_processor_, channels.at(0));
+ add_command_handlers(command_processor_, channels.at(0), cg_registry);
}
IO::protocol_strategy<wchar_t>::ptr clk_protocol_strategy_factory::create(
#include "../util/protocol_strategy.h"
#include "clk_command_processor.h"
#include <core/video_channel.h>
+#include <core/producer/cg_proxy.h>
namespace caspar { namespace protocol { namespace CLK {
clk_command_processor command_processor_;
public:
clk_protocol_strategy_factory(
- const std::vector<spl::shared_ptr<core::video_channel>>& channels);
+ const std::vector<spl::shared_ptr<core::video_channel>>& channels,
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry);
virtual IO::protocol_strategy<wchar_t>::ptr create(
const IO::client_connection<wchar_t>::ptr& client_connection);
#include <boost/lexical_cast.hpp>\r
\r
#include <common/log.h>\r
+#include <common/memory.h>\r
\r
-#include <modules/flash/producer/cg_proxy.h>\r
+#include <core/video_channel.h>\r
+#include <core/producer/stage.h>\r
+#include <core/producer/cg_proxy.h>\r
\r
#include "clk_commands.h"\r
\r
\r
class command_context\r
{\r
- bool clock_loaded_;\r
- spl::shared_ptr<core::video_channel> channel_;\r
+ bool clock_loaded_ = false;\r
+ spl::shared_ptr<core::video_channel> channel_;\r
+ spl::shared_ptr<core::cg_producer_registry> cg_registry_;\r
public:\r
- command_context(const spl::shared_ptr<core::video_channel>& channel)\r
- : clock_loaded_(false)\r
- , channel_(channel)\r
+ command_context(\r
+ const spl::shared_ptr<core::video_channel>& channel,\r
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry)\r
+ : channel_(channel)\r
+ , cg_registry_(cg_registry)\r
{\r
}\r
\r
{\r
if (!clock_loaded_) \r
{\r
- flash::create_cg_proxy(channel_).add(\r
- 0, L"hawrysklocka/clock.ft", true, L"", data);\r
+ cg_registry_->get_or_create_proxy(channel_, core::cg_proxy::DEFAULT_LAYER, L"hawrysklocka/clock")->add(\r
+ 0, L"hawrysklocka/clock", true, L"", data);\r
clock_loaded_ = true;\r
}\r
else\r
{\r
- flash::create_cg_proxy(channel_).update(0, data);\r
+ cg_registry_->get_proxy(channel_, core::cg_proxy::DEFAULT_LAYER)->update(0, data);\r
}\r
\r
CASPAR_LOG(debug) << L"CLK: Clockdata sent: " << data;\r
\r
void reset()\r
{\r
- channel_->stage().clear(flash::cg_proxy::DEFAULT_LAYER);\r
+ channel_->stage().clear(core::cg_proxy::DEFAULT_LAYER);\r
clock_loaded_ = false;\r
CASPAR_LOG(info) << L"CLK: Recieved and executed reset-command";\r
}\r
\r
void add_command_handlers(\r
clk_command_processor& processor, \r
- const spl::shared_ptr<core::video_channel>& channel)\r
+ const spl::shared_ptr<core::video_channel>& channel,\r
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry)\r
{\r
- auto context = spl::make_shared<command_context>(channel);\r
+ auto context = spl::make_shared<command_context>(channel, cg_registry);\r
\r
processor\r
.add_handler(L"DUR", \r
#pragma once\r
\r
#include <core/video_channel.h>\r
+#include <core/producer/cg_proxy.h>\r
\r
#include "clk_command_processor.h"\r
\r
*/\r
void add_command_handlers(\r
clk_command_processor& processor, \r
- const spl::shared_ptr<core::video_channel>& channel);\r
+ const spl::shared_ptr<core::video_channel>& channel,\r
+ const spl::shared_ptr<core::cg_producer_registry>& cg_registry);\r
\r
}}}\r
virtual ~IProtocolStrategy(){}
virtual void Parse(const std::wstring& msg, ClientInfoPtr pClientInfo) = 0;
- virtual std::string GetCodepage() = 0;
+ virtual std::string GetCodepage() const = 0;
};
typedef std::shared_ptr<IProtocolStrategy> ProtocolStrategyPtr;
{
boost::property_tree::wptree info;
repo->fill_information(info);
-
- /*CASPAR_LOG(info) << L"Decklink " << decklink::version();
- for (auto device : decklink::device_list())
- CASPAR_LOG(info) << L" - " << device;
-
- CASPAR_LOG(info) << L"Bluefish " << bluefish::version();
- for (auto device : bluefish::device_list())
- CASPAR_LOG(info) << L" - " << device;*/
for (auto& elem : info.get_child(L"system"))
print_child(L"", elem.first, elem.second);
-
- //CASPAR_LOG(info) << L"Flash " << flash::version();
- //CASPAR_LOG(info) << L"FreeImage " << image::version();
- /*CASPAR_LOG(info) << L"FFMPEG-avcodec " << ffmpeg::avcodec_version();
- CASPAR_LOG(info) << L"FFMPEG-avformat " << ffmpeg::avformat_version();
- CASPAR_LOG(info) << L"FFMPEG-avfilter " << ffmpeg::avfilter_version();
- CASPAR_LOG(info) << L"FFMPEG-avutil " << ffmpeg::avutil_version();
- CASPAR_LOG(info) << L"FFMPEG-swscale " << ffmpeg::swscale_version();*/
}
LONG WINAPI UserUnhandledExceptionFilter(EXCEPTION_POINTERS* info)
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>(
caspar_server.get_thumbnail_generator(),
caspar_server.get_media_info_repo(),
caspar_server.get_system_info_provider_repo(),
+ caspar_server.get_cg_registry(),
shutdown_server_now)))->create(console_client);
std::wstring wcmd;
#include <core/producer/media_info/media_info.h>
#include <core/producer/media_info/media_info_repository.h>
#include <core/producer/media_info/in_memory_media_info_repository.h>
+#include <core/producer/cg_proxy.h>
#include <core/diagnostics/subject_diagnostics.h>
#include <core/diagnostics/call_context.h>
#include <core/diagnostics/osd_graph.h>
spl::shared_ptr<media_info_repository> media_info_repo_;
boost::thread initial_media_info_thread_;
spl::shared_ptr<system_info_provider_repository> system_info_provider_repo_;
+ spl::shared_ptr<core::cg_producer_registry> cg_registry_;
tbb::atomic<bool> running_;
std::shared_ptr<thumbnail_generator> thumbnail_generator_;
std::promise<bool>& shutdown_server_now_;
image::init(media_info_repo_, system_info_provider_repo_);
CASPAR_LOG(info) << L"Initialized image module.";
- flash::init(media_info_repo_, system_info_provider_repo_);
+ flash::init(media_info_repo_, system_info_provider_repo_, cg_registry_);
CASPAR_LOG(info) << L"Initialized flash module.";
psd::init();
using namespace IO;
if(boost::iequals(name, L"AMCP"))
- return wrap_legacy_protocol("\r\n", spl::make_shared<amcp::AMCPProtocolStrategy>(channels_, thumbnail_generator_, media_info_repo_, system_info_provider_repo_, shutdown_server_now_));
+ return wrap_legacy_protocol("\r\n", spl::make_shared<amcp::AMCPProtocolStrategy>(
+ channels_,
+ thumbnail_generator_,
+ media_info_repo_,
+ system_info_provider_repo_,
+ cg_registry_,
+ shutdown_server_now_));
else if(boost::iequals(name, L"CII"))
- return wrap_legacy_protocol("\r\n", spl::make_shared<cii::CIIProtocolStrategy>(channels_));
+ return wrap_legacy_protocol("\r\n", spl::make_shared<cii::CIIProtocolStrategy>(channels_, cg_registry_));
else if(boost::iequals(name, L"CLOCK"))
return spl::make_shared<to_unicode_adapter_factory>(
"ISO-8859-1",
- spl::make_shared<CLK::clk_protocol_strategy_factory>(channels_));
+ spl::make_shared<CLK::clk_protocol_strategy_factory>(channels_, cg_registry_));
CASPAR_THROW_EXCEPTION(caspar_exception() << arg_name_info(L"name") << arg_value_info(name) << msg_info(L"Invalid protocol"));
}
std::shared_ptr<core::thumbnail_generator> server::get_thumbnail_generator() const {return impl_->thumbnail_generator_; }
spl::shared_ptr<media_info_repository> server::get_media_info_repo() const { return impl_->media_info_repo_; }
spl::shared_ptr<core::system_info_provider_repository> server::get_system_info_provider_repo() const { return impl_->system_info_provider_repo_; }
+spl::shared_ptr<core::cg_producer_registry> server::get_cg_registry() const { return impl_->cg_registry_; }
core::monitor::subject& server::monitor_output() { return *impl_->monitor_subject_; }
}
class thumbnail_generator;
struct media_info_repository;
class system_info_provider_repository;
+ class cg_producer_registry;
}
class server final : public boost::noncopyable
std::shared_ptr<core::thumbnail_generator> get_thumbnail_generator() const;
spl::shared_ptr<core::media_info_repository> get_media_info_repo() const;
spl::shared_ptr<core::system_info_provider_repository> get_system_info_provider_repo() const;
+ spl::shared_ptr<core::cg_producer_registry> get_cg_registry() const;
core::monitor::subject& monitor_output();
private: