Skip to content

Commit

Permalink
Feat: populate scriptevent variable for lua scripts #1279
Browse files Browse the repository at this point in the history
  • Loading branch information
jcorporation committed May 13, 2024
1 parent 88f1b10 commit 1928d92
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 13 deletions.
1 change: 1 addition & 0 deletions docs/scripting/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ myMPD populates automatically some global variables.
| -------- | ----------- |
| `arguments` | Script arguments |
| `partition` | MPD partition |
| `scriptevent` | Script start event: `extern`, `http`, `timer`, `trigger` or `user` |
| `scriptname` | Script name |

### Arguments
Expand Down
5 changes: 5 additions & 0 deletions htdocs/js/apidoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -1816,6 +1816,11 @@ const APImethods = {
"desc": "Executes a script",
"params": {
"script": APIparams.script,
"event": {
"type": APItypes.string,
"example": "user",
"desc": "One of: extern, http, timer, trigger or user"
},
"arguments": APIparams.scriptArguments
}
},
Expand Down
2 changes: 2 additions & 0 deletions htdocs/js/modalScriptExec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function execScript(cmd) {
if (cmd.arguments.length === 0) {
sendAPI("MYMPD_API_SCRIPT_EXECUTE", {
"script": cmd.script,
"event": "user",
"arguments": {}
}, null, false);
}
Expand Down Expand Up @@ -64,6 +65,7 @@ function execScriptArgs(target) {
}
sendAPI("MYMPD_API_SCRIPT_EXECUTE", {
"script": script,
"event": "user",
"arguments": args
}, modalClose, true);
}
8 changes: 5 additions & 3 deletions src/mympd_api/mympd_api_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,14 @@ void mympd_api_handler(struct t_mympd_state *mympd_state, struct t_partition_sta
break;
}
case MYMPD_API_SCRIPT_EXECUTE: {
//malloc list - it is used in another thread
//malloc list - it is used in the script thread
struct t_list *arguments = list_new();
if (json_get_string(request->data, "$.params.script", 1, FILENAME_LEN_MAX, &sds_buf1, vcb_isfilename, &parse_error) == true &&
json_get_string(request->data, "$.params.event", 0, FILENAME_LEN_MAX, &sds_buf2, vcb_isfilename, &parse_error) == true &&
json_get_object_string(request->data, "$.params.arguments", arguments, vcb_isname, 10, &parse_error) == true)
{
rc = mympd_api_script_start(config->workdir, sds_buf1, config->lualibs, arguments, partition_state->name, true);
enum script_start_events script_event = script_start_event_parse(sds_buf2);
rc = mympd_api_script_start(config->workdir, sds_buf1, config->lualibs, arguments, partition_state->name, true, script_event);
response->data = jsonrpc_respond_with_ok_or_error(response->data, request->cmd_id, request->id, rc,
JSONRPC_FACILITY_SCRIPT, "Can't create mympd_script thread");
}
Expand All @@ -355,7 +357,7 @@ void mympd_api_handler(struct t_mympd_state *mympd_state, struct t_partition_sta
if (json_get_string(request->data, "$.params.script", 1, CONTENT_LEN_MAX, &sds_buf1, vcb_istext, &parse_error) == true &&
json_get_object_string(request->data, "$.params.arguments", arguments, vcb_isname, 10, &parse_error) == true)
{
rc = mympd_api_script_start(config->workdir, sds_buf1, config->lualibs, arguments, partition_state->name, false);
rc = mympd_api_script_start(config->workdir, sds_buf1, config->lualibs, arguments, partition_state->name, false, SCRIPT_START_EXTERN);
response->data = jsonrpc_respond_with_ok_or_error(response->data, request->cmd_id, request->id, rc,
JSONRPC_FACILITY_SCRIPT, "Can't create mympd_script thread");
}
Expand Down
54 changes: 45 additions & 9 deletions src/mympd_api/scripts/scripts.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,14 @@
* Struct for passing values to the script thread
*/
struct t_script_thread_arg {
sds lualibs; //!< comma separated string of lua libs to load
bool localscript; //!< true = read script from filesystem, false = use script_content
sds script_fullpath; //!< full uri of the script
sds script_name; //!< name of the script
sds script_content; //!< script content if localscript = false
sds partition; //!< execute the script in this partition
struct t_list *arguments; //!< argumentlist
sds lualibs; //!< comma separated string of lua libs to load
bool localscript; //!< true = read script from filesystem, false = use script_content
sds script_fullpath; //!< full uri of the script
sds script_name; //!< name of the script
sds script_content; //!< script content if localscript = false
sds partition; //!< execute the script in this partition
struct t_list *arguments; //!< argumentlist
enum script_start_events start_event; //!< script start event
};

static lua_State *script_load(struct t_script_thread_arg *script_arg, int *rc);
Expand Down Expand Up @@ -286,7 +287,7 @@ sds mympd_api_script_get(sds workdir, sds buffer, unsigned request_id, sds scrip
* @return true on success, else false
*/
bool mympd_api_script_start(sds workdir, sds script, sds lualibs, struct t_list *arguments,
const char *partition, bool localscript)
const char *partition, bool localscript, enum script_start_events start_event)
{
pthread_t mympd_script_thread;
pthread_attr_t attr;
Expand All @@ -303,8 +304,9 @@ bool mympd_api_script_start(sds workdir, sds script, sds lualibs, struct t_list
script_thread_arg->localscript = localscript;
script_thread_arg->arguments = arguments;
script_thread_arg->partition = sdsnew(partition);
script_thread_arg->start_event = start_event;
if (localscript == true) {
script_thread_arg->script_name = sdsnew(script);
script_thread_arg->script_name = sdsdup(script);
script_thread_arg->script_fullpath = sdscatfmt(sdsempty(), "%S/%s/%S.lua", workdir, DIR_WORK_SCRIPTS, script);
script_thread_arg->script_content = sdsempty();
}
Expand All @@ -322,6 +324,37 @@ bool mympd_api_script_start(sds workdir, sds script, sds lualibs, struct t_list
return true;
}

/**
* Returns the name for the script start event
* @param start_event start event enum
* @return start event name or empty if unknown
*/
const char *script_start_event_name(enum script_start_events start_event) {
switch (start_event) {
case SCRIPT_START_EXTERN: return "extern";
case SCRIPT_START_HTTP: return "http";
case SCRIPT_START_TIMER: return "timer";
case SCRIPT_START_TRIGGER: return "trigger";
case SCRIPT_START_USER: return "user";
case SCRIPT_START_UNKNOWN: return "";
}
return "";
}

/**
* Parses the name for the script start event
* @param str string to parse
* @return script_start_event enum
*/
enum script_start_events script_start_event_parse(const char *str) {
if (strcmp(str, "http") == 0) { return SCRIPT_START_HTTP; }
if (strcmp(str, "timer") == 0) { return SCRIPT_START_TIMER; }
if (strcmp(str, "trigger") == 0) { return SCRIPT_START_TRIGGER; }
if (strcmp(str, "user") == 0) { return SCRIPT_START_USER; }
if (strcmp(str, "extern") == 0) { return SCRIPT_START_EXTERN; }
return SCRIPT_START_UNKNOWN;
}

/**
* Private functions
*/
Expand Down Expand Up @@ -481,6 +514,9 @@ static void *script_execute(void *script_thread_arg) {
//set global lua variable scriptname
lua_pushstring(lua_vm, script_arg->script_name);
lua_setglobal(lua_vm, "scriptname");
//set global lua variable scriptevent
lua_pushstring(lua_vm, script_start_event_name(script_arg->start_event));
lua_setglobal(lua_vm, "scriptevent");
//set arguments lua table
lua_newtable(lua_vm);
if (script_arg->arguments->length > 0) {
Expand Down
13 changes: 12 additions & 1 deletion src/mympd_api/scripts/scripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,23 @@

#include <stdbool.h>

enum script_start_events {
SCRIPT_START_UNKNOWN = -1,
SCRIPT_START_TIMER,
SCRIPT_START_TRIGGER,
SCRIPT_START_USER,
SCRIPT_START_HTTP,
SCRIPT_START_EXTERN
};

bool mympd_api_script_save(sds workdir, sds script, sds oldscript, int order, sds content, struct t_list *arguments, sds *error);
bool mympd_api_script_validate(sds name, sds content, sds lualibs, sds *error);
bool mympd_api_script_delete(sds workdir, sds script);
sds mympd_api_script_get(sds workdir, sds buffer, unsigned request_id, sds script);
sds mympd_api_script_list(sds workdir, sds buffer, unsigned request_id, bool all);
bool mympd_api_script_start(sds workdir, sds script, sds lualibs, struct t_list *arguments,
const char *partition, bool localscript);
const char *partition, bool localscript, enum script_start_events start_event);
const char *script_start_event_name(enum script_start_events start_event);
enum script_start_events script_start_event_parse(const char *str);

#endif
2 changes: 2 additions & 0 deletions src/mympd_api/timer_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "src/mpd_client/shortcuts.h"
#include "src/mpd_client/volume.h"
#include "src/mympd_api/requests.h"
#include "src/mympd_api/scripts/scripts.h"

#include <string.h>

Expand Down Expand Up @@ -79,6 +80,7 @@ void timer_handler_select(unsigned timer_id, struct t_timer_definition *definiti
else if (strcmp(definition->action, "script") == 0) {
struct t_work_request *request = create_request(REQUEST_TYPE_DISCARD, 0, 0, MYMPD_API_SCRIPT_EXECUTE, NULL, definition->partition);
request->data = tojson_sds(request->data, "script", definition->subaction, true);
request->data = tojson_char(request->data, "event", script_start_event_name(SCRIPT_START_TIMER), true);
request->data = sdscat(request->data, "\"arguments\":{");
struct t_list_node *argument = definition->arguments.head;
int i = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/mympd_api/trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "src/lib/msg_queue.h"
#include "src/lib/sds_extras.h"
#include "src/lib/state_files.h"
#include "src/mympd_api/scripts/scripts.h"

#include <errno.h>
#include <string.h>
Expand Down Expand Up @@ -488,6 +489,7 @@ static sds trigger_to_line_cb(sds buffer, struct t_list_node *current, bool newl
void trigger_execute(sds script, struct t_list *arguments, const char *partition) {
struct t_work_request *request = create_request(REQUEST_TYPE_DISCARD, 0, 0, MYMPD_API_SCRIPT_EXECUTE, NULL, partition);
request->data = tojson_sds(request->data, "script", script, true);
request->data = tojson_char(request->data, "event", script_start_event_name(SCRIPT_START_TIMER), true);
request->data = sdscat(request->data, "\"arguments\": {");
struct t_list_node *argument = arguments->head;
int i = 0;
Expand Down

0 comments on commit 1928d92

Please sign in to comment.