OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/ui/webui/media_router/query_result_manager.h" | |
6 | |
7 #include <unordered_set> | |
8 | |
9 #include "base/stl_util.h" | |
10 #include "chrome/browser/media/router/media_router.h" | |
11 #include "chrome/browser/media/router/media_sinks_observer.h" | |
12 | |
13 namespace media_router { | |
14 | |
15 // MediaSinkObserver that propagates results back to |result_manager|. | |
16 // An instance of this class is associated with each registered MediaCastMode. | |
17 class CastModeMediaSinksObserver : public MediaSinksObserver { | |
18 public: | |
19 CastModeMediaSinksObserver(MediaCastMode cast_mode, | |
20 const MediaSource& source, | |
21 MediaRouter* router, | |
22 QueryResultManager* result_manager) | |
23 : MediaSinksObserver(router, source), | |
24 cast_mode_(cast_mode), | |
25 result_manager_(result_manager) { | |
26 DCHECK(result_manager); | |
27 } | |
28 | |
29 ~CastModeMediaSinksObserver() override {} | |
30 | |
31 // MediaSinksObserver | |
32 void OnSinksReceived(const std::vector<MediaSink>& result) override { | |
33 latest_sink_ids_.clear(); | |
34 for (const MediaSink& sink : result) { | |
35 latest_sink_ids_.push_back(sink.id()); | |
36 } | |
37 result_manager_->UpdateWithSinksQueryResult(cast_mode_, result); | |
38 result_manager_->NotifyOnResultsUpdated(); | |
39 } | |
40 | |
41 // Returns the most recent sink IDs that were passed to |OnSinksReceived|. | |
42 void GetLatestSinkIds(std::vector<MediaSinkId>* sink_ids) const { | |
43 DCHECK(sink_ids); | |
44 *sink_ids = latest_sink_ids_; | |
45 } | |
46 | |
47 MediaCastMode cast_mode() const { return cast_mode_; } | |
48 | |
49 private: | |
50 MediaCastMode cast_mode_; | |
51 std::vector<MediaSinkId> latest_sink_ids_; | |
52 QueryResultManager* result_manager_; | |
53 }; | |
54 | |
55 QueryResultManager::QueryResultManager(MediaRouter* router) : router_(router) { | |
56 DCHECK(router_); | |
57 } | |
58 | |
59 QueryResultManager::~QueryResultManager() { | |
60 DCHECK(thread_checker_.CalledOnValidThread()); | |
61 } | |
62 | |
63 void QueryResultManager::AddObserver(Observer* observer) { | |
64 DCHECK(thread_checker_.CalledOnValidThread()); | |
65 DCHECK(observer); | |
66 observers_.AddObserver(observer); | |
67 } | |
68 | |
69 void QueryResultManager::RemoveObserver(Observer* observer) { | |
70 DCHECK(thread_checker_.CalledOnValidThread()); | |
71 DCHECK(observer); | |
72 observers_.RemoveObserver(observer); | |
73 } | |
74 | |
75 void QueryResultManager::StartSinksQuery(MediaCastMode cast_mode, | |
76 const MediaSource& source) { | |
77 DCHECK(thread_checker_.CalledOnValidThread()); | |
78 if (source.Empty()) { | |
79 LOG(WARNING) << "StartSinksQuery called with empty source for " | |
80 << cast_mode; | |
81 return; | |
82 } | |
83 | |
84 SetSourceForCastMode(cast_mode, source); | |
85 RemoveObserverForCastMode(cast_mode); | |
86 UpdateWithSinksQueryResult(cast_mode, std::vector<MediaSink>()); | |
87 | |
88 linked_ptr<CastModeMediaSinksObserver> observer( | |
89 new CastModeMediaSinksObserver(cast_mode, source, router_, this)); | |
90 auto result = sinks_observers_.insert(std::make_pair(cast_mode, observer)); | |
91 DCHECK(result.second); | |
92 NotifyOnResultsUpdated(); | |
93 } | |
94 | |
95 void QueryResultManager::StopSinksQuery(MediaCastMode cast_mode) { | |
96 DCHECK(thread_checker_.CalledOnValidThread()); | |
97 RemoveObserverForCastMode(cast_mode); | |
98 SetSourceForCastMode(cast_mode, MediaSource()); | |
99 UpdateWithSinksQueryResult(cast_mode, std::vector<MediaSink>()); | |
100 NotifyOnResultsUpdated(); | |
101 } | |
102 | |
103 void QueryResultManager::SetSourceForCastMode( | |
104 MediaCastMode cast_mode, const MediaSource& source) { | |
105 DCHECK(thread_checker_.CalledOnValidThread()); | |
106 cast_mode_sources_[cast_mode] = source; | |
107 } | |
108 | |
109 void QueryResultManager::RemoveObserverForCastMode(MediaCastMode cast_mode) { | |
110 auto observers_it = sinks_observers_.find(cast_mode); | |
111 if (observers_it != sinks_observers_.end()) | |
112 sinks_observers_.erase(observers_it); | |
113 } | |
114 | |
115 bool QueryResultManager::IsValid(const MediaSinkWithCastModes& entry) const { | |
116 return !entry.cast_modes.empty(); | |
117 } | |
118 | |
119 void QueryResultManager::UpdateWithSinksQueryResult( | |
120 MediaCastMode cast_mode, | |
121 const std::vector<MediaSink>& result) { | |
122 std::unordered_set<MediaSinkId> result_sink_ids; | |
123 for (const MediaSink& sink : result) | |
124 result_sink_ids.insert(sink.id()); | |
125 | |
126 // (1) Iterate through current sink set, remove cast mode from those that | |
127 // do not appear in latest result. | |
128 for (auto it = all_sinks_.begin(); it != all_sinks_.end(); /*no-op*/) { | |
129 if (!ContainsKey(result_sink_ids, it->first)) { | |
130 it->second.cast_modes.erase(cast_mode); | |
131 } | |
132 if (!IsValid(it->second)) { | |
133 all_sinks_.erase(it++); | |
134 } else { | |
135 ++it; | |
136 } | |
137 } | |
138 | |
139 // (2) Add / update sinks with latest result. | |
140 for (const MediaSink& sink : result) { | |
141 auto result = | |
142 all_sinks_.insert(std::make_pair(sink.id(), | |
143 MediaSinkWithCastModes(sink))); | |
144 if (!result.second) | |
145 result.first->second.sink = sink; | |
Bernhard Bauer
2015/05/12 09:34:34
Thinking about this a bit more, even if we have no
mark a. foltz
2015/05/12 19:05:26
If there's an existing sink in all_sinks_ it's not
Bernhard Bauer
2015/05/13 08:04:24
Okay, makes sense.
| |
146 result.first->second.cast_modes.insert(cast_mode); | |
147 } | |
148 } | |
149 | |
150 void QueryResultManager::GetSupportedCastModes(CastModeSet* cast_modes) const { | |
151 DCHECK(cast_modes); | |
152 cast_modes->clear(); | |
153 for (const auto& observer_pair : sinks_observers_) { | |
154 cast_modes->insert(observer_pair.first); | |
155 } | |
156 } | |
157 | |
158 MediaSource QueryResultManager::GetSourceForCastMode( | |
159 MediaCastMode cast_mode) const { | |
160 DCHECK(thread_checker_.CalledOnValidThread()); | |
161 auto source_it = cast_mode_sources_.find(cast_mode); | |
162 if (source_it == cast_mode_sources_.end()) | |
163 return MediaSource(); | |
164 return source_it->second; | |
165 } | |
166 | |
167 void QueryResultManager::NotifyOnResultsUpdated() { | |
168 std::vector<MediaSinkWithCastModes> sinks; | |
169 for (const auto& sink_pair : all_sinks_) { | |
170 sinks.push_back(sink_pair.second); | |
171 } | |
172 FOR_EACH_OBSERVER(QueryResultManager::Observer, observers_, | |
173 OnResultsUpdated(sinks)); | |
174 } | |
175 | |
176 } // namespace media_router | |
OLD | NEW |