Merge lp:~phablet-team/media-hub/multiple-sessions into lp:media-hub

Proposed by Jim Hodapp
Status: Merged
Merged at revision: 28
Proposed branch: lp:~phablet-team/media-hub/multiple-sessions
Merge into: lp:media-hub
Prerequisite: lp:~phablet-team/media-hub/video-support
Diff against target: 808 lines (+224/-40)
21 files modified
include/core/media/player.h (+3/-0)
include/core/media/service.h (+1/-0)
src/core/media/apparmor.h (+1/-1)
src/core/media/engine.h (+2/-0)
src/core/media/gstreamer/engine.cpp (+19/-0)
src/core/media/gstreamer/engine.h (+1/-0)
src/core/media/gstreamer/playbin.h (+5/-2)
src/core/media/mpris/player.h (+2/-0)
src/core/media/mpris/service.h (+1/-0)
src/core/media/player_implementation.cpp (+25/-8)
src/core/media/player_implementation.h (+3/-1)
src/core/media/player_skeleton.cpp (+33/-5)
src/core/media/player_skeleton.h (+1/-0)
src/core/media/player_stub.cpp (+30/-5)
src/core/media/player_stub.h (+2/-0)
src/core/media/service_implementation.cpp (+57/-10)
src/core/media/service_implementation.h (+5/-0)
src/core/media/service_skeleton.cpp (+17/-1)
src/core/media/service_skeleton.h (+1/-1)
src/core/media/service_stub.cpp (+13/-5)
src/core/media/service_stub.h (+2/-1)
To merge this branch: bzr merge lp:~phablet-team/media-hub/multiple-sessions
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Ubuntu Phablet Team Pending
Review via email: mp+217452@code.launchpad.net

Commit message

* One Engine instance per PlayerImplementation instance instead of one global Engine instance
* Pause other playing sessions when starting playback of a new foreground player
* Emit a PlaybackStatusChanged signal so that qtubuntu-media knows when PlaybackStatus changes from underneath it
* Use GST_SEEK_FLAG_KEY_UNIT instead because seeking doesn't perform well enough with GST_SEEK_FLAG_ACCURATE

Description of the change

