Version 2.2.25

88emuPlayer:

- [Fix] MIDI Player: Loading a MIDI file whose SysEx or Meta event is cut short
        by the end of the file, or by a track chunk that is shorter than its
        contents, no longer reads past the data or terminates the player.

- [Fix] ROMs: Make the VEGS-Pro support the SC-88Pro waveroms as well.

Version 2.2.24


Framework:

- [Fix] The patch manager could hang the interface for minutes on folders
        with tens of thousands of patch files.

- [Fix] DSPBridge: The server took the port of its UDP connection from the
        TCP port setting.

- [Fix] DSPBridge: When a device did not start on the server, the connection
        hung. The server now refuses the device instead.

88emuPlayer:

- [Fix] MIDI: Deliver System DT1 messages to the SC-88, SC-88VL and SC-88Pro
        firmware, restoring per-part `CHANNEL MSG RX PORT` assignments and
        System Mode Set. Individual parts can layer from the same MIDI input.

Version 2.2.23


88emuPlayer:

- [New] MIDI Player: The standalone now restores the last playlist automatically.
        Right-click the playlist to load or save portable `.m3u` / `.m3u8`
        playlist files, or add/drop one to append its entries.

- [Fix] MIDI Player: Prevent shortened opening notes in songs with dense
        initial instrument setup. Send safe opening setup ahead of playback
        and let cleanup finish even when the per-song reset is off.

- [Fix] MIDI Player: Recomposer RCP Track Exclusive messages now read their
        SysEx payload from F7 continuation records, so SC-88Pro setup data is
        no longer prefixed with invalid bytes and discarded.

- [Imp] MIDI: Command-line MIDI input options can now assign inputs to
        groups A-D with `--midi-in-a` through `--midi-in-d`. `--midi-in`
        remains the group-A shorthand.

- [Imp] UI: The CM-32P PCM card image can be chosen in the settings and is
        remembered, instead of only through the --pcm-card launch option.

- [Fix] Devices: The front-panel POWER switch and Q shortcut now use standby
        on the SC-55, SC-55mkII, SC-155, SC-155mkII and SC-88VL.

- [New] Devices: Added experimental support for NU-10B and MIIG5 (GM mode only).

Version 2.2.22


88emuPlayer:

- [Imp] UI: The Settings panel has now a more readable font size.

- [Fix] UI: Restore the standard window border color.

- [Fix] UI: Correct the SC-88Pro USER INST / EFX indicator to display green,
        red or amber according to the front-panel LED controls.

- [Imp] Devices: The PWM-controlled VCA in the CM-32P is now modelled.

- [Fix] Devices: LP chip emulation was using a wrong scaling factor that was
        affecting the total output volume.

- [Fix] Audio: Avoid waiting for the user interface when processing front-panel
        input and updating the display from the audio thread.

- [Fix] MIDI: Preserve outgoing MIDI timing within audio blocks, including when
        analog output emulation uses oversampling.

- [Fix] MIDI Player: Clear sustained and releasing notes on transport changes
        even after an All Notes Off message.

- [Fix] MIDI Player: Wait longer after the per-song reset before starting the
        song. The previous pause was shorter than the reset itself takes to
        reach the device, so songs that set up every part on their first tick
        lost the notes at their start.

- [Fix] macOS: Restore software rendering when Metal initialization fails,
        removing the native Metal view that could leave the window black.

- [Fix] macOS: Support GPUs requiring 4x instead of 2x Metal antialiasing and
        correct Metal texture transfers and unsupported OpenGL calls.

- [Fix] macOS: Release Metal resources when closing or recreating the interface
        to prevent graphics memory usage from growing.

- [Imp] ROMs: Added support for the SC-88Pro correct wave set as 5 separate chips.

Version 2.2.21


Framework:

- [Fix] BUG-10355 After switching to another ROM, the patch manager could keep
        offering the presets of the previous ROM, taken from its cache, instead
        of the ones of the ROM that is loaded. Tags, favourites, renames and
        MIDI bank numbers of ROM presets and banks are kept.

- [Fix] BUG-10323 Plugin windows could open at their smallest possible size
        and stay that small every time they were opened again. When a host,
        the window manager or a display change asked for a smaller window
        than that, the result was remembered as the chosen scale. It no
        longer is, and a window that was saved that small opens at 100%.

- [Imp] BUG-10322 The skin canvas supports more of the HTML5 2D drawing
        context: linear and radial gradients (createLinearGradient,
        createRadialGradient, addColorStop), clip, clearRect, lineJoin,
        lineCap and ctx.canvas, the canvas element being drawn, whose
        client_width and client_height give its size in pixels. strokeRect
        now centres its outline on the rectangle, as HTML5 does.

- [Imp] DSPBridge: The server is no longer limited to plugins of its own
        version. It can host any plugin version that uses the same bridge
        protocol, so new plugin versions can be copied into the server's
        plugins folder next to the old ones without reinstalling the server.
        A client still gets the exact plugin version it asks for.

- [Fix] DSPBridge: On Windows, the server could corrupt memory and crash
        when a device sent a lot of MIDI at once or had a large state.
        Plugins and server have to be updated together for this, older
        plugins are not loaded by the new server.

88emuPlayer:

- [New] Added comprehensive README, shipped with the binaries.

- [New] Added `88EmuCli` for rendering MIDI files offline.

- [New] Added standalone cli params for scripting and advanced options.

- [Imp] Performance: Removed the additional emulation-worker buffering from
        playback and live MIDI for performance. The player now renders the board
        synchronously.

- [New] Devices: Added support for the original SC-55, SC-155, SC-155mkII,
        SCC-1A and SCB-55.

- [New] Devices: Added the XPGS / G-800 sound engine.

- [New] Devices: Added VE-GS Pro as a separate device.

- [New] Devices: Added experimental SC-8820 emulation.

- [New] Devices: Added experimental CM-32P emulation.

- [New] Devices: Added emulated power on/off button using the Q shortcut.

- [New] Devices: Added “Factory Reset on load” and “Fast Boot (skip intro)”
        settings.

- [Fix] Devices: Firmware that ran past the end of a 64 KB code page crashed the
        player, for example a program ROM booted with the wrong MCU ROM. The
        program counter now wraps to the start of the same page, as on the real
        CPU.

