From db98d63fe01d245354547a202b479e36339fc709 Mon Sep 17 00:00:00 2001 From: Helge Norberg Date: Tue, 7 Apr 2015 17:43:56 +0200 Subject: [PATCH] Reduced the coupling between specific modules and InfoCommand, VersionCommand and main.cpp by enabling modules to contribute system information via providers --- core/CMakeLists.txt | 3 +- core/frame.h | 86 --------------------- core/system_info_provider.cpp | 103 +++++++++++++++++++++++++ core/system_info_provider.h | 50 ++++++++++++ modules/bluefish/bluefish.cpp | 36 +++++---- modules/bluefish/bluefish.h | 14 +++- modules/decklink/decklink.cpp | 70 ++++++++++------- modules/decklink/decklink.h | 14 +++- modules/ffmpeg/ffmpeg.cpp | 82 ++++++++++++-------- modules/ffmpeg/ffmpeg.h | 11 +-- modules/flash/flash.cpp | 16 +++- modules/flash/flash.h | 10 +-- modules/image/image.cpp | 24 ++++-- modules/image/image.h | 9 ++- protocol/amcp/AMCPCommandsImpl.cpp | 31 ++------ protocol/amcp/AMCPCommandsImpl.h | 16 +++- protocol/amcp/AMCPProtocolStrategy.cpp | 44 ++++++----- protocol/amcp/AMCPProtocolStrategy.h | 10 ++- shell/main.cpp | 65 +++++++++++----- shell/server.cpp | 32 +++++--- shell/server.h | 3 + 21 files changed, 451 insertions(+), 278 deletions(-) delete mode 100644 core/frame.h create mode 100644 core/system_info_provider.cpp create mode 100644 core/system_info_provider.h diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index cd1141745..a4d3c3586 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -45,6 +45,7 @@ set(SOURCES producer/layer.cpp producer/stage.cpp + system_info_provider.cpp StdAfx.cpp thumbnail_generator.cpp video_channel.cpp @@ -106,7 +107,7 @@ set(HEADERS producer/stage.h producer/variable.h - frame.h + system_info_provider.h StdAfx.h thumbnail_generator.h video_channel.h diff --git a/core/frame.h b/core/frame.h deleted file mode 100644 index 45d6bfdea..000000000 --- a/core/frame.h +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include "frame/pixel_format.h" -#include "video_format.h" - -namespace caspar { namespace core { - -struct data_frame : boost::noncopyable -{ - virtual ~frame() - { - } - - virtual const struct pixel_format_desc& get_pixel_format_desc() const = 0; - - virtual const boost::iterator_range image_data() const = 0; - virtual const boost::iterator_range audio_data() const = 0; - - virtual const boost::iterator_range image_data() = 0; - virtual const boost::iterator_range audio_data() = 0; - - virtual double get_frame_rate() const = 0; - virtual field_mode get_field_mode() const = 0; - - virtual int width() const = 0; - virtual int height() const = 0; - - static safe_ptr empty() - { - struct empty_frame : public frame - { - virtual const struct video_format_desc& get_video_format_desc() const - { - static video_format_desc invalid; - return invalid; - } - virtual const struct pixel_format_desc& get_pixel_format_desc() const - { - static pixel_format_desc invalid; - return invalid; - } - virtual const boost::iterator_range image_data() const - { - return boost::iterator_range(); - } - virtual const boost::iterator_range audio_data() const - { - return boost::iterator_range(); - } - const boost::iterator_range image_data() - { - return boost::iterator_range(); - } - const boost::iterator_range audio_data() - { - return boost::iterator_range(); - } - virtual double get_frame_rate() const - { - return 0.0; - } - virtual field_mode get_field_mode() const - { - return field_mode::empty; - } - virtual int width() const - { - return 0; - } - virtual int height() const - { - return 0; - } - }; - - static safe_ptr empty; - return empty; - } -}; - -}} \ No newline at end of file diff --git a/core/system_info_provider.cpp b/core/system_info_provider.cpp new file mode 100644 index 000000000..c26758a57 --- /dev/null +++ b/core/system_info_provider.cpp @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2011 Sveriges Television AB +* +* 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 . +* +* Author: Helge Norberg, helge.norberg@svt.se +*/ + +#include "StdAfx.h" + +#include "system_info_provider.h" + +#include +#include +#include +#include + +#include +#include + +namespace caspar { namespace core { + +struct system_info_provider_repository::impl +{ + mutable boost::mutex mutex_; + std::vector info_providers_; + std::map version_providers_; + + void register_system_info_provider(system_info_provider provider) + { + boost::lock_guard lock(mutex_); + + info_providers_.push_back(std::move(provider)); + } + + void register_version_provider(const std::wstring& version_name, version_provider provider) + { + boost::lock_guard lock(mutex_); + + version_providers_.insert(std::make_pair(boost::algorithm::to_lower_copy(version_name), std::move(provider))); + } + + void fill_information(boost::property_tree::wptree& info) const + { + boost::lock_guard lock(mutex_); + + for (auto& provider : info_providers_) + provider(info); + } + + std::wstring get_version(const std::wstring& version_name) const + { + boost::lock_guard lock(mutex_); + + auto found = version_providers_.find(boost::algorithm::to_lower_copy(version_name)); + + if (found == version_providers_.end()) + return L""; + + return found->second(); + } +}; + +system_info_provider_repository::system_info_provider_repository() + : impl_(new impl) +{ +} + +void system_info_provider_repository::register_system_info_provider(system_info_provider provider) +{ + impl_->register_system_info_provider(std::move(provider)); +} + +void system_info_provider_repository::register_version_provider( + const std::wstring& version_name, version_provider provider) +{ + impl_->register_version_provider(version_name, provider); +} + +void system_info_provider_repository::fill_information(boost::property_tree::wptree& info) const +{ + impl_->fill_information(info); +} + +std::wstring system_info_provider_repository::get_version(const std::wstring& version_name) const +{ + return impl_->get_version(version_name); +} + +}} diff --git a/core/system_info_provider.h b/core/system_info_provider.h new file mode 100644 index 000000000..0c91f1304 --- /dev/null +++ b/core/system_info_provider.h @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2011 Sveriges Television AB +* +* 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 . +* +* Author: Helge Norberg, helge.norberg@svt.se +*/ + +#pragma once + +#include + +#include +#include + +#include +#include + +namespace caspar { namespace core { + +typedef std::function system_info_provider; +typedef std::function version_provider; + +class system_info_provider_repository : boost::noncopyable +{ +public: + system_info_provider_repository(); + void register_system_info_provider(system_info_provider provider); + void register_version_provider(const std::wstring& version_name, version_provider provider); + void fill_information(boost::property_tree::wptree& info) const; + std::wstring get_version(const std::wstring& version_name) const; +private: + struct impl; + spl::shared_ptr impl_; +}; + +}} diff --git a/modules/bluefish/bluefish.cpp b/modules/bluefish/bluefish.cpp index b01e51f46..785ac4697 100644 --- a/modules/bluefish/bluefish.cpp +++ b/modules/bluefish/bluefish.cpp @@ -31,24 +31,13 @@ #include #include +#include #include +#include namespace caspar { namespace bluefish { -void init() -{ - try - { - blue_initialize(); - core::register_consumer_factory([](const std::vector& params) - { - return create_consumer(params); - }); - } - catch(...){} -} - std::wstring version() { try @@ -87,4 +76,25 @@ std::vector device_list() return devices; } +void init(const spl::shared_ptr& repo) +{ + try + { + blue_initialize(); + } + catch(...){} + + core::register_consumer_factory([](const std::vector& params) + { + return create_consumer(params); + }); + repo->register_system_info_provider([](boost::property_tree::wptree& info) + { + info.add(L"system.bluefish.version", version()); + + for (auto device : device_list()) + info.add(L"system.bluefish.device", device); + }); +} + }} \ No newline at end of file diff --git a/modules/bluefish/bluefish.h b/modules/bluefish/bluefish.h index 716193059..390f5dec4 100644 --- a/modules/bluefish/bluefish.h +++ b/modules/bluefish/bluefish.h @@ -24,11 +24,17 @@ #include #include -namespace caspar { namespace bluefish { +#include -void init(); +namespace caspar { +namespace core { -std::wstring version(); -std::vector device_list(); +class system_info_provider_repository; + +} + +namespace bluefish { + +void init(const spl::shared_ptr& repo); }} \ No newline at end of file diff --git a/modules/decklink/decklink.cpp b/modules/decklink/decklink.cpp index 4252e99d2..7d0a45806 100644 --- a/modules/decklink/decklink.cpp +++ b/modules/decklink/decklink.cpp @@ -29,6 +29,9 @@ #include #include +#include + +#include #include "interop/DeckLinkAPI_h.h" @@ -44,39 +47,23 @@ namespace caspar { namespace decklink { -void init() -{ - struct co_init - { - co_init(){::CoInitialize(nullptr);} - ~co_init(){::CoUninitialize();} - } init; - - CComPtr pDecklinkIterator; - if(FAILED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator))) - return; - - core::register_consumer_factory([](const std::vector& params){return create_consumer(params);}); - core::register_producer_factory(create_producer); -} - -std::wstring version() +std::wstring version() { std::wstring version = L"Not found"; - + struct co_init { - co_init(){::CoInitialize(nullptr);} - ~co_init(){::CoUninitialize();} + co_init(){ ::CoInitialize(nullptr); } + ~co_init(){ ::CoUninitialize(); } } init; try { CComPtr pDecklinkIterator; - if(SUCCEEDED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator))) + if (SUCCEEDED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator))) version = decklink::version(pDecklinkIterator); } - catch(...){} + catch (...){} return version; } @@ -84,31 +71,54 @@ std::wstring version() std::vector device_list() { std::vector devices; - + struct co_init { - co_init(){::CoInitialize(nullptr);} - ~co_init(){::CoUninitialize();} + co_init(){ ::CoInitialize(nullptr); } + ~co_init(){ ::CoUninitialize(); } } init; try { CComPtr pDecklinkIterator; - if(SUCCEEDED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator))) - { + if (SUCCEEDED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator))) + { IDeckLink* decklink; - for(int n = 1; pDecklinkIterator->Next(&decklink) == S_OK; ++n) + for (int n = 1; pDecklinkIterator->Next(&decklink) == S_OK; ++n) { BSTR model_name = L"Unknown"; decklink->GetModelName(&model_name); decklink->Release(); - devices.push_back(std::wstring(model_name) + L" [" + boost::lexical_cast(n) + L"]"); + devices.push_back(std::wstring(model_name) + L" [" + boost::lexical_cast(n)+L"]"); } } } - catch(...){} + catch (...){} return devices; } +void init(const spl::shared_ptr& repo) +{ + struct co_init + { + co_init(){::CoInitialize(nullptr);} + ~co_init(){::CoUninitialize();} + } init; + + CComPtr pDecklinkIterator; + if(FAILED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator))) + return; + + core::register_consumer_factory([](const std::vector& params){return create_consumer(params);}); + core::register_producer_factory(create_producer); + repo->register_system_info_provider([](boost::property_tree::wptree& info) + { + info.add(L"system.decklink.version", version()); + + for (auto device : device_list()) + info.add(L"system.decklink.device", device); + }); +} + }} \ No newline at end of file diff --git a/modules/decklink/decklink.h b/modules/decklink/decklink.h index db268b8a8..060a9ca6f 100644 --- a/modules/decklink/decklink.h +++ b/modules/decklink/decklink.h @@ -24,11 +24,17 @@ #include #include -namespace caspar { namespace decklink { +#include -void init(); +namespace caspar { +namespace core { -std::wstring version(); -std::vector device_list(); +class system_info_provider_repository; + +} + +namespace decklink { + +void init(const spl::shared_ptr& repo); }} \ No newline at end of file diff --git a/modules/ffmpeg/ffmpeg.cpp b/modules/ffmpeg/ffmpeg.cpp index 9a5d650f4..b0b59ae80 100644 --- a/modules/ffmpeg/ffmpeg.cpp +++ b/modules/ffmpeg/ffmpeg.cpp @@ -21,6 +21,8 @@ #include "StdAfx.h" +#include "ffmpeg.h" + #include "consumer/ffmpeg_consumer.h" #include "producer/ffmpeg_producer.h" #include "producer/util/util.h" @@ -31,6 +33,9 @@ #include #include #include +#include + +#include #include @@ -198,7 +203,41 @@ void log_callback(void* ptr, int level, const char* fmt, va_list vl) //} //#pragma warning (pop) -void init(const spl::shared_ptr& media_info_repo) +std::wstring make_version(unsigned int ver) +{ + std::wstringstream str; + str << ((ver >> 16) & 0xFF) << L"." << ((ver >> 8) & 0xFF) << L"." << ((ver >> 0) & 0xFF); + return str.str(); +} + +std::wstring avcodec_version() +{ + return make_version(::avcodec_version()); +} + +std::wstring avformat_version() +{ + return make_version(::avformat_version()); +} + +std::wstring avutil_version() +{ + return make_version(::avutil_version()); +} + +std::wstring avfilter_version() +{ + return make_version(::avfilter_version()); +} + +std::wstring swscale_version() +{ + return make_version(::swscale_version()); +} + +void init( + const spl::shared_ptr& media_info_repo, + const spl::shared_ptr& system_info_repo) { av_lockmgr_register(ffmpeg_lock_callback); av_log_set_callback(log_callback); @@ -230,7 +269,14 @@ void init(const spl::shared_ptr& media_info_repo) return try_get_duration(file, info.duration, info.time_base); }); - + system_info_repo->register_system_info_provider([](boost::property_tree::wptree& info) + { + info.add(L"system.ffmpeg.avcodec", avcodec_version()); + info.add(L"system.ffmpeg.avformat", avformat_version()); + info.add(L"system.ffmpeg.avfilter", avfilter_version()); + info.add(L"system.ffmpeg.avutil", avutil_version()); + info.add(L"system.ffmpeg.swscale", swscale_version()); + }); } void uninit() @@ -240,36 +286,4 @@ void uninit() av_lockmgr_register(nullptr); } -std::wstring make_version(unsigned int ver) -{ - std::wstringstream str; - str << ((ver >> 16) & 0xFF) << L"." << ((ver >> 8) & 0xFF) << L"." << ((ver >> 0) & 0xFF); - return str.str(); -} - -std::wstring avcodec_version() -{ - return make_version(::avcodec_version()); -} - -std::wstring avformat_version() -{ - return make_version(::avformat_version()); -} - -std::wstring avutil_version() -{ - return make_version(::avutil_version()); -} - -std::wstring avfilter_version() -{ - return make_version(::avfilter_version()); -} - -std::wstring swscale_version() -{ - return make_version(::swscale_version()); -} - }} \ No newline at end of file diff --git a/modules/ffmpeg/ffmpeg.h b/modules/ffmpeg/ffmpeg.h index 1119f0033..e96e8b067 100644 --- a/modules/ffmpeg/ffmpeg.h +++ b/modules/ffmpeg/ffmpeg.h @@ -29,18 +29,15 @@ namespace caspar { namespace core { struct media_info_repository; +class system_info_provider_repository; } namespace ffmpeg { -void init(const spl::shared_ptr& media_info_repo); +void init( + const spl::shared_ptr& media_info_repo, + const spl::shared_ptr& system_info_repo); void uninit(); -std::wstring avcodec_version(); -std::wstring avformat_version(); -std::wstring avutil_version(); -std::wstring avfilter_version(); -std::wstring swscale_version(); - }} \ No newline at end of file diff --git a/modules/flash/flash.cpp b/modules/flash/flash.cpp index 753ec25a1..5e35599cf 100644 --- a/modules/flash/flash.cpp +++ b/modules/flash/flash.cpp @@ -31,12 +31,20 @@ #include #include +#include + +#include #include namespace caspar { namespace flash { -void init(const spl::shared_ptr& media_info_repo) +std::wstring version(); +std::wstring cg_version(); + +void init( + const spl::shared_ptr& media_info_repo, + const spl::shared_ptr& info_provider_repo) { core::register_producer_factory(create_ct_producer); core::register_producer_factory(create_swf_producer); @@ -49,6 +57,12 @@ void init(const spl::shared_ptr& media_info_repo) return true; }); + info_provider_repo->register_system_info_provider([](boost::property_tree::wptree& info) + { + info.add(L"system.flash", version()); + }); + info_provider_repo->register_version_provider(L"FLASH", &version); + info_provider_repo->register_version_provider(L"TEMPLATEHOST", &cg_version); } std::wstring cg_version() diff --git a/modules/flash/flash.h b/modules/flash/flash.h index 945ebb359..1dcec3550 100644 --- a/modules/flash/flash.h +++ b/modules/flash/flash.h @@ -21,8 +21,6 @@ #pragma once -#include - #include namespace caspar { @@ -30,14 +28,14 @@ namespace caspar { namespace core { struct media_info_repository; +class system_info_provider_repository; } namespace flash { -void init(const spl::shared_ptr& media_info_repo); - -std::wstring cg_version(); -std::wstring version(); +void init( + const spl::shared_ptr& media_info_repo, + const spl::shared_ptr& info_provider_repo); }} \ No newline at end of file diff --git a/modules/image/image.cpp b/modules/image/image.cpp index d912afe5d..ffad16b3a 100644 --- a/modules/image/image.cpp +++ b/modules/image/image.cpp @@ -29,14 +29,24 @@ #include #include #include +#include #include +#include + #include namespace caspar { namespace image { -void init(const spl::shared_ptr& repo) +std::wstring version() +{ + return u16(FreeImage_GetVersion()); +} + +void init( + const spl::shared_ptr& repo, + const spl::shared_ptr& system_info_repo) { FreeImage_Initialise(); core::register_producer_factory(create_scroll_producer); @@ -60,6 +70,10 @@ void init(const spl::shared_ptr& repo) return false; }); + system_info_repo->register_system_info_provider([](boost::property_tree::wptree& info) + { + info.add(L"system.freeimage", version()); + }); } void uninit() @@ -67,10 +81,4 @@ void uninit() FreeImage_DeInitialise(); } - -std::wstring version() -{ - return u16(FreeImage_GetVersion()); -} - -}} \ No newline at end of file +}} diff --git a/modules/image/image.h b/modules/image/image.h index 8a7655ef4..888865052 100644 --- a/modules/image/image.h +++ b/modules/image/image.h @@ -30,14 +30,15 @@ namespace caspar { namespace core { struct media_info_repository; +class system_info_provider_repository; } namespace image { -void init(const spl::shared_ptr& repo); +void init( + const spl::shared_ptr& repo, + const spl::shared_ptr& system_info_repo); void uninit(); -std::wstring version(); - -}} \ No newline at end of file +}} diff --git a/protocol/amcp/AMCPCommandsImpl.cpp b/protocol/amcp/AMCPCommandsImpl.cpp index 48f323ba3..44224daeb 100644 --- a/protocol/amcp/AMCPCommandsImpl.cpp +++ b/protocol/amcp/AMCPCommandsImpl.cpp @@ -48,17 +48,13 @@ #include #include #include +#include #include -#include -#include -#include #include #include #include #include -#include -#include #include #include @@ -1523,19 +1519,8 @@ bool InfoCommand::DoExecute() info.add(L"system.name", caspar::system_product_name()); info.add(L"system.os.description", caspar::os_description()); info.add(L"system.cpu", caspar::cpu_info()); - - for (auto& device : caspar::decklink::device_list()) - info.add(L"system.decklink.device", device); - for (auto& device : caspar::bluefish::device_list()) - info.add(L"system.bluefish.device", device); - - info.add(L"system.flash", caspar::flash::version()); - info.add(L"system.ffmpeg.avcodec", caspar::ffmpeg::avcodec_version()); - info.add(L"system.ffmpeg.avformat", caspar::ffmpeg::avformat_version()); - info.add(L"system.ffmpeg.avfilter", caspar::ffmpeg::avfilter_version()); - info.add(L"system.ffmpeg.avutil", caspar::ffmpeg::avutil_version()); - info.add(L"system.ffmpeg.swscale", caspar::ffmpeg::swscale_version()); + repo_->fill_information(info); boost::property_tree::write_xml(replyString, info, w); } @@ -1665,14 +1650,14 @@ bool VersionCommand::DoExecute() { std::wstring replyString = L"201 VERSION OK\r\n" + env::version() + L"\r\n"; - if(parameters().size() > 0) + if (parameters().size() > 0 && !boost::iequals(parameters()[0], L"SERVER")) { - if(boost::iequals(parameters()[0], L"FLASH")) - replyString = L"201 VERSION OK\r\n" + flash::version() + L"\r\n"; - else if(boost::iequals(parameters()[0], L"TEMPLATEHOST")) - replyString = L"201 VERSION OK\r\n" + flash::cg_version() + L"\r\n"; - else if(!boost::iequals(parameters()[0], L"SERVER")) + auto version = repo_->get_version(parameters().at(0)); + + if (version.empty()) replyString = L"403 VERSION ERROR\r\n"; + else + replyString = L"201 VERSION OK\r\n" + version + L"\r\n"; } SetReplyString(replyString); diff --git a/protocol/amcp/AMCPCommandsImpl.h b/protocol/amcp/AMCPCommandsImpl.h index a4763ae1e..6a9cd468b 100644 --- a/protocol/amcp/AMCPCommandsImpl.h +++ b/protocol/amcp/AMCPCommandsImpl.h @@ -25,6 +25,7 @@ #include #include +#include #include @@ -260,17 +261,28 @@ private: class InfoCommand : public AMCPCommandBase<0>, AMCPChannelsAwareCommand { public: - InfoCommand(IO::ClientInfoPtr client, const std::vector& channels) : AMCPChannelsAwareCommand(channels), AMCPCommandBase(client) {} + InfoCommand(IO::ClientInfoPtr client, const std::vector& channels, const spl::shared_ptr& repo) + : AMCPChannelsAwareCommand(channels) + , AMCPCommandBase(client) + , repo_(repo) + {} std::wstring print() const { return L"InfoCommand";} bool DoExecute(); +private: + spl::shared_ptr repo_; }; class VersionCommand : public AMCPCommandBase<0> { public: - explicit VersionCommand(IO::ClientInfoPtr client) : AMCPCommandBase(client) {} + explicit VersionCommand(IO::ClientInfoPtr client, const spl::shared_ptr& repo) + : AMCPCommandBase(client) + , repo_(repo) + {} std::wstring print() const { return L"VersionCommand";} bool DoExecute(); +private: + spl::shared_ptr repo_; }; class ByeCommand : public AMCPCommandBase<0> diff --git a/protocol/amcp/AMCPProtocolStrategy.cpp b/protocol/amcp/AMCPProtocolStrategy.cpp index d6dce4ad2..a918e7dce 100644 --- a/protocol/amcp/AMCPProtocolStrategy.cpp +++ b/protocol/amcp/AMCPProtocolStrategy.cpp @@ -51,20 +51,23 @@ using IO::ClientInfoPtr; struct AMCPProtocolStrategy::impl { private: - std::vector channels_; - std::vector commandQueues_; - std::shared_ptr thumb_gen_; - spl::shared_ptr media_info_repo_; - std::promise& shutdown_server_now_; + std::vector channels_; + std::vector commandQueues_; + std::shared_ptr thumb_gen_; + spl::shared_ptr media_info_repo_; + spl::shared_ptr system_info_provider_repo_; + std::promise& shutdown_server_now_; public: impl( const std::vector>& channels, const std::shared_ptr& thumb_gen, const spl::shared_ptr& media_info_repo, + const spl::shared_ptr& system_info_provider_repo, std::promise& shutdown_server_now) : thumb_gen_(thumb_gen) , media_info_repo_(media_info_repo) + , system_info_provider_repo_(system_info_provider_repo) , shutdown_server_now_(shutdown_server_now) { commandQueues_.push_back(std::make_shared()); @@ -355,20 +358,20 @@ private: AMCPCommand::ptr_type create_command(const std::wstring& str, ClientInfoPtr client) { std::wstring s = boost::to_upper_copy(str); - if(s == L"DIAG") return std::make_shared(client); - else if(s == L"CHANNEL_GRID") return std::make_shared(client, channels_); - else if(s == L"DATA") return std::make_shared(client); - else if(s == L"CINF") return std::make_shared(client, media_info_repo_); - else if(s == L"INFO") return std::make_shared(client, channels_); - else if(s == L"CLS") return std::make_shared(client, media_info_repo_); - else if(s == L"TLS") return std::make_shared(client); - else if(s == L"VERSION") return std::make_shared(client); - else if(s == L"BYE") return std::make_shared(client); - else if(s == L"LOCK") return std::make_shared(client, channels_); - else if(s == L"LOG") return std::make_shared(client); - else if(s == L"THUMBNAIL") return std::make_shared(client, thumb_gen_); - else if(s == L"KILL") return std::make_shared(client, shutdown_server_now_); - else if(s == L"RESTART") return std::make_shared(client, shutdown_server_now_); + if ( s == L"DIAG") return std::make_shared(client); + else if (s == L"CHANNEL_GRID") return std::make_shared(client, channels_); + else if (s == L"DATA") return std::make_shared(client); + else if (s == L"CINF") return std::make_shared(client, media_info_repo_); + else if (s == L"INFO") return std::make_shared(client, channels_, system_info_provider_repo_); + else if (s == L"CLS") return std::make_shared(client, media_info_repo_); + else if (s == L"TLS") return std::make_shared(client); + else if (s == L"VERSION") return std::make_shared(client, system_info_provider_repo_); + else if (s == L"BYE") return std::make_shared(client); + else if (s == L"LOCK") return std::make_shared(client, channels_); + else if (s == L"LOG") return std::make_shared(client); + else if (s == L"THUMBNAIL") return std::make_shared(client, thumb_gen_); + else if (s == L"KILL") return std::make_shared(client, shutdown_server_now_); + else if (s == L"RESTART") return std::make_shared(client, shutdown_server_now_); return nullptr; } @@ -401,8 +404,9 @@ AMCPProtocolStrategy::AMCPProtocolStrategy( const std::vector>& channels, const std::shared_ptr& thumb_gen, const spl::shared_ptr& media_info_repo, + const spl::shared_ptr& system_info_provider_repo, std::promise& shutdown_server_now) - : impl_(spl::make_unique(channels, thumb_gen, media_info_repo, shutdown_server_now)) + : impl_(spl::make_unique(channels, thumb_gen, media_info_repo, system_info_provider_repo, shutdown_server_now)) { } AMCPProtocolStrategy::~AMCPProtocolStrategy() {} diff --git a/protocol/amcp/AMCPProtocolStrategy.h b/protocol/amcp/AMCPProtocolStrategy.h index 7afd59254..b65915dd1 100644 --- a/protocol/amcp/AMCPProtocolStrategy.h +++ b/protocol/amcp/AMCPProtocolStrategy.h @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -40,10 +41,11 @@ class AMCPProtocolStrategy : public IO::IProtocolStrategy, boost::noncopyable { public: AMCPProtocolStrategy( - const std::vector>& channels, - const std::shared_ptr& thumb_gen, - const spl::shared_ptr& media_info_repo, - std::promise& shutdown_server_now); + const std::vector>& channels, + const std::shared_ptr& thumb_gen, + const spl::shared_ptr& media_info_repo, + const spl::shared_ptr& system_info_provider_repo, + std::promise& shutdown_server_now); virtual ~AMCPProtocolStrategy(); diff --git a/shell/main.cpp b/shell/main.cpp index 233740edd..d08d97b91 100644 --- a/shell/main.cpp +++ b/shell/main.cpp @@ -48,12 +48,6 @@ #include #include -#include -#include -#include -#include -#include - #include #include #include @@ -61,6 +55,8 @@ #include #include +#include + #include #include #include @@ -146,22 +142,44 @@ void print_info() CASPAR_LOG(info) << L"on " << os_description(); CASPAR_LOG(info) << cpu_info(); CASPAR_LOG(info) << system_product_name(); +} + +void print_child(const std::wstring& indent, const std::wstring& elem, const boost::property_tree::wptree& tree) +{ + auto data = tree.data(); + + if (data.empty()) + CASPAR_LOG(info) << indent << elem; + else + CASPAR_LOG(info) << indent << elem << L" " << tree.data(); + + for (auto& child : tree) + print_child(indent + L" ", child.first, child.second); +} + +void print_system_info(const spl::shared_ptr& repo) +{ + boost::property_tree::wptree info; + repo->fill_information(info); - CASPAR_LOG(info) << L"Decklink " << decklink::version(); + /*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; - - 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" - " << 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(); + CASPAR_LOG(info) << L"FFMPEG-swscale " << ffmpeg::swscale_version();*/ } LONG WINAPI UserUnhandledExceptionFilter(EXCEPTION_POINTERS* info) @@ -196,6 +214,7 @@ void do_run(server& caspar_server, std::promise& shutdown_server_now) caspar_server.channels(), caspar_server.get_thumbnail_generator(), caspar_server.get_media_info_repo(), + caspar_server.get_system_info_provider_repo(), shutdown_server_now)))->create(console_client); std::wstring wcmd; @@ -294,9 +313,21 @@ bool run() std::promise shutdown_server_now; std::future shutdown_server = shutdown_server_now.get_future(); + print_info(); + // Create server object which initializes channels, protocols and controllers. server caspar_server(shutdown_server_now); + // Print environment information. + print_system_info(caspar_server.get_system_info_provider_repo()); + + std::wstringstream str; + boost::property_tree::xml_writer_settings w(' ', 3); + boost::property_tree::write_xml(str, env::properties(), w); + CASPAR_LOG(info) << L"casparcg.config:\n-----------------------------------------\n" << str.str().c_str() << L"-----------------------------------------"; + + caspar_server.start(); + //auto console_obs = reactive::make_observer([](const monitor::event& e) //{ // std::stringstream str; @@ -388,14 +419,6 @@ int main(int argc, wchar_t* argv[]) // Setup console window. setup_console_window(); - // Print environment information. - print_info(); - - std::wstringstream str; - boost::property_tree::xml_writer_settings w(' ', 3); - boost::property_tree::write_xml(str, env::properties(), w); - CASPAR_LOG(info) << L"casparcg.config:\n-----------------------------------------\n" << str.str().c_str() << L"-----------------------------------------"; - return_code = run() ? 5 : 0; Sleep(500); diff --git a/shell/server.cpp b/shell/server.cpp index ba8ef8aca..ce3657a67 100644 --- a/shell/server.cpp +++ b/shell/server.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -98,6 +99,7 @@ struct server::impl : boost::noncopyable std::vector> channels_; spl::shared_ptr media_info_repo_; boost::thread initial_media_info_thread_; + spl::shared_ptr system_info_provider_repo_; tbb::atomic running_; std::shared_ptr thumbnail_generator_; std::promise& shutdown_server_now_; @@ -108,17 +110,17 @@ struct server::impl : boost::noncopyable , media_info_repo_(create_in_memory_media_info_repository()) , shutdown_server_now_(shutdown_server_now) { - running_ = true; + running_ = false; core::diagnostics::osd::register_sink(); diag_subject_->attach_parent(monitor_subject_); - ffmpeg::init(media_info_repo_); + ffmpeg::init(media_info_repo_, system_info_provider_repo_); CASPAR_LOG(info) << L"Initialized ffmpeg module."; - bluefish::init(); + bluefish::init(system_info_provider_repo_); CASPAR_LOG(info) << L"Initialized bluefish module."; - decklink::init(); + decklink::init(system_info_provider_repo_); CASPAR_LOG(info) << L"Initialized decklink module."; oal::init(); @@ -127,10 +129,10 @@ struct server::impl : boost::noncopyable screen::init(); CASPAR_LOG(info) << L"Initialized ogl module."; - image::init(media_info_repo_); + image::init(media_info_repo_, system_info_provider_repo_); CASPAR_LOG(info) << L"Initialized image module."; - flash::init(media_info_repo_); + flash::init(media_info_repo_, system_info_provider_repo_); CASPAR_LOG(info) << L"Initialized flash module."; psd::init(); @@ -140,6 +142,11 @@ struct server::impl : boost::noncopyable register_producer_factory(&core::scene::create_dummy_scene_producer); register_producer_factory(&core::scene::create_xml_scene_producer); + } + + void start() + { + running_ = true; setup_channels(env::properties()); CASPAR_LOG(info) << L"Initialized channels."; @@ -159,8 +166,12 @@ struct server::impl : boost::noncopyable ~impl() { - running_ = false; - initial_media_info_thread_.join(); + if (running_) + { + running_ = false; + initial_media_info_thread_.join(); + } + thumbnail_generator_.reset(); primary_amcp_server_.reset(); async_servers_.clear(); @@ -322,7 +333,7 @@ struct server::impl : boost::noncopyable using namespace IO; if(boost::iequals(name, L"AMCP")) - return wrap_legacy_protocol("\r\n", spl::make_shared(channels_, thumbnail_generator_, media_info_repo_, shutdown_server_now_)); + return wrap_legacy_protocol("\r\n", spl::make_shared(channels_, thumbnail_generator_, media_info_repo_, system_info_provider_repo_, shutdown_server_now_)); else if(boost::iequals(name, L"CII")) return wrap_legacy_protocol("\r\n", spl::make_shared(channels_)); else if(boost::iequals(name, L"CLOCK")) @@ -357,13 +368,14 @@ struct server::impl : boost::noncopyable }; server::server(std::promise& shutdown_server_now) : impl_(new impl(shutdown_server_now)){} - +void server::start() { impl_->start(); } const std::vector> server::channels() const { return impl_->channels_; } std::shared_ptr server::get_thumbnail_generator() const {return impl_->thumbnail_generator_; } spl::shared_ptr server::get_media_info_repo() const { return impl_->media_info_repo_; } +spl::shared_ptr server::get_system_info_provider_repo() const { return impl_->system_info_provider_repo_; } core::monitor::subject& server::monitor_output() { return *impl_->monitor_subject_; } } diff --git a/shell/server.h b/shell/server.h index 6f21f7d5a..c7a0801f8 100644 --- a/shell/server.h +++ b/shell/server.h @@ -36,15 +36,18 @@ namespace core { class video_channel; class thumbnail_generator; struct media_info_repository; + class system_info_provider_repository; } class server final : public boost::noncopyable { public: explicit server(std::promise& shutdown_server_now); + void start(); const std::vector> channels() const; std::shared_ptr get_thumbnail_generator() const; spl::shared_ptr get_media_info_repo() const; + spl::shared_ptr get_system_info_provider_repo() const; core::monitor::subject& monitor_output(); private: -- 2.39.2