Merge lp:~thomas-voss/media-hub/introduce-power-controller-interface into lp:media-hub

Proposed by Thomas Voß
Status: Merged
Approved by: Ricardo Mendoza
Approved revision: 119
Merged at revision: 119
Proposed branch: lp:~thomas-voss/media-hub/introduce-power-controller-interface
Merge into: lp:media-hub
Prerequisite: lp:~thomas-voss/media-hub/move-playbin-implementation-to-cpp-file
Diff against target: 1357 lines (+781/-284)
12 files modified
src/core/media/CMakeLists.txt (+4/-0)
src/core/media/external_services.h (+83/-0)
src/core/media/player_implementation.cpp (+50/-66)
src/core/media/player_implementation.h (+18/-6)
src/core/media/power/state_controller.cpp (+360/-0)
src/core/media/power/state_controller.h (+108/-0)
src/core/media/powerd_service.h (+0/-73)
src/core/media/server/server.cpp (+121/-8)
src/core/media/service_implementation.cpp (+28/-56)
src/core/media/service_implementation.h (+8/-2)
src/core/media/unity_screen_service.h (+0/-72)
tests/CMakeLists.txt (+1/-1)
To merge this branch: bzr merge lp:~thomas-voss/media-hub/introduce-power-controller-interface
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Jim Hodapp (community) code Needs Fixing
Review via email: mp+242905@code.launchpad.net

Commit message

Introduce a common class media::helper::ExternalHelpers that provides a convenient way to:

  * Access the system and session bus instances.
  * Prepares for integration testing scenarios as we can switch to private testing bus instances.
  * Dispatch execution of tasks to worker threads.
  * Requires only one external worker thread transparently shared by implementations requiring access to the respective bus instances.

Introduce interfaces media::power::StateController and media::power::StateController::Lock for acquiring and releasing locks on power-relevant system components, mainly:

  * The display subsystem.
  * The overall system power state.

Provide two implementations talking to the com.canonical.Unity.Screen and com.canonical.powerd
that implement media::power::StateController and media::power::StateController::Lock.

Adjust existing implementation to leverage power::StateController{::Lock}.
Adjust server setup to:

  * hand down an instance of media::helper::ExternalServices to media::ServiceImplementation.
  * spin up two threads running the actual service and the external service helper in an exception-safe way.

Disable compilation of acceptance tests until the end of the wave of merge proposals to avoid having to resync. All of them are disabled anyway.

Description of the change

Introduce a common class media::helper::ExternalHelpers that provides a convenient way to:

  * Access the system and session bus instances.
  * Prepares for integration testing scenarios as we can switch to private testing bus instances.
  * Dispatch execution of tasks to worker threads.
  * Requires only one external worker thread transparently shared by implementations requiring access to the respective bus instances.

Introduce interfaces media::power::StateController and media::power::StateController::Lock for acquiring and releasing locks on power-relevant system components, mainly:

  * The display subsystem.
  * The overall system power state.

Provide two implementations talking to the com.canonical.Unity.Screen and com.canonical.powerd
that implement media::power::StateController and media::power::StateController::Lock.

Adjust existing implementation to leverage power::StateController{::Lock}.
Adjust server setup to:

  * hand down an instance of media::helper::ExternalServices to media::ServiceImplementation.
  * spin up two threads running the actual service and the external service helper in an exception-safe way.

Disable compilation of acceptance tests until the end of the wave of merge proposals to avoid having to resync. All of them are disabled anyway.

To post a comment you must log in.
105. By Thomas Voß

Initialize media::RecorderObserver in the ctor's initializer list.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
106. By Thomas Voß

Remerge prereq branch.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Jim Hodapp (jhodapp) wrote :

There's a lot to this one and we'll want to test the wakelock parts extremely well since there have been issues in the past with race conditions. Looks good, several comments inline below:

review: Needs Fixing (code)
Revision history for this message
Thomas Voß (thomas-voss) :
107. By Thomas Voß