- [New] MIDI Player: Added Recomposer RCP/R36 (V2) and G36 (V3) playback support
        (thanks to masanaohayashi and shingo45endo).

- [New] MIDI Player: Added a configurable GM/GS/MT32 reset before each song.

- [New] MIDI Player: Added a configurable pause between automatically advancing
        songs.

- [Fix] MIDI Player: Starting another song now clears channel controllers and
        pitch bend, including when the per-song reset is Off, preventing the
        previous song's pitch bend from leaving instruments out of tune.
        Transport changes also invalidate file events still waiting in the
        player/engine queues.

- [Fix] MIDI Player: MIDI files with non-ASCII filenames can be opened through
        the Unicode-aware filesystem path, including on Windows.

- [New] Audio: Added selectable left and right hardware output channels,
        remembered separately for each audio backend and device.

- [New] Audio: Added “Use system device” for CoreAudio and Windows Audio
        (WASAPI), enabled by default for configurations without an explicit
        output choice.

- [New] Audio: Added an optional stereo-linked output limiter after the volume
        control, protecting playback and WAV recording when gain is increased.

- [New] Audio: Added optional analog output emulation, including DAC word
        precision and modeled output filtering. Select Off, Auto for the current
        device, or a specific circuit: CM-32P, SC-55, SC-55mkII, SCC-1, G-800,
        SC-88, SC-88VL, SC-88Pro, SC-8820 or SC-8850. Off remains the default.

- [New] MIDI: Each MIDI input can now play one or more independently selected
        part groups A–D, with assignments saved in MIDI settings. Available
        groups depend on the selected device.

- [Imp] MIDI: Expanded virtual MIDI inputs and outputs from A/B to A–D on
        supported platforms, exposing all four SC-8850 groups. Device output
        retains its original group, and launch options can customize the
        port-name prefix.

- [Fix] MIDI: Implemented the SC-88/SC-88Pro firmware's MIDI output path,
        allowing messages such as front-panel bulk dumps to reach the selected
        MIDI output.

- [Fix] MIDI: Forwarded the Yamaha SysEx messages needed to activate the
        SC-88Pro firmware's XG compatibility mode. This exposes the firmware's
        existing compatibility behavior; it does not add full Yamaha XG
        emulation.

- [Fix] MIDI: Paced SC-55mkII MIDI bursts to avoid overflowing the emulated
        controller's input buffer when many events arrive together.

- [New] ROMs: Added custom ROM loading by conventional filename and exact size,
        taking precedence over hash-based discovery. Known images still work
        under arbitrary filenames. Unrecognized or modified content produces a
        warning, with an option to suppress custom-ROM warnings.

- [New] ROMs: Unavailable devices in the device menu now open a ROM requirements
        dialog showing accepted filenames, sizes, hashes, missing components and
        compatible alternatives. The details can be copied, and the ROM folder
        can be opened directly.

- [Imp] ROMs: SC-8850 wave ROMs can now be supplied as two distinct 16 MiB
        banks, including recognized raw XP dump layouts, in addition to the
        existing combined decoded image.

- [Imp] ROMs: Recognized the SC-55mkII GS-28 2.00 image pre-patched with
        shingo45endo's capital-tone-fallback patcher using its default SC-55
        tone and v1 drum options. The player loads the patched image; it does
        not apply the patch itself.

- [Imp] ROMs: Limited automatic ROM searches to the player's data folder and its
        subfolders, avoiding unrelated legacy/product locations. `--rom-dir`
        selects an exclusive alternative folder. ROMs previously found only in
        older search locations must be moved or selected through this option.

- [Imp] ROMs: Optimized wave-ROM descrambling and compatible Pro-wave conversion
        during loading (thanks to hackyourlife).

- [Imp] UI: Reorganized the device menu to keep related models together.

- [Imp] UI: Device and context menus now open in separate scrolling popup
        windows, avoiding clipping at the edge of the player.

- [Imp] UI: Added system-font fallbacks for names containing characters absent
        from the bundled font, including CJK text, and normalized decomposed
        macOS filenames for display.

- [Fix] UI: The SC-8850 SHIFT, DEC and INC keyboard shortcuts now reach the
        corresponding panel controls, including shifted minus/plus keys.

- [Fix] UI: Mouse-wheel input on endless knobs now wraps instead of stopping at
        the ends of the range, including the SC-8850 value encoder.

- [Fix] UI: Clicking an open drop-down's control to dismiss its popup no longer
        immediately reopens it.

- [Fix] UI: On macOS, opening a temporary popup no longer hides the close button
        of windows without minimize/maximize controls.

Version 2.2.20


Framework:

- [Fix] Switching the part through the MCP server left Vavra, Xenia, Osirus
        and OsTIrus showing the old part: the part selection did not move and
        the patch manager kept targeting the previous part.

- [Fix] The FX versions of OsTIrus, Vavra and Xenia did not show their device
        specific settings, such as the voice expansion option of Vavra and Xenia.

- [Fix] The DSP Bridge server ignored the plugins folder set in its
        configuration and only loaded plugins from the folder next to its
        executable.

- [Fix] The DSP Bridge server still started a device from a ROM that was
        damaged while being sent to it.

- [Imp] BUG-10327 The DSP Bridge server can now run a device from a regular
        plugin, not only from the server plugins that come with it. The
        plugin has to be the same version as the one in the DAW, and goes
        into the server's plugins folder.

- [Imp] If the DSP Bridge server cannot create the device, the plugin now says
        why, for example that the server has no plugin of that version,
        instead of showing "Error code 4".

- [Fix] BUG-10269 Dragging any edge of the plugin window other than a corner
        made the interface smaller and never larger again. The fixed aspect
        ratio was resolved from the proposed size alone, which always corrects
        the larger of the two dimensions - exactly the one an edge drag
        changes.

- [Fix] VST2 builds that use the fst fallback, which steps in when the
        Steinberg SDK is not present, corrupted the heap the first time the
        host asked for the speaker arrangement. Every channel count was
        affected, a mono bus included, and it could take down the plugin or
        the host.

- [Fix] Clock, start/stop, program change and channel pressure coming from the
        host carried whatever bytes happened to follow them in memory: three
        bytes were read from every message, however short it is.

