Music Hub  ..
A session-wide music playback service
player_implementation.cpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2013-2015 Canonical Ltd.
3  * Copyright © 2022 UBports Foundation.
4  *
5  * Contact: Alberto Mardegan <mardy@users.sourceforge.net>
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License version 3,
9  * as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Authored by: Thomas Voß <thomas.voss@canonical.com>
20  * Jim Hodapp <jim.hodapp@canonical.com>
21  */
22 
23 #include "player_implementation.h"
24 
25 #include <unistd.h>
26 #include <ctime>
27 
28 #include "client_death_observer.h"
29 #include "engine.h"
30 #include "logging.h"
32 #include "xesam.h"
33 
34 #include <QDateTime>
35 #include <QTimer>
36 #include <QVector>
37 
38 #include "gstreamer/engine.h"
39 
40 #include <memory>
41 #include <exception>
42 #include <mutex>
43 
44 namespace media = lomiri::MediaHubService;
45 
46 using namespace std;
47 using namespace media;
48 
49 namespace lomiri {
50 namespace MediaHubService {
51 
53 {
54  Q_DECLARE_PUBLIC(PlayerImplementation)
55 
56 public:
57  enum class wakelock_clear_t
58  {
59  WAKELOCK_CLEAR_INACTIVE,
60  WAKELOCK_CLEAR_DISPLAY,
61  WAKELOCK_CLEAR_SYSTEM,
62  WAKELOCK_CLEAR_INVALID
63  };
64 
65  PlayerImplementationPrivate(const media::PlayerImplementation::Configuration &config,
68 
70  {
71  /*
72  * Wakelock state logic:
73  * PLAYING->READY or PLAYING->PAUSED or PLAYING->STOPPED: delay 4 seconds and try to clear current wakelock type
74  * ANY STATE->PLAYING: request a new wakelock (system or display)
75  */
76  MH_DEBUG() << "Setting state:" << state;
77  switch(state)
78  {
79  case Engine::State::ready:
80  {
81  if (previous_state == Engine::State::playing)
82  {
83  m_wakeLockTimer.start();
84  }
85  break;
86  }
87  case Engine::State::playing:
88  {
89  // We update the track metadata prior to updating the playback status.
90  // Some MPRIS clients expect this order of events.
91  const auto trackMetadata = m_engine->trackMetadata();
92  media::Track::MetaData metadata = trackMetadata.second;
93  // Setting this with second resolution makes sure that the track_meta_data property changes
94  // and thus the track_meta_data().changed() signal gets sent out over dbus. Otherwise the
95  // Property caching mechanism would prevent this.
96  metadata.setLastUsed(QDateTime::currentDateTimeUtc().toString(Qt::ISODate));
97  update_mpris_metadata(trackMetadata.first, metadata);
98 
99  MH_INFO("Requesting power state");
100  request_power_state();
101  /* If this is part of a playlist, the wakelock timer was started
102  * when the previous track completed. So, we must stop it now or it
103  * will release the power state while we are playing. */
104  m_wakeLockTimer.stop();
105  break;
106  }
107  case Engine::State::stopped:
108  {
109  if (previous_state == Engine::State::playing)
110  {
111  m_wakeLockTimer.start();
112  }
113  break;
114  }
115  case Engine::State::paused:
116  {
117  if (previous_state == Engine::State::playing)
118  {
119  m_wakeLockTimer.start();
120  }
121  break;
122  }
123  default:
124  break;
125  };
126 
127  // Keep track of the previous Engine playback state:
128  previous_state = state;
129  }
130 
132  {
134  MH_TRACE("");
135  if (q->isVideoSource())
136  {
137  MH_INFO("Request display on.");
138  if (!m_holdsDisplayOn) {
139  power_state_controller->requestDisplayOn();
140  m_holdsDisplayOn = true;
141  }
142  }
143  else
144  {
145  MH_INFO("Request system state active.");
146  if (!m_holdsSystemActive) {
147  power_state_controller->requestSystemState(media::power::SystemState::active);
148  m_holdsSystemActive = true;
149  }
150  }
151  }
152 
153  void clear_wakelock(const wakelock_clear_t &wakelock)
154  {
155  MH_TRACE("");
156  switch (wakelock)
157  {
158  case wakelock_clear_t::WAKELOCK_CLEAR_INACTIVE:
159  break;
160  case wakelock_clear_t::WAKELOCK_CLEAR_SYSTEM:
161  MH_INFO("Release system state active.");
162  if (m_holdsSystemActive) {
163  power_state_controller->releaseSystemState(media::power::SystemState::active);
164  m_holdsSystemActive = false;
165  }
166  break;
167  case wakelock_clear_t::WAKELOCK_CLEAR_DISPLAY:
168  MH_INFO("Release display on.");
169  if (m_holdsDisplayOn) {
170  power_state_controller->releaseDisplayOn();
171  m_holdsDisplayOn = false;
172  }
173  break;
174  case wakelock_clear_t::WAKELOCK_CLEAR_INVALID:
175  default:
176  MH_WARNING("Can't clear invalid wakelock type");
177  }
178  }
179 
181  {
182  // Clear both types of wakelocks (display and system)
183  clear_wakelock(wakelock_clear_t::WAKELOCK_CLEAR_SYSTEM);
184  clear_wakelock(wakelock_clear_t::WAKELOCK_CLEAR_DISPLAY);
185  }
186 
188  {
190  m_engine->reset();
191 
192  // If the client disconnects, make sure both wakelock types
193  // are cleared
194  clear_wakelocks();
195  m_trackList->reset();
196 
197  // And tell the outside world that the client has gone away
198  Q_EMIT q->clientDisconnected();
199  }
200 
202  {
203  const QUrl uri = m_trackList->query_uri_for_track(id);
204  if (!uri.isEmpty())
205  {
206  // Using a TrackList for playback, added tracks via add_track(), but open_uri hasn't
207  // been called yet to load a media resource
208  MH_INFO("Calling d->m_engine->open_resource_for_uri() for first track added only: %s",
209  qUtf8Printable(uri.toString()));
210  MH_INFO("\twith a Track::Id: %s", qUtf8Printable(id));
211  static const bool do_pipeline_reset = true;
212  m_engine->open_resource_for_uri(uri, do_pipeline_reset);
213  }
214  }
215 
217  {
219  const bool has_previous = m_trackList->hasPrevious()
220  or m_trackList->loopStatus() != Player::LoopStatus::none;
221  const bool has_next = m_trackList->hasNext()
222  or m_trackList->loopStatus() != Player::LoopStatus::none;
223  const auto n_tracks = m_trackList->tracks().count();
224  const bool has_tracks = (n_tracks > 0) ? true : false;
225 
226  MH_INFO("Updating MPRIS TrackList properties:");
227  MH_INFO("\tTracks: %d", n_tracks);
228  MH_INFO("\thas_previous: %d", has_previous);
229  MH_INFO("\thas_next: %d", has_next);
230 
231  // Update properties
232  m_canPlay = has_tracks;
233  m_canPause = has_tracks;
234  m_canGoPrevious = has_previous;
235  m_canGoNext = has_next;
236  Q_EMIT q->mprisPropertiesChanged();
237  }
238 
239  QUrl get_uri_for_album_artwork(const QUrl &uri,
240  const media::Track::MetaData& metadata)
241  {
242  QUrl art_uri;
243  bool is_local_file = false;
244  if (not uri.isEmpty())
245  is_local_file = uri.isLocalFile();
246 
247  // If the track has a full image or preview image or is a video and it is a local file,
248  // then use the thumbnailer cache
249  if ( (metadata.value(tags::PreviewImage::name).toBool()
250  or (metadata.value(tags::Image::name).toBool())
251  or m_engine->isVideoSource())
252  and is_local_file)
253  {
254  art_uri = "image://thumbnailer/" + uri.path();
255  }
256  // If all else fails, display a placeholder icon
257  else
258  {
259  art_uri = "file:///usr/share/icons/suru/apps/scalable/music-app-symbolic.svg";
260  }
261 
262  return art_uri;
263  }
264 
265  // Makes sure all relevant metadata fields are set to current data and
266  // will trigger the track_meta_data().changed() signal to go out over dbus
267  void update_mpris_metadata(const QUrl &uri, const media::Track::MetaData &md)
268  {
270  media::Track::MetaData metadata{md};
271  if (not metadata.isSet(media::Track::MetaData::TrackIdKey))
272  {
273  const QString current_track = m_trackList->current();
274  if (not current_track.isEmpty())
275  {
276  const int last_slash = current_track.lastIndexOf('/');
277  const QStringRef track_id = current_track.midRef(last_slash + 1);
278  if (not track_id.isEmpty())
279  metadata.setTrackId("/org/mpris/MediaPlayer2/Track/" + track_id);
280  else
281  MH_WARNING("Failed to set MPRIS track id since the id value is NULL");
282  }
283  else
284  MH_WARNING("Failed to set MPRIS track id since the id value is NULL");
285  }
286 
287  if (not metadata.isSet(media::Track::MetaData::TrackArtlUrlKey))
288  metadata.setArtUrl(get_uri_for_album_artwork(uri, metadata));
289 
290  if (not metadata.isSet(media::Track::MetaData::TrackLengthKey))
291  {
292  // Duration is in nanoseconds, MPRIS spec requires microseconds
293  metadata.setTrackLength(m_engine->duration() / 1000);
294  }
295 
296  // not needed, and change frequently:
297  metadata.remove(QStringLiteral("bitrate"));
298  metadata.remove(QStringLiteral("minimum-bitrate"));
299  metadata.remove(QStringLiteral("maximum-bitrate"));
300 
301  m_metadataForCurrentTrack = metadata;
302  Q_EMIT q->metadataForCurrentTrackChanged();
303  }
304 
305  bool is_multimedia_role() const
306  {
307  return m_engine->audioStreamRole() == media::Player::AudioStreamRole::multimedia;
308  }
309 
312  media::power::StateController::Ptr power_state_controller;
313 
314  QScopedPointer<Engine> m_engine;
315  QSharedPointer<TrackListImplementation> m_trackList;
316  bool m_holdsSystemActive = false;
317  bool m_holdsDisplayOn = false;
319  std::atomic<bool> doing_abandon;
320  // Initialize default values for Player interface properties
321  bool m_canPlay = false;
322  bool m_canPause = false;
323  bool m_canGoPrevious = false;
324  bool m_canGoNext = false;
325  bool m_shuffle = false;
326  double m_playbackRate = 1.f;
327  Player::LoopStatus m_loopStatus = Player::LoopStatus::none;
328  int64_t m_position = 0;
329  int64_t m_duration = 0;
330  bool m_doingOpenUri = false;
331  Player::AudioStreamRole m_audioStreamRole = Player::AudioStreamRole::multimedia;
332  Player::Lifetime m_lifetime = Player::Lifetime::normal;
337 };
338 
339 }} // namespace
340 
341 PlayerImplementationPrivate::PlayerImplementationPrivate(
342  const media::PlayerImplementation::Configuration &config,
344  m_client(config.client),
345  m_clientDeathObserver(config.client_death_observer),
346  power_state_controller(media::power::StateController::instance()),
347  m_engine(new gstreamer::Engine(config.client.key)),
348  // TODO: set the path on the TrackListSkeleton!
349  // dbus::types::ObjectPath(config.parent.session->path().as_string() + "/TrackList")),
350  m_trackList(QSharedPointer<TrackListImplementation>::create(
351  m_engine->metadataExtractor())),
352  previous_state(Engine::State::stopped),
353  doing_abandon(false),
354  q_ptr(q)
355 {
356  // Poor man's logging of release/acquire events.
357  QObject::connect(power_state_controller.data(),
359  q, []() {
360  MH_INFO("Acquired display ON state");
361  });
362 
363  QObject::connect(power_state_controller.data(),
365  q, []() {
366  MH_INFO("Released display ON state");
367  });
368 
369  QObject::connect(power_state_controller.data(),
371  q, [](media::power::SystemState state)
372  {
373  MH_INFO() << "Acquired new system state:" << state;
374  });
375 
376  QObject::connect(power_state_controller.data(),
378  q, [](media::power::SystemState state)
379  {
380  MH_INFO() << "Released system state:" << state;
381  });
382 
383  QObject::connect(m_engine.data(), &Engine::stateChanged,
384  q, [this]() {
385  onStateChanged(m_engine->state());
386  });
387 
388  QObject::connect(m_engine.data(), &Engine::isVideoSourceChanged,
389  q, [this, q]() {
390  // Video streams on remote media are detected only after the playback
391  // has started; in that case, when the playback started we only
392  // requested the system wakelock, and now (if we are in "playing" state
393  // and the media has a video stream) we need to request the display
394  // lock too.
395  if (m_engine->state() == Engine::State::playing) {
396  MH_INFO("Streams changed, updating power/display locks");
397  request_power_state();
398  }
399  Q_EMIT q->isVideoSourceChanged();
400  });
401  QObject::connect(m_engine.data(), &Engine::isAudioSourceChanged,
403 
404  // Initialize default values for Player interface properties
405  m_engine->setAudioStreamRole(Player::AudioStreamRole::multimedia);
406  m_engine->setLifetime(Player::Lifetime::normal);
407 
408  // Make sure that the Position property gets updated from the Engine
409  // every time the client requests position
410  QObject::connect(m_engine.data(), &Engine::positionChanged,
411  q, [this, q]() {
412  m_trackList->setCurrentPosition(m_engine->position());
413  Q_EMIT q->positionChanged();
414  });
415 
416  // Make sure that the Duration property gets updated from the Engine
417  // every time the client requests duration
418  QObject::connect(m_engine.data(), &Engine::durationChanged,
420 
421  // When the value of the orientation Property is changed in the Engine by playbin,
422  // update the Player's cached value
423  QObject::connect(m_engine.data(), &Engine::orientationChanged,
425 
426  QObject::connect(m_engine.data(), &Engine::trackMetadataChanged,
427  q, [this]() {
428  const auto md = m_engine->trackMetadata();
429  update_mpris_metadata(md.first, md.second);
430  });
431 
432  QObject::connect(m_engine.data(), &Engine::endOfStream,
433  q, [q, this]()
434  {
435  if (doing_abandon)
436  return;
437 
438  Q_EMIT q->endOfStream();
439 
440  // Make sure that the TrackList keeps advancing. The logic for what gets played next,
441  // if anything at all, occurs in TrackListSkeleton::next()
442  m_trackList->next();
443  });
444 
445  QObject::connect(m_engine.data(), &Engine::clientDisconnected,
446  q, [this]()
447  {
448  on_client_died();
449  });
450 
451  QObject::connect(m_engine.data(), &Engine::seekedTo,
453  QObject::connect(m_engine.data(), &Engine::bufferingChanged,
455  QObject::connect(m_engine.data(), &Engine::playbackStatusChanged,
457  QObject::connect(m_engine.data(), &Engine::aboutToFinish,
459  QObject::connect(m_engine.data(), &Engine::videoDimensionChanged,
461  QObject::connect(m_engine.data(), &Engine::errorOccurred,
463 
464  QObject::connect(m_trackList.data(), &TrackListImplementation::endOfTrackList,
465  q, [this]()
466  {
467  if (m_engine->state() != gstreamer::Engine::State::stopped)
468  {
469  MH_INFO("End of tracklist reached, stopping playback");
470  m_engine->stop();
471  }
472  });
473 
474  QObject::connect(m_trackList.data(), &TrackListImplementation::onGoToTrack,
475  q, [this](const media::Track::Id &id)
476  {
477  // Store whether we should restore the current playing state after loading the new uri
478  const bool auto_play = m_engine->playbackStatus() == media::Player::playing;
479 
480  const QUrl uri = m_trackList->query_uri_for_track(id);
481  if (!uri.isEmpty())
482  {
483  MH_INFO("Setting next track on playbin (on_go_to_track signal): %s",
484  qUtf8Printable(uri.toString()));
485  MH_INFO("\twith a Track::Id: %s", qUtf8Printable(id));
486  static const bool do_pipeline_reset = true;
487  m_engine->open_resource_for_uri(uri, do_pipeline_reset);
488  }
489 
490  if (auto_play)
491  {
492  MH_DEBUG("Restoring playing state");
493  m_engine->play();
494  }
495  });
496 
497  QObject::connect(m_trackList.data(), &TrackListImplementation::trackAdded,
498  q, [this](const media::Track::Id &id)
499  {
500  MH_TRACE("** Track was added, handling in PlayerImplementation");
501  if (!m_doingOpenUri && m_trackList->tracks().count() == 1)
502  open_first_track_from_tracklist(id);
503 
504  update_mpris_properties();
505  });
506 
507  QObject::connect(m_trackList.data(), &TrackListImplementation::tracksAdded,
508  q, [this](const QVector<QUrl> &tracks)
509  {
510  MH_TRACE("** Track was added, handling in PlayerImplementation");
511  // If the two sizes are the same, that means the TrackList was previously empty and we need
512  // to open the first track in the TrackList so that is_audio_source() and is_video_source()
513  // will function correctly.
514  /* FIXME: we are passing a URL to a method expecting a track ID, so
515  * this will not work; on the other hand, the code has always been like
516  * this, so let's fix it later. */
517  if (not tracks.isEmpty() and m_trackList->tracks().count() == tracks.count())
518  open_first_track_from_tracklist(tracks.front().toString());
519 
520  update_mpris_properties();
521  });
522 
523  QObject::connect(m_trackList.data(),
524  &TrackListImplementation::trackRemoved,
525  q, [this]() { update_mpris_properties(); });
526 
527  QObject::connect(m_trackList.data(),
528  &TrackListImplementation::trackListReset,
529  q, [this]() { update_mpris_properties(); });
530 
531  QObject::connect(m_trackList.data(),
532  &TrackListImplementation::trackChanged,
533  q, [this]() { update_mpris_properties(); });
534 
535  QObject::connect(m_trackList.data(),
536  &TrackListImplementation::trackListReplaced,
537  q, [this]() { update_mpris_properties(); });
538 
539  // Everything is setup, we now subscribe to death notifications.
540  m_clientDeathObserver->registerForDeathNotifications(m_client);
541  QObject::connect(m_clientDeathObserver.data(),
542  &ClientDeathObserver::clientDied,
543  q, [this](const media::Player::Client &died)
544  {
545  if (doing_abandon)
546  return;
547 
548  if (died.key != m_client.key)
549  return;
550 
551  m_abandonTimer.start();
552  });
553 
554  m_abandonTimer.setSingleShot(true);
555  m_abandonTimer.setInterval(1000);
556  m_abandonTimer.callOnTimeout(q, [this]() { on_client_died(); });
557 
558  m_wakeLockTimer.setSingleShot(true);
559  int wakelockTimeout =
560  qEnvironmentVariableIsSet("MEDIA_HUB_WAKELOCK_TIMEOUT") ?
561  qEnvironmentVariableIntValue("MEDIA_HUB_WAKELOCK_TIMEOUT") : 4000;
562  m_wakeLockTimer.setInterval(wakelockTimeout);
563  m_wakeLockTimer.setTimerType(Qt::VeryCoarseTimer);
564  m_wakeLockTimer.callOnTimeout(q, [this]() {
565  clear_wakelocks();
566  });
567 }
568 
569 PlayerImplementationPrivate::~PlayerImplementationPrivate()
570 {
571  // Make sure that we don't hold on to the wakelocks if media-hub-server
572  // ever gets restarted manually or automatically
573  clear_wakelocks();
574 }
575 
577  QObject *parent):
578  QObject(parent),
579  d_ptr(new media::PlayerImplementationPrivate(config, this))
580 {
581  QObject::connect(this, &QObject::objectNameChanged,
582  this, [this](const QString &name) {
584  d->m_trackList->setObjectName(name + "/TrackList");
585  });
586 }
587 
589 {
590 }
591 
593 {
595 }
596 
598 {
599  Q_D(const PlayerImplementation);
600  return d->m_client;
601 }
602 
604 {
605  Q_D(const PlayerImplementation);
606  return d->m_canPlay;
607 }
608 
610 {
611  Q_D(const PlayerImplementation);
612  return d->m_canPause;
613 }
614 
616 {
617  Q_D(const PlayerImplementation);
618  return true;
619 }
620 
622 {
623  Q_D(const PlayerImplementation);
624  return d->m_canGoPrevious;
625 }
626 
628 {
629  Q_D(const PlayerImplementation);
630  return d->m_canGoNext;
631 }
632 
634 {
635  Q_UNUSED(rate);
636  MH_WARNING("Setting playback rate not implemented");
637 }
638 
640 {
641  return 1.0;
642 }
643 
645 {
646  return 1.0;
647 }
648 
650 {
651  return 1.0;
652 }
653 
655 {
657  MH_INFO() << "LoopStatus:" << status;
658  d->m_trackList->setLoopStatus(status);
659 }
660 
662 {
663  Q_D(const PlayerImplementation);
664  return d->m_trackList->loopStatus();
665 }
666 
668 {
670  d->m_trackList->setShuffle(shuffle);
671 }
672 
674 {
675  Q_D(const PlayerImplementation);
676  return d->m_trackList->shuffle();
677 }
678 
680 {
682  d->m_engine->setVolume(volume);
683  Q_EMIT volumeChanged();
684 }
685 
687 {
688  Q_D(const PlayerImplementation);
689  return d->m_engine->volume();
690 }
691 
693 {
694  Q_D(const PlayerImplementation);
695  return d->m_engine->playbackStatus();
696 }
697 
699 {
700  Q_D(const PlayerImplementation);
701  return d->m_engine->isVideoSource();
702 }
703 
705 {
706  Q_D(const PlayerImplementation);
707  return d->m_engine->isAudioSource();
708 }
709 
711 {
712  Q_D(const PlayerImplementation);
713  return d->m_engine->videoDimension();
714 }
715 
717 {
718  Q_D(const PlayerImplementation);
719  return d->m_engine->orientation();
720 }
721 
723 {
724  Q_D(const PlayerImplementation);
725  return d->m_metadataForCurrentTrack;
726 }
727 
729 {
730  Q_D(const PlayerImplementation);
731  return d->m_engine->position();
732 }
733 
735 {
736  Q_D(const PlayerImplementation);
737  return d->m_engine->duration();
738 }
739 
741 {
743  d->m_engine->setAudioStreamRole(role);
744 }
745 
747 {
748  Q_D(const PlayerImplementation);
749  return d->m_engine->audioStreamRole();
750 }
751 
753 {
755  d->m_engine->setLifetime(lifetime);
756 }
757 
759 {
760  Q_D(const PlayerImplementation);
761  return d->m_engine->lifetime();
762 }
763 
765 {
767  d->m_clientDeathObserver->registerForDeathNotifications(d->m_client);
768 }
769 
771 {
773  // Signal client disconnection due to abandonment of player
774  d->doing_abandon = true;
775  d->on_client_died();
776 }
777 
778 QSharedPointer<TrackListImplementation> media::PlayerImplementation::trackList()
779 {
781  return d->m_trackList;
782 }
783 
785 {
786  Q_D(const PlayerImplementation);
787  return d->m_client.key;
788 }
789 
791 {
793  d->m_engine->create_video_sink(texture_id);
794 }
795 
796 bool PlayerImplementation::open_uri(const QUrl &uri)
797 {
798  return open_uri(uri, Headers());
799 }
800 
801 bool PlayerImplementation::open_uri(const QUrl &uri, const Headers &headers)
802 {
804  d->m_doingOpenUri = true;
805  d->m_trackList->reset();
806 
807  // If empty uri, give the same meaning as QMediaPlayer::setMedia("")
808  if (uri.isEmpty())
809  {
810  MH_DEBUG("Resetting current media");
811  return true;
812  }
813 
814  const bool ret = d->m_engine->open_resource_for_uri(uri, headers);
815  // Don't set new track as the current track to play since we're calling open_resource_for_uri above
816  static const bool make_current = false;
817  d->m_trackList->add_track_with_uri_at(uri, TrackListImplementation::afterEmptyTrack(), make_current);
818  d->m_doingOpenUri = false;
819 
820  return ret;
821 }
822 
824 {
826  d->m_trackList->next();
827 }
828 
830 {
832  d->m_trackList->previous();
833 }
834 
836 {
837  MH_TRACE("");
839  if (d->is_multimedia_role())
840  {
841  Q_EMIT playbackRequested();
842  }
843 
844  d->m_engine->play();
845 }
846 
848 {
849  MH_TRACE("");
851  d->m_engine->pause();
852 }
853 
855 {
856  MH_TRACE("");
858  d->m_engine->stop();
859 }
860 
861 void PlayerImplementation::seek_to(const std::chrono::microseconds& ms)
862 {
864  d->m_engine->seek_to(ms);
865 }
lomiri::MediaHubService::PlayerImplementation::canSeek
bool canSeek() const
Definition: player_implementation.cpp:615
lomiri::MediaHubService::PlayerImplementation::abandon
void abandon()
Definition: player_implementation.cpp:770
lomiri::MediaHubService::Engine::State
State
Definition: engine.h:50
lomiri::MediaHubService::Engine::errorOccurred
void errorOccurred(Player::Error error)
lomiri::MediaHubService::PlayerImplementation::durationChanged
void durationChanged()
lomiri::MediaHubService::PlayerImplementation::shuffle
bool shuffle() const
Definition: player_implementation.cpp:673
QObject
lomiri::MediaHubService::PlayerImplementationPrivate
Definition: player_implementation.cpp:52
lomiri::MediaHubService::Track::MetaData
Definition: track.h:37
lomiri::MediaHubService::PlayerImplementation::seekedTo
void seekedTo(uint64_t offset)
lomiri::MediaHubService::PlayerImplementation::key
Player::PlayerKey key() const
Definition: player_implementation.cpp:784
lomiri::MediaHubService::PlayerImplementationPrivate::m_wakeLockTimer
QTimer m_wakeLockTimer
Definition: player_implementation.cpp:334
lomiri::MediaHubService::Engine::trackMetadataChanged
void trackMetadataChanged()
lomiri::MediaHubService::PlayerImplementation::duration
uint64_t duration() const
Definition: player_implementation.cpp:734
lomiri::MediaHubService::PlayerImplementationPrivate::update_mpris_properties
void update_mpris_properties()
Definition: player_implementation.cpp:216
lomiri::MediaHubService::PlayerImplementation::client
const Player::Client & client() const
Definition: player_implementation.cpp:597
lomiri::MediaHubService::PlayerImplementation
Definition: player_implementation.h:44
lomiri::MediaHubService::PlayerImplementation::loopStatus
Player::LoopStatus loopStatus() const
Definition: player_implementation.cpp:661
lomiri::MediaHubService::PlayerImplementation::volume
double volume() const
Definition: player_implementation.cpp:686
lomiri::MediaHubService::PlayerImplementation::isAudioSourceChanged
void isAudioSourceChanged()
lomiri::MediaHubService::Player::LoopStatus
LoopStatus
Definition: player.h:101
lomiri::MediaHubService::PlayerImplementation::setShuffle
void setShuffle(bool shuffle)
Definition: player_implementation.cpp:667
lomiri::MediaHubService::Engine::clientDisconnected
void clientDisconnected()
lomiri::MediaHubService::PlayerImplementation::setVolume
void setVolume(double volume)
Definition: player_implementation.cpp:679
lomiri::MediaHubService::PlayerImplementationPrivate::update_mpris_metadata
void update_mpris_metadata(const QUrl &uri, const media::Track::MetaData &md)
Definition: player_implementation.cpp:267
lomiri::MediaHubService::PlayerImplementation::playbackStatusChanged
void playbackStatusChanged()
lomiri::MediaHubService::PlayerImplementation::videoDimensionChanged
void videoDimensionChanged()
lomiri::MediaHubService::PlayerImplementation::minimumRate
double minimumRate() const
Definition: player_implementation.cpp:644
lomiri::MediaHubService::PlayerImplementationPrivate::get_uri_for_album_artwork
QUrl get_uri_for_album_artwork(const QUrl &uri, const media::Track::MetaData &metadata)
Definition: player_implementation.cpp:239
lomiri::MediaHubService::PlayerImplementation::reconnect
void reconnect()
Definition: player_implementation.cpp:764
lomiri::MediaHubService::PlayerImplementation::PlayerImplementation
PlayerImplementation(const Configuration &configuration, QObject *parent=nullptr)
Definition: player_implementation.cpp:576
lomiri::MediaHubService::PlayerImplementationPrivate::q_ptr
media::PlayerImplementation * q_ptr
Definition: player_implementation.cpp:336
lomiri::MediaHubService::PlayerImplementation::canGoPrevious
bool canGoPrevious() const
Definition: player_implementation.cpp:621
lomiri::MediaHubService::Track::Id
QString Id
Definition: track.h:34
lomiri::MediaHubService::PlayerImplementationPrivate::open_first_track_from_tracklist
void open_first_track_from_tracklist(const media::Track::Id &id)
Definition: player_implementation.cpp:201
lomiri::MediaHubService::PlayerImplementationPrivate::m_engine
QScopedPointer< Engine > m_engine
Definition: player_implementation.cpp:314
lomiri::MediaHubService::PlayerImplementation::playbackRequested
void playbackRequested()
lomiri::MediaHubService::Engine::orientationChanged
void orientationChanged()
lomiri::MediaHubService::PlayerImplementationPrivate::doing_abandon
std::atomic< bool > doing_abandon
Definition: player_implementation.cpp:319
lomiri::MediaHubService::PlayerImplementation::errorOccurred
void errorOccurred(Player::Error error)
lomiri::MediaHubService::AVBackend::Backend
Backend
Definition: player.h:36
lomiri::MediaHubService::RecordingState::stopped
@ stopped
lomiri::MediaHubService::Engine::durationChanged
void durationChanged()
lomiri::MediaHubService::PlayerImplementation::aboutToFinish
void aboutToFinish()
lomiri::MediaHubService::PlayerImplementation::create_gl_texture_video_sink
void create_gl_texture_video_sink(std::uint32_t texture_id)
Definition: player_implementation.cpp:790
lomiri::MediaHubService::TrackListImplementation::endOfTrackList
void endOfTrackList()
lomiri::MediaHubService::PlayerImplementation::bufferingChanged
void bufferingChanged(int)
lomiri::MediaHubService::PlayerImplementationPrivate::onStateChanged
void onStateChanged(Engine::State state)
Definition: player_implementation.cpp:69
lomiri::MediaHubService::Engine::bufferingChanged
void bufferingChanged(int)
lomiri::MediaHubService::PlayerImplementation::Configuration
Definition: player_implementation.h:52
lomiri::MediaHubService::PlayerImplementation::maximumRate
double maximumRate() const
Definition: player_implementation.cpp:649
lomiri::MediaHubService::Player::Client
Definition: player.h:61
lomiri::MediaHubService::Player::AudioStreamRole
AudioStreamRole
Definition: player.h:113
lomiri::MediaHubService::PlayerImplementation::canPause
bool canPause() const
Definition: player_implementation.cpp:609
player_implementation.h
lomiri::MediaHubService::PlayerImplementation::next
void next()
Definition: player_implementation.cpp:823
lomiri::MediaHubService::power::StateController::displayOnAcquired
void displayOnAcquired()
gstreamer
Definition: bus.h:34
lomiri::MediaHubService::Player::PlayerKey
uint32_t PlayerKey
Definition: player.h:55
xesam.h
lomiri::MediaHubService::PlayerImplementationPrivate::is_multimedia_role
bool is_multimedia_role() const
Definition: player_implementation.cpp:305
lomiri::MediaHubService::AVBackend::get_backend_type
static Backend get_backend_type()
Returns the type of audio/video decoding/encoding backend being used.
Definition: backend.cpp:28
lomiri::MediaHubService::PlayerImplementation::~PlayerImplementation
~PlayerImplementation()
Definition: player_implementation.cpp:588
lomiri::MediaHubService::Engine::videoDimensionChanged
void videoDimensionChanged()
client_death_observer.h
lomiri::MediaHubService::Engine::playbackStatusChanged
void playbackStatusChanged()
lomiri::MediaHubService::ClientDeathObserver::Ptr
QSharedPointer< ClientDeathObserver > Ptr
Definition: client_death_observer.h:45
lomiri::MediaHubService::PlayerImplementation::trackList
QSharedPointer< TrackListImplementation > trackList()
Definition: player_implementation.cpp:778
lomiri::MediaHubService::Engine::seekedTo
void seekedTo(uint64_t offset)
lomiri::MediaHubService::PlayerImplementation::setLoopStatus
void setLoopStatus(Player::LoopStatus status)
Definition: player_implementation.cpp:654
lomiri::MediaHubService::PlayerImplementation::metadataForCurrentTrack
Track::MetaData metadataForCurrentTrack() const
Definition: player_implementation.cpp:722
lomiri::MediaHubService::PlayerImplementation::stop
void stop()
Definition: player_implementation.cpp:854
lomiri::MediaHubService::PlayerImplementationPrivate::m_metadataForCurrentTrack
Track::MetaData m_metadataForCurrentTrack
Definition: player_implementation.cpp:335
lomiri::MediaHubService::PlayerImplementation::volumeChanged
void volumeChanged()
lomiri::MediaHubService::PlayerImplementation::lifetime
Player::Lifetime lifetime() const
Definition: player_implementation.cpp:758
lomiri::MediaHubService::PlayerImplementation::setPlaybackRate
void setPlaybackRate(double rate)
Definition: player_implementation.cpp:633
lomiri::MediaHubService::PlayerImplementation::isVideoSourceChanged
void isVideoSourceChanged()
lomiri::MediaHubService::PlayerImplementation::Headers
Player::HeadersType Headers
Definition: player_implementation.h:49
lomiri::MediaHubService::TrackListImplementation::afterEmptyTrack
static const Track::Id & afterEmptyTrack()
Definition: track_list_implementation.cpp:775
MH_TRACE
#define MH_TRACE(...)
Definition: logging.h:37
lomiri::MediaHubService::Engine::stateChanged
void stateChanged()
lomiri::MediaHubService::PlayerImplementation::position
uint64_t position() const
Definition: player_implementation.cpp:728
lomiri::MediaHubService
Definition: context.h:28
lomiri::MediaHubService::PlayerImplementation::audioStreamRole
Player::AudioStreamRole audioStreamRole() const
Definition: player_implementation.cpp:746
lomiri::MediaHubService::PlayerImplementationPrivate::on_client_died
void on_client_died()
Definition: player_implementation.cpp:187
lomiri::MediaHubService::Engine::endOfStream
void endOfStream()
lomiri::MediaHubService::power::SystemState
SystemState
Definition: state_controller.h:37
lomiri::MediaHubService::Player::PlaybackStatus
PlaybackStatus
Definition: player.h:92
lomiri::MediaHubService::PlayerImplementationPrivate::m_client
Player::Client m_client
Definition: player_implementation.cpp:310
lomiri::MediaHubService::Engine::positionChanged
void positionChanged()
lomiri::MediaHubService::PlayerImplementation::open_uri
bool open_uri(const QUrl &uri)
Definition: player_implementation.cpp:796
lomiri::MediaHubService::Player::Lifetime
Lifetime
Definition: player.h:129
lomiri::MediaHubService::PlayerImplementation::canGoNext
bool canGoNext() const
Definition: player_implementation.cpp:627
lomiri::MediaHubService::PlayerImplementationPrivate::wakelock_clear_t
wakelock_clear_t
Definition: player_implementation.cpp:57
lomiri::MediaHubService::PlayerImplementation::playbackStatus
Player::PlaybackStatus playbackStatus() const
Definition: player_implementation.cpp:692
lomiri::MediaHubService::PlayerImplementation::orientation
Player::Orientation orientation() const
Definition: player_implementation.cpp:716
lomiri::MediaHubService::PlayerImplementation::backend
AVBackend::Backend backend() const
Definition: player_implementation.cpp:592
lomiri::MediaHubService::PlayerImplementation::previous
void previous()
Definition: player_implementation.cpp:829
lomiri::MediaHubService::PlayerImplementationPrivate::clear_wakelocks
void clear_wakelocks()
Definition: player_implementation.cpp:180
lomiri::MediaHubService::PlayerImplementation::seek_to
void seek_to(const std::chrono::microseconds &offset)
Definition: player_implementation.cpp:861
lomiri::MediaHubService::PlayerImplementationPrivate::request_power_state
void request_power_state()
Definition: player_implementation.cpp:131
MH_DEBUG
#define MH_DEBUG(...)
Definition: logging.h:38
lomiri::MediaHubService::Engine
Definition: engine.h:44
lomiri::MediaHubService::PlayerImplementationPrivate::m_abandonTimer
QTimer m_abandonTimer
Definition: player_implementation.cpp:333
MH_INFO
#define MH_INFO(...)
Definition: logging.h:39
lomiri::MediaHubService::PlayerImplementationPrivate::m_trackList
QSharedPointer< TrackListImplementation > m_trackList
Definition: player_implementation.cpp:315
lomiri::MediaHubService::PlayerImplementationPrivate::previous_state
Engine::State previous_state
Definition: player_implementation.cpp:318
track_list_implementation.h
lomiri::MediaHubService::Engine::isVideoSourceChanged
void isVideoSourceChanged()
lomiri::MediaHubService::PlayerImplementation::playbackRate
double playbackRate() const
Definition: player_implementation.cpp:639
engine.h
lomiri::MediaHubService::power::StateController::displayOnReleased
void displayOnReleased()
lomiri::MediaHubService::PlayerImplementationPrivate::power_state_controller
media::power::StateController::Ptr power_state_controller
Definition: player_implementation.cpp:312
lomiri::MediaHubService::Engine::isAudioSourceChanged
void isAudioSourceChanged()
lomiri::MediaHubService::PlayerImplementation::orientationChanged
void orientationChanged()
lomiri
Definition: dbus_utils.h:24
lomiri::MediaHubService::Engine::aboutToFinish
void aboutToFinish()
lomiri::MediaHubService::PlayerImplementation::setLifetime
void setLifetime(Player::Lifetime lifetime)
Definition: player_implementation.cpp:752
lomiri::MediaHubService::PlayerImplementationPrivate::clear_wakelock
void clear_wakelock(const wakelock_clear_t &wakelock)
Definition: player_implementation.cpp:153
lomiri::MediaHubService::PlayerImplementationPrivate::m_clientDeathObserver
ClientDeathObserver::Ptr m_clientDeathObserver
Definition: player_implementation.cpp:311
lomiri::MediaHubService::PlayerImplementation::pause
void pause()
Definition: player_implementation.cpp:847
lomiri::MediaHubService::PlayerImplementation::canPlay
bool canPlay() const
Definition: player_implementation.cpp:603
engine.h
lomiri::MediaHubService::PlayerImplementation::isVideoSource
bool isVideoSource() const
Definition: player_implementation.cpp:698
lomiri::MediaHubService::PlayerImplementation::setAudioStreamRole
void setAudioStreamRole(Player::AudioStreamRole role)
Definition: player_implementation.cpp:740
lomiri::MediaHubService::power::StateController::systemStateAcquired
void systemStateAcquired(SystemState state)
lomiri::MediaHubService::PlayerImplementation::play
void play()
Definition: player_implementation.cpp:835
MH_WARNING
#define MH_WARNING(...)
Definition: logging.h:40
lomiri::MediaHubService::PlayerImplementation::isAudioSource
bool isAudioSource() const
Definition: player_implementation.cpp:704
logging.h
lomiri::MediaHubService::Player::Orientation
Orientation
Definition: player.h:121
lomiri::MediaHubService::TrackListImplementation
Definition: track_list_implementation.h:74
lomiri::MediaHubService::PlayerImplementation::videoDimension
QSize videoDimension() const
Definition: player_implementation.cpp:710