34 #include <core/dbus/object.h> 35 #include <core/dbus/property.h> 36 #include <core/dbus/types/object_path.h> 37 #include <core/dbus/types/variant.h> 38 #include <core/dbus/types/stl/map.h> 39 #include <core/dbus/types/stl/vector.h> 54 const apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver,
55 const media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator)
59 request_context_resolver(request_context_resolver),
60 request_authenticator(request_authenticator),
61 uri_check(
std::make_shared<UriCheck>()),
63 current_track(skeleton.properties.tracks->get().begin()),
64 empty_iterator(skeleton.properties.tracks->get().begin()),
65 loop_status(media::Player::LoopStatus::none),
70 skeleton.signals.track_added,
71 skeleton.signals.tracks_added,
72 skeleton.signals.track_moved,
73 skeleton.signals.track_removed,
74 skeleton.signals.track_changed,
75 skeleton.signals.track_list_reset,
76 skeleton.signals.tracklist_replaced
84 msg->reader() >> track;
86 const auto meta_data =
impl->query_meta_data_for_track(track);
88 const auto reply = dbus::Message::make_method_return(msg);
89 reply->writer() << *meta_data;
96 msg->reader() >> track;
98 const auto uri =
impl->query_uri_for_track(track);
100 const auto reply = dbus::Message::make_method_return(msg);
101 reply->writer() << uri;
107 std::cout <<
"*** " << __PRETTY_FUNCTION__ << std::endl;
108 request_context_resolver->resolve_context_for_dbus_name_async
109 (msg->sender(), [
this, msg](
const media::apparmor::ubuntu::Context& context)
114 msg->reader() >> uri >> after >> make_current;
117 const auto result = request_authenticator->authenticate_open_uri_request(context, uri);
118 auto reply = dbus::Message::make_method_return(msg);
121 const bool valid_uri = !uri_check->is_local_file() or
122 (uri_check->is_local_file() and uri_check->file_exists());
125 const std::string err_str = {
"Warning: Not adding track " + uri +
126 " to TrackList because it can't be found."};
127 std::cerr << err_str << std::endl;
128 reply = dbus::Message::make_error(
136 if (std::get<0>(result))
138 impl->add_track_with_uri_at(uri, after, make_current);
142 const std::string err_str = {
"Warning: Not adding track " + uri +
143 " to TrackList because of inadequate client apparmor permissions."};
144 std::cerr << err_str << std::endl;
145 reply = dbus::Message::make_error(
158 std::cout <<
"*** " << __PRETTY_FUNCTION__ << std::endl;
159 request_context_resolver->resolve_context_for_dbus_name_async
160 (msg->sender(), [
this, msg](
const media::apparmor::ubuntu::Context& context)
164 msg->reader() >> uris >> after;
166 bool valid_uri =
false;
167 media::apparmor::ubuntu::RequestAuthenticator::Result result;
168 std::string uri_err_str, err_str;
169 core::dbus::Message::Ptr reply;
170 for (
const auto uri : uris)
173 valid_uri = !uri_check->is_local_file() or
174 (uri_check->is_local_file() and uri_check->file_exists());
177 uri_err_str = {
"Warning: Not adding track " + uri +
178 " to TrackList because it can't be found."};
179 std::cerr << uri_err_str << std::endl;
180 reply = dbus::Message::make_error(
187 result = request_authenticator->authenticate_open_uri_request(context, uri);
188 if (not std::get<0>(result))
190 err_str = {
"Warning: Not adding track " + uri +
191 " to TrackList because of inadequate client apparmor permissions."};
197 if (std::get<0>(result))
199 reply = dbus::Message::make_method_return(msg);
200 impl->add_tracks_with_uri_at(uris, after);
204 std::cerr << err_str << std::endl;
205 reply = dbus::Message::make_error(
219 msg->reader() >>
id >> to;
221 core::dbus::Message::Ptr reply;
223 const bool ret =
impl->move_track(
id, to);
226 const std::string err_str = {
"Error: Not moving track " +
id +
227 " to destination " + to};
228 std::cerr << err_str << std::endl;
229 reply = dbus::Message::make_error(
236 reply = dbus::Message::make_method_return(msg);
238 }
catch(media::TrackList::Errors::FailedToMoveTrack& e) {
239 reply = dbus::Message::make_error(
243 }
catch(media::TrackList::Errors::FailedToFindMoveTrackSource& e) {
244 reply = dbus::Message::make_error(
248 }
catch(media::TrackList::Errors::FailedToFindMoveTrackDest& e) {
249 reply = dbus::Message::make_error(
261 msg->reader() >> track;
263 auto id_it = find(
impl->tracks().get().begin(),
impl->tracks().get().end(), track);
264 if (id_it ==
impl->tracks().get().end()) {
265 ostringstream err_str;
266 err_str <<
"Track " << track <<
" not found in track list";
267 cout << __PRETTY_FUNCTION__ <<
" WARNING " << err_str.str() << endl;
268 auto reply = dbus::Message::make_error(
277 bool deleting_current =
false;
279 if (id_it ==
impl->current_iterator())
281 cout <<
"Removing current track" << endl;
282 deleting_current =
true;
284 if (current_track != empty_iterator)
288 if (current_track ==
impl->tracks().get().end()
289 && loop_status == media::Player::LoopStatus::playlist)
293 current_track =
impl->tracks().get().begin();
296 if (current_track ==
impl->tracks().get().end())
298 current_track = empty_iterator;
300 impl->emit_on_end_of_tracklist();
304 next = *current_track;
308 else if (current_track != empty_iterator)
310 next = *current_track;
312 id_after_remove = next;
315 impl->remove_track(track);
317 if ((not next.empty()) and deleting_current)
320 auto reply = dbus::Message::make_method_return(msg);
327 msg->reader() >> track;
329 current_track = std::find(skeleton.properties.tracks->get().begin(), skeleton.properties.tracks->get().end(), track);
332 auto reply = dbus::Message::make_method_return(msg);
340 auto reply = dbus::Message::make_method_return(msg);
360 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackAdded, mpris::TrackList::Signals::TrackAdded::ArgumentType>
DBusTrackAddedSignal;
361 typedef core::dbus::Signal<mpris::TrackList::Signals::TracksAdded, mpris::TrackList::Signals::TracksAdded::ArgumentType>
DBusTracksAddedSignal;
362 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackMoved, mpris::TrackList::Signals::TrackMoved::ArgumentType>
DBusTrackMovedSignal;
363 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackRemoved, mpris::TrackList::Signals::TrackRemoved::ArgumentType>
DBusTrackRemovedSignal;
364 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackChanged, mpris::TrackList::Signals::TrackChanged::ArgumentType>
DBusTrackChangedSignal;
365 typedef core::dbus::Signal<
366 mpris::TrackList::Signals::TrackListReset,
367 mpris::TrackList::Signals::TrackListReset::ArgumentType>
369 typedef core::dbus::Signal<mpris::TrackList::Signals::TrackListReplaced, mpris::TrackList::Signals::TrackListReplaced::ArgumentType>
DBusTrackListReplacedSignal;
371 Signals(
const std::shared_ptr<DBusTrackAddedSignal>& remote_track_added,
372 const std::shared_ptr<DBusTracksAddedSignal>& remote_tracks_added,
373 const std::shared_ptr<DBusTrackMovedSignal>& remote_track_moved,
374 const std::shared_ptr<DBusTrackRemovedSignal>& remote_track_removed,
375 const std::shared_ptr<DBusTrackChangedSignal>& remote_track_changed,
376 const std::shared_ptr<DBusTrackListResetSignal>& remote_track_list_reset,
377 const std::shared_ptr<DBusTrackListReplacedSignal>& remote_track_list_replaced)
382 remote_track_added->emit(
id);
387 remote_tracks_added->emit(tracks);
392 remote_track_moved->emit(ids);
397 remote_track_removed->emit(
id);
400 on_track_list_reset.connect([remote_track_list_reset]()
402 remote_track_list_reset->emit();
407 remote_track_changed->emit(
id);
412 remote_track_list_replaced->emit(tltuple);
429 const media::apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver,
430 const media::apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator)
431 : d(new
Private(this, bus, object, request_context_resolver, request_authenticator))
433 d->object->install_method_handler<mpris::TrackList::GetTracksMetadata>(
436 std::placeholders::_1));
438 d->object->install_method_handler<mpris::TrackList::GetTracksUri>(
441 std::placeholders::_1));
443 d->object->install_method_handler<mpris::TrackList::AddTrack>(
446 std::placeholders::_1));
448 d->object->install_method_handler<mpris::TrackList::AddTracks>(
451 std::placeholders::_1));
453 d->object->install_method_handler<mpris::TrackList::MoveTrack>(
456 std::placeholders::_1));
458 d->object->install_method_handler<mpris::TrackList::RemoveTrack>(
461 std::placeholders::_1));
463 d->object->install_method_handler<mpris::TrackList::GoTo>(
466 std::placeholders::_1));
468 d->object->install_method_handler<mpris::TrackList::Reset>(
471 std::placeholders::_1));
485 const auto n_tracks =
tracks().get().size();
496 if (d->current_track == d->empty_iterator)
523 if (
tracks().
get().empty() || d->current_track == d->empty_iterator)
529 return d->current_track != std::begin(
tracks().
get());
540 std::cout << __PRETTY_FUNCTION__ << std::endl;
541 if (
tracks().
get().empty()) {
543 std::cerr <<
"ERROR: no tracks, cannot go to next" << std::endl;
547 bool go_to_track =
false;
550 if (d->loop_status == media::Player::LoopStatus::track)
552 std::cout <<
"Looping on the current track since LoopStatus is set to track" << std::endl;
556 else if (d->loop_status == media::Player::LoopStatus::playlist && not
has_next())
558 std::cout <<
"Looping on the tracklist since LoopStatus is set to playlist" << std::endl;
567 d->current_track =
tracks().get().begin();
577 cout <<
"Advancing to next track: " << *it << endl;
587 cout <<
"Advancing to next track: " << *it << endl;
588 d->current_track = it;
606 cout <<
"End of tracklist reached" << endl;
615 std::cout << __PRETTY_FUNCTION__ << std::endl;
616 if (
tracks().
get().empty()) {
618 std::cerr <<
"ERROR: no tracks, cannot go to previous" << std::endl;
622 bool go_to_track =
false;
624 const uint64_t max_position = 5 * UINT64_C(1000000000);
628 if (d->current_position > max_position)
630 std::cout <<
"Repeating current track..." << std::endl;
634 else if (d->loop_status == media::Player::LoopStatus::track)
636 std::cout <<
"Looping on the current track..." << std::endl;
640 else if (d->loop_status == media::Player::LoopStatus::playlist && not
has_previous())
642 std::cout <<
"Looping on the entire TrackList..." << std::endl;
651 d->current_track = std::prev(
tracks().
get().end());
683 cout <<
"Beginning of tracklist reached" << endl;
699 if (
tracks().
get().size() && (d->current_track == d->empty_iterator))
701 std::cout <<
"Wrapping d->current_track back to begin()" << std::endl;
702 d->current_track = d->skeleton.properties.tracks->get().begin();
704 else if (
tracks().
get().empty())
706 std::cerr <<
"TrackList is empty therefore there is no valid current track" << std::endl;
709 return d->current_track;
714 std::cout << __PRETTY_FUNCTION__ << std::endl;
715 if (it ==
tracks().
get().end())
718 std::cout <<
"Updating current_track iterator" << std::endl;
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;
783 cout << __PRETTY_FUNCTION__ << endl;
790 return *d->skeleton.properties.tracks;
796 std::cout << *
this << std::endl;
797 return d->signals.on_track_list_replaced;
802 return d->signals.on_track_added;
807 return d->signals.on_tracks_added;
812 return d->signals.on_track_moved;
817 return d->signals.on_track_removed;
822 return d->signals.on_track_list_reset;
827 return d->signals.on_track_changed;
832 return d->signals.on_go_to_track;
837 return d->signals.on_end_of_tracklist;
842 return d->signals.on_track_list_replaced;
847 return d->signals.on_track_added;
852 return d->signals.on_tracks_added;
857 return d->signals.on_track_moved;
862 return d->signals.on_track_removed;
867 return d->signals.on_track_list_reset;
872 return d->signals.on_track_changed;
877 return d->signals.on_go_to_track;
882 return d->signals.on_end_of_tracklist;
887 d->current_track = d->empty_iterator;
894 out <<
"TrackList\n---------------" << std::endl;
899 out <<
"Track Id: " <<
id << std::endl;
903 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