- [Fix] SysEx that reaches the plugin in pieces was handed to the emulation
        twice, once reassembled and once as the raw fragments, which a
        firmware can read as channel data.

- [Fix] SysEx from a host that frames it twice lost its start byte instead of
        the surplus end byte, leaving a headless message behind.

- [Fix] BUG-10332 BUG-10337 The software renderer drew garbage and could crash
        the plugin with a skin that tiles an image across an area: it read
        past the end of the image instead of repeating it.

- [Fix] The DSP Bridge server kept a device that could not be initialized,
        for example because its firmware did not finish booting, and the
        connection to it hung. The plugin now shows why the device could not
        be created.

- [Fix] On macOS, the packages of the standalone effect plugins never
        contained the script that removes the quarantine flag.

Version 2.2.19


Framework:

- [Fix] Closing a window while one of its drop-down or context menus was
        still open could crash. The menu removed itself from a document that
        was already tearing down, where every child has been detached from
        its parent before any of them is destroyed.

- [Fix] On macOS, the Metal renderer read the window and view geometry from
        its own render thread. AppKit is not thread-safe, and doing so while
        the message thread rearranges windows - reloading a skin, closing a
        settings window - can corrupt state that only fails much later, in an
        unrelated redraw. The geometry is now taken on the message thread.

- [Fix] On macOS, the interface could freeze or stutter while its window was
        hidden or covered by another one: the Metal render thread waited for
        a drawable while holding the UI lock, up to a second at a time, and
        the message thread starved waiting for it. And once that wait timed
        out, the frame was dropped without telling the update loop, which
        then waited for it forever - the window never updated again.

- [Fix] On Windows and Linux, the OpenGL thread could draw the interface
        while the message thread was changing it, without any lock between
        them. The redraw juce requests on a resize took that path.

- [Fix] With software rendering forced on Windows and Linux, the interface
        was drawn from the top left corner of the window rather than at the
        editor's position, so in a standalone it covered the title bar and
        lost its bottom rows.

- [Fix] After falling back from a software OpenGL rasterizer to the built-in
        software renderer, the interface stopped updating.

- [Fix] The DSP Bridge could crash or freeze the plugin, most often while a
        project was being saved or when the connection to the server stalled.

- [Fix] Picking a skin or a renderer from a menu could crash: choosing it closes
        the window the menu itself lives in, and the menu kept working with what
        was already gone.

- [Fix] After the renderer changed, anything drawn from a cached snapshot - a box
        shadow, for example - stayed invisible for the rest of the session.

- [Fix] Keys held down while the window lost focus stayed down on Linux, and a
        key that auto-repeated was reported as released once per repeat.

- [Fix] The plugin told the host its latency from the audio thread, once per
        block. Hosts answer that by suspending and re-preparing the plugin, so
        playback could be interrupted at any moment.

- [Fix] The interface could stall for as long as a frame took to draw, with
        mouse and keyboard input queuing up behind it, and a redraw that called
        back into the renderer could lock up completely.

88emuPlayer:

- [Fix] Selecting ASIO now waits for an explicit output-device choice,
        avoiding crashes from automatically loading an unsuitable driver.
        Opening the driver's control panel no longer uses a deleted device.

- [Fix] With software rendering forced, the interface was drawn into the top
        left corner of the window on Windows displays running at a scaling
        other than 100%, and mouse positions were off by the same factor. The
        software renderer sized its output in logical pixels while the image
        it draws into is sized in physical ones.

- [Fix] On the SC-8850, the front panel could stop responding after a while
        of playing a song: PART < and PART > did nothing, or a single press
        switched ALL mode on and off. The emulated CPU delivered an interrupt
        the firmware had just requested up to one audio sample late, and in
        that gap the firmware's own task scheduler lost the task that times
        the panel keys. Interrupts now arrive right after the instruction
        that requested them.

- [Fix] Panel switches are released when the window loses focus, so a stuck
        switch can no longer turn every later press into a key combination.

- [Fix] On the SC-88 and SC-88Pro, Display Letter and Display Dot Data
        messages were ignored: the emulated sub-MCU only passed SysEx with
        the GS model ID through to the main CPU, and the display messages
        use model ID 45H. Songs that draw on the level-meter dots now do.

- [Fix] On the SC-55mkII, a dense SysEx stream such as a display dot
        animation produced "Check Sum Error" and "DT1 Data Error" every few
        seconds. The emulated sub-MCU could hand the main CPU the same byte
        twice when its periodic wake-up fell between the CPU reading the
        status and reading the data.

- [Fix] On the SC-88 and SC-88VL, a song that follows its GS Reset with a
        burst of parameter SysEx without the pause the GS spec asks for could
        lock the module up: no sound, no panel. The emulated MIDI wire
        delivered such messages about a fifth faster than a real cable can,
        which drained the firmware's transfer buffers while it was still
        busy with the reset. SysEx is now paced by its full wire length.

- [Fix] Stopping or pausing a song left notes hanging on the SC-8850's part
        groups C and D, and so did removing the song that was playing. Panic
        and the GM/GS reset buttons reached only groups A and B as well. The
        player silenced two MIDI ports where a song can address four.

- [Fix] The player no longer sends MIDI clock to the emulated module.

- [Fix] On Linux the data and ROM folder was $HOME/Documents/The Usual
        Suspects instead of the XDG location the other plugins use. It is now
        $XDG_DATA_HOME (or $HOME/.local/share); the old folder is still read
        so an existing installation keeps finding its ROMs.

- [Fix] The MIDI settings no longer offer "Enable Virtual Port" on Windows.
        PortMidi can only create virtual endpoints on macOS and Linux, so the
        switch never did anything and left a polling thread running.

- [Fix] Added missing ASIO support.

- [Imp] "Force software rendering" now takes effect in the settings window as
        well, not only in the panel. Until now the settings kept drawing with
        the old renderer until they were closed and reopened.

- [Imp] The drop-down lists in the audio and MIDI settings open in a window of
        their own. They are no longer cut off at the edge of the settings
        dialog, and a long list such as the buffer sizes scrolls instead of
        spreading into columns across the whole page.

