Forum
    • Categories
    • Register
    • Login

    Using custom preset system - as in the actual presets themselves, not a browser

    Scheduled Pinned Locked Moved General Questions
    23 Posts 6 Posters 191 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ustkU
      ustk @DanH
      last edited by

      @DanH Oh in fact you don't even need to create a JSON file, all can be kept internally in a variable since the tag list is gathered at init...

      Hise made me an F5 dude, any other app just suffers...

      1 Reply Last reply Reply Quote 0
      • OrvillainO
        Orvillain
        last edited by Orvillain

        We're covering a lot of this in this thread:
        https://forum.hise.audio/topic/13701/custom-browser-custom-preset-file-format/29

        Basically, you've got this:

        namespace PluginUserPresetHandling {
        
            const UserPresetHandler = Engine.createUserPresetHandler();
        
            inline function onPresetSave() // this is your main preset save method
            {
                Console.print("onPresetSave triggered");
            }
        
            inline function onPresetLoad(obj) // this is your main preset load method
            {
                Console.print("onPresetLoad triggered");
            }
        
            inline function preLoadCallback() // things you want to happen before loading a preset happen here - looking for samples, looking for graphical assets, etc.
            {
                Console.print("preLoadCallback triggered");
            }
        
            inline function postLoadCallback() // things you want to happen after loading a preset happen here - updating preset name labels in your UI, triggering other UI updates, etc.
            {
                Console.print("postLoadCallback triggered");
            }
        
            inline function postSaveCallback() // things you want to happen after saving a preset happen here - copying samples to an external location, removing any dirty flags you might've setup in the UI layer, etc.
            {
                Console.print("postSaveCallback triggered");
            }
        
        
            inline function init() {
                UserPresetHandler.setUseCustomUserPresetModel(onPresetLoad, onPresetSave, false); // this line is essential
                UserPresetHandler.setPreCallback(preLoadCallback);
                UserPresetHandler.setPostCallback(postLoadCallback);
                UserPresetHandler.setPostSaveCallback(postSaveCallback);
            }
        }
        
        

        You can achieve a hell of a lot with this, without discarding the HISE preset system.

        For example, here is my onPresetSave method in my current project:

            inline function onPresetSave() {
                Console.print("onPresetSave triggered");
                PluginSharedHelpers.forceAllOuterSlotsEnabled();
        
                if (PluginSharedData.presetMode == "Global") {
                    return saveGlobalPreset();
                }
                if (PluginSharedData.presetMode == "FXChain") {
                    return saveFXChain();
                }
            }
        

        In this way, I'm able to gate different save functions based on a master type, which means I can either write the HISE .preset file, or I can write a custom file using my own data model.

        My load one is this:
        inline function onPresetLoad(obj) {
        Console.print("onPresetLoad triggered");
        PluginSharedData.isRestoringPreset = true;

            if (PluginSharedData.presetMode == "Global") {
                loadGlobalPreset(obj);
            }
            if (PluginSharedData.presetMode == "FXChain") {
                loadFXChain(obj);
            }
        
            PluginSharedData.isRestoringPreset = false;
        }
        

        The loadFXchain method is this:

        inline function loadFXChain(obj) {
                if (!isDefined(obj)) return;
        
                Console.print("we are now attempting to load an fx chain");
                PluginSharedHelpers.forceAllOuterSlotsEnabled();
        
                local fxSelections = obj.fxSelections;
                local fxChainOrder = obj.fxChainOrder;
                local params = obj.parameters;
        
                // Set effect menus by stable id (this loads the networks)
                if (isDefined(fxSelections)) {
                    for (i = 0; i < fxSelections.length; i++) {
                        local sel = fxSelections[i];
                        if (!isDefined(sel) || !isDefined(sel.id)) continue;
        
                        local idName = (isDefined(sel.idName) && sel.idName != "") ? sel.idName : "empty";
                        UIEffectDropDownMenu.setMenuToId(sel.id, idName, true); // fire callback
                    }
                }
        
                // Restore FX parameters for the current fxchainScope, skipping selectors (already set)
                if (isDefined(params)) {
                    for (i = 0; i < params.length; i++) {
                        local p = params[i];
                        if (!isDefined(p) || !isDefined(p.id)) continue;
                        if (!_isFxParam(p.id)) continue;
                        if (p.id.contains("EffectSelector")) continue; // handled above
        
                        local c = Content.getComponent(p.id);
                        if (!isDefined(c)) continue;
        
                        c.setValue(p.value);
                        c.changed();
                    }
                }
        

        And you can hopefully see, that what that is doing is skipping userPresetLoad altogether - and instead is manually iterating around whatever data exists in the file, finding the right UI component, and setting the value. This allows me to circumvent some of the HISE assumptions; namely that if a UI component is not specified when loading a user preset, it gets reset to the default value. Which is super no bueno.

        Bear in mind some of this stuff can be asynchronous. So I don't think you can always rely on the order of things.

        Musician - Instrument Designer - Sonic Architect - Creative Product Owner
        Crafting sound at every level. From strings to signal paths, samples to systems.

        OrvillainO 1 Reply Last reply Reply Quote 1
        • OrvillainO
          Orvillain @Orvillain
          last edited by Orvillain

          @Christoph-Hart along these lines....

          Calling:
          updateSaveInPresetComponents(params) does indeed have the effect of setting any non specified parameters to their default value. This is not optimal for all use cases, for example my fx chain use case. Because what is happening is my synthesis generators are being reset to their default state, and the only way I can see how to avoid this is by iterating over all controls I do want to edit, and calling .setValue and then .changed() on them... which is actually quite slow it turns out.

          Could anything be done about this???

          Musician - Instrument Designer - Sonic Architect - Creative Product Owner
          Crafting sound at every level. From strings to signal paths, samples to systems.

          ustkU 1 Reply Last reply Reply Quote 0
          • ustkU
            ustk @Orvillain
            last edited by

            @Orvillain I'm not certain my brain gets all this so pardon me if it's not helping...
            But can't you do it the other way round, saving the module state with addModuleStateToUserPreset and then restore the UI components from it with updateConnectedComponentsFromModuleState?

            Hise made me an F5 dude, any other app just suffers...

            OrvillainO 1 Reply Last reply Reply Quote 0
            • OrvillainO
              Orvillain @ustk
              last edited by Orvillain

              @ustk Yep, indeed you can! the XML data you get from the module state call isn't pretty, but it does work. I think you'd do that if you had some module that did not have any UI controls, but you still wanted the preset to dictate its internal state when loading or saving.

              Musician - Instrument Designer - Sonic Architect - Creative Product Owner
              Crafting sound at every level. From strings to signal paths, samples to systems.

              1 Reply Last reply Reply Quote 0
              • DanHD
                DanH @ustk
                last edited by DanH

                @ustk clever - but possibly running through all the presets every time you load a new preset is going to take a while.... I'd need to cache them somehow.

                How does saving panel data work? Do you have to save the preset (bad for my use case)? Does it auto update / write to the .preset file? Where is the data in the .preset file?!

                EDIT - Oh it's not persistant... doh 😆

                DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
                https://dhplugins.com/ | https://dcbreaks.com/
                London, UK

                ustkU 1 Reply Last reply Reply Quote 0
                • ustkU
                  ustk @DanH
                  last edited by

                  @DanH said in Using custom preset system - as in the actual presets themselves, not a browser:

                  @ustk clever - but possibly running through all the presets every time you load a new preset is going to take a while.... I'd need to cache them somehow.

                  No, only at init when for checking if new presets are present

                  How does saving panel data work? Do you have to save the preset (bad for my use case)? Does it auto update / write to the .preset file?

                  Yes true... but it should be possible to just write it in the preset dynamically without the need to save. but that would require some clever string handling, don't know if it's secure enough and/or doable, but that might worth a try...
                  That might be where the already existing custom preset system is better...

                  Where is the data in the .preset file?!

                  Under the panel's value, like all other components

                  EDIT - Oh it's not persistant... doh 😆

                  Yes it is if in the preset..., it's recalled like any other value, that's what I do a lot in the things I've worked on

                  Hise made me an F5 dude, any other app just suffers...

                  DanHD 1 Reply Last reply Reply Quote 0
                  • DanHD
                    DanH @ustk
                    last edited by

                    @ustk said in Using custom preset system - as in the actual presets themselves, not a browser:

                    that's what I do a lot in the things I've worked on

                    of course 😆 Ok I'm obviously passing the data in wrong. Will take another look...

                    DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
                    https://dhplugins.com/ | https://dcbreaks.com/
                    London, UK

                    DanHD 1 Reply Last reply Reply Quote 0
                    • DanHD
                      DanH @DanH
                      last edited by

                      @ustk ok got it working. Is it possible to update the .preset file without using Engine.saveUserPreset ?

                      DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
                      https://dhplugins.com/ | https://dcbreaks.com/
                      London, UK

                      ustkU 1 Reply Last reply Reply Quote 0
                      • ustkU
                        ustk @DanH
                        last edited by

                        @DanH Yeah that's where the biggest job resides.
                        might doable with some XML parsing, and save as XML but the object might live as strings that are difficult to read/write. I won't be able to make tests within the next days so...

                        Hise made me an F5 dude, any other app just suffers...

                        DanHD 1 Reply Last reply Reply Quote 0
                        • DanHD
                          DanH @ustk
                          last edited by

                          @ustk I think it's too risky. One mistake in a preset file and it doesn't load.

                          DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
                          https://dhplugins.com/ | https://dcbreaks.com/
                          London, UK

                          David HealeyD 1 Reply Last reply Reply Quote 0
                          • David HealeyD
                            David Healey @DanH
                            last edited by

                            @DanH what about with HISE's xml parser?

                            Free HISE Bootcamp Full Course for beginners.
                            YouTube Channel - Public HISE tutorials
                            My Patreon - HISE tutorials

                            DanHD 1 Reply Last reply Reply Quote 0
                            • DanHD
                              DanH @David Healey
                              last edited by

                              @David-Healey don't know anything about it

                              DHPlugins / DC Breaks | Artist / Producer / DJ / Developer
                              https://dhplugins.com/ | https://dcbreaks.com/
                              London, UK

                              David HealeyD 1 Reply Last reply Reply Quote 0
                              • David HealeyD
                                David Healey @DanH
                                last edited by

                                @DanH These two

                                45560452-a98c-43ef-b1fc-6123cf2a9e08-image.png

                                Free HISE Bootcamp Full Course for beginners.
                                YouTube Channel - Public HISE tutorials
                                My Patreon - HISE tutorials

                                ustkU 1 Reply Last reply Reply Quote 0
                                • ustkU
                                  ustk @David Healey
                                  last edited by

                                  @David-Healey I tried in during my testing and even if I could make it work, the parsing of an array that contains strings is bad bad bad. You need to rework the result to remove the escape char and other things.
                                  This might just be normal, but then what about rewriting it back? Might work, might be risky, this I'm not sure until further testing it

                                  Hise made me an F5 dude, any other app just suffers...

                                  1 Reply Last reply Reply Quote 0
                                  • First post
                                    Last post

                                  26

                                  Online

                                  2.2k

                                  Users

                                  13.4k

                                  Topics

                                  116.4k

                                  Posts