Music Hub  ..
A session-wide music playback service
engine.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 <stdio.h>
21 #include <stdlib.h>
22 
23 #include "bus.h"
24 #include "engine.h"
25 #include "meta_data_extractor.h"
26 #include "playbin.h"
27 
28 #include <cassert>
29 
30 namespace media = core::ubuntu::media;
31 
32 using namespace std;
33 
34 namespace gstreamer
35 {
36 struct Init
37 {
38  Init()
39  {
40  gst_init(nullptr, nullptr);
41  }
42 
44  {
45  gst_deinit();
46  }
47 } init;
48 }
49 
51 {
53  {
54  if (state.new_state == GST_STATE_PLAYING)
55  return media::Player::PlaybackStatus::playing;
56  else if (state.new_state == GST_STATE_PAUSED)
57  return media::Player::PlaybackStatus::paused;
58  else if (state.new_state == GST_STATE_READY)
59  return media::Player::PlaybackStatus::ready;
60  else if (state.new_state == GST_STATE_NULL)
61  return media::Player::PlaybackStatus::null;
62  else
63  return media::Player::PlaybackStatus::stopped;
64  }
65 
66  void on_playbin_state_changed(const std::pair<gstreamer::Bus::Message::Detail::StateChanged,std::string>& p)
67  {
68  if (p.second == "playbin")
69  {
70  std::cout << "State changed on playbin: "
71  << gst_element_state_get_name(p.first.new_state) << std::endl;
72  const auto status = gst_state_to_player_status(p.first);
73  /*
74  * When state moves to "paused" the pipeline is already set. We check that we
75  * have streams to play.
76  */
77  if (status == media::Player::PlaybackStatus::paused &&
78  !playbin.can_play_streams()) {
79  std::cerr << "** Cannot play: some codecs are missing" << std::endl;
80  playbin.reset();
81  const media::Player::Error e = media::Player::Error::format_error;
82  error(e);
83  } else {
84  playback_status_changed(status);
85  }
86  }
87  }
88 
89  // Converts from a GStreamer GError to a media::Player:Error enum
91  {
92  media::Player::Error ret_error = media::Player::Error::no_error;
93 
94  if (g_strcmp0(g_quark_to_string(ewi.error->domain), "gst-core-error-quark") == 0)
95  {
96  switch (ewi.error->code)
97  {
98  case GST_CORE_ERROR_FAILED:
99  std::cerr << "** Encountered a GST_CORE_ERROR_FAILED" << std::endl;
100  ret_error = media::Player::Error::resource_error;
101  break;
102  case GST_CORE_ERROR_NEGOTIATION:
103  std::cerr << "** Encountered a GST_CORE_ERROR_NEGOTIATION" << std::endl;
104  ret_error = media::Player::Error::resource_error;
105  break;
106  case GST_CORE_ERROR_MISSING_PLUGIN:
107  std::cerr << "** Encountered a GST_CORE_ERROR_MISSING_PLUGIN" << std::endl;
108  ret_error = media::Player::Error::format_error;
109  break;
110  default:
111  std::cerr << "** Encountered an unhandled core error: '"
112  << ewi.debug << "' (code: " << ewi.error->code << ")" << std::endl;
113  ret_error = media::Player::Error::no_error;
114  break;
115  }
116  }
117  else if (g_strcmp0(g_quark_to_string(ewi.error->domain), "gst-resource-error-quark") == 0)
118  {
119  switch (ewi.error->code)
120  {
121  case GST_RESOURCE_ERROR_FAILED:
122  std::cerr << "** Encountered a GST_RESOURCE_ERROR_FAILED" << std::endl;
123  ret_error = media::Player::Error::resource_error;
124  break;
125  case GST_RESOURCE_ERROR_NOT_FOUND:
126  std::cerr << "** Encountered a GST_RESOURCE_ERROR_NOT_FOUND" << std::endl;
127  ret_error = media::Player::Error::resource_error;
128  break;
129  case GST_RESOURCE_ERROR_OPEN_READ:
130  std::cerr << "** Encountered a GST_RESOURCE_ERROR_OPEN_READ" << std::endl;
131  ret_error = media::Player::Error::resource_error;
132  break;
133  case GST_RESOURCE_ERROR_OPEN_WRITE:
134  std::cerr << "** Encountered a GST_RESOURCE_ERROR_OPEN_WRITE" << std::endl;
135  ret_error = media::Player::Error::resource_error;
136  break;
137  case GST_RESOURCE_ERROR_READ:
138  std::cerr << "** Encountered a GST_RESOURCE_ERROR_READ" << std::endl;
139  ret_error = media::Player::Error::resource_error;
140  break;
141  case GST_RESOURCE_ERROR_WRITE:
142  std::cerr << "** Encountered a GST_RESOURCE_ERROR_WRITE" << std::endl;
143  ret_error = media::Player::Error::resource_error;
144  break;
145  case GST_RESOURCE_ERROR_NOT_AUTHORIZED:
146  std::cerr << "** Encountered a GST_RESOURCE_ERROR_NOT_AUTHORIZED" << std::endl;
147  ret_error = media::Player::Error::access_denied_error;
148  break;
149  default:
150  std::cerr << "** Encountered an unhandled resource error: '"
151  << ewi.debug << "' (code: " << ewi.error->code << ")" << std::endl;
152  ret_error = media::Player::Error::no_error;
153  break;
154  }
155  }
156  else if (g_strcmp0(g_quark_to_string(ewi.error->domain), "gst-stream-error-quark") == 0)
157  {
158  switch (ewi.error->code)
159  {
160  case GST_STREAM_ERROR_FAILED:
161  std::cerr << "** Encountered a GST_STREAM_ERROR_FAILED" << std::endl;
162  ret_error = media::Player::Error::resource_error;
163  break;
164  case GST_STREAM_ERROR_CODEC_NOT_FOUND:
165  std::cerr << "** Encountered a GST_STREAM_ERROR_CODEC_NOT_FOUND" << std::endl;
166  // Missing codecs are handled later, when state switches to "paused"
167  ret_error = media::Player::Error::no_error;
168  break;
169  case GST_STREAM_ERROR_DECODE:
170  std::cerr << "** Encountered a GST_STREAM_ERROR_DECODE" << std::endl;
171  ret_error = media::Player::Error::format_error;
172  break;
173  default:
174  std::cerr << "** Encountered an unhandled stream error: '"
175  << ewi.debug << "' (code: " << ewi.error->code << ")" << std::endl;
176  ret_error = media::Player::Error::no_error;
177  break;
178  }
179  }
180 
181  if (ret_error != media::Player::Error::no_error) {
182  std::cerr << "Resetting playbin pipeline after unrecoverable error" << std::endl;
183  playbin.reset();
184  }
185  return ret_error;
186  }
187 
189  {
190  const media::Player::Error e = from_gst_errorwarning(ewi);
191  if (e != media::Player::Error::no_error)
192  error(e);
193  }
194 
196  {
197  const media::Player::Error e = from_gst_errorwarning(ewi);
198  if (e != media::Player::Error::no_error)
199  error(e);
200  }
201 
203  {
204  std::cerr << "Got a playbin info message (no action taken): " << ewi.debug << std::endl;
205  }
206 
208  {
209  media::Track::MetaData md;
211  track_meta_data.set(std::make_tuple(playbin.uri(), md));
212  }
213 
214  void on_volume_changed(const media::Engine::Volume& new_volume)
215  {
216  playbin.set_volume(new_volume.value);
217  }
218 
220  {
221  playbin.set_audio_stream_role(new_audio_role);
222  }
223 
225  {
226  // Update the local orientation Property, which should then update the Player
227  // orientation Property
228  orientation.set(o);
229  }
230 
232  {
233  playbin.set_lifetime(lifetime);
234  }
235 
237  {
238  state = Engine::State::ready;
239  about_to_finish();
240  }
241 
242  void on_seeked_to(uint64_t value)
243  {
244  seeked_to(value);
245  }
246 
248  {
249  client_disconnected();
250  }
251 
253  {
254  end_of_stream();
255  }
256 
258  {
259  video_dimension_changed(dimensions);
260  }
261 
263  : meta_data_extractor(new gstreamer::MetaDataExtractor()),
264  volume(media::Engine::Volume(1.)),
265  orientation(media::Player::Orientation::rotate0),
266  is_video_source(false),
267  is_audio_source(false),
268  about_to_finish_connection(
269  playbin.signals.about_to_finish.connect(
270  std::bind(
271  &Private::on_about_to_finish,
272  this))),
273  on_state_changed_connection(
274  playbin.signals.on_state_changed.connect(
275  std::bind(
276  &Private::on_playbin_state_changed,
277  this,
278  std::placeholders::_1))),
279  on_error_connection(
280  playbin.signals.on_error.connect(
281  std::bind(
282  &Private::on_playbin_error,
283  this,
284  std::placeholders::_1))),
285  on_warning_connection(
286  playbin.signals.on_warning.connect(
287  std::bind(
288  &Private::on_playbin_warning,
289  this,
290  std::placeholders::_1))),
291  on_info_connection(
292  playbin.signals.on_info.connect(
293  std::bind(
294  &Private::on_playbin_info,
295  this,
296  std::placeholders::_1))),
297  on_tag_available_connection(
298  playbin.signals.on_tag_available.connect(
299  std::bind(
300  &Private::on_tag_available,
301  this,
302  std::placeholders::_1))),
303  on_volume_changed_connection(
304  volume.changed().connect(
305  std::bind(
306  &Private::on_volume_changed,
307  this,
308  std::placeholders::_1))),
309  on_audio_stream_role_changed_connection(
310  audio_role.changed().connect(
311  std::bind(
312  &Private::on_audio_stream_role_changed,
313  this,
314  std::placeholders::_1))),
315  on_orientation_changed_connection(
316  playbin.signals.on_orientation_changed.connect(
317  std::bind(
318  &Private::on_orientation_changed,
319  this,
320  std::placeholders::_1))),
321  on_lifetime_changed_connection(
322  lifetime.changed().connect(
323  std::bind(
324  &Private::on_lifetime_changed,
325  this,
326  std::placeholders::_1))),
327  on_seeked_to_connection(
328  playbin.signals.on_seeked_to.connect(
329  std::bind(
330  &Private::on_seeked_to,
331  this,
332  std::placeholders::_1))),
333  client_disconnected_connection(
334  playbin.signals.client_disconnected.connect(
335  std::bind(
336  &Private::on_client_disconnected,
337  this))),
338  on_end_of_stream_connection(
339  playbin.signals.on_end_of_stream.connect(
340  std::bind(
341  &Private::on_end_of_stream,
342  this))),
343  on_video_dimension_changed_connection(
344  playbin.signals.on_video_dimensions_changed.connect(
345  std::bind(
346  &Private::on_video_dimension_changed,
347  this,
348  std::placeholders::_1)))
349  {
350  }
351 
352  // Ensure the playbin is the last item destroyed
353  // otherwise properties could try to access a dead playbin object
355 
356  std::shared_ptr<Engine::MetaDataExtractor> meta_data_extractor;
357  core::Property<Engine::State> state;
358  core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>> track_meta_data;
359  core::Property<uint64_t> position;
360  core::Property<uint64_t> duration;
361  core::Property<media::Engine::Volume> volume;
362  core::Property<media::Player::AudioStreamRole> audio_role;
363  core::Property<media::Player::Orientation> orientation;
364  core::Property<media::Player::Lifetime> lifetime;
365  core::Property<bool> is_video_source;
366  core::Property<bool> is_audio_source;
367 
368  core::ScopedConnection about_to_finish_connection;
369  core::ScopedConnection on_state_changed_connection;
370  core::ScopedConnection on_error_connection;
371  core::ScopedConnection on_warning_connection;
372  core::ScopedConnection on_info_connection;
373  core::ScopedConnection on_tag_available_connection;
374  core::ScopedConnection on_volume_changed_connection;
376  core::ScopedConnection on_orientation_changed_connection;
377  core::ScopedConnection on_lifetime_changed_connection;
378  core::ScopedConnection on_seeked_to_connection;
379  core::ScopedConnection client_disconnected_connection;
380  core::ScopedConnection on_end_of_stream_connection;
382 
383  core::Signal<void> about_to_finish;
384  core::Signal<uint64_t> seeked_to;
385  core::Signal<void> client_disconnected;
386  core::Signal<void> end_of_stream;
387  core::Signal<media::Player::PlaybackStatus> playback_status_changed;
388  core::Signal<core::ubuntu::media::video::Dimensions> video_dimension_changed;
389  core::Signal<media::Player::Error> error;
390 };
391 
393 {
394  d->state = media::Engine::State::no_media;
395 }
396 
398 {
399  stop();
400  d->state = media::Engine::State::no_media;
401 }
402 
403 const std::shared_ptr<media::Engine::MetaDataExtractor>&
405 {
406  return d->meta_data_extractor;
407 }
408 
409 const core::Property<media::Engine::State>& gstreamer::Engine::state() const
410 {
411  return d->state;
412 }
413 
415  bool do_pipeline_reset)
416 {
417  d->playbin.set_uri(uri, core::ubuntu::media::Player::HeadersType{}, do_pipeline_reset);
418  return true;
419 }
420 
423 {
424  d->playbin.set_uri(uri, headers);
425  return true;
426 }
427 
428 void gstreamer::Engine::create_video_sink(uint32_t texture_id)
429 {
430  d->playbin.create_video_sink(texture_id);
431 }
432 
434 {
435  const auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);
436 
437  if (result)
438  {
439  d->state = media::Engine::State::playing;
440  cout << __PRETTY_FUNCTION__ << endl;
441  cout << "Engine: playing uri: " << d->playbin.uri() << endl;
442  d->playback_status_changed(media::Player::PlaybackStatus::playing);
443  }
444 
445  return result;
446 }
447 
449 {
450  // No need to wait, and we can immediately return.
451  if (d->state == media::Engine::State::stopped)
452  {
453  std::cerr << "Current player state is already stopped - no need to change state to stopped" << std::endl;
454  return true;
455  }
456 
457  const auto result = d->playbin.set_state_and_wait(GST_STATE_NULL);
458  if (result)
459  {
460  d->state = media::Engine::State::stopped;
461  cout << __PRETTY_FUNCTION__ << endl;
462  d->playback_status_changed(media::Player::PlaybackStatus::stopped);
463  }
464 
465  return result;
466 }
467 
469 {
470  const auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);
471 
472  if (result)
473  {
474  d->state = media::Engine::State::paused;
475  cout << __PRETTY_FUNCTION__ << endl;
476  d->playback_status_changed(media::Player::PlaybackStatus::paused);
477  }
478 
479  return result;
480 }
481 
482 bool gstreamer::Engine::seek_to(const std::chrono::microseconds& ts)
483 {
484  return d->playbin.seek(ts);
485 }
486 
487 const core::Property<bool>& gstreamer::Engine::is_video_source() const
488 {
489  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
490  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO)
491  d->is_video_source.set(true);
492  else
493  d->is_video_source.set(false);
494 
495  return d->is_video_source;
496 }
497 
498 const core::Property<bool>& gstreamer::Engine::is_audio_source() const
499 {
500  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
501  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO)
502  d->is_audio_source.set(true);
503  else
504  d->is_audio_source.set(false);
505 
506  return d->is_audio_source;
507 }
508 
509 const core::Property<uint64_t>& gstreamer::Engine::position() const
510 {
511  d->position.set(d->playbin.position());
512  return d->position;
513 }
514 
515 const core::Property<uint64_t>& gstreamer::Engine::duration() const
516 {
517  d->duration.set(d->playbin.duration());
518  return d->duration;
519 }
520 
521 const core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume() const
522 {
523  return d->volume;
524 }
525 
526 core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume()
527 {
528  return d->volume;
529 }
530 
531 const core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role() const
532 {
533  return d->audio_role;
534 }
535 
536 const core::Property<core::ubuntu::media::Player::Lifetime>& gstreamer::Engine::lifetime() const
537 {
538  return d->lifetime;
539 }
540 
541 core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role()
542 {
543  return d->audio_role;
544 }
545 
546 const core::Property<core::ubuntu::media::Player::Orientation>& gstreamer::Engine::orientation() const
547 {
548  return d->orientation;
549 }
550 
551 core::Property<core::ubuntu::media::Player::Lifetime>& gstreamer::Engine::lifetime()
552 {
553  return d->lifetime;
554 }
555 
556 const core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>>&
558 {
559  return d->track_meta_data;
560 }
561 
562 const core::Signal<void>& gstreamer::Engine::about_to_finish_signal() const
563 {
564  return d->about_to_finish;
565 }
566 
567 const core::Signal<uint64_t>& gstreamer::Engine::seeked_to_signal() const
568 {
569  return d->seeked_to;
570 }
571 
572 const core::Signal<void>& gstreamer::Engine::client_disconnected_signal() const
573 {
574  return d->client_disconnected;
575 }
576 
577 const core::Signal<void>& gstreamer::Engine::end_of_stream_signal() const
578 {
579  return d->end_of_stream;
580 }
581 
582 const core::Signal<media::Player::PlaybackStatus>& gstreamer::Engine::playback_status_changed_signal() const
583 {
584  return d->playback_status_changed;
585 }
586 
587 const core::Signal<core::ubuntu::media::video::Dimensions>& gstreamer::Engine::video_dimension_changed_signal() const
588 {
589  return d->video_dimension_changed;
590 }
591 
592 const core::Signal<core::ubuntu::media::Player::Error>& gstreamer::Engine::error_signal() const
593 {
594  return d->error;
595 }
596 
598 {
599  d->playbin.reset();
600 }
void on_tag_available(const gstreamer::Bus::Message::Detail::Tag &tag)
Definition: engine.cpp:207
core::ScopedConnection on_state_changed_connection
Definition: engine.cpp:369
core::ScopedConnection on_video_dimension_changed_connection
Definition: engine.cpp:381
core::Signal< core::ubuntu::media::video::Dimensions > video_dimension_changed
Definition: engine.cpp:388
const core::Property< core::ubuntu::media::Engine::Volume > & volume() const
Definition: engine.cpp:521
core::Property< bool > is_video_source
Definition: engine.cpp:365
const core::Signal< core::ubuntu::media::Player::PlaybackStatus > & playback_status_changed_signal() const
Definition: engine.cpp:582
const core::Property< core::ubuntu::media::Player::AudioStreamRole > & audio_stream_role() const
Definition: engine.cpp:531
std::tuple< Height, Width > Dimensions
Height and Width of a video.
Definition: dimensions.h:139
const core::Property< bool > & is_video_source() const
Definition: engine.cpp:487
const core::Signal< void > & client_disconnected_signal() const
Definition: engine.cpp:572
core::ScopedConnection on_info_connection
Definition: engine.cpp:372
core::Signal< void > end_of_stream
Definition: engine.cpp:386
Definition: bus.h:33
core::ScopedConnection on_lifetime_changed_connection
Definition: engine.cpp:377
void on_seeked_to(uint64_t value)
Definition: engine.cpp:242
void on_playbin_warning(const gstreamer::Bus::Message::Detail::ErrorWarningInfo &ewi)
Definition: engine.cpp:195
STL namespace.
const core::Property< State > & state() const
Definition: engine.cpp:409
const core::Property< core::ubuntu::media::Player::Lifetime > & lifetime() const
Definition: engine.cpp:536
core::ScopedConnection on_seeked_to_connection
Definition: engine.cpp:378
core::ScopedConnection on_end_of_stream_connection
Definition: engine.cpp:380
void on_orientation_changed(const media::Player::Orientation &o)
Definition: engine.cpp:224
core::Signal< media::Player::Error > error
Definition: engine.cpp:389
std::map< std::string, std::string > HeadersType
Definition: player.h:49
gstreamer::Playbin playbin
Definition: engine.cpp:354
bool seek_to(const std::chrono::microseconds &ts)
Definition: engine.cpp:482
core::ScopedConnection on_warning_connection
Definition: engine.cpp:371
bool open_resource_for_uri(const core::ubuntu::media::Track::UriType &uri, bool do_pipeline_reset)
const core::Signal< uint64_t > & seeked_to_signal() const
Definition: engine.cpp:567
struct gstreamer::Init init
void create_video_sink(uint32_t texture_id)
Definition: engine.cpp:428
const core::Property< std::tuple< core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData > > & track_meta_data() const
Definition: engine.cpp:557
core::ScopedConnection client_disconnected_connection
Definition: engine.cpp:379
void on_playbin_error(const gstreamer::Bus::Message::Detail::ErrorWarningInfo &ewi)
Definition: engine.cpp:188
media::Player::Error from_gst_errorwarning(const gstreamer::Bus::Message::Detail::ErrorWarningInfo &ewi)
Definition: engine.cpp:90
const core::Property< bool > & is_audio_source() const
Definition: engine.cpp:498
void on_volume_changed(const media::Engine::Volume &new_volume)
Definition: engine.cpp:214
const core::Signal< core::ubuntu::media::Player::Error > & error_signal() const
Definition: engine.cpp:592
const core::Property< uint64_t > & duration() const
Definition: engine.cpp:515
core::ScopedConnection on_volume_changed_connection
Definition: engine.cpp:374
const core::Signal< void > & about_to_finish_signal() const
Definition: engine.cpp:562
core::Property< media::Player::Orientation > orientation
Definition: engine.cpp:363
core::Property< media::Player::AudioStreamRole > audio_role
Definition: engine.cpp:362
const core::Signal< void > & end_of_stream_signal() const
Definition: engine.cpp:577
const core::Signal< core::ubuntu::media::video::Dimensions > & video_dimension_changed_signal() const
Definition: engine.cpp:587
core::Signal< void > client_disconnected
Definition: engine.cpp:385
core::Signal< uint64_t > seeked_to
Definition: engine.cpp:384
void on_playbin_info(const gstreamer::Bus::Message::Detail::ErrorWarningInfo &ewi)
Definition: engine.cpp:202
core::ScopedConnection on_error_connection
Definition: engine.cpp:370
core::Property< media::Player::Lifetime > lifetime
Definition: engine.cpp:364
std::shared_ptr< Engine::MetaDataExtractor > meta_data_extractor
Definition: engine.cpp:356
static void on_tag_available(const gstreamer::Bus::Message::Detail::Tag &tag, core::ubuntu::media::Track::MetaData &md)
core::ScopedConnection on_tag_available_connection
Definition: engine.cpp:373
const std::shared_ptr< MetaDataExtractor > & meta_data_extractor() const
Definition: engine.cpp:404
core::Property< media::Engine::Volume > volume
Definition: engine.cpp:361
void on_playbin_state_changed(const std::pair< gstreamer::Bus::Message::Detail::StateChanged, std::string > &p)
Definition: engine.cpp:66
media::Player::PlaybackStatus gst_state_to_player_status(const gstreamer::Bus::Message::Detail::StateChanged &state)
Definition: engine.cpp:52
std::string UriType
Definition: track.h:40
core::ScopedConnection about_to_finish_connection
Definition: engine.cpp:368
core::Property< Engine::State > state
Definition: engine.cpp:357
const core::Property< core::ubuntu::media::Player::Orientation > & orientation() const
Definition: engine.cpp:546
core::Property< uint64_t > position
Definition: engine.cpp:359
core::Property< std::tuple< media::Track::UriType, media::Track::MetaData > > track_meta_data
Definition: engine.cpp:358
core::Signal< void > about_to_finish
Definition: engine.cpp:383
core::Signal< media::Player::PlaybackStatus > playback_status_changed
Definition: engine.cpp:387
const core::Property< uint64_t > & position() const
Definition: engine.cpp:509
core::ScopedConnection on_orientation_changed_connection
Definition: engine.cpp:376
void on_audio_stream_role_changed(const media::Player::AudioStreamRole &new_audio_role)
Definition: engine.cpp:219
void on_video_dimension_changed(const media::video::Dimensions &dimensions)
Definition: engine.cpp:257
void on_lifetime_changed(const media::Player::Lifetime &lifetime)
Definition: engine.cpp:231
core::Property< bool > is_audio_source
Definition: engine.cpp:366
core::Property< uint64_t > duration
Definition: engine.cpp:360
core::ScopedConnection on_audio_stream_role_changed_connection
Definition: engine.cpp:375