- [Imp] MIDI settings: the list of MIDI inputs is three times as tall, with one
        compact line per device, and the note about virtual MIDI ports on
        Windows sits below the list instead of crowding the output selector.

- [Fix] Fixed midi receive in the high level sub mcu emulation with midi files
        that send custom LCD messages.

- [Imp] ROM images are now identified by their size and content instead of by
        filename, and subfolders of a ROM search path are searched too. Dumps
        can be renamed or kept in an unsorted collection, either byte order of
        a mask ROM is accepted, and a truncated or unrelated file of the right
        size can no longer be mistaken for a ROM.

- [Imp] A device can only be selected once every ROM it needs is present.
        Incomplete ones are greyed out instead of failing when picked, the
        first complete device is used when the configured one is unavailable,
        and the missing-ROM notice names each image with its size and hash.

- [Imp] Added icon for the app.

Version 2.2.18


88emuPlayer:

- [New] First internal release.

Version 2.2.17


Framework:

- [Fix] BUG-10308 Skins: an animation did nothing at all when its keyframes
        name contained an uppercase letter, because the name was folded to
        lower case before it was looked up. Keyframe names are now case
        sensitive, the same as in CSS.

- [New] BUG-10200 Skins can react to notes being played. A skin script can
        now register for note on and note off and draw a keyboard, a velocity
        meter or an activity indicator, which was impossible before because
        notes go straight to the emulated hardware and never reach the
        parameter API. Notes are reported whatever their source and before
        MIDI Learn can consume them, and a note on with velocity 0 is
        reported as the note off it means. See doc/lua_scripting.md.

- [New] BUG-10302 Skins can store their own variables. A skin can now keep
        state the synth knows nothing about, such as which of its knobs it
        has linked together, in one of two scopes: per instance, saved and
        restored with the host project, or global, shared by every instance
        through the plugin config. Reading without naming a scope answers
        from the instance and falls back to the global, so a skin can ship a
        default and let a project override it. Values are numbers or strings
        and a callback reports changes. See doc/lua_scripting.md.

- [Imp] BUG-10273 BUG-10277 Mame HQ is now the default resampler mode, and
        the mode is remembered. A mode stored in a project is still used for
        that project; when a project does not carry one, the mode last
        selected on the settings page applies, and Mame HQ if it was never
        changed. Note that projects saved before this version did not store
        the mode at all while it was set to Legacy, so those open in Mame HQ
        now and need the mode set once if Legacy is wanted.

- [Fix] BUG-10313 Preset files of other plugins failed to import when they
        happened to contain an $f0 and an $f7 byte with arbitrary data in
        between. Such a pair is not a sysex message, but it was read as one,
        after which the importer considered the file parsed and never tried
        the format the file actually is.

Version 2.2.16


Framework:

- [Imp] BUG-10304 Skins can now animate on their own clock. A skin that
        declares an onframe handler on its body receives a frame event
        once per rendered frame, carrying the elapsed time and the time
        since the previous frame, which is what an oscilloscope or a VU
        meter needs. Until now the only way to loop an animation was to
        chain a CSS transition into itself. The rate is capped at 60 Hz,
        follows the refreshRateLimitHz config setting if one is present,
        and drops to nothing while the editor is off screen or while no
        skin asks for it. See doc/lua_scripting.md.

Version 2.2.14


Framework:

- [Fix] BUG-10281 BUG-10288 BUG-10278 macOS: the plugin failed to load and
        did not pass validation on macOS versions below 14, with dyld
        reporting a missing symbol for std::pmr::get_default_resource. The
        sysex buffer used a std::pmr::vector whose runtime symbols are only
        available on macOS 14 and newer; it now falls back to std::vector
        unless the deployment target is macOS 14 or later.

- [Fix] BUG-10293 macOS: the user interface was rendered even though the
        plugin editor was hidden or minimized, causing a high GPU load. The
        UI is not rendered anymore while it is not visible on screen.

- [Imp] Faster DSP emulation. The emulation core shared by all synths has
        been optimized and now runs about 20% faster on average, measured
        on Windows, Linux and macOS with both Intel/AMD and ARM CPUs. How
        much is gained depends on the patch, some benefit considerably
        more than others. This lowers CPU usage and allows running more
        instances at once.

Version 2.2.9


Framework:

- [Fix] macOS: emulation threads could lose their realtime status and end
        up being scheduled like background work, causing spikes and
        dropouts. The realtime scheduling parameters were computed with
        wrong units (microseconds instead of Mach time units) and an
        invalid period, and thread QOS classes were never applied.
- [Fix] Linux: thread priorities were never applied due to a bug in the
        priority mapping.
- [Fix] macOS: gradient decorators were rendered incorrectly with the
        Metal renderer and could break the rendering of the whole UI,
        leaving most of it black and seemingly frozen. The gradient
        parameters were uploaded to the GPU with a wrong memory layout.
- [New] macOS: setting disableMetalRenderer to 1 in the plugin config
        file makes the UI render with OpenGL instead of Metal. This
        helps to find out whether a rendering issue is Metal specific.
- [Fix] EMU-80 The MCP screenshot tool now works with the Metal renderer
        on macOS. Previously only the OpenGL path could capture.
- [New] Skins can now use SVG images via the RmlUi SVG plugin (svg
        element and svg() decorator), rendered with LunaSVG.
- [New] Lua binding for the canvas element with an HTML5-compatible 2D
        drawing context (fillStyle, strokeStyle, lineWidth, fillRect,
        strokeRect, beginPath, moveTo, lineTo, rect, arc, ellipse, fill,
        stroke). Skin scripts can draw custom graphics on a canvas.

Version 2.2.7


Framework:

- [Fix] BUG-10214 Linux: VST2 plugins were named "lib<Name>" because the
        shared object kept the default "lib" prefix. The prefix is now
        cleared so the VST2 is named like the other formats.

Version 2.2.6


Framework:

- [Fix] EMU-75 Fix intermittent JIT cache crash during DSP boot caused
        by a race in the MmuHelper placeholder restore on Windows.
- [Fix] Fix crash in part button preset menu when comparing patches
        with null source pointers.
- [Fix] BUG-10209 Fix "Overwrite patch" option disappearing from save
        menu after saving once.

Version 2.2.5


Framework:

