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