[ Jim Hodapp ]
* Resubmitting with prerequisite branch (LP: #1331041)
[ Justin McPherson ]
* Resubmitting with prerequisite branch (LP: #1331041)

108. By Thomas Voß

Address review comments.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
109. By Thomas Voß

Fix ftbfs.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
110. By Thomas Voß

[ Jim Hodapp ]
* Error reporting all the way up to the app level from the playbin
  pipeline.
[ Ubuntu daily release ]
* New rebuild forced
[ Jim Hodapp ]
* Don't auto-resume playback of videos after a phone call ends. (LP:
  #1411273)
[ Ubuntu daily release ]
* New rebuild forced
[ Ricardo Salveti de Araujo ]
* service_implementation: adding debug for call started/ended signals.
  Make sure account and connection are available when setting up
  account manager (patch from Gustavo Boiko). call_monitor: don't
  check caps when hooking up on/off signals, until bug 1409125 is
  fixed. Enable parallel building . (LP: #1409125)
[ Jim Hodapp ]
* Pause playback when recording begins. (LP: #1398047)
[ Ricardo Salveti de Araujo ]
* call_monitor.cpp: waiting for bridge to be up, and also protecting
  the on_change call (LP: #1408137)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
111. By Thomas Voß

Merge prereq branch.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
112. By Thomas Voß

Fix init issue for assigning executors to buses.

113. By Thomas Voß

Merge prereq branch.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
114. By Thomas Voß

Make the default implementation more verbose.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
115. By Thomas Voß

Make sure that the system state lock instance is around long enough when reaching out via the bus.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
116. By Thomas Voß

We really should release the on request, not the off one.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
117. By Thomas Voß

Make sure that a DisplayStateLock is alive for long enough to always be able to complete a release operation.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
118. By Thomas Voß

* debian/control:
  - Removing pre-depends that are not required
  - Bumping standards-version to 3.9.6
[ Ricardo Salveti de Araujo ]
* Migrating tests to use ogg instead of mp3/avi removed:
  tests/h264.avi tests/test.mp3 added: tests/test-audio-1.ogg
  tests/test-video.ogg tests/test.mp3 renamed: tests/test.ogg =>
  tests/test-audio.ogg

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
119. By Thomas Voß

Tighten scope in StateController.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/core/media/CMakeLists.txt'
2--- src/core/media/CMakeLists.txt 2015-03-19 20:49:44 +0000
3+++ src/core/media/CMakeLists.txt 2015-03-19 20:49:45 +0000
4@@ -90,8 +90,12 @@
5 hybris_client_death_observer.cpp
6 cover_art_resolver.cpp
7 engine.cpp
8+
9+ power/state_controller.cpp
10+
11 recorder_observer.cpp
12 hybris_recorder_observer.cpp
13+
14 gstreamer/engine.cpp
15 gstreamer/playbin.cpp
16
17
18=== added file 'src/core/media/external_services.h'
19--- src/core/media/external_services.h 1970-01-01 00:00:00 +0000
20+++ src/core/media/external_services.h 2015-03-19 20:49:45 +0000
21@@ -0,0 +1,83 @@
22+/*
23+ * Copyright © 2014 Canonical Ltd.
24+ *
25+ * This program is free software: you can redistribute it and/or modify it
26+ * under the terms of the GNU Lesser General Public License version 3,
27+ * as published by the Free Software Foundation.
28+ *
29+ * This program is distributed in the hope that it will be useful,
30+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32+ * GNU Lesser General Public License for more details.
33+ *
34+ * You should have received a copy of the GNU Lesser General Public License
35+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
36+ *
37+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
38+ */
39+#ifndef CORE_UBUNTU_MEDIA_EXTERNAL_SERVICES_H_
40+#define CORE_UBUNTU_MEDIA_EXTERNAL_SERVICES_H_
41+
42+#include <core/dbus/bus.h>
43+
44+#include <core/dbus/asio/executor.h>
45+
46+#include <boost/asio.hpp>
47+
48+namespace core
49+{
50+namespace ubuntu
51+{
52+namespace media
53+{
54+namespace helper
55+{
56+// A helper struct that bundles:
57+// * a dispatcher, i.e., the io_service
58+// * access to the system and session bus
59+//
60+// In addtion, it allows us to mock out services and
61+// for acceptance testing purposes.
62+struct ExternalServices
63+{
64+ ExternalServices(const core::dbus::Bus::Ptr& session, const core::dbus::Bus::Ptr& system)
65+ : keep_alive{io_service},
66+ session{session},
67+ system{system}
68+ {
69+ }
70+
71+ ExternalServices()
72+ : ExternalServices
73+ {
74+ core::dbus::Bus::Ptr{new core::dbus::Bus{core::dbus::WellKnownBus::session}},
75+ core::dbus::Bus::Ptr{new core::dbus::Bus{core::dbus::WellKnownBus::system}}
76+ }
77+ {
78+ session->install_executor(core::dbus::asio::make_executor(session, io_service));
79+ system->install_executor(core::dbus::asio::make_executor(system, io_service));
80+ }
81+
82+
83+ void run()
84+ {
85+ io_service.run();
86+ }
87+
88+ void stop()
89+ {
90+ io_service.stop();
91+ }
92+
93+ boost::asio::io_service io_service;
94+ boost::asio::io_service::work keep_alive;
95+
96+ core::dbus::Bus::Ptr session;
97+ core::dbus::Bus::Ptr system;
98+};
99+}
100+}
101+}
102+}
103+
104+#endif // CORE_UBUNTU_MEDIA_EXTERNAL_SERVICES_H_
105
106=== modified file 'src/core/media/player_implementation.cpp'
107--- src/core/media/player_implementation.cpp 2015-03-19 20:49:44 +0000
108+++ src/core/media/player_implementation.cpp 2015-03-19 20:49:45 +0000
109@@ -25,8 +25,6 @@
110 #include "engine.h"
111 #include "track_list_implementation.h"
112
113-#include "powerd_service.h"
114-#include "unity_screen_service.h"
115 #include "gstreamer/engine.h"
116
117 #include <memory>
118@@ -52,45 +50,50 @@
119 WAKELOCK_CLEAR_INVALID
120 };
121
122- Private(PlayerImplementation* parent,
123- const dbus::types::ObjectPath& session_path,
124- const std::shared_ptr<media::Service>& service,
125- PlayerImplementation::PlayerKey key)
126+ Private(PlayerImplementation* parent, const media::PlayerImplementation::Configuration& config)
127 : parent(parent),
128- service(service),
129+ config(config),
130+ display_state_lock(config.power_state_controller->display_state_lock()),
131+ system_state_lock(config.power_state_controller->system_state_lock()),
132 engine(std::make_shared<gstreamer::Engine>()),
133- session_path(session_path),
134 track_list(
135 new media::TrackListImplementation(
136- session_path.as_string() + "/TrackList",
137+ config.session->path().as_string() + "/TrackList",
138 engine->meta_data_extractor())),
139- sys_lock_name("media-hub-music-playback"),
140- disp_cookie(-1),
141 system_wakelock_count(0),
142 display_wakelock_count(0),
143 previous_state(Engine::State::stopped),
144- key(key),
145 engine_state_change_connection(engine->state().changed().connect(make_state_change_handler()))
146 {
147- auto bus = std::shared_ptr<dbus::Bus>(new dbus::Bus(core::dbus::WellKnownBus::system));
148- bus->install_executor(dbus::asio::make_executor(bus));
149-
150- auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service<core::Powerd>::interface_name());
151- powerd_session = stub_service->object_for_path(dbus::types::ObjectPath("/com/canonical/powerd"));
152-
153- auto uscreen_stub_service = dbus::Service::use_service(bus, dbus::traits::Service<core::UScreen>::interface_name());
154- uscreen_session = uscreen_stub_service->object_for_path(dbus::types::ObjectPath("/com/canonical/Unity/Screen"));
155-
156- auto client_death_observer = media::platform_default_client_death_observer();
157-
158- client_death_observer->register_for_death_notifications_with_key(key);
159- client_death_observer->on_client_with_key_died().connect([this](const media::Player::PlayerKey& died)
160+ config.client_death_observer->register_for_death_notifications_with_key(config.key);
161+ config.client_death_observer->on_client_with_key_died().connect([this](const media::Player::PlayerKey& died)
162 {
163- if (died != this->key)
164+ if (died != this->config.key)
165 return;
166
167 on_client_died();
168 });
169+
170+ // Poor man's logging of release/acquire events.
171+ display_state_lock->acquired().connect([](media::power::DisplayState state)
172+ {
173+ std::cout << "Acquired new display state: " << state << std::endl;
174+ });
175+
176+ display_state_lock->released().connect([](media::power::DisplayState state)
177+ {
178+ std::cout << "Released display state: " << state << std::endl;
179+ });
180+
181+ system_state_lock->acquired().connect([](media::power::SystemState state)
182+ {
183+ std::cout << "Acquired new system state: " << state << std::endl;
184+ });
185+
186+ system_state_lock->released().connect([](media::power::SystemState state)
187+ {
188+ std::cout << "Released system state: " << state << std::endl;
189+ });
190 }
191
192 ~Private()
193@@ -170,22 +173,16 @@
194 {
195 if (++display_wakelock_count == 1)
196 {
197- auto result = uscreen_session->invoke_method_synchronously<core::UScreen::keepDisplayOn, int>();
198- if (result.is_error())
199- throw std::runtime_error(result.error().print());
200- disp_cookie = result.value();
201- cout << "Requested new display wakelock" << endl;
202+ display_state_lock->request_acquire(media::power::DisplayState::on);
203+ std::cout << "Requested new display wakelock." << std::endl;
204 }
205 }
206 else
207 {
208 if (++system_wakelock_count == 1)
209 {
210- auto result = powerd_session->invoke_method_synchronously<core::Powerd::requestSysState, std::string>(sys_lock_name, static_cast<int>(1));
211- if (result.is_error())
212- throw std::runtime_error(result.error().print());
213- sys_cookie = result.value();
214- cout << "Requested new system wakelock" << endl;
215+ system_state_lock->request_acquire(media::power::SystemState::active);
216+ std::cout << "Requested new system wakelock." << std::endl;
217 }
218 }
219 }
220@@ -209,18 +206,16 @@
221 // Only actually clear the system wakelock once the count reaches zero
222 if (--system_wakelock_count == 0)
223 {
224- cout << "Clearing system wakelock" << endl;
225- powerd_session->invoke_method_synchronously<core::Powerd::clearSysState, void>(sys_cookie);
226- sys_cookie.clear();
227+ std::cout << "Clearing system wakelock." << std::endl;
228+ system_state_lock->request_release(media::power::SystemState::active);
229 }
230 break;
231 case wakelock_clear_t::WAKELOCK_CLEAR_DISPLAY:
232 // Only actually clear the display wakelock once the count reaches zero
233 if (--display_wakelock_count == 0)
234 {
235- cout << "Clearing display wakelock" << endl;
236- uscreen_session->invoke_method_synchronously<core::UScreen::removeDisplayOnRequest, void>(disp_cookie);
237- disp_cookie = -1;
238+ std::cout << "Clearing display wakelock." << std::endl;
239+ display_state_lock->request_release(media::power::DisplayState::on);
240 }
241 break;
242 case wakelock_clear_t::WAKELOCK_CLEAR_INVALID:
243@@ -275,44 +270,33 @@
244 engine->reset();
245 }
246
247- PlayerImplementation* parent;
248- std::shared_ptr<Service> service;
249+ // Our link back to our parent.
250+ media::PlayerImplementation* parent;
251+ // We just store the parameters passed on construction.
252+ media::PlayerImplementation::Configuration config;
253+ media::power::StateController::Lock<media::power::DisplayState>::Ptr display_state_lock;
254+ media::power::StateController::Lock<media::power::SystemState>::Ptr system_state_lock;
255+
256 std::shared_ptr<Engine> engine;
257- dbus::types::ObjectPath session_path;
258 std::shared_ptr<TrackListImplementation> track_list;
259- std::shared_ptr<dbus::Object> powerd_session;
260- std::shared_ptr<dbus::Object> uscreen_session;
261- std::string sys_lock_name;
262- int disp_cookie;
263- std::string sys_cookie;
264 std::atomic<int> system_wakelock_count;
265 std::atomic<int> display_wakelock_count;
266 Engine::State previous_state;
267- PlayerImplementation::PlayerKey key;
268 core::Signal<> on_client_disconnected;
269 core::Connection engine_state_change_connection;
270 };
271
272-media::PlayerImplementation::PlayerImplementation(
273- const std::string& identity,
274- const std::shared_ptr<core::dbus::Bus>& bus,
275- const std::shared_ptr<core::dbus::Object>& session,
276- const std::shared_ptr<Service>& service,
277- PlayerKey key)
278+media::PlayerImplementation::PlayerImplementation(const media::PlayerImplementation::Configuration& config)
279 : media::PlayerSkeleton
280 {
281 media::PlayerSkeleton::Configuration
282 {
283- bus,
284- session,
285- identity
286+ config.bus,
287+ config.session,
288+ config.identity
289 }
290 },
291- d(make_shared<Private>(
292- this,
293- session->path(),
294- service,
295- key))
296+ d{std::make_shared<Private>(this, config)}
297 {
298 // Initialize default values for Player interface properties
299 can_play().set(true);
300@@ -464,7 +448,7 @@
301 // TODO: Convert this to be a property instead of sync call
302 media::Player::PlayerKey media::PlayerImplementation::key() const
303 {
304- return d->key;
305+ return d->config.key;
306 }
307
308 media::video::Sink::Ptr media::PlayerImplementation::create_gl_texture_video_sink(std::uint32_t texture_id)
309
310=== modified file 'src/core/media/player_implementation.h'
311--- src/core/media/player_implementation.h 2015-03-19 20:49:44 +0000
312+++ src/core/media/player_implementation.h 2015-03-19 20:49:45 +0000
313@@ -21,6 +21,9 @@
314
315 #include "player_skeleton.h"
316
317+#include "client_death_observer.h"
318+#include "power/state_controller.h"
319+
320 #include <memory>
321
322 namespace core
323@@ -35,12 +38,21 @@
324 class PlayerImplementation : public PlayerSkeleton
325 {
326 public:
327- PlayerImplementation(
328- const std::string& identity,
329- const std::shared_ptr<core::dbus::Bus>& bus,
330- const std::shared_ptr<core::dbus::Object>& session,
331- const std::shared_ptr<Service>& service,
332- PlayerKey key);
333+ // All creation time arguments go here
334+ struct Configuration
335+ {
336+ std::string identity;
337+ std::shared_ptr<core::dbus::Bus> bus;
338+ std::shared_ptr<core::dbus::Object> session;
339+ std::shared_ptr<Service> service;
340+ PlayerKey key;
341+
342+ // Functional dependencies
343+ ClientDeathObserver::Ptr client_death_observer;
344+ power::StateController::Ptr power_state_controller;
345+ };
346+
347+ PlayerImplementation(const Configuration& configuration);
348 ~PlayerImplementation();
349
350 virtual std::shared_ptr<TrackList> track_list();
351
352=== added directory 'src/core/media/power'
353=== added file 'src/core/media/power/state_controller.cpp'
354--- src/core/media/power/state_controller.cpp 1970-01-01 00:00:00 +0000
355+++ src/core/media/power/state_controller.cpp 2015-03-19 20:49:45 +0000
356@@ -0,0 +1,360 @@
357+/*
358+ * Copyright © 2014 Canonical Ltd.
359+ *
360+ * This program is free software: you can redistribute it and/or modify it
361+ * under the terms of the GNU Lesser General Public License version 3,
362+ * as published by the Free Software Foundation.
363+ *
364+ * This program is distributed in the hope that it will be useful,
365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
367+ * GNU Lesser General Public License for more details.
368+ *
369+ * You should have received a copy of the GNU Lesser General Public License
370+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
371+ *
372+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
373+ */
374+
375+#include <core/media/power/state_controller.h>
376+
377+#include <core/dbus/macros.h>
378+#include <core/dbus/object.h>
379+
380+#include <iostream>
381+
382+namespace media = core::ubuntu::media;
383+
384+namespace com { namespace canonical {
385+struct Unity
386+{
387+ struct Screen
388+ {
389+ static const std::string& name()
390+ {
391+ static std::string s = "com.canonical.Unity.Screen";
392+ return s;
393+ }
394+
395+ static const core::dbus::types::ObjectPath& path()
396+ {
397+ static core::dbus::types::ObjectPath p{"/com/canonical/Unity/Screen"};
398+ return p;
399+ }
400+
401+ DBUS_CPP_METHOD_DEF(keepDisplayOn, Screen)
402+ DBUS_CPP_METHOD_DEF(removeDisplayOnRequest, Screen)
403+ };
404+};
405+namespace powerd {
406+struct Interface
407+{
408+ static std::string& name()
409+ {
410+ static std::string s = "com.canonical.powerd";
411+ return s;
412+ }
413+
414+ static const core::dbus::types::ObjectPath& path()
415+ {
416+ static core::dbus::types::ObjectPath p{"/com/canonical/powerd"};
417+ return p;
418+ }
419+
420+ DBUS_CPP_METHOD_DEF(requestSysState, com::canonical::powerd::Interface)
421+ DBUS_CPP_METHOD_DEF(clearSysState, com::canonical::powerd::Interface)
422+};
423+}}}
424+
425+namespace
426+{
427+namespace impl
428+{
429+struct DisplayStateLock : public media::power::StateController::Lock<media::power::DisplayState>,
430+ public std::enable_shared_from_this<DisplayStateLock>
431+{
432+ // To safe us some typing
433+ typedef std::shared_ptr<DisplayStateLock> Ptr;
434+
435+ // We postpone releasing the display for this amount of time.
436+ static boost::posix_time::seconds timeout_for_release()
437+ {
438+ return boost::posix_time::seconds{4};
439+ }
440+
441+ // The invalid cookie marker.
442+ static constexpr const std::int32_t the_invalid_cookie{-1};
443+
444+ DisplayStateLock(const media::power::StateController::Ptr& parent,
445+ boost::asio::io_service& io_service,
446+ const core::dbus::Object::Ptr& object)
447+ : parent{parent},
448+ timeout{io_service},
449+ object{object},
450+ cookie{the_invalid_cookie}
451+ {
452+ }
453+
454+ // From core::ubuntu::media::power::StateController::Lock<DisplayState>
455+ void request_acquire(media::power::DisplayState state) override
456+ {
457+ if (state == media::power::DisplayState::off)
458+ return;
459+
460+ std::weak_ptr<DisplayStateLock> wp{shared_from_this()};
461+
462+ object->invoke_method_asynchronously_with_callback<com::canonical::Unity::Screen::keepDisplayOn, std::int32_t>(
463+ [wp, state](const core::dbus::Result<std::int32_t>& result)
464+ {
465+ if (result.is_error())
466+ {
467+ std::cerr << result.error().print() << std::endl;
468+ return;
469+ }
470+
471+ if (auto sp = wp.lock())
472+ {
473+ sp->cookie = result.value();
474+ sp->signals.acquired(state);
475+ }
476+ });
477+ }
478+
479+ void request_release(media::power::DisplayState state) override
480+ {
481+ if (state == media::power::DisplayState::off)
482+ return;
483+
484+ if (cookie == the_invalid_cookie)
485+ return;
486+
487+ // We make sure that we keep ourselves alive to make sure
488+ // that release requests are always correctly issued.
489+ auto sp = shared_from_this();
490+
491+ auto current_cookie(cookie);
492+
493+ timeout.expires_from_now(timeout_for_release());
494+ timeout.async_wait([sp, state, current_cookie](const boost::system::error_code& ec)
495+ {
496+ // We only return early from the timeout handler if the operation has been
497+ // explicitly aborted before.
498+ if (ec == boost::asio::error::operation_aborted)
499+ return;
500+
501+ sp->object->invoke_method_asynchronously_with_callback<com::canonical::Unity::Screen::removeDisplayOnRequest, void>(
502+ [sp, state, current_cookie](const core::dbus::Result<void>& result)
503+ {
504+ if (result.is_error())
505+ {
506+ std::cerr << result.error().print() << std::endl;
507+ return;
508+ }
509+
510+ sp->signals.released(state);
511+
512+ // We might have issued a different request before and
513+ // only call the display state done if the original cookie
514+ // corresponds to the one we just gave up.
515+ if (sp->cookie == current_cookie)
516+ sp->cookie = the_invalid_cookie;
517+
518+ }, current_cookie);
519+ });
520+ }
521+
522+ // Emitted whenever the acquire request completes.
523+ const core::Signal<media::power::DisplayState>& acquired() const override
524+ {
525+ return signals.acquired;
526+ }
527+
528+ // Emitted whenever the release request completes.
529+ const core::Signal<media::power::DisplayState>& released() const override
530+ {
531+ return signals.released;
532+ }
533+
534+ media::power::StateController::Ptr parent;
535+ boost::asio::deadline_timer timeout;
536+ core::dbus::Object::Ptr object;
537+ std::int32_t cookie;
538+
539+ struct
540+ {
541+ core::Signal<media::power::DisplayState> acquired;
542+ core::Signal<media::power::DisplayState> released;
543+ } signals;
544+};
545+
546+struct SystemStateLock : public media::power::StateController::Lock<media::power::SystemState>,
547+ public std::enable_shared_from_this<SystemStateLock>
548+{
549+ static constexpr const char* wake_lock_name
550+ {
551+ "media-hub-playback_lock"
552+ };
553+
554+ SystemStateLock(const media::power::StateController::Ptr& parent, const core::dbus::Object::Ptr& object)
555+ : parent{parent},
556+ object{object}
557+ {
558+ }
559+
560+ // Informs the system that the caller would like
561+ // the system to stay active.
562+ void request_acquire(media::power::SystemState state) override
563+ {
564+ if (state == media::power::SystemState::suspend)
565+ return;
566+
567+ // Keep scope of this lock tight as to avoid
568+ // deadlocks on PlayerImplementation destruction
569+ {
570+ std::lock_guard<std::mutex> lg{system_state_cookie_store_guard};
571+ if (system_state_cookie_store.count(state) > 0)
572+ return;
573+ }
574+
575+ std::weak_ptr<SystemStateLock> wp{shared_from_this()};
576+
577+ object->invoke_method_asynchronously_with_callback<com::canonical::powerd::Interface::requestSysState, std::string>([wp, state](const core::dbus::Result<std::string>& result)
578+ {
579+ if (result.is_error()) // TODO(tvoss): We should log the error condition here.
580+ return;
581+
582+ if (auto sp = wp.lock())
583+ {
584+ std::lock_guard<std::mutex> lg{sp->system_state_cookie_store_guard};
585+
586+ sp->system_state_cookie_store[state] = result.value();
587+ sp->signals.acquired(state);
588+ }
589+ }, std::string{wake_lock_name}, static_cast<std::int32_t>(state));
590+ }
591+
592+ // Informs the system that the caller does not
593+ // require the system to stay active anymore.
594+ void request_release(media::power::SystemState state) override
595+ {
596+ if (state == media::power::SystemState::suspend)
597+ return;
598+
599+ std::lock_guard<std::mutex> lg{system_state_cookie_store_guard};
600+
601+ if (system_state_cookie_store.count(state) == 0)
602+ return;
603+
604+ std::weak_ptr<SystemStateLock> wp{shared_from_this()};
605+
606+ object->invoke_method_asynchronously_with_callback<com::canonical::powerd::Interface::clearSysState, void>([wp, state](const core::dbus::Result<void>& result)
607+ {
608+ if (result.is_error())
609+ std::cerr << result.error().print() << std::endl;
610+
611+ if (auto sp = wp.lock())
612+ {
613+ std::lock_guard<std::mutex> lg{sp->system_state_cookie_store_guard};
614+
615+ sp->system_state_cookie_store.erase(state);
616+ sp->signals.released(state);
617+ }
618+ }, system_state_cookie_store.at(state));
619+ }
620+
621+ // Emitted whenever the acquire request completes.
622+ const core::Signal<media::power::SystemState>& acquired() const override
623+ {
624+ return signals.acquired;
625+ }
626+
627+ // Emitted whenever the release request completes.
628+ const core::Signal<media::power::SystemState>& released() const override
629+ {
630+ return signals.released;
631+ }
632+
633+ // Guards concurrent accesses to the cookie store.
634+ std::mutex system_state_cookie_store_guard;
635+ // Maps previously requested system states to the cookies returned
636+ // by the remote end. Used for keeping track of acquired states and
637+ // associated cookies to be able to release previously granted acquisitions.
638+ std::map<media::power::SystemState, std::string> system_state_cookie_store;
639+ media::power::StateController::Ptr parent;
640+ core::dbus::Object::Ptr object;
641+ struct
642+ {
643+ core::Signal<media::power::SystemState> acquired;
644+ core::Signal<media::power::SystemState> released;
645+ } signals;
646+};
647+
648+struct StateController : public media::power::StateController,
649+ public std::enable_shared_from_this<impl::StateController>
650+{
651+ StateController(media::helper::ExternalServices& es)
652+ : external_services{es},
653+ powerd
654+ {
655+ core::dbus::Service::use_service<com::canonical::powerd::Interface>(external_services.system)
656+ ->object_for_path(com::canonical::powerd::Interface::path())
657+ },
658+ unity_screen
659+ {
660+ core::dbus::Service::use_service<com::canonical::Unity::Screen>(external_services.system)
661+ ->object_for_path(com::canonical::Unity::Screen::path())
662+ }
663+ {
664+ }
665+
666+ media::power::StateController::Lock<media::power::SystemState>::Ptr system_state_lock() override
667+ {
668+ return std::make_shared<impl::SystemStateLock>(shared_from_this(), powerd);
669+ }
670+
671+ media::power::StateController::Lock<media::power::DisplayState>::Ptr display_state_lock() override
672+ {
673+ return std::make_shared<impl::DisplayStateLock>(shared_from_this(), external_services.io_service, unity_screen);
674+ }
675+
676+ media::helper::ExternalServices& external_services;
677+ core::dbus::Object::Ptr powerd;
678+ core::dbus::Object::Ptr unity_screen;
679+};
680+}
681+}
682+
683+media::power::StateController::Ptr media::power::make_platform_default_state_controller(core::ubuntu::media::helper::ExternalServices& external_services)
684+{
685+ return std::make_shared<impl::StateController>(external_services);
686+}
687+
688+// operator<< pretty prints the given display state to the given output stream.
689+std::ostream& media::power::operator<<(std::ostream& out, media::power::DisplayState state)
690+{
691+ switch (state)
692+ {
693+ case media::power::DisplayState::off:
694+ return out << "DisplayState::off";
695+ case media::power::DisplayState::on:
696+ return out << "DisplayState::on";
697+ }
698+
699+ return out;
700+}
701+
702+// operator<< pretty prints the given system state to the given output stream.
703+std::ostream& media::power::operator<<(std::ostream& out, media::power::SystemState state)
704+{
705+ switch (state)
706+ {
707+ case media::power::SystemState::active:
708+ return out << "SystemState::active";
709+ case media::power::SystemState::blank_on_proximity:
710+ return out << "SystemState::blank_on_proximity";
711+ case media::power::SystemState::suspend:
712+ return out << "SystemState::suspend";
713+ }
714+
715+ return out;
716+}
717
718=== added file 'src/core/media/power/state_controller.h'
719--- src/core/media/power/state_controller.h 1970-01-01 00:00:00 +0000
720+++ src/core/media/power/state_controller.h 2015-03-19 20:49:45 +0000
721@@ -0,0 +1,108 @@
722+/*
723+ * Copyright © 2014 Canonical Ltd.
724+ *
725+ * This program is free software: you can redistribute it and/or modify it
726+ * under the terms of the GNU Lesser General Public License version 3,
727+ * as published by the Free Software Foundation.
728+ *
729+ * This program is distributed in the hope that it will be useful,
730+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
731+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
732+ * GNU Lesser General Public License for more details.
733+ *
734+ * You should have received a copy of the GNU Lesser General Public License
735+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
736+ *
737+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
738+ */
739+#ifndef CORE_UBUNTU_MEDIA_POWER_STATE_CONTROLLER_H_
740+#define CORE_UBUNTU_MEDIA_POWER_STATE_CONTROLLER_H_
741+
742+#include <core/media/external_services.h>
743+
744+#include <core/property.h>
745+
746+#include <iosfwd>
747+#include <memory>
748+
749+namespace core
750+{
751+namespace ubuntu
752+{
753+namespace media
754+{
755+namespace power
756+{
757+// Enumerates all known power states of a display.
758+enum class DisplayState
759+{
760+ // The display is off.
761+ off = 0,
762+ // The display is on.
763+ on = 1
764+};
765+
766+// Enumerates known power states of the system.
767+enum class SystemState
768+{
769+ // Note that callers will be notified of suspend state changes
770+ // but may not request this state.
771+ suspend = 0,
772+ // The Active state will prevent system suspend
773+ active = 1,
774+ // Substate of Active with disabled proximity based blanking
775+ blank_on_proximity = 2
776+};
777+
778+// Interface that enables observation of the system power state.
779+struct StateController
780+{
781+ // To save us some typing.
782+ typedef std::shared_ptr<StateController> Ptr;
783+
784+ // When acquired, ensures that the system stays active,
785+ // and decreases the reference count when released.
786+ template<typename State>
787+ struct Lock
788+ {
789+ // To save us some typing.
790+ typedef std::shared_ptr<Lock> Ptr;
791+
792+ Lock() = default;
793+ virtual ~Lock() = default;
794+
795+ // Informs the system that the caller would like
796+ // the system to stay active.
797+ virtual void request_acquire(State state) = 0;
798+ // Informs the system that the caller does not
799+ // require the system to stay active anymore.
800+ virtual void request_release(State state) = 0;
801+
802+ // Emitted whenever the acquire request completes.
803+ virtual const core::Signal<State>& acquired() const = 0;
804+ // Emitted whenever the release request completes.
805+ virtual const core::Signal<State>& released() const = 0;
806+ };
807+
808+ StateController() = default;
809+ virtual ~StateController() = default;
810+
811+ // Returns a power::StateController::Lock<DisplayState> instance.
812+ virtual Lock<DisplayState>::Ptr display_state_lock() = 0;
813+ // Returns a power::StateController::Lock<SystemState> instance.
814+ virtual Lock<SystemState>::Ptr system_state_lock() = 0;
815+};
816+
817+// Creates a StateController instance that connects to the platform default
818+// services to control system and display power states.
819+StateController::Ptr make_platform_default_state_controller(core::ubuntu::media::helper::ExternalServices&);
820+
821+// operator<< pretty prints the given display state to the given output stream.
822+std::ostream& operator<<(std::ostream& out, DisplayState state);
823+// operator<< pretty prints the given system state to the given output stream.
824+std::ostream& operator<<(std::ostream& out, SystemState state);
825+}
826+}
827+}
828+}
829+#endif // CORE_UBUNTU_MEDIA_POWER_STATE_CONTROLLER_H_
830
831=== removed file 'src/core/media/powerd_service.h'
832--- src/core/media/powerd_service.h 2014-08-08 14:36:29 +0000
833+++ src/core/media/powerd_service.h 1970-01-01 00:00:00 +0000
834@@ -1,73 +0,0 @@
835-/*
836- * Copyright (C) 2014 Canonical Ltd
837- *
838- * This program is free software: you can redistribute it and/or modify
839- * it under the terms of the GNU Lesser General Public License version 3 as
840- * published by the Free Software Foundation.
841- *
842- * This program is distributed in the hope that it will be useful,
843- * but WITHOUT ANY WARRANTY; without even the implied warranty of
844- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
845- * GNU Lesser General Public License for more details.
846- *
847- * You should have received a copy of the GNU Lesser General Public License
848- * along with this program. If not, see <http://www.gnu.org/licenses/>.
849- *
850- * Author: Ricardo Mendoza <ricardo.mendoza@canonical.com>
851- */
852-
853-#include <core/dbus/dbus.h>
854-#include <core/dbus/fixture.h>
855-#include <core/dbus/object.h>
856-#include <core/dbus/property.h>
857-#include <core/dbus/service.h>
858-#include <core/dbus/interfaces/properties.h>
859-#include <core/dbus/types/stl/tuple.h>
860-#include <core/dbus/types/stl/vector.h>
861-
862-#include <core/dbus/asio/executor.h>
863-
864-#include <string>
865-#include <vector>
866-#include <chrono>
867-
868-namespace core
869-{
870-
871-struct Powerd
872-{
873- static std::string& name()
874- {
875- static std::string s = "com.canonical.powerd";
876- return s;
877- }
878-
879- struct requestSysState
880- {
881- static std::string name()
882- {
883- static std::string s = "requestSysState";
884- return s;
885- }
886-
887- static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
888-
889- typedef Powerd Interface;
890- };
891-
892- struct clearSysState
893- {
894- static std::string name()
895- {
896- static std::string s = "clearSysState";
897- return s;
898- }
899-
900- static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
901-
902- typedef Powerd Interface;
903- };
904-
905-};
906-
907-}
908
909=== modified file 'src/core/media/server/server.cpp'
910--- src/core/media/server/server.cpp 2014-04-04 14:31:43 +0000
911+++ src/core/media/server/server.cpp 2015-03-19 20:49:45 +0000
912@@ -20,24 +20,137 @@
913 #include <core/media/player.h>
914 #include <core/media/track_list.h>
915
916-#include <hybris/media/media_codec_layer.h>
917-
918 #include "core/media/service_implementation.h"
919
920+#include <core/posix/signal.h>
921+
922 #include <iostream>
923
924 namespace media = core::ubuntu::media;
925
926 using namespace std;
927
928+#if defined(MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER)
929+#include <hybris/media/media_codec_layer.h>
930+
931+namespace
932+{
933+// All platform-specific initialization routines go here.
934+void platform_init()
935+{
936+ decoding_service_init();
937+}
938+}
939+#else // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
940+namespace
941+{
942+// All platform-specific initialization routines go here.
943+void platform_init()
944+{
945+ // Consciously left empty
946+}
947+}
948+#endif // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
949+
950 int main()
951 {
952- // Init hybris-level DecodingService
953- decoding_service_init();
954- cout << "Starting DecodingService..." << endl;
955-
956- auto service = std::make_shared<media::ServiceImplementation>();
957- service->run();
958+ auto trap = core::posix::trap_signals_for_all_subsequent_threads(
959+ {
960+ core::posix::Signal::sig_int,
961+ core::posix::Signal::sig_term
962+ });
963+
964+ trap->signal_raised().connect([trap](core::posix::Signal)
965+ {
966+ trap->stop();
967+ });
968+
969+ // Init platform-specific functionality.
970+ platform_init();
971+
972+ // We keep track of our state.
973+ bool shutdown_requested{false};
974+
975+ // Our helper for connecting to external services.
976+ core::ubuntu::media::helper::ExternalServices external_services;
977+
978+ // We move communication with all external services to its own worker thread
979+ // to keep the actual service thread free from such operations.
980+ std::thread external_services_worker
981+ {
982+ // We keep on running until shutdown has been explicitly requested.
983+ // All exceptions thrown on this thread are caught, and reported to
984+ // the terminal for post-mortem debugging purposes.
985+ [&shutdown_requested, &external_services]()
986+ {
987+ while (not shutdown_requested)
988+ {
989+ try
990+ {
991+ // Blocking call to the underlying reactor implementation.
992+ // Only returns cleanly when explicitly stopped.
993+ external_services.io_service.run();
994+ }
995+ catch (const std::exception& e)
996+ {
997+ std::cerr << "Error while executing the underlying io_service: " << e.what() << std::endl;
998+ }
999+ catch (...)
1000+ {
1001+ std::cerr << "Error while executing the underlying io_service." << std::endl;
1002+ }
1003+ }
1004+ }
1005+ };
1006+
1007+ // We assemble the configuration for executing the service now.
1008+ media::ServiceImplementation::Configuration service_config
1009+ {
1010+ external_services
1011+ };
1012+
1013+ auto service = std::make_shared<media::ServiceImplementation>(service_config);
1014+
1015+ std::thread service_worker
1016+ {
1017+ [&shutdown_requested, service]()
1018+ {
1019+ while (not shutdown_requested)
1020+ {
1021+ try
1022+ {
1023+ service->run();
1024+ }
1025+ catch (const std::exception& e)
1026+ {
1027+ std::cerr << "Recoverable error while executing the service: " << e.what() << std::endl;
1028+ }
1029+ catch (...)
1030+ {
1031+ std::cerr << "Recoverable error while executing the service." << std::endl;
1032+ }
1033+ }
1034+ }
1035+ };
1036+
1037+ // We block on waiting for signals telling us to gracefully shutdown.
1038+ // Incoming signals are handled in a lambda connected to signal_raised()
1039+ // which is setup at the beginning of main(...).
1040+ trap->run();
1041+
1042+ // Inform our workers that we should shutdown gracefully
1043+ shutdown_requested = true;
1044+
1045+ // And stop execution of helper and actual service.
1046+ service->stop();
1047+
1048+ if (service_worker.joinable())
1049+ service_worker.join();
1050+
1051+ external_services.stop();
1052+
1053+ if (external_services_worker.joinable())
1054+ external_services_worker.join();
1055
1056 return 0;
1057 }
1058
1059=== modified file 'src/core/media/service_implementation.cpp'
1060--- src/core/media/service_implementation.cpp 2015-03-19 20:49:44 +0000
1061+++ src/core/media/service_implementation.cpp 2015-03-19 20:49:45 +0000
1062@@ -22,6 +22,7 @@
1063
1064 #include "service_implementation.h"
1065
1066+#include "client_death_observer.h"
1067 #include "indicator_power_service.h"
1068 #include "call-monitor/call_monitor.h"
1069 #include "player_configuration.h"
1070@@ -40,7 +41,6 @@
1071 #include <pulse/pulseaudio.h>
1072
1073 #include "util/timeout.h"
1074-#include "unity_screen_service.h"
1075
1076 namespace media = core::ubuntu::media;
1077
1078@@ -48,10 +48,13 @@
1079
1080 struct media::ServiceImplementation::Private
1081 {
1082- Private()
1083- : resume_key(std::numeric_limits<std::uint32_t>::max()),
1084- keep_alive(io_service),
1085- disp_cookie(0),
1086+ Private(const ServiceImplementation::Configuration& configuration)
1087+ : configuration(configuration),
1088+ resume_key(std::numeric_limits<std::uint32_t>::max()),
1089+ power_state_controller(media::power::make_platform_default_state_controller(configuration.external_services)),
1090+ display_state_lock(power_state_controller->display_state_lock()),
1091+ client_death_observer(media::platform_default_client_death_observer()),
1092+ recorder_observer(media::make_platform_default_recorder_observer()),
1093 pulse_mainloop_api(nullptr),
1094 pulse_context(nullptr),
1095 headphones_connected(false),
1096@@ -59,13 +62,6 @@
1097 primary_idx(-1),
1098 call_monitor(new CallMonitor)
1099 {
1100- bus = std::shared_ptr<dbus::Bus>(new dbus::Bus(core::dbus::WellKnownBus::session));
1101- bus->install_executor(dbus::asio::make_executor(bus, io_service));
1102- worker = std::move(std::thread([this]()
1103- {
1104- bus->run();
1105- }));
1106-
1107 // Spawn pulse watchdog
1108 pulse_mainloop = nullptr;
1109 pulse_worker = std::move(std::thread([this]()
1110@@ -129,19 +125,11 @@
1111
1112 // Connect the property change signal that will allow media-hub to take appropriate action
1113 // when the battery level reaches critical
1114- auto stub_service = dbus::Service::use_service(bus, "com.canonical.indicator.power");
1115+ auto stub_service = dbus::Service::use_service(configuration.external_services.session, "com.canonical.indicator.power");
1116 indicator_power_session = stub_service->object_for_path(dbus::types::ObjectPath("/com/canonical/indicator/power/Battery"));
1117 power_level = indicator_power_session->get_property<core::IndicatorPower::PowerLevel>();
1118 is_warning = indicator_power_session->get_property<core::IndicatorPower::IsWarning>();
1119
1120- // Obtain session with Unity.Screen so that we request state when doing recording
1121- auto bus = std::shared_ptr<dbus::Bus>(new dbus::Bus(core::dbus::WellKnownBus::system));
1122- bus->install_executor(dbus::asio::make_executor(bus));
1123-
1124- auto uscreen_stub_service = dbus::Service::use_service(bus, dbus::traits::Service<core::UScreen>::interface_name());
1125- uscreen_session = uscreen_stub_service->object_for_path(dbus::types::ObjectPath("/com/canonical/Unity/Screen"));
1126-
1127- recorder_observer = media::make_platform_default_recorder_observer();
1128 recorder_observer->recording_state().changed().connect([this](media::RecordingState state)
1129 {
1130 media_recording_state_changed(state);
1131@@ -159,42 +147,20 @@
1132 pulse_mainloop = nullptr;
1133 }
1134
1135- bus->stop();
1136-
1137- if (worker.joinable())
1138- worker.join();
1139-
1140 if (pulse_worker.joinable())
1141 pulse_worker.join();
1142 }
1143
1144 void media_recording_state_changed(media::RecordingState state)
1145 {
1146- if (uscreen_session == nullptr)
1147- return;
1148-
1149 if (state == media::RecordingState::started)
1150 {
1151- if (disp_cookie > 0)
1152- return;
1153-
1154- // Make sure we pause all playback sessions so that it doesn't interfere with recorded audio
1155+ display_state_lock->request_acquire(media::power::DisplayState::on);
1156 pause_playback();
1157-
1158- auto result = uscreen_session->invoke_method_synchronously<core::UScreen::keepDisplayOn, int>();
1159- if (result.is_error())
1160- throw std::runtime_error(result.error().print());
1161- disp_cookie = result.value();
1162 }
1163 else if (state == media::RecordingState::stopped)
1164 {
1165- if (disp_cookie != -1)
1166- {
1167- timeout(4000, true, [this](){
1168- this->uscreen_session->invoke_method_synchronously<core::UScreen::removeDisplayOnRequest, void>(this->disp_cookie);
1169- this->disp_cookie = -1;
1170- });
1171- }
1172+ display_state_lock->request_release(media::power::DisplayState::on);
1173 }
1174 }
1175
1176@@ -441,18 +407,16 @@
1177 }
1178 }
1179
1180+ media::ServiceImplementation::Configuration configuration;
1181 // This holds the key of the multimedia role Player instance that was paused
1182 // when the battery level reached 10% or 5%
1183- media::Player::PlayerKey resume_key;
1184- std::thread worker;
1185- dbus::Bus::Ptr bus;
1186- boost::asio::io_service io_service;
1187- boost::asio::io_service::work keep_alive;
1188+ media::Player::PlayerKey resume_key;
1189 std::shared_ptr<dbus::Object> indicator_power_session;
1190 std::shared_ptr<core::dbus::Property<core::IndicatorPower::PowerLevel>> power_level;
1191 std::shared_ptr<core::dbus::Property<core::IndicatorPower::IsWarning>> is_warning;
1192- int disp_cookie;
1193- std::shared_ptr<dbus::Object> uscreen_session;
1194+ media::power::StateController::Ptr power_state_controller;
1195+ media::power::StateController::Lock<media::power::DisplayState>::Ptr display_state_lock;
1196+ media::ClientDeathObserver::Ptr client_death_observer;
1197 media::RecorderObserver::Ptr recorder_observer;
1198 // Pulse-specific
1199 pa_mainloop_api *pulse_mainloop_api;
1200@@ -474,7 +438,7 @@
1201 std::list<media::Player::PlayerKey> paused_sessions;
1202 };
1203
1204-media::ServiceImplementation::ServiceImplementation() : d(new Private())
1205+media::ServiceImplementation::ServiceImplementation(const Configuration& configuration) : d(new Private(configuration))
1206 {
1207 d->power_level->changed().connect([this](const core::IndicatorPower::PowerLevel::ValueType &level)
1208 {
1209@@ -520,8 +484,16 @@
1210 std::shared_ptr<media::Player> media::ServiceImplementation::create_session(
1211 const media::Player::Configuration& conf)
1212 {
1213- auto player = std::make_shared<media::PlayerImplementation>(
1214- conf.identity, conf.bus, conf.session, shared_from_this(), conf.key);
1215+ auto player = std::make_shared<media::PlayerImplementation>(media::PlayerImplementation::Configuration
1216+ {
1217+ conf.identity,
1218+ conf.bus,
1219+ conf.session,
1220+ shared_from_this(),
1221+ conf.key,
1222+ d->client_death_observer,
1223+ d->power_state_controller
1224+ });
1225
1226 auto key = conf.key;
1227 player->on_client_disconnected().connect([this, key]()
1228@@ -531,7 +503,7 @@
1229 // remove_player_for_key can destroy the player instance which in turn
1230 // destroys the "on_client_disconnected" signal whose destructor will wait
1231 // until all dispatches are done
1232- d->io_service.post([this, key]()
1233+ d->configuration.external_services.io_service.post([this, key]()
1234 {
1235 if (!has_player_for_key(key))
1236 return;
1237
1238=== modified file 'src/core/media/service_implementation.h'
1239--- src/core/media/service_implementation.h 2015-01-16 17:17:30 +0000
1240+++ src/core/media/service_implementation.h 2015-03-19 20:49:45 +0000
1241@@ -20,6 +20,7 @@
1242 #define CORE_UBUNTU_MEDIA_SERVICE_IMPLEMENTATION_H_
1243
1244 #include "service_skeleton.h"
1245+#include "external_services.h"
1246
1247 namespace core
1248 {
1249@@ -27,13 +28,18 @@
1250 {
1251 namespace media
1252 {
1253-
1254 class Player;
1255
1256 class ServiceImplementation : public ServiceSkeleton
1257 {
1258 public:
1259- ServiceImplementation ();
1260+ // All creation time arguments go here.
1261+ struct Configuration
1262+ {
1263+ helper::ExternalServices& external_services;
1264+ };
1265+
1266+ ServiceImplementation (const Configuration& configuration);
1267 ~ServiceImplementation ();
1268
1269 std::shared_ptr<Player> create_session(const Player::Configuration&);
1270
1271=== removed file 'src/core/media/unity_screen_service.h'
1272--- src/core/media/unity_screen_service.h 2014-06-16 22:28:53 +0000
1273+++ src/core/media/unity_screen_service.h 1970-01-01 00:00:00 +0000
1274@@ -1,72 +0,0 @@
1275-/*
1276- * Copyright (C) 2014 Canonical Ltd
1277- *
1278- * This program is free software: you can redistribute it and/or modify
1279- * it under the terms of the GNU Lesser General Public License version 3 as
1280- * published by the Free Software Foundation.
1281- *
1282- * This program is distributed in the hope that it will be useful,
1283- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1284- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1285- * GNU Lesser General Public License for more details.
1286- *
1287- * You should have received a copy of the GNU Lesser General Public License
1288- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1289- *
1290- * Author: Alberto Aguirre <alberto.aguirre@canonical.com>
1291- */
1292-
1293-#include <core/dbus/dbus.h>
1294-#include <core/dbus/fixture.h>
1295-#include <core/dbus/object.h>
1296-#include <core/dbus/property.h>
1297-#include <core/dbus/service.h>
1298-#include <core/dbus/interfaces/properties.h>
1299-#include <core/dbus/types/stl/tuple.h>
1300-#include <core/dbus/types/stl/vector.h>
1301-
1302-#include <core/dbus/asio/executor.h>
1303-
1304-#include <string>
1305-#include <vector>
1306-#include <chrono>
1307-
1308-namespace core
1309-{
1310-
1311-struct UScreen
1312-{
1313- static std::string& name()
1314- {
1315- static std::string s = "com.canonical.Unity.Screen";
1316- return s;
1317- }
1318-
1319- struct keepDisplayOn
1320- {
1321- static std::string name()
1322- {
1323- static std::string s = "keepDisplayOn";
1324- return s;
1325- }
1326-
1327- static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
1328-
1329- typedef UScreen Interface;
1330- };
1331-
1332- struct removeDisplayOnRequest
1333- {
1334- static std::string name()
1335- {
1336- static std::string s = "removeDisplayOnRequest";
1337- return s;
1338- }
1339-
1340- static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
1341-
1342- typedef UScreen Interface;
1343- };
1344-};
1345-
1346-}
1347
1348=== modified file 'tests/CMakeLists.txt'
1349--- tests/CMakeLists.txt 2014-02-14 08:12:35 +0000
1350+++ tests/CMakeLists.txt 2015-03-19 20:49:45 +0000
1351@@ -50,5 +50,5 @@
1352 "COM_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME=fakesink"
1353 )
1354
1355-add_subdirectory(acceptance-tests)
1356+# add_subdirectory(acceptance-tests)
1357 add_subdirectory(unit-tests)

Subscribers

People subscribed via source and target branches