Index: media/remoting/remoting_source_impl.cc |
diff --git a/media/remoting/remoting_source_impl.cc b/media/remoting/remoting_source_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..eb0dcf6cb9c0526f9f16fbf3686035226ca3c4ba |
--- /dev/null |
+++ b/media/remoting/remoting_source_impl.cc |
@@ -0,0 +1,172 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/remoting/remoting_source_impl.h" |
+ |
+#include "base/bind.h" |
+#include "base/logging.h" |
+ |
+namespace media { |
+ |
+RemotingSourceImpl::RemotingSourceImpl( |
+ mojom::RemotingSourceRequest source_request, |
+ mojom::RemoterPtr remoter) |
+ : binding_(this, std::move(source_request)), remoter_(std::move(remoter)) {} |
+ |
+RemotingSourceImpl::~RemotingSourceImpl() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (!clients_.empty()) { |
+ Shutdown(); |
+ clients_.clear(); |
+ } |
+} |
+ |
+void RemotingSourceImpl::OnSinkAvailable() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (state_ == RemotingSessionState::SESSION_UNAVAILABLE) |
+ UpdateAndNotifyState(RemotingSessionState::SESSION_CAN_START); |
+} |
+ |
+void RemotingSourceImpl::OnSinkGone() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (state_ == RemotingSessionState::SESSION_PERMANENTLY_STOPPED) |
+ return; |
+ if (state_ == RemotingSessionState::SESSION_CAN_START) { |
+ UpdateAndNotifyState(RemotingSessionState::SESSION_UNAVAILABLE); |
+ return; |
+ } |
+ if (state_ == RemotingSessionState::SESSION_STARTED || |
+ state_ == RemotingSessionState::SESSION_STARTING) { |
+ VLOG(1) << "Sink is gone in a remoting session."; |
+ // Remoting is being stopped by Remoter. |
+ UpdateAndNotifyState(RemotingSessionState::SESSION_STOPPING); |
+ } |
+} |
+ |
+void RemotingSourceImpl::OnStarted() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ VLOG(1) << "Remoting started successively."; |
+ if (clients_.empty() || |
+ state_ == RemotingSessionState::SESSION_PERMANENTLY_STOPPED || |
+ state_ == RemotingSessionState::SESSION_STOPPING) { |
+ for (Client* client : clients_) |
+ client->OnStarted(false); |
+ return; |
+ } |
+ for (Client* client : clients_) |
+ client->OnStarted(true); |
xhwang
2016/11/01 08:21:29
Actually you notify all clients, so the comment is
xjz
2016/11/01 21:55:53
In general, no. Only when there are requests from
|
+ state_ = RemotingSessionState::SESSION_STARTED; |
+} |
+ |
+void RemotingSourceImpl::OnStartFailed(mojom::RemotingStartFailReason reason) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ VLOG(1) << "Failed to start remoting:" << reason; |
+ for (Client* client : clients_) |
+ client->OnStarted(false); |
+ if (state_ == RemotingSessionState::SESSION_PERMANENTLY_STOPPED) |
+ return; |
+ state_ = RemotingSessionState::SESSION_UNAVAILABLE; |
+} |
+ |
+void RemotingSourceImpl::OnStopped(mojom::RemotingStopReason reason) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ VLOG(1) << "Remoting stopped: " << reason; |
+ if (state_ == RemotingSessionState::SESSION_PERMANENTLY_STOPPED) |
+ return; |
+ RemotingSessionState state = RemotingSessionState::SESSION_UNAVAILABLE; |
+ UpdateAndNotifyState(state); |
+} |
+ |
+void RemotingSourceImpl::OnMessageFromSink( |
+ const std::vector<uint8_t>& message) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ // TODO(xjz): Merge with Eric's CL to handle the RPC messages here. |
+ NOTIMPLEMENTED(); |
+} |
+ |
+void RemotingSourceImpl::UpdateAndNotifyState(RemotingSessionState state) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (state_ == state) |
+ return; |
+ state_ = state; |
+ for (Client* client : clients_) |
+ client->OnSessionStateChanged(); |
+} |
+ |
+void RemotingSourceImpl::StartRemoting(Client* client) { |
+ DCHECK(std::find(clients_.begin(), clients_.end(), client) != clients_.end()); |
+ |
+ switch (state_) { |
+ case SESSION_CAN_START: |
+ remoter_->Start(); |
+ UpdateAndNotifyState(RemotingSessionState::SESSION_STARTING); |
+ break; |
+ case SESSION_STARTING: |
+ break; |
+ case SESSION_STARTED: |
+ client->OnStarted(true); |
+ break; |
+ case SESSION_STOPPING: |
+ case SESSION_UNAVAILABLE: |
+ case SESSION_PERMANENTLY_STOPPED: |
+ client->OnStarted(false); |
xhwang
2016/11/01 08:21:29
hmm, now I see why you have |client|...
Does it m
xjz
2016/11/01 21:55:53
That may make the switching logic more complicate.
|
+ break; |
+ } |
+} |
+ |
+void RemotingSourceImpl::StopRemoting(Client* client) { |
+ DCHECK(std::find(clients_.begin(), clients_.end(), client) != clients_.end()); |
+ |
+ VLOG(1) << "RemotingSourceImpl::StopRemoting: " << state_; |
+ |
+ if (state_ != RemotingSessionState::SESSION_STARTING && |
+ state_ != RemotingSessionState::SESSION_STARTED) |
+ return; |
+ |
+ remoter_->Stop(mojom::RemotingStopReason::LOCAL_PLAYBACK); |
+ UpdateAndNotifyState(RemotingSessionState::SESSION_STOPPING); |
+} |
+ |
+void RemotingSourceImpl::AddClient(Client* client) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (std::find(clients_.begin(), clients_.end(), client) != clients_.end()) |
+ return; |
xhwang
2016/11/01 08:21:29
If this happens, it'll be a programming error... D
xjz
2016/11/01 21:55:53
Done.
|
+ clients_.push_back(client); |
+ client->OnSessionStateChanged(); |
+} |
+ |
+void RemotingSourceImpl::RemoveClient(Client* client) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ auto it = std::find(clients_.begin(), clients_.end(), client); |
+ if (it == clients_.end()) |
+ return; |
xhwang
2016/11/01 08:21:29
ditto, DCHECK?
xjz
2016/11/01 21:55:53
Done.
|
+ |
+ clients_.erase(it); |
+ if (clients_.empty() && (state_ == RemotingSessionState::SESSION_STARTED || |
+ state_ == RemotingSessionState::SESSION_STARTING)) { |
+ remoter_->Stop(mojom::RemotingStopReason::SOURCE_GONE); |
+ state_ = RemotingSessionState::SESSION_STOPPING; |
+ } |
+} |
+ |
+void RemotingSourceImpl::Shutdown() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ |
+ if (state_ == RemotingSessionState::SESSION_STARTED || |
+ state_ == RemotingSessionState::SESSION_STARTING) |
+ remoter_->Stop(mojom::RemotingStopReason::UNEXPECTED_FAILURE); |
+ UpdateAndNotifyState(RemotingSessionState::SESSION_PERMANENTLY_STOPPED); |
+} |
+ |
+} // namespace media |