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);
292 const Track::UriType uri = track_list->query_uri_for_track(
id);
297 std::cout <<
"Calling d->engine->open_resource_for_uri() for first track added only: " << uri << std::endl;
298 std::cout <<
"\twith a Track::Id: " <<
id << std::endl;
299 static const bool do_pipeline_reset =
false;
300 engine->open_resource_for_uri(uri, do_pipeline_reset);
324 template<
typename Parent>
327 d{std::make_shared<Private>(
this, config)}
330 Parent::can_play().set(
true);
331 Parent::can_pause().set(
true);
332 Parent::can_seek().set(
true);
333 Parent::can_go_previous().set(
false);
334 Parent::can_go_next().set(
false);
335 Parent::is_video_source().set(
false);
336 Parent::is_audio_source().set(
false);
337 Parent::shuffle().set(
false);
338 Parent::playback_rate().set(1.f);
339 Parent::playback_status().set(Player::PlaybackStatus::null);
340 Parent::loop_status().set(Player::LoopStatus::none);
341 Parent::position().set(0);
342 Parent::duration().set(0);
343 Parent::audio_stream_role().set(Player::AudioStreamRole::multimedia);
344 d->engine->audio_stream_role().set(Player::AudioStreamRole::multimedia);
345 Parent::orientation().set(Player::Orientation::rotate0);
346 Parent::lifetime().set(Player::Lifetime::normal);
347 d->engine->lifetime().set(Player::Lifetime::normal);
351 std::function<uint64_t()> position_getter = [
this]()
353 return d->engine->position().get();
355 Parent::position().install(position_getter);
359 std::function<uint64_t()> duration_getter = [
this]()
361 return d->engine->duration().get();
363 Parent::duration().install(duration_getter);
365 std::function<bool()> video_type_getter = [
this]()
367 return d->engine->is_video_source().get();
369 Parent::is_video_source().install(video_type_getter);
371 std::function<bool()> audio_type_getter = [
this]()
373 return d->engine->is_audio_source().get();
375 Parent::is_audio_source().install(audio_type_getter);
377 std::function<bool()> can_go_next_getter = [
this]()
381 Parent::can_go_next().install(can_go_next_getter);
383 std::function<bool()> can_go_previous_getter = [
this]()
385 return d->track_list->has_previous();
387 Parent::can_go_previous().install(can_go_previous_getter);
392 std::cout <<
"LoopStatus: " << loop_status << std::endl;
393 d->track_list->on_loop_status_changed(loop_status);
397 Parent::shuffle().changed().connect([
this](
bool shuffle)
399 d->track_list->on_shuffle_changed(shuffle);
406 d->engine->audio_stream_role().set(new_role);
413 Parent::orientation().set(o);
418 d->engine->lifetime().set(lifetime);
421 d->engine->about_to_finish_signal().connect([
this]()
423 if (d->doing_abandon)
429 d->doing_go_to_track.lock();
431 Parent::about_to_finish()();
436 const Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next());
437 if (prev_track_id != d->track_list->current() && !uri.empty())
439 std::cout <<
"Advancing to next track on playbin: " << uri << std::endl;
440 static const bool do_pipeline_reset =
false;
441 d->engine->open_resource_for_uri(uri, do_pipeline_reset);
444 d->doing_go_to_track.unlock();
447 d->engine->client_disconnected_signal().connect([
this]()
451 d->clear_wakelocks();
452 d->track_list->reset();
454 d->on_client_disconnected();
457 d->engine->seeked_to_signal().connect([
this](uint64_t value)
459 Parent::seeked_to()(value);
462 d->engine->end_of_stream_signal().connect([
this]()
464 Parent::end_of_stream()();
469 Parent::video_dimension_changed()(dimensions);
472 d->engine->error_signal().connect([
this](
const Player::Error& e)
477 d->track_list->on_end_of_tracklist().connect([
this]()
482 std::cout <<
"End of tracklist reached, stopping playback" << std::endl;
488 d->track_list->on_go_to_track().connect([
this](std::pair<const media::Track::Id, bool> p)
491 const bool locked = d->doing_go_to_track.try_lock();
498 const bool toggle_player_state = p.second;
500 if (toggle_player_state)
503 const Track::UriType uri = d->track_list->query_uri_for_track(
id);
506 std::cout <<
"Setting next track on playbin (on_go_to_track signal): " << uri << std::endl;
507 std::cout <<
"\twith a Track::Id: " <<
id << std::endl;
508 static const bool do_pipeline_reset =
true;
509 d->engine->open_resource_for_uri(uri, do_pipeline_reset);
512 if (toggle_player_state)
515 d->doing_go_to_track.unlock();
520 std::cout <<
"** Track was added, handling in PlayerImplementation" << std::endl;
521 if (d->track_list->tracks()->size() == 1)
522 d->open_first_track_from_tracklist(
id);
526 std::weak_ptr<Private> wp{d};
528 d->config.client_death_observer->register_for_death_notifications_with_key(config.key);
531 if (
auto sp = wp.lock())
533 if (sp->doing_abandon)
536 if (died != sp->config.key)
539 static const std::chrono::milliseconds timeout{1000};
542 if (
auto sp = wp.lock())
543 sp->on_client_died();
549 template<
typename Parent>
555 std::function<uint64_t()> position_getter = [
this]()
557 return static_cast<uint64_t
>(0);
559 Parent::position().install(position_getter);
561 std::function<uint64_t()> duration_getter = [
this]()
563 return static_cast<uint64_t
>(0);
565 Parent::duration().install(duration_getter);
567 std::function<bool()> video_type_getter = [
this]()
571 Parent::is_video_source().install(video_type_getter);
573 std::function<bool()> audio_type_getter = [
this]()
577 Parent::is_audio_source().install(audio_type_getter);
580 template<
typename Parent>
584 return std::string{};
587 template<
typename Parent>
590 d->config.client_death_observer->register_for_death_notifications_with_key(d->config.key);
593 template<
typename Parent>
597 d->doing_abandon =
true;
601 template<
typename Parent>
604 return d->track_list;
608 template<
typename Parent>
611 return d->config.key;
614 template<
typename Parent>
617 d->engine->create_video_sink(texture_id);
618 return media::video::Sink::Ptr{};
621 template<
typename Parent>
624 d->track_list->reset();
625 const bool ret = d->engine->open_resource_for_uri(uri,
false);
627 static const bool make_current =
false;
632 template<
typename Parent>
635 return d->engine->open_resource_for_uri(uri, headers);
638 template<
typename Parent>
641 d->track_list->next();
644 template<
typename Parent>
647 d->track_list->previous();
650 template<
typename Parent>
656 template<
typename Parent>
662 template<
typename Parent>
665 std::cout << __PRETTY_FUNCTION__ << std::endl;
669 template<
typename Parent>
672 d->engine->seek_to(ms);
675 template<
typename Parent>
678 return d->on_client_disconnected;
681 template<
typename Parent>
684 Parent::playback_status_changed()(status);