diff --git a/src/input/Open.cxx b/src/input/Open.cxx
index 94d9a8546..19d76d731 100644
--- a/src/input/Open.cxx
+++ b/src/input/Open.cxx
@@ -5,8 +5,8 @@
 #include "Registry.hxx"
 #include "InputPlugin.hxx"
 #include "LocalOpen.hxx"
-#include "CondHandler.hxx"
 #include "RewindInputStream.hxx"
+#include "WaitReady.hxx"
 #include "fs/Traits.hxx"
 #include "fs/AllocatedPath.hxx"
 
@@ -35,22 +35,7 @@ InputStream::Open(const char *url, Mutex &mutex)
 InputStreamPtr
 InputStream::OpenReady(const char *uri, Mutex &mutex)
 {
-	CondInputStreamHandler handler;
-
 	auto is = Open(uri, mutex);
-	is->SetHandler(&handler);
-
-	{
-		std::unique_lock<Mutex> lock(mutex);
-
-		handler.cond.wait(lock, [&is]{
-			is->Update();
-			return is->IsReady();
-		});
-
-		is->Check();
-	}
-
-	is->SetHandler(nullptr);
+	LockWaitReady(*is);
 	return is;
 }
diff --git a/src/input/WaitReady.cxx b/src/input/WaitReady.cxx
new file mode 100644
index 000000000..498fd336f
--- /dev/null
+++ b/src/input/WaitReady.cxx
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright The Music Player Daemon Project
+
+#include "WaitReady.hxx"
+#include "InputStream.hxx"
+#include "CondHandler.hxx"
+
+void
+WaitReady(InputStream &is, std::unique_lock<Mutex> &lock)
+{
+	CondInputStreamHandler handler;
+	const ScopeExchangeInputStreamHandler h{is, &handler};
+
+	handler.cond.wait(lock, [&is]{
+		is.Update();
+		return is.IsReady();
+	});
+
+	is.Check();
+}
+
+void
+LockWaitReady(InputStream &is)
+{
+	std::unique_lock lock{is.mutex};
+	WaitReady(is, lock);
+}
diff --git a/src/input/WaitReady.hxx b/src/input/WaitReady.hxx
new file mode 100644
index 000000000..953f85e45
--- /dev/null
+++ b/src/input/WaitReady.hxx
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright The Music Player Daemon Project
+
+#pragma once
+
+#include "thread/Mutex.hxx"
+
+class InputStream;
+
+void
+WaitReady(InputStream &is, std::unique_lock<Mutex> &lock);
+
+void
+LockWaitReady(InputStream &is);
diff --git a/src/input/meson.build b/src/input/meson.build
index 490cd3370..611108c8e 100644
--- a/src/input/meson.build
+++ b/src/input/meson.build
@@ -28,6 +28,7 @@ input_glue = static_library(
   'input_glue',
   'Init.cxx',
   'Registry.cxx',
+  'WaitReady.cxx',
   'Open.cxx',
   'LocalOpen.cxx',
   'ScanTags.cxx',