Music Hub  ..
A session-wide music playback service
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
player_skeleton.cpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2013-2014 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 "apparmor.h"
21 #include "codec.h"
22 #include "player_skeleton.h"
23 #include "player_traits.h"
24 #include "property_stub.h"
25 #include "the_session_bus.h"
26 
27 #include "mpris/player.h"
28 
29 #include <core/dbus/object.h>
30 #include <core/dbus/property.h>
31 #include <core/dbus/stub.h>
32 #include <core/dbus/asio/executor.h>
33 
34 namespace dbus = core::dbus;
35 namespace media = core::ubuntu::media;
36 
38 {
39  Private(media::PlayerSkeleton* player, const dbus::types::ObjectPath& session)
40  : impl(player),
41  object(impl->access_service()->add_object_for_path(session)),
42  apparmor_session(nullptr),
44  {
45  object->get_property<mpris::Player::Properties::CanPlay>(),
46  object->get_property<mpris::Player::Properties::CanPause>(),
47  object->get_property<mpris::Player::Properties::CanSeek>(),
48  object->get_property<mpris::Player::Properties::CanControl>(),
49  object->get_property<mpris::Player::Properties::CanGoNext>(),
50  object->get_property<mpris::Player::Properties::CanGoPrevious>(),
51  object->get_property<mpris::Player::Properties::IsVideoSource>(),
52  object->get_property<mpris::Player::Properties::IsAudioSource>(),
53  object->get_property<mpris::Player::Properties::PlaybackStatus>(),
54  object->get_property<mpris::Player::Properties::LoopStatus>(),
55  object->get_property<mpris::Player::Properties::PlaybackRate>(),
56  object->get_property<mpris::Player::Properties::Shuffle>(),
57  object->get_property<mpris::Player::Properties::MetaData>(),
58  object->get_property<mpris::Player::Properties::Volume>(),
59  object->get_property<mpris::Player::Properties::Position>(),
60  object->get_property<mpris::Player::Properties::Duration>(),
61  object->get_property<mpris::Player::Properties::AudioStreamRole>(),
62  object->get_property<mpris::Player::Properties::MinimumRate>(),
63  object->get_property<mpris::Player::Properties::MaximumRate>()
64  },
65  signals
66  {
67  object->get_signal<mpris::Player::Signals::Seeked>(),
68  object->get_signal<mpris::Player::Signals::EndOfStream>(),
69  object->get_signal<mpris::Player::Signals::PlaybackStatusChanged>()
70  }
71  {
72  }
73 
74  void handle_next(const core::dbus::Message::Ptr& msg)
75  {
76  impl->next();
77  auto reply = dbus::Message::make_method_return(msg);
78  impl->access_bus()->send(reply);
79  }
80 
81  void handle_previous(const core::dbus::Message::Ptr& msg)
82  {
83  impl->previous();
84  auto reply = dbus::Message::make_method_return(msg);
85  impl->access_bus()->send(reply);
86  }
87 
88  void handle_pause(const core::dbus::Message::Ptr& msg)
89  {
90  impl->pause();
91  auto reply = dbus::Message::make_method_return(msg);
92  impl->access_bus()->send(reply);
93  }
94 
95  void handle_playpause(DBusMessage*)
96  {
97  }
98 
99  void handle_stop(const core::dbus::Message::Ptr& msg)
100  {
101  impl->stop();
102  auto reply = dbus::Message::make_method_return(msg);
103  impl->access_bus()->send(reply);
104  }
105 
106  void handle_play(const core::dbus::Message::Ptr& msg)
107  {
108  impl->play();
109  auto reply = dbus::Message::make_method_return(msg);
110  impl->access_bus()->send(reply);
111  }
112 
113  void handle_seek(const core::dbus::Message::Ptr& in)
114  {
115  uint64_t ticks;
116  in->reader() >> ticks;
117  impl->seek_to(std::chrono::microseconds(ticks));
118 
119  auto reply = dbus::Message::make_method_return(in);
120  impl->access_bus()->send(reply);
121  }
122 
123  void handle_set_position(const core::dbus::Message::Ptr&)
124  {
125  }
126 
127  void handle_create_video_sink(const core::dbus::Message::Ptr& in)
128  {
129  uint32_t texture_id;
130  in->reader() >> texture_id;
131  impl->create_video_sink(texture_id);
132 
133  auto reply = dbus::Message::make_method_return(in);
134  impl->access_bus()->send(reply);
135  }
136 
137  std::string get_client_apparmor_context(const core::dbus::Message::Ptr& msg)
138  {
139  auto bus = std::shared_ptr<dbus::Bus>(new dbus::Bus(core::dbus::WellKnownBus::session));
140  bus->install_executor(dbus::asio::make_executor(bus));
141 
142  auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service<core::Apparmor>::interface_name());
143  apparmor_session = stub_service->object_for_path(dbus::types::ObjectPath("/org/freedesktop/DBus"));
144  // Get the AppArmor security context for the client
145  auto result = apparmor_session->invoke_method_synchronously<core::Apparmor::getConnectionAppArmorSecurityContext, std::string>(msg->sender());
146  if (result.is_error())
147  {
148  std::cout << "Error getting apparmor profile: " << result.error().print() << std::endl;
149  return std::string();
150  }
151 
152  return result.value();
153  }
154 
155  bool does_client_have_access(const std::string& context, const std::string& uri)
156  {
157  if (context.empty() || uri.empty())
158  {
159  std::cout << "Client denied access since context or uri are empty" << std::endl;
160  return false;
161  }
162 
163  if (context == "unconfined")
164  {
165  std::cout << "Client allowed access since it's unconfined" << std::endl;
166  return true;
167  }
168 
169  size_t pos = context.find_first_of('_');
170  if (pos == std::string::npos)
171  {
172  std::cout << "Client denied access since it's an invalid apparmor security context" << std::endl;
173  return false;
174  }
175 
176  const std::string pkgname = context.substr(0, pos);
177  std::cout << "client pkgname: " << pkgname << std::endl;
178  std::cout << "uri: " << uri << std::endl;
179 
180  // All confined apps can access their own files
181  if (uri.find(std::string(".local/share/" + pkgname + "/")) != std::string::npos
182  || uri.find(std::string(".cache/" + pkgname + "/")) != std::string::npos)
183  {
184  std::cout << "Client can access content in ~/.local/share/" << pkgname << " or ~/.cache/" << pkgname << std::endl;
185  return true;
186  }
187  else if (uri.find(std::string("opt/click.ubuntu.com/")) != std::string::npos
188  && uri.find(pkgname) != std::string::npos)
189  {
190  std::cout << "Client can access content in own opt directory" << std::endl;
191  return true;
192  }
193  else if ((uri.find(std::string("/system/media/audio/ui/")) != std::string::npos
194  || uri.find(std::string("/android/system/media/audio/ui/")) != std::string::npos)
195  && pkgname == "com.ubuntu.camera")
196  {
197  std::cout << "Camera app can access ui sounds" << std::endl;
198  return true;
199  }
200  // TODO: Check if the trust store previously allowed direct access to uri
201 
202  // Check in ~/Music and ~/Videos
203  // TODO: when the trust store lands, check it to see if this app can access the dirs and
204  // then remove the explicit whitelist of the music-app, and gallery-app
205  else if ((pkgname == "com.ubuntu.music" || pkgname == "com.ubuntu.gallery") &&
206  (uri.find(std::string("Music/")) != std::string::npos
207  || uri.find(std::string("Videos/")) != std::string::npos
208  || uri.find(std::string("/media")) != std::string::npos))
209  {
210  std::cout << "Client can access content in ~/Music or ~/Videos" << std::endl;
211  return true;
212  }
213  else if (uri.find(std::string("/usr/share/sounds")) != std::string::npos)
214  {
215  std::cout << "Client can access content in /usr/share/sounds" << std::endl;
216  return true;
217  }
218  else if (uri.find(std::string("http://")) != std::string::npos
219  || uri.find(std::string("rtsp://")) != std::string::npos)
220  {
221  std::cout << "Client can access streaming content" << std::endl;
222  return true;
223  }
224  else
225  {
226  std::cout << "Client denied access to open_uri()" << std::endl;
227  return false;
228  }
229  }
230 
231  void handle_key(const core::dbus::Message::Ptr& in)
232  {
233  auto reply = dbus::Message::make_method_return(in);
234  reply->writer() << impl->key();
235  impl->access_bus()->send(reply);
236  }
237 
238  void handle_open_uri(const core::dbus::Message::Ptr& in)
239  {
240  Track::UriType uri;
241  in->reader() >> uri;
242 
243  std::string context = get_client_apparmor_context(in);
244  bool have_access = does_client_have_access(context, uri);
245 
246  auto reply = dbus::Message::make_method_return(in);
247  if (have_access)
248  reply->writer() << impl->open_uri(uri);
249  else
250  reply->writer() << false;
251  impl->access_bus()->send(reply);
252  }
253 
255  dbus::Object::Ptr object;
256  dbus::Object::Ptr apparmor_session;
257  struct
258  {
259  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPlay>> can_play;
260  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPause>> can_pause;
261  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanSeek>> can_seek;
262  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control;
263  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next;
264  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous;
265  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsVideoSource>> is_video_source;
266  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsAudioSource>> is_audio_source;
267 
268  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status;
269  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status;
270  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackRate>> playback_rate;
271  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Shuffle>> is_shuffle;
272  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MetaData>> meta_data_for_current_track;
273  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Volume>> volume;
274  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Position>> position;
275  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::Duration>> duration;
276  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::AudioStreamRole>> audio_role;
277  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MinimumRate>> minimum_playback_rate;
278  std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;
279  } properties;
280 
281  struct Signals
282  {
283  typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
284  typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
285  typedef core::dbus::Signal<mpris::Player::Signals::PlaybackStatusChanged, mpris::Player::Signals::PlaybackStatusChanged::ArgumentType> DBusPlaybackStatusChangedSignal;
286 
287  Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked,
288  const std::shared_ptr<DBusEndOfStreamSignal>& eos,
289  const std::shared_ptr<DBusPlaybackStatusChangedSignal>& status)
290  : dbus
291  {
292  seeked,
293  eos,
294  status
295  },
296  seeked_to(),
297  end_of_stream(),
299  {
300  seeked_to.connect([this](std::uint64_t value)
301  {
302  dbus.seeked_to->emit(value);
303  });
304 
305  end_of_stream.connect([this]()
306  {
307  dbus.end_of_stream->emit();
308  });
309 
310  playback_status_changed.connect([this](const media::Player::PlaybackStatus& status)
311  {
312  dbus.playback_status_changed->emit(status);
313  });
314  }
315 
316  struct DBus
317  {
318  std::shared_ptr<DBusSeekedToSignal> seeked_to;
319  std::shared_ptr<DBusEndOfStreamSignal> end_of_stream;
320  std::shared_ptr<DBusPlaybackStatusChangedSignal> playback_status_changed;
321  } dbus;
322  core::Signal<uint64_t> seeked_to;
323  core::Signal<void> end_of_stream;
324  core::Signal<media::Player::PlaybackStatus> playback_status_changed;
325  } signals;
326 
327 };
328 
330  const core::dbus::types::ObjectPath& session_path)
331  : dbus::Skeleton<media::Player>(the_session_bus()),
332  d(new Private{this, session_path})
333 {
334  d->object->install_method_handler<mpris::Player::Next>(
335  std::bind(&Private::handle_next,
336  std::ref(d),
337  std::placeholders::_1));
338  d->object->install_method_handler<mpris::Player::Previous>(
339  std::bind(&Private::handle_previous,
340  std::ref(d),
341  std::placeholders::_1));
342  d->object->install_method_handler<mpris::Player::Pause>(
343  std::bind(&Private::handle_pause,
344  std::ref(d),
345  std::placeholders::_1));
346  d->object->install_method_handler<mpris::Player::Stop>(
347  std::bind(&Private::handle_stop,
348  std::ref(d),
349  std::placeholders::_1));
350  d->object->install_method_handler<mpris::Player::Play>(
351  std::bind(&Private::handle_play,
352  std::ref(d),
353  std::placeholders::_1));
354  d->object->install_method_handler<mpris::Player::Seek>(
355  std::bind(&Private::handle_seek,
356  std::ref(d),
357  std::placeholders::_1));
358  d->object->install_method_handler<mpris::Player::SetPosition>(
359  std::bind(&Private::handle_set_position,
360  std::ref(d),
361  std::placeholders::_1));
362  d->object->install_method_handler<mpris::Player::CreateVideoSink>(
364  std::ref(d),
365  std::placeholders::_1));
366  d->object->install_method_handler<mpris::Player::Key>(
367  std::bind(&Private::handle_key,
368  std::ref(d),
369  std::placeholders::_1));
370  d->object->install_method_handler<mpris::Player::OpenUri>(
371  std::bind(&Private::handle_open_uri,
372  std::ref(d),
373  std::placeholders::_1));
374 }
375 
377 {
378 }
379 
380 const core::Property<bool>& media::PlayerSkeleton::can_play() const
381 {
382  return *d->properties.can_play;
383 }
384 
385 const core::Property<bool>& media::PlayerSkeleton::can_pause() const
386 {
387  return *d->properties.can_pause;
388 }
389 
390 const core::Property<bool>& media::PlayerSkeleton::can_seek() const
391 {
392  return *d->properties.can_seek;
393 }
394 
395 const core::Property<bool>& media::PlayerSkeleton::can_go_previous() const
396 {
397  return *d->properties.can_go_previous;
398 }
399 
400 const core::Property<bool>& media::PlayerSkeleton::can_go_next() const
401 {
402  return *d->properties.can_go_next;
403 }
404 
405 const core::Property<bool>& media::PlayerSkeleton::is_video_source() const
406 {
407  return *d->properties.is_video_source;
408 }
409 
410 const core::Property<bool>& media::PlayerSkeleton::is_audio_source() const
411 {
412  return *d->properties.is_audio_source;
413 }
414 
415 const core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status() const
416 {
417  return *d->properties.playback_status;
418 }
419 
420 const core::Property<media::Player::LoopStatus>& media::PlayerSkeleton::loop_status() const
421 {
422  return *d->properties.loop_status;
423 }
424 
425 const core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::playback_rate() const
426 {
427  return *d->properties.playback_rate;
428 }
429 
430 const core::Property<bool>& media::PlayerSkeleton::is_shuffle() const
431 {
432  return *d->properties.is_shuffle;
433 }
434 
435 const core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track() const
436 {
437  return *d->properties.meta_data_for_current_track;
438 }
439 
440 const core::Property<media::Player::Volume>& media::PlayerSkeleton::volume() const
441 {
442  return *d->properties.volume;
443 }
444 
445 const core::Property<uint64_t>& media::PlayerSkeleton::position() const
446 {
447  return *d->properties.position;
448 }
449 
450 const core::Property<uint64_t>& media::PlayerSkeleton::duration() const
451 {
452  return *d->properties.duration;
453 }
454 
455 const core::Property<media::Player::AudioStreamRole>& media::PlayerSkeleton::audio_stream_role() const
456 {
457  return *d->properties.audio_role;
458 }
459 
460 const core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::minimum_playback_rate() const
461 {
462  return *d->properties.minimum_playback_rate;
463 }
464 
465 const core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::maximum_playback_rate() const
466 {
467  return *d->properties.maximum_playback_rate;
468 }
469 
470 core::Property<media::Player::LoopStatus>& media::PlayerSkeleton::loop_status()
471 {
472  return *d->properties.loop_status;
473 }
474 
475 core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::playback_rate()
476 {
477  return *d->properties.playback_rate;
478 }
479 
480 core::Property<bool>& media::PlayerSkeleton::is_shuffle()
481 {
482  return *d->properties.is_shuffle;
483 }
484 
485 core::Property<media::Player::Volume>& media::PlayerSkeleton::volume()
486 {
487  return *d->properties.volume;
488 }
489 
490 core::Property<uint64_t>& media::PlayerSkeleton::position()
491 {
492  return *d->properties.position;
493 }
494 
495 core::Property<uint64_t>& media::PlayerSkeleton::duration()
496 {
497  return *d->properties.duration;
498 }
499 
500 core::Property<media::Player::AudioStreamRole>& media::PlayerSkeleton::audio_stream_role()
501 {
502  return *d->properties.audio_role;
503 }
504 
505 core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status()
506 {
507  return *d->properties.playback_status;
508 }
509 
510 core::Property<bool>& media::PlayerSkeleton::can_play()
511 {
512  return *d->properties.can_play;
513 }
514 
515 core::Property<bool>& media::PlayerSkeleton::can_pause()
516 {
517  return *d->properties.can_pause;
518 }
519 
520 core::Property<bool>& media::PlayerSkeleton::can_seek()
521 {
522  return *d->properties.can_seek;
523 }
524 
525 core::Property<bool>& media::PlayerSkeleton::can_go_previous()
526 {
527  return *d->properties.can_go_previous;
528 }
529 
530 core::Property<bool>& media::PlayerSkeleton::can_go_next()
531 {
532  return *d->properties.can_go_next;
533 }
534 
535 core::Property<bool>& media::PlayerSkeleton::is_video_source()
536 {
537  return *d->properties.is_video_source;
538 }
539 
540 core::Property<bool>& media::PlayerSkeleton::is_audio_source()
541 {
542  return *d->properties.is_audio_source;
543 }
544 
545 
546 core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track()
547 {
548  return *d->properties.meta_data_for_current_track;
549 }
550 
551 core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::minimum_playback_rate()
552 {
553  return *d->properties.minimum_playback_rate;
554 }
555 
556 core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::maximum_playback_rate()
557 {
558  return *d->properties.maximum_playback_rate;
559 }
560 
561 const core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to() const
562 {
563  return d->signals.seeked_to;
564 }
565 
566 core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to()
567 {
568  return d->signals.seeked_to;
569 }
570 
571 const core::Signal<void>& media::PlayerSkeleton::end_of_stream() const
572 {
573  return d->signals.end_of_stream;
574 }
575 
576 core::Signal<void>& media::PlayerSkeleton::end_of_stream()
577 {
578  return d->signals.end_of_stream;
579 }
580 
581 core::Signal<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status_changed()
582 {
583  return d->signals.playback_status_changed;
584 }
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanPause > > can_pause
void handle_previous(const core::dbus::Message::Ptr &msg)
std::shared_ptr< DBusSeekedToSignal > seeked_to
Signals(const std::shared_ptr< DBusSeekedToSignal > &seeked, const std::shared_ptr< DBusEndOfStreamSignal > &eos, const std::shared_ptr< DBusPlaybackStatusChangedSignal > &status)
void handle_play(const core::dbus::Message::Ptr &msg)
virtual const core::Property< PlaybackStatus > & playback_status() const
virtual const core::Property< bool > & is_video_source() const
void handle_playpause(DBusMessage *)
virtual const core::Signal< void > & end_of_stream() const
virtual const core::Property< bool > & can_seek() const
virtual const core::Property< PlaybackRate > & maximum_playback_rate() const
core::dbus::Bus::Ptr the_session_bus()
virtual const core::Property< bool > & is_shuffle() const
virtual const core::Property< bool > & can_go_next() const
virtual const core::Property< bool > & can_go_previous() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Volume > > volume
virtual const core::Property< uint64_t > & duration() const
void handle_set_position(const core::dbus::Message::Ptr &)
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::MinimumRate > > minimum_playback_rate
bool does_client_have_access(const std::string &context, const std::string &uri)
std::shared_ptr< DBusEndOfStreamSignal > end_of_stream
virtual const core::Property< bool > & can_play() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Duration > > duration
virtual const core::Signal< uint64_t > & seeked_to() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanGoNext > > can_go_next
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanPlay > > can_play
virtual const core::Property< Track::MetaData > & meta_data_for_current_track() const
std::shared_ptr< DBusPlaybackStatusChangedSignal > playback_status_changed
virtual const core::Property< bool > & can_pause() const
virtual const core::Property< LoopStatus > & loop_status() const
void handle_stop(const core::dbus::Message::Ptr &msg)
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanControl > > can_control
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::MaximumRate > > maximum_playback_rate
struct media::PlayerSkeleton::Private::Signals::DBus dbus
virtual const core::Property< PlaybackRate > & playback_rate() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::LoopStatus > > loop_status
virtual const core::Property< AudioStreamRole > & audio_stream_role() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Shuffle > > is_shuffle
core::dbus::Signal< mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType > DBusEndOfStreamSignal
media::PlayerSkeleton * impl
PlayerSkeleton(const core::dbus::types::ObjectPath &session_path)
void handle_pause(const core::dbus::Message::Ptr &msg)
core::dbus::Signal< mpris::Player::Signals::PlaybackStatusChanged, mpris::Player::Signals::PlaybackStatusChanged::ArgumentType > DBusPlaybackStatusChangedSignal
Private(media::PlayerSkeleton *player, const dbus::types::ObjectPath &session)
virtual const core::Property< PlaybackRate > & minimum_playback_rate() const
struct media::PlayerSkeleton::Private::Signals signals
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::IsVideoSource > > is_video_source
void handle_seek(const core::dbus::Message::Ptr &in)
void handle_open_uri(const core::dbus::Message::Ptr &in)
virtual const core::Property< Volume > & volume() const
std::string UriType
Definition: track.h:40
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::PlaybackStatus > > playback_status
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::Position > > position
void handle_next(const core::dbus::Message::Ptr &msg)
virtual core::Signal< PlaybackStatus > & playback_status_changed()
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::IsAudioSource > > is_audio_source
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::AudioStreamRole > > audio_role
virtual const core::Property< bool > & is_audio_source() const
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::PlaybackRate > > playback_rate
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanGoPrevious > > can_go_previous
core::dbus::Signal< mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType > DBusSeekedToSignal
core::Signal< media::Player::PlaybackStatus > playback_status_changed
struct media::PlayerSkeleton::Private::@12 properties
virtual const core::Property< uint64_t > & position() const
void handle_create_video_sink(const core::dbus::Message::Ptr &in)
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::CanSeek > > can_seek
void handle_key(const core::dbus::Message::Ptr &in)
std::string get_client_apparmor_context(const core::dbus::Message::Ptr &msg)
std::shared_ptr< core::dbus::Property< mpris::Player::Properties::MetaData > > meta_data_for_current_track