COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :
Old 08-13-2010, 02:41 AM   #1
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default 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();
       }
cc_ is offline   Reply With Quote
Old 08-16-2010, 06:41 AM   #2
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by cc_ View Post
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_ View Post
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.
Tale is offline   Reply With Quote
Old 08-17-2010, 12:42 AM   #3
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-17-2010, 02:00 AM   #4
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by cc_ View Post
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).
Tale is offline   Reply With Quote
Old 08-25-2010, 03:51 AM   #5
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-25-2010, 04:48 AM   #6
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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().
Tale is offline   Reply With Quote
Old 08-25-2010, 05:07 AM   #7
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

I see.

So where did SerializePresetsState() come from? I don't see it in the cockos latest WDL zip.
cc_ is offline   Reply With Quote
Old 08-25-2010, 05:17 AM   #8
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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().
cc_ is offline   Reply With Quote
Old 08-25-2010, 05:22 AM   #9
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

SerializePresetsState() is currently only in the "next" branch of my Git repository.
Tale is offline   Reply With Quote
Old 08-25-2010, 05:35 AM   #10
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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?
cc_ is offline   Reply With Quote
Old 08-25-2010, 05:41 AM   #11
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by cc_ View Post
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.
Tale is offline   Reply With Quote
Old 08-25-2010, 05:45 AM   #12
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-25-2010, 07:10 AM   #13
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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.
Tale is offline   Reply With Quote
Old 08-25-2010, 07:40 AM   #14
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-25-2010, 08:19 AM   #15
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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?
Tale is offline   Reply With Quote
Old 08-25-2010, 09:06 AM   #16
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by cc_ View Post
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...
Tale is offline   Reply With Quote
Old 08-25-2010, 09:40 AM   #17
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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?
cc_ is offline   Reply With Quote
Old 08-25-2010, 09:52 AM   #18
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-25-2010, 12:51 PM   #19
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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?
Tale is offline   Reply With Quote
Old 08-25-2010, 01:11 PM   #20
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-25-2010, 01:16 PM   #21
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-25-2010, 01:40 PM   #22
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-25-2010, 03:29 PM   #23
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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.
Tale is offline   Reply With Quote
Old 08-26-2010, 02:48 AM   #24
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

Quote:
Originally Posted by Tale View Post
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().
cc_ is offline   Reply With Quote
Old 08-26-2010, 05:19 AM   #25
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

I could have a go at implementing this if you like.
cc_ is offline   Reply With Quote
Old 08-26-2010, 05:29 AM   #26
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

Quote:
Originally Posted by cc_ View Post
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).
Tale is offline   Reply With Quote
Old 08-26-2010, 06:01 AM   #27
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

Interesting, I would have thought it would work if you didn't add any data.
cc_ is offline   Reply With Quote
Old 08-27-2010, 06:03 AM   #28
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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?
cc_ is offline   Reply With Quote
Old 08-27-2010, 06:49 AM   #29
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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.
Tale is offline   Reply With Quote
Old 08-27-2010, 07:55 AM   #30
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 08-27-2010, 10:10 AM   #31
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

Quote:
Originally Posted by cc_ View Post
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.
cc_ is offline   Reply With Quote
Old 08-27-2010, 01:32 PM   #32
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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 .
cc_ is offline   Reply With Quote
Old 08-28-2010, 03:36 AM   #33
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,645
Default

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.
Tale is offline   Reply With Quote
Old 08-28-2010, 06:22 AM   #34
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 11:19 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.