#include "AMCPCommandsImpl.h"
#include "amcp_command_repository.h"
+#include "AMCPCommandQueue.h"
#include <common/env.h>
#include <common/os/system_info.h>
#include <common/os/filesystem.h>
#include <common/base64.h>
+#include <common/thread_info.h>
+#include <common/filesystem.h>
#include <core/producer/cg_proxy.h>
#include <core/producer/frame_producer.h>
#include <core/help/util.h>
#include <core/video_format.h>
#include <core/producer/transition/transition_producer.h>
+#include <core/frame/audio_channel_layout.h>
#include <core/frame/frame_transform.h>
+#include <core/producer/text/text_producer.h>
#include <core/producer/stage.h>
#include <core/producer/layer.h>
#include <core/mixer/mixer.h>
auto is_not_digit = [](char c){ return std::isdigit(c) == 0; };
- auto relativePath = boost::filesystem::path(path.wstring().substr(env::media_folder().size() - 1, path.wstring().size()));
-
auto writeTimeStr = boost::posix_time::to_iso_string(boost::posix_time::from_time_t(boost::filesystem::last_write_time(path)));
writeTimeStr.erase(std::remove_if(writeTimeStr.begin(), writeTimeStr.end(), is_not_digit), writeTimeStr.end());
auto writeTimeWStr = std::wstring(writeTimeStr.begin(), writeTimeStr.end());
sizeStr.erase(std::remove_if(sizeStr.begin(), sizeStr.end(), is_not_digit), sizeStr.end());
auto sizeWStr = std::wstring(sizeStr.begin(), sizeStr.end());
- auto str = relativePath.replace_extension(L"").generic_wstring();
+ auto relativePath = get_relative_without_extension(path, env::media_folder());
+ auto str = relativePath.generic_wstring();
+
if (str[0] == '\\' || str[0] == '/')
str = std::wstring(str.begin() + 1, str.end());
{
if(boost::filesystem::is_regular_file(itr->path()) && cg_registry->is_cg_extension(itr->path().extension().wstring()))
{
- auto relativePath = boost::filesystem::path(itr->path().wstring().substr(env::template_folder().size()-1, itr->path().wstring().size()));
+ auto relativePath = get_relative_without_extension(itr->path(), env::template_folder());
auto writeTimeStr = boost::posix_time::to_iso_string(boost::posix_time::from_time_t(boost::filesystem::last_write_time(itr->path())));
writeTimeStr.erase(std::remove_if(writeTimeStr.begin(), writeTimeStr.end(), [](char c){ return std::isdigit(c) == 0;}), writeTimeStr.end());
auto file = boost::to_upper_copy(relativePath.filename().wstring());
relativePath = dir / file;
- auto str = relativePath.replace_extension(L"").generic_wstring();
+ auto str = relativePath.generic_wstring();
boost::trim_if(str, boost::is_any_of("\\/"));
+ auto template_type = cg_registry->get_cg_producer_name(str);
+
replyString << L"\"" << str
<< L"\" " << sizeWStr
<< L" " << writeTimeWStr
+ << L" " << template_type
<< L"\r\n";
}
}
std::wstring call_command(command_context& ctx)
{
- auto result = ctx.channel.channel->stage().call(ctx.layer_index(), ctx.parameters);
+ auto result = ctx.channel.channel->stage().call(ctx.layer_index(), ctx.parameters).get();
// TODO: because of std::async deferred timed waiting does not work
CASPAR_THROW_EXCEPTION(timed_out());*/
std::wstringstream replyString;
- if (result.get().empty())
+ if (result.empty())
replyString << L"202 CALL OK\r\n";
else
- replyString << L"201 CALL OK\r\n" << result.get() << L"\r\n";
+ replyString << L"201 CALL OK\r\n" << result << L"\r\n";
return replyString.str();
}
void add_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Add a consumer to a video channel.");
- sink.syntax(L"ADD [video_channel:int] [consumer:string] [parameters:string]");
+ sink.syntax(L"ADD [video_channel:int]{-[consumer_index:int]} [consumer:string] [parameters:string]");
sink.para()
->text(L"Adds a consumer to the specified video channel. The string ")
->code(L"consumer")->text(L" will be parsed by the available consumer factories. ")
->code(L"video_channel")->text(L". Different consumers require different parameters, ")
->text(L"some examples are below. Consumers can alternatively be specified by adding them to ")
->see(L"the CasparCG config file")->text(L".");
+ sink.para()
+ ->text(L"Specifying ")->code(L"consumer_index")
+ ->text(L" overrides the index that the consumer itself decides and can later be used with the ")
+ ->see(L"REMOVE")->text(L" command to remove the consumer.");
sink.para()->text(L"Examples:");
sink.example(L">> ADD 1 DECKLINK 1");
sink.example(L">> ADD 1 BLUEFISH 2");
sink.example(L">> ADD 1 IMAGE filename");
sink.example(L">> ADD 1 FILE filename.mov");
sink.example(L">> ADD 1 FILE filename.mov SEPARATE_KEY");
+ sink.example(
+ L">> ADD 1-700 FILE filename.mov SEPARATE_KEY\n"
+ L">> REMOVE 1-700", L"overriding the consumer index to easier remove later.");
sink.para()->text(L"The streaming consumer is an implementation of the ffmpeg_consumer and supports many of the same arguments:");
sink.example(L">> ADD 1 STREAM udp://localhost:5004 -vcodec libx264 -tune zerolatency -preset ultrafast -crf 25 -format mpegts -vf scale=240:180");
}
return L"202 LOG OK\r\n";
}
+void log_category_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+ sink.short_description(L"Enable/disable a logging category in the server.");
+ sink.syntax(L"LOG CATEGORY [category:calltrace,communication] [enable:0,1]");
+ sink.para()->text(L"Enables or disables the specified logging category.");
+ sink.para()->text(L"Examples:");
+ sink.example(L">> LOG CATEGORY calltrace 1", L"to enable call trace");
+ sink.example(L">> LOG CATEGORY calltrace 0", L"to disable call trace");
+}
+
+std::wstring log_category_command(command_context& ctx)
+{
+ log::set_log_category(ctx.parameters.at(0), ctx.parameters.at(1) == L"1");
+
+ return L"202 LOG OK\r\n";
+}
+
void set_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Change the value of a channel variable.");
sink.syntax(L"SET [video_channel:int] [variable:string] [value:string]");
sink.para()->text(L"Changes the value of a channel variable. Available variables to set:");
sink.definitions()
- ->item(L"MODE", L"Changes the video format of the channel.");
+ ->item(L"MODE", L"Changes the video format of the channel.")
+ ->item(L"CHANNEL_LAYOUT", L"Changes the audio channel layout of the video channel channel.");
sink.para()->text(L"Examples:");
- sink.example(L">> SET 1 MODE PAL", L"changes the video mode on channel 1 to PAL");
+ sink.example(L">> SET 1 MODE PAL", L"changes the video mode on channel 1 to PAL.");
+ sink.example(L">> SET 1 CHANNEL_LAYOUT smpte", L"changes the audio channel layout on channel 1 to smpte.");
}
std::wstring set_command(command_context& ctx)
return L"202 SET MODE OK\r\n";
}
- CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(L"Invalid video mode"));
+ CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Invalid video mode"));
}
+ else if (name == L"CHANNEL_LAYOUT")
+ {
+ auto channel_layout = core::audio_channel_layout_repository::get_default()->get_layout(value);
- CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(L"Invalid channel variable"));
+ if (channel_layout)
+ {
+ ctx.channel.channel->audio_channel_layout(*channel_layout);
+ return L"202 SET CHANNEL_LAYOUT OK\r\n";
+ }
+
+ CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Invalid audio channel layout"));
+ }
+
+ CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Invalid channel variable"));
}
void data_store_describer(core::help_sink& sink, const core::help_repository& repo)
if (!boost::iequals(itr->path().extension().wstring(), L".ftd"))
continue;
- auto relativePath = boost::filesystem::path(itr->path().wstring().substr(env::data_folder().size() - 1, itr->path().wstring().size()));
+ auto relativePath = get_relative_without_extension(itr->path(), env::data_folder());
+ auto str = relativePath.generic_wstring();
- auto str = relativePath.replace_extension(L"").generic_wstring();
if (str[0] == L'\\' || str[0] == L'/')
str = std::wstring(str.begin() + 1, str.end());
if (!boost::filesystem::remove(filename))
CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(filename + L" could not be removed"));
- return L"201 DATA REMOVE OK\r\n";
+ return L"202 DATA REMOVE OK\r\n";
}
// Template Graphics Commands
-int get_and_validate_layer(const std::wstring& layerstring) {
- int length = layerstring.length();
- for (int i = 0; i < length; ++i) {
- if (!std::isdigit(layerstring[i])) {
- CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(layerstring + L" is not a layer"));
- }
- }
-
- return boost::lexical_cast<int>(layerstring);
-}
-
void cg_add_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Prepare a template for displaying.");
{
//CG 1 ADD 0 "template_folder/templatename" [STARTLABEL] 0/1 [DATA]
- int layer = get_and_validate_layer(ctx.parameters.at(0));
+ int layer = boost::lexical_cast<int>(ctx.parameters.at(0));
std::wstring label; //_parameters[2]
bool bDoStart = false; //_parameters[2] alt. _parameters[3]
unsigned int dataIndex = 3;
std::wstring cg_play_command(command_context& ctx)
{
- int layer = get_and_validate_layer(ctx.parameters.at(0));
+ int layer = boost::lexical_cast<int>(ctx.parameters.at(0));
ctx.cg_registry->get_proxy(spl::make_shared_ptr(ctx.channel.channel), ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))->play(layer);
return L"202 CG OK\r\n";
}
+spl::shared_ptr<core::cg_proxy> get_expected_cg_proxy(command_context& ctx)
+{
+ auto proxy = ctx.cg_registry->get_proxy(spl::make_shared_ptr(ctx.channel.channel), ctx.layer_index(core::cg_proxy::DEFAULT_LAYER));
+
+ if (proxy == cg_proxy::empty())
+ CASPAR_THROW_EXCEPTION(expected_user_error() << msg_info(L"No CG proxy running on layer"));
+
+ return proxy;
+}
+
void cg_stop_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Stop and remove a template.");
std::wstring cg_stop_command(command_context& ctx)
{
- int layer = get_and_validate_layer(ctx.parameters.at(0));
- ctx.cg_registry->get_proxy(spl::make_shared_ptr(ctx.channel.channel), ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))->stop(layer, 0);
+ int layer = boost::lexical_cast<int>(ctx.parameters.at(0));
+ get_expected_cg_proxy(ctx)->stop(layer, 0);
return L"202 CG OK\r\n";
}
std::wstring cg_next_command(command_context& ctx)
{
- int layer = get_and_validate_layer(ctx.parameters.at(0));
- ctx.cg_registry->get_proxy(spl::make_shared_ptr(ctx.channel.channel), ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))->next(layer);
+ int layer = boost::lexical_cast<int>(ctx.parameters.at(0));
+ get_expected_cg_proxy(ctx)->next(layer);
return L"202 CG OK\r\n";
}
std::wstring cg_remove_command(command_context& ctx)
{
- int layer = get_and_validate_layer(ctx.parameters.at(0));
- ctx.cg_registry->get_proxy(spl::make_shared_ptr(ctx.channel.channel), ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))->remove(layer);
+ int layer = boost::lexical_cast<int>(ctx.parameters.at(0));
+ get_expected_cg_proxy(ctx)->remove(layer);
return L"202 CG OK\r\n";
}
std::wstring cg_update_command(command_context& ctx)
{
- int layer = get_and_validate_layer(ctx.parameters.at(0));
+ int layer = boost::lexical_cast<int>(ctx.parameters.at(0));
std::wstring dataString = ctx.parameters.at(1);
if (dataString.at(0) != L'<' && dataString.at(0) != L'{')
dataString = read_file(boost::filesystem::path(filename));
}
- ctx.cg_registry->get_proxy(
- spl::make_shared_ptr(ctx.channel.channel),
- ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))
- ->update(layer, dataString);
+ get_expected_cg_proxy(ctx)->update(layer, dataString);
return L"202 CG OK\r\n";
}
{
std::wstringstream replyString;
replyString << L"201 CG OK\r\n";
- int layer = get_and_validate_layer(ctx.parameters.at(0));
- auto result = ctx.cg_registry->get_proxy(
- spl::make_shared_ptr(ctx.channel.channel),
- ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))
- ->invoke(layer, ctx.parameters.at(1));
+ int layer = boost::lexical_cast<int>(ctx.parameters.at(0));
+ auto result = get_expected_cg_proxy(ctx)->invoke(layer, ctx.parameters.at(1));
replyString << result << L"\r\n";
return replyString.str();
if (ctx.parameters.empty())
{
- auto info = ctx.cg_registry->get_proxy(
- spl::make_shared_ptr(ctx.channel.channel),
- ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))
- ->template_host_info();
+ auto info = get_expected_cg_proxy(ctx)->template_host_info();
replyString << info << L"\r\n";
}
else
{
- int layer = get_and_validate_layer(ctx.parameters.at(0));
- auto desc = ctx.cg_registry->get_proxy(
- spl::make_shared_ptr(ctx.channel.channel),
- ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))
- ->description(layer);
+ int layer = boost::lexical_cast<int>(ctx.parameters.at(0));
+ auto desc = get_expected_cg_proxy(ctx)->description(layer);
replyString << desc << L"\r\n";
}
void commit_deferred()
{
- ctx_.channel.channel->stage().apply_transforms(
- std::move(deferred_transforms_[ctx_.channel_index]));
+ auto& transforms = deferred_transforms_[ctx_.channel_index];
+ ctx_.channel.channel->stage().apply_transforms(transforms).get();
+ transforms.clear();
}
void apply()
{
transform.image_transform.is_key = value;
return transform;
- }, 0, L"linear"));
+ }, 0, tweener(L"linear")));
transforms.apply();
return L"202 MIXER OK\r\n";
{
transform.image_transform.blend_mode = value;
return transform;
- }, 0, L"linear"));
+ }, 0, tweener(L"linear")));
transforms.apply();
return L"202 MIXER OK\r\n";
{
transform.image_transform.use_mipmap = value;
return transform;
- }, 0, L"linear"));
+ }, 0, tweener(L"linear")));
transforms.apply();
return L"202 MIXER OK\r\n";
return L"202 MIXER OK\r\n";
}
+void mixer_straight_alpha_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+ sink.short_description(L"Turn straight alpha output on or off for a channel.");
+ sink.syntax(L"MIXER [video_channel:int] STRAIGHT_ALPHA_OUTPUT {[straight_alpha:0,1|0]}");
+ sink.para()->text(L"Turn straight alpha output on or off for the specified channel.");
+ sink.para()->code(L"casparcg.config")->text(L" needs to be configured to enable the feature.");
+ sink.para()->text(L"Examples:");
+ sink.example(L">> MIXER 1 STRAIGHT_ALPHA_OUTPUT 0");
+ sink.example(L">> MIXER 1 STRAIGHT_ALPHA_OUTPUT 1");
+ sink.example(
+ L">> MIXER 1 STRAIGHT_ALPHA_OUTPUT\n"
+ L"<< 201 MIXER OK\n"
+ L"<< 1");
+}
+
+std::wstring mixer_straight_alpha_command(command_context& ctx)
+{
+ if (ctx.parameters.empty())
+ {
+ bool state = ctx.channel.channel->mixer().get_straight_alpha_output();
+ return L"201 MIXER OK\r\n" + boost::lexical_cast<std::wstring>(state) + L"\r\n";
+ }
+
+ bool state = boost::lexical_cast<bool>(ctx.parameters.at(0));
+ ctx.channel.channel->mixer().set_straight_alpha_output(state);
+
+ return L"202 MIXER OK\r\n";
+}
+
void mixer_grid_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Create a grid of video layers.");
void mixer_commit_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Commit all deferred mixer transforms.");
- sink.syntax(L"MIXER [video_channel:int]{-[layer:int]|-0} COMMIT");
+ sink.syntax(L"MIXER [video_channel:int] COMMIT");
sink.para()->text(L"Commits all deferred mixer transforms on the specified channel. This ensures that all animations start at the same exact frame.");
sink.para()->text(L"Examples:");
sink.example(
if (channel.channel != self.channel)
{
core::diagnostics::call_context::for_thread().layer = index;
- auto producer = ctx.producer_registry->create_producer(get_producer_dependencies(channel.channel, ctx), L"route://" + boost::lexical_cast<std::wstring>(channel.channel->index()));
+ auto producer = ctx.producer_registry->create_producer(get_producer_dependencies(self.channel, ctx), L"route://" + boost::lexical_cast<std::wstring>(channel.channel->index()));
self.channel->stage().load(index, producer, false);
self.channel->stage().play(index);
index++;
if (!boost::iequals(itr->path().extension().wstring(), L".png"))
continue;
- auto relativePath = boost::filesystem::path(itr->path().wstring().substr(env::thumbnails_folder().size() - 1, itr->path().wstring().size()));
+ auto relativePath = get_relative_without_extension(itr->path(), env::thumbnails_folder());
+ auto str = relativePath.generic_wstring();
- auto str = relativePath.replace_extension(L"").generic_wstring();
if (str[0] == '\\' || str[0] == '/')
str = std::wstring(str.begin() + 1, str.end());
return L"202 THUMBNAIL GENERATE OK\r\n";
}
else
- CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(L"Thumbnail generation turned off"));
+ CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L"Thumbnail generation turned off"));
}
void thumbnail_generateall_describer(core::help_sink& sink, const core::help_repository& repo)
return L"202 THUMBNAIL GENERATE_ALL OK\r\n";
}
else
- CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(L"Thumbnail generation turned off"));
+ CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L"Thumbnail generation turned off"));
}
// Query Commands
auto path = itr->path();
auto file = path.replace_extension(L"").filename().wstring();
if (boost::iequals(file, ctx.parameters.at(0)))
- info += MediaInfo(itr->path(), ctx.media_info_repo) + L"\r\n";
+ info += MediaInfo(itr->path(), ctx.media_info_repo);
}
if (info.empty())
return boost::to_upper_copy(replyString.str());
}
+void fls_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+ sink.short_description(L"List all fonts.");
+ sink.syntax(L"FLS");
+ sink.para()
+ ->text(L"Lists all font files in the ")->code(L"fonts")->text(L" folder. Use the command ")
+ ->see(L"INFO PATHS")->text(L" to get the path to the ")->code(L"fonts")->text(L" folder.");
+ sink.para()->text(L"Columns in order from left to right are: Font name and font path.");
+}
+
+std::wstring fls_command(command_context& ctx)
+{
+ std::wstringstream replyString;
+ replyString << L"200 FLS OK\r\n";
+
+ for (auto& font : core::text::list_fonts())
+ replyString << L"\"" << font.first << L"\" \"" << get_relative(font.second, env::font_folder()).wstring() << L"\"\r\n";
+
+ replyString << L"\r\n";
+
+ return replyString.str();
+}
+
void tls_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"List all templates.");
L">> VERSION FLASH\n"
L"<< 201 VERSION OK\n"
L"<< 11.8.800.94");
+ sink.example(
+ L">> VERSION TEMPLATEHOST\n"
+ L"<< 201 VERSION OK\n"
+ L"<< unknown");
+ sink.example(
+ L">> VERSION CEF\n"
+ L"<< 201 VERSION OK\n"
+ L"<< 3.1750.1805");
}
std::wstring version_command(command_context& ctx)
return create_info_xml_reply(info, L"SERVER");
}
+void info_queues_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+ sink.short_description(L"Get detailed information about all AMCP Command Queues.");
+ sink.syntax(L"INFO QUEUES");
+ sink.para()->text(L"Gets detailed information about all AMCP Command Queues.");
+}
+
+std::wstring info_queues_command(command_context& ctx)
+{
+ return create_info_xml_reply(AMCPCommandQueue::info_all_queues(), L"QUEUES");
+}
+
+void info_threads_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+ sink.short_description(L"Lists all known threads in the server.");
+ sink.syntax(L"INFO THREADS");
+ sink.para()->text(L"Lists all known threads in the server.");
+}
+
+std::wstring info_threads_command(command_context& ctx)
+{
+ std::wstringstream replyString;
+ replyString << L"200 INFO THREADS OK\r\n";
+
+ for (auto& thread : get_thread_infos())
+ {
+ replyString << thread->native_id << L" " << u16(thread->name) << L"\r\n";
+ }
+
+ replyString << L"\r\n";
+ return replyString.str();
+}
+
+void info_delay_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+ sink.short_description(L"Get the current delay on a channel or a layer.");
+ sink.syntax(L"INFO [video_channel:int]{-[layer:int]} DELAY");
+ sink.para()->text(L"Get the current delay on the specified channel or layer.");
+}
+
+std::wstring info_delay_command(command_context& ctx)
+{
+ boost::property_tree::wptree info;
+ auto layer = ctx.layer_index(std::numeric_limits<int>::min());
+
+ if (layer == std::numeric_limits<int>::min())
+ info.add_child(L"channel-delay", ctx.channel.channel->delay_info());
+ else
+ info.add_child(L"layer-delay", ctx.channel.channel->stage().delay_info(layer).get())
+ .add(L"index", layer);
+
+ return create_info_xml_reply(info, L"DELAY");
+}
+
void diag_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Open the diagnostics window.");
return L"202 DIAG OK\r\n";
}
-void help_describer(core::help_sink& sink, const core::help_repository& repository)
+void gl_info_describer(core::help_sink& sink, const core::help_repository& repo)
{
- sink.short_description(L"Show online help.");
- sink.syntax(LR"(HELP {[command:string]})");
- sink.para()->text(LR"(Shows online help for a specific command or a list of all commands.)");
- sink.example(L">> HELP", L"Shows a list of commands.");
- sink.example(L">> HELP PLAY", L"Shows a detailed description of the PLAY command.");
+ sink.short_description(L"Get information about the allocated and pooled OpenGL resources.");
+ sink.syntax(L"GL INFO");
+ sink.para()->text(L"Retrieves information about the allocated and pooled OpenGL resources.");
}
-std::wstring help_command(command_context& ctx)
+std::wstring gl_info_command(command_context& ctx)
{
- static const int WIDTH = 80;
- struct max_width_sink : public core::help_sink
- {
- std::size_t max_width = 0;
+ auto device = ctx.ogl_device;
- void begin_item(const std::wstring& name) override
- {
- max_width = std::max(name.length(), max_width);
- };
- };
+ if (!device)
+ CASPAR_THROW_EXCEPTION(not_supported() << msg_info("GL command only supported with OpenGL accelerator."));
- struct short_description_sink : public core::help_sink
- {
- std::size_t width;
- std::wstringstream& out;
+ std::wstringstream result;
+ result << L"201 GL INFO OK\r\n";
- short_description_sink(std::size_t width, std::wstringstream& out) : width(width), out(out) { }
+ boost::property_tree::xml_writer_settings<std::wstring> w(' ', 3);
+ auto info = device->info();
+ boost::property_tree::write_xml(result, info, w);
+ result << L"\r\n";
- void begin_item(const std::wstring& name) override
- {
- out << std::left << std::setw(width + 1) << name;
- };
+ return result.str();
+}
- void short_description(const std::wstring& short_description) override
- {
- out << short_description << L"\r\n";
- };
- };
+void gl_gc_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+ sink.short_description(L"Release pooled OpenGL resources.");
+ sink.syntax(L"GL GC");
+ sink.para()->text(L"Releases all the pooled OpenGL resources. ")->strong(L"May cause a pause on all video channels.");
+}
- struct simple_paragraph_builder : core::paragraph_builder
- {
- std::wostringstream out;
- std::wstringstream& commit_to;
+std::wstring gl_gc_command(command_context& ctx)
+{
+ auto device = ctx.ogl_device;
- simple_paragraph_builder(std::wstringstream& out) : commit_to(out) { }
- ~simple_paragraph_builder()
- {
- commit_to << core::wordwrap(out.str(), WIDTH) << L"\n";
- }
- spl::shared_ptr<paragraph_builder> text(std::wstring text) override
- {
- out << std::move(text);
- return shared_from_this();
- }
- spl::shared_ptr<paragraph_builder> code(std::wstring txt) override { return text(std::move(txt)); }
- spl::shared_ptr<paragraph_builder> see(std::wstring item) override { return text(std::move(item)); }
- spl::shared_ptr<paragraph_builder> url(std::wstring url, std::wstring name) override { return text(std::move(url)); }
- };
+ if (!device)
+ CASPAR_THROW_EXCEPTION(not_supported() << msg_info("GL command only supported with OpenGL accelerator."));
+
+ device->gc().wait();
+
+ return L"202 GL GC OK\r\n";
+}
- struct simple_definition_list_builder : core::definition_list_builder
+static const int WIDTH = 80;
+
+struct max_width_sink : public core::help_sink
+{
+ std::size_t max_width = 0;
+
+ void begin_item(const std::wstring& name) override
{
- std::wstringstream& out;
+ max_width = std::max(name.length(), max_width);
+ };
+};
- simple_definition_list_builder(std::wstringstream& out) : out(out) { }
- ~simple_definition_list_builder()
- {
- out << L"\n";
- }
+struct short_description_sink : public core::help_sink
+{
+ std::size_t width;
+ std::wstringstream& out;
- spl::shared_ptr<definition_list_builder> item(std::wstring term, std::wstring description) override
- {
- out << core::indent(core::wordwrap(term, WIDTH - 2), L" ");
- out << core::indent(core::wordwrap(description, WIDTH - 4), L" ");
- return shared_from_this();
- }
+ short_description_sink(std::size_t width, std::wstringstream& out) : width(width), out(out) { }
+
+ void begin_item(const std::wstring& name) override
+ {
+ out << std::left << std::setw(width + 1) << name;
};
- struct long_description_sink : public core::help_sink
+ void short_description(const std::wstring& short_description) override
{
- std::wstringstream& out;
+ out << short_description << L"\r\n";
+ };
+};
- long_description_sink(std::wstringstream& out) : out(out) { }
+struct simple_paragraph_builder : core::paragraph_builder
+{
+ std::wostringstream out;
+ std::wstringstream& commit_to;
- void syntax(const std::wstring& syntax) override
- {
- out << L"Syntax:\n";
- out << core::indent(core::wordwrap(syntax, WIDTH - 2), L" ") << L"\n";
- };
+ simple_paragraph_builder(std::wstringstream& out) : commit_to(out) { }
+ ~simple_paragraph_builder()
+ {
+ commit_to << core::wordwrap(out.str(), WIDTH) << L"\n";
+ }
+ spl::shared_ptr<paragraph_builder> text(std::wstring text) override
+ {
+ out << std::move(text);
+ return shared_from_this();
+ }
+ spl::shared_ptr<paragraph_builder> code(std::wstring txt) override { return text(std::move(txt)); }
+ spl::shared_ptr<paragraph_builder> strong(std::wstring item) override { return text(L"*" + std::move(item) + L"*"); }
+ spl::shared_ptr<paragraph_builder> see(std::wstring item) override { return text(std::move(item)); }
+ spl::shared_ptr<paragraph_builder> url(std::wstring url, std::wstring name) override { return text(std::move(url)); }
+};
- spl::shared_ptr<core::paragraph_builder> para() override
- {
- return spl::make_shared<simple_paragraph_builder>(out);
- }
+struct simple_definition_list_builder : core::definition_list_builder
+{
+ std::wstringstream& out;
- spl::shared_ptr<core::definition_list_builder> definitions() override
- {
- return spl::make_shared<simple_definition_list_builder>(out);
- }
+ simple_definition_list_builder(std::wstringstream& out) : out(out) { }
+ ~simple_definition_list_builder()
+ {
+ out << L"\n";
+ }
- void example(const std::wstring& code, const std::wstring& caption = L"") override
- {
- out << core::indent(core::wordwrap(code, WIDTH - 2), L" ");
+ spl::shared_ptr<definition_list_builder> item(std::wstring term, std::wstring description) override
+ {
+ out << core::indent(core::wordwrap(term, WIDTH - 2), L" ");
+ out << core::indent(core::wordwrap(description, WIDTH - 4), L" ");
+ return shared_from_this();
+ }
+};
+
+struct long_description_sink : public core::help_sink
+{
+ std::wstringstream& out;
- if (!caption.empty())
- out << core::indent(core::wordwrap(L"..." + caption, WIDTH - 2), L" ");
+ long_description_sink(std::wstringstream& out) : out(out) { }
- out << L"\n";
- }
- private:
- void begin_item(const std::wstring& name) override
- {
- out << name << L"\n\n";
- };
+ void syntax(const std::wstring& syntax) override
+ {
+ out << L"Syntax:\n";
+ out << core::indent(core::wordwrap(syntax, WIDTH - 2), L" ") << L"\n";
};
- std::wstringstream result;
+ spl::shared_ptr<core::paragraph_builder> para() override
+ {
+ return spl::make_shared<simple_paragraph_builder>(out);
+ }
- if (ctx.parameters.size() == 0)
+ spl::shared_ptr<core::definition_list_builder> definitions() override
{
- result << L"200 HELP OK\r\n";
- max_width_sink width;
- ctx.help_repo->help({ L"AMCP" }, width);
- short_description_sink sink(width.max_width, result);
- sink.width = width.max_width;
- ctx.help_repo->help({ L"AMCP" }, sink);
- result << L"\r\n";
+ return spl::make_shared<simple_definition_list_builder>(out);
}
- else
+
+ void example(const std::wstring& code, const std::wstring& caption) override
{
- result << L"201 HELP OK\r\n";
- auto command = boost::to_upper_copy(
- ctx.parameters.size() == 2
- ? ctx.parameters.at(0) + L" " + ctx.parameters.at(1)
- : ctx.parameters.at(0));
- long_description_sink sink(result);
- ctx.help_repo->help({ L"AMCP" }, command, sink);
- result << L"\r\n";
+ out << core::indent(core::wordwrap(code, WIDTH - 2), L" ");
+
+ if (!caption.empty())
+ out << core::indent(core::wordwrap(L"..." + caption, WIDTH - 2), L" ");
+
+ out << L"\n";
}
+private:
+ void begin_item(const std::wstring& name) override
+ {
+ out << name << L"\n\n";
+ };
+};
+
+std::wstring create_help_list(const std::wstring& help_command, const command_context& ctx, std::set<std::wstring> tags)
+{
+ std::wstringstream result;
+ result << L"200 " << help_command << L" OK\r\n";
+ max_width_sink width;
+ ctx.help_repo->help(tags, width);
+ short_description_sink sink(width.max_width, result);
+ sink.width = width.max_width;
+ ctx.help_repo->help(tags, sink);
+ result << L"\r\n";
+ return result.str();
+}
+std::wstring create_help_details(const std::wstring& help_command, const command_context& ctx, std::set<std::wstring> tags)
+{
+ std::wstringstream result;
+ result << L"201 " << help_command << L" OK\r\n";
+ auto joined = boost::join(ctx.parameters, L" ");
+ long_description_sink sink(result);
+ ctx.help_repo->help(tags, joined, sink);
+ result << L"\r\n";
return result.str();
}
+void help_describer(core::help_sink& sink, const core::help_repository& repository)
+{
+ sink.short_description(L"Show online help for AMCP commands.");
+ sink.syntax(LR"(HELP {[command:string]})");
+ sink.para()->text(LR"(Shows online help for a specific command or a list of all commands.)");
+ sink.example(L">> HELP", L"Shows a list of commands.");
+ sink.example(L">> HELP PLAY", L"Shows a detailed description of the PLAY command.");
+}
+
+std::wstring help_command(command_context& ctx)
+{
+ if (ctx.parameters.size() == 0)
+ return create_help_list(L"HELP", ctx, { L"AMCP" });
+ else
+ return create_help_details(L"HELP", ctx, { L"AMCP" });
+}
+
+void help_producer_describer(core::help_sink& sink, const core::help_repository& repository)
+{
+ sink.short_description(L"Show online help for producers.");
+ sink.syntax(LR"(HELP PRODUCER {[producer:string]})");
+ sink.para()->text(LR"(Shows online help for a specific producer or a list of all producers.)");
+ sink.example(L">> HELP PRODUCER", L"Shows a list of producers.");
+ sink.example(L">> HELP PRODUCER FFmpeg Producer", L"Shows a detailed description of the FFmpeg Producer.");
+}
+
+std::wstring help_producer_command(command_context& ctx)
+{
+ if (ctx.parameters.size() == 0)
+ return create_help_list(L"HELP PRODUCER", ctx, { L"producer" });
+ else
+ return create_help_details(L"HELP PRODUCER", ctx, { L"producer" });
+}
+
+void help_consumer_describer(core::help_sink& sink, const core::help_repository& repository)
+{
+ sink.short_description(L"Show online help for consumers.");
+ sink.syntax(LR"(HELP CONSUMER {[consumer:string]})");
+ sink.para()->text(LR"(Shows online help for a specific consumer or a list of all consumers.)");
+ sink.example(L">> HELP CONSUMER", L"Shows a list of consumers.");
+ sink.example(L">> HELP CONSUMER Decklink Consumer", L"Shows a detailed description of the Decklink Consumer.");
+}
+
+std::wstring help_consumer_command(command_context& ctx)
+{
+ if (ctx.parameters.size() == 0)
+ return create_help_list(L"HELP CONSUMER", ctx, { L"consumer" });
+ else
+ return create_help_details(L"HELP CONSUMER", ctx, { L"consumer" });
+}
+
void bye_describer(core::help_sink& sink, const core::help_repository& repo)
{
sink.short_description(L"Disconnect the session.");
CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L"Unknown LOCK command " + command));
}
-/*bool LockCommand::DoExecute()
-{
- try
- {
- auto it = parameters().begin();
-
- std::shared_ptr<caspar::IO::lock_container> lock;
- try
- {
- int channel_index = boost::lexical_cast<int>(*it) - 1;
- lock = channels().at(channel_index).lock;
- }
- catch(const boost::bad_lexical_cast&) {}
- catch(...)
- {
- SetReplyString(L"401 LOCK ERROR\r\n");
- return false;
- }
-
- if(lock)
- ++it;
-
- if(it == parameters().end()) //too few parameters
- {
- SetReplyString(L"402 LOCK ERROR\r\n");
- return false;
- }
-
- std::wstring command = boost::to_upper_copy(*it);
- if(command == L"ACQUIRE")
- {
- ++it;
- if(it == parameters().end()) //too few parameters
- {
- SetReplyString(L"402 LOCK ACQUIRE ERROR\r\n");
- return false;
- }
- std::wstring lock_phrase = (*it);
-
- //TODO: read options
-
- if(lock)
- {
- //just lock one channel
- if(!lock->try_lock(lock_phrase, client()))
- {
- SetReplyString(L"503 LOCK ACQUIRE FAILED\r\n");
- return false;
- }
- }
- else
- {
- //TODO: lock all channels
- CASPAR_THROW_EXCEPTION(not_implemented());
- }
- SetReplyString(L"202 LOCK ACQUIRE OK\r\n");
-
- }
- else if(command == L"RELEASE")
- {
- if(lock)
- {
- lock->release_lock(client());
- }
- else
- {
- //TODO: release all channels
- CASPAR_THROW_EXCEPTION(not_implemented());
- }
- SetReplyString(L"202 LOCK RELEASE OK\r\n");
- }
- else if(command == L"CLEAR")
- {
- std::wstring override_phrase = env::properties().get(L"configuration.lock-clear-phrase", L"");
- std::wstring client_override_phrase;
- if(!override_phrase.empty())
- {
- ++it;
- if(it == parameters().end())
- {
- SetReplyString(L"402 LOCK CLEAR ERROR\r\n");
- return false;
- }
- client_override_phrase = (*it);
- }
-
- if(lock)
- {
- //just clear one channel
- if(client_override_phrase != override_phrase)
- {
- SetReplyString(L"503 LOCK CLEAR FAILED\r\n");
- return false;
- }
-
- lock->clear_locks();
- }
- else
- {
- //TODO: clear all channels
- CASPAR_THROW_EXCEPTION(not_implemented());
- }
-
- SetReplyString(L"202 LOCK CLEAR OK\r\n");
- }
- else
- {
- SetReplyString(L"403 LOCK ERROR\r\n");
- return false;
- }
- }
- catch(not_implemented&)
- {
- SetReplyString(L"600 LOCK FAILED\r\n");
- return false;
- }
- catch(...)
- {
- CASPAR_LOG_CURRENT_EXCEPTION();
- SetReplyString(L"501 LOCK FAILED\r\n");
- return false;
- }
-
- return true;
-}*/
-
void register_commands(amcp_command_repository& repo)
{
- repo.register_channel_command( L"Basic Commands", L"LOADBG", loadbg_describer, loadbg_command, 1);
- repo.register_channel_command( L"Basic Commands", L"LOAD", load_describer, load_command, 1);
- repo.register_channel_command( L"Basic Commands", L"PLAY", play_describer, play_command, 0);
- repo.register_channel_command( L"Basic Commands", L"PAUSE", pause_describer, pause_command, 0);
- repo.register_channel_command( L"Basic Commands", L"RESUME", resume_describer, resume_command, 0);
- repo.register_channel_command( L"Basic Commands", L"STOP", stop_describer, stop_command, 0);
- repo.register_channel_command( L"Basic Commands", L"CLEAR", clear_describer, clear_command, 0);
- repo.register_channel_command( L"Basic Commands", L"CALL", call_describer, call_command, 1);
- repo.register_channel_command( L"Basic Commands", L"SWAP", swap_describer, swap_command, 1);
- repo.register_channel_command( L"Basic Commands", L"ADD", add_describer, add_command, 1);
- repo.register_channel_command( L"Basic Commands", L"REMOVE", remove_describer, remove_command, 0);
- repo.register_channel_command( L"Basic Commands", L"PRINT", print_describer, print_command, 0);
- repo.register_command( L"Basic Commands", L"LOG LEVEL", log_level_describer, log_level_command, 1);
- repo.register_channel_command( L"Basic Commands", L"SET", set_describer, set_command, 2);
- repo.register_command( L"Basic Commands", L"LOCK", lock_describer, lock_command, 2);
-
- repo.register_command( L"Data Commands", L"DATA STORE", data_store_describer, data_store_command, 2);
- repo.register_command( L"Data Commands", L"DATA RETRIEVE", data_retrieve_describer, data_retrieve_command, 1);
- repo.register_command( L"Data Commands", L"DATA LIST", data_list_describer, data_list_command, 0);
- repo.register_command( L"Data Commands", L"DATA REMOVE", data_remove_describer, data_remove_command, 1);
-
- repo.register_channel_command( L"Template Commands", L"CG ADD", cg_add_describer, cg_add_command, 3);
- repo.register_channel_command( L"Template Commands", L"CG PLAY", cg_play_describer, cg_play_command, 1);
- repo.register_channel_command( L"Template Commands", L"CG STOP", cg_stop_describer, cg_stop_command, 1);
- repo.register_channel_command( L"Template Commands", L"CG NEXT", cg_next_describer, cg_next_command, 1);
- repo.register_channel_command( L"Template Commands", L"CG REMOVE", cg_remove_describer, cg_remove_command, 1);
- repo.register_channel_command( L"Template Commands", L"CG CLEAR", cg_clear_describer, cg_clear_command, 0);
- repo.register_channel_command( L"Template Commands", L"CG UPDATE", cg_update_describer, cg_update_command, 2);
- repo.register_channel_command( L"Template Commands", L"CG INVOKE", cg_invoke_describer, cg_invoke_command, 2);
- repo.register_channel_command( L"Template Commands", L"CG INFO", cg_info_describer, cg_info_command, 0);
-
- repo.register_channel_command( L"Mixer Commands", L"MIXER KEYER", mixer_keyer_describer, mixer_keyer_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER CHROMA", mixer_chroma_describer, mixer_chroma_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER BLEND", mixer_blend_describer, mixer_blend_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER OPACITY", mixer_opacity_describer, mixer_opacity_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER BRIGHTNESS", mixer_brightness_describer, mixer_brightness_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER SATURATION", mixer_saturation_describer, mixer_saturation_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER CONTRAST", mixer_contrast_describer, mixer_contrast_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER LEVELS", mixer_levels_describer, mixer_levels_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER FILL", mixer_fill_describer, mixer_fill_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER CLIP", mixer_clip_describer, mixer_clip_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER ANCHOR", mixer_anchor_describer, mixer_anchor_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER CROP", mixer_crop_describer, mixer_crop_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER ROTATION", mixer_rotation_describer, mixer_rotation_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER PERSPECTIVE", mixer_perspective_describer, mixer_perspective_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER MIPMAP", mixer_mipmap_describer, mixer_mipmap_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER VOLUME", mixer_volume_describer, mixer_volume_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER MASTERVOLUME", mixer_mastervolume_describer, mixer_mastervolume_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER GRID", mixer_grid_describer, mixer_grid_command, 1);
- repo.register_channel_command( L"Mixer Commands", L"MIXER COMMIT", mixer_commit_describer, mixer_commit_command, 0);
- repo.register_channel_command( L"Mixer Commands", L"MIXER CLEAR", mixer_clear_describer, mixer_clear_command, 0);
- repo.register_command( L"Mixer Commands", L"CHANNEL_GRID", channel_grid_describer, channel_grid_command, 0);
-
- repo.register_command( L"Thumbnail Commands", L"THUMBNAIL LIST", thumbnail_list_describer, thumbnail_list_command, 0);
- repo.register_command( L"Thumbnail Commands", L"THUMBNAIL RETRIEVE", thumbnail_retrieve_describer, thumbnail_retrieve_command, 1);
- repo.register_command( L"Thumbnail Commands", L"THUMBNAIL GENERATE", thumbnail_generate_describer, thumbnail_generate_command, 1);
- repo.register_command( L"Thumbnail Commands", L"THUMBNAIL GENERATE_ALL", thumbnail_generateall_describer, thumbnail_generateall_command, 0);
-
- repo.register_command( L"Query Commands", L"CINF", cinf_describer, cinf_command, 1);
- repo.register_command( L"Query Commands", L"CLS", cls_describer, cls_command, 0);
- repo.register_command( L"Query Commands", L"TLS", tls_describer, tls_command, 0);
- repo.register_command( L"Query Commands", L"VERSION", version_describer, version_command, 0);
- repo.register_command( L"Query Commands", L"INFO", info_describer, info_command, 0);
- repo.register_channel_command( L"Query Commands", L"INFO", info_channel_describer, info_channel_command, 0);
- repo.register_command( L"Query Commands", L"INFO TEMPLATE", info_template_describer, info_template_command, 1);
- repo.register_command( L"Query Commands", L"INFO CONFIG", info_config_describer, info_config_command, 0);
- repo.register_command( L"Query Commands", L"INFO PATHS", info_paths_describer, info_paths_command, 0);
- repo.register_command( L"Query Commands", L"INFO SYSTEM", info_system_describer, info_system_command, 0);
- repo.register_command( L"Query Commands", L"INFO SERVER", info_server_describer, info_server_command, 0);
- repo.register_command( L"Query Commands", L"DIAG", diag_describer, diag_command, 0);
- repo.register_command( L"Query Commands", L"BYE", bye_describer, bye_command, 0);
- repo.register_command( L"Query Commands", L"KILL", kill_describer, kill_command, 0);
- repo.register_command( L"Query Commands", L"RESTART", restart_describer, restart_command, 0);
- repo.register_command( L"Query Commands", L"HELP", help_describer, help_command, 0);
+ repo.register_channel_command( L"Basic Commands", L"LOADBG", loadbg_describer, loadbg_command, 1);
+ repo.register_channel_command( L"Basic Commands", L"LOAD", load_describer, load_command, 1);
+ repo.register_channel_command( L"Basic Commands", L"PLAY", play_describer, play_command, 0);
+ repo.register_channel_command( L"Basic Commands", L"PAUSE", pause_describer, pause_command, 0);
+ repo.register_channel_command( L"Basic Commands", L"RESUME", resume_describer, resume_command, 0);
+ repo.register_channel_command( L"Basic Commands", L"STOP", stop_describer, stop_command, 0);
+ repo.register_channel_command( L"Basic Commands", L"CLEAR", clear_describer, clear_command, 0);
+ repo.register_channel_command( L"Basic Commands", L"CALL", call_describer, call_command, 1);
+ repo.register_channel_command( L"Basic Commands", L"SWAP", swap_describer, swap_command, 1);
+ repo.register_channel_command( L"Basic Commands", L"ADD", add_describer, add_command, 1);
+ repo.register_channel_command( L"Basic Commands", L"REMOVE", remove_describer, remove_command, 0);
+ repo.register_channel_command( L"Basic Commands", L"PRINT", print_describer, print_command, 0);
+ repo.register_command( L"Basic Commands", L"LOG LEVEL", log_level_describer, log_level_command, 1);
+ repo.register_command( L"Basic Commands", L"LOG CATEGORY", log_category_describer, log_category_command, 2);
+ repo.register_channel_command( L"Basic Commands", L"SET", set_describer, set_command, 2);
+ repo.register_command( L"Basic Commands", L"LOCK", lock_describer, lock_command, 2);
+
+ repo.register_command( L"Data Commands", L"DATA STORE", data_store_describer, data_store_command, 2);
+ repo.register_command( L"Data Commands", L"DATA RETRIEVE", data_retrieve_describer, data_retrieve_command, 1);
+ repo.register_command( L"Data Commands", L"DATA LIST", data_list_describer, data_list_command, 0);
+ repo.register_command( L"Data Commands", L"DATA REMOVE", data_remove_describer, data_remove_command, 1);
+
+ repo.register_channel_command( L"Template Commands", L"CG ADD", cg_add_describer, cg_add_command, 3);
+ repo.register_channel_command( L"Template Commands", L"CG PLAY", cg_play_describer, cg_play_command, 1);
+ repo.register_channel_command( L"Template Commands", L"CG STOP", cg_stop_describer, cg_stop_command, 1);
+ repo.register_channel_command( L"Template Commands", L"CG NEXT", cg_next_describer, cg_next_command, 1);
+ repo.register_channel_command( L"Template Commands", L"CG REMOVE", cg_remove_describer, cg_remove_command, 1);
+ repo.register_channel_command( L"Template Commands", L"CG CLEAR", cg_clear_describer, cg_clear_command, 0);
+ repo.register_channel_command( L"Template Commands", L"CG UPDATE", cg_update_describer, cg_update_command, 2);
+ repo.register_channel_command( L"Template Commands", L"CG INVOKE", cg_invoke_describer, cg_invoke_command, 2);
+ repo.register_channel_command( L"Template Commands", L"CG INFO", cg_info_describer, cg_info_command, 0);
+
+ repo.register_channel_command( L"Mixer Commands", L"MIXER KEYER", mixer_keyer_describer, mixer_keyer_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER CHROMA", mixer_chroma_describer, mixer_chroma_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER BLEND", mixer_blend_describer, mixer_blend_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER OPACITY", mixer_opacity_describer, mixer_opacity_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER BRIGHTNESS", mixer_brightness_describer, mixer_brightness_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER SATURATION", mixer_saturation_describer, mixer_saturation_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER CONTRAST", mixer_contrast_describer, mixer_contrast_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER LEVELS", mixer_levels_describer, mixer_levels_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER FILL", mixer_fill_describer, mixer_fill_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER CLIP", mixer_clip_describer, mixer_clip_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER ANCHOR", mixer_anchor_describer, mixer_anchor_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER CROP", mixer_crop_describer, mixer_crop_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER ROTATION", mixer_rotation_describer, mixer_rotation_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER PERSPECTIVE", mixer_perspective_describer, mixer_perspective_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER MIPMAP", mixer_mipmap_describer, mixer_mipmap_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER VOLUME", mixer_volume_describer, mixer_volume_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER MASTERVOLUME", mixer_mastervolume_describer, mixer_mastervolume_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER STRAIGHT_ALPHA_OUTPUT", mixer_straight_alpha_describer, mixer_straight_alpha_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER GRID", mixer_grid_describer, mixer_grid_command, 1);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER COMMIT", mixer_commit_describer, mixer_commit_command, 0);
+ repo.register_channel_command( L"Mixer Commands", L"MIXER CLEAR", mixer_clear_describer, mixer_clear_command, 0);
+ repo.register_command( L"Mixer Commands", L"CHANNEL_GRID", channel_grid_describer, channel_grid_command, 0);
+
+ repo.register_command( L"Thumbnail Commands", L"THUMBNAIL LIST", thumbnail_list_describer, thumbnail_list_command, 0);
+ repo.register_command( L"Thumbnail Commands", L"THUMBNAIL RETRIEVE", thumbnail_retrieve_describer, thumbnail_retrieve_command, 1);
+ repo.register_command( L"Thumbnail Commands", L"THUMBNAIL GENERATE", thumbnail_generate_describer, thumbnail_generate_command, 1);
+ repo.register_command( L"Thumbnail Commands", L"THUMBNAIL GENERATE_ALL", thumbnail_generateall_describer, thumbnail_generateall_command, 0);
+
+ repo.register_command( L"Query Commands", L"CINF", cinf_describer, cinf_command, 1);
+ repo.register_command( L"Query Commands", L"CLS", cls_describer, cls_command, 0);
+ repo.register_command( L"Query Commands", L"FLS", fls_describer, fls_command, 0);
+ repo.register_command( L"Query Commands", L"TLS", tls_describer, tls_command, 0);
+ repo.register_command( L"Query Commands", L"VERSION", version_describer, version_command, 0);
+ repo.register_command( L"Query Commands", L"INFO", info_describer, info_command, 0);
+ repo.register_channel_command( L"Query Commands", L"INFO", info_channel_describer, info_channel_command, 0);
+ repo.register_command( L"Query Commands", L"INFO TEMPLATE", info_template_describer, info_template_command, 1);
+ repo.register_command( L"Query Commands", L"INFO CONFIG", info_config_describer, info_config_command, 0);
+ repo.register_command( L"Query Commands", L"INFO PATHS", info_paths_describer, info_paths_command, 0);
+ repo.register_command( L"Query Commands", L"INFO SYSTEM", info_system_describer, info_system_command, 0);
+ repo.register_command( L"Query Commands", L"INFO SERVER", info_server_describer, info_server_command, 0);
+ repo.register_command( L"Query Commands", L"INFO QUEUES", info_queues_describer, info_queues_command, 0);
+ repo.register_command( L"Query Commands", L"INFO THREADS", info_threads_describer, info_threads_command, 0);
+ repo.register_channel_command( L"Query Commands", L"INFO DELAY", info_delay_describer, info_delay_command, 0);
+ repo.register_command( L"Query Commands", L"DIAG", diag_describer, diag_command, 0);
+ repo.register_command( L"Query Commands", L"GL INFO", gl_info_describer, gl_info_command, 0);
+ repo.register_command( L"Query Commands", L"GL GC", gl_gc_describer, gl_gc_command, 0);
+ repo.register_command( L"Query Commands", L"BYE", bye_describer, bye_command, 0);
+ repo.register_command( L"Query Commands", L"KILL", kill_describer, kill_command, 0);
+ repo.register_command( L"Query Commands", L"RESTART", restart_describer, restart_command, 0);
+ repo.register_command( L"Query Commands", L"HELP", help_describer, help_command, 0);
+ repo.register_command( L"Query Commands", L"HELP PRODUCER", help_producer_describer, help_producer_command, 0);
+ repo.register_command( L"Query Commands", L"HELP CONSUMER", help_consumer_describer, help_consumer_command, 0);
}
} //namespace amcp