36 #define UNUSED __attribute__((unused))
43 template<
typename Parent>
45 public std::enable_shared_from_this<Private>
49 WAKELOCK_CLEAR_INACTIVE,
50 WAKELOCK_CLEAR_DISPLAY,
51 WAKELOCK_CLEAR_SYSTEM,
52 WAKELOCK_CLEAR_INVALID
58 display_state_lock(config.power_state_controller->display_state_lock()),
59 system_state_lock(config.power_state_controller->system_state_lock()),
61 track_list(
std::make_shared<TrackListImplementation>(
63 config.parent.service->add_object_for_path(
64 dbus::types::ObjectPath(config.parent.session->path().as_string() +
"/TrackList")),
65 engine->meta_data_extractor(),
66 config.parent.request_context_resolver,
67 config.parent.request_authenticator)),
68 system_wakelock_count(0),
69 display_wakelock_count(0),
70 previous_state(Engine::State::stopped),
71 engine_state_change_connection(engine->state().changed().connect(make_state_change_handler())),
72 engine_playback_status_change_connection(engine->playback_status_changed_signal().connect(make_playback_status_change_handler())),
78 std::cout <<
"Acquired new display state: " << state << std::endl;
83 std::cout <<
"Released display state: " << state << std::endl;
88 std::cout <<
"Acquired new system state: " << state << std::endl;
93 std::cout <<
"Released system state: " << state << std::endl;
106 engine_state_change_connection.disconnect();
111 engine_playback_status_change_connection.disconnect();
121 return [
this](
const Engine::State& state)
123 std::cout <<
"Setting state for parent: " << parent << std::endl;
126 case Engine::State::ready:
129 if (previous_state == Engine::State::playing)
131 timeout(4000,
true, make_clear_wakelock_functor());
135 case Engine::State::playing:
139 parent->meta_data_for_current_track().set(std::get<1>(engine->track_meta_data().get()));
142 std::cout <<
"Requesting power state" << std::endl;
143 request_power_state();
146 case Engine::State::stopped:
149 if (previous_state == Engine::State::playing)
151 timeout(4000,
true, make_clear_wakelock_functor());
155 case Engine::State::paused:
158 if (previous_state == Engine::State::playing)
160 timeout(4000,
true, make_clear_wakelock_functor());
169 previous_state = state;
177 std::cout <<
"Emiting playback_status_changed signal: " << status << std::endl;
178 parent->emit_playback_status_changed(status);
184 std::cout << __PRETTY_FUNCTION__ << std::endl;
187 if (parent->is_video_source())
189 if (++display_wakelock_count == 1)
191 std::cout <<
"Requesting new display wakelock." << std::endl;
192 display_state_lock->request_acquire(media::power::DisplayState::on);
193 std::cout <<
"Requested new display wakelock." << std::endl;
198 if (++system_wakelock_count == 1)
200 std::cout <<
"Requesting new system wakelock." << std::endl;
201 system_state_lock->request_acquire(media::power::SystemState::active);
202 std::cout <<
"Requested new system wakelock." << std::endl;
206 catch(
const std::exception& e)
208 std::cerr <<
"Warning: failed to request power state: ";
209 std::cerr << e.what() << std::endl;
215 cout << __PRETTY_FUNCTION__ << endl;
220 case wakelock_clear_t::WAKELOCK_CLEAR_INACTIVE:
222 case wakelock_clear_t::WAKELOCK_CLEAR_SYSTEM:
224 if (--system_wakelock_count == 0)
226 std::cout <<
"Clearing system wakelock." << std::endl;
227 system_state_lock->request_release(media::power::SystemState::active);
230 case wakelock_clear_t::WAKELOCK_CLEAR_DISPLAY:
232 if (--display_wakelock_count == 0)
234 std::cout <<
"Clearing display wakelock." << std::endl;
235 display_state_lock->request_release(media::power::DisplayState::on);
238 case wakelock_clear_t::WAKELOCK_CLEAR_INVALID:
240 cerr <<
"Can't clear invalid wakelock type" << endl;
243 catch(
const std::exception& e)
245 std::cerr <<
"Warning: failed to clear power state: ";
246 std::cerr << e.what() << std::endl;
252 return (parent->is_video_source()) ?
253 wakelock_clear_t::WAKELOCK_CLEAR_DISPLAY : wakelock_clear_t::WAKELOCK_CLEAR_SYSTEM;
259 if (system_wakelock_count.load() > 0)
261 system_wakelock_count = 1;
262 clear_wakelock(wakelock_clear_t::WAKELOCK_CLEAR_SYSTEM);
264 if (display_wakelock_count.load() > 0)
266 display_wakelock_count = 1;
267 clear_wakelock(wakelock_clear_t::WAKELOCK_CLEAR_DISPLAY);
277 std::weak_ptr<Private> weak_self{this->shared_from_this()};
278 auto wakelock_type = current_wakelock_type();
279 return [weak_self, wakelock_type] {
280 if (
auto self = weak_self.lock())
281 self->clear_wakelock(wakelock_type);
310 template<
typename Parent>
313 d{std::make_shared<Private>(
this, config)}
316 Parent::can_play().set(
true);
317 Parent::can_pause().set(
true);
318 Parent::can_seek().set(
true);
319 Parent::can_go_previous().set(
true);
320 Parent::can_go_next().set(
true);
321 Parent::is_video_source().set(
false);
322 Parent::is_audio_source().set(
false);
323 Parent::shuffle().set(
false);
324 Parent::playback_rate().set(1.f);
325 Parent::playback_status().set(Player::PlaybackStatus::null);
326 Parent::loop_status().set(Player::LoopStatus::none);
327 Parent::position().set(0);
328 Parent::duration().set(0);
329 Parent::audio_stream_role().set(Player::AudioStreamRole::multimedia);
330 d->engine->audio_stream_role().set(Player::AudioStreamRole::multimedia);
331 Parent::orientation().set(Player::Orientation::rotate0);
332 Parent::lifetime().set(Player::Lifetime::normal);
333 d->engine->lifetime().set(Player::Lifetime::normal);
337 std::function<uint64_t()> position_getter = [
this]()
339 return d->engine->position().get();
341 Parent::position().install(position_getter);
345 std::function<uint64_t()> duration_getter = [
this]()
347 return d->engine->duration().get();
349 Parent::duration().install(duration_getter);
351 std::function<bool()> video_type_getter = [
this]()
353 return d->engine->is_video_source().get();
355 Parent::is_video_source().install(video_type_getter);
357 std::function<bool()> audio_type_getter = [
this]()
359 return d->engine->is_audio_source().get();
361 Parent::is_audio_source().install(audio_type_getter);
366 d->track_list->on_loop_status_changed(loop_status);
370 Parent::shuffle().changed().connect([
this](
bool shuffle)
372 d->track_list->on_shuffle_changed(shuffle);
379 d->engine->audio_stream_role().set(new_role);
386 Parent::orientation().set(o);
391 d->engine->lifetime().set(lifetime);
394 d->engine->about_to_finish_signal().connect([
this]()
396 if (d->doing_abandon)
399 Parent::about_to_finish()();
402 d->doing_go_to_track.lock();
407 const Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next());
408 if (prev_track_id != d->track_list->current() && !uri.empty())
410 std::cout <<
"Setting next track on playbin: " << uri << std::endl;
411 static const bool do_pipeline_reset =
false;
412 d->engine->open_resource_for_uri(uri, do_pipeline_reset);
415 d->doing_go_to_track.unlock();
418 d->engine->client_disconnected_signal().connect([
this]()
422 d->clear_wakelocks();
423 d->track_list->reset();
425 d->on_client_disconnected();
428 d->engine->seeked_to_signal().connect([
this](uint64_t value)
430 Parent::seeked_to()(value);
433 d->engine->end_of_stream_signal().connect([
this]()
435 Parent::end_of_stream()();
440 Parent::video_dimension_changed()(dimensions);
443 d->engine->error_signal().connect([
this](
const Player::Error& e)
448 d->
track_list->on_go_to_track().connect([
this](std::pair<const media::Track::Id, bool> p)
453 d->doing_go_to_track.lock();
456 const bool toggle_player_state = p.second;
458 if (toggle_player_state)
461 const Track::UriType uri = d->track_list->query_uri_for_track(
id);
464 std::cout <<
"Setting next track on playbin (on_go_to_track signal): " << uri << std::endl;
465 std::cout <<
"\twith a Track::Id: " <<
id << std::endl;
466 static const bool do_pipeline_reset =
true;
467 d->engine->open_resource_for_uri(uri, do_pipeline_reset);
470 if (toggle_player_state)
473 d->doing_go_to_track.unlock();
478 std::weak_ptr<Private> wp{d};
480 d->config.client_death_observer->register_for_death_notifications_with_key(config.key);
483 if (
auto sp = wp.lock())
485 if (sp->doing_abandon)
488 if (died != sp->config.key)
491 static const std::chrono::milliseconds timeout{1000};
494 if (
auto sp = wp.lock())
495 sp->on_client_died();
501 template<
typename Parent>
507 std::function<uint64_t()> position_getter = [
this]()
509 return static_cast<uint64_t
>(0);
511 Parent::position().install(position_getter);
513 std::function<uint64_t()> duration_getter = [
this]()
515 return static_cast<uint64_t
>(0);
517 Parent::duration().install(duration_getter);
519 std::function<bool()> video_type_getter = [
this]()
523 Parent::is_video_source().install(video_type_getter);
525 std::function<bool()> audio_type_getter = [
this]()
529 Parent::is_audio_source().install(audio_type_getter);
532 template<
typename Parent>
536 return std::string{};
539 template<
typename Parent>
542 d->config.client_death_observer->register_for_death_notifications_with_key(d->config.key);
545 template<
typename Parent>
549 d->doing_abandon =
true;
553 template<
typename Parent>
556 return d->track_list;
560 template<
typename Parent>
563 return d->config.key;
566 template<
typename Parent>
569 d->engine->create_video_sink(texture_id);
570 return media::video::Sink::Ptr{};
573 template<
typename Parent>
576 d->track_list->reset();
582 template<
typename Parent>
585 return d->engine->open_resource_for_uri(uri, headers);
588 template<
typename Parent>
593 template<
typename Parent>
598 template<
typename Parent>
601 if (d->track_list !=
nullptr && d->track_list->tracks()->size() > 0 && d->engine->state() == media::Engine::State::no_media)
605 std::cout <<
"No media loaded yet, calling open_uri on first track in track_list" << std::endl;
606 static const bool do_pipeline_reset =
true;
607 d->engine->open_resource_for_uri(d->track_list->query_uri_for_track(d->track_list->current()), do_pipeline_reset);
608 std::cout << *d->track_list << endl;
614 template<
typename Parent>
620 template<
typename Parent>
623 std::cout << __PRETTY_FUNCTION__ << std::endl;
627 template<
typename Parent>
630 d->engine->seek_to(ms);
633 template<
typename Parent>
636 return d->on_client_disconnected;
639 template<
typename Parent>
642 Parent::playback_status_changed()(status);