Chromium Code Reviews| 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 |