aboutsummaryrefslogtreecommitdiff
path: root/site/udo/sequencing_melodic_persistence.udo
blob: 070983269c4d61f887bba81d503a03a67fbbe4a1 (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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#ifndef UDO_MELSEQUENCINGPERSIST
#define UDO_MELSEQUENCINGPERSIST ##
/*
	Melodic sequencer persistence: saving/loading from files and database
	Requires JSON opcodes

	This file is part of the SONICS UDO collection by Richard Knight 2021, 2022
		License: GPL-2.0-or-later
		http://1bpm.net
*/

#include "pgdb.udo"
#include "sequencing_melodic.udo"
#include "array_tools.udo"
#include "interop.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, i, 0
	iJson jsoninit
	index = 0
	while (index < lenarray(gimel_fns)) do
		iarray[] tab2array gimel_fns[index]
		jsoninsertval iJson, gSmel_names[index], iarray
		index += 1
	od
	iarray[] tab2array gimel_state
	jsoninsertval iJson, "state", iarray
	jsoninsertval iJson, "details", gSmel_details
	jsoninsertval iJson, "mel_number", gimel_number
	jsoninsertval iJson, "seq_tempo", i(gkseq_tempo)
	jsoninsertval iJson, "seq_swing", i(gkseq_swing)
	xout iJson
endop


/*
	Set the current sequencing and progression state

	mel_setstate_json iJson

	iJson		JSON object containing state data
	
*/
opcode mel_setstate_json, 0, i
	iJson xin
	
	gSmel_details jsongetval iJson, "details"
	gimel_number jsongetval iJson, "mel_number"
	itempo jsongetval iJson, "seq_tempo"
	iswing jsongetval iJson, "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
		iJsonSub jsonget iJson, gSmel_names[index]
		iarray[] jsonarrval iJsonSub
		copya2ftab iarray, gimel_fns[index]
		jsondestroy iJsonSub
		index += 1
	od


	iJsonSub jsonget iJson, "state"
	iarray[] jsonarrval iJsonSub
	copya2ftab iarray, gimel_state
	jsondestroy(iJsonSub)

endop



/*
	Save the sequencing and progression state to a file

	p4		path to save file to
	p5		optional callback ID for host interop; sent on completion
*/
instr mel_savestate_fs
	Spath = p4
	icbid = p5
	iJson = mel_getstate_json()
	jsondump(iJson, Spath)
	jsondestroy(iJson)
	if (icbid != 0) then
		schedule("io_callback", 0, 1, icbid)
	endif
	turnoff
endin



opcode mel_loadstate_fs, 0, S
	Spath xin
	iJson jsonload Spath
	mel_setstate_json(iJson)
	jsondestroy(iJson)
endop
/*
	Load the sequencing and progression state from a file

	p4		path to load data from
	p5		optional callback ID for host interop; sent on completion
*/
instr mel_loadstate_fs
	Spath = p4
	icbid = p5
	mel_loadstate_fs Spath
	if (icbid != 0) then
		schedule("io_callback", 0, 1, icbid)
	endif
	schedule("mel_futures_refresh", 0, 1)
	turnoff
endin



opcode mel_savestate_db, 0, S
	Sname xin
	iJson = mel_getstate_json()
	pgdb_json_save Sname, "melsys", iJson
	jsondestroy(iJson)
endop
/*
	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
	mel_savestate_db Sname
	if (icbid != 0) then
		schedule("io_callback", 0, 1, icbid)
	endif
	turnoff
endin



opcode mel_loadstate_db, 0, S
	Sname xin
	iJson pgdb_json_load Sname, "melsys"
	mel_setstate_json(iJson)
	jsondestroy(iJson)
endop
/*
	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
	mel_loadstate_db Sname
	if (icbid != 0) then
		schedule("io_callback", 0, 1, icbid)
	endif
	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
	iJson jsonloads Sdata
	mel_setstate_json(iJson)
	jsondestroy(iJson)
	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
	iJson = mel_getstate_json()
	jsoninsertval iJson, "cbid", icbid
	Sjson = jsondumps(iJson, 0)
	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
	iJson = jsoninit()
	jsoninsertval(iJson, "cbid", icbid)
	jsoninsertval(iJson, "states", mel_liststates_db())
	io_sendstring("callback", jsondumps(iJson, 0))
	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