From 5ddb6fc0c5ce75a0c2a37daa92f7eadf2ee4c640 Mon Sep 17 00:00:00 2001
From: patrick96
Date: Sun, 31 May 2020 16:49:25 +0200
Subject: [PATCH] Move legacy action handling to separate function
---
include/components/controller.hpp | 2 +
src/components/controller.cpp | 137 ++++++++++++++++--------------
2 files changed, 76 insertions(+), 63 deletions(-)
diff --git a/include/components/controller.hpp b/include/components/controller.hpp
index d6755bc7..f5593a96 100644
--- a/include/components/controller.hpp
+++ b/include/components/controller.hpp
@@ -75,6 +75,8 @@ class controller
private:
size_t setup_modules(alignment align);
+ bool try_forward_legacy_action(const string cmd);
+
connection& m_connection;
signal_emitter& m_sig;
const logger& m_log;
diff --git a/src/components/controller.cpp b/src/components/controller.cpp
index 5d3ef6f0..a0cc7404 100644
--- a/src/components/controller.cpp
+++ b/src/components/controller.cpp
@@ -391,66 +391,18 @@ void controller::process_eventqueue() {
}
/**
- * Process stored input data
+ * Tries to match the given command to a legacy action string and sends the
+ * appropriate new action (and data) to the right module if possible.
+ *
+ * \returns true iff the given command matches a legacy action string and was
+ * successfully forwarded to a module
*/
-void controller::process_inputdata() {
- if (m_inputdata.empty()) {
- return;
- }
-
- const string cmd = m_inputdata;
- m_inputdata.clear();
-
- m_log.trace("controller: Processing inputdata: %s", cmd);
-
- /*
- * Module inputs have the following form (w/o the quotes): "#NAME.ACTION[.DATA]"
- * where 'NAME' is the name of the module (for which '.' is a forbidden
- * character) and 'ACTION' is the input that is sent to the module. 'DATA'
- * is optional data that is attached to the action and is also sent to the
- * module.
- */
- if (cmd.front() == '#') {
- try {
- auto res = actions_util::parse_action_string(cmd);
-
- auto handler_name = std::get<0>(res);
- auto action = std::get<1>(res);
- auto data = std::get<2>(res);
-
- m_log.info(
- "Forwarding data to input handlers (name: '%s', action: '%s', data: '%s') ", handler_name, action, data);
-
- int num_delivered = 0;
-
- // Forwards the action to all input handlers that match the name
- for (auto&& handler : m_inputhandlers) {
- if (handler->input_handler_name() == handler_name) {
- if (!handler->input(std::forward(action), std::forward(data))) {
- m_log.err("The '%s' module does not support the '%s' action.", handler_name, action);
- }
-
- num_delivered++;
- }
- }
-
- if (num_delivered == 0) {
- m_log.err("There exists no input handler with name '%s' (input: %s)", handler_name, cmd);
- } else {
- m_log.info("Delivered input to %d input handler%s", num_delivered, num_delivered > 1 ? "s" : "");
- }
- } catch (runtime_error& e) {
- m_log.err("Invalid action string (reason: %s)", e.what());
- }
-
- return;
- }
-
+bool controller::try_forward_legacy_action(const string cmd) {
/*
* Maps legacy action names to a module type and the new action name in that module.
*
* We try to match the old action name as a prefix, and everything after it will also be added to the end of the new
- * action string (for example "mpdseek+5" will be redirected to "seek+5" in the first mpd module).
+ * action string (for example "mpdseek+5" will be redirected to "seek.+5" in the first mpd module).
*
* The action will be delivered to the first module of that type so that it is consistent with existing behavior.
* If the module does not support the action or no matching module is found, the command is forwarded to the shell.
@@ -511,7 +463,7 @@ void controller::process_inputdata() {
A_MAP("menu-close", menu_module, EVENT_CLOSE),
};
#undef A_MAP
-// clang-format on
+ // clang-format on
// Check if any key in the map is a prefix for the `cmd`
for (const auto& entry : legacy_actions) {
@@ -537,20 +489,79 @@ void controller::process_inputdata() {
"Forwarding legacy action '%s' to module '%s' as '%s' with data '%s'", cmd, handler_name, action, data);
if (!handler_ptr->input(std::forward(action), std::forward(data))) {
m_log.err("Failed to forward deprecated action to %s module", type);
- /*
- * Forward to shell if the module cannot accept the action to not break existing behavior.
- * goto is used to break out of multiple loops at once.
- */
- goto forward_shell;
+ // Forward to shell if the module cannot accept the action to not break existing behavior.
+ return false;
}
// Only deliver to the first matching module.
- return;
+ return true;
}
}
}
}
-forward_shell:
+ /*
+ * If we couldn't find any matching legacy action, we return false and let
+ * the command be forwarded to the shell
+ */
+ return false;
+}
+
+/**
+ * Process stored input data
+ */
+void controller::process_inputdata() {
+ if (m_inputdata.empty()) {
+ return;
+ }
+
+ const string cmd = m_inputdata;
+ m_inputdata.clear();
+
+ m_log.trace("controller: Processing inputdata: %s", cmd);
+
+ // Every command that starts with '#' is considered an action string.
+ if (cmd.front() == '#') {
+ string handler_name;
+ string action;
+ string data;
+
+ try {
+ auto res = actions_util::parse_action_string(cmd);
+
+ handler_name = std::get<0>(res);
+ action = std::get<1>(res);
+ data = std::get<2>(res);
+ } catch (runtime_error& e) {
+ m_log.err("Invalid action string (reason: %s)", e.what());
+ return;
+ }
+
+ m_log.info("Forwarding data to input handlers (name: '%s', action: '%s', data: '%s') ", handler_name, action, data);
+
+ int num_delivered = 0;
+
+ // Forwards the action to all input handlers that match the name
+ for (auto&& handler : m_inputhandlers) {
+ if (handler->input_handler_name() == handler_name) {
+ if (!handler->input(std::forward(action), std::forward(data))) {
+ m_log.err("The '%s' module does not support the '%s' action.", handler_name, action);
+ }
+
+ num_delivered++;
+ }
+ }
+
+ if (num_delivered == 0) {
+ m_log.err("There exists no input handler with name '%s' (input: %s)", handler_name, cmd);
+ } else {
+ m_log.info("Delivered input to %d input handler%s", num_delivered, num_delivered > 1 ? "s" : "");
+ }
+ return;
+ }
+
+ if (this->try_forward_legacy_action(cmd)) {
+ return;
+ }
try {
// Run input as command if it's not an input for a module