- [Fix] BUG-10199 Fix build errors on macOS ARM64: SSE compiler flags
        were added on non-x86 architectures, and missing cstddef include
        for size_t in dac.h.

Version 2.2.4


Framework:

- [New] BUG-10179 MIDI Learn: Invert option per mapping. Incoming CC
        values and outgoing feedback can now be inverted (a new
        "Invert" checkbox in the MIDI Learn settings page).
- [Imp] Support parsing of ".mid" files that are not really midi but
        raw sysex
- [Imp] ParameterDescriptions: "toText" now accepts an object form
        {format, scale, offset} that synthesises a value list at load
        time. Lets devices with non-7-bit native parameter ranges
        declare native min/max and produce human-readable display text
        without controller-side scaling.

- [Fix] BUG-10177 Third-party skins: Plugin-specific settings pages
        (e.g. Voice Expansion) are now loaded from the embedded plugin
        binary when a skin is loaded from disk
- [Fix] BUG-10189 Fix crash on the audio thread when a rate-limited
        parameter is automated by the DAW.

Version 2.2.3


Framework:

- [New] EMU-73 Native Metal renderer for macOS, replacing the
        deprecated OpenGL path. Supports all rendering features
        including backdrop blur, filters, drop shadows, gradients,
        clip masking and MSAA.
- [New] EMU-70 Lua scripting support for skins. Skin authors can use
        Lua scripts in RML files to create dynamic UI behavior, read
        and write synth parameters, and react to parameter changes.
        See doc/lua_scripting.md for documentation.

- [Fix] Fix file drag and drop onto part buttons (patch name, part
        slots) not accepting dropped .syx/.mid files
- [Fix] MIDI Learn: Feedback to host and physical MIDI ports was not
        working
- [Fix] Fix crash on plugin shutdown when a physical MIDI port was
        active and a MIDI event arrived during shutdown (common problem
        for controllers that send MIDI clock)
- [Fix] BUG-10159 CLAP: Fix keyboard input in text fields (cursor
        jumping, digit reordering) on Windows
- [Fix] #262 Restore Windows 7 compatibility
- [Fix] BUG-10144 Fix combo box value mapping for parameters with empty
        entries (e.g. Phaser Stages in Osirus)
- [Fix] BUG-10163 Software renderer: Fix GUI content shifting when
        window is partially off-screen
- [Fix] BUG-10168 Software renderer: Fix triangle rendering ignoring
        scissor clip region (settings dialog overflow)
- [Fix] EMU-42 Patch Manager: Fix file move failures with multiple
        plugin instances in the same DAW
- [Fix] BUG-10166 Fix slider following knob after double-click

Version 2.2.2


Framework:

- [Imp] BUG-10125 Browser grid view now supports mouse wheel scrolling for
        horizontal navigation
- [Imp] Added parameter linking for individual parameters

- [Fix] EMU-18 Patch Manager: MIDI Banks category now appears for all synths
        (was missing in Xenia, Vavra, and NodalRed2x)
- [Fix] EMU-18 Patch Manager: MIDI bank assignments now persist across
        plugin reloads (added serialization to binary cache)
- [Fix] EMU-18 Patch Manager: MIDI Banks category is now collapsed by default
- [Fix] BUG-10148 Patch Manager: Dragging a folder onto the data sources
        tree now correctly adds it as a folder source instead of a file
- [Fix] Patch Manager: Fix potential crash when scrolling group tree node
        into view after element was destroyed
- [Fix] Software Renderer: Fix UI scaling issue in Bitwig when monitor
        DPI is set above 100%
- [Fix] BUG-10102 Parameter Links: Prevent circular link dependencies that
        caused erratic controller jumps. Bidirectional links are now rejected
        with a user-facing warning dialog
- [Fix] BUG-10111 Linux: Fix crash when loading multiple TUS plugin types
        in the same DAW process, caused by ELF symbol interposition between
        plugin shared objects
- [Fix] BUG-10134 Fixed parameter rate limiting firing too fast due to
        unreliable JUCE timer, causing sluggish wavetable bank cycling
- [Fix] BUG-10117 Combo box mouse wheel scrolling now follows display order
        for custom-ordered dropdowns (e.g. Page Matrix Assign Destination)
- [Fix] Right-click context menu now opens correctly on scrollbar/slider
        elements instead of falling through to the global menu
- [Fix] BUG-10153 Patch Manager: Fix crash when typing in browser search
        columns caused by invalid tree node cast during filtering

Version 2.2.1


Framework:

- [Imp] EMU-6 MIDI Learn Mode: Replaced single-parameter dialog with a
        full visual overlay mode. Enter via right-click context menu,
        overlays appear on all parameters showing bound/unbound state.
        Left-click to select a parameter for learning, right-click to
        clear a mapping. Press Escape to exit MIDI Learn mode.
- [Fix] Removed old MIDI Learn dialog (replaced by overlay mode)
- [Fix] Fix crash when closing plugin while MIDI Learn mode is active

Version 2.2.0


Framework:

- [Imp] New Settings screen replacing context menu options, with pages for:
        MIDI routing matrix with presets, DSP & Audio (latency, gain,
        DSP clock, resampler mode), and Skin/GUI (skin selection, scale,
        software renderer toggle)
- [Imp] EMU-6 MIDI Learn: Map any physical MIDI controller to synth
        parameters with auto-detection of absolute and relative modes.
        Supports CC, Pitch Bend, Aftertouch, and Poly Pressure.
        Includes preset management, conflict detection, and MIDI feedback.
- [Imp] EMU-23 Part buttons: Right-click copy/paste via system clipboard,
        enabling patch transfer between multi and single mode
- [Imp] Add MAME high-quality and lo-fi resampler modes as alternatives
        to the legacy resampler, selectable per instance in DSP & Audio settings
- [Imp] Optimize MAME resampler: use contiguous scratch buffers in FIR
        loops, eliminate per-callback heap allocation
- [Imp] EMU-18 Patch Manager: Program change banks — assign MIDI bank
        numbers to data sources, enabling Bank Select + Program Change to
        select patches from the patch manager. Factory ROM banks get
        default assignments. Respects MIDI routing matrix settings.

Version 2.1.4


Framework:

