36 #include <core/dbus/object.h> 37 #include <core/dbus/property.h> 38 #include <core/dbus/types/object_path.h> 39 #include <core/dbus/types/variant.h> 40 #include <core/dbus/types/stl/map.h> 41 #include <core/dbus/types/stl/vector.h> 55 const apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver,
56 const media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator)
60 request_context_resolver(request_context_resolver),
61 request_authenticator(request_authenticator),
62 uri_check(
std::make_shared<UriCheck>()),
64 current_track(skeleton.properties.tracks->get().begin()),
65 empty_iterator(skeleton.properties.tracks->get().begin()),
66 loop_status(media::Player::LoopStatus::none),
71 skeleton.signals.track_added,
72 skeleton.signals.tracks_added,
73 skeleton.signals.track_moved,
74 skeleton.signals.track_removed,
75 skeleton.signals.track_changed,
76 skeleton.signals.track_list_reset,
77 skeleton.signals.tracklist_replaced
85 msg->reader() >> track;
87 const auto meta_data =
impl->query_meta_data_for_track(track);
89 const auto reply = dbus::Message::make_method_return(msg);
90 reply->writer() << *meta_data;
97 msg->reader() >> track;
99 const auto uri =
impl->query_uri_for_track(track);
101 const auto reply = dbus::Message::make_method_return(msg);
102 reply->writer() << uri;
109 request_context_resolver->resolve_context_for_dbus_name_async
110 (msg->sender(), [
this, msg](
const media::apparmor::ubuntu::Context& context)
115 msg->reader() >> uri >> after >> make_current;
118 const auto result = request_authenticator->authenticate_open_uri_request(context, uri);
119 auto reply = dbus::Message::make_method_return(msg);
122 const bool valid_uri = !uri_check->is_local_file() or
123 (uri_check->is_local_file() and uri_check->file_exists());
126 const std::string err_str = {
"Warning: Not adding track " + uri +
127 " to TrackList because it can't be found."};
129 reply = dbus::Message::make_error(
137 if (std::get<0>(result))
139 impl->add_track_with_uri_at(uri, after, make_current);
143 const std::string err_str = {
"Warning: Not adding track " + uri +
144 " to TrackList because of inadequate client apparmor permissions."};
146 reply = dbus::Message::make_error(
160 request_context_resolver->resolve_context_for_dbus_name_async
161 (msg->sender(), [
this, msg](
const media::apparmor::ubuntu::Context& context)
165 msg->reader() >> uris >> after;
167 bool valid_uri =
false;
168 media::apparmor::ubuntu::RequestAuthenticator::Result result;
169 std::string uri_err_str, err_str;
170 core::dbus::Message::Ptr reply;
171 for (
const auto uri : uris)
174 valid_uri = !uri_check->is_local_file() or
175 (uri_check->is_local_file() and uri_check->file_exists());
178 uri_err_str = {
"Warning: Not adding track " + uri +
179 " to TrackList because it can't be found."};
181 reply = dbus::Message::make_error(
188 result = request_authenticator->authenticate_open_uri_request(context, uri);
189 if (not std::get<0>(result))
191 err_str = {
"Warning: Not adding track " + uri +
192 " to TrackList because of inadequate client apparmor permissions."};
198 if (std::get<0>(result))
200 reply = dbus::Message::make_method_return(msg);
201 impl->add_tracks_with_uri_at(uris, after);
206 reply = dbus::Message::make_error(
220 msg->reader() >>
id >> to;
222 core::dbus::Message::Ptr reply;
224 const bool ret =
impl->move_track(
id, to);
227 const std::string err_str = {
"Error: Not moving track " +
id +
228 " to destination " + to};
230 reply = dbus::Message::make_error(
237 reply = dbus::Message::make_method_return(msg);
239 }
catch(media::TrackList::Errors::FailedToMoveTrack& e) {
240 reply = dbus::Message::make_error(
244 }
catch(media::TrackList::Errors::FailedToFindMoveTrackSource& e) {
245 reply = dbus::Message::make_error(
249 }
catch(media::TrackList::Errors::FailedToFindMoveTrackDest& e) {
250 reply = dbus::Message::make_error(
262 msg->reader() >> track;
264 auto id_it = find(
impl->tracks().get().begin(),
impl->tracks().get().end(), track);
265 if (id_it ==
impl->tracks().get().end()) {
266 stringstream err_str;
267 err_str <<
"Track " << track <<
" not found in track list";
269 auto reply = dbus::Message::make_error(
278 bool deleting_current =
false;
280 if (id_it ==
impl->current_iterator())
283 deleting_current =
true;
285 if (current_track != empty_iterator)
289 if (current_track ==
impl->tracks().get().end()
290 && loop_status == media::Player::LoopStatus::playlist)
294 current_track =
impl->tracks().get().begin();
297 if (current_track ==
impl->tracks().get().end())
299 current_track = empty_iterator;
301 impl->emit_on_end_of_tracklist();
305 next = *current_track;
309 else if (current_track != empty_iterator)
311 next = *current_track;
313 id_after_remove = next;
316 impl->remove_track(track);
318 if ((not next.empty()) and deleting_current)
321 auto reply = dbus::Message::make_method_return(msg);
328 msg->reader() >> track;
330 current_track = std::find(skeleton.properties.tracks->get().begin(), skeleton.properties.tracks->get().end(), track);
333 auto reply = dbus::Message::make_method_return(msg);
341 auto reply = dbus::Message::make_method_return(msg);
361 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackAdded, mpris::TrackList::Signals::TrackAdded::ArgumentType>
DBusTrackAddedSignal;
362 typedef core::dbus::Signal<mpris::TrackList::Signals::TracksAdded, mpris::TrackList::Signals::TracksAdded::ArgumentType>
DBusTracksAddedSignal;
363 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackMoved, mpris::TrackList::Signals::TrackMoved::ArgumentType>
DBusTrackMovedSignal;
364 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackRemoved, mpris::TrackList::Signals::TrackRemoved::ArgumentType>
DBusTrackRemovedSignal;
365 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackChanged, mpris::TrackList::Signals::TrackChanged::ArgumentType>
DBusTrackChangedSignal;
366 typedef core::dbus::Signal<
367 mpris::TrackList::Signals::TrackListReset,
368 mpris::TrackList::Signals::TrackListReset::ArgumentType>
370 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackListReplaced, mpris::TrackList::Signals::TrackListReplaced::ArgumentType>
DBusTrackListReplacedSignal;
372 Signals(
const std::shared_ptr<DBusTrackAddedSignal>& remote_track_added,
373 const std::shared_ptr<DBusTracksAddedSignal>& remote_tracks_added,
374 const std::shared_ptr<DBusTrackMovedSignal>& remote_track_moved,
375 const std::shared_ptr<DBusTrackRemovedSignal>& remote_track_removed,
376 const std::shared_ptr<DBusTrackChangedSignal>& remote_track_changed,
377 const std::shared_ptr<DBusTrackListResetSignal>& remote_track_list_reset,
378 const std::shared_ptr<DBusTrackListReplacedSignal>& remote_track_list_replaced)
383 remote_track_added->emit(
id);
388 remote_tracks_added->emit(tracks);
393 remote_track_moved->emit(ids);
398 remote_track_removed->emit(
id);
401 on_track_list_reset.connect([remote_track_list_reset]()
403 remote_track_list_reset->emit();
408 remote_track_changed->emit(
id);
413 remote_track_list_replaced->emit(tltuple);
430 const media::apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver,
431 const media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator)
432 : d(new
Private(this, bus, object, request_context_resolver, request_authenticator))
434 d->object->install_method_handler<mpris::TrackList::GetTracksMetadata>(
437 std::placeholders::_1));
439 d->object->install_method_handler<mpris::TrackList::GetTracksUri>(
442 std::placeholders::_1));
444 d->object->install_method_handler<mpris::TrackList::AddTrack>(
447 std::placeholders::_1));
449 d->object->install_method_handler<mpris::TrackList::AddTracks>(
452 std::placeholders::_1));
454 d->object->install_method_handler<mpris::TrackList::MoveTrack>(
457 std::placeholders::_1));
459 d->object->install_method_handler<mpris::TrackList::RemoveTrack>(
462 std::placeholders::_1));
464 d->object->install_method_handler<mpris::TrackList::GoTo>(
467 std::placeholders::_1));
469 d->object->install_method_handler<mpris::TrackList::Reset>(
472 std::placeholders::_1));
486 const auto n_tracks =
tracks().get().size();
497 if (d->current_track == d->empty_iterator)
524 if (
tracks().
get().empty() || d->current_track == d->empty_iterator)
530 return d->current_track != std::begin(
tracks().
get());
542 if (
tracks().
get().empty()) {
544 MH_ERROR(
"No tracks, cannot go to next");
548 bool go_to_track =
false;
551 if (d->loop_status == media::Player::LoopStatus::track)
553 MH_INFO(
"Looping on the current track since LoopStatus is set to track");
557 else if (d->loop_status == media::Player::LoopStatus::playlist && not
has_next())
559 MH_INFO(
"Looping on the tracklist since LoopStatus is set to playlist");
568 d->current_track =
tracks().get().begin();
578 MH_INFO(
"Advancing to next track: %s", *it);
588 MH_INFO(
"Advancing to next track: %s", *it);
589 d->current_track = it;
607 MH_INFO(
"End of tracklist reached");
617 if (
tracks().
get().empty()) {
619 MH_ERROR(
"No tracks, cannot go to previous");
623 bool go_to_track =
false;
625 const uint64_t max_position = 5 * UINT64_C(1000000000);
629 if (d->current_position > max_position)
631 MH_INFO(
"Repeating current track...");
635 else if (d->loop_status == media::Player::LoopStatus::track)
637 MH_INFO(
"Looping on the current track...");
641 else if (d->loop_status == media::Player::LoopStatus::playlist && not
has_previous())
643 MH_INFO(
"Looping on the entire TrackList...");
652 d->current_track = std::prev(
tracks().
get().end());
684 MH_INFO(
"Beginning of tracklist reached");
700 if (
tracks().
get().size() && (d->current_track == d->empty_iterator))
702 MH_DEBUG(
"Wrapping d->current_track back to begin()");
703 d->current_track = d->skeleton.properties.tracks->get().begin();
705 else if (
tracks().
get().empty())
707 MH_ERROR(
"TrackList is empty therefore there is no valid current track");
710 return d->current_track;
716 if (it ==
tracks().
get().end())
719 d->current_track = it;
726 d->current_track = find(
tracks().
get().begin(),
tracks().
get().end(), d->id_after_remove);
727 if (d->current_track ==
tracks().
get().end())
728 d->current_track = d->empty_iterator;
733 if (d->current_track == d->empty_iterator ||
tracks().
get().empty())
741 const auto id_it = find(
tracks().
get().begin(),
tracks().
get().end(),
id);
742 if (id_it !=
tracks().
get().end())
743 d->current_track = id_it;
753 return *d->skeleton.properties.can_edit_tracks;
758 return *d->skeleton.properties.can_edit_tracks;
763 return *d->skeleton.properties.tracks;
768 d->current_position = position;
778 return d->loop_status;
789 return *d->skeleton.properties.tracks;
796 return d->signals.on_track_list_replaced;
801 return d->signals.on_track_added;
806 return d->signals.on_tracks_added;
811 return d->signals.on_track_moved;
816 return d->signals.on_track_removed;
821 return d->signals.on_track_list_reset;
826 return d->signals.on_track_changed;
831 return d->signals.on_go_to_track;
836 return d->signals.on_end_of_tracklist;
841 return d->signals.on_track_list_replaced;
846 return d->signals.on_track_added;
851 return d->signals.on_tracks_added;
856 return d->signals.on_track_moved;
861 return d->signals.on_track_removed;
866 return d->signals.on_track_list_reset;
871 return d->signals.on_track_changed;
876 return d->signals.on_go_to_track;
881 return d->signals.on_end_of_tracklist;
886 d->current_track = d->empty_iterator;
893 out <<
"TrackList\n---------------" << std::endl;
898 out <<
"Track Id: " <<
id << std::endl;
902 out <<
"---------------\nEnd TrackList" << std::endl;
static constexpr const char * name
static constexpr const char * name
static constexpr const char * name
static constexpr const char * name
static constexpr const char * name
static constexpr const char * name