X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=shell%2Fserver.cpp;h=87b7e105c3303aa203e0fd4f10c1c117a2012554;hb=f448ec11e7f03bd25d9e578ba95a921edbad20e1;hp=76b0d3556d75276859d420484dffd4ece8ec575a;hpb=a36f794e330f7a29ea4583868290817c483c10ae;p=casparcg diff --git a/shell/server.cpp b/shell/server.cpp index 76b0d3556..87b7e105c 100644 --- a/shell/server.cpp +++ b/shell/server.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -41,8 +42,11 @@ #include #include #include +#include #include +#include #include +#include #include #include #include @@ -51,6 +55,7 @@ #include #include #include +#include #include #include @@ -64,6 +69,7 @@ #include #include #include +#include #include #include @@ -103,12 +109,15 @@ std::shared_ptr create_running_io_service() CASPAR_LOG_CURRENT_EXCEPTION(); } } + + CASPAR_LOG(info) << "[asio] Global io_service uninitialized."; }); return std::shared_ptr( service.get(), [service, work, thread](void*) mutable { + CASPAR_LOG(info) << "[asio] Shutting down global io_service."; work.reset(); service->stop(); if (thread->get_id() != boost::this_thread::get_id()) @@ -141,7 +150,7 @@ struct server::impl : boost::noncopyable std::shared_ptr thumbnail_generator_; std::promise& shutdown_server_now_; - explicit impl(std::promise& shutdown_server_now) + explicit impl(std::promise& shutdown_server_now) : accelerator_(env::properties().get(L"configuration.accelerator", L"auto")) , media_info_repo_(create_in_memory_media_info_repository()) , producer_registry_(spl::make_shared(help_repo_)) @@ -149,7 +158,8 @@ struct server::impl : boost::noncopyable , shutdown_server_now_(shutdown_server_now) { running_ = false; - core::diagnostics::osd::register_sink(); + core::diagnostics::register_graph_to_log_sink(); + caspar::core::diagnostics::osd::register_sink(); diag_subject_->attach_parent(monitor_subject_); module_dependencies dependencies( @@ -161,7 +171,10 @@ struct server::impl : boost::noncopyable initialize_modules(dependencies); core::text::init(dependencies); + core::init_cg_proxy_as_producer(dependencies); core::scene::init(dependencies); + core::syncto::init(dependencies); + help_repo_->register_item({ L"producer" }, L"Color Producer", &core::describe_color_producer); } void start() @@ -205,7 +218,7 @@ struct server::impl : boost::noncopyable destroy_producers_synchronously(); destroy_consumers_synchronously(); channels_.clear(); - + while (weak_io_service.lock()) boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); @@ -228,82 +241,110 @@ struct server::impl : boost::noncopyable auto custom_mix_configs = pt.get_child_optional(L"configuration.audio.mix-configs"); if (custom_channel_layouts) + { + CASPAR_SCOPED_CONTEXT_MSG("/configuration/audio/channel-layouts"); audio_channel_layout_repository::get_default()->register_all_layouts(*custom_channel_layouts); + } if (custom_mix_configs) + { + CASPAR_SCOPED_CONTEXT_MSG("/configuration/audio/mix-configs"); audio_mix_config_repository::get_default()->register_all_configs(*custom_mix_configs); + } } void setup_channels(const boost::property_tree::wptree& pt) - { + { using boost::property_tree::wptree; - for (auto& xml_channel : pt.get_child(L"configuration.channels")) - { - auto format_desc = video_format_desc(xml_channel.second.get(L"video-mode", L"PAL")); + + std::vector xml_channels; + + for (auto& xml_channel : pt | witerate_children(L"configuration.channels") | welement_context_iteration) + { + xml_channels.push_back(xml_channel.second); + ptree_verify_element_name(xml_channel, L"channel"); + + auto format_desc_str = xml_channel.second.get(L"video-mode", L"PAL"); + auto format_desc = video_format_desc(format_desc_str); if(format_desc.format == video_format::invalid) - CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Invalid video-mode.")); + CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Invalid video-mode: " + format_desc_str)); - auto channel_layout = core::audio_channel_layout_repository::get_default()->get_layout(xml_channel.second.get(L"channel-layout", L"stereo")); + auto channel_layout_str = xml_channel.second.get(L"channel-layout", L"stereo"); + auto channel_layout = core::audio_channel_layout_repository::get_default()->get_layout(channel_layout_str); if (!channel_layout) - CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Unknown channel-layout.")); + CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Unknown channel-layout: " + channel_layout_str)); + + auto channel_id = static_cast(channels_.size() + 1); + auto channel = spl::make_shared(channel_id, format_desc, *channel_layout, accelerator_.create_image_mixer(channel_id)); - auto channel = spl::make_shared(static_cast(channels_.size()+1), format_desc, *channel_layout, accelerator_.create_image_mixer()); + channel->monitor_output().attach_parent(monitor_subject_); + channel->mixer().set_straight_alpha_output(xml_channel.second.get(L"straight-alpha-output", false)); + channels_.push_back(channel); + } + for (auto& channel : channels_) + { core::diagnostics::scoped_call_context save; core::diagnostics::call_context::for_thread().video_channel = channel->index(); - - for (auto& xml_consumer : xml_channel.second.get_child(L"consumers")) + + for (auto& xml_consumer : xml_channels.at(channel->index() - 1) | witerate_children(L"consumers") | welement_context_iteration) { + auto name = xml_consumer.first; + try { - auto name = xml_consumer.first; - if (name != L"") - channel->output().add(consumer_registry_->create_consumer(name, xml_consumer.second, &channel->stage())); + channel->output().add(consumer_registry_->create_consumer(name, xml_consumer.second, &channel->stage(), channels_)); + } + catch (const user_error& e) + { + CASPAR_LOG_CURRENT_EXCEPTION_AT_LEVEL(debug); + CASPAR_LOG(error) << get_message_and_context(e) << " Turn on log level debug for stacktrace."; } - catch(...) + catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); } - } - - channel->monitor_output().attach_parent(monitor_subject_); - channel->mixer().set_straight_alpha_output(xml_channel.second.get(L"straight-alpha-output", false)); - channels_.push_back(channel); + } } // Dummy diagnostics channel if (env::properties().get(L"configuration.channel-grid", false)) { + auto channel_id = static_cast(channels_.size() + 1); channels_.push_back(spl::make_shared( - static_cast(channels_.size() + 1), + channel_id, core::video_format_desc(core::video_format::x576p2500), *core::audio_channel_layout_repository::get_default()->get_layout(L"stereo"), - accelerator_.create_image_mixer())); + accelerator_.create_image_mixer(channel_id))); channels_.back()->monitor_output().attach_parent(monitor_subject_); } } void setup_osc(const boost::property_tree::wptree& pt) - { + { using boost::property_tree::wptree; using namespace boost::asio::ip; monitor_subject_->attach_parent(osc_client_->sink()); - + auto default_port = pt.get(L"configuration.osc.default-port", 6250); + auto disable_send_to_amcp_clients = + pt.get(L"configuration.osc.disable-send-to-amcp-clients", false); auto predefined_clients = pt.get_child_optional(L"configuration.osc.predefined-clients"); if (predefined_clients) { - for (auto& predefined_client : *predefined_clients) + for (auto& predefined_client : pt | witerate_children(L"configuration.osc.predefined-clients") | welement_context_iteration) { + ptree_verify_element_name(predefined_client, L"predefined-client"); + const auto address = - predefined_client.second.get(L"address"); + ptree_get(predefined_client.second, L"address"); const auto port = - predefined_client.second.get(L"port"); + ptree_get(predefined_client.second, L"port"); predefined_osc_subscriptions_.push_back( osc_client_->get_subscription_token(udp::endpoint( address_v4::from_string(u8(address)), @@ -311,7 +352,7 @@ struct server::impl : boost::noncopyable } } - if (primary_amcp_server_) + if (!disable_send_to_amcp_clients && primary_amcp_server_) primary_amcp_server_->add_client_lifecycle_object_factory( [=] (const std::string& ipv4_address) -> std::pair> @@ -337,22 +378,21 @@ struct server::impl : boost::noncopyable polling_filesystem_monitor_factory monitor_factory(io_service_, scan_interval_millis); thumbnail_generator_.reset(new thumbnail_generator( - monitor_factory, + monitor_factory, env::media_folder(), - env::thumbnails_folder(), + env::thumbnail_folder(), pt.get(L"configuration.thumbnails.width", 256), pt.get(L"configuration.thumbnails.height", 144), core::video_format_desc(pt.get(L"configuration.thumbnails.video-mode", L"720p2500")), - accelerator_.create_image_mixer(), + accelerator_.create_image_mixer(0), pt.get(L"configuration.thumbnails.generate-delay-millis", 2000), &image::write_cropped_png, media_info_repo_, producer_registry_, + cg_registry_, pt.get(L"configuration.thumbnails.mipmap", true))); - - CASPAR_LOG(info) << L"Initialized thumbnail generator."; } - + void setup_controllers(const boost::property_tree::wptree& pt) { amcp_command_repo_ = spl::make_shared( @@ -364,36 +404,30 @@ struct server::impl : boost::noncopyable help_repo_, producer_registry_, consumer_registry_, + accelerator_.get_ogl_device(), shutdown_server_now_); amcp::register_commands(*amcp_command_repo_); using boost::property_tree::wptree; - for (auto& xml_controller : pt.get_child(L"configuration.controllers")) + for (auto& xml_controller : pt | witerate_children(L"configuration.controllers") | welement_context_iteration) { - try - { - auto name = xml_controller.first; - auto protocol = xml_controller.second.get(L"protocol"); - - if(name == L"tcp") - { - unsigned int port = xml_controller.second.get(L"port", 5250); - auto asyncbootstrapper = spl::make_shared( - io_service_, - create_protocol(protocol, L"TCP Port " + boost::lexical_cast(port)), - port); - async_servers_.push_back(asyncbootstrapper); - - if (!primary_amcp_server_ && boost::iequals(protocol, L"AMCP")) - primary_amcp_server_ = asyncbootstrapper; - } - else - CASPAR_LOG(warning) << "Invalid controller: " << name; - } - catch(...) + auto name = xml_controller.first; + auto protocol = ptree_get(xml_controller.second, L"protocol"); + + if(name == L"tcp") { - CASPAR_LOG_CURRENT_EXCEPTION(); + auto port = ptree_get(xml_controller.second, L"port"); + auto asyncbootstrapper = spl::make_shared( + io_service_, + create_protocol(protocol, L"TCP Port " + boost::lexical_cast(port)), + port); + async_servers_.push_back(asyncbootstrapper); + + if (!primary_amcp_server_ && boost::iequals(protocol, L"AMCP")) + primary_amcp_server_ = asyncbootstrapper; } + else + CASPAR_LOG(warning) << "Invalid controller: " << name; } } @@ -409,8 +443,10 @@ struct server::impl : boost::noncopyable return spl::make_shared( "ISO-8859-1", spl::make_shared(channels_, cg_registry_, producer_registry_)); - - CASPAR_THROW_EXCEPTION(caspar_exception() << arg_name_info(L"name") << arg_value_info(name) << msg_info(L"Invalid protocol")); + else if (boost::iequals(name, L"LOG")) + return spl::make_shared(); + + CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Invalid protocol: " + name)); } void start_initial_media_info_scan()