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