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
|
#ifndef UDO_MELSEQUENCINGPERSIST_LEGACY
#define UDO_MELSEQUENCINGPERSIST_LEGACY ##
/*
Melodic sequencer persistence: saving/loading from files and database
Legacy: superceded by JSON
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"
/*
Save state to file
p4 path to save to
*/
instr mel_savestate_fs
Spath = p4
ftsave Spath, 1,\
gimel_chords, gimel_notes,
gimel_lengths, gimel_action1,\
gimel_action2, gimel_actionthreshold,\
gimel_active, gimel_importance,\
gimel_mod1, gimel_mod2,\
gimel_mod3, gimel_mod4,\
gimel_state
turnoff
endin
/*
Load state from file
p4 path to load from
*/
instr mel_loadstate_fs
Spath = p4
isize = -1
iline = 0
/* ; COMMENTED AS readfi IS NOT AVAILABLE ON LIVE COMP?!?!?! - testing if size matches etc
; get size from first table
while (isize == -1 && iline != -1) do
Sline, iline readfi Spath
if (strcmp(strsub(Sline, 0, 4), "flen") == 0) then
isize = strtod(strsub(Sline, 6, strlen(Sline)-1))
isizefound = 1
endif
od
; size not found in file
if (isize == -1) then
isize = ftlen(gimel_chords)
; resize required
elseif (isize != ftlen(gimel_chords)) then
gimel_number = isize
_mel_refreshactions() ; update actions list to cater for number of patterns
index = 0
while (index < lenarray(gimel_fns)) do
ifn = gimel_fns[index]
ftfree ifn, 0
itemp ftgen 0, 0, -isize, -7, 0
index += 1
od
endif
*/
ftload Spath, 1,\
gimel_chords, gimel_notes,
gimel_lengths, gimel_action1,\
gimel_action2, gimel_actionthreshold,\
gimel_active, gimel_importance,\
gimel_mod1, gimel_mod2,\
gimel_mod3, gimel_mod4,\
gimel_state
gkmel_futures_refresh_trig = 1
turnoff
endin
/*
Save state to database
mel_savestate_db Sname
Sname identifier to be used
*/
opcode mel_savestate_db, 0, S
Sname xin
pgdb_table_save Sname, "melseq", gimel_state
index = 0
while (index < lenarray(gimel_fns)) do
pgdb_table_save strcat(Sname, strcat("||", gSmel_names[index])), "melseq", gimel_fns[index]
index += 1
od
endop
; broken: underlying pgdb_table_savek not working
opcode mel_savestate_dbk, k, S
Sname xin
ilength = lenarray(gimel_fns)
ktrigger init 0
kcomplete init 0
kindex init -1
if (kindex == -1) then
kdone pgdb_table_savek Sname, "melseq", gimel_state, -1
else
kdone pgdb_table_savek strcatk(Sname, strcatk("||", gSmel_names[kindex])), "melseq", gimel_fns[kindex], ktrigger
ktrigger = 0
endif
if (kdone == 1) then
if (kindex + 1 < ilength) then
kindex += 1
ktrigger = 1
else
kcomplete = 1
endif
endif
xout kcomplete
endop
; ftresize ?????
/*
Load state from database
mel_loadstate_db Sname
Sname identifier to be used
*/
opcode mel_loadstate_db, 0, S
Sname xin
inull pgdb_table_get Sname, "melseq", gimel_state
index = 0
while (index < lenarray(gimel_fns)) do
StestName = sprintf("%s||%s", Sname, gSmel_names[index])
inull pgdb_table_get StestName, "melseq", gimel_fns[index]
index += 1
od
gkmel_futures_refresh_trig = 1
endop
/*
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 distinct (string_to_array(name, '||'))[1] FROM savearray WHERE unit = 'melseq'"
ilen = lenarray(Sresult)
Sdata[] init ilen
index = 0
while (index < ilen) do
Sdata[index] = Sresult[index][0]
index += 1
od
xout Sdata
endop
; broken
instr mel_savestate_dbk
Sname = p4
kdone mel_savestate_dbk Sname
if (kdone == 1) then
io_sendstring("mel_state_saved", Sname)
turnoff
endif
endin
instr mel_savestate_db
Sname = p4
mel_savestate_db Sname
event_i "i", "mel_hostsendstates_db", 0, 1 ; resend list of items
if (timeinstk() >= 3) then
outvalue "mel_state_saved", Sname
turnoff
endif
;io_sendstring("mel_state_saved", Sname)
;turnoff
endin
instr mel_loadstate_db
Sname = p4
mel_loadstate_db Sname
event_i "i", "mel_updatehost", 0, 1
if (timeinstk() >= 3) then
outvalue "mel_state_loaded", Sname
turnoff
endif
;io_sendstring("mel_state_loaded", Sname)
;turnoff
endin
instr mel_hostsendstates_db
Sjson = sprintf("{\"states\": %s}", arr_serialise(mel_liststates_db()))
;io_sendstring("mel_dbstates", Sjson)
;turnoff
if (timeinstk() >= 3) then
outvalue "mel_dbstates", Sjson
turnoff
endif
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
|