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>& gstreamer::Engine::meta_data_extractor() const
404 {
405  return d->meta_data_extractor;
406 }
407 
408 const core::Property<media::Engine::State>& gstreamer::Engine::state() const
409 {
410  return d->state;
411 }
412 
413 bool gstreamer::Engine::open_resource_for_uri(const media::Track::UriType& uri, bool do_pipeline_reset)
414 {
415  d->playbin.set_uri(uri, core::ubuntu::media::Player::HeadersType{}, do_pipeline_reset);
416  return true;
417 }
418 
420 {
421  d->playbin.set_uri(uri, headers);
422  return true;
423 }
424 
425 void gstreamer::Engine::create_video_sink(uint32_t texture_id)
426 {
427  d->playbin.create_video_sink(texture_id);
428 }
429 
431 {
432  const auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);
433 
434  if (result)
435  {
436  d->state = media::Engine::State::playing;
437  cout << __PRETTY_FUNCTION__ << endl;
438  cout << "Engine: playing uri: " << d->playbin.uri() << endl;
439  d->playback_status_changed(media::Player::PlaybackStatus::playing);
440  }
441 
442  return result;
443 }
444 
446 {
447  // No need to wait, and we can immediately return.
448  if (d->state == media::Engine::State::stopped)
449  {
450  std::cerr << "Current player state is already stopped - no need to change state to stopped" << std::endl;
451  return true;
452  }
453 
454  const auto result = d->playbin.set_state_and_wait(GST_STATE_NULL);
455  if (result)
456  {
457  d->state = media::Engine::State::stopped;
458  cout << __PRETTY_FUNCTION__ << endl;
459  d->playback_status_changed(media::Player::PlaybackStatus::stopped);
460  }
461 
462  return result;
463 }
464 
466 {
467  const auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);
468 
469  if (result)
470  {
471  d->state = media::Engine::State::paused;
472  cout << __PRETTY_FUNCTION__ << endl;
473  d->playback_status_changed(media::Player::PlaybackStatus::paused);
474  }
475 
476  return result;
477 }
478 
479 bool gstreamer::Engine::seek_to(const std::chrono::microseconds& ts)
480 {
481  return d->playbin.seek(ts);
482 }
483 
484 const core::Property<bool>& gstreamer::Engine::is_video_source() const
485 {
486  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
487  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO)
488  d->is_video_source.set(true);
489  else
490  d->is_video_source.set(false);
491 
492  return d->is_video_source;
493 }
494 
495 const core::Property<bool>& gstreamer::Engine::is_audio_source() const
496 {
497  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
498  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO)
499  d->is_audio_source.set(true);
500  else
501  d->is_audio_source.set(false);
502 
503  return d->is_audio_source;
504 }
505 
506 const core::Property<uint64_t>& gstreamer::Engine::position() const
507 {
508  d->position.set(d->playbin.position());
509  return d->position;
510 }
511 
512 const core::Property<uint64_t>& gstreamer::Engine::duration() const
513 {
514  d->duration.set(d->playbin.duration());
515  return d->duration;
516 }
517 
518 const core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume() const
519 {
520  return d->volume;
521 }
522 
523 core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume()
524 {
525  return d->volume;
526 }
527 
528 const core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role() const
529 {
530  return d->audio_role;
531 }
532 
533 const core::Property<core::ubuntu::media::Player::Lifetime>& gstreamer::Engine::lifetime() const
534 {
535  return d->lifetime;
536 }
537 
538 core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role()
539 {
540  return d->audio_role;
541 }
542 
543 const core::Property<core::ubuntu::media::Player::Orientation>& gstreamer::Engine::orientation() const
544 {
545  return d->orientation;
546 }
547 
548 core::Property<core::ubuntu::media::Player::Lifetime>& gstreamer::Engine::lifetime()
549 {
550  return d->lifetime;
551 }
552 
553 const core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>>&
555 {
556  return d->track_meta_data;
557 }
558 
559 const core::Signal<void>& gstreamer::Engine::about_to_finish_signal() const
560 {
561  return d->about_to_finish;
562 }
563 
564 const core::Signal<uint64_t>& gstreamer::Engine::seeked_to_signal() const
565 {
566  return d->seeked_to;
567 }
568 
569 const core::Signal<void>& gstreamer::Engine::client_disconnected_signal() const
570 {
571  return d->client_disconnected;
572 }
573 
574 const core::Signal<void>& gstreamer::Engine::end_of_stream_signal() const
575 {
576  return d->end_of_stream;
577 }
578 
579 const core::Signal<media::Player::PlaybackStatus>& gstreamer::Engine::playback_status_changed_signal() const
580 {
581  return d->playback_status_changed;
582 }
583 
584 const core::Signal<core::ubuntu::media::video::Dimensions>& gstreamer::Engine::video_dimension_changed_signal() const
585 {
586  return d->video_dimension_changed;
587 }
588 
589 const core::Signal<core::ubuntu::media::Player::Error>& gstreamer::Engine::error_signal() const
590 {
591  return d->error;
592 }
593 
595 {
596  d->playbin.reset();
597 }
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:518
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:579
const core::Property< core::ubuntu::media::Player::AudioStreamRole > & audio_stream_role() const
Definition: engine.cpp:528
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:484
const core::Signal< void > & client_disconnected_signal() const
Definition: engine.cpp:569
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:408
const core::Property< core::ubuntu::media::Player::Lifetime > & lifetime() const
Definition: engine.cpp:533
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:479
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:564
struct gstreamer::Init init
void create_video_sink(uint32_t texture_id)
Definition: engine.cpp:425
const core::Property< std::tuple< core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData > > & track_meta_data() const
Definition: engine.cpp:554
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:495
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:589
const core::Property< uint64_t > & duration() const
Definition: engine.cpp:512
core::ScopedConnection on_volume_changed_connection
Definition: engine.cpp:374
const core::Signal< void > & about_to_finish_signal() const
Definition: engine.cpp:559
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:574
const core::Signal< core::ubuntu::media::video::Dimensions > & video_dimension_changed_signal() const
Definition: engine.cpp:584
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:403
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:543
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:506
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