Merge lp:~morphis/aethercast/input-provider-support into lp:aethercast
- input-provider-support
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~morphis/aethercast/input-provider-support |
Merge into: | lp:aethercast |
Diff against target: |
1174 lines (+872/-9) 26 files modified
CMakeLists.txt (+1/-0) data/org.aethercast.xml (+15/-0) docs/input-provider.txt (+2/-2) src/CMakeLists.txt (+5/-0) src/mcs/dbus_types.h (+31/-0) src/mcs/forwardingmiracastcontroller.cpp (+12/-0) src/mcs/forwardingmiracastcontroller.h (+4/-0) src/mcs/inputeventchannel.cpp (+123/-0) src/mcs/inputeventchannel.h (+74/-0) src/mcs/inputprovider.cpp (+18/-0) src/mcs/inputprovider.h (+46/-0) src/mcs/inputproviderstub.cpp (+137/-0) src/mcs/inputproviderstub.h (+67/-0) src/mcs/miracastcontroller.cpp (+16/-0) src/mcs/miracastcontroller.h (+5/-0) src/mcs/miracastcontrollerskeleton.cpp (+66/-3) src/mcs/miracastcontrollerskeleton.h (+8/-4) src/mcs/miracastservice.cpp (+16/-0) src/mcs/miracastservice.h (+7/-0) src/mcs/withdelegate.cpp (+16/-0) src/mcs/withdelegate.h (+37/-0) tests/mcs/CMakeLists.txt (+8/-0) tests/mcs/forwardingmiracastcontroller_tests.cpp (+10/-0) tests/mcs/inputeventchannel_tests.cpp (+66/-0) tests/mcs/miracastcontrollerskeleton_tests.cpp (+4/-0) tests/mcs/miracastservice_tests.cpp (+78/-0) |
To merge this branch: | bzr merge lp:~morphis/aethercast/input-provider-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Simon Fels | Needs Fixing | ||
Review via email: mp+280746@code.launchpad.net |
Commit message
Description of the change
Add input provider support
- 119. By Simon Fels
-
Merge trunk
- 120. By Simon Fels
-
Fix problems after merge
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:120
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 121. By Simon Fels
-
Wrap input provider into service and add channel implementation + tests
- 122. By Simon Fels
-
Fix ForwardingMirac
astController tests
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:122
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 123. By Simon Fels
-
Correct InputEventChannel unit tests to pass fully
- 124. By Simon Fels
-
Process real input events
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:124
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 125. By Simon Fels
-
Properly register input provider
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:125
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
- 125. By Simon Fels
-
Properly register input provider
- 124. By Simon Fels
-
Process real input events
- 123. By Simon Fels
-
Correct InputEventChannel unit tests to pass fully
- 122. By Simon Fels
-
Fix ForwardingMirac
astController tests - 121. By Simon Fels
-
Wrap input provider into service and add channel implementation + tests
- 120. By Simon Fels
-
Fix problems after merge
- 119. By Simon Fels
-
Merge trunk
- 118. By Simon Fels
-
First part of input provider infrastructure
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-12-10 06:47:03 +0000 |
3 | +++ CMakeLists.txt 2015-12-18 16:38:21 +0000 |
4 | @@ -64,6 +64,7 @@ |
5 | pkg_check_modules(GST REQUIRED gstreamer-1.0) |
6 | pkg_check_modules(WDS REQUIRED wds) |
7 | pkg_check_modules(READLINE readline) |
8 | + |
9 | # Build with system gmock and embedded gtest |
10 | set (GMOCK_INCLUDE_DIR "/usr/include/gmock/include" CACHE PATH "gmock source include directory") |
11 | set (GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory") |
12 | |
13 | === modified file 'data/org.aethercast.xml' |
14 | --- data/org.aethercast.xml 2015-12-10 17:13:50 +0000 |
15 | +++ data/org.aethercast.xml 2015-12-18 16:38:21 +0000 |
16 | @@ -9,10 +9,25 @@ |
17 | <arg name="path" type="o" direction="in"/> |
18 | </method> |
19 | <method name="Scan"/> |
20 | + <method name="RegisterInputProvider"> |
21 | + <arg name="path" type="o" direction="in"/> |
22 | + <arg name="options" type="a{sv}" direction="in"/> |
23 | + </method> |
24 | + <method name="UnregisterInputProvider"> |
25 | + <arg name="path" type="o" direction="in"/> |
26 | + </method> |
27 | <property name="State" type="s" access="read"/> |
28 | <property name="Capabilities" type="as" access="read"/> |
29 | <property name="Scanning" type="b" access="read"/> |
30 | </interface> |
31 | + <interface name="org.aethercast.InputProvider"> |
32 | + <method name="NewConnection"> |
33 | + <arg name="fd" type="h" direction="in"/> |
34 | + <arg name="options" type="a{sv}" direction="in"/> |
35 | + </method> |
36 | + <method name="RequestDisconnection"/> |
37 | + <property name="cursor" type="s" access="read"/> |
38 | + </interface> |
39 | <interface name="org.aethercast.Device"> |
40 | <method name="Connect"> |
41 | <arg name="role" type="s" direction="in"/> |
42 | |
43 | === modified file 'docs/input-provider.txt' |
44 | --- docs/input-provider.txt 2015-12-16 11:54:08 +0000 |
45 | +++ docs/input-provider.txt 2015-12-18 16:38:21 +0000 |
46 | @@ -43,7 +43,7 @@ |
47 | This method gets called when the input provider is |
48 | unregistered and can be used to perform cleanup tasks. |
49 | |
50 | - void NewConnection(object device, fd, dict options) |
51 | + void NewConnection(fd, dict options) |
52 | |
53 | This methods gets called when a connection to a remote |
54 | display is established. |
55 | @@ -51,7 +51,7 @@ |
56 | Possible errors: org.aethercast.Error.Rejected |
57 | org.aethercast.Error.Canceled |
58 | |
59 | - void RequestDisconnection(object device) |
60 | + void RequestDisconnection() |
61 | |
62 | This methods gets called when a device gets disconnected. |
63 | |
64 | |
65 | === modified file 'src/CMakeLists.txt' |
66 | --- src/CMakeLists.txt 2015-12-12 20:22:35 +0000 |
67 | +++ src/CMakeLists.txt 2015-12-18 16:38:21 +0000 |
68 | @@ -17,9 +17,12 @@ |
69 | mcs/keep_alive.h |
70 | mcs/mac_address.h |
71 | mcs/types.h |
72 | + mcs/dbus_types.h |
73 | ) |
74 | |
75 | set(SOURCES |
76 | + mcs/withdelegate.cpp |
77 | + mcs/inputeventchannel.cpp |
78 | mcs/utils.cpp |
79 | mcs/networkutils.cpp |
80 | mcs/mediamanagerfactory.cpp |
81 | @@ -37,10 +40,12 @@ |
82 | mcs/networkmanager.cpp |
83 | mcs/networkmanagerfactory.cpp |
84 | mcs/networkdevice.cpp |
85 | + mcs/inputprovider.cpp |
86 | |
87 | ${CMAKE_CURRENT_BINARY_DIR}/mcs/aethercastinterface.c |
88 | mcs/dbushelpers.cpp |
89 | mcs/networkdeviceadapter.cpp |
90 | + mcs/inputproviderstub.cpp |
91 | |
92 | wpa/gdhcp/common.c |
93 | wpa/gdhcp/ipv4ll.c |
94 | |
95 | === added file 'src/mcs/dbus_types.h' |
96 | --- src/mcs/dbus_types.h 1970-01-01 00:00:00 +0000 |
97 | +++ src/mcs/dbus_types.h 2015-12-18 16:38:21 +0000 |
98 | @@ -0,0 +1,31 @@ |
99 | +/* |
100 | + * Copyright (C) 2015 Canonical, Ltd. |
101 | + * |
102 | + * This program is free software: you can redistribute it and/or modify it |
103 | + * under the terms of the GNU General Public License version 3, as published |
104 | + * by the Free Software Foundation. |
105 | + * |
106 | + * This program is distributed in the hope that it will be useful, but |
107 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
108 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
109 | + * PURPOSE. See the GNU General Public License for more details. |
110 | + * |
111 | + * You should have received a copy of the GNU General Public License along |
112 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
113 | + * |
114 | + */ |
115 | + |
116 | +#ifndef DBUS_TYPES_H_ |
117 | +#define DBUS_TYPES_H_ |
118 | + |
119 | +#include <string> |
120 | + |
121 | +namespace mcs { |
122 | +namespace dbus { |
123 | + |
124 | +typedef std::string ObjectPath; |
125 | + |
126 | +} // namespace dbus |
127 | +} // namespace mcs |
128 | + |
129 | +#endif |
130 | |
131 | === modified file 'src/mcs/forwardingmiracastcontroller.cpp' |
132 | --- src/mcs/forwardingmiracastcontroller.cpp 2015-12-11 22:02:52 +0000 |
133 | +++ src/mcs/forwardingmiracastcontroller.cpp 2015-12-18 16:38:21 +0000 |
134 | @@ -57,4 +57,16 @@ |
135 | bool ForwardingMiracastController::Scanning() const { |
136 | return fwd_->Scanning(); |
137 | } |
138 | + |
139 | +bool ForwardingMiracastController::HasInputProvider() const { |
140 | + return fwd_->HasInputProvider(); |
141 | +} |
142 | + |
143 | +void ForwardingMiracastController::SetInputProvider(const InputProvider::Ptr &provider) { |
144 | + fwd_->SetInputProvider(provider); |
145 | +} |
146 | + |
147 | +void ForwardingMiracastController::ResetInputProvider() { |
148 | + fwd_->ResetInputProvider(); |
149 | +} |
150 | } |
151 | |
152 | === modified file 'src/mcs/forwardingmiracastcontroller.h' |
153 | --- src/mcs/forwardingmiracastcontroller.h 2015-12-11 22:02:52 +0000 |
154 | +++ src/mcs/forwardingmiracastcontroller.h 2015-12-18 16:38:21 +0000 |
155 | @@ -38,6 +38,10 @@ |
156 | virtual std::vector<NetworkDeviceRole> SupportedRoles() const override; |
157 | virtual bool Scanning() const override; |
158 | |
159 | + virtual bool HasInputProvider() const; |
160 | + virtual void SetInputProvider(const InputProvider::Ptr &provider); |
161 | + virtual void ResetInputProvider(); |
162 | + |
163 | private: |
164 | MiracastController::Ptr fwd_; |
165 | }; |
166 | |
167 | === added file 'src/mcs/inputeventchannel.cpp' |
168 | --- src/mcs/inputeventchannel.cpp 1970-01-01 00:00:00 +0000 |
169 | +++ src/mcs/inputeventchannel.cpp 2015-12-18 16:38:21 +0000 |
170 | @@ -0,0 +1,123 @@ |
171 | +/* |
172 | + * Copyright (C) 2015 Canonical, Ltd. |
173 | + * |
174 | + * This program is free software: you can redistribute it and/or modify it |
175 | + * under the terms of the GNU General Public License version 3, as published |
176 | + * by the Free Software Foundation. |
177 | + * |
178 | + * This program is distributed in the hope that it will be useful, but |
179 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
180 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
181 | + * PURPOSE. See the GNU General Public License for more details. |
182 | + * |
183 | + * You should have received a copy of the GNU General Public License along |
184 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
185 | + * |
186 | + */ |
187 | + |
188 | +#include <unistd.h> |
189 | +#include <sys/types.h> |
190 | +#include <sys/socket.h> |
191 | +#include <fcntl.h> |
192 | +#include <linux/input.h> |
193 | + |
194 | +#include "inputeventchannel.h" |
195 | +#include "keep_alive.h" |
196 | +#include "logger.h" |
197 | + |
198 | +namespace mcs { |
199 | + |
200 | +std::ostream& operator<<(std::ostream& out, const InputEvent& e) |
201 | +{ |
202 | + return out << "[" |
203 | + << e.when.count() << " " |
204 | + << e.type << " " |
205 | + << e.code << " " |
206 | + << e.value |
207 | + << "]"; |
208 | +} |
209 | + |
210 | +InputEventChannel::InputEventChannel() : |
211 | + local_fd_(0), |
212 | + remote_fd_(0), |
213 | + channel_(nullptr), |
214 | + channel_watch_(0) { |
215 | +} |
216 | + |
217 | +InputEventChannel::~InputEventChannel() { |
218 | + if (channel_watch_ > 0) |
219 | + g_source_remove(channel_watch_); |
220 | + |
221 | + if (channel_) |
222 | + g_io_channel_unref(channel_); |
223 | + |
224 | + if (local_fd_ > 0) |
225 | + ::close(local_fd_); |
226 | + |
227 | + if (remote_fd_ > 0) |
228 | + ::close(remote_fd_); |
229 | +} |
230 | + |
231 | +std::shared_ptr<InputEventChannel> InputEventChannel::Create() { |
232 | + return std::shared_ptr<InputEventChannel>(new InputEventChannel)->FinalizeConstruction(); |
233 | +} |
234 | + |
235 | +InputEvent InputEventChannel::ReadNextEvent() { |
236 | + struct input_event ev; |
237 | + |
238 | + ssize_t bytes_read = ::read(local_fd_, &ev, sizeof(ev)); |
239 | + if (bytes_read <= 0) |
240 | + return InputEvent{}; |
241 | + |
242 | + return InputEvent{std::chrono::milliseconds(0), ev.type, ev.code, ev.value}; |
243 | +} |
244 | + |
245 | +gboolean InputEventChannel::OnActivity(GIOChannel *channel, GIOCondition condition, gpointer user_data) { |
246 | + auto inst = static_cast<WeakKeepAlive<InputEventChannel>*>(user_data)->GetInstance().lock(); |
247 | + |
248 | + if (condition & G_IO_HUP) { |
249 | + if (auto sp = inst->delegate_.lock()) |
250 | + sp->OnChannelClosed(); |
251 | + |
252 | + return TRUE; |
253 | + } |
254 | + |
255 | + auto event = inst->ReadNextEvent(); |
256 | + |
257 | + if (auto sp = inst->delegate_.lock()) |
258 | + sp->OnEvent(event); |
259 | + |
260 | + return TRUE; |
261 | +} |
262 | + |
263 | +std::shared_ptr<InputEventChannel> InputEventChannel::FinalizeConstruction() { |
264 | + auto sp = shared_from_this(); |
265 | + |
266 | + int endpoints[2] = {0, 0}; |
267 | + |
268 | + if (::socketpair(AF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0, endpoints) < 0) { |
269 | + ERROR("Failed to create socket pair"); |
270 | + return sp; |
271 | + } |
272 | + |
273 | + local_fd_ = endpoints[0]; |
274 | + remote_fd_ = endpoints[1]; |
275 | + |
276 | + channel_ = g_io_channel_unix_new(local_fd_); |
277 | + channel_watch_ = g_io_add_watch_full(channel_, 0, (GIOCondition) (G_IO_IN | G_IO_HUP | G_IO_ERR), |
278 | + &InputEventChannel::OnActivity, |
279 | + new WeakKeepAlive<InputEventChannel>{sp}, |
280 | + [](gpointer data) { delete static_cast<WeakKeepAlive<InputEventChannel>*>(data); }); |
281 | + if (channel_watch_ == 0) { |
282 | + ERROR("Failed to input channel watch"); |
283 | + return sp; |
284 | + } |
285 | + |
286 | + return sp; |
287 | +} |
288 | + |
289 | +int InputEventChannel::RemoteEndpoint() { |
290 | + return remote_fd_; |
291 | +} |
292 | + |
293 | +} // namespace mcs |
294 | |
295 | === added file 'src/mcs/inputeventchannel.h' |
296 | --- src/mcs/inputeventchannel.h 1970-01-01 00:00:00 +0000 |
297 | +++ src/mcs/inputeventchannel.h 2015-12-18 16:38:21 +0000 |
298 | @@ -0,0 +1,74 @@ |
299 | +/* |
300 | + * Copyright (C) 2015 Canonical, Ltd. |
301 | + * |
302 | + * This program is free software: you can redistribute it and/or modify it |
303 | + * under the terms of the GNU General Public License version 3, as published |
304 | + * by the Free Software Foundation. |
305 | + * |
306 | + * This program is distributed in the hope that it will be useful, but |
307 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
308 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
309 | + * PURPOSE. See the GNU General Public License for more details. |
310 | + * |
311 | + * You should have received a copy of the GNU General Public License along |
312 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
313 | + * |
314 | + */ |
315 | + |
316 | +#ifndef INPUTEVENTCHANNEL_H_ |
317 | +#define INPUTEVENTCHANNEL_H_ |
318 | + |
319 | +#include <glib.h> |
320 | + |
321 | +#include <memory> |
322 | +#include <chrono> |
323 | + |
324 | +#include "non_copyable.h" |
325 | +#include "withdelegate.h" |
326 | + |
327 | +namespace mcs { |
328 | + |
329 | +struct InputEvent { |
330 | + std::chrono::milliseconds when; |
331 | + std::uint16_t type; |
332 | + std::uint16_t code; |
333 | + std::uint32_t value; |
334 | +}; |
335 | + |
336 | +std::ostream& operator<<(std::ostream& out, const InputEvent& e); |
337 | + |
338 | +class InputEventChannelDelegate : public mcs::NonCopyable { |
339 | +public: |
340 | + virtual ~InputEventChannelDelegate() { } |
341 | + virtual void OnChannelClosed() = 0; |
342 | + virtual void OnEvent(const InputEvent &event) = 0; |
343 | +}; |
344 | + |
345 | +class InputEventChannel : public std::enable_shared_from_this<InputEventChannel>, |
346 | + public mcs::WithDelegate<InputEventChannelDelegate> { |
347 | +public: |
348 | + static std::shared_ptr<InputEventChannel> Create(); |
349 | + |
350 | + ~InputEventChannel(); |
351 | + |
352 | + int RemoteEndpoint(); |
353 | + |
354 | +private: |
355 | + InputEventChannel(); |
356 | + std::shared_ptr<InputEventChannel> FinalizeConstruction(); |
357 | + |
358 | + InputEvent ReadNextEvent(); |
359 | + |
360 | +private: |
361 | + static gboolean OnActivity(GIOChannel *channel, GIOCondition condition, gpointer user_data); |
362 | + |
363 | +private: |
364 | + int local_fd_; |
365 | + int remote_fd_; |
366 | + GIOChannel *channel_; |
367 | + guint channel_watch_; |
368 | +}; |
369 | + |
370 | +} // namespace mcs |
371 | + |
372 | +#endif |
373 | |
374 | === added file 'src/mcs/inputprovider.cpp' |
375 | --- src/mcs/inputprovider.cpp 1970-01-01 00:00:00 +0000 |
376 | +++ src/mcs/inputprovider.cpp 2015-12-18 16:38:21 +0000 |
377 | @@ -0,0 +1,18 @@ |
378 | +/* |
379 | + * Copyright (C) 2015 Canonical, Ltd. |
380 | + * |
381 | + * This program is free software: you can redistribute it and/or modify it |
382 | + * under the terms of the GNU General Public License version 3, as published |
383 | + * by the Free Software Foundation. |
384 | + * |
385 | + * This program is distributed in the hope that it will be useful, but |
386 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
387 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
388 | + * PURPOSE. See the GNU General Public License for more details. |
389 | + * |
390 | + * You should have received a copy of the GNU General Public License along |
391 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
392 | + * |
393 | + */ |
394 | + |
395 | +#include "inputprovider.h" |
396 | |
397 | === added file 'src/mcs/inputprovider.h' |
398 | --- src/mcs/inputprovider.h 1970-01-01 00:00:00 +0000 |
399 | +++ src/mcs/inputprovider.h 2015-12-18 16:38:21 +0000 |
400 | @@ -0,0 +1,46 @@ |
401 | +/* |
402 | + * Copyright (C) 2015 Canonical, Ltd. |
403 | + * |
404 | + * This program is free software: you can redistribute it and/or modify it |
405 | + * under the terms of the GNU General Public License version 3, as published |
406 | + * by the Free Software Foundation. |
407 | + * |
408 | + * This program is distributed in the hope that it will be useful, but |
409 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
410 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
411 | + * PURPOSE. See the GNU General Public License for more details. |
412 | + * |
413 | + * You should have received a copy of the GNU General Public License along |
414 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
415 | + * |
416 | + */ |
417 | + |
418 | +#ifndef INPUTPROVIDER_H_ |
419 | +#define INPUTPROVIDER_H_ |
420 | + |
421 | +#include <memory> |
422 | + |
423 | +#include "non_copyable.h" |
424 | +#include "withdelegate.h" |
425 | + |
426 | +namespace mcs { |
427 | + |
428 | +class InputProviderDelegate : public mcs::NonCopyable { |
429 | +public: |
430 | + virtual ~InputProviderDelegate() { } |
431 | + virtual void OnConnectedChanged() = 0; |
432 | +}; |
433 | + |
434 | +class InputProvider : public mcs::WithDelegate<InputProviderDelegate> { |
435 | +public: |
436 | + typedef std::shared_ptr<InputProvider> Ptr; |
437 | + |
438 | + virtual bool NewConnection(int fd) = 0; |
439 | + virtual void RequestDisconnection() = 0; |
440 | + |
441 | + virtual bool Connected() const = 0; |
442 | +}; |
443 | + |
444 | +} // namespace mcs |
445 | + |
446 | +#endif |
447 | |
448 | === added file 'src/mcs/inputproviderstub.cpp' |
449 | --- src/mcs/inputproviderstub.cpp 1970-01-01 00:00:00 +0000 |
450 | +++ src/mcs/inputproviderstub.cpp 2015-12-18 16:38:21 +0000 |
451 | @@ -0,0 +1,137 @@ |
452 | +/* |
453 | + * Copyright (C) 2015 Canonical, Ltd. |
454 | + * |
455 | + * This program is free software: you can redistribute it and/or modify it |
456 | + * under the terms of the GNU General Public License version 3, as published |
457 | + * by the Free Software Foundation. |
458 | + * |
459 | + * This program is distributed in the hope that it will be useful, but |
460 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
461 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
462 | + * PURPOSE. See the GNU General Public License for more details. |
463 | + * |
464 | + * You should have received a copy of the GNU General Public License along |
465 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
466 | + * |
467 | + */ |
468 | + |
469 | +#include <boost/concept_check.hpp> |
470 | + |
471 | +#include "inputproviderstub.h" |
472 | +#include "keep_alive.h" |
473 | +#include "logger.h" |
474 | + |
475 | +namespace mcs { |
476 | +namespace dbus { |
477 | + |
478 | +std::shared_ptr<InputProviderStub> InputProviderStub::Create(const SharedGObject<GDBusConnection> &connection, const ObjectPath &path) { |
479 | + return std::shared_ptr<InputProviderStub>(new InputProviderStub(path))->FinalizeConstruction(connection); |
480 | +} |
481 | + |
482 | +InputProviderStub::InputProviderStub(const ObjectPath &path) : |
483 | + path_(path), |
484 | + proxy_(nullptr), |
485 | + connected_(false) { |
486 | +} |
487 | + |
488 | +InputProviderStub::~InputProviderStub() { |
489 | +} |
490 | + |
491 | +void InputProviderStub::RequestDisconnection() { |
492 | + if (!connected_) |
493 | + return; |
494 | + |
495 | + auto sp = shared_from_this(); |
496 | + |
497 | + aethercast_interface_input_provider_call_request_disconnection(proxy_, |
498 | + nullptr, |
499 | + InputProviderStub::OnNewConnectionFinish, |
500 | + new SharedKeepAlive<InputProviderStub>{sp}); |
501 | +} |
502 | + |
503 | +void InputProviderStub::OnRequestDisconnectionFinish(GObject *object, GAsyncResult *res, gpointer user_data) { |
504 | + boost::ignore_unused_variable_warning(object); |
505 | + |
506 | + auto inst = static_cast<SharedKeepAlive<InputProviderStub>*>(user_data)->ShouldDie(); |
507 | + |
508 | + GError *error = nullptr; |
509 | + if (!aethercast_interface_input_provider_call_request_disconnection_finish(inst->proxy_, res, &error)) { |
510 | + ERROR("Failed to request disconnection of the input provider %s: %s", inst->path_, error->message); |
511 | + g_error_free(error); |
512 | + return; |
513 | + } |
514 | + |
515 | + inst->connected_ = false; |
516 | + |
517 | + if (auto sp = inst->delegate_.lock()) |
518 | + sp->OnConnectedChanged(); |
519 | +} |
520 | + |
521 | +bool InputProviderStub::NewConnection(int fd) { |
522 | + if (connected_) |
523 | + return false; |
524 | + |
525 | + auto sp = shared_from_this(); |
526 | + |
527 | + aethercast_interface_input_provider_call_new_connection(proxy_, |
528 | + g_variant_new_handle(fd), |
529 | + nullptr, // We don't have any options to provide yet |
530 | + nullptr, |
531 | + InputProviderStub::OnNewConnectionFinish, |
532 | + new SharedKeepAlive<InputProviderStub>{sp}); |
533 | + |
534 | + return true; |
535 | +} |
536 | + |
537 | +void InputProviderStub::OnNewConnectionFinish(GObject *object, GAsyncResult *res, gpointer user_data) { |
538 | + boost::ignore_unused_variable_warning(object); |
539 | + |
540 | + auto inst = static_cast<SharedKeepAlive<InputProviderStub>*>(user_data)->ShouldDie(); |
541 | + |
542 | + GError *error = nullptr; |
543 | + if (!aethercast_interface_input_provider_call_new_connection_finish(inst->proxy_, res, &error)) { |
544 | + ERROR("Failed to signal a new connection to the input provider %s: %s", inst->path_, error->message); |
545 | + g_error_free(error); |
546 | + return; |
547 | + } |
548 | + |
549 | + inst->connected_ = true; |
550 | + |
551 | + if (auto sp = inst->delegate_.lock()) |
552 | + sp->OnConnectedChanged(); |
553 | +} |
554 | + |
555 | +void InputProviderStub::OnProxyConnected(GObject *object, GAsyncResult *res, gpointer user_data) { |
556 | + boost::ignore_unused_variable_warning(object); |
557 | + |
558 | + auto inst = static_cast<SharedKeepAlive<InputProviderStub>*>(user_data)->ShouldDie(); |
559 | + |
560 | + GError *error = nullptr; |
561 | + inst->proxy_ = aethercast_interface_input_provider_proxy_new_finish(res, &error); |
562 | + if (!inst->proxy_) { |
563 | + ERROR("Failed to connect with input provider %s: %s", inst->path_, error->message); |
564 | + g_error_free(error); |
565 | + return; |
566 | + } |
567 | +} |
568 | + |
569 | +std::shared_ptr<InputProviderStub> InputProviderStub::FinalizeConstruction(const SharedGObject<GDBusConnection> &connection) { |
570 | + auto sp = shared_from_this(); |
571 | + |
572 | + aethercast_interface_input_provider_proxy_new(connection.get(), |
573 | + G_DBUS_PROXY_FLAGS_NONE, |
574 | + nullptr, |
575 | + path_.c_str(), |
576 | + nullptr, |
577 | + &InputProviderStub::OnProxyConnected, |
578 | + new SharedKeepAlive<InputProviderStub>{sp}); |
579 | + |
580 | + return sp; |
581 | +} |
582 | + |
583 | +bool InputProviderStub::Connected() const { |
584 | + return connected_; |
585 | +} |
586 | + |
587 | +} // namespace dbus |
588 | +} // namespace mcs |
589 | |
590 | === added file 'src/mcs/inputproviderstub.h' |
591 | --- src/mcs/inputproviderstub.h 1970-01-01 00:00:00 +0000 |
592 | +++ src/mcs/inputproviderstub.h 2015-12-18 16:38:21 +0000 |
593 | @@ -0,0 +1,67 @@ |
594 | +/* |
595 | + * Copyright (C) 2015 Canonical, Ltd. |
596 | + * |
597 | + * This program is free software: you can redistribute it and/or modify it |
598 | + * under the terms of the GNU General Public License version 3, as published |
599 | + * by the Free Software Foundation. |
600 | + * |
601 | + * This program is distributed in the hope that it will be useful, but |
602 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
603 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
604 | + * PURPOSE. See the GNU General Public License for more details. |
605 | + * |
606 | + * You should have received a copy of the GNU General Public License along |
607 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
608 | + * |
609 | + */ |
610 | + |
611 | +#ifndef INPUTPROVIDERSTUB_H_ |
612 | +#define INPUTPROVIDERSTUB_H_ |
613 | + |
614 | +#include <memory> |
615 | + |
616 | +#include "inputprovider.h" |
617 | + |
618 | +#include "dbus_types.h" |
619 | +#include "shared_gobject.h" |
620 | + |
621 | +extern "C" { |
622 | +#include "aethercastinterface.h" |
623 | +} |
624 | + |
625 | +namespace mcs { |
626 | +namespace dbus { |
627 | + |
628 | +class InputProviderStub : public std::enable_shared_from_this<InputProviderStub>, |
629 | + public InputProvider { |
630 | +public: |
631 | + static constexpr const char *kManagerIface{"org.aethercast.InputProvider"}; |
632 | + |
633 | + static std::shared_ptr<InputProviderStub> Create(const SharedGObject<GDBusConnection> &connection, const ObjectPath &path); |
634 | + |
635 | + ~InputProviderStub(); |
636 | + |
637 | + bool NewConnection(int fd); |
638 | + void RequestDisconnection(); |
639 | + |
640 | + bool Connected() const override; |
641 | + |
642 | +private: |
643 | + InputProviderStub(const ObjectPath &path); |
644 | + std::shared_ptr<InputProviderStub> FinalizeConstruction(const SharedGObject<GDBusConnection> &connection); |
645 | + |
646 | +private: |
647 | + static void OnProxyConnected(GObject *object, GAsyncResult *res, gpointer user_data); |
648 | + static void OnNewConnectionFinish(GObject *object, GAsyncResult *res, gpointer user_data); |
649 | + static void OnRequestDisconnectionFinish(GObject *object, GAsyncResult *res, gpointer user_data); |
650 | + |
651 | +private: |
652 | + std::string path_; |
653 | + AethercastInterfaceInputProvider *proxy_; |
654 | + bool connected_; |
655 | +}; |
656 | + |
657 | +} // namespace dbus |
658 | +} // namespace mcs |
659 | + |
660 | +#endif |
661 | |
662 | === modified file 'src/mcs/miracastcontroller.cpp' |
663 | --- src/mcs/miracastcontroller.cpp 2015-12-11 21:10:24 +0000 |
664 | +++ src/mcs/miracastcontroller.cpp 2015-12-18 16:38:21 +0000 |
665 | @@ -0,0 +1,16 @@ |
666 | +/* |
667 | + * Copyright (C) 2015 Canonical, Ltd. |
668 | + * |
669 | + * This program is free software: you can redistribute it and/or modify it |
670 | + * under the terms of the GNU General Public License version 3, as published |
671 | + * by the Free Software Foundation. |
672 | + * |
673 | + * This program is distributed in the hope that it will be useful, but |
674 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
675 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
676 | + * PURPOSE. See the GNU General Public License for more details. |
677 | + * |
678 | + * You should have received a copy of the GNU General Public License along |
679 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
680 | + * |
681 | + */ |
682 | |
683 | === modified file 'src/mcs/miracastcontroller.h' |
684 | --- src/mcs/miracastcontroller.h 2015-12-11 21:10:24 +0000 |
685 | +++ src/mcs/miracastcontroller.h 2015-12-18 16:38:21 +0000 |
686 | @@ -22,6 +22,7 @@ |
687 | #include <memory> |
688 | |
689 | #include "networkdevice.h" |
690 | +#include "inputprovider.h" |
691 | #include "non_copyable.h" |
692 | #include "types.h" |
693 | |
694 | @@ -57,6 +58,10 @@ |
695 | virtual std::vector<NetworkDeviceRole> SupportedRoles() const = 0; |
696 | virtual bool Scanning() const = 0; |
697 | |
698 | + virtual bool HasInputProvider() const = 0; |
699 | + virtual void SetInputProvider(const InputProvider::Ptr &provider) = 0; |
700 | + virtual void ResetInputProvider() = 0; |
701 | + |
702 | protected: |
703 | |
704 | }; |
705 | |
706 | === modified file 'src/mcs/miracastcontrollerskeleton.cpp' |
707 | --- src/mcs/miracastcontrollerskeleton.cpp 2015-12-16 14:59:45 +0000 |
708 | +++ src/mcs/miracastcontrollerskeleton.cpp 2015-12-18 16:38:21 +0000 |
709 | @@ -23,6 +23,8 @@ |
710 | #include <boost/concept_check.hpp> |
711 | |
712 | #include "miracastcontrollerskeleton.h" |
713 | +#include "inputproviderstub.h" |
714 | + |
715 | #include "keep_alive.h" |
716 | #include "utils.h" |
717 | #include "dbushelpers.h" |
718 | @@ -114,13 +116,18 @@ |
719 | SyncProperties(); |
720 | } |
721 | |
722 | +#define CONNECT_HANDLER(signal, callback) \ |
723 | + g_signal_connect_data(inst->manager_obj_.get(), signal, \ |
724 | + G_CALLBACK(&MiracastControllerSkeleton::callback), new WeakKeepAlive<MiracastControllerSkeleton>(inst), \ |
725 | + [](gpointer data, GClosure *) { delete static_cast<WeakKeepAlive<MiracastControllerSkeleton>*>(data); }, GConnectFlags(0)) |
726 | + |
727 | void MiracastControllerSkeleton::OnNameAcquired(GDBusConnection *connection, const gchar *name, gpointer user_data) { |
728 | auto inst = static_cast<SharedKeepAlive<MiracastControllerSkeleton>*>(user_data)->ShouldDie(); |
729 | inst->manager_obj_.reset(aethercast_interface_manager_skeleton_new()); |
730 | |
731 | - g_signal_connect_data(inst->manager_obj_.get(), "handle-scan", |
732 | - G_CALLBACK(&MiracastControllerSkeleton::OnHandleScan), new WeakKeepAlive<MiracastControllerSkeleton>(inst), |
733 | - [](gpointer data, GClosure *) { delete static_cast<WeakKeepAlive<MiracastControllerSkeleton>*>(data); }, GConnectFlags(0)); |
734 | + CONNECT_HANDLER("handle-scan", OnHandleScan); |
735 | + CONNECT_HANDLER("handle-register-input-provider", OnHandleRegisterInputProvider); |
736 | + CONNECT_HANDLER("handle-unregister-input-provider", OnHandleUnregisterInputProvider); |
737 | |
738 | inst->SyncProperties(); |
739 | |
740 | @@ -152,6 +159,62 @@ |
741 | return TRUE; |
742 | } |
743 | |
744 | +gboolean MiracastControllerSkeleton::OnHandleRegisterInputProvider(AethercastInterfaceManager *skeleton, |
745 | + GDBusMethodInvocation *invocation, |
746 | + const char *path, GVariant *options, |
747 | + gpointer user_data) { |
748 | + boost::ignore_unused_variable_warning(skeleton); |
749 | + auto inst = static_cast<WeakKeepAlive<MiracastControllerSkeleton>*>(user_data)->GetInstance().lock(); |
750 | + |
751 | + if (not inst) { |
752 | + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid state"); |
753 | + return TRUE; |
754 | + } |
755 | + |
756 | + DEBUG("Got request for new input provider %s", path); |
757 | + |
758 | + if (inst->HasInputProvider()) { |
759 | + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
760 | + "Input provider is already registered"); |
761 | + return TRUE; |
762 | + } |
763 | + |
764 | + auto provider = mcs::dbus::InputProviderStub::Create(inst->bus_connection_, mcs::dbus::ObjectPath(path)); |
765 | + |
766 | + inst->SetInputProvider(provider); |
767 | + |
768 | + g_dbus_method_invocation_return_value(invocation, nullptr); |
769 | + |
770 | + return TRUE; |
771 | +} |
772 | + |
773 | +gboolean MiracastControllerSkeleton::OnHandleUnregisterInputProvider(AethercastInterfaceManager *skeleton, |
774 | + GDBusMethodInvocation *invocation, |
775 | + const char *path, |
776 | + gpointer user_data) { |
777 | + boost::ignore_unused_variable_warning(skeleton); |
778 | + auto inst = static_cast<WeakKeepAlive<MiracastControllerSkeleton>*>(user_data)->GetInstance().lock(); |
779 | + |
780 | + if (not inst) { |
781 | + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Invalid state"); |
782 | + return TRUE; |
783 | + } |
784 | + |
785 | + DEBUG("Got request to remove input provider %s", path); |
786 | + |
787 | + if (!inst->HasInputProvider()) { |
788 | + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
789 | + "Input provider is not registered"); |
790 | + return TRUE; |
791 | + } |
792 | + |
793 | + inst->ResetInputProvider(); |
794 | + |
795 | + g_dbus_method_invocation_return_value(invocation, nullptr); |
796 | + |
797 | + return TRUE; |
798 | +} |
799 | + |
800 | std::shared_ptr<MiracastControllerSkeleton> MiracastControllerSkeleton::FinalizeConstruction() { |
801 | auto sp = shared_from_this(); |
802 | |
803 | |
804 | === modified file 'src/mcs/miracastcontrollerskeleton.h' |
805 | --- src/mcs/miracastcontrollerskeleton.h 2015-12-16 14:59:45 +0000 |
806 | +++ src/mcs/miracastcontrollerskeleton.h 2015-12-18 16:38:21 +0000 |
807 | @@ -18,13 +18,9 @@ |
808 | #ifndef MIRACASTSERVICEADAPTOR_H_ |
809 | #define MIRACASTSERVICEADAPTOR_H_ |
810 | |
811 | -#ifdef __cplusplus |
812 | extern "C" { |
813 | -#endif |
814 | #include "aethercastinterface.h" |
815 | -#ifdef __cplusplus |
816 | } |
817 | -#endif |
818 | |
819 | #include <memory> |
820 | #include <unordered_map> |
821 | @@ -59,6 +55,14 @@ |
822 | static gboolean OnHandleScan(AethercastInterfaceManager *skeleton, GDBusMethodInvocation *invocation, |
823 | gpointer user_data); |
824 | |
825 | + static gboolean OnHandleRegisterInputProvider(AethercastInterfaceManager *skeleton, GDBusMethodInvocation *invocation, |
826 | + const char *path, GVariant *options, |
827 | + gpointer user_data); |
828 | + |
829 | + static gboolean OnHandleUnregisterInputProvider(AethercastInterfaceManager *skeleton, GDBusMethodInvocation *invocation, |
830 | + const char *path, |
831 | + gpointer user_data); |
832 | + |
833 | MiracastControllerSkeleton(const std::shared_ptr<MiracastController> &controller); |
834 | std::shared_ptr<MiracastControllerSkeleton> FinalizeConstruction(); |
835 | |
836 | |
837 | === modified file 'src/mcs/miracastservice.cpp' |
838 | --- src/mcs/miracastservice.cpp 2015-12-16 14:59:45 +0000 |
839 | +++ src/mcs/miracastservice.cpp 2015-12-18 16:38:21 +0000 |
840 | @@ -346,4 +346,20 @@ |
841 | void MiracastService::Scan(const std::chrono::seconds &timeout) { |
842 | network_manager_->Scan(timeout); |
843 | } |
844 | + |
845 | +bool MiracastService::HasInputProvider() const { |
846 | + return !!input_provider_; |
847 | +} |
848 | + |
849 | +void MiracastService::SetInputProvider(const InputProvider::Ptr &provider) { |
850 | + input_provider_ = provider; |
851 | +} |
852 | + |
853 | +void MiracastService::ResetInputProvider() { |
854 | + if (input_provider_->Connected()) |
855 | + input_provider_->RequestDisconnection(); |
856 | + |
857 | + input_provider_.reset(); |
858 | +} |
859 | + |
860 | } // namespace miracast |
861 | |
862 | === modified file 'src/mcs/miracastservice.h' |
863 | --- src/mcs/miracastservice.h 2015-12-11 21:10:24 +0000 |
864 | +++ src/mcs/miracastservice.h 2015-12-18 16:38:21 +0000 |
865 | @@ -30,6 +30,8 @@ |
866 | #include "miracastsourcemanager.h" |
867 | #include "networkmanager.h" |
868 | #include "networkdevice.h" |
869 | +#include "inputprovider.h" |
870 | + |
871 | #include "non_copyable.h" |
872 | #include "types.h" |
873 | |
874 | @@ -70,6 +72,10 @@ |
875 | std::vector<NetworkDeviceRole> SupportedRoles() const; |
876 | bool Scanning() const; |
877 | |
878 | + bool HasInputProvider() const; |
879 | + void SetInputProvider(const InputProvider::Ptr &provider); |
880 | + void ResetInputProvider(); |
881 | + |
882 | void OnClientDisconnected(); |
883 | |
884 | public: |
885 | @@ -101,6 +107,7 @@ |
886 | guint scan_timeout_source_; |
887 | ResultCallback current_scan_callback_; |
888 | std::vector<NetworkDeviceRole> supported_roles_; |
889 | + InputProvider::Ptr input_provider_; |
890 | }; |
891 | } // namespace mcs |
892 | #endif |
893 | |
894 | === added file 'src/mcs/withdelegate.cpp' |
895 | --- src/mcs/withdelegate.cpp 1970-01-01 00:00:00 +0000 |
896 | +++ src/mcs/withdelegate.cpp 2015-12-18 16:38:21 +0000 |
897 | @@ -0,0 +1,16 @@ |
898 | +/* |
899 | + * Copyright (C) 2015 Canonical, Ltd. |
900 | + * |
901 | + * This program is free software: you can redistribute it and/or modify it |
902 | + * under the terms of the GNU General Public License version 3, as published |
903 | + * by the Free Software Foundation. |
904 | + * |
905 | + * This program is distributed in the hope that it will be useful, but |
906 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
907 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
908 | + * PURPOSE. See the GNU General Public License for more details. |
909 | + * |
910 | + * You should have received a copy of the GNU General Public License along |
911 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
912 | + * |
913 | + */ |
914 | |
915 | === added file 'src/mcs/withdelegate.h' |
916 | --- src/mcs/withdelegate.h 1970-01-01 00:00:00 +0000 |
917 | +++ src/mcs/withdelegate.h 2015-12-18 16:38:21 +0000 |
918 | @@ -0,0 +1,37 @@ |
919 | +/* |
920 | + * Copyright (C) 2015 Canonical, Ltd. |
921 | + * |
922 | + * This program is free software: you can redistribute it and/or modify it |
923 | + * under the terms of the GNU General Public License version 3, as published |
924 | + * by the Free Software Foundation. |
925 | + * |
926 | + * This program is distributed in the hope that it will be useful, but |
927 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
928 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
929 | + * PURPOSE. See the GNU General Public License for more details. |
930 | + * |
931 | + * You should have received a copy of the GNU General Public License along |
932 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
933 | + * |
934 | + */ |
935 | + |
936 | +#ifndef WITHDELEGATE_H_ |
937 | +#define WITHDELEGATE_H_ |
938 | + |
939 | +#include <memory> |
940 | + |
941 | +namespace mcs { |
942 | + |
943 | +template <typename T> |
944 | +class WithDelegate { |
945 | +public: |
946 | + void SetDelegate(const std::weak_ptr<T> &delegate) { delegate_ = delegate; } |
947 | + void ResetDelegate() { delegate_.reset(); } |
948 | + |
949 | +protected: |
950 | + std::weak_ptr<T> delegate_; |
951 | +}; |
952 | + |
953 | +} // namespace mcs |
954 | + |
955 | +#endif |
956 | |
957 | === modified file 'tests/mcs/CMakeLists.txt' |
958 | --- tests/mcs/CMakeLists.txt 2015-12-11 22:02:52 +0000 |
959 | +++ tests/mcs/CMakeLists.txt 2015-12-18 16:38:21 +0000 |
960 | @@ -24,4 +24,12 @@ |
961 | target_link_libraries(miracastcontrollerskeleton_tests aethercast-core gmock gmock_main) |
962 | add_test(miracastcontrollerskeleton_tests miracastcontrollerskeleton_tests) |
963 | |
964 | +add_executable(inputeventchannel_tests inputeventchannel_tests.cpp) |
965 | +target_link_libraries(inputeventchannel_tests aethercast-core gmock gmock_main) |
966 | +add_test(inputeventchannel_tests inputeventchannel_tests) |
967 | + |
968 | +add_executable(miracastservice_tests miracastservice_tests.cpp) |
969 | +target_link_libraries(miracastservice_tests aethercast-core gmock gmock_main) |
970 | +add_test(miracastservice_tests miracastservice_tests) |
971 | + |
972 | add_subdirectory(acceptance_tests) |
973 | |
974 | === modified file 'tests/mcs/forwardingmiracastcontroller_tests.cpp' |
975 | --- tests/mcs/forwardingmiracastcontroller_tests.cpp 2015-12-11 22:02:52 +0000 |
976 | +++ tests/mcs/forwardingmiracastcontroller_tests.cpp 2015-12-18 16:38:21 +0000 |
977 | @@ -32,6 +32,10 @@ |
978 | MOCK_CONST_METHOD0(State, mcs::NetworkDeviceState()); |
979 | MOCK_CONST_METHOD0(SupportedRoles, std::vector<mcs::NetworkDeviceRole>()); |
980 | MOCK_CONST_METHOD0(Scanning, bool()); |
981 | + |
982 | + MOCK_CONST_METHOD0(HasInputProvider, bool()); |
983 | + MOCK_METHOD1(SetInputProvider, void(const mcs::InputProvider::Ptr &)); |
984 | + MOCK_METHOD0(ResetInputProvider, void()); |
985 | }; |
986 | } |
987 | |
988 | @@ -52,6 +56,9 @@ |
989 | EXPECT_CALL(*impl, State()).Times(1).WillRepeatedly(Return(mcs::NetworkDeviceState::kConnected)); |
990 | EXPECT_CALL(*impl, SupportedRoles()).Times(1).WillRepeatedly(Return(std::vector<mcs::NetworkDeviceRole>{mcs::NetworkDeviceRole::kSource})); |
991 | EXPECT_CALL(*impl, Scanning()).Times(1).WillRepeatedly(Return(true)); |
992 | + EXPECT_CALL(*impl, HasInputProvider()).Times(1); |
993 | + EXPECT_CALL(*impl, SetInputProvider(_)).Times(1); |
994 | + EXPECT_CALL(*impl, ResetInputProvider()).Times(1); |
995 | |
996 | mcs::ForwardingMiracastController fmc{impl}; |
997 | fmc.SetDelegate(std::shared_ptr<mcs::MiracastController::Delegate>{}); |
998 | @@ -62,4 +69,7 @@ |
999 | fmc.State(); |
1000 | fmc.SupportedRoles(); |
1001 | fmc.Scanning(); |
1002 | + fmc.HasInputProvider(); |
1003 | + fmc.SetInputProvider(nullptr); |
1004 | + fmc.ResetInputProvider(); |
1005 | } |
1006 | |
1007 | === added file 'tests/mcs/inputeventchannel_tests.cpp' |
1008 | --- tests/mcs/inputeventchannel_tests.cpp 1970-01-01 00:00:00 +0000 |
1009 | +++ tests/mcs/inputeventchannel_tests.cpp 2015-12-18 16:38:21 +0000 |
1010 | @@ -0,0 +1,66 @@ |
1011 | +/* |
1012 | + * Copyright (C) 2015 Canonical, Ltd. |
1013 | + * |
1014 | + * This program is free software: you can redistribute it and/or modify it |
1015 | + * under the terms of the GNU General Public License version 3, as published |
1016 | + * by the Free Software Foundation. |
1017 | + * |
1018 | + * This program is distributed in the hope that it will be useful, but |
1019 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1020 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1021 | + * PURPOSE. See the GNU General Public License for more details. |
1022 | + * |
1023 | + * You should have received a copy of the GNU General Public License along |
1024 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1025 | + * |
1026 | + */ |
1027 | + |
1028 | +#include <gmock/gmock.h> |
1029 | + |
1030 | +#include <mcs/inputeventchannel.h> |
1031 | + |
1032 | +#include <linux/input.h> |
1033 | + |
1034 | +namespace { |
1035 | +class MockInputEventChannelDelegate : public mcs::InputEventChannelDelegate { |
1036 | +public: |
1037 | + MOCK_METHOD0(OnChannelClosed, void()); |
1038 | + MOCK_METHOD1(OnEvent, void(const mcs::InputEvent &)); |
1039 | +}; |
1040 | + |
1041 | +static void RunMainLoopIteration() { |
1042 | + std::shared_ptr<GMainLoop> loop(g_main_loop_new(nullptr, false), &g_main_loop_unref); |
1043 | + auto context = g_main_loop_get_context(loop.get()); |
1044 | + g_main_context_iteration(context, TRUE); |
1045 | +} |
1046 | +} |
1047 | + |
1048 | +TEST(InputEventChannel, ChannelGotClosed) { |
1049 | + auto delegate = std::make_shared<MockInputEventChannelDelegate>(); |
1050 | + |
1051 | + EXPECT_CALL(*delegate, OnChannelClosed()).Times(1); |
1052 | + |
1053 | + auto channel = mcs::InputEventChannel::Create(); |
1054 | + channel->SetDelegate(delegate); |
1055 | + |
1056 | + ::close(channel->RemoteEndpoint()); |
1057 | + |
1058 | + RunMainLoopIteration(); |
1059 | +} |
1060 | + |
1061 | +TEST(InputEventChannel, EventReporting) { |
1062 | + using namespace ::testing; |
1063 | + |
1064 | + auto delegate = std::make_shared<MockInputEventChannelDelegate>(); |
1065 | + |
1066 | + EXPECT_CALL(*delegate, OnEvent(_)).Times(1); |
1067 | + |
1068 | + auto channel = mcs::InputEventChannel::Create(); |
1069 | + channel->SetDelegate(delegate); |
1070 | + |
1071 | + struct input_event ev = {{0, 0}, EV_ABS, ABS_X, 42}; |
1072 | + EXPECT_EQ(::write(channel->RemoteEndpoint(), &ev, sizeof(ev)), sizeof(ev)); |
1073 | + |
1074 | + RunMainLoopIteration(); |
1075 | +} |
1076 | + |
1077 | |
1078 | === modified file 'tests/mcs/miracastcontrollerskeleton_tests.cpp' |
1079 | --- tests/mcs/miracastcontrollerskeleton_tests.cpp 2015-12-12 20:03:23 +0000 |
1080 | +++ tests/mcs/miracastcontrollerskeleton_tests.cpp 2015-12-18 16:38:21 +0000 |
1081 | @@ -32,6 +32,10 @@ |
1082 | MOCK_CONST_METHOD0(State, mcs::NetworkDeviceState()); |
1083 | MOCK_CONST_METHOD0(SupportedRoles, std::vector<mcs::NetworkDeviceRole>()); |
1084 | MOCK_CONST_METHOD0(Scanning, bool()); |
1085 | + |
1086 | + MOCK_CONST_METHOD0(HasInputProvider, bool()); |
1087 | + MOCK_METHOD1(SetInputProvider, void(const mcs::InputProvider::Ptr &)); |
1088 | + MOCK_METHOD0(ResetInputProvider, void()); |
1089 | }; |
1090 | } |
1091 | |
1092 | |
1093 | === added file 'tests/mcs/miracastservice_tests.cpp' |
1094 | --- tests/mcs/miracastservice_tests.cpp 1970-01-01 00:00:00 +0000 |
1095 | +++ tests/mcs/miracastservice_tests.cpp 2015-12-18 16:38:21 +0000 |
1096 | @@ -0,0 +1,78 @@ |
1097 | +/* |
1098 | + * Copyright (C) 2015 Canonical, Ltd. |
1099 | + * |
1100 | + * This program is free software: you can redistribute it and/or modify it |
1101 | + * under the terms of the GNU General Public License version 3, as published |
1102 | + * by the Free Software Foundation. |
1103 | + * |
1104 | + * This program is distributed in the hope that it will be useful, but |
1105 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1106 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1107 | + * PURPOSE. See the GNU General Public License for more details. |
1108 | + * |
1109 | + * You should have received a copy of the GNU General Public License along |
1110 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1111 | + * |
1112 | + */ |
1113 | + |
1114 | +#include <gmock/gmock.h> |
1115 | + |
1116 | +#include <mcs/miracastservice.h> |
1117 | + |
1118 | +class MockNetworkManager : public mcs::NetworkManager { |
1119 | +public: |
1120 | + MOCK_METHOD1(SetDelegate, void(mcs::NetworkManager::Delegate*)); |
1121 | + MOCK_METHOD0(Setup, bool()); |
1122 | + MOCK_METHOD1(Scan, void(const std::chrono::seconds &)); |
1123 | + MOCK_METHOD1(Connect, bool(const mcs::NetworkDevice::Ptr &)); |
1124 | + MOCK_METHOD1(Disconnect, bool(const mcs::NetworkDevice::Ptr &)); |
1125 | + MOCK_METHOD1(SetWfdSubElements, void(const std::list<std::string> &)); |
1126 | + |
1127 | + MOCK_CONST_METHOD0(Devices, std::vector<mcs::NetworkDevice::Ptr>()); |
1128 | + MOCK_CONST_METHOD0(LocalAddress, mcs::IpV4Address()); |
1129 | + MOCK_CONST_METHOD0(Running, bool()); |
1130 | + MOCK_CONST_METHOD0(Scanning, bool()); |
1131 | +}; |
1132 | + |
1133 | +class MockInputProvider : public mcs::InputProvider { |
1134 | +public: |
1135 | + MOCK_METHOD1(NewConnection, bool(int)); |
1136 | + MOCK_METHOD0(RequestDisconnection, void()); |
1137 | + MOCK_CONST_METHOD0(Connected, bool()); |
1138 | +}; |
1139 | + |
1140 | +TEST(MiracastService, CorrectConstruction) { |
1141 | + using namespace ::testing; |
1142 | + |
1143 | + auto network_manager = std::make_shared<MockNetworkManager>(); |
1144 | + |
1145 | + EXPECT_CALL(*network_manager, SetDelegate(_)).Times(1); |
1146 | + EXPECT_CALL(*network_manager, Setup()).Times(1); |
1147 | + |
1148 | + auto service = mcs::MiracastService::Create(network_manager); |
1149 | + EXPECT_TRUE(!!service); |
1150 | +} |
1151 | + |
1152 | +TEST(MiracastService, InputProviderRegistration) { |
1153 | + using namespace ::testing; |
1154 | + |
1155 | + auto network_manager = std::make_shared<MockNetworkManager>(); |
1156 | + |
1157 | + EXPECT_CALL(*network_manager, SetDelegate(_)).Times(1); |
1158 | + EXPECT_CALL(*network_manager, Setup()).Times(1); |
1159 | + |
1160 | + auto service = mcs::MiracastService::Create(network_manager); |
1161 | + EXPECT_TRUE(!!service); |
1162 | + |
1163 | + auto input_provider = std::make_shared<MockInputProvider>(); |
1164 | + |
1165 | + EXPECT_FALSE(service->HasInputProvider()); |
1166 | + |
1167 | + service->SetInputProvider(input_provider); |
1168 | + |
1169 | + EXPECT_TRUE(service->HasInputProvider()); |
1170 | + |
1171 | + service->ResetInputProvider(); |
1172 | + |
1173 | + EXPECT_FALSE(service->HasInputProvider()); |
1174 | +} |
Still WIP.