- [Fix] EMU-42 Patch Manager: Fix threading bugs and file I/O race
        conditions with multiple plugin instances
- [Fix] Patch Manager: Fix ghost nodes remaining in tree after
        clearing a search filter
- [Fix] Patch Manager: Fix non-matching folder nodes remaining
        visible during tree search filtering

Version 2.1.2


Framework:

- [Imp] BUG-10120 allow to drag sliders slower by using shift key
- [Imp] BUG-10130 Add IParameterFinder support for VST3 plug-ins
        to support "AI knob" control surfaces

- [Fix] BUG-10135 Patch Manager now works with WSL2 EXT4 mounted drives
- [Fix] BUG-10136 Conditional parameter links now work with mouse wheel
- [Fix] BUG-10133 Parameter values now correctly update when dragging controls quickly
- [Fix] Crash when loading plugin on some Linux distributions

Version 2.1.1


Framework:

- [Fix] BUG-10089 Crash when unloading plugin while automating a parameter
- [Fix] Warning dialog and broken UI in certain hosts if host alters
        the locale to something that uses , as decimal point instead of .

Version 2.1.0


Framework:

- [Fix] BUG-10085 Do not expand factory ROM presets tree node by default
- [Fix] BUG-10084 Linux: Plugin editor cannot be operated after releasing
        the mouse

Version 2.0.14


Framework:

- [Imp] Implemented software renderer that is used if no compatible OpenGL
        version is available. Software rendering can be forced via config
        file: Set forceSoftwareRenderer to 1

- [Fix] Further attempts to improve thread priority for DSP threads on macOS
- [Fix] List view in patch manager might not always refresh correctly when
        selecting a different bank

Version 2.0.13


Framework:

- [Imp] Improved compatiblity with Win 7 and older OpenGL versions

Version 2.0.11


Framework:

- [Fix] BUG-10045 Vertical sliders won't reset to 0 but to -1 on double click
- [Fix] BUG-10051 Do not send gesture begin/end to host if parameter is
        changed via midi CCs

Version 2.0.10


Framework:

- [Fix] BUG-10043 First GUI event "eaten" on plugin init

Version 2.0.9


Framework:

- [Fix] Thread priorities were not set correctly on Mac/Linux, solves
        BUG-10040 Track performance affected by application focus
- [Fix] BUG-10039 Right clicking a menu entry opened a second menu
- [Fix] Reworked UI frame timing to use less resources
- [Fix] Patch Manager: Exported patches may not have consecutive
        bank/program numbers

Version 2.0.8


Framework:

- [Imp] Patch Manager: Setting to hide duplicates by name & hash are now
        remembered when reopening the plugin

- [Fix] Random tooltips shown when resizing the plugin window
- [Fix] BUG-10035 Automation randomly stopped working in some hosts due to UI
        sending automation events back to host
- [Fix] EMU-25 focused parameter keeps dragged element in focus

Version 2.0.6


Framework:

- [Fix] [UI] Pressing a button should not set the "checked" pseudo-class, that is what
        the "active" state is for. BUG-10026 Furthermore, checked state was kept when
        moving out of the button while holding the mouse button down.
- [Fix] [UI] Missing repaint if parameter changed via Midi CC causing sliders to jump
- [Fix] Possible crash when resizing the editor window

Version 2.0.4


Framework:

- [Imp] Add ability to cycle through drop down entries and radio button groups
        via mouse wheel

- [Fix] Fix inverted mouse wheel on Mac if natural scrolling is enabled

Version 2.0.3


Framework:

- [Imp] DSP Bridge: The last connected host is now stored as part of the plugin state
        and is reconnected to automatically on next plugin load.
        If a connection cannot be established, the plugin will display a warning message
        and will automatically fall back to local processing.

- [Fix] BUG-10016 Added OpenGL 2 renderer as fallback if OpenGL 3.3 is not supported to
        fix crashes on older hardware / Raspberry Pi
- [Fix] BUG-10013 Sliders can now be adjusted via mouse wheel.
- [Fix] BUG-10014 Patch Manager: Child data sources were still visible even
        if parent node closed.
- [Fix] BUG-10017 Tooltips could exceed screen bounds in some cases
- [Fix] Patch Manager: List entry was being force-selected when being dragged
- [Fix] Patch Manager: Patch list didn't refresh after renaming a patch
- [Fix] Patch Manager: Drag & Drop from patch list to patch slot of UI (depending on plugin)
        not working
- [Fix] Wrong initial state of toggle buttons bound to a parameter
- [Fix] Toggle buttons that are part of a radio group shouldn't disable when clicked again
- [Fix] Vertical sliders being reversed when bound to a parameter
- [Fix] Erratic behaviour of tooltips/focused parameters when multiple parameters
        are automated
- [Fix] Focused parameter display & tooltips not working for sliders

Version 2.0.2


Framework:

- [Fix] Disable all DSP Bridge related network activity if DSP Bridge is
        not explicitly enabled via config file.
- [Fix] Context Menus didn't open via Ctrl+Click on macOS.
- [Fix] Plugins consumed all keyboard events regardless of if they were
        actually handled or not. This caused issues in various hosts. For example,
        it prevented using the space bar to toggle playback while the plugin was
        focused.
- [Fix] Content flickering in some hosts when resizing the plugin window to odd
        aspect ratios

Version 2.0.1


Framework:

- [Imp] Incresed size of RmlUi debugger

- [Fix] Knobs didn't respect the selected part and always displayed/modified part 1
- [Fix] Patch Manager: Data sources were not sorted
- [Fix] Patch Manager: List/Grid cell sizes height increased to cover descenders of letters like 'g' or 'y'
- [Fix] UI didn't repaint immediately when parameter is modified via automation or MIDI
- [Fix] Skin conversion didn't work when skin was in the legacy location next to the plugin
- [Fix] Multiple context menus could be opened at the same time

Version 2.0.0


Framework:

- [Imp] Juce GUI has been replaced with RmlUi, a HTML/CSS based UI framework.
        This allows to create more complex and visually appealing UI skins.
        More information can be found at
        https://dsp56300.wordpress.com/2025/08/19/rmlui-new-gui-rendering-engine-skinning-system/

Version 1.4.5


Framework:

