aboutsummaryrefslogtreecommitdiff
path: root/site/udo/sequencing_melodic_persistence.web.udo
blob: 01d005fd0496180a560c6f48c6f561ee6e428a0a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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