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-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 "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 #include "xesam.h"
27 
28 #include "mpris/media_player2.h"
29 #include "mpris/metadata.h"
30 #include "mpris/player.h"
31 #include "mpris/playlists.h"
32 
33 #include <core/dbus/object.h>
34 #include <core/dbus/property.h>
35 #include <core/dbus/stub.h>
36 
37 #include <core/dbus/asio/executor.h>
38 #include <core/dbus/interfaces/properties.h>
39 
40 namespace dbus = core::dbus;
41 namespace media = core::ubuntu::media;
42 
44 {
46  const std::string& identity,
47  const std::shared_ptr<core::dbus::Bus>& bus,
48  const std::shared_ptr<core::dbus::Object>& session)
49  : impl(player),
50  identity(identity),
51  bus(bus),
52  object(session),
53  apparmor_session(nullptr),
54  dbus_stub{bus},
56  signals
57  {
63  }
64  {
65  }
66 
67  void handle_next(const core::dbus::Message::Ptr& msg)
68  {
69  impl->next();
70  auto reply = dbus::Message::make_method_return(msg);
71  bus->send(reply);
72  }
73 
74  void handle_previous(const core::dbus::Message::Ptr& msg)
75  {
76  impl->previous();
77  auto reply = dbus::Message::make_method_return(msg);
78  bus->send(reply);
79  }
80 
81  void handle_pause(const core::dbus::Message::Ptr& msg)
82  {
83  impl->pause();
84  auto reply = dbus::Message::make_method_return(msg);
85  bus->send(reply);
86  }
87 
88  void handle_stop(const core::dbus::Message::Ptr& msg)
89  {
90  impl->stop();
91  auto reply = dbus::Message::make_method_return(msg);
92  bus->send(reply);
93  }
94 
95  void handle_play(const core::dbus::Message::Ptr& msg)
96  {
97  impl->play();
98  auto reply = dbus::Message::make_method_return(msg);
99  bus->send(reply);
100  }
101 
102  void handle_play_pause(const core::dbus::Message::Ptr& msg)
103  {
104  switch(impl->playback_status().get())
105  {
106  case core::ubuntu::media::Player::PlaybackStatus::ready:
107  case core::ubuntu::media::Player::PlaybackStatus::paused:
108  case core::ubuntu::media::Player::PlaybackStatus::stopped:
109  impl->play();
110  break;
111  case core::ubuntu::media::Player::PlaybackStatus::playing:
112  impl->pause();
113  break;
114  default:
115  break;
116  }
117 
118  bus->send(dbus::Message::make_method_return(msg));
119  }
120 
121  void handle_seek(const core::dbus::Message::Ptr& in)
122  {
123  uint64_t ticks;
124  in->reader() >> ticks;
125  impl->seek_to(std::chrono::microseconds(ticks));
126 
127  auto reply = dbus::Message::make_method_return(in);
128  bus->send(reply);
129  }
130 
131  void handle_set_position(const core::dbus::Message::Ptr&)
132  {
133  }
134 
135  void handle_create_video_sink(const core::dbus::Message::Ptr& in)
136  {
137  uint32_t texture_id;
138  in->reader() >> texture_id;
139  impl->create_video_sink(texture_id);
140 
141  auto reply = dbus::Message::make_method_return(in);
142  bus->send(reply);
143  }
144 
145  bool does_client_have_access(const std::string& context, const std::string& uri)
146  {
147  if (context.empty() || uri.empty())
148  {
149  std::cout << "Client denied access since context or uri are empty" << std::endl;
150  return false;
151  }
152 
153  if (context == "unconfined")
154  {
155  std::cout << "Client allowed access since it's unconfined" << std::endl;
156  return true;
157  }
158 
159  size_t pos = context.find_first_of('_');
160  if (pos == std::string::npos)
161  {
162  std::cout << "Client denied access since it's an invalid apparmor security context" << std::endl;
163  return false;
164  }
165 
166  const std::string pkgname = context.substr(0, pos);
167  std::cout << "client pkgname: " << pkgname << std::endl;
168  std::cout << "uri: " << uri << std::endl;
169 
170  // All confined apps can access their own files
171  if (uri.find(std::string(".local/share/" + pkgname + "/")) != std::string::npos
172  || uri.find(std::string(".cache/" + pkgname + "/")) != std::string::npos)
173  {
174  std::cout << "Client can access content in ~/.local/share/" << pkgname << " or ~/.cache/" << pkgname << std::endl;
175  return true;
176  }
177  else if (uri.find(std::string("opt/click.ubuntu.com/")) != std::string::npos
178  && uri.find(pkgname) != std::string::npos)
179  {
180  std::cout << "Client can access content in own opt directory" << std::endl;
181  return true;
182  }
183  else if ((uri.find(std::string("/system/media/audio/ui/")) != std::string::npos
184  || uri.find(std::string("/android/system/media/audio/ui/")) != std::string::npos)
185  && pkgname == "com.ubuntu.camera")
186  {
187  std::cout << "Camera app can access ui sounds" << std::endl;
188  return true;
189  }
190  // TODO: Check if the trust store previously allowed direct access to uri
191 
192  // Check in ~/Music and ~/Videos
193  // TODO: when the trust store lands, check it to see if this app can access the dirs and
194  // then remove the explicit whitelist of the music-app, and gallery-app
195  else if ((pkgname == "com.ubuntu.music" || pkgname == "com.ubuntu.gallery") &&
196  (uri.find(std::string("Music/")) != std::string::npos
197  || uri.find(std::string("Videos/")) != std::string::npos
198  || uri.find(std::string("/media")) != std::string::npos))
199  {
200  std::cout << "Client can access content in ~/Music or ~/Videos" << std::endl;
201  return true;
202  }
203  else if (uri.find(std::string("/usr/share/sounds")) != std::string::npos)
204  {
205  std::cout << "Client can access content in /usr/share/sounds" << std::endl;
206  return true;
207  }
208  else if (uri.find(std::string("http://")) != std::string::npos
209  || uri.find(std::string("rtsp://")) != std::string::npos)
210  {
211  std::cout << "Client can access streaming content" << std::endl;
212  return true;
213  }
214  else
215  {
216  std::cout << "Client denied access to open_uri()" << std::endl;
217  return false;
218  }
219  }
220 
221  void handle_key(const core::dbus::Message::Ptr& in)
222  {
223  auto reply = dbus::Message::make_method_return(in);
224  reply->writer() << impl->key();
225  bus->send(reply);
226  }
227 
228  void handle_open_uri(const core::dbus::Message::Ptr& in)
229  {
230  dbus_stub.get_connection_app_armor_security_async(in->sender(), [this, in](const std::string& profile)
231  {
232  Track::UriType uri;
233  in->reader() >> uri;
234 
235  bool have_access = does_client_have_access(profile, uri);
236 
237  auto reply = dbus::Message::make_method_return(in);
238  reply->writer() << (have_access ? impl->open_uri(uri) : false);
239 
240  bus->send(reply);
241  });
242  }
243 
244  void handle_open_uri_extended(const core::dbus::Message::Ptr& in)
245  {
246  dbus_stub.get_connection_app_armor_security_async(in->sender(), [this, in](const std::string& profile)
247  {
248  Track::UriType uri;
249  Player::HeadersType headers;
250 
251  in->reader() >> uri >> headers;
252 
253  bool have_access = does_client_have_access(profile, uri);
254  auto reply = dbus::Message::make_method_return(in);
255  reply->writer() << (have_access ? impl->open_uri(uri, headers) : false);
256 
257  bus->send(reply);
258  });
259  }
260 
261  template<typename Property>
263  const typename Property::ValueType& value,
264  const dbus::Signal
265  <
266  core::dbus::interfaces::Properties::Signals::PropertiesChanged,
267  core::dbus::interfaces::Properties::Signals::PropertiesChanged::ArgumentType
268  >::Ptr& signal)
269  {
270  typedef std::map<std::string, dbus::types::Variant> Dictionary;
271 
272  static const std::vector<std::string> the_empty_list_of_invalidated_properties;
273 
274  Dictionary dict; dict[Property::name()] = dbus::types::Variant::encode(value);
275 
276  signal->emit(std::make_tuple(
277  dbus::traits::Service<typename Property::Interface>::interface_name(),
278  dict,
279  the_empty_list_of_invalidated_properties));
280  }
281 
283  std::string identity;
284  dbus::Bus::Ptr bus;
285  dbus::Object::Ptr object;
286  dbus::Object::Ptr apparmor_session;
287 
289 
291 
292  struct Signals
293  {
294  typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
295  typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
296  typedef core::dbus::Signal<mpris::Player::Signals::PlaybackStatusChanged, mpris::Player::Signals::PlaybackStatusChanged::ArgumentType> DBusPlaybackStatusChangedSignal;
297  typedef core::dbus::Signal<mpris::Player::Signals::VideoDimensionChanged, mpris::Player::Signals::VideoDimensionChanged::ArgumentType> DBusVideoDimensionChangedSignal;
298  typedef core::dbus::Signal<mpris::Player::Signals::Error, mpris::Player::Signals::Error::ArgumentType> DBusErrorSignal;
299 
300  Signals(const std::shared_ptr<DBusSeekedToSignal>& remote_seeked,
301  const std::shared_ptr<DBusEndOfStreamSignal>& remote_eos,
302  const std::shared_ptr<DBusPlaybackStatusChangedSignal>& remote_playback_status_changed,
303  const std::shared_ptr<DBusVideoDimensionChangedSignal>& remote_video_dimension_changed,
304  const std::shared_ptr<DBusErrorSignal>& remote_error)
305  {
306  seeked_to.connect([remote_seeked](std::uint64_t value)
307  {
308  remote_seeked->emit(value);
309  });
310 
311  end_of_stream.connect([remote_eos]()
312  {
313  remote_eos->emit();
314  });
315 
316  playback_status_changed.connect([remote_playback_status_changed](const media::Player::PlaybackStatus& status)
317  {
318  remote_playback_status_changed->emit(status);
319  });
320 
321  video_dimension_changed.connect([remote_video_dimension_changed](uint64_t mask)
322  {
323  remote_video_dimension_changed->emit(mask);
324  });
325 
326  error.connect([remote_error](const media::Player::Error& e)
327  {
328  remote_error->emit(e);
329  });
330  }
331 
332  core::Signal<int64_t> seeked_to;
333  core::Signal<void> end_of_stream;
334  core::Signal<media::Player::PlaybackStatus> playback_status_changed;
335  core::Signal<uint64_t> video_dimension_changed;
336  core::Signal<media::Player::Error> error;
337  } signals;
338 
339 };
340 
341 media::PlayerSkeleton::PlayerSkeleton(const media::PlayerSkeleton::Configuration& config)
342  : d(new Private{this, config.identity, config.bus, config.session})
343 {
344  // Setup method handlers for mpris::Player methods.
345  auto next = std::bind(&Private::handle_next, d, std::placeholders::_1);
346  d->object->install_method_handler<mpris::Player::Next>(next);
347 
348  auto previous = std::bind(&Private::handle_previous, d, std::placeholders::_1);
349  d->object->install_method_handler<mpris::Player::Previous>(previous);
350 
351  auto pause = std::bind(&Private::handle_pause, d, std::placeholders::_1);
352  d->object->install_method_handler<mpris::Player::Pause>(pause);
353 
354  auto stop = std::bind(&Private::handle_stop, d, std::placeholders::_1);
355  d->object->install_method_handler<mpris::Player::Stop>(stop);
356 
357  auto play = std::bind(&Private::handle_play, d, std::placeholders::_1);
358  d->object->install_method_handler<mpris::Player::Play>(play);
359 
360  auto play_pause = std::bind(&Private::handle_play_pause, d, std::placeholders::_1);
361  d->object->install_method_handler<mpris::Player::PlayPause>(play_pause);
362 
363  auto seek = std::bind(&Private::handle_seek, d, std::placeholders::_1);
364  d->object->install_method_handler<mpris::Player::Seek>(seek);
365 
366  auto set_position = std::bind(&Private::handle_set_position, d, std::placeholders::_1);
367  d->object->install_method_handler<mpris::Player::SetPosition>(set_position);
368 
369  auto open_uri = std::bind(&Private::handle_open_uri, d, std::placeholders::_1);
370  d->object->install_method_handler<mpris::Player::OpenUri>(open_uri);
371 
372  // All the method handlers that exceed the mpris spec go here.
373  d->object->install_method_handler<mpris::Player::CreateVideoSink>(
375  d,
376  std::placeholders::_1));
377 
378  d->object->install_method_handler<mpris::Player::Key>(
379  std::bind(&Private::handle_key,
380  d,
381  std::placeholders::_1));
382 
383  d->object->install_method_handler<mpris::Player::OpenUriExtended>(
385  d,
386  std::placeholders::_1));
387 }
388 
390 {
391  // The session object may outlive the private instance
392  // so uninstall all method handlers.
393  d->object->uninstall_method_handler<mpris::Player::Next>();
394  d->object->uninstall_method_handler<mpris::Player::Previous>();
395  d->object->uninstall_method_handler<mpris::Player::Pause>();
396  d->object->uninstall_method_handler<mpris::Player::Stop>();
397  d->object->uninstall_method_handler<mpris::Player::Play>();
398  d->object->uninstall_method_handler<mpris::Player::PlayPause>();
399  d->object->uninstall_method_handler<mpris::Player::Seek>();
400  d->object->uninstall_method_handler<mpris::Player::SetPosition>();
401  d->object->uninstall_method_handler<mpris::Player::OpenUri>();
402  d->object->uninstall_method_handler<mpris::Player::CreateVideoSink>();
403  d->object->uninstall_method_handler<mpris::Player::Key>();
404  d->object->uninstall_method_handler<mpris::Player::OpenUriExtended>();
405 }
406 
407 const core::Property<bool>& media::PlayerSkeleton::can_play() const
408 {
409  return *d->skeleton.properties.can_play;
410 }
411 
412 const core::Property<bool>& media::PlayerSkeleton::can_pause() const
413 {
414  return *d->skeleton.properties.can_pause;
415 }
416 
417 const core::Property<bool>& media::PlayerSkeleton::can_seek() const
418 {
419  return *d->skeleton.properties.can_seek;
420 }
421 
422 const core::Property<bool>& media::PlayerSkeleton::can_go_previous() const
423 {
424  return *d->skeleton.properties.can_go_previous;
425 }
426 
427 const core::Property<bool>& media::PlayerSkeleton::can_go_next() const
428 {
429  return *d->skeleton.properties.can_go_next;
430 }
431 
432 const core::Property<bool>& media::PlayerSkeleton::is_video_source() const
433 {
434  return *d->skeleton.properties.is_video_source;
435 }
436 
437 const core::Property<bool>& media::PlayerSkeleton::is_audio_source() const
438 {
439  return *d->skeleton.properties.is_audio_source;
440 }
441 
442 const core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status() const
443 {
444  return *d->skeleton.properties.typed_playback_status;
445 }
446 
447 const core::Property<media::Player::LoopStatus>& media::PlayerSkeleton::loop_status() const
448 {
449  return *d->skeleton.properties.typed_loop_status;
450 }
451 
452 const core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::playback_rate() const
453 {
454  return *d->skeleton.properties.playback_rate;
455 }
456 
457 const core::Property<bool>& media::PlayerSkeleton::is_shuffle() const
458 {
459  return *d->skeleton.properties.is_shuffle;
460 }
461 
462 const core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track() const
463 {
464  return *d->skeleton.properties.typed_meta_data_for_current_track;
465 }
466 
467 const core::Property<media::Player::Volume>& media::PlayerSkeleton::volume() const
468 {
469  return *d->skeleton.properties.volume;
470 }
471 
472 const core::Property<int64_t>& media::PlayerSkeleton::position() const
473 {
474  return *d->skeleton.properties.position;
475 }
476 
477 const core::Property<int64_t>& media::PlayerSkeleton::duration() const
478 {
479  return *d->skeleton.properties.duration;
480 }
481 
482 const core::Property<media::Player::AudioStreamRole>& media::PlayerSkeleton::audio_stream_role() const
483 {
484  return *d->skeleton.properties.audio_stream_role;
485 }
486 
487 const core::Property<media::Player::Orientation>& media::PlayerSkeleton::orientation() const
488 {
489  return *d->skeleton.properties.orientation;
490 }
491 
492 const core::Property<media::Player::Lifetime>& media::PlayerSkeleton::lifetime() const
493 {
494  return *d->skeleton.properties.lifetime;
495 }
496 
497 const core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::minimum_playback_rate() const
498 {
499  return *d->skeleton.properties.minimum_playback_rate;
500 }
501 
502 const core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::maximum_playback_rate() const
503 {
504  return *d->skeleton.properties.maximum_playback_rate;
505 }
506 
507 core::Property<media::Player::LoopStatus>& media::PlayerSkeleton::loop_status()
508 {
509  return *d->skeleton.properties.typed_loop_status;
510 }
511 
512 core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::playback_rate()
513 {
514  return *d->skeleton.properties.playback_rate;
515 }
516 
517 core::Property<bool>& media::PlayerSkeleton::is_shuffle()
518 {
519  return *d->skeleton.properties.is_shuffle;
520 }
521 
522 core::Property<media::Player::Volume>& media::PlayerSkeleton::volume()
523 {
524  return *d->skeleton.properties.volume;
525 }
526 
527 core::Property<int64_t>& media::PlayerSkeleton::position()
528 {
529  return *d->skeleton.properties.position;
530 }
531 
532 core::Property<int64_t>& media::PlayerSkeleton::duration()
533 {
534  return *d->skeleton.properties.duration;
535 }
536 
537 core::Property<media::Player::AudioStreamRole>& media::PlayerSkeleton::audio_stream_role()
538 {
539  return *d->skeleton.properties.audio_stream_role;
540 }
541 
542 core::Property<media::Player::Orientation>& media::PlayerSkeleton::orientation()
543 {
544  return *d->skeleton.properties.orientation;
545 }
546 
547 core::Property<media::Player::Lifetime>& media::PlayerSkeleton::lifetime()
548 {
549  return *d->skeleton.properties.lifetime;
550 }
551 
552 core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status()
553 {
554  return *d->skeleton.properties.typed_playback_status;
555 }
556 
557 core::Property<bool>& media::PlayerSkeleton::can_play()
558 {
559  return *d->skeleton.properties.can_play;
560 }
561 
562 core::Property<bool>& media::PlayerSkeleton::can_pause()
563 {
564  return *d->skeleton.properties.can_pause;
565 }
566 
567 core::Property<bool>& media::PlayerSkeleton::can_seek()
568 {
569  return *d->skeleton.properties.can_seek;
570 }
571 
572 core::Property<bool>& media::PlayerSkeleton::can_go_previous()
573 {
574  return *d->skeleton.properties.can_go_previous;
575 }
576 
577 core::Property<bool>& media::PlayerSkeleton::can_go_next()
578 {
579  return *d->skeleton.properties.can_go_next;
580 }
581 
582 core::Property<bool>& media::PlayerSkeleton::is_video_source()
583 {
584  return *d->skeleton.properties.is_video_source;
585 }
586 
587 core::Property<bool>& media::PlayerSkeleton::is_audio_source()
588 {
589  return *d->skeleton.properties.is_audio_source;
590 }
591 
592 core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track()
593 {
594  return *d->skeleton.properties.typed_meta_data_for_current_track;
595 }
596 
597 core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::minimum_playback_rate()
598 {
599  return *d->skeleton.properties.minimum_playback_rate;
600 }
601 
602 core::Property<media::Player::PlaybackRate>& media::PlayerSkeleton::maximum_playback_rate()
603 {
604  return *d->skeleton.properties.maximum_playback_rate;
605 }
606 
607 const core::Signal<int64_t>& media::PlayerSkeleton::seeked_to() const
608 {
609  return d->signals.seeked_to;
610 }
611 
612 core::Signal<int64_t>& media::PlayerSkeleton::seeked_to()
613 {
614  return d->signals.seeked_to;
615 }
616 
617 const core::Signal<void>& media::PlayerSkeleton::end_of_stream() const
618 {
619  return d->signals.end_of_stream;
620 }
621 
622 core::Signal<void>& media::PlayerSkeleton::end_of_stream()
623 {
624  return d->signals.end_of_stream;
625 }
626 
627 core::Signal<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status_changed()
628 {
629  return d->signals.playback_status_changed;
630 }
631 
632 const core::Signal<uint64_t>& media::PlayerSkeleton::video_dimension_changed() const
633 {
634  return d->signals.video_dimension_changed;
635 }
636 
637 core::Signal<uint64_t>& media::PlayerSkeleton::video_dimension_changed()
638 {
639  return d->signals.video_dimension_changed;
640 }
641 
642 core::Signal<media::Player::Error>& media::PlayerSkeleton::error()
643 {
644  return d->signals.error;
645 }
646 
647 const core::Signal<media::Player::Error>& media::PlayerSkeleton::error() const
648 {
649  return d->signals.error;
650 }
void handle_previous(const core::dbus::Message::Ptr &msg)
Signals(const std::shared_ptr< DBusSeekedToSignal > &remote_seeked, const std::shared_ptr< DBusEndOfStreamSignal > &remote_eos, const std::shared_ptr< DBusPlaybackStatusChangedSignal > &remote_playback_status_changed, const std::shared_ptr< DBusVideoDimensionChangedSignal > &remote_video_dimension_changed, const std::shared_ptr< DBusErrorSignal > &remote_error)
virtual const core::Signal< Error > & error() const
mpris::Player::Skeleton skeleton
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
virtual const core::Signal< void > & end_of_stream() const
virtual const core::Property< int64_t > & duration() const
virtual const core::Property< bool > & can_seek() const
virtual const core::Property< PlaybackRate > & maximum_playback_rate() const
virtual const core::Property< bool > & is_shuffle() const
virtual const core::Property< bool > & can_go_next() const
virtual const core::Property< int64_t > & position() const
virtual const core::Property< bool > & can_go_previous() const
virtual void previous()=0
void handle_set_position(const core::dbus::Message::Ptr &)
void handle_open_uri_extended(const core::dbus::Message::Ptr &in)
bool does_client_have_access(const std::string &context, const std::string &uri)
virtual const core::Property< bool > & can_play() const
core::dbus::Signal< Signals::VideoDimensionChanged, Signals::VideoDimensionChanged::ArgumentType >::Ptr video_dimension_changed
Definition: player.h:363
std::map< std::string, std::string > HeadersType
Definition: player.h:45
void handle_play_pause(const core::dbus::Message::Ptr &msg)
virtual const core::Property< Track::MetaData > & meta_data_for_current_track() const
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)
Private(media::PlayerSkeleton *player, const std::string &identity, const std::shared_ptr< core::dbus::Bus > &bus, const std::shared_ptr< core::dbus::Object > &session)
virtual const core::Signal< uint64_t > & video_dimension_changed() const
virtual bool open_uri(const Track::UriType &uri)=0
virtual const core::Signal< int64_t > & seeked_to() const
virtual const core::Property< PlaybackRate > & playback_rate() const
PlayerSkeleton(const Configuration &configuration)
virtual void create_video_sink(uint32_t texture_id)=0
virtual const core::Property< AudioStreamRole > & audio_stream_role() const
core::dbus::Signal< mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType > DBusEndOfStreamSignal
media::PlayerSkeleton * impl
core::dbus::Signal< mpris::Player::Signals::VideoDimensionChanged, mpris::Player::Signals::VideoDimensionChanged::ArgumentType > DBusVideoDimensionChangedSignal
void handle_pause(const core::dbus::Message::Ptr &msg)
core::Signal< uint64_t > video_dimension_changed
core::dbus::Signal< mpris::Player::Signals::PlaybackStatusChanged, mpris::Player::Signals::PlaybackStatusChanged::ArgumentType > DBusPlaybackStatusChangedSignal
virtual const core::Property< PlaybackRate > & minimum_playback_rate() const
struct media::PlayerSkeleton::Private::Signals signals
core::Signal< media::Player::Error > error
void handle_seek(const core::dbus::Message::Ptr &in)
virtual const core::Property< Orientation > & orientation() const
void get_connection_app_armor_security_async(const std::string &name, std::function< void(const std::string &)> handler)
Definition: apparmor.h:75
struct mpris::Player::Skeleton::@15 signals
org::freedesktop::dbus::DBus::Stub dbus_stub
void handle_open_uri(const core::dbus::Message::Ptr &in)
core::dbus::Signal< Signals::Seeked, Signals::Seeked::ArgumentType >::Ptr seeked_to
Definition: player.h:360
virtual const core::Property< Volume > & volume() const
std::string UriType
Definition: track.h:40
virtual PlayerKey key() const =0
void handle_next(const core::dbus::Message::Ptr &msg)
virtual core::Signal< PlaybackStatus > & playback_status_changed()
void on_property_value_changed(const typename Property::ValueType &value, const dbus::Signal< core::dbus::interfaces::Properties::Signals::PropertiesChanged, core::dbus::interfaces::Properties::Signals::PropertiesChanged::ArgumentType >::Ptr &signal)
virtual const core::Property< bool > & is_audio_source() const
core::dbus::Signal< mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType > DBusSeekedToSignal
core::dbus::Signal< Signals::EndOfStream, Signals::EndOfStream::ArgumentType >::Ptr end_of_stream
Definition: player.h:361
core::dbus::Signal< mpris::Player::Signals::Error, mpris::Player::Signals::Error::ArgumentType > DBusErrorSignal
core::Signal< media::Player::PlaybackStatus > playback_status_changed
virtual const core::Property< Lifetime > & lifetime() const
core::dbus::Signal< Signals::PlaybackStatusChanged, Signals::PlaybackStatusChanged::ArgumentType >::Ptr playback_status_changed
Definition: player.h:362
void handle_create_video_sink(const core::dbus::Message::Ptr &in)
core::dbus::Signal< Signals::Error, Signals::Error::ArgumentType >::Ptr error
Definition: player.h:364
void handle_key(const core::dbus::Message::Ptr &in)
virtual void seek_to(const std::chrono::microseconds &offset)=0