Index: /trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java	(revision 551)
+++ /trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java	(revision 552)
@@ -3,4 +3,8 @@
 
 package org.openstreetmap.josm.data.gpx;
+
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 
 import org.openstreetmap.josm.Main;
@@ -22,3 +26,18 @@
 		return "WayPoint (" + (attr.containsKey("name") ? attr.get("name") + ", " :"") + latlon.toString() + ", " + attr + ")";
 	}
+	
+	/**
+	 * convert the time stamp of ther waypoint into seconds from the epoch
+	 * @return seconds
+	 */
+	public double time () {
+		if (! attr.containsKey("time"))
+			return 0.0;
+		SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); // ignore timezone
+		Date d = f.parse(attr.get("time").toString(), new ParsePosition(0));
+		if (d == null /* failed to parse */)
+			return 0.0;
+		return d.getTime() / 1000.0; /* ms => seconds */
+	}
+
 }
Index: /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 551)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 552)
@@ -11,4 +11,5 @@
 import java.awt.GridBagLayout;
 import java.awt.Point;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedList;
@@ -57,4 +58,5 @@
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
+import org.openstreetmap.josm.gui.layer.markerlayer.AudioMarker;
 import org.openstreetmap.josm.gui.layer.markerlayer.Marker;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
@@ -140,9 +142,4 @@
 		markersFromNamedTrackpoints.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent e) {
-/*
-				public Collection<GpxTrack> tracks = new LinkedList<GpxTrack>();
-				public Collection<Collection<WayPoint>> trackSegs
-				= new LinkedList<Collection<WayPoint>>();
-				*/
 				GpxData namedTrackPoints = new GpxData();
 				for (GpxTrack track : data.tracks)
@@ -156,4 +153,27 @@
 	            	Main.main.addLayer(ml);
 	            }
+			}
+		});
+
+		JMenuItem applyAudio = new JMenuItem(tr("Make Sampled Audio Layer"), ImageProvider.get("applyaudio"));
+		applyAudio.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				JFileChooser fc = new JFileChooser(Main.pref.get("tagimages.lastdirectory"));
+				fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
+				fc.setAcceptAllFileFilterUsed(false);
+				fc.setFileFilter(new FileFilter(){
+					@Override public boolean accept(File f) {
+						return f.isDirectory() || f.getName().toLowerCase().endsWith(".wav");
+					}
+					@Override public String getDescription() {
+						return tr("Wave Audio files (*.wav)");
+					}
+				});
+				fc.showOpenDialog(Main.parent);
+				File sel = fc.getSelectedFile();
+				if (sel == null)
+					return;
+				applyAudio(sel);
+				Main.map.repaint();
 			}
 		});
@@ -216,4 +236,5 @@
 				line,
 				tagimage,
+				applyAudio,
 				markersFromNamedTrackpoints,
 				new JMenuItem(new ConvertToDataLayerAction()),
@@ -456,3 +477,60 @@
 	}
 
+	/**
+	 * 
+	 *
+	 */
+	private void applyAudio(File wavFile) {
+		String uri = "file:".concat(wavFile.getAbsolutePath());
+	    double audioGapSecs = 15.0; 
+		try {
+			audioGapSecs = Double.parseDouble(Main.pref.get("marker.audiosampleminsecs", Double.toString(audioGapSecs)));
+		} catch (NumberFormatException e) {
+		}
+	    double audioGapMetres = 75.0; 
+		try {
+			audioGapMetres = Double.parseDouble(Main.pref.get("marker.audiosampleminmetres", Double.toString(audioGapMetres)));
+		} catch (NumberFormatException e) {
+		}
+		double audioGapRadians = (audioGapMetres / 40041455.0 /* circumference of Earth in metres */) * 2.0 * Math.PI;
+		double audioGapRadiansSquared = audioGapRadians * audioGapRadians;
+		double firstTime = -1.0;
+	    double prevOffset = - (audioGapSecs + 1.0); // first point always exceeds time difference
+	    WayPoint prevPoint = null;
+
+	    MarkerLayer ml = new MarkerLayer(new GpxData(), tr("Sampled audio markers from {0}", name), associatedFile);
+	    
+		for (GpxTrack track : data.tracks) {
+			for (Collection<WayPoint> seg : track.trackSegs) {
+				for (WayPoint point : seg) {
+					double time = point.time();
+					if (firstTime < 0.0)
+						firstTime = time;
+					double offset = time - firstTime;
+					if (prevPoint == null ||
+						(offset - prevOffset > audioGapSecs &&
+						/* note: distance is misleading: it actually gives distance _squared_ */
+						point.eastNorth.distance(prevPoint.eastNorth) > audioGapRadiansSquared))
+					{
+						String markerName;
+						int wholeSeconds = (int)(offset + 0.5);
+						if (wholeSeconds < 60)
+							markerName = Integer.toString(wholeSeconds);
+						else if (wholeSeconds < 3600)
+							markerName = String.format("%d:%02d", wholeSeconds / 60, wholeSeconds % 60);
+						else
+							markerName = String.format("%d:%02d:%02d", wholeSeconds / 3600, (wholeSeconds % 3600)/60, wholeSeconds % 60);
+						AudioMarker am = AudioMarker.create(point.latlon, markerName, uri, offset);
+						ml.data.add(am);
+						prevPoint = point;
+						prevOffset = offset;
+					}
+				}
+			}
+		}
+
+        if (ml.data.size() > 0) {
+        	Main.main.addLayer(ml);
+        }
+	}
 }
Index: /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/ButtonMarker.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/ButtonMarker.java	(revision 551)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/ButtonMarker.java	(revision 552)
@@ -61,5 +61,5 @@
 			b.paintBorder(mv, g, r.x, r.y, r.width, r.height);
 		}
-		if ((text != null) && (show.equalsIgnoreCase("show")) && Main.pref.getBoolean("marker.buttonlabels"))
+		if ((text != null) && (show.equalsIgnoreCase("show")) && Main.pref.getBoolean("marker.buttonlabels", true))
 			g.drawString(text, screen.x+4, screen.y+2);
 	}
Index: /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java	(revision 551)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java	(revision 552)
@@ -17,8 +17,4 @@
 import java.util.Collection;
 import java.util.Iterator;
-import java.util.Date;
-import java.text.SimpleDateFormat;
-import java.text.ParsePosition;
-import java.text.ParseException;
 import java.net.URL;
 
@@ -70,23 +66,12 @@
 		this.associatedFile = associatedFile;
 		this.data = new ArrayList<Marker>();
-		double offset = 0.0;
-		Date firstDate = null;
+		double firstTime = -1.0;
 
 		for (WayPoint wpt : indata.waypoints) {
 			/* calculate time differences in waypoints */
-			if (wpt.attr.containsKey("time")) {
-				SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); // ignore timezone, as it is all relative
-				Date d = f.parse(wpt.attr.get("time").toString(), new ParsePosition(0));
-				if (d == null /* failed to parse */) {
-					offset = 0.0;
-				} else if (firstDate == null) {
-					firstDate = d;
-					offset = 0.0;
-				} else {
-					offset = (d.getTime() - firstDate.getTime()) / 1000.0; /* ms => seconds */
-				}
-			}
-			
-            Marker m = Marker.createMarker(wpt, indata.storageFile, offset);
+			double time = wpt.time();
+			if (firstTime < 0)
+				firstTime = time;
+            Marker m = Marker.createMarker(wpt, indata.storageFile, time - firstTime);
             if (m != null)
             	data.add(m);
