diff --git a/src/DatabasePlaylist.cxx b/src/DatabasePlaylist.cxx
index b557cbf29..5f7c85a78 100644
--- a/src/DatabasePlaylist.cxx
+++ b/src/DatabasePlaylist.cxx
@@ -24,6 +24,7 @@
 #include "DatabaseGlue.hxx"
 #include "DatabasePlugin.hxx"
 #include "DetachedSong.hxx"
+#include "Mapper.hxx"
 
 #include <functional>
 
@@ -31,7 +32,8 @@ static bool
 AddSong(const char *playlist_path_utf8,
 	Song &song, Error &error)
 {
-	return spl_append_song(playlist_path_utf8, DetachedSong(song), error);
+	return spl_append_song(playlist_path_utf8, map_song_detach(song),
+			       error);
 }
 
 bool
diff --git a/src/DatabaseQueue.cxx b/src/DatabaseQueue.cxx
index 697771273..0ed073285 100644
--- a/src/DatabaseQueue.cxx
+++ b/src/DatabaseQueue.cxx
@@ -24,6 +24,7 @@
 #include "Partition.hxx"
 #include "util/Error.hxx"
 #include "DetachedSong.hxx"
+#include "Mapper.hxx"
 
 #include <functional>
 
@@ -31,7 +32,8 @@ static bool
 AddToQueue(Partition &partition, const Song &song, Error &error)
 {
 	PlaylistResult result =
-		partition.playlist.AppendSong(partition.pc, DetachedSong(song),
+		partition.playlist.AppendSong(partition.pc,
+					      map_song_detach(song),
 					      nullptr);
 	if (result != PlaylistResult::SUCCESS) {
 		error.Set(playlist_domain, int(result), "Playlist error");
diff --git a/src/DatabaseSong.cxx b/src/DatabaseSong.cxx
index 9afd109cb..a8f2188cc 100644
--- a/src/DatabaseSong.cxx
+++ b/src/DatabaseSong.cxx
@@ -22,6 +22,7 @@
 #include "DatabaseGlue.hxx"
 #include "DatabasePlugin.hxx"
 #include "DetachedSong.hxx"
+#include "Mapper.hxx"
 
 DetachedSong *
 DatabaseDetachSong(const char *uri, Error &error)
@@ -34,7 +35,7 @@ DatabaseDetachSong(const char *uri, Error &error)
 	if (tmp == nullptr)
 		return nullptr;
 
-	DetachedSong *song = new DetachedSong(*tmp);
+	DetachedSong *song = new DetachedSong(map_song_detach(*tmp));
 	db->ReturnSong(tmp);
 	return song;
 }
diff --git a/src/DetachedSong.hxx b/src/DetachedSong.hxx
index a99cbb4c8..7d841a4c2 100644
--- a/src/DetachedSong.hxx
+++ b/src/DetachedSong.hxx
@@ -32,6 +32,8 @@
 struct Song;
 
 class DetachedSong {
+	friend DetachedSong map_song_detach(const Song &song);
+
 	/**
 	 * An UTF-8-encoded URI referring to the song file.  This can
 	 * be one of:
@@ -60,6 +62,8 @@ class DetachedSong {
 	 */
 	unsigned end_ms;
 
+	explicit DetachedSong(const Song &other);
+
 public:
 	explicit DetachedSong(const DetachedSong &other)
 		:uri(other.uri),
@@ -67,8 +71,6 @@ public:
 		 mtime(other.mtime),
 		 start_ms(other.start_ms), end_ms(other.end_ms) {}
 
-	explicit DetachedSong(const Song &other);
-
 	explicit DetachedSong(const char *_uri)
 		:uri(_uri),
 		 mtime(0), start_ms(0), end_ms(0) {}
diff --git a/src/Mapper.cxx b/src/Mapper.cxx
index c6d8a3ea5..d41fba957 100644
--- a/src/Mapper.cxx
+++ b/src/Mapper.cxx
@@ -217,6 +217,12 @@ map_detached_song_fs(const char *uri_utf8)
 	return AllocatedPath::Build(music_dir_fs, uri_fs);
 }
 
+DetachedSong
+map_song_detach(const Song &song)
+{
+	return DetachedSong(song);
+}
+
 AllocatedPath
 map_song_fs(const Song &song)
 {
diff --git a/src/Mapper.hxx b/src/Mapper.hxx
index e19a9e137..18a5ca3fe 100644
--- a/src/Mapper.hxx
+++ b/src/Mapper.hxx
@@ -106,6 +106,14 @@ gcc_pure
 AllocatedPath
 map_directory_child_fs(const Directory &directory, const char *name);
 
+/**
+ * "Detach" the #Song object, i.e. convert it to a #DetachedSong
+ * instance.
+ */
+gcc_pure
+DetachedSong
+map_song_detach(const Song &song);
+
 /**
  * Determines the file system path of a song.  This must not be a
  * remote song.
diff --git a/src/PlaylistEdit.cxx b/src/PlaylistEdit.cxx
index 24d9d9653..0eea62e18 100644
--- a/src/PlaylistEdit.cxx
+++ b/src/PlaylistEdit.cxx
@@ -31,6 +31,7 @@
 #include "util/Error.hxx"
 #include "Song.hxx"
 #include "DetachedSong.hxx"
+#include "Mapper.hxx"
 #include "Idle.hxx"
 #include "DatabaseSong.hxx"
 #include "Log.hxx"