Skip to main content
iPlug2 provides flexible state management through parameter serialization and custom chunk-based state. Learn how to save and restore complex plugin state beyond simple parameters.

Overview

By default, iPlug2 serializes all parameters automatically. For complex state (custom data, UI settings, step sequencer patterns), override the serialization methods:
  • SerializeState() - Save state to a byte chunk
  • UnserializeState() - Restore state from a byte chunk
  • CompareState() - (Optional) Compare two states for equality

Basic Parameter Serialization

Parameters are automatically serialized when PLUG_DOES_STATE_CHUNKS is enabled in config.h:
config.h
#define PLUG_DOES_STATE_CHUNKS 1
To save only parameters, call SerializeParams() at the end of your SerializeState() method.

Custom State Example

The IPlugChunks example shows how to save custom state alongside parameters:
IPlugChunks.h
class IPlugChunks final : public Plugin
{
public:
  bool SerializeState(IByteChunk &chunk) const override;
  int UnserializeState(const IByteChunk &chunk, int startPos) override;

private:
  double mSteps[kNumSteps] = {};
};

Serializing Custom Data

IPlugChunks.cpp:36
bool IPlugChunks::SerializeState(IByteChunk &chunk) const
{
  // Serialize custom data BEFORE parameters
  for (int i = 0; i < kNumSteps; i++)
  {
    chunk.Put(&mSteps[i]);
  }
  
  // Must call SerializeParams at the end
  return SerializeParams(chunk);
}
Always call SerializeParams(chunk) at the end to save parameter values.

Deserializing Custom Data

IPlugChunks.cpp:48
int IPlugChunks::UnserializeState(const IByteChunk &chunk, int startPos)
{
  double v = 0.;
  
  // Unserialize custom data in the SAME ORDER as serialization
  for (int i = 0; i < kNumSteps; i++)
  {
    startPos = chunk.Get(&v, startPos);
    mSteps[i] = v;
  }
  
  // Update UI if it exists
#if IPLUG_EDITOR
  if(GetUI())
    UpdateUIControls();
#endif

  // Must call UnserializeParams at the end
  return UnserializeParams(chunk, startPos);
}

Syncing State with UI

When state is restored, the UI may not exist yet. Use OnUIOpen() to sync UI controls:
IPlugChunks.cpp:94
void IPlugChunks::OnUIOpen()
{
  UpdateUIControls();
}

void IPlugChunks::UpdateUIControls()
{
  auto* pMultiSlider = GetUI()->GetControlWithTag(kCtrlMultiSlider);

  for (int i = 0; i < kNumSteps; i++)
  {
    pMultiSlider->SetValue(mSteps[i], i);
  }

  GetUI()->SetAllControlsDirty();
}

UI to DSP Communication

For realtime-safe communication from UI to audio thread, use OnMessage():
IPlugChunks.cpp:112
bool IPlugChunks::OnMessage(int msgTag, int ctrlTag, int dataSize, const void* pData)
{
  if(msgTag == kMsgTagSliderChanged)
  {
    auto* pVals = reinterpret_cast<const double*>(pData);
    memcpy(mSteps, pVals, kNumSteps * sizeof(double));
    return true;
  }
  return false;
}
Send messages from UI with SendArbitraryMsgFromUI():
IPlugChunks.cpp:23
pGraphics->AttachControl(new IVMultiSliderControl<kNumSteps>(b, "", style), 
  kCtrlMultiSlider)->SetActionFunction([pGraphics](IControl* pCaller) {
    double vals[kNumSteps];
    
    for (int i = 0; i < kNumSteps; i++) {
      vals[i] = pCaller->GetValue(i);
    }
    
    pGraphics->GetDelegate()->SendArbitraryMsgFromUI(
      kMsgTagSliderChanged, kCtrlMultiSlider, sizeof(vals), &vals);
});

IByteChunk Methods

Put()

Write data to chunk
chunk.Put(&value);

Get()

Read data from chunk
pos = chunk.Get(&value, pos);

PutBytes()

Write raw bytes
chunk.PutBytes(data, size);

GetBytes()

Read raw bytes
chunk.GetBytes(data, size, pos);

Best Practices

1

Maintain Order

Always serialize and deserialize data in the exact same order
2

Version Your Format

Save a version number as the first value to support format changes:
const int kStateVersion = 1;
chunk.Put(&kStateVersion);
3

Call Base Methods

Always call SerializeParams() and UnserializeParams() to preserve parameter state
4

Update UI Safely

Check if UI exists before updating: if(GetUI())
Preset management is built on top of state chunks. When users save presets, your SerializeState() method is called automatically.