* One Engine instance per PlayerImplementation instance instead of one global Engine instance
* Pause other playing sessions when starting playback of a new foreground player
* Emit a PlaybackStatusChanged signal so that qtubuntu-media knows when PlaybackStatus changes from underneath it
* Use GST_SEEK_FLAG_KEY_UNIT instead because seeking doesn't perform well enough with GST_SEEK_FLAG_ACCURATE

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/core/media/player.h'
2--- include/core/media/player.h 2014-04-28 14:20:04 +0000
3+++ include/core/media/player.h 2014-04-28 14:20:05 +0000
4@@ -39,6 +39,7 @@
5 public:
6 typedef double PlaybackRate;
7 typedef double Volume;
8+ typedef uint32_t PlayerKey;
9 typedef void* GLConsumerWrapperHybris;
10
11 /** Used to set a callback function to be called when a frame is ready to be rendered **/
12@@ -78,6 +79,7 @@
13 bool operator==(const Player&) const = delete;
14
15 virtual std::shared_ptr<TrackList> track_list() = 0;
16+ virtual PlayerKey key() const = 0;
17
18 virtual bool open_uri(const Track::UriType& uri) = 0;
19 virtual void create_video_sink(uint32_t texture_id) = 0;
20@@ -118,6 +120,7 @@
21
22 virtual const core::Signal<uint64_t>& seeked_to() const = 0;
23 virtual const core::Signal<void>& end_of_stream() const = 0;
24+ virtual core::Signal<PlaybackStatus>& playback_status_changed() = 0;
25 protected:
26 Player();
27
28
29=== modified file 'include/core/media/service.h'
30--- include/core/media/service.h 2014-01-13 21:51:14 +0000
31+++ include/core/media/service.h 2014-04-28 14:20:05 +0000
32@@ -43,6 +43,7 @@
33 bool operator==(const Service&) const = delete;
34
35 virtual std::shared_ptr<Player> create_session(const Player::Configuration&) = 0;
36+ virtual void pause_other_sessions(Player::PlayerKey) = 0;
37
38 protected:
39 Service() = default;
40
41=== modified file 'src/core/media/apparmor.h'
42--- src/core/media/apparmor.h 2014-04-28 14:20:04 +0000
43+++ src/core/media/apparmor.h 2014-04-28 14:20:05 +0000
44@@ -13,7 +13,7 @@
45 * You should have received a copy of the GNU Lesser General Public License
46 * along with this program. If not, see <http://www.gnu.org/licenses/>.
47 *
48- * Author: Ricardo Mendoza <ricardo.mendoza@canonical.com>
49+ * Author: Jim Hodapp <jim.hodapp@canonical.com>
50 */
51
52 #ifndef APPARMOR_H_DBUS_
53
54=== modified file 'src/core/media/engine.h'
55--- src/core/media/engine.h 2014-04-28 14:20:04 +0000
56+++ src/core/media/engine.h 2014-04-28 14:20:05 +0000
57@@ -18,6 +18,7 @@
58 #ifndef CORE_UBUNTU_MEDIA_ENGINE_H_
59 #define CORE_UBUNTU_MEDIA_ENGINE_H_
60
61+#include <core/media/player.h>
62 #include <core/media/track.h>
63
64 #include <core/property.h>
65@@ -118,6 +119,7 @@
66 virtual const core::Signal<void>& about_to_finish_signal() const = 0;
67 virtual const core::Signal<uint64_t>& seeked_to_signal() const = 0;
68 virtual const core::Signal<void>& end_of_stream_signal() const = 0;
69+ virtual const core::Signal<core::ubuntu::media::Player::PlaybackStatus>& playback_status_changed_signal() const = 0;
70 };
71 }
72 }
73
74=== modified file 'src/core/media/gstreamer/engine.cpp'
75--- src/core/media/gstreamer/engine.cpp 2014-04-28 14:20:04 +0000
76+++ src/core/media/gstreamer/engine.cpp 2014-04-28 14:20:05 +0000
77@@ -28,6 +28,8 @@
78
79 namespace media = core::ubuntu::media;
80
81+using namespace std;
82+
83 namespace gstreamer
84 {
85 struct Init
86@@ -239,10 +241,12 @@
87 core::Signal<void> about_to_finish;
88 core::Signal<uint64_t> seeked_to;
89 core::Signal<void> end_of_stream;
90+ core::Signal<media::Player::PlaybackStatus> playback_status_changed;
91 };
92
93 gstreamer::Engine::Engine() : d(new Private{})
94 {
95+ cout << "Creating a new Engine instance in " << __PRETTY_FUNCTION__ << endl;
96 d->state = media::Engine::State::ready;
97 }
98
99@@ -279,8 +283,11 @@
100 if (result)
101 {
102 d->state = media::Engine::State::playing;
103+ d->playback_status_changed(media::Player::PlaybackStatus::playing);
104 }
105
106+ cout << "Engine: " << this << endl;
107+
108 return result;
109 }
110
111@@ -289,7 +296,10 @@
112 auto result = d->playbin.set_state_and_wait(GST_STATE_NULL);
113
114 if (result)
115+ {
116 d->state = media::Engine::State::stopped;
117+ d->playback_status_changed(media::Player::PlaybackStatus::stopped);
118+ }
119
120 return result;
121 }
122@@ -299,7 +309,11 @@
123 auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);
124
125 if (result)
126+ {
127 d->state = media::Engine::State::paused;
128+ cout << "pause" << endl;
129+ d->playback_status_changed(media::Player::PlaybackStatus::paused);
130+ }
131
132 return result;
133 }
134@@ -373,3 +387,8 @@
135 {
136 return d->end_of_stream;
137 }
138+
139+const core::Signal<media::Player::PlaybackStatus>& gstreamer::Engine::playback_status_changed_signal() const
140+{
141+ return d->playback_status_changed;
142+}
143
144=== modified file 'src/core/media/gstreamer/engine.h'
145--- src/core/media/gstreamer/engine.h 2014-04-28 14:20:04 +0000
146+++ src/core/media/gstreamer/engine.h 2014-04-28 14:20:05 +0000
147@@ -54,6 +54,7 @@
148 const core::Signal<void>& about_to_finish_signal() const;
149 const core::Signal<uint64_t>& seeked_to_signal() const;
150 const core::Signal<void>& end_of_stream_signal() const;
151+ const core::Signal<core::ubuntu::media::Player::PlaybackStatus>& playback_status_changed_signal() const;
152
153 private:
154 struct Private;
155
156=== modified file 'src/core/media/gstreamer/playbin.h'
157--- src/core/media/gstreamer/playbin.h 2014-04-28 14:20:04 +0000
158+++ src/core/media/gstreamer/playbin.h 2014-04-28 14:20:05 +0000
159@@ -20,6 +20,7 @@
160 #define GSTREAMER_PLAYBIN_H_
161
162 #include "bus.h"
163+#include "../mpris/player.h"
164
165 #include <hybris/media/media_codec_layer.h>
166 #include <hybris/media/surface_texture_client_hybris.h>
167@@ -30,6 +31,8 @@
168 #include <chrono>
169 #include <string>
170
171+namespace media = core::ubuntu::media;
172+
173 namespace gstreamer
174 {
175 struct Playbin
176@@ -312,8 +315,7 @@
177 return gst_element_seek_simple(
178 pipeline,
179 GST_FORMAT_TIME,
180- (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT |
181- GST_SEEK_FLAG_SNAP_BEFORE),
182+ (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
183 ms.count() * 1000);
184 }
185
186@@ -408,6 +410,7 @@
187 core::Signal<Bus::Message::Detail::StateChanged> on_state_changed;
188 core::Signal<uint64_t> on_seeked_to;
189 core::Signal<void> on_end_of_stream;
190+ core::Signal<media::Player::PlaybackStatus> on_playback_status_changed;
191 } signals;
192 };
193 }
194
195=== modified file 'src/core/media/mpris/player.h'
196--- src/core/media/mpris/player.h 2014-04-28 14:20:04 +0000
197+++ src/core/media/mpris/player.h 2014-04-28 14:20:05 +0000
198@@ -55,12 +55,14 @@
199 METHOD(Seek, Player, std::chrono::seconds(1))
200 METHOD(SetPosition, Player, std::chrono::seconds(1))
201 METHOD(CreateVideoSink, Player, std::chrono::seconds(1))
202+ METHOD(Key, Player, std::chrono::seconds(1))
203 METHOD(OpenUri, Player, std::chrono::seconds(1))
204
205 struct Signals
206 {
207 SIGNAL(Seeked, Player, uint64_t)
208 SIGNAL(EndOfStream, Player, void)
209+ SIGNAL(PlaybackStatusChanged, Player, core::ubuntu::media::Player::PlaybackStatus)
210 };
211
212 struct Properties
213
214=== modified file 'src/core/media/mpris/service.h'
215--- src/core/media/mpris/service.h 2014-01-13 21:51:14 +0000
216+++ src/core/media/mpris/service.h 2014-04-28 14:20:05 +0000
217@@ -50,6 +50,7 @@
218 };
219
220 METHOD(CreateSession, Service, std::chrono::seconds(1))
221+ METHOD(PauseOtherSessions, Service, std::chrono::seconds(1))
222 };
223 }
224
225
226=== modified file 'src/core/media/player_implementation.cpp'
227--- src/core/media/player_implementation.cpp 2014-04-28 14:20:04 +0000
228+++ src/core/media/player_implementation.cpp 2014-04-28 14:20:05 +0000
229@@ -22,24 +22,29 @@
230 #include "engine.h"
231 #include "track_list_implementation.h"
232
233+#include "gstreamer/engine.h"
234+
235 #define UNUSED __attribute__((unused))
236
237 namespace media = core::ubuntu::media;
238
239+using namespace std;
240+
241 struct media::PlayerImplementation::Private
242 {
243 Private(PlayerImplementation* parent,
244 const dbus::types::ObjectPath& session_path,
245 const std::shared_ptr<media::Service>& service,
246- const std::shared_ptr<media::Engine>& engine)
247+ PlayerImplementation::PlayerKey key)
248 : parent(parent),
249 service(service),
250- engine(engine),
251+ engine(std::make_shared<gstreamer::Engine>()),
252 session_path(session_path),
253 track_list(
254 new media::TrackListImplementation(
255 session_path.as_string() + "/TrackList",
256- engine->meta_data_extractor()))
257+ engine->meta_data_extractor())),
258+ key(key)
259 {
260 engine->state().changed().connect(
261 [parent](const Engine::State& state)
262@@ -62,18 +67,19 @@
263 std::shared_ptr<Engine> engine;
264 dbus::types::ObjectPath session_path;
265 std::shared_ptr<TrackListImplementation> track_list;
266+ PlayerImplementation::PlayerKey key;
267 };
268
269 media::PlayerImplementation::PlayerImplementation(
270 const dbus::types::ObjectPath& session_path,
271 const std::shared_ptr<Service>& service,
272- const std::shared_ptr<Engine>& engine)
273+ PlayerKey key)
274 : media::PlayerSkeleton(session_path),
275 d(new Private(
276 this,
277 session_path,
278 service,
279- engine))
280+ key))
281 {
282 // Initializing default values for properties
283 can_play().set(true);
284@@ -118,7 +124,7 @@
285 };
286 is_audio_source().install(audio_type_getter);
287
288- engine->about_to_finish_signal().connect([this]()
289+ d->engine->about_to_finish_signal().connect([this]()
290 {
291 if (d->track_list->has_next())
292 {
293@@ -128,15 +134,20 @@
294 }
295 });
296
297- engine->seeked_to_signal().connect([this](uint64_t value)
298+ d->engine->seeked_to_signal().connect([this](uint64_t value)
299 {
300 seeked_to()(value);
301 });
302
303- engine->end_of_stream_signal().connect([this]()
304+ d->engine->end_of_stream_signal().connect([this]()
305 {
306 end_of_stream()();
307 });
308+
309+ d->engine->playback_status_changed_signal().connect([this](const Player::PlaybackStatus& status)
310+ {
311+ playback_status_changed()(status);
312+ });
313 }
314
315 media::PlayerImplementation::~PlayerImplementation()
316@@ -148,6 +159,12 @@
317 return d->track_list;
318 }
319
320+// TODO: Convert this to be a property instead of sync call
321+media::Player::PlayerKey media::PlayerImplementation::key() const
322+{
323+ return d->key;
324+}
325+
326 bool media::PlayerImplementation::open_uri(const Track::UriType& uri)
327 {
328 return d->engine->open_resource_for_uri(uri);
329
330=== modified file 'src/core/media/player_implementation.h'
331--- src/core/media/player_implementation.h 2014-04-28 14:20:04 +0000
332+++ src/core/media/player_implementation.h 2014-04-28 14:20:05 +0000
333@@ -1,4 +1,5 @@
334 /*
335+ * Copyright © 2013-2014 Canonical Ltd.
336 *
337 * This program is free software: you can redistribute it and/or modify it
338 * under the terms of the GNU Lesser General Public License version 3,
339@@ -37,10 +38,11 @@
340 PlayerImplementation(
341 const core::dbus::types::ObjectPath& session_path,
342 const std::shared_ptr<Service>& service,
343- const std::shared_ptr<Engine>& engine);
344+ PlayerKey key);
345 ~PlayerImplementation();
346
347 virtual std::shared_ptr<TrackList> track_list();
348+ virtual PlayerKey key() const;
349
350 virtual bool open_uri(const Track::UriType& uri);
351 virtual void create_video_sink(uint32_t texture_id);
352
353=== modified file 'src/core/media/player_skeleton.cpp'
354--- src/core/media/player_skeleton.cpp 2014-04-28 14:20:04 +0000
355+++ src/core/media/player_skeleton.cpp 2014-04-28 14:20:05 +0000
356@@ -1,5 +1,5 @@
357 /*
358- * Copyright © 2013 Canonical Ltd.
359+ * Copyright © 2013-2014 Canonical Ltd.
360 *
361 * This program is free software: you can redistribute it and/or modify it
362 * under the terms of the GNU Lesser General Public License version 3,
363@@ -63,7 +63,8 @@
364 signals
365 {
366 object->get_signal<mpris::Player::Signals::Seeked>(),
367- object->get_signal<mpris::Player::Signals::EndOfStream>()
368+ object->get_signal<mpris::Player::Signals::EndOfStream>(),
369+ object->get_signal<mpris::Player::Signals::PlaybackStatusChanged>()
370 }
371 {
372 }
373@@ -219,6 +220,13 @@
374 }
375 }
376
377+ void handle_key(const core::dbus::Message::Ptr& in)
378+ {
379+ auto reply = dbus::Message::make_method_return(in);
380+ reply->writer() << impl->key();
381+ impl->access_bus()->send(reply);
382+ }
383+
384 void handle_open_uri(const core::dbus::Message::Ptr& in)
385 {
386 Track::UriType uri;
387@@ -265,16 +273,20 @@
388 {
389 typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
390 typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
391+ typedef core::dbus::Signal<mpris::Player::Signals::PlaybackStatusChanged, mpris::Player::Signals::PlaybackStatusChanged::ArgumentType> DBusPlaybackStatusChangedSignal;
392
393 Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked,
394- const std::shared_ptr<DBusEndOfStreamSignal>& eos)
395+ const std::shared_ptr<DBusEndOfStreamSignal>& eos,
396+ const std::shared_ptr<DBusPlaybackStatusChangedSignal>& status)
397 : dbus
398 {
399 seeked,
400- eos
401+ eos,
402+ status
403 },
404 seeked_to(),
405- end_of_stream()
406+ end_of_stream(),
407+ playback_status_changed()
408 {
409 seeked_to.connect([this](std::uint64_t value)
410 {
411@@ -285,15 +297,22 @@
412 {
413 dbus.end_of_stream->emit();
414 });
415+
416+ playback_status_changed.connect([this](const media::Player::PlaybackStatus& status)
417+ {
418+ dbus.playback_status_changed->emit(status);
419+ });
420 }
421
422 struct DBus
423 {
424 std::shared_ptr<DBusSeekedToSignal> seeked_to;
425 std::shared_ptr<DBusEndOfStreamSignal> end_of_stream;
426+ std::shared_ptr<DBusPlaybackStatusChangedSignal> playback_status_changed;
427 } dbus;
428 core::Signal<uint64_t> seeked_to;
429 core::Signal<void> end_of_stream;
430+ core::Signal<media::Player::PlaybackStatus> playback_status_changed;
431 } signals;
432
433 };
434@@ -335,6 +354,10 @@
435 std::bind(&Private::handle_create_video_sink,
436 std::ref(d),
437 std::placeholders::_1));
438+ d->object->install_method_handler<mpris::Player::Key>(
439+ std::bind(&Private::handle_key,
440+ std::ref(d),
441+ std::placeholders::_1));
442 d->object->install_method_handler<mpris::Player::OpenUri>(
443 std::bind(&Private::handle_open_uri,
444 std::ref(d),
445@@ -535,3 +558,8 @@
446 {
447 return d->signals.end_of_stream;
448 }
449+
450+core::Signal<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status_changed()
451+{
452+ return d->signals.playback_status_changed;
453+}
454
455=== modified file 'src/core/media/player_skeleton.h'
456--- src/core/media/player_skeleton.h 2014-04-28 14:20:04 +0000
457+++ src/core/media/player_skeleton.h 2014-04-28 14:20:05 +0000
458@@ -68,6 +68,7 @@
459
460 virtual const core::Signal<uint64_t>& seeked_to() const;
461 virtual const core::Signal<void>& end_of_stream() const;
462+ virtual core::Signal<PlaybackStatus>& playback_status_changed();
463
464 protected:
465 PlayerSkeleton(const core::dbus::types::ObjectPath& session_path);
466
467=== modified file 'src/core/media/player_stub.cpp'
468--- src/core/media/player_stub.cpp 2014-04-28 14:20:04 +0000
469+++ src/core/media/player_stub.cpp 2014-04-28 14:20:05 +0000
470@@ -80,7 +80,8 @@
471 signals
472 {
473 object->get_signal<mpris::Player::Signals::Seeked>(),
474- object->get_signal<mpris::Player::Signals::EndOfStream>()
475+ object->get_signal<mpris::Player::Signals::EndOfStream>(),
476+ object->get_signal<mpris::Player::Signals::PlaybackStatusChanged>()
477 }
478 {
479 }
480@@ -136,7 +137,7 @@
481
482 FrameAvailableCb frame_available_cb;
483 void *frame_available_context;
484-
485+
486 dbus::Bus::Ptr bus;
487 dbus::types::ObjectPath path;
488 dbus::Object::Ptr object;
489@@ -168,18 +169,22 @@
490 {
491 typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
492 typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
493+ typedef core::dbus::Signal<mpris::Player::Signals::PlaybackStatusChanged, mpris::Player::Signals::PlaybackStatusChanged::ArgumentType> DBusPlaybackStatusChangedSignal;
494
495 Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked,
496- const std::shared_ptr<DBusEndOfStreamSignal>& eos)
497+ const std::shared_ptr<DBusEndOfStreamSignal>& eos,
498+ const std::shared_ptr<DBusPlaybackStatusChangedSignal>& status)
499 : dbus
500 {
501 seeked,
502- eos
503+ eos,
504+ status
505 },
506 playback_complete_cb(nullptr),
507 playback_complete_context(nullptr),
508 seeked_to(),
509- end_of_stream()
510+ end_of_stream(),
511+ playback_status_changed()
512 {
513 dbus.seeked_to->connect([this](std::uint64_t value)
514 {
515@@ -194,12 +199,19 @@
516 playback_complete_cb(playback_complete_context);
517 end_of_stream();
518 });
519+
520+ dbus.playback_status_changed->connect([this](const media::Player::PlaybackStatus& status)
521+ {
522+ std::cout << "PlaybackStatusChanged signal arrived via the bus." << std::endl;
523+ playback_status_changed(status);
524+ });
525 }
526
527 struct DBus
528 {
529 std::shared_ptr<DBusSeekedToSignal> seeked_to;
530 std::shared_ptr<DBusEndOfStreamSignal> end_of_stream;
531+ std::shared_ptr<DBusPlaybackStatusChangedSignal> playback_status_changed;
532 } dbus;
533
534 void set_playback_complete_cb(PlaybackCompleteCb cb, void *context)
535@@ -212,6 +224,7 @@
536 void *playback_complete_context;
537 core::Signal<uint64_t> seeked_to;
538 core::Signal<void> end_of_stream;
539+ core::Signal<media::Player::PlaybackStatus> playback_status_changed;
540 } signals;
541 };
542
543@@ -243,6 +256,13 @@
544 return d->track_list;
545 }
546
547+media::Player::PlayerKey media::PlayerStub::key() const
548+{
549+ auto op = d->object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>();
550+
551+ return op.value();
552+}
553+
554 bool media::PlayerStub::open_uri(const media::Track::UriType& uri)
555 {
556 auto op = d->object->invoke_method_synchronously<mpris::Player::OpenUri, bool>(uri);
557@@ -437,3 +457,8 @@
558 {
559 return d->signals.end_of_stream;
560 }
561+
562+core::Signal<media::Player::PlaybackStatus>& media::PlayerStub::playback_status_changed()
563+{
564+ return d->signals.playback_status_changed;
565+}
566
567=== modified file 'src/core/media/player_stub.h'
568--- src/core/media/player_stub.h 2014-04-28 14:20:04 +0000
569+++ src/core/media/player_stub.h 2014-04-28 14:20:05 +0000
570@@ -43,6 +43,7 @@
571 ~PlayerStub();
572
573 virtual std::shared_ptr<TrackList> track_list();
574+ virtual PlayerKey key() const;
575
576 virtual bool open_uri(const Track::UriType& uri);
577 virtual void create_video_sink(uint32_t texture_id);
578@@ -82,6 +83,7 @@
579
580 virtual const core::Signal<uint64_t>& seeked_to() const;
581 virtual const core::Signal<void>& end_of_stream() const;
582+ virtual core::Signal<PlaybackStatus>& playback_status_changed();
583
584 private:
585 struct Private;
586
587=== modified file 'src/core/media/service_implementation.cpp'
588--- src/core/media/service_implementation.cpp 2014-01-13 21:51:14 +0000
589+++ src/core/media/service_implementation.cpp 2014-04-28 14:20:05 +0000
590@@ -21,21 +21,63 @@
591 #include "player_configuration.h"
592 #include "player_implementation.h"
593
594-#include "gstreamer/engine.h"
595+#include <map>
596
597 namespace media = core::ubuntu::media;
598
599+using namespace std;
600+
601 struct media::ServiceImplementation::Private
602 {
603- Private() : engine(std::make_shared<gstreamer::Engine>())
604- {
605- }
606- std::shared_ptr<media::Engine> engine;
607+ Private()
608+ : key_(0)
609+ {
610+ }
611+
612+ void track_player(const std::shared_ptr<media::Player>& player)
613+ {
614+ cout << __PRETTY_FUNCTION__ << endl;
615+ cout << "key: " << key_ << endl;
616+ player_map.insert(
617+ std::pair<media::Player::PlayerKey,
618+ std::shared_ptr<media::Player>>(key_, player));
619+
620+ ++key_;
621+ }
622+
623+ inline media::Player::PlayerKey key() const
624+ {
625+ return key_;
626+ }
627+
628+ void pause_other_sessions(media::Player::PlayerKey key)
629+ {
630+ cout << __PRETTY_FUNCTION__ << endl;
631+ cout << "key: " << key << endl;
632+
633+ // TODO: Add a field to Player that is the type of player so that certain
634+ // types of playback aren't paused below. E.g. a camera click sound shouldn't
635+ // pause, nor should it pause background music sessions
636+ for (auto& player_pair : player_map)
637+ {
638+ if (player_pair.second->playback_status() == Player::playing
639+ && player_pair.first != key)
640+ {
641+ cout << "Pausing player with key: " << player_pair.first << endl;
642+ player_pair.second->pause();
643+ }
644+ }
645+ }
646+
647+ // Used for Player instance management
648+ std::map<media::Player::PlayerKey, std::shared_ptr<media::Player>> player_map;
649+ media::Player::PlayerKey key_;
650+
651 };
652
653 media::ServiceImplementation::ServiceImplementation() : d(new Private())
654 {
655-
656+ cout << __PRETTY_FUNCTION__ << endl;
657 }
658
659 media::ServiceImplementation::~ServiceImplementation()
660@@ -45,8 +87,13 @@
661 std::shared_ptr<media::Player> media::ServiceImplementation::create_session(
662 const media::Player::Configuration& conf)
663 {
664- return std::make_shared<media::PlayerImplementation>(
665- conf.object_path,
666- shared_from_this(),
667- d->engine);
668+ std::shared_ptr<media::Player> player = std::make_shared<media::PlayerImplementation>(
669+ conf.object_path, shared_from_this(), d->key());
670+ d->track_player(player);
671+ return player;
672+}
673+
674+void media::ServiceImplementation::pause_other_sessions(media::Player::PlayerKey key)
675+{
676+ d->pause_other_sessions(key);
677 }
678
679=== modified file 'src/core/media/service_implementation.h'
680--- src/core/media/service_implementation.h 2014-01-13 21:51:14 +0000
681+++ src/core/media/service_implementation.h 2014-04-28 14:20:05 +0000
682@@ -27,6 +27,9 @@
683 {
684 namespace media
685 {
686+
687+class Player;
688+
689 class ServiceImplementation : public ServiceSkeleton
690 {
691 public:
692@@ -35,6 +38,8 @@
693
694 std::shared_ptr<Player> create_session(const Player::Configuration&);
695
696+ void pause_other_sessions(Player::PlayerKey key);
697+
698 private:
699 struct Private;
700 std::shared_ptr<Private> d;
701
702=== modified file 'src/core/media/service_skeleton.cpp'
703--- src/core/media/service_skeleton.cpp 2014-02-12 15:53:57 +0000
704+++ src/core/media/service_skeleton.cpp 2014-04-28 14:20:05 +0000
705@@ -1,5 +1,5 @@
706 /*
707- * Copyright © 2013 Canonical Ltd.
708+ * Copyright © 2013-2014 Canonical Ltd.
709 *
710 * This program is free software: you can redistribute it and/or modify it
711 * under the terms of the GNU Lesser General Public License version 3,
712@@ -49,6 +49,11 @@
713 &Private::handle_create_session,
714 this,
715 std::placeholders::_1));
716+ object->install_method_handler<mpris::Service::PauseOtherSessions>(
717+ std::bind(
718+ &Private::handle_pause_other_sessions,
719+ this,
720+ std::placeholders::_1));
721 }
722
723 void handle_create_session(const core::dbus::Message::Ptr& msg)
724@@ -86,6 +91,17 @@
725 }
726 }
727
728+ void handle_pause_other_sessions(const core::dbus::Message::Ptr& msg)
729+ {
730+ std::cout << __PRETTY_FUNCTION__ << std::endl;
731+ Player::PlayerKey key;
732+ msg->reader() >> key;
733+ impl->pause_other_sessions(key);
734+
735+ auto reply = dbus::Message::make_method_return(msg);
736+ impl->access_bus()->send(reply);
737+ }
738+
739 media::ServiceSkeleton* impl;
740 dbus::Object::Ptr object;
741
742
743=== modified file 'src/core/media/service_skeleton.h'
744--- src/core/media/service_skeleton.h 2014-02-12 15:53:57 +0000
745+++ src/core/media/service_skeleton.h 2014-04-28 14:20:05 +0000
746@@ -1,5 +1,5 @@
747 /*
748- * Copyright © 2013 Canonical Ltd.
749+ * Copyright © 2013-2014 Canonical Ltd.
750 *
751 * This program is free software: you can redistribute it and/or modify it
752 * under the terms of the GNU Lesser General Public License version 3,
753
754=== modified file 'src/core/media/service_stub.cpp'
755--- src/core/media/service_stub.cpp 2014-02-12 15:53:57 +0000
756+++ src/core/media/service_stub.cpp 2014-04-28 14:20:05 +0000
757@@ -1,5 +1,5 @@
758 /*
759- * Copyright © 2013 Canonical Ltd.
760+ * Copyright © 2013-2014 Canonical Ltd.
761 *
762 * This program is free software: you can redistribute it and/or modify it
763 * under the terms of the GNU Lesser General Public License version 3,
764@@ -47,13 +47,21 @@
765
766 std::shared_ptr<media::Player> media::ServiceStub::create_session(const media::Player::Configuration&)
767 {
768- auto op
769- = d->object->invoke_method_synchronously<
770- mpris::Service::CreateSession,
771- dbus::types::ObjectPath>();
772+ auto op = d->object->invoke_method_synchronously<mpris::Service::CreateSession,
773+ dbus::types::ObjectPath>();
774
775 if (op.is_error())
776 throw std::runtime_error("Problem creating session: " + op.error());
777
778 return std::shared_ptr<media::Player>(new media::PlayerStub(shared_from_this(), op.value()));
779 }
780+
781+void media::ServiceStub::pause_other_sessions(media::Player::PlayerKey key)
782+{
783+ std::cout << __PRETTY_FUNCTION__ << std::endl;
784+ auto op = d->object->invoke_method_synchronously<mpris::Service::PauseOtherSessions,
785+ void>(key);
786+
787+ if (op.is_error())
788+ throw std::runtime_error("Problem pausing other sessions: " + op.error());
789+}
790
791=== modified file 'src/core/media/service_stub.h'
792--- src/core/media/service_stub.h 2014-02-12 15:53:57 +0000
793+++ src/core/media/service_stub.h 2014-04-28 14:20:05 +0000
794@@ -1,5 +1,5 @@
795 /*
796- * Copyright © 2013 Canonical Ltd.
797+ * Copyright © 2013-2014 Canonical Ltd.
798 *
799 * This program is free software: you can redistribute it and/or modify it
800 * under the terms of the GNU Lesser General Public License version 3,
801@@ -40,6 +40,7 @@
802 ~ServiceStub();
803
804 std::shared_ptr<Player> create_session(const Player::Configuration&);
805+ void pause_other_sessions(Player::PlayerKey key);
806
807 private:
808 struct Private;

Subscribers

People subscribed via source and target branches

to all changes: