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
21namespace polo {
22namespace pairing {
23namespace message {
24
25ConfigurationMessage::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
33const encoding::EncodingOption& ConfigurationMessage::encoding() const {
34  return encoding_;
35}
36
37OptionsMessage::ProtocolRole ConfigurationMessage::client_role() const {
38  return client_role_;
39}
40
41std::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
48ConfigurationMessage* 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