- [Fix] Physical MIDI input was not disabled when changing port from any
        valid input to none
- [Fix] The program name was always returned as "default" even if previously
        modified via the host. This fixes incorrect host preset names after
        a rename in Logic, Reaper and possibly other hosts
- [Fix] Various issues if root path contains non-ASCII characters

Version 1.4.2


Framework:

- [Imp] Skinning System: Added ability to add parameter bindings to labels
- [Imp] Skinning System: Added roughly CSS-based styling system. This allows to
        move properties that are common to all buttons/knobs/etc to a single style
        to prevent that they need to be repeated for each element.
        Export the latest NodalRed2x skin to see the new format

- [Imp] Downgraded to Juce 7 to regain compatibility with Windows 7 & fix font
        rendering issues on macOS

Version 1.4.1


Framework:

- [Imp] Allow to find patches with similar parameter setting by right clicking on
        a knob and selecting "Find similar..."
- [Imp] Allow to add a patch to a user bank by dragging it onto the free space of
        the patch list

- [Imp] [Skins] Add new option "boldRootItems" to tree view style to disable that root
        items are displayed in bold font (default 1 = enabled)
- [Imp] [Skins] Add new option "antialiasing" for label style to disable antialiased
        font rendering (default 1 = enabled)

- [Fix] Patch Manager might report file access errors that are not relevant
- [Fix] Renamed patches might be displayed with previous name when loaded

Version 1.4.0


Framework:

- [Imp] Upgraded to Juce 8.0.3 which uses Direct2D on Windows for faster UI rendering
- [Imp] Patch Manager now stores its database in the user documents folder, next
        to skins and roms:
        c:\Users\<username>\Documents\The Usual Suspects\<synthname>\patchmanager (Win)
        ~/Documents/The Usual Suspects/<synthname>/patchmanager (Mac)
        [XDG_DATA_HOME or ~/.local/share]/The Usual Suspects/<synthname>/patchmanager (Linux)
        Any existing database in the old location is automatically migrated to
        the new one.
- [Imp] Config file location has been changed and is now located in a subfolder
        "config" next to the other folders. Existing configurations in legacy
        locations are migrated automatically.

Version 1.3.21


DSP:

- [Imp] Performance improvements

Framework:

- [Imp] Added new entry to 'Skins' submenu to open the skins folder in the default
        file browser
- [Imp] All MacOS builds now include a script to remove quaratine attributes
- [Imp] The default skin folder has changed. Custom skins are now supposed to be in:

        c:\Users\<username>\Documents\The Usual Suspects\<synthname>\skins (Win)
        ~/Documents/The Usual Suspects/<synthname>/skins (Mac)
        [XDG_DATA_HOME or ~/.local/share]/The Usual Suspects/<synthname>/skins (Linux)

        Existing skins in the old location are still supported to ensure backwards
        compatibility

- [Imp] ROMs are now also searched for in the following directories

        c:\Users\<username>\Documents\The Usual Suspects\<synthname>\roms (Win)
        ~/Documents/The Usual Suspects/<synthname>/roms (Mac)
        [XDG_DATA_HOME or ~/.local/share]/The Usual Suspects/<synthname>/roms (Linux)

        For backwards compatibility, it is also possible to copy ROMs next to the
        plugins as it was before

- [Imp] If a firmware is missing, the target folder is now being opened to prevent
        that a user has to search for it manually

- [Fix] FX plugins didn't apply latency when being processed as bypassed, causing the
        signal to appear early
- [Fix] Tooltips didn't refresh correctly in some hosts / plugin formats
- [Fix] Redraw issues in Bitwig on Windows if DPI is set to a value != 100%
- [Fix] VST3: Hosts didn't pick up new parameter values when switching presets or
        loading state

Version 1.3.20


Framework:

- [Imp] Strip path names from skin names in GUI Skin submenu (mkruselj)

- [Fix] Patch Manager: Lost Favourites/Tags/User Banks if plugin closed before scan
        finished
- [Fix] Crash when dragging a patch from Patch Manager to a part slot
- [Fix] Crash when dragging a patch on an empty area in grid view
- [Fix] Drag target slot rectangles displayed in grid view for areas without content
- [Fix] Continue MIDI clock generation while DAW sequencer is stopped

Version 1.3.19


Framework:

- [Imp] Patch Manager: Added options to reveal a datasource in the default
        File Browser of the OS

- [Fix] CLAP: Ranges of discrete parameters were not reported properly,
        causing automation issues
- [Fix] Context menu for text edit fields was twice as large as intended
- [Fix] LV2 plugins were packaged into a a Unix like subfolder for Mac/Win

Version 1.3.18


Framework:

- [Imp] Physical MIDI port selection is now stored per instance

- [Fix] Physical MIDI ports were not opened before GUI was opened

Version 1.3.17 (2024.08.04)


Framework:

- [Imp] Patch Manager: Added grid layout, you can switch between list and
        grid layout via context menu

