Introduction
Over the past weeks I have completed a project that, for some time, seemed both technically awkward and conceptually unavoidable: running the CMME Score Viewer, a legacy Java Swing applet for early music notation, inside modern browsers, and embedding it seamlessly within a scholarly web edition.
The result is now publicly available on Codeberg:
👉 https://codeberg.org/perotinus/CMME_CheerpJ
This post explains the motivation, the technical challenges, the solutions, and what this means for digital critical editions of early music.
The Problem
The CMME Editor and Viewer, originally developed by Theodor Dumitrescu as part of the Computerized Mensural Music Editing project, remains one of the most powerful tools for encoding and visualising late medieval and Renaissance notation.
Upstream project:
However, the viewer was designed as a Java applet. Modern browsers no longer support NPAPI or Java plug-ins. The result is that the viewer, although still perfectly functional as Java code, cannot be used directly in the web environment in which most scholarly editions now live.
In my case, the need was concrete:
- I am preparing an online edition of the Cancionero Musical de Palacio.
- Each piece has:
- A critically revised modern edition.
- A structured
.cmme.xmlfile containing the original mensural encoding, variants, editorial markings, etc.
- I needed to display the CMME rendering inside the body of a web page, with commentary above and below.
- The viewer could not float as a draggable window.
- It had to behave as a proper embedded component.
The Strategic Decision: CheerpJ
The obvious long-term solution would be a complete rewrite of the viewer in JavaScript or TypeScript. That would require re-implementing:
- The rendering engine
- The mensural logic
- All interaction logic
- The configuration system
That is a multi-year project.
Instead, I chose a pragmatic route: CheerpJ by Leaning Technologies, which allows Java bytecode (including Swing applications and applets) to run in modern browsers via WebAssembly.
CheerpJ documentation:
CheerpJ does not emulate the old plug-in model. Instead, it loads a Java runtime in the browser and executes the application inside a managed environment.
This meant that:
- The original Java code could remain largely intact.
- The viewer could run in Chrome, Firefox, Edge, etc.
- The integration effort would focus on embedding and layout rather than rewriting music rendering.
Phase 1: Making the Viewer Run
The first stage involved:
- Building the
dist-applettarget with Ant. - Adjusting the Java source to compile against modern JDKs (Java 8 target).
- Removing legacy JAR signing steps.
- Serving the viewer via HTTP (CheerpJ requires HTTP, not file URLs).
- Ensuring all dependencies (
jdom,itext,xerces, etc.) were available. - Providing required resources:
- Fonts (
cmme.ttf) - Configuration file (
cmme-config.xml) - Gzipped score files (
.cmme.xml.gz)
- Fonts (
Once these were in place, the viewer ran correctly in a modern browser.
Phase 2: From Floating Window to Embedded Component
By default, the viewer opens each score in a JFrame. In CheerpJ this appears as a draggable internal window. That behaviour is unacceptable inside a critical edition.
The challenge was:
- Keep all rendering logic intact.
- Remove the “windowed” behaviour.
- Embed the UI into the applet container.
- Preserve menus and toolbar.
- Maintain full interactivity.
The Core Modification
Instead of displaying the JFrame, I:
- Created the
MusicWininstance normally. - Detached its
contentPane. - Reattached that content into the
JAppletroot container. - Reinstalled the
JMenuBaron the applet’s root pane. - Forced proper resizing logic using
ViewCanvas.newsize(...).
This required:
- Exposing
getViewCanvas()safely. - Adding an embedded refresh hook.
- Ensuring that menu actions trigger repaint.
Phase 3: Fixing Embedded Refresh Issues
After embedding, certain view options did not apply immediately. For example:
- Barline style (None / Mensurstrich / Tick / Modern)
- Note shape reduction
- Texting modes
- Pitch system
- Clef display toggles
The reason was subtle:
- These menu options update internal state.
- In standalone mode, repaint is implicitly triggered by window logic.
- In embedded mode, no automatic repaint occurred.
The solution was to:
- Introduce a
requestEmbeddedRefresh()method. - Hook it into all relevant listeners.
- Explicitly call
revalidate()andrepaint()onViewCanvas.
After that, all view options applied immediately and correctly.
Phase 4: WordPress-Friendly Embedding
To make the system usable by non-technical editors, I created:
web/embed.html- URL-driven loading via:
embed.html?file=palacio/001.cmme.xml
- A clean
<iframe>integration pattern:
<iframe
src="https://your-domain/viewer/embed.html?file=palacio/001.cmme.xml"
style="width:100%; height:70vh; min-height:420px;"
></iframe>
The viewer:
- Loads CheerpJ.
- Parses the
fileparameter. - Loads
/data/music/...gz. - Resizes responsively using
ResizeObserver.
This makes it suitable for inclusion in:
- WordPress
- Static sites
- Research portals
- Institutional repositories
Phase 5: Documentation and Publication
The repository includes:
- A complete
README.md - WordPress embedding documentation
- Build scripts
- Batch compression tools
- Clear deployment instructions
The fork is maintained under:
👉 https://codeberg.org/perotinus/CMME_CheerpJ
The upstream GPL licence is preserved, as required.
What This Enables
This work allows:
- Fully interactive mensural notation rendering
- Variant visualisation
- Switching between modern and original systems
- Clef and editorial toggle control
- Commentary integration
All inside:
- A modern browser
- A critical edition page
- Without Java plug-ins
- Without rewriting the rendering engine
For large projects such as the Cancionero Musical de Palacio, this bridges legacy scholarly tooling and contemporary web publication.
Reflections
This project is a case study in digital musicology pragmatism.
We often face a choice:
- Rewrite everything in modern web frameworks.
- Or intelligently wrap legacy systems.
In this case, wrapping was the correct decision.
The result preserves:
- Scholarly reliability
- Rendering fidelity
- Full CMME logic
While achieving:
- Browser compatibility
- Clean embedding
- Public deployability
If you are working on early notation, digital editions, or legacy Java scholarly tools and wish to discuss similar integrations, feel free to contact me.