|
08-13-2010, 02:41 AM
|
#1
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
tale SerializePresets
I'm trying to figure out why you did this:
Code:
Find:
//savedOK = _this->SerializePresets(pChunk);
savedOK = _this->SerializeState(pChunk);
After, add
if (savedOK) savedOK = _this->SerializePresets(pChunk);
Find:
//pos = _this->UnserializePresets(pChunk, pos);
pos = _this->UnserializeState(pChunk, pos);
After, add:
if (pos >= 0 && pos < pChunk->Size()) pos = _this->UnserializePresets(pChunk, pos);
Find:
if (!(_this->DoesStateChunks())) {
_this->ModifyCurrentPreset();
}
replace with:
//if (!(_this->DoesStateChunks())) {
_this->ModifyCurrentPreset();
//}
The code I have been using (which seems to work fine) is a bit different, I do this instead of the regular iplug code:
Code:
savedOK = _this->SerializePresets(pChunk);
//savedOK = _this->SerializeState(pChunk);
so I don't call SerializeState at all and it seems to work. I think your code is saving one preset twice, but I could be wrong.
Also I inverted the test rather than commenting it out:
Code:
if (_this->DoesStateChunks()) {
_this->ModifyCurrentPreset();
}
|
|
|
08-16-2010, 06:41 AM
|
#2
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Quote:
Originally Posted by cc_
I'm trying to figure out why you did this:
...
so I don't call SerializeState at all and it seems to work. I think your code is saving one preset twice, but I could be wrong.
|
You are right. The "current" settings are saved, but these same settings are also stored in the currently selected preset. However, my plug-in's SerializeState() saves not just the VST parameters, but also some internal state variables.
Alternatively I guess I could (should?) have made SerializePresets() virtual, so I could override it, and make it store the internal state variables along with the presets.
Quote:
Originally Posted by cc_
Also I inverted the test rather than commenting it out:
Code:
if (_this->DoesStateChunks()) {
_this->ModifyCurrentPreset();
}
|
If you do some custom settings, and then select another preset, then your custom settings should be saved before switching to the other preset. I don't think this should depend on whether or not you are using state chunks.
|
|
|
08-17-2010, 12:42 AM
|
#3
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
The way I did it was to override SerializeState (already virtual I think), the code is in my version of the example too, to save the scribble strip state:
Code:
bool PlugExample::SerializeState(ByteChunk* pChunk)
{
IMutexLock lock(this);
if ( ScribbleStrip == NULL ) {
if (pChunk->PutStr("default") <= 0)
return false;
}
else {
if (pChunk->PutStr(ScribbleStrip->GetText()) <= 0)
return false;
}
return SerializeParams(pChunk);
}
int PlugExample::UnserializeState(ByteChunk* pChunk, int startPos)
{
IMutexLock lock(this);
WDL_String MyStr("xxx");
startPos = pChunk->GetStr(&MyStr, startPos);
char *s = MyStr.Get();
if (ScribbleStrip) ScribbleStrip->SetTextFromPlug( MyStr.Get() );
return UnserializeParams(pChunk, startPos);
}
Quote:
If you do some custom settings, and then select another preset, then your custom settings should be saved before switching to the other preset. I don't think this should depend on whether or not you are using state chunks.
|
My brain seems to be resisting remembering this preset stuff, but I think I was assuming that when you are not using state chunks all the information about the preset is managed by the host, so no need to call ModifyCurrentPreset. I could very easily be very wrong though.
|
|
|
08-17-2010, 02:00 AM
|
#4
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Quote:
Originally Posted by cc_
My brain seems to be resisting remembering this preset stuff, but I think I was assuming that when you are not using state chunks all the information about the preset is managed by the host, so no need to call ModifyCurrentPreset. I could very easily be very wrong though.
|
When I disable PLUG_DOES_STATE_CHUNKS and I comment out the _this->ModifyCurrentPreset(), then changes aren't saved when switching presets (in REAPER on Windows).
|
|
|
08-25-2010, 03:51 AM
|
#5
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Ah yes, I think you are right.
I have switched to using your save chunks mods instead of mine. It seems to work, I have implemented SerializeState and UnserializeState to save/restore my stuff and then call (Un)SerializeParams.
But I'm not sure what (if anything) I should be doing with SerializePresetsState and UnserializePresetsState.
|
|
|
08-25-2010, 04:48 AM
|
#6
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
SerializeState() saves one preset, the current preset. SerializePresetsState() saves all presets. The host could call SerializeState() when e.g. it saves a patch to an .FXP file, and SerializePresetsState() to save a bank to a .FXB file.
By default SerializeState() simply calls SerializeParams(), which makes perfect sense. It would even more sense if the default SerializePresetsState() would call SerializePresets(). Unfortunately it doesn't, but you can easily override SerializePresetsState() and make it call SerializePresets().
|
|
|
08-25-2010, 05:07 AM
|
#7
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
I see.
So where did SerializePresetsState() come from? I don't see it in the cockos latest WDL zip.
|
|
|
08-25-2010, 05:17 AM
|
#8
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
I'm very confused now... your IPlugBase::RestorePreset is calling SerializeParams, shouldn't it be calling SerializeState instead? Otherwise only the params will get restored?
Edit: also in MakeDefaultPreset().
|
|
|
08-25-2010, 05:22 AM
|
#9
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
SerializePresetsState() is currently only in the "next" branch of my Git repository.
|
|
|
08-25-2010, 05:35 AM
|
#10
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Ok, maybe I have totally lost the plot here, but I'm not sure why you introduced that new function.
I used the existing SerializePresets() function in IPlugVST - in fact the line was there already, I just uncommented it.
The other thing I did was went through and changed all the SerializeParams to SerializeState, so they all go through that function (which you can override).
That seemed to work. Did I miss something?
|
|
|
08-25-2010, 05:41 AM
|
#11
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Quote:
Originally Posted by cc_
I'm very confused now... your IPlugBase::RestorePreset is calling SerializeParams, shouldn't it be calling SerializeState instead? Otherwise only the params will get restored?
Edit: also in MakeDefaultPreset().
|
Yeah, that can't be right. I (or you?) will have to take another look at this.
|
|
|
08-25-2010, 05:45 AM
|
#12
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
I found my post on this a while back
http://forum.cockos.com/showpost.php...9&postcount=14
I still think that is right. If you want to try it it is in my WDL.git. Unfortunately I fucked up the check in and it is 3 different commits. I know I should be able to mush them into one, but at the time I was too scared of breaking something.
Code:
713ce7f GetChunk / SetChunk more missing changes
fe6036c GetChunk / SetChunk - missed a change
adaf6a3 GetChunk / SetChunk with VST presets working.
|
|
|
08-25-2010, 07:10 AM
|
#13
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Your changes seem very promising. I would make (Un)SerializeParams() virtual, so you can override it on a per plug-in basis. However, your version has the same downside as mine; it may not be compatible with existing projects.
BTW, I see your adaf6a3 commit contains changes to the default example. This is not a good idea IMHO, because if I would change the example with every feature I add, the example would quickly become way too complex.
|
|
|
08-25-2010, 07:40 AM
|
#14
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
I take your point about the example.
I think it will be pretty compatible. For the non-preset version it does the same thing (when people loading the plugin state). For the preset version (switching between presets) it doesn't do the same thing, but it was broken before, so I don't think it matters that people can't load the broken presets in their old projects.
Edit: also this only affects people who are using chunks and multiple presets - if they are doing that won't they have noticed it doesn't work, come here and be using my code from that thread anyway?
Last edited by cc_; 08-25-2010 at 07:48 AM.
|
|
|
08-25-2010, 08:19 AM
|
#15
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Yes, perhaps we should give up on backward compatibility. After all, if SerializeParams() is virtual, one could just as easily override it and let it call SerializeState() to fix a project that depends on SerializeState() being called for banks, right?
|
|
|
08-25-2010, 09:06 AM
|
#16
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Quote:
Originally Posted by cc_
If you want to try it it is in my WDL.git. Unfortunately I fucked up the check in and it is 3 different commits. I know I should be able to mush them into one, but at the time I was too scared of breaking something.
Code:
713ce7f GetChunk / SetChunk more missing changes
fe6036c GetChunk / SetChunk - missed a change
adaf6a3 GetChunk / SetChunk with VST presets working.
|
I have just temporarily undone my changes, and then I have committed your changes (using git cheery-pick, hoping this is the right way), but now my test project crashes. Grrr...
|
|
|
08-25-2010, 09:40 AM
|
#17
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Because it has the current state saved before all the presets in the bank? I guess that would happen!
I think you will be the only one with this problem though, maybe the fix should be specific to this one plugin?
|
|
|
08-25-2010, 09:52 AM
|
#18
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Actually, maybe you could stop it crashing by adding a check to see if the preset name string looks sensible, and if not refuse to read the bank. That might not be a thing to have in there anyway.
|
|
|
08-25-2010, 12:51 PM
|
#19
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
It could well just be this one project, although I think it does work with the original Cokcos WDL code. Still, I don't understand... Shouldn't SerializeState() be able to save any data whatever, as long as you provide an UnserializeState() that reads back the same data?
|
|
|
08-25-2010, 01:11 PM
|
#20
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Yes, SerializeState can save anything. The problem for you is in UnserializePresets() - that expects each bank to be a series of presets and each preset is a name followed by a bool flag (for initialized) followed by the SerializeState data.
The banks you have in your current project start with the current plugin state's SerializeState data (without a name) followed by the presets in the proper format. So when they get read they will almost certainly break as UnserializePresets() tries to treat the first part of the SerializeState data as a WDL string.
Last edited by cc_; 08-25-2010 at 01:20 PM.
|
|
|
08-25-2010, 01:16 PM
|
#21
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
BTW I didn't really write any of this code, it was mostly there commented out, with just a few steps needed to make it all work.
It seems like a sensible way to do it all to me though.
|
|
|
08-25-2010, 01:40 PM
|
#22
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
And just before I go... I think the best thing to do would be for you to just add #ifdefed code into SerializePresets and UnserializePresets that does a SerializeState or UnserializeState before doing the presets for real. Then next plugin you can just turn it off.
|
|
|
08-25-2010, 03:29 PM
|
#23
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Thanks for explaining. However, that was not it (storing data in any order you want works just fine). The problem was that I called GetGUI()->GetControl() from within SerializeState() at a moment the GUI wasn't available yet. I can easily fix this by checking GetGUI(). However, I have to think a little harder to see if this could cause any other issues.
But now I have stumbled upon a new problem: I use MakePresetFromNamedParams(), which doesn't work anymore (as also explained in your comments). Oh well... I will leave it for a couple of days; perhaps I can come up with another (better?) solution then.
|
|
|
08-26-2010, 02:48 AM
|
#24
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Quote:
Originally Posted by Tale
Thanks for explaining. However, that was not it (storing data in any order you want works just fine). The problem was that I called GetGUI()->GetControl() from within SerializeState() at a moment the GUI wasn't available yet. I can easily fix this by checking GetGUI(). However, I have to think a little harder to see if this could cause any other issues.
|
Ah, that's good. I had that problem in the Example I did, I ended up with this (ScribbleStrip is an editable text control which is the only non-parameter data that was being put in the state):
Code:
bool PlugExample::SerializeState(ByteChunk* pChunk)
{
IMutexLock lock(this);
if ( ScribbleStrip == NULL ) {
if (pChunk->PutStr("default") <= 0)
return false;
}
else {
if (pChunk->PutStr(ScribbleStrip->GetText()) <= 0)
return false;
}
return SerializeParams(pChunk);
}
Quote:
But now I have stumbled upon a new problem: I use MakePresetFromNamedParams(), which doesn't work anymore
|
Well, it works as well as it used to: if you are using chunks, not at all
I didn't implement it because I'm not using it and so wouldn't test it. But I think the answer is pretty simple, just rename that function to MakePresetParamsFromNamedParams(), then add a new virtual function called MakePresetFromNamedParams() that just calls MakePresetParamsFromNamedParams() by default. Then overide MakePresetFromNamedParams() in your plugin to do whatever you need before calling MakePresetParamsFromNamedParams().
|
|
|
08-26-2010, 05:19 AM
|
#25
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
I could have a go at implementing this if you like.
|
|
|
08-26-2010, 05:29 AM
|
#26
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
Quote:
Originally Posted by cc_
Well, it works as well as it used to: if you are using chunks, not at all
|
Not exactly... With the original WDL implementation you can actually use MakePresetFromNamedParams(), as long as you don't add extra data within each preset. You might want to do this if you are using state chunks to save some "global" setting (e.g. GUI state).
|
|
|
08-26-2010, 06:01 AM
|
#27
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Interesting, I would have thought it would work if you didn't add any data.
|
|
|
08-27-2010, 06:03 AM
|
#28
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
I just switched from the 8da3756 commit version back to my version and opening projects that had been saved with 8da3756 caused reaper to crash like this:
Code:
0x18940b72 WDL_HeapBuf::Resize(int, bool) + 458 (heapbuf.h:245)
0x18940f02 WDL_TypedBuf<unsigned char>::Resize(int, bool) + 44 (heapbuf.h:294)
0x18940f56 int ByteChunk::Put<int>(int const*) + 56
0x18940fbe ByteChunk::PutStr(char const*) + 62 (Containers.h:194)
0x1893e636 Indus::SerializeState(ByteChunk*) + 188 (Indus.cpp:228)
0x1897e69e IPlugBase::RestorePreset(int) + 158
0x1897e83a IPlugBase::UnserializePresets(ByteChunk*, int) + 326
0x18982b0f IPlugVST::VSTDispatcher(AEffect*, int, int, int, void*, float) + 2079
I added this hacky code into UnserializePresets:
Code:
char *t = name.Get();
for (int j=0; ; j++) {
if (t[j]='\0') break;
if (j > MAX_PRESET_NAME_LEN) return 0;
}
Which got rid of the crashes, I could then resave the projects and then take the hacky code out. And all is well again.
Or maybe we could keep some check like that in there anyway?
|
|
|
08-27-2010, 06:49 AM
|
#29
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
If would take the "hack" code out again. I would however double-check whether all the plug-in settings in your projects are still what you expect them to be.
|
|
|
08-27-2010, 07:55 AM
|
#30
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
The presets are toast, as they have been saved in the project without the extra data my plug needs. That's OK though, luckily it's only me testing at the moment.
|
|
|
08-27-2010, 10:10 AM
|
#31
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Quote:
Originally Posted by cc_
But I think the answer is pretty simple, just rename that function to MakePresetParamsFromNamedParams(), then add a new virtual function called MakePresetFromNamedParams() that just calls MakePresetParamsFromNamedParams() by default. Then overide MakePresetFromNamedParams() in your plugin to do whatever you need before calling MakePresetParamsFromNamedParams().
|
Who is this idiot?
I took a look and it is nowhere near simple
Hmm... think again.
|
|
|
08-27-2010, 01:32 PM
|
#32
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
OK, I got MakePresetFromNamedParams() working with chunks, and updated my git.
There's now a function you can overide to do whatever extra processing you need before the rest of the args are used for the parameters, the default one in IPlugBase looks like this:
Code:
virtual void MakePresetStateFromNamedParams(ByteChunk *pChunk, int nParamsNamed, va_list vp) {
MakePresetParamsFromNamedParams(pChunk, nParamsNamed, vp);
}
There's also an example of using it in IPlug/Example/chunks .
|
|
|
08-28-2010, 03:36 AM
|
#33
|
Human being with feelings
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
|
I like the way the new MakePreset*() look in your example. However, I have managed to fix my original changes with very little effort: I have just made SerializeParams() and UserializeParams() virtual, and I have added a MakePresetFromChunk(). So now I can:
a) Save a customized chunk of data (e.g. a hidden parameter, or an unsupported data type) in each preset.
b) Save a customized chunk of data (e.g. a global setting like a GUI state variable) along with all presets (or along with one patch).
MakePresetFromChunk() is pretty ugly to use, but you only need it if you override SerializeParams(). I have been thinking of adding a MakePresetFromFormat(name, "%d%f%s%f%f", ...), so you can do something like:
Code:
#define PRESET_FORMAT "%d%f%s%d"
MakePresetFromFormat("Foo", PRESET_FORMAT, 5, -6.0, "bar.wav", true);
This is a lot prettier (but still not as pretty as cc_'s MakePreset stuff). Then again, if you define a helper function in your plug-in that creates a preset chunk for you, it will not only look pretty but it will also be type safe.
|
|
|
08-28-2010, 06:22 AM
|
#34
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
I guess the rational behind SerializeState being virtual and SerializeParams not is that SerializeParams' job is to serialize the parameters, and there's no need to ever change how that is done. Of course changing how any state outside the params is handled is something you need to change per plugin, so that is handled in a virtual function SerializeState. This isn't my idea, this is how the original IPlug is set up.
It would be nice to have these things type safe. I know gcc has some extensions that can allow type checking printf like format strings (with some __attribute__ type thing), but I'm not sure about MS compilers.
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 11:19 AM.
|