JSON-RPC SendKey, ExecuteAction, ShowCodec and ShowOSD in Input namespace #1056

Merged
merged 7 commits into from Jul 11, 2012
+349 −20
View
10 xbmc/Application.cpp
@@ -3061,6 +3061,16 @@ bool CApplication::ProcessJsonRpcButtons()
{
#ifdef HAS_JSONRPC
CKey tempKey(JSONRPC::CInputOperations::GetKey());
+ if (tempKey.GetButtonCode() == KEY_UNICODE && tempKey.GetUnicode() != 0)
+ {
+ XBMC_Event event = { 0 };
+ event.type = XBMC_KEYDOWN;
+ event.key.type = XBMC_KEYDOWN;
+ event.key.keysym.unicode = (uint16_t)tempKey.GetUnicode();
+ event.key.keysym.sym = (XBMCKey)tempKey.GetUnicode();
+
+ return OnEvent(event);
+ }
if (tempKey.GetButtonCode() != KEY_INVALID)
{
tempKey.SetFromService(true);
View
16 xbmc/dialogs/GUIDialogKeyboard.cpp
@@ -34,6 +34,7 @@
#include "Application.h"
#include "settings/AdvancedSettings.h"
#include "guilib/LocalizeStrings.h"
+#include "interfaces/AnnouncementManager.h"
// Symbol mapping (based on MS virtual keyboard - may need improving)
static char symbol_map[37] = ")!@#$%^&*([]{}-_=+;:\'\",.<>/?\\|`~ ";
@@ -98,6 +99,11 @@ void CGUIDialogKeyboard::OnInitWindow()
{
SET_CONTROL_HIDDEN(CTL_LABEL_HEADING);
}
+
+ CVariant data;
+ data["title"] = m_strHeading;
+ data["type"] = "keyboard";
+ ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputRequested", data);
}
bool CGUIDialogKeyboard::OnAction(const CAction &action)
@@ -255,6 +261,14 @@ bool CGUIDialogKeyboard::OnMessage(CGUIMessage& message)
}
}
break;
+
+ case GUI_MSG_SET_TEXT:
+ SetText(message.GetLabel());
+
+ // close the dialog if requested
+ if (message.GetParam1() > 0)
+ OnOK();
+ break;
}
return true;
@@ -664,6 +678,8 @@ void CGUIDialogKeyboard::OnDeinitWindow(int nextWindowID)
CGUIDialog::OnDeinitWindow(nextWindowID);
// reset the heading (we don't always have this)
m_strHeading = "";
+
+ ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputFinished");
}
void CGUIDialogKeyboard::MoveCursor(int iAmount)
View
101 xbmc/dialogs/GUIDialogNumeric.cpp
@@ -27,6 +27,7 @@
#include "input/XBMC_vkeys.h"
#include "utils/StringUtils.h"
#include "guilib/LocalizeStrings.h"
+#include "interfaces/AnnouncementManager.h"
#define CONTROL_HEADING_LABEL 1
#define CONTROL_INPUT_LABEL 4
@@ -54,6 +55,51 @@ CGUIDialogNumeric::~CGUIDialogNumeric(void)
{
}
+void CGUIDialogNumeric::OnInitWindow()
+{
+ CGUIDialog::OnInitWindow();
+
+ CVariant data;
+ switch (m_mode)
+ {
+ case INPUT_TIME:
+ data["type"] = "time";
+ break;
+ case INPUT_DATE:
+ data["type"] = "date";
+ break;
+ case INPUT_IP_ADDRESS:
+ data["type"] = "ip";
+ break;
+ case INPUT_PASSWORD:
+ data["type"] = "password";
+ break;
+ case INPUT_NUMBER:
+ data["type"] = "number";
+ break;
+ case INPUT_TIME_SECONDS:
+ data["type"] = "seconds";
+ break;
+ default:
+ data["type"] = "keyboard";
+ break;
+ }
+
+ const CGUILabelControl *control = (const CGUILabelControl *)GetControl(CONTROL_HEADING_LABEL);
+ if (control != NULL)
+ data["title"] = control->GetDescription();
+
+ ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputRequested", data);
+}
+
+void CGUIDialogNumeric::OnDeinitWindow(int nextWindowID)
+{
+ // call base class
+ CGUIDialog::OnDeinitWindow(nextWindowID);
+
+ ANNOUNCEMENT::CAnnouncementManager::Announce(ANNOUNCEMENT::Input, "xbmc", "OnInputFinished");
+}
+
bool CGUIDialogNumeric::OnAction(const CAction &action)
{
if (action.GetID() == ACTION_NEXT_ITEM)
@@ -139,6 +185,14 @@ bool CGUIDialogNumeric::OnMessage(CGUIMessage& message)
}
}
break;
+
+ case GUI_MSG_SET_TEXT:
+ SetMode(m_mode, message.GetLabel());
+
+ // close the dialog if requested
+ if (message.GetParam1() > 0)
+ OnOK();
+ break;
}
return CGUIDialog::OnMessage(message);
}
@@ -462,7 +516,7 @@ void CGUIDialogNumeric::SetMode(INPUT_MODE mode, void *initial)
m_datetime = *(SYSTEMTIME *)initial;
m_lastblock = (m_mode == INPUT_DATE) ? 2 : 1;
}
- if (m_mode == INPUT_IP_ADDRESS)
+ else if (m_mode == INPUT_IP_ADDRESS)
{
m_lastblock = 3;
m_ip[0] = m_ip[1] = m_ip[2] = m_ip[3] = 0;
@@ -484,10 +538,51 @@ void CGUIDialogNumeric::SetMode(INPUT_MODE mode, void *initial)
}
}
}
- if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD)
- {
+ else if (m_mode == INPUT_NUMBER || m_mode == INPUT_PASSWORD)
m_number = *(CStdString *)initial;
+}
+
+void CGUIDialogNumeric::SetMode(INPUT_MODE mode, const CStdString &initial)
+{
+ m_mode = mode;
+ m_block = 0;
+ m_lastblock = 0;
+ if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS || m_mode == INPUT_DATE)
+ {
+ CDateTime dateTime;
+ if (m_mode == INPUT_TIME || m_mode == INPUT_TIME_SECONDS)
+ {
+ // check if we have a pure number
+ if (initial.find_first_not_of("0123456789") == std::string::npos)
+ {
+ long seconds = strtol(initial.c_str(), NULL, 10);
+ dateTime = seconds;
+ }
+ else
+ {
+ CStdString tmp = initial;
+ // if we are handling seconds and if the string only contains
+ // "mm:ss" we need to add dummy "hh:" to get "hh:mm:ss"
+ if (m_mode == INPUT_TIME_SECONDS && tmp.size() <= 5)
+ tmp = "00:" + tmp;
+ dateTime.SetFromDBTime(tmp);
+ }
+ }
+ else if (m_mode == INPUT_DATE)
+ {
+ CStdString tmp = initial;
+ tmp.Replace("/", ".");
+ dateTime.SetFromDBDate(tmp);
+ }
+
+ if (!dateTime.IsValid())
+ return;
+
+ dateTime.GetAsSystemTime(m_datetime);
+ m_lastblock = (m_mode == INPUT_DATE) ? 2 : 1;
}
+ else
+ SetMode(mode, (void*)&initial);
}
void CGUIDialogNumeric::GetOutput(void *output)
View
4 xbmc/dialogs/GUIDialogNumeric.h
@@ -44,6 +44,7 @@ class CGUIDialogNumeric :
void SetHeading(const CStdString &strHeading);
void SetMode(INPUT_MODE mode, void *initial);
+ void SetMode(INPUT_MODE mode, const CStdString &initial);
void GetOutput(void *output);
static bool ShowAndGetTime(SYSTEMTIME &time, const CStdString &heading);
@@ -53,6 +54,9 @@ class CGUIDialogNumeric :
static bool ShowAndGetSeconds(CStdString& timeString, const CStdString &heading);
protected:
+ virtual void OnInitWindow();
+ virtual void OnDeinitWindow(int nextWindowID);
+
void OnNumber(unsigned int num);
void VerifyDate(bool checkYear);
void OnNext();
View
5 xbmc/guilib/GUIEditControl.cpp
@@ -94,6 +94,11 @@ bool CGUIEditControl::OnMessage(CGUIMessage &message)
{
m_smsTimer.Stop();
}
+ else if (message.GetMessage() == GUI_MSG_SET_TEXT)
+ {
+ SetLabel2(message.GetLabel());
+ UpdateText();
+ }
return CGUIButtonControl::OnMessage(message);
}
View
2 xbmc/guilib/GUIMessage.h
@@ -130,6 +130,8 @@
*/
#define GUI_MSG_UNFOCUS_ALL 41
+#define GUI_MSG_SET_TEXT 42
+
#define GUI_MSG_USER 1000
/*!
View
9 xbmc/input/ButtonTranslator.cpp
@@ -845,6 +845,15 @@ bool CButtonTranslator::TranslateJoystickString(int window, const char* szDevice
}
#endif
+void CButtonTranslator::GetActions(std::vector<std::string> &actionList)
+{
+ unsigned int size = sizeof(actions) / sizeof(ActionMapping);
+ actionList.clear();
+ actionList.reserve(size);
+ for (unsigned int index = 0; index < size; index++)
+ actionList.push_back(actions[index].name);
+}
+
CAction CButtonTranslator::GetAction(int window, const CKey &key, bool fallback)
{
CStdString strAction;
View
3 xbmc/input/ButtonTranslator.h
@@ -25,6 +25,7 @@
#pragma once
#include <map>
+#include <vector>
#include "system.h" // for HAS_EVENT_SERVER, HAS_SDL_JOYSTICK, HAS_LIRC
#ifdef HAS_EVENT_SERVER
@@ -69,6 +70,8 @@ class CButtonTranslator
/// clears the maps
void Clear();
+ static void GetActions(std::vector<std::string> &actionList);
+
CAction GetAction(int window, const CKey &key, bool fallback = true);
/*! \brief Translate between a window name and it's id
View
19 xbmc/interfaces/IAnnouncer.h
@@ -25,16 +25,17 @@ namespace ANNOUNCEMENT
{
enum AnnouncementFlag
{
- Player = 0x1,
- GUI = 0x2,
- System = 0x4,
- VideoLibrary = 0x8,
- AudioLibrary = 0x10,
- Application = 0x20,
- Other = 0x40
+ Player = 0x01,
+ GUI = 0x02,
+ System = 0x04,
+ VideoLibrary = 0x08,
+ AudioLibrary = 0x10,
+ Application = 0x20,
+ Input = 0x40,
+ Other = 0x80
};
- #define ANNOUNCE_ALL (Player | GUI | System | VideoLibrary | AudioLibrary | Application | Other)
+ #define ANNOUNCE_ALL (Player | GUI | System | VideoLibrary | AudioLibrary | Application | Input | Other)
/*!
\brief Returns a string representation for the
@@ -58,6 +59,8 @@ namespace ANNOUNCEMENT
return "AudioLibrary";
case Application:
return "Application";
+ case Input:
+ return "Input";
case Other:
return "Other";
default:
View
57 xbmc/interfaces/json-rpc/InputOperations.cpp
@@ -22,19 +22,24 @@
#include "InputOperations.h"
#include "Application.h"
#include "guilib/GUIAudioManager.h"
+#include "guilib/GUIWindow.h"
+#include "guilib/GUIWindowManager.h"
+#include "input/ButtonTranslator.h"
+#include "input/XBMC_keyboard.h"
#include "input/XBMC_vkeys.h"
#include "threads/SingleLock.h"
+#include "utils/CharsetConverter.h"
using namespace JSONRPC;
CCriticalSection CInputOperations::m_critSection;
-uint32_t CInputOperations::m_key = KEY_INVALID;
+CKey CInputOperations::m_key(KEY_INVALID);
-uint32_t CInputOperations::GetKey()
+CKey CInputOperations::GetKey()
{
CSingleLock lock(m_critSection);
- uint32_t currentKey = m_key;
- m_key = KEY_INVALID;
+ CKey currentKey = m_key;
+ m_key = CKey(KEY_INVALID);
return currentKey;
}
@@ -55,13 +60,16 @@ bool CInputOperations::handleScreenSaver()
return screenSaverBroken;
}
-JSONRPC_STATUS CInputOperations::SendKey(uint32_t keyCode)
+JSONRPC_STATUS CInputOperations::SendKey(uint32_t keyCode, bool unicode /* = false */)
{
if (keyCode == KEY_INVALID)
return InternalError;
CSingleLock lock(m_critSection);
- m_key = keyCode | KEY_VKEY;
+ if (unicode)
+ m_key = CKey(0, (wchar_t)keyCode, 0, 0, 0);
+ else
+ m_key = CKey(keyCode | KEY_VKEY);
return ACK;
}
@@ -84,6 +92,33 @@ JSONRPC_STATUS CInputOperations::activateWindow(int windowID)
return ACK;
}
+JSONRPC_STATUS CInputOperations::SendText(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+ std::string text = parameterObject["text"].asString();
+ if (text.empty())
+ return InvalidParams;
+
+ int controlID = 0;
+ CGUIWindow *window = g_windowManager.GetWindow(g_windowManager.GetFocusedWindow());
+ if (!window)
+ return InternalError;
+
+ CGUIMessage msg(GUI_MSG_SET_TEXT, 0, 0);
+ msg.SetLabel(text);
+ msg.SetParam1(parameterObject["done"].asBoolean() ? 1 : 0);
+ g_application.getApplicationMessenger().SendGUIMessage(msg, window->GetID());
+ return ACK;
+}
+
+JSONRPC_STATUS CInputOperations::ExecuteAction(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+ int action;
+ if (!CButtonTranslator::TranslateActionString(parameterObject["action"].asString().c_str(), action))
+ return InvalidParams;
+
+ return SendAction(action);
+}
+
JSONRPC_STATUS CInputOperations::Left(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
{
return SendKey(XBMCVK_LEFT);
@@ -128,3 +163,13 @@ JSONRPC_STATUS CInputOperations::Home(const CStdString &method, ITransportLayer
{
return activateWindow(WINDOW_HOME);
}
+
+JSONRPC_STATUS CInputOperations::ShowCodec(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+ return SendAction(ACTION_SHOW_CODEC);
+}
+
+JSONRPC_STATUS CInputOperations::ShowOSD(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
+{
+ return SendAction(ACTION_SHOW_OSD);
+}
View
13 xbmc/interfaces/json-rpc/InputOperations.h
@@ -21,6 +21,7 @@
*/
#include "JSONRPC.h"
+#include "guilib/Key.h"
#include "threads/CriticalSection.h"
#include "utils/StdString.h"
@@ -29,7 +30,10 @@ namespace JSONRPC
class CInputOperations
{
public:
- static uint32_t GetKey();
+ static CKey GetKey();
+
+ static JSONRPC_STATUS SendText(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+ static JSONRPC_STATUS ExecuteAction(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
static JSONRPC_STATUS Left(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
static JSONRPC_STATUS Right(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
@@ -42,14 +46,17 @@ namespace JSONRPC
static JSONRPC_STATUS Info(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
static JSONRPC_STATUS Home(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
- static JSONRPC_STATUS SendKey(uint32_t keyCode);
+ static JSONRPC_STATUS ShowCodec(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+ static JSONRPC_STATUS ShowOSD(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result);
+
+ static JSONRPC_STATUS SendKey(uint32_t keyCode, bool unicode = false);
static JSONRPC_STATUS SendAction(int actionID, bool wakeScreensaver = true, bool waitResult = false);
private:
static JSONRPC_STATUS activateWindow(int windowID);
static bool handleScreenSaver();
static CCriticalSection m_critSection;
- static uint32_t m_key;
+ static CKey m_key;
};
}
View
6 xbmc/interfaces/json-rpc/JSONRPC.cpp
@@ -23,6 +23,7 @@
#include "JSONRPC.h"
#include "ServiceDescription.h"
+#include "input/ButtonTranslator.h"
#include "interfaces/AnnouncementManager.h"
#include "settings/AdvancedSettings.h"
#include "utils/log.h"
@@ -39,6 +40,11 @@ void CJSONRPC::Initialize()
if (m_initialized)
return;
+ // Add some types/enums at runtime
+ vector<string> inputActions;
+ CButtonTranslator::GetActions(inputActions);
+ CJSONServiceDescription::AddEnum("Input.Action", inputActions);
+
unsigned int size = sizeof(JSONRPC_SERVICE_TYPES) / sizeof(char*);
for (unsigned int index = 0; index < size; index++)
View
4 xbmc/interfaces/json-rpc/JSONServiceDescription.cpp
@@ -162,6 +162,8 @@ JsonRpcMethodMap CJSONServiceDescription::m_methodMaps[] = {
{ "System.Reboot", CSystemOperations::Reboot },
// Input operations
+ { "Input.SendText", CInputOperations::SendText },
+ { "Input.ExecuteAction", CInputOperations::ExecuteAction },
{ "Input.Left", CInputOperations::Left },
{ "Input.Right", CInputOperations::Right },
{ "Input.Down", CInputOperations::Down },
@@ -171,6 +173,8 @@ JsonRpcMethodMap CJSONServiceDescription::m_methodMaps[] = {
{ "Input.ContextMenu", CInputOperations::ContextMenu },
{ "Input.Info", CInputOperations::Info },
{ "Input.Home", CInputOperations::Home },
+ { "Input.ShowCodec", CInputOperations::ShowCodec },
+ { "Input.ShowOSD", CInputOperations::ShowOSD },
// Application operations
{ "Application.GetProperties", CApplicationOperations::GetProperties },
View
60 xbmc/interfaces/json-rpc/ServiceDescription.h
@@ -2328,6 +2328,27 @@ namespace JSONRPC
"\"params\": [],"
"\"returns\": \"string\""
"}",
+ "\"Input.SendText\": {"
+ "\"type\": \"method\","
+ "\"description\": \"Send a generic (unicode) text\","
+ "\"transport\": \"Response\","
+ "\"permission\": \"Navigate\","
+ "\"params\": ["
+ "{ \"name\": \"text\", \"type\": \"string\", \"minLength\": 1, \"required\": true, \"description\": \"Unicode text\" },"
+ "{ \"name\": \"done\", \"type\": \"boolean\", \"default\": true, \"description\": \"Whether this is the whole input or not (closes an open input dialog if true).\" }"
+ "],"
+ "\"returns\": \"string\""
+ "}",
+ "\"Input.ExecuteAction\": {"
+ "\"type\": \"method\","
+ "\"description\": \"Execute a specific action\","
+ "\"transport\": \"Response\","
+ "\"permission\": \"Navigate\","
+ "\"params\": ["
+ "{ \"name\": \"action\", \"$ref\": \"Input.Action\", \"required\": true }"
+ "],"
+ "\"returns\": \"string\""
+ "}",
"\"Input.Left\": {"
"\"type\": \"method\","
"\"description\": \"Navigate left in GUI\","
@@ -2400,6 +2421,22 @@ namespace JSONRPC
"\"params\": [],"
"\"returns\": \"string\""
"}",
+ "\"Input.ShowCodec\": {"
+ "\"type\": \"method\","
+ "\"description\": \"Show codec information of the playing item\","
+ "\"transport\": \"Response\","
+ "\"permission\": \"Navigate\","
+ "\"params\": [],"
+ "\"returns\": \"string\""
+ "}",
+ "\"Input.ShowOSD\": {"
+ "\"type\": \"method\","
+ "\"description\": \"Show the on-screen display for the current player\","
+ "\"transport\": \"Response\","
+ "\"permission\": \"Navigate\","
+ "\"params\": [],"
+ "\"returns\": \"string\""
+ "}",
"\"Application.GetProperties\": {"
"\"type\": \"method\","
"\"description\": \"Retrieves the values of the given properties\","
@@ -2660,6 +2697,29 @@ namespace JSONRPC
"}"
"],"
"\"returns\": null"
+ "}",
+ "\"Input.OnInputRequested\": {"
+ "\"type\": \"notification\","
+ "\"description\": \"The user is requested to provide some information.\","
+ "\"params\": ["
+ "{ \"name\": \"sender\", \"type\": \"string\", \"required\": true },"
+ "{ \"name\": \"data\", \"type\": \"object\", \"required\": true,"
+ "\"properties\": {"
+ "\"type\": { \"type\": \"string\", \"enum\": [ \"keyboard\", \"time\", \"date\", \"ip\", \"password\", \"number\", \"seconds\" ], \"required\": true },"
+ "\"title\": { \"type\": \"string\" }"
+ "}"
+ "}"
+ "],"
+ "\"returns\": null"
+ "}",
+ "\"Input.OnInputFinished\": {"
+ "\"type\": \"notification\","
+ "\"description\": \"The user has provided the requested input.\","
+ "\"params\": ["
+ "{ \"name\": \"sender\", \"type\": \"string\", \"required\": true },"
+ "{ \"name\": \"data\", \"type\": \"null\", \"required\": true }"
+ "],"
+ "\"returns\": null"
"}"
};
}
View
37 xbmc/interfaces/json-rpc/methods.json
@@ -1463,6 +1463,27 @@
"params": [],
"returns": "string"
},
+ "Input.SendText": {
+ "type": "method",
+ "description": "Send a generic (unicode) text",
+ "transport": "Response",
+ "permission": "Navigate",
+ "params": [
+ { "name": "text", "type": "string", "minLength": 1, "required": true, "description": "Unicode text" },
+ { "name": "done", "type": "boolean", "default": true, "description": "Whether this is the whole input or not (closes an open input dialog if true)." }
+ ],
+ "returns": "string"
+ },
+ "Input.ExecuteAction": {
+ "type": "method",
+ "description": "Execute a specific action",
+ "transport": "Response",
+ "permission": "Navigate",
+ "params": [
+ { "name": "action", "$ref": "Input.Action", "required": true }
+ ],
+ "returns": "string"
+ },
"Input.Left": {
"type": "method",
"description": "Navigate left in GUI",
@@ -1535,6 +1556,22 @@
"params": [],
"returns": "string"
},
+ "Input.ShowCodec": {
+ "type": "method",
+ "description": "Show codec information of the playing item",
+ "transport": "Response",
+ "permission": "Navigate",
+ "params": [],
+ "returns": "string"
+ },
+ "Input.ShowOSD": {
+ "type": "method",
+ "description": "Show the on-screen display for the current player",
+ "transport": "Response",
+ "permission": "Navigate",
+ "params": [],
+ "returns": "string"
+ },
"Application.GetProperties": {
"type": "method",
"description": "Retrieves the values of the given properties",
View
23 xbmc/interfaces/json-rpc/notifications.json
@@ -187,5 +187,28 @@
}
],
"returns": null
+ },
+ "Input.OnInputRequested": {
+ "type": "notification",
+ "description": "The user is requested to provide some information.",
+ "params": [
+ { "name": "sender", "type": "string", "required": true },
+ { "name": "data", "type": "object", "required": true,
+ "properties": {
+ "type": { "type": "string", "enum": [ "keyboard", "time", "date", "ip", "password", "number", "seconds" ], "required": true },
+ "title": { "type": "string" }
+ }
+ }
+ ],
+ "returns": null
+ },
+ "Input.OnInputFinished": {
+ "type": "notification",
+ "description": "The user has provided the requested input.",
+ "params": [
+ { "name": "sender", "type": "string", "required": true },
+ { "name": "data", "type": "null", "required": true }
+ ],
+ "returns": null
}
}