]> git.sesse.net Git - casparcg/commitdiff
[AMCP] #475 Added special command REQ that can be prepended before any command to...
authorHelge Norberg <helge.norberg@svt.se>
Tue, 17 Jan 2017 16:45:54 +0000 (17:45 +0100)
committerHelge Norberg <helge.norberg@svt.se>
Tue, 17 Jan 2017 16:45:54 +0000 (17:45 +0100)
CHANGELOG
protocol/amcp/AMCPCommand.h
protocol/amcp/AMCPCommandsImpl.cpp
protocol/amcp/AMCPProtocolStrategy.cpp
protocol/amcp/amcp_command_repository.cpp
protocol/amcp/amcp_command_repository.h

index 1d9deb884a0331f4d7cd4fdf215bd04655a2a877..fc3e1a53b961d6317d5278ee18b69040153862d8 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -56,6 +56,9 @@ AMCP
     values.\r
   o MIXER CHROMA syntax deprecated (still supported) in favour of the more\r
     advanced syntax required by the rewritten chroma key code.\r
+  o Added special command REQ that can be prepended before any command to\r
+    identify the response with a client specified request id, allowing a client\r
+    to know exactly what asynchronous response matched a specific request.\r
 \r
 \r
 \r
index 0eb9a2855bff2297c9d4629aa4e09e1b6c858744..7c6d56af797a3468746c928a1515177e95d23c2b 100644 (file)
@@ -95,6 +95,7 @@ namespace amcp {
                int                                     min_num_params_;
                std::wstring            name_;
                std::wstring            replyString_;
+               std::wstring            request_id_;
        public:
                AMCPCommand(const command_context& ctx, const amcp_command_func& command, int min_num_params, const std::wstring& name)
                        : ctx_(ctx)
@@ -134,9 +135,17 @@ namespace amcp {
                        return name_;
                }
 
+               void set_request_id(std::wstring request_id)
+               {
+                       request_id_ = std::move(request_id);
+               }
+
                void SetReplyString(const std::wstring& str)
                {
-                       replyString_ = str;
+                       if (request_id_.empty())
+                               replyString_ = str;
+                       else
+                               replyString_ = L"RES " + request_id_ + L" " + str;
                }
        };
 }}}
index b1e6536c70fab344c315f14098047c0997f7e41b..a46120cc6f0996d94d5f97f25d2a552ab4a40605 100644 (file)
@@ -2948,6 +2948,21 @@ std::wstring lock_command(command_context& ctx)
        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L"Unknown LOCK command " + command));
 }
 
+void req_describer(core::help_sink& sink, const core::help_repository& repo)
+{
+       sink.short_description(L"Perform any command with an additional request id identifying the response.");
+       sink.syntax(L"REQ [request_id:string] COMMAND...");
+       sink.para()
+               ->text(L"This special command modifies the AMCP protocol a little bit to prepend ")
+               ->code(L"RES request_id")->text(L" to the response, in order to see what asynchronous response matches what request.");
+       sink.para()->text(L"Examples:");
+       sink.example(L"REQ unique PLAY 1-0 AMB\n");
+       sink.example(
+               L">> REQ unique PLAY 1-0 AMB\n"
+               L"<< RES unique 202 PLAY OK");
+}
+
+
 void register_commands(amcp_command_repository& repo)
 {
        repo.register_channel_command(  L"Basic Commands",              L"LOADBG",                                              loadbg_describer,                                       loadbg_command,                                 1);
@@ -3034,6 +3049,8 @@ void register_commands(amcp_command_repository& repo)
        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);
+
+       repo.help_repo()->register_item({ L"AMCP", L"Protocol Commands" }, L"REQ", req_describer);
 }
 
 }      //namespace amcp
index 871f25c918d17d7d9133925f28d8e0d43c825028..39529a709f3c6380e62298a45495930d28b29b5a 100644 (file)
@@ -19,7 +19,7 @@
 * Author: Nicklas P Andersson
 */
 
+
 #include "../StdAfx.h"
 
 #include "AMCPProtocolStrategy.h"
@@ -106,7 +106,7 @@ public:
        void Parse(const std::wstring& message, ClientInfoPtr client)
        {
                CASPAR_LOG_COMMUNICATION(info) << L"Received message from " << client->address() << ": " << message << L"\\r\\n";
-       
+
                command_interpreter_result result;
                if(interpret_command_string(message, result, client))
                {
@@ -115,7 +115,7 @@ public:
                        else
                                result.queue->AddCommand(result.command);
                }
-               
+
                if (result.error != error_state::no_error)
                {
                        std::wstringstream answer;
@@ -157,6 +157,22 @@ private:
                        if (!tokens.empty() && tokens.front().at(0) == L'/')
                                tokens.pop_front();
 
+                       std::wstring request_id;
+
+                       if (boost::iequals(tokens.front(), L"REQ"))
+                       {
+                               tokens.pop_front();
+
+                               if (tokens.empty())
+                               {
+                                       result.error = error_state::parameters_error;
+                                       return false;
+                               }
+
+                               request_id = tokens.front();
+                               tokens.pop_front();
+                       }
+
                        // Fail if no more tokens.
                        if (tokens.empty())
                        {
@@ -234,6 +250,9 @@ private:
                                if (result.command->parameters().size() < result.command->minimum_parameters())
                                        result.error = error_state::parameters_error;
                        }
+
+                       if (result.command)
+                               result.command->set_request_id(std::move(request_id));
                }
                catch (std::out_of_range&)
                {
index 06249814def23a49a9bbaed5bc2229f9c7d68b3f..2457ec72d5b0f847897fe5b204ef65b53f02e27c 100644 (file)
@@ -225,4 +225,9 @@ void amcp_command_repository::register_channel_command(
        self.channel_commands.insert(std::make_pair(std::move(name), std::make_pair(std::move(command), min_num_params)));
 }
 
+spl::shared_ptr<core::help_repository> amcp_command_repository::help_repo() const
+{
+       return impl_->help_repo;
+}
+
 }}}
index 778c99845dcf1e20d420255d94f316d30fc3a364..2cd065fbba5a09be25eb796a2cc49537d68ce6d3 100644 (file)
@@ -60,6 +60,7 @@ public:
 
        void register_command(std::wstring category, std::wstring name, core::help_item_describer describer, amcp_command_func command, int min_num_params);
        void register_channel_command(std::wstring category, std::wstring name, core::help_item_describer describer, amcp_command_func command, int min_num_params);
+       spl::shared_ptr<core::help_repository> help_repo() const;
 private:
        struct impl;
        spl::shared_ptr<impl> impl_;