Music Hub  ..
A session-wide music playback service
player_stub.cpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2013-2015 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License version 3,
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY {} without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authored by: Thomas Voß <thomas.voss@canonical.com>
17  * Jim Hodapp <jim.hodapp@canonical.com>
18  */
19 
20 #include <core/media/service.h>
21 #include <core/media/track_list.h>
23 
24 #include "codec.h"
25 #include "player_stub.h"
26 #include "player_traits.h"
27 #include "property_stub.h"
28 #include "the_session_bus.h"
29 #include "track_list_stub.h"
30 
31 #include "mpris/player.h"
32 
33 #include <core/dbus/property.h>
34 #include <core/dbus/types/object_path.h>
35 
36 #include <limits>
37 
38 #define UNUSED __attribute__((unused))
39 
40 namespace dbus = core::dbus;
41 namespace media = core::ubuntu::media;
42 
44 {
45  Private(const std::shared_ptr<Service>& parent,
46  const std::shared_ptr<core::dbus::Service>& service,
47  const std::shared_ptr<core::dbus::Object>& object,
48  const std::string& uuid
49  ) : parent(parent),
50  service(service),
51  object(object),
52  key(object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>().value()),
53  uuid(uuid),
56  {
57  // Link the properties from the server side to the client side over the bus
58  object->get_property<mpris::Player::Properties::CanPlay>(),
59  object->get_property<mpris::Player::Properties::CanPause>(),
60  object->get_property<mpris::Player::Properties::CanSeek>(),
61  object->get_property<mpris::Player::Properties::CanControl>(),
62  object->get_property<mpris::Player::Properties::CanGoNext>(),
63  object->get_property<mpris::Player::Properties::CanGoPrevious>(),
64  object->get_property<mpris::Player::Properties::IsVideoSource>(),
65  object->get_property<mpris::Player::Properties::IsAudioSource>(),
66  object->get_property<mpris::Player::Properties::TypedPlaybackStatus>(),
67  object->get_property<mpris::Player::Properties::TypedLoopStatus>(),
68  object->get_property<mpris::Player::Properties::PlaybackRate>(),
69  object->get_property<mpris::Player::Properties::Shuffle>(),
70  object->get_property<mpris::Player::Properties::TypedMetaData>(),
71  object->get_property<mpris::Player::Properties::Volume>(),
72  object->get_property<mpris::Player::Properties::Position>(),
73  object->get_property<mpris::Player::Properties::Duration>(),
74  object->get_property<mpris::Player::Properties::AudioStreamRole>(),
75  object->get_property<mpris::Player::Properties::Orientation>(),
76  object->get_property<mpris::Player::Properties::Lifetime>(),
77  object->get_property<mpris::Player::Properties::MinimumRate>(),
78  object->get_property<mpris::Player::Properties::MaximumRate>()
79  },
80  signals
81  {
82  object->get_signal<mpris::Player::Signals::Seeked>(),
83  object->get_signal<mpris::Player::Signals::AboutToFinish>(),
84  object->get_signal<mpris::Player::Signals::EndOfStream>(),
85  object->get_signal<mpris::Player::Signals::PlaybackStatusChanged>(),
86  object->get_signal<mpris::Player::Signals::VideoDimensionChanged>(),
87  object->get_signal<mpris::Player::Signals::Error>()
88  }
89  {
90  }
91 
93  {
94  }
95 
96  std::shared_ptr<Service> parent;
97  std::shared_ptr<TrackList> track_list;
98  dbus::Service::Ptr service;
99  dbus::Object::Ptr object;
101  std::string uuid;
103  struct
104  {
105  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPlay>> can_play;
106  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPause>> can_pause;
107  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanSeek>> can_seek;
108  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control;
109  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next;
110  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous;
111  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsVideoSource>> is_video_source;
112  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsAudioSource>> is_audio_source;
113 
114  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedPlaybackStatus>> playback_status;
115  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedLoopStatus>> loop_status;
116  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackRate>> playback_rate;
117  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Shuffle>> shuffle;
118  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::TypedMetaData>> meta_data_for_current_track;
119  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Volume>> volume;
120  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Position>> position;
121  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Duration>> duration;
122  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::AudioStreamRole>> audio_role;
123  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Orientation>> orientation;
124  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Lifetime>> lifetime;
125  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MinimumRate>> minimum_playback_rate;
126  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;
127  } properties;
128 
129  struct Signals
130  {
131  typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
132  typedef core::dbus::Signal<mpris::Player::Signals::AboutToFinish, mpris::Player::Signals::AboutToFinish::ArgumentType> DBusAboutToFinishSignal;
133  typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
134  typedef core::dbus::Signal<mpris::Player::Signals::PlaybackStatusChanged, mpris::Player::Signals::PlaybackStatusChanged::ArgumentType> DBusPlaybackStatusChangedSignal;
135  typedef core::dbus::Signal<mpris::Player::Signals::VideoDimensionChanged, mpris::Player::Signals::VideoDimensionChanged::ArgumentType> DBusVideoDimensionChangedSignal;
136  typedef core::dbus::Signal<mpris::Player::Signals::Error, mpris::Player::Signals::Error::ArgumentType> DBusErrorSignal;
137 
138  Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked,
139  const std::shared_ptr<DBusAboutToFinishSignal>& atf,
140  const std::shared_ptr<DBusEndOfStreamSignal>& eos,
141  const std::shared_ptr<DBusPlaybackStatusChangedSignal>& status,
142  const std::shared_ptr<DBusVideoDimensionChangedSignal>& d,
143  const std::shared_ptr<DBusErrorSignal>& e)
144  : seeked_to(),
145  about_to_finish(),
146  end_of_stream(),
149  error(),
150  dbus
151  {
152  seeked,
153  atf,
154  eos,
155  status,
156  d,
157  e
158  }
159  {
160  dbus.seeked_to->connect([this](std::uint64_t value)
161  {
162  std::cout << "SeekedTo signal arrived via the bus." << std::endl;
163  seeked_to(value);
164  });
165 
166  dbus.about_to_finish->connect([this]()
167  {
168  std::cout << "AboutToFinish signal arrived via the bus." << std::endl;
169  about_to_finish();
170  });
171 
172  dbus.end_of_stream->connect([this]()
173  {
174  std::cout << "EndOfStream signal arrived via the bus." << std::endl;
175  end_of_stream();
176  });
177 
178  dbus.playback_status_changed->connect([this](const media::Player::PlaybackStatus& status)
179  {
180  std::cout << "PlaybackStatusChanged signal arrived via the bus (Status: " << status << ")" << std::endl;
181  playback_status_changed(status);
182  });
183 
184  dbus.video_dimension_changed->connect([this](const media::video::Dimensions dimensions)
185  {
186  std::cout << "VideoDimensionChanged signal arrived via the bus." << std::endl;
187  video_dimension_changed(dimensions);
188  });
189 
190  dbus.error->connect([this](const media::Player::Error& e)
191  {
192  std::cout << "Error signal arrived via the bus (Error: " << e << ")" << std::endl;
193  error(e);
194  });
195  }
196 
197  core::Signal<int64_t> seeked_to;
198  core::Signal<void> about_to_finish;
199  core::Signal<void> end_of_stream;
200  core::Signal<media::Player::PlaybackStatus> playback_status_changed;
201  core::Signal<media::video::Dimensions> video_dimension_changed;
202  core::Signal<media::Player::Error> error;
203 
204  struct DBus
205  {
206  std::shared_ptr<DBusSeekedToSignal> seeked_to;
207  std::shared_ptr<DBusAboutToFinishSignal> about_to_finish;
208  std::shared_ptr<DBusEndOfStreamSignal> end_of_stream;
209  std::shared_ptr<DBusPlaybackStatusChangedSignal> playback_status_changed;
210  std::shared_ptr<DBusVideoDimensionChangedSignal> video_dimension_changed;
211  std::shared_ptr<DBusErrorSignal> error;
212  } dbus;
213  } signals;
214 };
215 
217  const std::shared_ptr<Service>& parent,
218  const std::shared_ptr<core::dbus::Service>& service,
219  const std::shared_ptr<core::dbus::Object>& object,
220  const std::string& uuid)
221  : d(new Private{parent, service, object, uuid})
222 {
223 }
224 
226 {
227 }
228 
229 std::string media::PlayerStub::uuid() const
230 {
231  return d->uuid;
232 }
233 
235 {
236  // No implementation
237 }
238 
240 {
241  // No implementation
242 }
243 
244 std::shared_ptr<media::TrackList> media::PlayerStub::track_list()
245 {
246  if (!d->track_list)
247  {
248  d->track_list = std::make_shared<media::TrackListStub>(
249  shared_from_this(),
250  d->service->object_for_path(
251  dbus::types::ObjectPath(
252  d->object->path().as_string() + "/TrackList")));
253  }
254  return d->track_list;
255 }
256 
258 {
259  return d->key;
260 }
261 
263 {
264  auto op = d->object->transact_method<mpris::Player::OpenUri, bool>(uri);
265 
266  return op.value();
267 }
268 
269 
270 bool media::PlayerStub::open_uri(const Track::UriType& uri, const Player::HeadersType& headers)
271 {
272  auto op = d->object->transact_method<mpris::Player::OpenUriExtended, bool>(uri, headers);
273 
274  return op.value();
275 }
276 
277 media::video::Sink::Ptr media::PlayerStub::create_gl_texture_video_sink(std::uint32_t texture_id)
278 {
279  auto op = d->object->transact_method<mpris::Player::CreateVideoSink, void>(texture_id);
280 
281  if (op.is_error())
282  {
284  throw media::Player::Errors::OutOfProcessBufferStreamingNotSupported{};
285  else
286  throw std::runtime_error{op.error().print()};
287  }
288 
289  return d->sink_factory(texture_id);
290 }
291 
293 {
294  auto op = d->object->transact_method<mpris::Player::Next, void>();
295 
296  if (op.is_error())
297  throw std::runtime_error("Problem switching to next track on remote object");
298 }
299 
301 {
302  auto op = d->object->transact_method<mpris::Player::Previous, void>();
303 
304  if (op.is_error())
305  throw std::runtime_error("Problem switching to previous track on remote object");
306 }
307 
309 {
310  auto op = d->object->transact_method<mpris::Player::Play, void>();
311 
312  if (op.is_error())
313  throw std::runtime_error("Problem starting playback on remote object");
314 }
315 
317 {
318  auto op = d->object->transact_method<mpris::Player::Pause, void>();
319 
320  if (op.is_error())
321  throw std::runtime_error("Problem pausing playback on remote object");
322 }
323 
324 void media::PlayerStub::seek_to(const std::chrono::microseconds& offset)
325 {
326  auto op = d->object->transact_method<mpris::Player::Seek, void, uint64_t>(offset.count());
327 
328  if (op.is_error())
329  throw std::runtime_error("Problem seeking on remote object");
330 }
331 
333 {
334  auto op = d->object->transact_method<mpris::Player::Stop, void>();
335 
336  if (op.is_error())
337  throw std::runtime_error("Problem stopping playback on remote object");
338 }
339 
340 const core::Property<bool>& media::PlayerStub::can_play() const
341 {
342  return *d->properties.can_play;
343 }
344 
345 const core::Property<bool>& media::PlayerStub::can_pause() const
346 {
347  return *d->properties.can_pause;
348 }
349 
350 const core::Property<bool>& media::PlayerStub::can_seek() const
351 {
352  return *d->properties.can_seek;
353 }
354 
355 const core::Property<bool>& media::PlayerStub::can_go_previous() const
356 {
357  return *d->properties.can_go_previous;
358 }
359 
360 const core::Property<bool>& media::PlayerStub::can_go_next() const
361 {
362  return *d->properties.can_go_next;
363 }
364 
365 const core::Property<bool>& media::PlayerStub::is_video_source() const
366 {
367  return *d->properties.is_video_source;
368 }
369 
370 const core::Property<bool>& media::PlayerStub::is_audio_source() const
371 {
372  return *d->properties.is_audio_source;
373 }
374 
375 const core::Property<media::Player::PlaybackStatus>& media::PlayerStub::playback_status() const
376 {
377  return *d->properties.playback_status;
378 }
379 
380 const core::Property<media::Player::LoopStatus>& media::PlayerStub::loop_status() const
381 {
382  return *d->properties.loop_status;
383 }
384 
385 const core::Property<media::Player::PlaybackRate>& media::PlayerStub::playback_rate() const
386 {
387  return *d->properties.playback_rate;
388 }
389 
390 const core::Property<bool>& media::PlayerStub::shuffle() const
391 {
392  return *d->properties.shuffle;
393 }
394 
395 const core::Property<media::Track::MetaData>& media::PlayerStub::meta_data_for_current_track() const
396 {
397  return *d->properties.meta_data_for_current_track;
398 }
399 
400 const core::Property<media::Player::Volume>& media::PlayerStub::volume() const
401 {
402  return *d->properties.volume;
403 }
404 
405 const core::Property<int64_t>& media::PlayerStub::position() const
406 {
407  return *d->properties.position;
408 }
409 
410 const core::Property<int64_t>& media::PlayerStub::duration() const
411 {
412  return *d->properties.duration;
413 }
414 
415 const core::Property<media::Player::AudioStreamRole>& media::PlayerStub::audio_stream_role() const
416 {
417  return *d->properties.audio_role;
418 }
419 
420 const core::Property<media::Player::Orientation>& media::PlayerStub::orientation() const
421 {
422  return *d->properties.orientation;
423 }
424 
425 const core::Property<media::Player::Lifetime>& media::PlayerStub::lifetime() const
426 {
427  return *d->properties.lifetime;
428 }
429 
430 const core::Property<media::Player::PlaybackRate>& media::PlayerStub::minimum_playback_rate() const
431 {
432  return *d->properties.minimum_playback_rate;
433 }
434 
435 const core::Property<media::Player::PlaybackRate>& media::PlayerStub::maximum_playback_rate() const
436 {
437  return *d->properties.maximum_playback_rate;
438 }
439 
440 core::Property<media::Player::LoopStatus>& media::PlayerStub::loop_status()
441 {
442  return *d->properties.loop_status;
443 }
444 
445 core::Property<media::Player::PlaybackRate>& media::PlayerStub::playback_rate()
446 {
447  return *d->properties.playback_rate;
448 }
449 
450 core::Property<bool>& media::PlayerStub::shuffle()
451 {
452  return *d->properties.shuffle;
453 }
454 
455 core::Property<media::Player::Volume>& media::PlayerStub::volume()
456 {
457  return *d->properties.volume;
458 }
459 
460 core::Property<media::Player::AudioStreamRole>& media::PlayerStub::audio_stream_role()
461 {
462  return *d->properties.audio_role;
463 }
464 
465 core::Property<media::Player::Lifetime>& media::PlayerStub::lifetime()
466 {
467  return *d->properties.lifetime;
468 }
469 
470 const core::Signal<int64_t>& media::PlayerStub::seeked_to() const
471 {
472  return d->signals.seeked_to;
473 }
474 
475 const core::Signal<void>& media::PlayerStub::about_to_finish() const
476 {
477  return d->signals.about_to_finish;
478 }
479 
480 const core::Signal<void>& media::PlayerStub::end_of_stream() const
481 {
482  return d->signals.end_of_stream;
483 }
484 
485 core::Signal<media::Player::PlaybackStatus>& media::PlayerStub::playback_status_changed()
486 {
487  return d->signals.playback_status_changed;
488 }
489 
490 const core::Signal<media::video::Dimensions>& media::PlayerStub::video_dimension_changed() const
491 {
492  return d->signals.video_dimension_changed;
493 }
494 
495 const core::Signal<media::Player::Error>& media::PlayerStub::error() const
496 {
497  return d->signals.error;
498 }
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanPlay > > can_play
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanControl > > can_control
std::shared_ptr< DBusEndOfStreamSignal > end_of_stream
std::shared_ptr< DBusVideoDimensionChangedSignal > video_dimension_changed
virtual video::Sink::Ptr create_gl_texture_video_sink(std::uint32_t texture_id)
SinkFactory make_platform_default_sink_factory(const Player::PlayerKey &key)
virtual const core::Property< bool > & shuffle() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::IsAudioSource > > is_audio_source
virtual const core::Property< int64_t > & position() const
std::tuple< Height, Width > Dimensions
Height and Width of a video.
Definition: dimensions.h:139
virtual const core::Property< Orientation > & orientation() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::MinimumRate > > minimum_playback_rate
virtual const core::Property< bool > & is_video_source() const
struct media::PlayerStub::Private::Signals signals
virtual const core::Signal< void > & end_of_stream() const
core::Signal< void > end_of_stream
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Lifetime > > lifetime
dbus::Object::Ptr object
Definition: player_stub.cpp:99
struct media::PlayerStub::Private::@21 properties
virtual const core::Property< int64_t > & duration() const
std::shared_ptr< DBusSeekedToSignal > seeked_to
virtual const core::Property< bool > & is_audio_source() const
core::dbus::Signal< mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType > DBusEndOfStreamSignal
std::map< std::string, std::string > HeadersType
Definition: player.h:49
std::shared_ptr< Service > parent
Definition: player_stub.cpp:96
core::dbus::Signal< mpris::Player::Signals::VideoDimensionChanged, mpris::Player::Signals::VideoDimensionChanged::ArgumentType > DBusVideoDimensionChangedSignal
core::Signal< void > about_to_finish
virtual const core::Property< bool > & can_pause() const
core::Signal< media::video::Dimensions > video_dimension_changed
core::dbus::Signal< mpris::Player::Signals::Error, mpris::Player::Signals::Error::ArgumentType > DBusErrorSignal
virtual const core::Signal< video::Dimensions > & video_dimension_changed() const
virtual const core::Property< Volume > & volume() const
struct media::PlayerStub::Private::Signals::DBus dbus
virtual const core::Property< bool > & can_play() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Volume > > volume
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Shuffle > > shuffle
std::shared_ptr< DBusErrorSignal > error
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::TypedLoopStatus > > loop_status
media::video::SinkFactory sink_factory
std::shared_ptr< DBusAboutToFinishSignal > about_to_finish
virtual const core::Property< bool > & can_go_next() const
core::dbus::Signal< mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType > DBusSeekedToSignal
virtual const core::Property< Track::MetaData > & meta_data_for_current_track() const
core::dbus::Signal< mpris::Player::Signals::PlaybackStatusChanged, mpris::Player::Signals::PlaybackStatusChanged::ArgumentType > DBusPlaybackStatusChangedSignal
core::dbus::Signal< mpris::Player::Signals::AboutToFinish, mpris::Player::Signals::AboutToFinish::ArgumentType > DBusAboutToFinishSignal
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanPause > > can_pause
Signals(const std::shared_ptr< DBusSeekedToSignal > &seeked, const std::shared_ptr< DBusAboutToFinishSignal > &atf, const std::shared_ptr< DBusEndOfStreamSignal > &eos, const std::shared_ptr< DBusPlaybackStatusChangedSignal > &status, const std::shared_ptr< DBusVideoDimensionChangedSignal > &d, const std::shared_ptr< DBusErrorSignal > &e)
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanGoPrevious > > can_go_previous
virtual core::Signal< PlaybackStatus > & playback_status_changed()
std::function< Sink::Ptr(std::uint32_t)> SinkFactory
virtual const core::Signal< void > & about_to_finish() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Duration > > duration
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::TypedMetaData > > meta_data_for_current_track
virtual const core::Signal< int64_t > & seeked_to() const
std::shared_ptr< TrackList > track_list
Definition: player_stub.cpp:97
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanSeek > > can_seek
virtual const core::Property< PlaybackStatus > & playback_status() const
virtual const core::Property< AudioStreamRole > & audio_stream_role() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::AudioStreamRole > > audio_role
virtual const core::Property< Lifetime > & lifetime() const
virtual PlayerKey key() const
core::Signal< media::Player::Error > error
virtual const core::Property< PlaybackRate > & minimum_playback_rate() const
virtual const core::Property< bool > & can_seek() const
dbus::Service::Ptr service
Definition: player_stub.cpp:98
virtual std::string uuid() const
virtual bool open_uri(const Track::UriType &uri)
std::string UriType
Definition: track.h:40
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Position > > position
core::Signal< int64_t > seeked_to
virtual void seek_to(const std::chrono::microseconds &offset)
Private(const std::shared_ptr< Service > &parent, const std::shared_ptr< core::dbus::Service > &service, const std::shared_ptr< core::dbus::Object > &object, const std::string &uuid)
Definition: player_stub.cpp:45
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Orientation > > orientation
virtual const core::Signal< Error > & error() const
virtual std::shared_ptr< TrackList > track_list()
std::shared_ptr< DBusPlaybackStatusChangedSignal > playback_status_changed
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::TypedPlaybackStatus > > playback_status
virtual const core::Property< PlaybackRate > & playback_rate() const
virtual const core::Property< bool > & can_go_previous() const
virtual const core::Property< PlaybackRate > & maximum_playback_rate() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::PlaybackRate > > playback_rate
core::Signal< media::Player::PlaybackStatus > playback_status_changed
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::MaximumRate > > maximum_playback_rate
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::IsVideoSource > > is_video_source
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanGoNext > > can_go_next
virtual const core::Property< LoopStatus > & loop_status() const
media::Player::PlayerKey key
PlayerStub(const std::shared_ptr< Service > &parent, const std::shared_ptr< core::dbus::Service > &service, const std::shared_ptr< core::dbus::Object > &object, const std::string &uuid=std::string{})