Index: trunk/src/org/openstreetmap/josm/io/audio/AudioPlayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/AudioPlayer.java	(revision 14182)
+++ trunk/src/org/openstreetmap/josm/io/audio/AudioPlayer.java	(revision 14183)
@@ -4,4 +4,5 @@
 import java.io.IOException;
 import java.net.URL;
+import java.util.Objects;
 
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -47,4 +48,5 @@
 
     private State state;
+    private static Class<? extends SoundPlayer> soundPlayerClass;
     private SoundPlayer soundPlayer;
     private URL playingUrl;
@@ -266,4 +268,5 @@
     }
 
+    @SuppressWarnings("unchecked")
     private AudioPlayer() {
         state = State.INITIALIZING;
@@ -273,6 +276,10 @@
         double calibration = Config.getPref().getDouble("audio.calibration", 1.0 /* default, ratio */);
         try {
-            soundPlayer = (SoundPlayer) Class.forName("org.openstreetmap.josm.io.audio.fx.JavaFxMediaPlayer")
-                    .getDeclaredConstructor().newInstance();
+            if (soundPlayerClass == null) {
+                // To remove when switching to Java 11
+                soundPlayerClass = (Class<? extends SoundPlayer>) Class.forName(
+                        "org.openstreetmap.josm.io.audio.fx.JavaFxMediaPlayer");
+            }
+            soundPlayer = soundPlayerClass.getDeclaredConstructor().newInstance();
         } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
             Logging.debug(e);
@@ -355,3 +362,25 @@
         this.playingUrl = playingUrl;
     }
+
+    /**
+     * Returns the custom sound player class, if any.
+     * @return the custom sound player class, or {@code null}
+     * @since 14183
+     */
+    public static Class<? extends SoundPlayer> getSoundPlayerClass() {
+        return soundPlayerClass;
+    }
+
+    /**
+     * Sets the custom sound player class to override default core player.
+     * Must be called before the first audio method invocation.
+     * @param playerClass custom sound player class to override default core player
+     * @since 14183
+     */
+    public static void setSoundPlayerClass(Class<? extends SoundPlayer> playerClass) {
+        if (audioPlayer != null) {
+            throw new IllegalStateException("Audio player already initialized");
+        }
+        soundPlayerClass = Objects.requireNonNull(playerClass);
+    }
 }
Index: trunk/src/org/openstreetmap/josm/io/audio/fx/JavaFxMediaPlayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/fx/JavaFxMediaPlayer.java	(revision 14182)
+++ trunk/src/org/openstreetmap/josm/io/audio/fx/JavaFxMediaPlayer.java	(revision 14183)
@@ -34,5 +34,7 @@
  * </ul>
  * @since 12328
+ * @deprecated MP3 support moved to openjfx plugin as JavaFX is gone with Java 11.
  */
+@Deprecated
 public class JavaFxMediaPlayer implements SoundPlayer {
 
Index: trunk/src/org/openstreetmap/josm/io/audio/fx/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/fx/package-info.java	(revision 14182)
+++ trunk/src/org/openstreetmap/josm/io/audio/fx/package-info.java	(revision 14183)
@@ -4,4 +4,5 @@
  * Provides the classes for Audio mapping features requiring JavaFX.
  * The package is distinct to ease the decoupling between JOSM and JavaFX as an optional dependence.
+ * @deprecated MP3 support moved to openjfx plugin as JavaFX is gone with Java 11.
  */
 package org.openstreetmap.josm.io.audio.fx;
