1 // Copyright 2012 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "polo/pairing/message/configurationmessage.h"
16 
17 #include <algorithm>
18 #include <sstream>
19 #include <string>
20 
21 namespace polo {
22 namespace pairing {
23 namespace message {
24 
ConfigurationMessage(const encoding::EncodingOption & encoding,message::OptionsMessage::ProtocolRole client_role)25 ConfigurationMessage::ConfigurationMessage(
26     const encoding::EncodingOption& encoding,
27     message::OptionsMessage::ProtocolRole client_role)
28     : PoloMessage(PoloMessage::kConfiguration),
29       encoding_(encoding),
30       client_role_(client_role) {
31 }
32 
encoding() const33 const encoding::EncodingOption& ConfigurationMessage::encoding() const {
34   return encoding_;
35 }
36 
client_role() const37 OptionsMessage::ProtocolRole ConfigurationMessage::client_role() const {
38   return client_role_;
39 }
40 
ToString() const41 std::string ConfigurationMessage::ToString() const {
42   std::ostringstream ss;
43   ss << "[ConfigurationMessage encoding=" << encoding_.ToString()
44       << ", client_role=" << client_role_ << "]";
45   return ss.str();
46 }
47 
GetBestConfiguration(const OptionsMessage & local_options,const OptionsMessage & peer_options)48 ConfigurationMessage* ConfigurationMessage::GetBestConfiguration(
49     const OptionsMessage &local_options,
50     const OptionsMessage &peer_options) {
51   // Compute the intersection of the available encodings. The sets use the
52   // 'less' comparator so they are ordered using EncodingOption's less-than
53   // operator.
54   encoding::EncodingOption::EncodingSet common_outputs;
55   std::insert_iterator<encoding::EncodingOption::EncodingSet> outputs_inserter(
56       common_outputs,
57       common_outputs.begin());
58   set_intersection(local_options.output_encodings().begin(),
59                    local_options.output_encodings().end(),
60                    peer_options.output_encodings().begin(),
61                    peer_options.output_encodings().end(),
62                    outputs_inserter,
63                    encoding::EncodingOption::EncodingOptionComparator());
64 
65   encoding::EncodingOption::EncodingSet common_inputs;
66   std::insert_iterator<encoding::EncodingOption::EncodingSet> inputs_inserter(
67       common_inputs,
68       common_inputs.begin());
69   set_intersection(local_options.input_encodings().begin(),
70                    local_options.input_encodings().end(),
71                    peer_options.input_encodings().begin(),
72                    peer_options.input_encodings().end(),
73                    inputs_inserter,
74                    encoding::EncodingOption::EncodingOptionComparator());
75 
76   if (common_outputs.size() == 0 || common_inputs.size() == 0) {
77     return NULL;
78   }
79 
80   const encoding::EncodingOption* best_input = NULL;
81   const encoding::EncodingOption* best_output = NULL;
82 
83   // Use the last option as the best encoding since that one will be the most
84   // complex based on the sorting order.
85   if (common_outputs.size() > 0) {
86     best_output = &*(--common_outputs.end());
87   }
88 
89   if (common_inputs.size() > 0) {
90     best_input = &*(--common_inputs.end());
91   }
92 
93   if (local_options.protocol_role_preference()
94       == OptionsMessage::kDisplayDevice) {
95     if (best_input) {
96       return new ConfigurationMessage(*best_input,
97                                       OptionsMessage::kDisplayDevice);
98     } else {
99       return new ConfigurationMessage(*best_output,
100                                       OptionsMessage::kInputDevice);
101     }
102   } else {
103     if (best_output) {
104       return new ConfigurationMessage(*best_output,
105                                       OptionsMessage::kInputDevice);
106     } else {
107       return new ConfigurationMessage(*best_input,
108                                       OptionsMessage::kDisplayDevice);
109     }
110   }
111 }
112 
113 }  // namespace message
114 }  // namespace pairing
115 }  // namespace polo
116