# AudioProcessorValueTreeState & UndoManager usage

**URL:** <https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179>\
**Category:** Audio Plugins\
**Created:** [December 9, 2015, 1:23pm UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179 "2015-12-09T13:23:39Z")\
**Posts on this page:** 12\
**Page:** 2

<div class="post-metadata">

**Author:** ![tadnicol](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/tadnicol/32/5141_2.png) [@tadnicol](https://forum.juce.com/u/tadnicol)\
**Post date:** [March 14, 2018, 5:09pm UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/21 "2018-03-14T17:09:41Z")

</div>

I’m a bit confused, in the description it says that `AudioProcessorUndoAttachment` is not intended for `AudioProcessorValueTreeState` based projects, but you’re saying that it should work fine?

---

<div class="post-metadata">

**Author:** ![ttg](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/ttg/32/14456_2.png) [@ttg](https://forum.juce.com/u/ttg)\
**Post date:** [March 15, 2018, 6:06am UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/22 "2018-03-15T06:06:16Z")

</div>

You’re right. @yairadix should maybe edit this comment. it was very early before we had a product with AudioProcessorValueTreeState released.

TL;DR:  
**The implantation on the gist is agnostic to your parameter system. we use it on older products and newer with great success.**

Few caveats to remember:

- it based on [AudioProcessorListener](https://juce.com/doc/classAudioProcessorListener). I’m not sure about future changes as seen [here](https://forum.juce.com/t/we-are-removing-audioprocessor-based-parameter-management/26032/22) . but it simply keeps track on any parameter changes within the plug-in (not from the host, which is a good thing).

- you should use begin/end gestures properly for sliders to get a proper behavior. (same goes with AudioProcessorValueTree from my experience).

- A/B switch or single transaction for entire states aren’t being registered that way.

---

<div class="post-metadata">

**Author:** ![yairadix](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/yairadix/32/1114_2.png) [@yairadix](https://forum.juce.com/u/yairadix)\
**Post date:** [March 15, 2018, 8:59am UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/23 "2018-03-15T08:59:26Z")

</div>

I wrote that description naively assuming that `AudioProcessorValueTreeState`'s own undo attachment should work fine. Nowadays, knowing that it doesn’t work well I recommend `AudioProcessorUndoAttachment` everywhere.

---

<div class="post-metadata">

**Author:** ![tadnicol](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/tadnicol/32/5141_2.png) [@tadnicol](https://forum.juce.com/u/tadnicol)\
**Post date:** [March 22, 2018, 6:29pm UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/24 "2018-03-22T18:29:46Z")

</div>

It’s working great so far with my `AudioProcessorValueTreeState` setup!! Bunches and bunches of thanks Yair! 🙂

---

<div class="post-metadata">

**Author:** ![t0m](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/t0m/32/16413_2.png) [@t0m](https://forum.juce.com/u/t0m)\
**Post date:** [May 9, 2018, 6:44am UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/25 "2018-05-09T06:44:38Z")

</div>

[https://github.com/WeAreROLI/JUCE/commit/2e51654958df26d9c374e961758180cc842e0dfa](https://github.com/WeAreROLI/JUCE/commit/2e51654958df26d9c374e961758180cc842e0dfa)

This commit should address the issues using an UndoManager with an AudioProcessorValueTreeState.

- An undoable action is no longer pushed onto the stack when the plug-in is loaded
- Redoing actions works correctly
- New transactions are started when you interact with an attachment

Since this alters the behaviour of the UndoManager this is technically a _breaking change_, but I doubt anyone was relying upon the old way of doing things.

---

<div class="post-metadata">

**Author:** ![lalala](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/lalala/32/8577_2.png) [@lalala](https://forum.juce.com/u/lalala)\
**Post date:** [May 9, 2018, 8:19am UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/26 "2018-05-09T08:19:15Z")

</div>

thanks tom! everything works just fine!

---

<div class="post-metadata">

**Author:** ![erteash](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@erteash](https://forum.juce.com/u/erteash)\
**Post date:** [June 15, 2018, 1:54am UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/27 "2018-06-15T01:54:45Z")

</div>

HI.  
Working with undomanager and valueTreeState (latest version), i have a randomiser function that changes the values of multiple parameters (notifying host). Undo manager undos all the changes made with just one undo() which is convenient. I thought it would undo them one by one, now I am curious how does it work since im not doing any perform() or beginNewTransaction()?

---

<div class="post-metadata">

**Author:** ![lalala](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/lalala/32/8577_2.png) [@lalala](https://forum.juce.com/u/lalala)\
**Post date:** [June 15, 2018, 6:01am UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/28 "2018-06-15T06:01:15Z")

</div>

> [@erteash](#):
>
> I thought it would undo them one by one, now I am curious how does it work since im not doing any perform() or beginNewTransaction()?

I dont expect it to work correctly if you don’t call beginNewTransaction() when the randomizer button is clicked.

it is probably undoing all the changes you made since the last beginNewTransaction() (so since you previously interact with a slider or something?). also, if you don’t call beginNewTransaction, then successive clicks on your randomiser button will get grouped together no?

---

<div class="post-metadata">

**Author:** ![erteash](https://avatars.discourse-cdn.com/v4/letter/e/53a042/32.png) [@erteash](https://forum.juce.com/u/erteash)\
**Post date:** [June 15, 2018, 3:41pm UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/29 "2018-06-15T15:41:40Z")

</div>

Yes you’re right. All of them gets into one group and i can call beginNewTransaction() after each randomize action to separate them. So only changing sliders that are attached will create a single transaction, and if we want to call setValueNotifyingHost() ourselves we should call beginNewTransaction() after that. Got it.

---

<div class="post-metadata">

**Author:** ![lalala](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/lalala/32/8577_2.png) [@lalala](https://forum.juce.com/u/lalala)\
**Post date:** [June 15, 2018, 3:57pm UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/30 "2018-06-15T15:57:19Z")

</div>

> [@erteash](#):
>
> i can call beginNewTransaction() after each randomize action to separate them

no, you have to call beginNewTransaction() _before_ the action, not after.

```
void buttonClicked (Button*)
{
    beginNewTransaction();
    setValueNotifyingHost()
}

```

---

<div class="post-metadata">

**Author:** ![khiner](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/khiner/32/4431_2.png) [@khiner](https://forum.juce.com/u/khiner)\
**Post date:** [June 23, 2018, 7:04pm UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/31 "2018-06-23T19:04:04Z")

</div>

Thanks for this! I noticed this introduced a regression where initializing an AudioProcessorValueTreeState with a null UndoManager will throw assertion failures due to the lack of a null check around the undoManager here [https://github.com/WeAreROLI/JUCE/commit/2e51654958df26d9c374e961758180cc842e0dfa#diff-1ec75d23db30b69cffab9854fa6697f4R127](https://github.com/WeAreROLI/JUCE/commit/2e51654958df26d9c374e961758180cc842e0dfa#diff-1ec75d23db30b69cffab9854fa6697f4R127)

EDIT: Hrm, I’m not sure what the right behavior is or if I’m missing something obvious, but I keep hitting this assertion error whenever I change any param with `param.setValue(newValue)`. The AudioProcessorValueTreeState is being initialized with a a non-null AudioProcessor and UndoManager. Having trouble getting to the bottom of this one.

> <https://github.com/WeAreROLI/JUCE/blob/master/modules/juce_data_structures/values/juce_ValueTree.cpp#L737>

---

<div class="post-metadata">

**Author:** ![khiner](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/khiner/32/4431_2.png) [@khiner](https://forum.juce.com/u/khiner)\
**Post date:** [June 24, 2018, 6:48pm UTC](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179/32 "2018-06-24T18:48:59Z")

</div>

It turns out I was missing this step of the AudioProcessorValueTreeState setup:

`state.state = ValueTree(Identifier("My-Identifier"));`

@t0m before your commit, I would get no assertion errors at all in my project because the `state.isValid()` check in `copyValueToValueTree()` was always returning `false`, and was thus never descending into the `state.setPropertyExcludingListener` call. With your changes, it _does_ make the `setProperty...` call even if the `state` is invalid (initialized with only the default constructor and given no explicit identifier).

Basically, with the new changes, if someone (a newb like me) is just starting a project and throws a default `AudioProcessorValueTreeState` constructor on their `AudioProcessor`, it will throw errors, whereas before the behavior was, “ok, you’ve done that. I won’t complain but I also won’t be doing anything useful.” Now, in that scenario we get obscure-looking errors. I’ll leave it to the team to decide if this is desired, but I would suggest that if this is an undesirable state for an `AudioProcessorValueTreeState` to be in, that you make it harder, or even impossible, to get into this state by, say, _requiring_ an identifier and initializing the internal `ValueTree state` in the constructor or something like that. Barring this, if you’d rather allow the bad state but “fail-fast” with an assert error, I would suggest a helpful warning message that mentions explicitly initializing the internal `ValueTree state`.

Again, thanks for addressing these issues!

[Previous page](https://forum.juce.com/t/audioprocessorvaluetreestate-undomanager-usage/16179.md?page=1)