- [Fix] LV2 plugins were packaged incorrectly (#199)

Version 1.3.16 (2024.07.14)


Framework:

- [Fix] Patch Manager: Last selected patch was not always restored properly

Version 1.3.15 (2024.07.06)


Framework:

- [Imp] Patches can now be imported via drag & drop. You can drag .mid, .syx,
        .vstpreset, .fxb, .fxp files into the plugin to load them. You can drop
        patches on a part to load them directly, drop them on the patch manager
        data sources to add them as new source or drop them onto the user banks
        area to add a new user bank or add them to an existing one
- [Imp] Patches can now be dragged to external applications or the desktop. This
        will export MIDI files. You can drag parts, data sources or an arbitrary
        number of selected patches from the patch list
- [Imp] You can now drag parts from one instances to a part of another instance
        of the same plugin kind to copy/paste patches across instances
- [Imp] The patch of the currently selected part can now be copied & pasted via
        Ctrl/Cmd C/V or via context menu. This copying is text based so that you
        can share presets easily in forums etc.
- [Imp] A data source can now be dragged onto tags to modify all patches at once
- [Imp] Parameters now have their own context menu. In this context menu you can:
- Lock/unlock a region
- Copy/paste a region
- Link/unlink regions across parts
- [Imp] Added parameter linking across parts. If you link a region of a part to
        another part, knob movements/automation data/MIDI controls for the
        source part are forwarded to all parts linked. This eases automation
        for layered instruments
- [Imp] Region locks are now per part instead of being global
- [Imp] Region locks are indicated by displaying an overlay next to each locked
        parameter.
- [Imp] Rotaries operated via mouse wheel now increment/decrement in single
        steps while shift is pressed
- [Imp] Tooltip duration shortened to 1.5 seconds (mkruselj)
- [Imp] Parameter tooltips are now constrained to the plugin window (mkruselj)

- [Fix] Patch export as .mid created broken midi files
- [Fix] Corrupted data was sent to physical midi output (if selected) at plugin startup
- [Fix] Parameter change information in LCDs and tooltips were flickering if one knob
        was modified via mouse while another one was modified via automation or MIDI

Version 1.3.14


Framework:

- [Imp] Rename "db" to "dB" in all gain context menus (mkruselj)
- [Imp] Column breaks for dropdown menu based parameters improved (mkruselj)
- [Imp] Selecting the same skin again reloads it, useful for skin
        developers (mkruselj)

Patch Manager:

- [Fix] Typo "Deleted Selected" in patch context menu (mkruselj)

Version 1.3.13


Framework:

- [Imp] Added warning message if running under Rosetta as performance will be bad
- [Imp] Added 'Panic' menu to send All Notes Off / reboot device

- [Fix] Do not crash if a skin cannot be loaded

Patch Manager:

- [Imp] Added context menu setting to hide duplicates by name
- [Imp] Added options to add/remove patches to/from tags, categories & favourites
        via context menu
- [Imp] "Save" buttons now have more options: Allow to save to any
        existing user bank or create a new one automatically if there is none yet
- [Fix] Name of user bank not displayed in patch information panel
- [Fix] Fix possible crash when loading cache
- [Fix] List ordering incorrect when being loaded from cache
- [Fix] Tags/Favourites got lost in some circumstances

Version 1.3.12


Framework:

- [Fix] VST3 plugins were rejected by some hosts on macOS

Version 1.3.11


Framework:

- [Imp] Added disclaimer about ROM usage
- [Imp] Add warning message if a Midi port cannot be opened because it is already in use
- [Imp] Third-party skins are now expected to be in a folder that is named like the plugin:
        skins_PlugName, for example skins_Osirus.
        Currently selected skins are still loaded and you can export the current skin to
        disk to create the new folder automatically. Move other skins to the new
        folder manually.

Patch Manager:

- [Imp] Database is now cached so subsequent loads are faster. If a datasource needs to be
        updated, right click and select "Refresh" to force a rescan
- [Imp] Added a default text "Search..." to search boxes independent from the used skin
- [Imp] Allow to add multiple files/folders at once when adding datasources

- [Fix] Info about selected patch not updated when patch renamed or tags modified

Version 1.3.9


DSP:

- [Imp] Small performance optimizations

- [Fix] DSP thread not set to high priority on Mac/Linux

Framework:

- [Imp] Upgraded Juce to version 7.0.10
- [Imp] Plugin window can now have an arbitrary size by dragging the bottom right corner
- [Imp] Added support for the LV2 plugin format
- [Imp] Added options to Save button to allow storing the current preset in a user bank

- [Fix] VST3 packaging corrected for Windows & Linux to match specification as stated at
        https://steinbergmedia.github.io/vst3_dev_portal/pages/Technical+Documentation/Locations+Format/Plugin+Format.html
- [Fix] Patch Manager: Failed to parse folder that contains UTF-8 characters
- [Fix] Patch Manager: Selection was not updated when a part is saved to a user bank
- [Fix] Knob movement via mouse wheel didn't update automation & parameter display

Version 1.3.8 (2024.03.11)


DSP:

- [Imp] Small performance improvements

Framework:

- [Imp] Second click on root tree items of category tree deselects the item
- [Imp] Patch Manager: "Uncategorized" has been moved into the Categories group

- [Fix] Patch Manager: Missing patches if a directory contains files with unicode characters

Version 1.3.7


Framework:

- [Imp] Patch Manager: A category can now be deselected via second mouse click to remove
        any category filter
- [Imp] Patch Manager: Root tree items (Factory Patches, Datasources) are no longer
        auto-expand upon load
- [Imp] Patch Manager: data source names are now shortened

- [Imp] Inform that changing plugin latency blocks while being in use might cause synchronization
        problems

- [Fix] Patch Manager: No error message was displayed if a user bank cannot be written to disk
- [Fix] Patch Manager: It was not possible to add presets to a newly created tag until another
        data source was selected

Version 1.3.6 (2024.03.03)


DSP:

- [Imp] Performance improvements

- [Fix] Crash on x86 processors in various circumstances

Framework:

- [Fix] PatchManager: Edit field not refreshing text while typing in some hosts when adding
        a user bank or favourite

Version 1.3.5 (2024.03.01)


DSP:

- [Imp] Reduced host memory consumption
- [Imp] Performance improvements

Framework:

- [Imp] Patch Manager: Add "Locate" context menu entry for patch to select the data source that contains it

Version 1.3.4 (TBD)


DSP:

- [Imp] Small performance improvements when JIT compiler needs to recompile code

Framework:

- [Imp] Patch Manager: Add tooltip for data source to show the full path in case its cut off
- [Imp] Patch Manager: Columns can now be resized by dragging
- [Imp] The DSP can now be underclocked/overclocked via context menu between 50% and 200%. This is
        an advanced setting that needs to be confirmed before activation

- [Fix] Patch Manager: Fix subfolders not enumerated on Mac & Linux
- [Fix] Add missing .vstpreset, .fxb and .cpr file extensions to file selector when loading a patch via "Load" button
- [Fix] Parameter value change by double-click on knob to reset it was not sent to host for automation
- [Fix] Linked parameters confused Bitwig / Ableton and other hosts
- [Fix] Long plugin loading times in some hosts due to excessive initial parameter automation updates
- [Fix] Part context menu and global context menu opened at the same time on right click

Version 1.2.21 (2022.12.06)


DSP:

- Performance improvements (5-10%)
- Stability improvemens
- Large speedup of code (re)generation. Results in faster startup time, reduces hiccups in Multi mode and when changing patches
