From ece59710275851c1100ca992dc25cd0f84c20fca Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Wed, 14 Dec 2016 12:54:19 +0100
Subject: [PATCH] output/Multiple: move Wait() to struct PlayerControl

Eliminate a dependency from MultipleOutputs on PlayerControl.
---
 src/output/MultipleOutputs.cxx | 17 -----------------
 src/output/MultipleOutputs.hxx | 10 ----------
 src/player/Control.cxx         | 13 +++++++++++++
 src/player/Control.hxx         | 17 +++++++++++++++++
 src/player/Thread.cxx          |  4 ++--
 5 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx
index 639aa1560..6341554bf 100644
--- a/src/output/MultipleOutputs.cxx
+++ b/src/output/MultipleOutputs.cxx
@@ -19,7 +19,6 @@
 
 #include "config.h"
 #include "MultipleOutputs.hxx"
-#include "player/Control.hxx"
 #include "Internal.hxx"
 #include "Domain.hxx"
 #include "MusicBuffer.hxx"
@@ -331,22 +330,6 @@ MultipleOutputs::Check()
 	return 0;
 }
 
-bool
-MultipleOutputs::Wait(PlayerControl &pc, unsigned threshold)
-{
-	pc.Lock();
-
-	if (Check() < threshold) {
-		pc.Unlock();
-		return true;
-	}
-
-	pc.Wait();
-	pc.Unlock();
-
-	return Check() < threshold;
-}
-
 void
 MultipleOutputs::Pause()
 {
diff --git a/src/output/MultipleOutputs.hxx b/src/output/MultipleOutputs.hxx
index 3bde1c697..3352ad7dc 100644
--- a/src/output/MultipleOutputs.hxx
+++ b/src/output/MultipleOutputs.hxx
@@ -159,16 +159,6 @@ public:
 	 */
 	unsigned Check();
 
-	/**
-	 * Checks if the size of the #MusicPipe is below the #threshold.  If
-	 * not, it attempts to synchronize with all output threads, and waits
-	 * until another #MusicChunk is finished.
-	 *
-	 * @param threshold the maximum number of chunks in the pipe
-	 * @return true if there are less than #threshold chunks in the pipe
-	 */
-	bool Wait(PlayerControl &pc, unsigned threshold);
-
 	/**
 	 * Puts all audio outputs into pause mode.  Most implementations will
 	 * simply close it then.
diff --git a/src/player/Control.cxx b/src/player/Control.cxx
index db2537a33..87620fc90 100644
--- a/src/player/Control.cxx
+++ b/src/player/Control.cxx
@@ -21,6 +21,7 @@
 #include "Control.hxx"
 #include "Idle.hxx"
 #include "DetachedSong.hxx"
+#include "output/MultipleOutputs.hxx"
 
 #include <algorithm>
 
@@ -46,6 +47,18 @@ PlayerControl::~PlayerControl()
 	delete tagged_song;
 }
 
+bool
+PlayerControl::WaitOutputConsumed(unsigned threshold)
+{
+	bool result = outputs.Check() < threshold;
+	if (!result && command == PlayerCommand::NONE) {
+		Wait();
+		result = outputs.Check() < threshold;
+	}
+
+	return result;
+}
+
 void
 PlayerControl::Play(DetachedSong *song)
 {
diff --git a/src/player/Control.hxx b/src/player/Control.hxx
index ac0d53800..175677e4a 100644
--- a/src/player/Control.hxx
+++ b/src/player/Control.hxx
@@ -280,6 +280,23 @@ struct PlayerControl {
 		CommandFinished();
 	}
 
+	/**
+	 * Checks if the size of the #MusicPipe is below the #threshold.  If
+	 * not, it attempts to synchronize with all output threads, and waits
+	 * until another #MusicChunk is finished.
+	 *
+	 * Caller must lock the mutex.
+	 *
+	 * @param threshold the maximum number of chunks in the pipe
+	 * @return true if there are less than #threshold chunks in the pipe
+	 */
+	bool WaitOutputConsumed(unsigned threshold);
+
+	bool LockWaitOutputConsumed(unsigned threshold) {
+		const ScopeLock protect(mutex);
+		return WaitOutputConsumed(threshold);
+	}
+
 private:
 	/**
 	 * Wait for the command to be finished by the player thread.
diff --git a/src/player/Thread.cxx b/src/player/Thread.cxx
index 564192dd4..564425f3b 100644
--- a/src/player/Thread.cxx
+++ b/src/player/Thread.cxx
@@ -500,7 +500,7 @@ Player::CheckDecoderStartup()
 		pc.Unlock();
 
 		if (output_open &&
-		    !pc.outputs.Wait(pc, 1))
+		    !pc.LockWaitOutputConsumed(1))
 			/* the output devices havn't finished playing
 			   all chunks yet - wait for that */
 			return true;
@@ -813,7 +813,7 @@ play_chunk(PlayerControl &pc,
 inline bool
 Player::PlayNextChunk()
 {
-	if (!pc.outputs.Wait(pc, 64))
+	if (!pc.LockWaitOutputConsumed(64))
 		/* the output pipe is still large enough, don't send
 		   another chunk */
 		return true;