aboutsummaryrefslogtreecommitdiff
path: root/site/udo/scss/persistence.udo
diff options
context:
space:
mode:
authorRichard <q@1bpm.net>2025-04-13 18:48:02 +0100
committerRichard <q@1bpm.net>2025-04-13 18:48:02 +0100
commit9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 (patch)
tree291bd79ce340e67affa755a8a6b4f6a83cce93ea /site/udo/scss/persistence.udo
downloadapps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.gz
apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.tar.bz2
apps.csound.1bpm.net-9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22.zip
initial
Diffstat (limited to 'site/udo/scss/persistence.udo')
-rwxr-xr-xsite/udo/scss/persistence.udo366
1 files changed, 366 insertions, 0 deletions
diff --git a/site/udo/scss/persistence.udo b/site/udo/scss/persistence.udo
new file mode 100755
index 0000000..075b06a
--- /dev/null
+++ b/site/udo/scss/persistence.udo
@@ -0,0 +1,366 @@
+#ifndef UDO_SCSS_PERSISTENCE
+#define UDO_SCSS_PERSISTENCE ##
+/*
+ SONICS Category Sequencer System
+ Persistence: saving and loading state to database and FS
+
+ Designed for use with an API host to/from which callbacks and JSON states can be exchanged
+
+ Requires JSON opcodes
+ https://git.1bpm.net/csound-json
+
+ This file is part of the SONICS UDO collection by Richard Knight 2022
+ License: GPL-2.0-or-later
+ http://1bpm.net
+*/
+#include "sequencing_melodic_persistence.udo"
+#include "table_tools.udo"
+#include "pgdb.udo"
+
+opcode scss_json2tab, 0, ii
+ iJson, ifn xin
+ if (jsontype(iJson) == 4) then
+ iarray[] jsonarrval iJson
+ copya2ftab iarray, ifn
+ endif
+endop
+
+opcode scss_json2tab, 0, iiS
+ iJsonTop, ifn, Skey xin
+ iJson = jsonget(iJsonTop, Skey)
+ scss_json2tab(iJson, ifn)
+ jsondestroy(iJson)
+endop
+
+opcode scss_tabarr2json, 0, iSi[][]
+ iJson, Srelname, ifns[][] xin
+ iJarrTop = jsonloads("[]")
+ index = 0
+ while (index < lenarray(ifns, 1)) do
+ iJarrSub = jsonloads("[]")
+ index2 = 0
+ while (index2 < lenarray(ifns, 2)) do
+ iJtable = jsonloads(tab_serialise(ifns[index][index2]))
+ jsonptradd iJarrSub, sprintf("/%d", jsonsize(iJarrSub)), iJtable
+ index2 += 1
+ od
+ index += 1
+ jsonptradd iJarrTop, sprintf("/%d", jsonsize(iJarrTop)), iJarrSub
+ jsondestroy(iJarrSub)
+ od
+ jsoninsert iJson, Srelname, iJarrTop
+ jsondestroy(iJarrTop)
+endop
+
+
+opcode scss_json2tabarr, i[][], iSi[][]
+ iJsonTop, Srelname, ifns[][] xin
+ iJson = jsonget(iJsonTop, Srelname)
+ isize = jsonsize(iJson)
+ index = 0
+ while (index < isize) do
+ iJsonSub = jsonget(iJson, index)
+ isize2 = jsonsize(iJsonSub)
+ index2 = 0
+ while (index2 < isize2) do
+ iJtable = jsonget(iJsonSub, index2)
+
+ iarray[] jsonarrval iJsonSub
+ copya2ftab iarray, ifns[index][index2]
+ ;tab_unserialise(jsondumps(iJtable, 0), ifns[index][index2])
+ jsondestroy(iJtable)
+ index2 += 1
+ od
+ jsondestroy(iJsonSub)
+ index += 1
+ od
+ jsondestroy(iJson)
+ xout ifns
+endop
+
+
+/*
+ Set parameters based on a JSON object with key as channel name and value as channel value to be set
+
+ scss_setparamstate iJsonInput
+
+ iJsonInput JSON object of channel values
+*/
+opcode scss_setparamstate, 0, i
+ iJsonInput xin
+ Skeys[] jsonkeys iJsonInput
+ index = 0
+ while (index < lenarray(Skeys)) do
+ Sparam = Skeys[index]
+ chnset jsongetval:i(iJsonInput, Sparam), Sparam
+ index += 1
+ od
+endop
+
+
+
+/*
+ Get parameters from a SCSS definition JSON object and append current values to iJsonOutput using channel prefix Sprefix
+
+ _scss_getparams iJsonInput, iJsonOutput, Sprefix
+
+ iJsonInput object to evaluate; should have an array with key "parameters" featuring objects which have a key "name" specifying parameter name
+ iJsonOutput output object to add values to (key is channel name, value is current value)
+ Sprefix parameter prefix to use for channel name
+*/
+opcode _scss_getparams, 0, iiS
+ iJsonInput, iJsonOutput, Sprefix xin
+ SparameterPointer = "/parameters"
+ if (jsonptrhas(iJsonInput, SparameterPointer) == 1) then
+ iJsonParameters = jsonptr(iJsonInput, SparameterPointer)
+ iparamsize = jsonsize(iJsonParameters)
+ indexparam = 0
+ while (indexparam < iparamsize) do
+ SparamName jsonptrval iJsonParameters, sprintf("/%d/name", indexparam)
+ Sparam = sprintf("%s_%s", Sprefix, SparamName)
+ jsoninsertval iJsonOutput, Sparam, chnget:i(Sparam)
+ indexparam += 1
+ od
+ jsondestroy(iJsonParameters)
+ endif
+endop
+
+
+/*
+ Get all registered parameters in giscss_stateJson, and get current channel values,
+ returning an object with key as channel name and value as channel value
+
+ iJsonOutput scss_getparamstate
+
+ iJsonOutput JSON object of channel values
+*/
+opcode scss_getparamstate, i, 0
+ iJsonOutput = jsoninit()
+
+
+ ; global parameters
+ _scss_getparams(giscss_stateJson, iJsonOutput, "scss")
+
+ ; categories
+ iJsonCategories = jsonptr(giscss_stateJson, "/categories")
+ icatnum = jsonsize(iJsonCategories)
+ jsondestroy(iJsonCategories)
+ index = 0
+ while (index < icatnum) do
+ iJsonCategory = jsonptr(giscss_stateJson, sprintf("/categories/%d", index))
+ Scategory jsonptrval iJsonCategory, "/name"
+
+ ; category parameters
+ _scss_getparams(iJsonCategory, iJsonOutput, Scategory)
+
+ ; items/instruments
+ iJsonItems = jsonptr(iJsonCategory, "/items")
+ iinstrnum = jsonsize(iJsonItems)
+ indexItem = 0
+ while (indexItem < iinstrnum) do
+ iJsonItem = jsonptr(iJsonItems, sprintf("/%d", indexItem))
+ Sinstrument = jsongetval(iJsonItem, "name")
+ _scss_getparams(iJsonItem, iJsonOutput, Sinstrument)
+ jsondestroy(iJsonItem)
+ indexItem += 1
+ od
+ jsondestroy(iJsonItems)
+ jsondestroy(iJsonCategory)
+ index += 1
+ od
+ xout iJsonOutput
+endop
+
+
+
+/*
+ Get sequencing state as JSON object
+
+ iJsonSeq scss_getseqstate
+
+ iJsonSeq object of sequencing data
+*/
+opcode scss_getseqstate, i, 0
+ iJsonSeq = jsoninit()
+ scss_tabarr2json(iJsonSeq, "giscss_stfn_trig", giscss_stfn_trig)
+ scss_tabarr2json(iJsonSeq, "giscss_stfn_dur", giscss_stfn_dur)
+ scss_tabarr2json(iJsonSeq, "giscss_stfn_params", giscss_stfn_params)
+
+ Skeys[] fillarray "giscss_st_size", "giscss_st_slots", "giscss_st_paramnumber" ; giscss_stfn_temp", "giscss_stfn_param_temp"
+ ivalues[] fillarray giscss_st_size, giscss_st_slots, giscss_st_paramnumber ; giscss_stfn_temp giscss_stfn_param_temp
+ jsoninsertval(iJsonSeq, Skeys, ivalues)
+ xout iJsonSeq
+endop
+
+
+
+/*
+ Set sequencing state from JSON object
+
+ scss_setseqstate iJsonSeq
+
+ iJsonSeq object of sequencing data
+*/
+opcode scss_setseqstate, 0, i
+ iJsonSeq xin
+
+ giscss_stfn_trig scss_json2tabarr iJsonSeq, "giscss_stfn_trig", giscss_stfn_trig
+ giscss_stfn_dur scss_json2tabarr iJsonSeq, "giscss_stfn_dur", giscss_stfn_dur
+ giscss_stfn_params scss_json2tabarr iJsonSeq, "giscss_stfn_params", giscss_stfn_params
+
+ giscss_st_size = jsongetval:i(iJsonSeq, "giscss_st_size")
+ giscss_st_slots = jsongetval:i(iJsonSeq, "giscss_st_slots")
+ giscss_st_paramnumber = jsongetval:i(iJsonSeq, "giscss_st_paramnumber")
+endop
+
+
+
+opcode scss_getstate, i, ppppp
+ igetsequencing, igetparameters, igetmelstate, igetinstrstate, igetcatenabled xin
+
+ iJson = jsoninit()
+
+ if (igetsequencing == 1) then
+ iJsonSequencing = scss_getseqstate()
+ jsoninsert(iJson, "sequencing", iJsonSequencing)
+ jsondestroy(iJsonSequencing)
+ endif
+
+ if (igetparameters == 1) then
+ iJsonParameters = scss_getparamstate()
+ jsoninsert(iJson, "parameters", iJsonParameters)
+ jsondestroy(iJsonParameters)
+ endif
+
+ if (igetmelstate == 1) then
+ iJsonMelstate = mel_getstate_json()
+ jsoninsert(iJson, "melstate", iJsonMelstate)
+ jsondestroy(iJsonMelstate)
+ endif
+
+
+ if (igetinstrstate == 1) then
+ iJinstrState = jsonloads(tab_serialise(giscss_instrState))
+ jsoninsert(iJson, "giscss_instrState", iJinstrState)
+ jsondestroy(iJinstrState)
+ endif
+
+ if (igetcatenabled == 1) then
+ iJcatEnabled = jsonloads(tab_serialise(giscss_catEnabled))
+ jsoninsert(iJson, "giscss_catEnabled", iJcatEnabled)
+ jsondestroy(iJcatEnabled)
+ endif
+
+ xout iJson
+endop
+
+
+
+opcode scss_setstate, 0, ippppp
+ iJson, isetsequencing, isetparameters, isetmelstate, isetinstrstate, isetcatenabled xin
+
+ if (isetsequencing == 1 && jsonptrhas(iJson, "/sequencing") == 1) then
+ iJsonSequencing = jsonget(iJson, "sequencing")
+ scss_setseqstate(iJsonSequencing)
+ jsondestroy(iJsonSequencing)
+ endif
+
+ if (isetparameters == 1 && jsonptrhas(iJson, "/parameters") == 1) then
+ iJsonParameters = jsonget(iJson, "parameters")
+ scss_setparamstate(iJsonParameters)
+ jsondestroy(iJsonParameters)
+ endif
+
+ if (isetmelstate == 1 && jsonptrhas(iJson, "/melstate") == 1) then
+ iJsonMelstate = jsonget(iJson, "melstate")
+ mel_setstate_json(iJsonMelstate)
+ jsondestroy(iJsonMelstate)
+ endif
+
+ if (isetinstrstate == 1 && jsonptrhas(iJson, "/giscss_instrState") == 1) then
+ iJinstrState = jsonget(iJson, "giscss_instrState")
+ endif
+
+ if (isetcatenabled == 1 && jsonptrhas(iJson, "/giscss_catEnabled") == 1) then
+ iJcatEnabled = jsonget(iJson, "giscss_catEnabled")
+ endif
+
+endop
+
+
+
+/*
+ Get the current values of all registered parameters, returning callback ID to host and an object with key "parameters"
+ containing keys as the channel names and values as the channel values
+
+ p4 callback ID
+*/
+instr scss_getparamstate
+ icbid = p4
+ iJson = jsoninit()
+ iJsonState = scss_getparamstate()
+ jsoninsert iJson, "parameters", iJsonState
+ jsoninsertval iJson, "cbid", icbid
+ jsoninsertval iJson, "status", "complete"
+ io_sendstring("callback", jsondumps(iJson, 0))
+ jsondestroy(iJsonState)
+ jsondestroy(iJson)
+ turnoff
+endin
+
+
+
+/*
+ Save state to database
+
+ p4 callback ID
+ p5 reference name of the state to save; blank is accepted and saves as SCSS_NAME
+*/
+instr scss_savestate_db
+ icbid = p4
+ Sreference = strcat("$SCSS_NAME||", strget(p5))
+
+ ; save state values
+ iJsonState = scss_getstate()
+ Squery = sprintf("DELETE FROM savejson WHERE name = '%s' AND unit = 'scss_state'; INSERT INTO savejson (name, data, unit, created) VALUES ('%s', '%s', 'scss_state', current_timestamp)",\
+ Sreference, Sreference, jsondumps(iJsonState, 0)\
+ )
+ dbexec gidb, Squery
+ jsondestroy(iJsonState)
+
+
+ ; return callback ID to host
+ iJson = jsoninit()
+ jsoninsertval iJson, "cbid", icbid
+ jsoninsertval iJson, "status", "complete"
+ io_sendstring("callback", jsondumps(iJson, 0))
+ turnoff
+endin
+
+
+
+
+/*
+ Load parameter state from database, returning JSON to host as in the instrument scss_getparamstate
+
+ p4 callback ID
+ p5 reference name of the state to load; blank is accepted and loads as SCSS_NAME
+*/
+instr scss_loadstate_db
+ icbid = p4
+ Sreference = strcat("$SCSS_NAME||", strget(p5))
+
+ ; load parameter values
+ Squery = sprintf("SELECT data::text FROM savejson WHERE unit = 'scss_state' AND name = '%s'", Sreference)
+ Sresult dbscalar gidb, Squery
+ iJson = jsonloads(Sresult)
+ scss_setstate(iJson)
+ jsondestroy(iJson)
+
+ ; returns state data and callback ID to host
+ schedule("scss_getparamstate", 0, 1, icbid)
+ turnoff
+endin
+
+
+#end