From 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 13 Apr 2025 18:48:02 +0100 Subject: initial --- site/udo/sequencing_melodic_persistence.web.udo | 213 ++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100755 site/udo/sequencing_melodic_persistence.web.udo (limited to 'site/udo/sequencing_melodic_persistence.web.udo') diff --git a/site/udo/sequencing_melodic_persistence.web.udo b/site/udo/sequencing_melodic_persistence.web.udo new file mode 100755 index 0000000..01d005f --- /dev/null +++ b/site/udo/sequencing_melodic_persistence.web.udo @@ -0,0 +1,213 @@ +#ifndef UDO_MELSEQUENCINGPERSIST +#define UDO_MELSEQUENCINGPERSIST ## +/* + Melodic sequencer persistence: saving/loading from files and database + Web version + + This file is part of the SONICS UDO collection by Richard Knight 2021, 2022, 2024 + License: GPL-2.0-or-later + http://1bpm.net +*/ + +#include "/sequencing_melodic.udo" +#include "/array_tools.udo" +#include "/table_tools.udo" +#include "/interop.udo" +#include "/json.udo" + + +/* + Get the current state as a JSON object + + iJson mel_getstate_json + + iJson the JSON object containing current sequencing and progression data + +*/ +opcode mel_getstate_json, S, 0 + Sjson = "{" + index = 0 + while (index < lenarray(gimel_fns)) do + Sjson = strcat(Sjson, sprintf("\"%s\":%s,", gSmel_names[index], tab_serialise(gimel_fns[index]))) + index += 1 + od + + Sjson = strcat(Sjson, sprintf("\"state\":%s,", tab_serialise(gimel_state))) + Sjson = strcat(Sjson, sprintf("\"details\":\"%s\",\"mel_number\":%d,\"seq_tempo\":%f,\"seq_swing\":%f}", gSmel_details, gimel_number, i(gkseq_tempo), i(gkseq_swing))) + xout Sjson +endop + + +/* + Set the current sequencing and progression state + + mel_setstate_json SJson + + SJson JSON string containing state data + +*/ +opcode mel_setstate_json, 0, S + Sjson xin + + i_, gSmel_details, i_ json_parse Sjson, "details" + i_, S_, gimel_number json_parse Sjson, "mel_number" + i_, S_, itempo json_parse Sjson, "seq_tempo" + i_, S_, iswing json_parse Sjson, "seq_swing" + +#ifdef MEL_INITTIME + gkseq_tempo init itempo + gkseq_swing init iswing +#end + + ; if data to be loaded has more progression items than ftables, free and generate again + if (gimel_number > ftlen(gimel_fns[0])) then + index = 0 + while (index < lenarray(gimel_fns)) do + ftfree gimel_fns[index], 0 + gimel_fns[index] = ftgen(0, 0, -gimel_number, -7, 0) + od + endif + + + index = 0 + while (index < lenarray(gimel_fns)) do + i_, Stringvalue, i_ json_parse Sjson, gSmel_names[index] + iarray[] json_getnumericarray Stringvalue + copya2ftab iarray, gimel_fns[index] + index += 1 + od + + + i_, Stringvalue, i_ json_parse Sjson, "state" + iarray[] json_getnumericarray Stringvalue + copya2ftab iarray, gimel_state +endop + + + + +instr mel_savestate_fs + prints sprintf("%s unsupported in web UDO\n", nstrstr(p1)) + turnoff +endin + +instr mel_loadstate_fs + prints sprintf("%s unsupported in web UDO\n", nstrstr(p1)) + turnoff +endin + + +/* + Save the sequencing and progression state to database + + p4 reference name in database + p5 optional callback ID for host interop; sent on completion +*/ +instr mel_savestate_db + Sname = p4 + icbid = p5 + + turnoff +endin + + + + + +/* + Load the sequencing and progression state from database + + p4 reference name in database + p5 optional callback ID for host interop; sent on completion +*/ +instr mel_loadstate_db + Sname = p4 + icbid = p5 + + schedule("mel_futures_refresh", 0, 1) + turnoff +endin + + + +/* + Load the sequencing and progression state from a string channel + + p4 channel name containing string representation of JSON + p5 optional callback ID for host interop; sent on completion +*/ +instr mel_loadstate_channel + Schannel = p4 + icbid = p5 + Sdata chnget Schannel + mel_setstate_json(Sdata) + if (icbid != 0) then + schedule("io_callback", 0, 1, icbid) + endif + schedule("mel_futures_refresh", 0, 1) + turnoff +endin + + +/* + Just get state: interop host handles persistence + p4 callback ID to send data with/to +*/ +instr mel_getstate_string + icbid = p4 + Sjson = mel_getstate_json() + Sjson json_appendvalue Sjson, "cbid", icbid + io_sendstring("callback", Sjson) + turnoff +endin + + +/* + Get an array of the known mel states from database + Sdata[] mel_liststates_db + + Sdata[] the state names + +opcode mel_liststates_db, S[], 0 + Sresult[][] dbarray gidb, "SELECT name FROM savejson WHERE unit = 'melsys'" + ilen = lenarray(Sresult) + Sdata[] init ilen + index = 0 + while (index < ilen) do + Sdata[index] = Sresult[index][0] + index += 1 + od + xout Sdata +endop +*/ + +/* + Get a list of mel states from database and return to host with the specified callback ID + + p4 callback ID +*/ +instr mel_liststates_db + icbid = p4 + turnoff +endin + + +; if MEL_INITPATH or MEL_INITDB is set, load the specified progression data accordingly +#ifdef MEL_HASINIT +instr _mel_persistence_init +#ifdef MEL_INITPATH + subinstrinit "mel_loadstate_fs", "$MEL_INITPATH" +#end +#ifdef MEL_INITDB + ;mel_loadstate_db "$MEL_INITDB" + subinstrinit "mel_loadstate_db", "$MEL_INITDB" +#end + alwayson "_mel_manager" + turnoff +endin +schedule "_mel_persistence_init", 0, 60 + +; end MEL_HASINIT +#end + +#end -- cgit v1.2.3