Restoring properties with DAW session
-
My current solution is to write the value to a file and read it back in to the saveInPreset=false control
Isn't that
saveInPreset=true
with extra steps?And in my scenario the lock button is necessary, or you can just set
saveInPreset=true
for the master volume, no? -
@Christoph-Hart I'll play around with it and report back :)
-
I just want to check I'm doing this the way you meant
HiseSnippet 1173.3ocsV0raabCDlqroakRa9AnmKV3Sx.tFRwooAInH1RVpUHwNBVNtEHnHfdWJsDdWxEjbkiPfOzC8deU5afeX5CPuTzitCIWockspis.5dvVb98aF9QNruTDPUJgD4U8nIoTj2WfGLgqiZGQXbTu8Pd2GuOQooRemnVSRIJEMD44sxOXD3UcUj86udYKRLgGPKDgPGKXAzWyRX5Bo824Ur33tjP5QrjRV+jc5EH3sEwhL.OqfafRIAmRFQOfXLqBF4sVmPlVHGnIZpBrokHbxfHwYbm8GyTrSholEMQCf.4DiZGwhC6OsVUHj2p8Kp7UbU9Wg2mExlIunC7PqB+BOJ2C7pbSPp4c.RdkfzpNH8H7f.IKUWnwfm6g6wgMjgDnUWFJNaQUdXEbaAXAWuUB4TZWIrXlG0eZiFa5C+YiWTqljNxeL7ensqz9iIR+WwEmzz+68mFfQTcaQRpfCKputU65FOY7XFm5OLiGnYBtuf2JSqE7lFGkh35AS8ZSHtwYzMp8wZUYC8qmupZ0wPZrAzjjiMRqCQ9bH3KN44IX8M1RYjaSSaRb7I.Io9Uy+FyppzHHOc3i.3tUfjB6RuUQk8kTHJ+HgGFSkl7VKMxD29BkdVPmVc0SsVuGQSrkQNrUSg8XCt23EkZFGHzz2vqast1407uppgCWntbvagzBTaNtHuIGqyyRNgJK2xMFB7o4Ioqc6HoAt8gRFJ383L8aRo4q6JhCMjOyuuNkFkuQZH24HDLUao12OmZOHlERkHFDjOCa6qHK3yuV3h+t9e9Rza6Y58SCCDQHKoTolYJFu8nigKYbmXph2ipNUKRgDMi6.0+mLoen78PSJu.UJN34iiiyYiSUbNArTjtXjIRXuuF9shLl1i6nclCqki58z4W.4hZ2XAQy3iNhAaIlX+.bYQygUDp.qWDuSd6w0Kd.1ktVRwY.kGcxno2sVcMv7+w3CSSSJj9GW96WNuzGmar8ytIT42pf+XMe+0MzhAPU4p60etuVlQ2bplNeHkvU.6TsqBBUVhwhgjXUgIVxibwtaNkntlGFVrydUYGJDCGrfBFz0rwLm1MLbw43PJGFrrXc6Qio5+CccIiERnEYlVUVWNx5AkcHskPBE2bUvAYItNgA7aaE4V+SrPczgvFr.T7NPtueis19JeadGkCh+EaNdMSo2Et3aVuIOCatn+MyKGxNTbVeRXHv7ts9MfRjAQsHxVhLdnoRemSw9BYd+7pZJHQWUyzN80zV6bzYllVA2+W2IhxFEU7Lizw6ft9DUXVtHLKlnme.u4kL4J.J6bSUMSNgcT8jxuz4NL0uwMN0+1BwGg6yzAQKFiUV.FgKK++.i4uU5KwcFNjFnK.3p3t+7x9vnOQ5OTjYt6aehVxfq9vv4nAvUSATH6bNMVYtishYbiacCyZSGX.kGZWbI7kqroYsWtxlSUhRHARw6CbCoLuF6ysR.LwsO9rJ7JXXs+roSXbisZfRfGF99f.S4+MvDvE6yiWBe1dI74IKgOe6R3ySWBe9tkvmmci9XdS9tYZQh63.HneG6.JOuNbBvrrrPz+RW15HJ
With this setup I have to add a new button to the UI and the user has to click it every time they adjust the knob. If I have unrelated components on the UI that require this system I'll need to have multiple lock buttons that the user has to click. Also the knob's callback will still be triggered when the preset is changed so I have to add extra checks there. Am I understanding this correctly?
-
@Christoph-Hart
I would really like this kind of feature (save in DAW, but not in preset)! I would also need a preset pre/post-save callback function for the project I am working on.
I see you have added this function (UserPresetHandler.setUseCustomUserPresetModel()) that seems to give us control over the load and save callbacks.
Could you please give us a little more details on how to correctly use this?
How can we differentiate between preset and DAW save data with this save/load callback? Would functions like updateSaveInPresetComponents() and updateConnectedComponentsFromModuleState() still work with this? -
Is it possible to add preset pre-processing for when the DAW session is restored?
That way I could do something like this
presetHandler.setPreCallback(function(presetData) { for (x in presetData.Content) { if (x.id == "knbMasterGain") x.value = knbMasterGain.getValue(); } });
-
I'm really trying to prevent giving the user the ability to distinguish between DAW restoring, initial plugin loading and user preset recalling because it creates so many branches with edge cases that are impossible to cover across all hosts.
What are you trying to achieve? If you want to lock the master gain while the user switches presets, you can easily do this with a button that the user has to press before loading the preset, but I remember we already discussed this.
-
@Christoph-Hart Yes we tried that before. But I don't want to add a special lock button for every control that the user wants to preserve with the DAW session but not with the preset, so I'm looking for an alternative. I want it to be a seamless experience for the user, requiring no additional action from them.
-
@d-healey attach a mouse listener to the user preset browser and / or preset load buttons that will deactivate the restoring of any parameter? This makes your entire UI that lock button :)
const var userPresetMouseWatcher = Engine.createBroadcaster({ "id": "Mouse Watcher", "args": ["component", "value"] }); reg ENABLE_MASTER_LOCK = false; reg LOCKED_MASTER_GAIN = 0.0; userPresetMouseWatcher.attachToComponentMouseEvents(["PresetBrowser", "NextPresetButton", "PrevPresetButton"], "Clicks Only", "activate the master gain lock once the user tries to load a preset", function(component, event) { if(event.clicked) ENABLE_MASTER_LOCK = true; }); presetHandler.setPreloadCallback(function() { if(ENABLE_MASTER_LOCK) LOCKED_MASTER_GAIN = masterKnb.getValue(); }); presetHandler.setPostloadCallback(function() { if(ENABLE_MASTER_LOCK) masterKnb.setValue(LOCKED_MASTER_GAIN); });
I just typed this out of my head so I'm sure there are some errors, but this should be the gist of it.
-
@Christoph-Hart Aha that's a clever idea. I'll try it, thanks!
-
@Christoph-Hart Yep that works, thank you!
-
-
Actually I gave in to your constant nagging (JK, I needed it myself now too) so you can use
UserPresetHandler.isInternalPresetLoad()
which should returntrue
when the DAW restores a preset (and only for the duration of the pre / post load callbacks). -
@Christoph-Hart Excellent!
-
@Christoph-Hart Finally got around to testing this.
It works in Reaper on Windows, but not on Linux. Haven't tested on MacOS, Any ideas?
This is my test snippet:
HiseSnippet 1163.3ocsV8taaaCDmxIbq1sacEn66Z4SN.YA1NoIscnHN1wdynIoFQooCnXnfQh1lHRjBjTI0sHCEC8AauJ6IX6MX6nnrkbhSWlwp9fMt++6Nd7N1WJ7oJkPhbJe73XJx4dXuwb8n1iHLNp2dHmGhYbMUxIg8kTEUeLUoQsFGSTJZ.xwYoeznoS4kQoe+0NsHgDtOMmEBchf4S2mEwz4b6274rvvtj.5wrnBZuYyd9BdaQnHAP0R3ZnXh+YjgzCIF0JgQNeQm.lVH8zDMUgbVtkHXr2HwEbq9mvTrSCoFh5HOvQV1cEgAFDa3hZOhEFzeR1qPfW5mWKVxVKdH9.V.aJ+7Zx2jJvM2hh0CmRyBuklAd0KBuZEf2bfjSAHsrERO.64KYw5bIF7bWbOyYz.BT1KBEqtnReaIbaAnAWudD4LZWIPL0hpaUq1ZtvOq9CUp.kdk1MIdj6yb6vGx3z08kTHQdohJsM.+DgGDRkUyU+bhz84bwo0AilDmgTcaQTrfCDUWIU5JFKjzgtmATmPBSn.MDp0AmBttMIL7T3nt5fDtulI3UiSi2dDMY0JuuRYW1.2pemw.lp2L8j6KHAUWcUPkxS8MfkznZPRJCCfub0BgTnz2TL6xBo29XZiiZRblBAa.m3ZWA+Pgl9Bd0TOW4xJtWUzfAyUlolJEgoE84H1b+Q9oLrJOI5TpbM3fxfpIJBMUy1ohu4N0hWj7sGwETTv6wY5WDS42z0KTVegoqNCUfp5zd5uNqm1KjEPkHFz59k3zZJJEvYyF9vyp7m6fdYOS+vD2.dDhRLUpYlDvYO54vjF6Ukx38npyzhXXnwzVQHI+WC5amNL52CaNNexzu1Toowdr2MAQM+i28wcPE78c0YyMr9tanfnY7gGCcSoQ393hrJFI3abQhKXA5Q4332ZNhxFNJe74GNuYV9aS16iscksjhKfapnSGNYB58vaVeyMdx1M13QMPLMMpffFOd6sdRisaTuffF1C4zpboOVB+9JttqXNq8HmSakn0B9JO0UKSnqMQRm2FS3JnkSsqBbRRjQiAjPUtJoCeky2bSqu5Z9D5LspOinb1vkEHeAY0qM0ncCBleHNhxgsGyW1dzPp9Fj0kbtPB0FyJohxxPVOHqCnsDRH2lIkOLIxVHLfeiTVV5WYNWOBZADffWC7ccqs9FW4as+i7A1+RZL1moz6BiqmVaxhvZy6uoVYQ1QhK5SBBfdyaqcdThzeTKhrkHgGXxzWaEbfPlUOupj7dnqJYRk9ZRqbI7VgqsGD1.KBRBI5YWKadKRl.ncblcglo2vwkdbw2p7+1t5aKDe.tOS6OZ9XrzbvHLo6yAFydgyWg6LX.0WmCvkwc+4OOOmAcjHwL56.hVxfIeX3RhGLvwmBQmyoglMPNkL6Jrz0LzlJfGkGjR72vWlv5FZmLg0mHDEQ7kh23a2vXdC0cR4.Xhm97wx3CLztSWsfw0VuFJBdN2a78Mo+2CquluMMV.a1XArYyEvlGs.1r0BXy1KfMO9SZi4kz6lnEQ1qC.i9cRW933zgSfNqztPz+.CS.lG
-
@d-healey no idea and precisely the reason why I didn't want to implement this in the first place :)
-
@Christoph-Hart :D I think I'll stick with the previous hack then
-
Turns out the hack doesn't work properly, but I found a solution to the problem I was having with
isInternalPresetLoad
.Here is the working version:
HiseSnippet 1183.3ocsVslaabCDlqr21JkzlFfb.15eDHC3XnGN1Isnvx5UpPrcDrbbKPPQ.8tTRDdWxEjbsiRfKJJxAoGk96dKxMn2f1gK2WxVN0UnY+gD37MO93vgyvgBtKQJ4BjU4imERPV20dzLlZZmoXJCMnKx5A1TlhHXX+gBhjnNlHUn1yBwRIwCYYsxyzZZUdUT72esaarOl4RxEgPmvotj8oATUtzgsdN02uO1ibLMnf1a0ZfKm0g6yi.VshcMTH18L7DxgXsZkrQVeVOOphKFovJhDYsZat2rQS4WvL5eBURO0mnWTGMBbjQbetumlwZonNSo9dCS28RD3kg44hUL4hGXe.0ilIOOm70w.N4VTLeXUZd5sxbzqdQ5Uq.8V.krJPoUMT591ibEzPUNhlO2wdf9LZLFR6EohQWToGUxtCGzfo1L.eFou.VjYQ0sqUaCG3m0+tJUDjINmw3mdB1Oh.qgiBoxIJbpy26ziMgxHa5JHvF6kRhvTP7CXlmOQTc8L0OGKbdN3j5fQowcBQ0gGDxYvhpqEitl1Bv0aBNAbUGru+ovQc0wQLWEkypFF6+tXEd8JuqRYG5Xmpei1.pbvb0j6ywdUWecPkxYjGhcbTzQNVflfWVLjbo5lhYepO4VESmG9PGprKYLjY7plEbCWLwWlF+bzXhjFRGN6Pth7BV03HV4xJNWEZ73EhoysBtebxeAv56UhOlgUYQAmRDa.GXZVkpHTrMeEr8MWAW7Blq4ntfhb1.FU8hPB6lt1gRpOzU6IrBTUEWq+UI05i7odDAhBkzetcbNEES3jdF+9y9vetK5kCz0IotA7HDkPhPQ0a.qtjygNPlqPks6Rjmo3gPyjrRRXS9uFz2j0j5O7aMKui0uzRpHginuMkQs9vae+tnB99Npj9IFe22miUT1jigpr3HbO6hhJFI3aVwEWP8TSy4wu0ZJgNYZda0e87VI6eyl8d1lp01B9EvMVzoSR6rdW6spuUymtSilOtAhpHAE.Z7jc19oM1oQ8B.MLGxwY4Ruuj86p33rl9rdD9bR6HkhyV6acThHxFoH8dSHlIgRN4dRvIQAZMFi8k4pD2TVrXy0k9xq4Snxzn9bP4hgKKv9EvpWKyn877VbHNhvfoJKFqKwmntAr93y4BH2nGUUDKgYCfcsGoMW.6s41xGFEXRDZx2LVjY8OpOWOBJA3.vq.4NN01r4U913+nbP7OGGi8oR0dPa6rbSRD1XQ+kYkgYGwuXH1yCpMus1MhfEtSaiEs4QLO8N8UFfC3hj74UQxqgtJRZl9ZnUtDdCw0lOBSl4dQ9X07iq0uQIA.JGmaFotqNbbolU7ML+uMC+1Rw6aOjpbmtXNVZAbD5z8ofiIu74Ks6MdLwUkSvUs6+SeZdlC5Hdjt02AXkfBc9rgKIifFNtDH5LFwWOAxpjdVgYcM8ZcFXDg4Eu3uguDv550VIf0SAQAXWA+0tlIL52V8EwR.NwheVYY6CzqcxFsXaWayZn.3Ydu10Uu8eDL9Zw1zXIro4RXyVKgMOdIrY6kvlcVBadxG0F8Kr2KRwCLWG.AC6EO7wxpGCCUVwUgn+AHQeh7A
-
I still seem to be having issues with this. Am I going about this the wrong way?
const uph = Engine.createUserPresetHandler(); const var Knob1 = Content.getComponent("Knob1"); reg knobValue; uph.setPreCallback(function(presetData) { if (!uph.isInternalPresetLoad()) knobValue = Knob1.getValue(); }); uph.setPostCallback(function(presetFile) { if (!uph.isInternalPresetLoad()) Knob1.setValue(knobValue); });
-
@d-healey Have you check that the functions for presetData and presetFile are doing their thing first?
I just looked at my project. I moved the function outside of the Pre/Post callback
userPresetHandler.setPostCallback(function() { setMetaData(); }); inline function setMetaData() { //do stuff here }
I wonder if I hit the same issue in the past?
-
@Dan-Korneff The functions are being triggered correctly. Inline functions are inlined when the code is compiled anyway so I don't see that making a difference here.
-
@d-healey said in Restoring properties with DAW session:
Inline functions are inlined
Haha, I tricked you with my deceiving naming! Inline functions are not inlined, they just use a better localized scope that doesn't allocate, but it's a function call never the less.