My effect plugin is implementing sequence data to save and retrieve a string just like the PathMaster example. In fact, the code is pretty much cut and paste from that example. Everything works fine for saving and opening a file but when copying and pasting the effect it seems that I am getting corrupt data for the flattened sequence data. I see that AE is making the following calls in order:
PF_Cmd_SEQUENCE_FLATTEN
PF_Cmd_SEQUENCE_RESETUP
PF_Cmd_SEQUENCE_RESETUP
PF_Cmd_SEQUENCE_RESETUP
It is on the third PF_Cmd_SEQUENCE_RESETUP that the sequence_data is not correct. I have seen similar posts to this issue however it has never been answered.
Any help would be appreciated.
i don't know what you're doing wrong, so let's just make sure we know what's happening in each step.
when you hit copy AE asks you to flatten your data, so it can be moved.
after the flattening is done, it asks you to unflatten your data for the existing instance so it can be used.
it asks for you to unflatten again, but this time for the copy held in the clipboard.
for that copy, you're requested to allocate a new handle for your sequence data, as the two instances (the one on the layer and the one on the clipboard) don't share the same sequence_data handle.
i think that you get the third resetup call after you paste the instance in the clipboard, but i'm not sure about that.
in any case, if you didn't create a new sequence_data handle for the new instance, then you'll either get an invalid handle, or a handle that this new instance doesn't own.
crash, burn, screams, horror.
is that the case? or are you allocating new handles during PF_Cmd_SEQUENCE_RESETUP?
Following is my code. It is for the most part a cut and paste of the PathMaster example. Strange thing is it all works out fine when opening from a saved file. Just when copying and pasting the effect. Is there something missing from here that may be creating an invalid handle?
static PF_Err
SequenceFlatten(
PF_InData *in_data,
PF_OutData *out_data)
{
PF_Err err = PF_Err_NONE;
AEGP_SuiteHandler suites(in_data->pica_basicP);
// Make a flat copy of whatever is in the unflat seq data handed to us.
// Do NOT delete the unflat one!
if(in_data->sequence_data)
{
Unflat_Seq_Data* unflat_seq_dataP = static_cast<Unflat_Seq_Data*>(suites.HandleSuite1()->host_lock_handle (in_data->sequence_data));
if(unflat_seq_dataP)
{
PF_Handle flat_seq_dataH = suites.HandleSuite1()->host_new_handle(sizeof(Flat_Seq_Data));
if(flat_seq_dataH)
{
Flat_Seq_Data* flat_seq_dataP = static_cast<Flat_Seq_Data*>(suites.HandleSuite1()->host_lock_handle(f lat_seq_dataH));
if(flat_seq_dataP)
{
PF_STRCPY(flat_seq_dataP->prefix, unflat_seq_dataP->prefix);
out_data->sequence_data = flat_seq_dataH;
suites.HandleSuite1()->host_unlock_handle(flat_seq_dataH);
}
else
err = PF_Err_INTERNAL_STRUCT_DAMAGED;
}
else
err = PF_Err_OUT_OF_MEMORY;
}
else
err = PF_Err_INTERNAL_STRUCT_DAMAGED;
}
else
err = PF_Err_INTERNAL_STRUCT_DAMAGED;
return err;
}
static PF_Err
SequenceResetup (
PF_InData *in_data,
PF_OutData *out_data)
{
PF_Err err = PF_Err_NONE;
AEGP_SuiteHandler suites(in_data->pica_basicP);
if(in_data->sequence_data)
{
Flat_Seq_Data* flatP = static_cast<Flat_Seq_Data*>(suites.HandleSuite1()->host_lock_handle(i n_data->sequence_data));
if(flatP)
{
PF_Handle unflat_seq_dataH = suites.HandleSuite1()->host_new_handle(sizeof(Unflat_Seq_Data));
if(unflat_seq_dataH)
{
Unflat_Seq_Data* unflatP = static_cast<Unflat_Seq_Data*>(suites.HandleSuite1()->host_lock_handle (unflat_seq_dataH));
if(unflatP)
{
A_short lengthS = (A_short)strlen(flatP->prefix);
// clamp it to the max flat length
if((lengthS+1) > AEGP_MAX_LAYER_NAME_SIZE) lengthS = AEGP_MAX_LAYER_NAME_SIZE;
PF_Handle unflat_charsH = suites.HandleSuite1()->host_new_handle(lengthS);
if(unflat_charsH)
{
unflatP->prefix = static_cast<A_char*>(suites.HandleSuite1()->host_lock_handle(unflat_c harsH));
if(unflatP->prefix)
{
PF_STRCPY(unflatP->prefix, flatP->prefix);
// suites.ANSICallbacksSuite1()->strcpy(unflatP->prefix, flatP->prefix);
// if it all went well, set the sequence data to our new, inflated seq data.
out_data->sequence_data = unflat_seq_dataH;
}
}
else
err = PF_Err_INTERNAL_STRUCT_DAMAGED;
}
else
err = PF_Err_INTERNAL_STRUCT_DAMAGED;
}
else
= PF_Err_INTERNAL_STRUCT_DAMAGED;
}
else
err = PF_Err_INTERNAL_STRUCT_DAMAGED;
}
else
err = PF_Err_INTERNAL_STRUCT_DAMAGED;
return err;
}
hmmm. it seems you're allocating new data on each round.
i'm not sure about that, but shouldn't you release/dispose of the flat handle after successfully unflattening it?
anyways:
1. can you tell which instance gets the last call? (the original or the copy)
2. keep track of the memory address of the sequence_data you provide at the end of the flatten call.
i want to see if the corrupt handle is a random address or the original address corrupted.
Hey,
if(in_data->sequence_data)
{
Flat_Seq_Data* flatP = static_cast<Flat_Seq_Data*>(suites.HandleSuite1()->host_lock_handle(i n_data->sequence_data));
if(flatP)
{
PF_Handle unflat_seq_dataH = suites.HandleSuite1()->host_new_handle(sizeof(Unflat_Seq_Data));
are you sure that it is always flat? sequence_data may also be unflat during resetup. The sdk guide recommends to use a flag at the same offset.
see "FLATTENED AND UNFLATTENED SEQUENCE DATA" section!
also a tip: create a class to lock handles using smart pointers with a custom deleter ![]()
greets
I checked the memory addresses for the flattened data going into PF_Cmd_SEQUENCE_RESETUP. All 3 addresses were different handles. The second RESETUP's handle was the same as that when PF_Cmd_SEQUENCE_FLATTEN was called. One is for the existing instance, one is for the clipboard, and another for the new instance. That sounds like the way it should be right? How can I tell if the instance is the existing one or is a new instance? Would effectRefH be the way to find that?
I added a flattened flag to the sequence data and set it during PF_Cmd_SEQUENCE_FLATTEN and made sure to check it during PF_Cmd_SEQUENCE_RESETUP. No change. It looks that only flattened data gets sent to PF_Cmd_SEQUENCE_RESETUP. At least for this particular issue however, that is probably a good tip to keep.
I figured out what the issue was. My data structure was not ordered correctly. The sequence data should be structure so that your unflatten/flattened flag come before any data that needs flattening like pointers so that when RESETUP gets called it can cast correctly and can properly detect if the sequence data is flat or not. Previously my data structure was as follows:
typedef struct {
A_char prefix[255];
A_Boolean flat;
} Flat_Seq_Data;
typedef struct {
A_char* prefix;
A_Boolean flat;
} Unflat_Seq_Data;
And it should be like this:
typedef struct {
A_Boolean flat;
A_char prefix[255];
} Flat_Seq_Data;
typedef struct {
A_Boolean flat;
A_char* prefix;
} Unflat_Seq_Data;
Which makes me wonder if unflat data does get passed into RESETUP should an error be returned or simply do nothing?
@sharchar
hey, well happy to tag along ![]()
@squirrel
in the case of resetup with unflat data - i just delete an old handle and create a new one, saving/restoring the necessary data accordingly.
Cannot recall now if necessary though - try it if you have problems when sequence data is not changed.
greets
North America
Europe, Middle East and Africa
Asia Pacific
Copyright © 2012 Adobe Systems Incorporated. All rights reserved.
Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy (updated 07-14-2009).