# Read_persistent with arrays



## Mike Greene (Nov 19, 2011)

I have an articulation-select menu which has varying values that the user can select. This is accomplished with the new Kontakt 5 "set_menu..." commands. It works really well. The menu updates perfectly as the user decides what entries to fill it with.

Except . . . when I save a preset with new user defined values in the menu, it doesn't give me the menu the way I left off. Instead, I get an empty menu. I can't figure out what's wrong.

Here's the init code:


```
on init
    declare %keyselect[30]
    make_persistent (%keyselect)

    declare ui_menu $art
    read_persistent_var (%keyselect)
    $count := 0
    while ($count < 30)
        add_menu_item ($art, !artname[%keyselect[$count]], %keyselect[$count])
        inc ($count)
    end while
end on
```

To troubleshoot, I put in a message("keyselect25 = ", & %keyselect[25]) command after the read_persistent. It returns zero every time, so apparently the problem is that %keyselect isn't filling itself with the saved values.

In case it matters, %keyselect fills itself in the same script (tab), although it gets those values from a separate tab using PGS commands. Here's the code for that:


```
on pgs_changed
    if pgs_key_exists (KEYSWITCH)
        %keyselect[0] := pgs_get_key_val(KEYSWITCH,0)
        %keyselect[1] := pgs_get_key_val(KEYSWITCH,1)
        %keyselect[2] := pgs_get_key_val(KEYSWITCH,2)
        etc..... 

        $count := 0
        while ($count < 30)
            if (%keyselect[$count] = 0)
                set_menu_item_visibility (get_ui_id($art),$count,0)
            else
                set_menu_item_value (get_ui_id($art),$count,%keyselect[$count])
                set_menu_item_str (get_ui_id($art),$count,!artname[%keyselect[$count]])
                set_menu_item_visibility (get_ui_id($art),$count,1)
            end if
            inc ($count)
        end while
end on
```
I don't see how my problem could be with that part of the code, though, because as I said, that parts works perfectly. It's just that %keyselect is either not saving or not reading it's saved (persistent) values.

Any ideas?


----------



## Big Bob (Nov 19, 2011)

Hi Mike,

Sadly, while there was a rumor circulating for a while that persistent string arrays were going to be added with K5, in reality they weren't. :( This of course is very unfortunate because it would have made a nice companion with the new dynamic menu stuff.

For now the only thing you can do is to use separate @ vars which of course requires more code to implement because each string var must be addressed 'by name' instead of by index. ie another big select-case construct.

Sorry,

Bob


----------



## Mike Greene (Nov 19, 2011)

Except in this case, it's not the string array I'm having problems with. It's the regular _%keyselect[30]_ array, which should (unless I have this confused) just be integer values that maintain their "persistence."

I do have a string array involved: _!artname_, and it does get used in the menus. But the values for each of the indices of this _!artname_ array never change, so I don't think that's my problem, since persistence isn't an issue there.

I'm wondering if maybe my syntax is wrong or something. Here's how I'm writing the two relevant lines:
make_persistent (%keyselect)
read_persistent_var (%keyselect)

Neither Nils' editor or ksp thinks there's an error with how I typed those, but maybe there is?


----------



## Mike Greene (Nov 19, 2011)

I think I've found a clue. I put a "message" command in the pgs callback of my main script and that message displayed when I loaded the instrument! It seems this pgs callback gets called when an instrument is loaded!

My guess is that that's why everything is zeroing out, since the PGS variables must get reset to zero when loading a saved instrument. (Those PGS variables are where _%keyselect_ gets its values.)

Interestingly, the pgs callback seems to get called when loading an instrument, but _doesn't_ seem to get called when resetting a script. (I have different messages in different parts of the script. That's how I can tell which parts get called.)

Weird.


----------



## Big Bob (Nov 19, 2011)

Sorry Mike,

Let me actually look at your code more carefully. I just assumed you were talking about persistence for string arrays :oops: 

Rejoice,

Bob


----------



## Big Bob (Nov 19, 2011)

> My guess is that that's why everything is zeroing out, since the PGS variables must get reset to zero when loading a saved instrument. (Those PGS variables are where %keyselect gets its values.)



Apparently your pgs callback fills the keyselect array with values from the pgs KEYSWITCH array, and, does so unconditionally. ie it will do that for each and every trigger of the pgs?

I don't know the mechanism for initializing the KEYSWITCH values but, it seems like the way you should do this is to create the 'equivalent' of persistent pgs values in the script that initializes and updates the KEYSWITCH values but then I probably don't have the picture quite sorted out yet. :lol: 

Rejoice,

Bob


----------



## mk282 (Nov 20, 2011)

You should be writing values _from_ %keyselect *to* KEYSWITCH PGS variable, not the other way round. Then use the PGS variable for everything in your script, instead of %keyselect. This means that %keyselect would actually save your menu ordering, and KEYSWITCH would be your working variable for any changes during the time the script has been run.

This way when you read persistent value in ICB, things won't zero out on ya. Just make sure you trigger the PGS callback AFTER reading persistent value in the ICB.




```
on pgs_changed
    if pgs_key_exists (KEYSWITCH)
        %keyselect[0] := pgs_get_key_val(KEYSWITCH,0)
        %keyselect[1] := pgs_get_key_val(KEYSWITCH,1)
        %keyselect[2] := pgs_get_key_val(KEYSWITCH,2)
        etc.....
```

Don't torture yourself! How about:



```
on pgs_changed
    if pgs_key_exists (KEYSWITCH)
        $i := 0
        while ($i < <whatever>)
            pgs_set_key_val(KEYSWITCH,$i) := %keyselect[$i]
            inc($i)
        end while
```


----------



## Big Bob (Nov 20, 2011)

Hi Mike,

re;



> but, it seems like the way you should do this is to create the 'equivalent' of *persistent pgs values *in the script that initializes and updates the KEYSWITCH values



Looks like mk282 has posted an excellent illustration of what I was suggesting (my suggestion was perhaps a little too cryptic? :lol:


----------



## Mike Greene (Nov 20, 2011)

Yeah, I think you guys have nailed it on this one. Apparently what's happening is this:

I have two script slots in this instrument. Upon loading this instrument, Kontakt first runs the ICB in slot one. Then it runs the ICB in slot two. Inside this ICB of slot 2 is where the PGS variables are created. So when Kontakt creates these PGS variables, that must trigger the _on_pgs_changed_ callback in slot 1. Since PGS aren't persistent, then their values are all zeros. And since that _on_pgs_changed_ callback in slot 1 refills my _ui_menu,_ those values all get zeroed in the process.

I think I can fix this by filling the PGS values in the slot 2 ICB with saved values from a persistent array. (pgs_set_key_val(KEYSWITCH,$i) := %keyselect[$i]) The _on_pgs_changed_ callback in slot 1 will still get triggered, but since the PGS variables are now correct (thanks to the persistent array,) it will be refilling with the correct (in theory!) values, so I should be in good shape.

Mk282, good point about taking advantage of a while loop in the arrays. I don't know how I missed that one. Well, actually I _do_ how I missed it, but we won't get into that . . . :mrgreen: 

Thank you very much for your help guys! I'll report back soon with how it all works out.


----------



## Mike Greene (Nov 20, 2011)

Yep, that did the trick. 8)


----------



## mk282 (Nov 21, 2011)

Good!


----------

