Index: trunk/src/org/openstreetmap/josm/io/audio/AudioListener.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/AudioListener.java	(revision 13818)
+++ trunk/src/org/openstreetmap/josm/io/audio/AudioListener.java	(revision 13819)
@@ -8,5 +8,5 @@
  * @since 12328
  */
-interface AudioListener {
+public interface AudioListener {
 
     /**
Index: trunk/src/org/openstreetmap/josm/io/audio/AudioPlayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/AudioPlayer.java	(revision 13818)
+++ trunk/src/org/openstreetmap/josm/io/audio/AudioPlayer.java	(revision 13819)
@@ -20,9 +20,29 @@
     private static volatile AudioPlayer audioPlayer;
 
-    enum State { INITIALIZING, NOTPLAYING, PLAYING, PAUSED, INTERRUPTED }
-
-    enum Command { PLAY, PAUSE }
-
-    enum Result { WAITING, OK, FAILED }
+    /**
+     * Audio player state.
+     */
+    public enum State {
+        /** Initializing */
+        INITIALIZING,
+        /** Not playing */
+        NOTPLAYING,
+        /** Playing */
+        PLAYING,
+        /** Paused */
+        PAUSED,
+        /** Interrupted */
+        INTERRUPTED
+    }
+
+    /**
+     * Audio player command.
+     */
+    public enum Command { /** Audio play */ PLAY, /** Audio pause */ PAUSE }
+
+    /**
+     * Audio player result.
+     */
+    public enum Result { /** In progress */ WAITING, /** Success */ OK, /** Failure */ FAILED }
 
     private State state;
@@ -33,5 +53,5 @@
      * Passes information from the control thread to the playing thread
      */
-    class Execute {
+    public class Execute {
         private Command command;
         private Result result;
@@ -84,17 +104,33 @@
         }
 
-        protected double offset() {
+        /**
+         * Returns the offset.
+         * @return the offset, in seconds
+         */
+        public double offset() {
             return offset;
         }
 
-        protected double speed() {
+        /**
+         * Returns the speed.
+         * @return the speed (ratio)
+         */
+        public double speed() {
             return speed;
         }
 
-        protected URL url() {
+        /**
+         * Returns the URL.
+         * @return The resource to play, which must be a WAV file or stream
+         */
+        public URL url() {
             return url;
         }
 
-        protected Command command() {
+        /**
+         * Returns the command.
+         * @return the command
+         */
+        public Command command() {
             return command;
         }
@@ -237,5 +273,5 @@
         double calibration = Config.getPref().getDouble("audio.calibration", 1.0 /* default, ratio */);
         try {
-            soundPlayer = (SoundPlayer) Class.forName("org.openstreetmap.josm.io.audio.JavaFxMediaPlayer")
+            soundPlayer = (SoundPlayer) Class.forName("org.openstreetmap.josm.io.audio.fx.JavaFxMediaPlayer")
                     .getDeclaredConstructor().newInstance();
         } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
Index: trunk/src/org/openstreetmap/josm/io/audio/JavaFxMediaPlayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/JavaFxMediaPlayer.java	(revision 13818)
+++ 	(revision )
@@ -1,123 +1,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.io.audio;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.concurrent.CountDownLatch;
-
-import org.openstreetmap.josm.io.audio.AudioPlayer.Execute;
-import org.openstreetmap.josm.io.audio.AudioPlayer.State;
-import org.openstreetmap.josm.tools.JosmRuntimeException;
-import org.openstreetmap.josm.tools.ListenerList;
-
-import com.sun.javafx.application.PlatformImpl;
-
-import javafx.scene.media.Media;
-import javafx.scene.media.MediaException;
-import javafx.scene.media.MediaPlayer;
-import javafx.scene.media.MediaPlayer.Status;
-import javafx.util.Duration;
-
-/**
- * Default sound player based on the Java FX Media API.
- * Used on platforms where Java FX is available. It supports the following audio codecs:<ul>
- * <li>MP3</li>
- * <li>AIFF containing uncompressed PCM</li>
- * <li>WAV containing uncompressed PCM</li>
- * <li>MPEG-4 multimedia container with Advanced Audio Coding (AAC) audio</li>
- * </ul>
- * @since 12328
- */
-class JavaFxMediaPlayer implements SoundPlayer {
-
-    private final ListenerList<AudioListener> listeners = ListenerList.create();
-
-    private MediaPlayer mediaPlayer;
-
-    JavaFxMediaPlayer() throws JosmRuntimeException {
-        try {
-            initFxPlatform();
-        } catch (InterruptedException e) {
-            throw new JosmRuntimeException(e);
-        }
-    }
-
-    /**
-     * Initializes the JavaFX platform runtime.
-     * @throws InterruptedException if the current thread is interrupted while waiting
-     */
-    public static void initFxPlatform() throws InterruptedException {
-        final CountDownLatch startupLatch = new CountDownLatch(1);
-
-        // Note, this method is called on the FX Application Thread
-        PlatformImpl.startup(startupLatch::countDown);
-
-        // Wait for FX platform to start
-        startupLatch.await();
-    }
-
-    @Override
-    public synchronized void play(Execute command, State stateChange, URL playingUrl) throws AudioException, IOException {
-        try {
-            final URL url = command.url();
-            if (playingUrl != url) {
-                if (mediaPlayer != null) {
-                    mediaPlayer.stop();
-                }
-                // Fail fast in case of invalid local URI (JavaFX Media locator retries 5 times with a 1 second delay)
-                if ("file".equals(url.getProtocol()) && !new File(url.toURI()).exists()) {
-                    throw new FileNotFoundException(url.toString());
-                }
-                mediaPlayer = new MediaPlayer(new Media(url.toString()));
-                mediaPlayer.setOnPlaying(() ->
-                    listeners.fireEvent(l -> l.playing(url))
-                );
-            }
-            mediaPlayer.setRate(command.speed());
-            if (Status.PLAYING == mediaPlayer.getStatus()) {
-                Duration seekTime = Duration.seconds(command.offset());
-                if (!seekTime.equals(mediaPlayer.getCurrentTime())) {
-                    mediaPlayer.seek(seekTime);
-                }
-            }
-            mediaPlayer.play();
-        } catch (MediaException | URISyntaxException e) {
-            throw new AudioException(e);
-        }
-    }
-
-    @Override
-    public synchronized void pause(Execute command, State stateChange, URL playingUrl) throws AudioException, IOException {
-        if (mediaPlayer != null) {
-            try {
-                mediaPlayer.pause();
-            } catch (MediaException e) {
-                throw new AudioException(e);
-            }
-        }
-    }
-
-    @Override
-    public boolean playing(Execute command) throws AudioException, IOException, InterruptedException {
-        // Not used: JavaFX handles the low-level audio playback
-        return false;
-    }
-
-    @Override
-    public synchronized double position() {
-        return mediaPlayer != null ? mediaPlayer.getCurrentTime().toSeconds() : -1;
-    }
-
-    @Override
-    public synchronized double speed() {
-        return mediaPlayer != null ? mediaPlayer.getCurrentRate() : -1;
-    }
-
-    @Override
-    public void addAudioListener(AudioListener listener) {
-        listeners.addWeakListener(listener);
-    }
-}
Index: trunk/src/org/openstreetmap/josm/io/audio/SoundPlayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/SoundPlayer.java	(revision 13818)
+++ trunk/src/org/openstreetmap/josm/io/audio/SoundPlayer.java	(revision 13819)
@@ -12,5 +12,5 @@
  * @since 12328
  */
-interface SoundPlayer {
+public interface SoundPlayer {
 
     /**
Index: trunk/src/org/openstreetmap/josm/io/audio/fx/JavaFxMediaPlayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/fx/JavaFxMediaPlayer.java	(revision 13819)
+++ trunk/src/org/openstreetmap/josm/io/audio/fx/JavaFxMediaPlayer.java	(revision 13819)
@@ -0,0 +1,126 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.audio.fx;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.concurrent.CountDownLatch;
+
+import org.openstreetmap.josm.io.audio.AudioException;
+import org.openstreetmap.josm.io.audio.AudioListener;
+import org.openstreetmap.josm.io.audio.AudioPlayer.Execute;
+import org.openstreetmap.josm.io.audio.AudioPlayer.State;
+import org.openstreetmap.josm.io.audio.SoundPlayer;
+import org.openstreetmap.josm.tools.JosmRuntimeException;
+import org.openstreetmap.josm.tools.ListenerList;
+
+import com.sun.javafx.application.PlatformImpl;
+
+import javafx.scene.media.Media;
+import javafx.scene.media.MediaException;
+import javafx.scene.media.MediaPlayer;
+import javafx.scene.media.MediaPlayer.Status;
+import javafx.util.Duration;
+
+/**
+ * Default sound player based on the Java FX Media API.
+ * Used on platforms where Java FX is available. It supports the following audio codecs:<ul>
+ * <li>MP3</li>
+ * <li>AIFF containing uncompressed PCM</li>
+ * <li>WAV containing uncompressed PCM</li>
+ * <li>MPEG-4 multimedia container with Advanced Audio Coding (AAC) audio</li>
+ * </ul>
+ * @since 12328
+ */
+public class JavaFxMediaPlayer implements SoundPlayer {
+
+    private final ListenerList<AudioListener> listeners = ListenerList.create();
+
+    private MediaPlayer mediaPlayer;
+
+    JavaFxMediaPlayer() throws JosmRuntimeException {
+        try {
+            initFxPlatform();
+        } catch (InterruptedException e) {
+            throw new JosmRuntimeException(e);
+        }
+    }
+
+    /**
+     * Initializes the JavaFX platform runtime.
+     * @throws InterruptedException if the current thread is interrupted while waiting
+     */
+    public static void initFxPlatform() throws InterruptedException {
+        final CountDownLatch startupLatch = new CountDownLatch(1);
+
+        // Note, this method is called on the FX Application Thread
+        PlatformImpl.startup(startupLatch::countDown);
+
+        // Wait for FX platform to start
+        startupLatch.await();
+    }
+
+    @Override
+    public synchronized void play(Execute command, State stateChange, URL playingUrl) throws AudioException, IOException {
+        try {
+            final URL url = command.url();
+            if (playingUrl != url) {
+                if (mediaPlayer != null) {
+                    mediaPlayer.stop();
+                }
+                // Fail fast in case of invalid local URI (JavaFX Media locator retries 5 times with a 1 second delay)
+                if ("file".equals(url.getProtocol()) && !new File(url.toURI()).exists()) {
+                    throw new FileNotFoundException(url.toString());
+                }
+                mediaPlayer = new MediaPlayer(new Media(url.toString()));
+                mediaPlayer.setOnPlaying(() ->
+                    listeners.fireEvent(l -> l.playing(url))
+                );
+            }
+            mediaPlayer.setRate(command.speed());
+            if (Status.PLAYING == mediaPlayer.getStatus()) {
+                Duration seekTime = Duration.seconds(command.offset());
+                if (!seekTime.equals(mediaPlayer.getCurrentTime())) {
+                    mediaPlayer.seek(seekTime);
+                }
+            }
+            mediaPlayer.play();
+        } catch (MediaException | URISyntaxException e) {
+            throw new AudioException(e);
+        }
+    }
+
+    @Override
+    public synchronized void pause(Execute command, State stateChange, URL playingUrl) throws AudioException, IOException {
+        if (mediaPlayer != null) {
+            try {
+                mediaPlayer.pause();
+            } catch (MediaException e) {
+                throw new AudioException(e);
+            }
+        }
+    }
+
+    @Override
+    public boolean playing(Execute command) throws AudioException, IOException, InterruptedException {
+        // Not used: JavaFX handles the low-level audio playback
+        return false;
+    }
+
+    @Override
+    public synchronized double position() {
+        return mediaPlayer != null ? mediaPlayer.getCurrentTime().toSeconds() : -1;
+    }
+
+    @Override
+    public synchronized double speed() {
+        return mediaPlayer != null ? mediaPlayer.getCurrentRate() : -1;
+    }
+
+    @Override
+    public void addAudioListener(AudioListener listener) {
+        listeners.addWeakListener(listener);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/audio/fx/package-info.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/audio/fx/package-info.java	(revision 13819)
+++ trunk/src/org/openstreetmap/josm/io/audio/fx/package-info.java	(revision 13819)
@@ -0,0 +1,7 @@
+// License: GPL. For details, see LICENSE file.
+
+/**
+ * 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.
+ */
+package org.openstreetmap.josm.io.audio.fx;
