Music Hub  ..
A session-wide music playback service
track_list_stub.cpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2013 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  */
18 
19 #include "track_list_stub.h"
20 
21 #include <core/media/player.h>
22 #include <core/media/track_list.h>
23 
24 #include "property_stub.h"
25 #include "track_list_traits.h"
26 #include "the_session_bus.h"
27 
28 #include "mpris/track_list.h"
29 
30 #include <core/dbus/property.h>
31 #include <core/dbus/types/object_path.h>
32 #include <core/dbus/types/variant.h>
33 #include <core/dbus/types/stl/map.h>
34 #include <core/dbus/types/stl/vector.h>
35 
36 #include <limits>
37 
38 namespace dbus = core::dbus;
39 namespace media = core::ubuntu::media;
40 
42 {
45  const std::shared_ptr<media::Player>& parent,
46  const dbus::Object::Ptr& object)
47  : impl(impl),
48  parent(parent),
49  object(object),
50  can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()),
51  tracks(object->get_property<mpris::TrackList::Properties::Tracks>()),
52  signals
53  {
54  object->get_signal<mpris::TrackList::Signals::TrackAdded>(),
55  object->get_signal<mpris::TrackList::Signals::TrackRemoved>(),
56  object->get_signal<mpris::TrackList::Signals::TrackListReplaced>(),
57  object->get_signal<mpris::TrackList::Signals::TrackChanged>()
58  }
59  {
60  }
61 
63  std::shared_ptr<media::Player> parent;
64  dbus::Object::Ptr object;
65 
66  std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks;
67  std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks;
68 
69 
70  struct Signals
71  {
72  typedef core::dbus::Signal<mpris::TrackList::Signals::TrackAdded, mpris::TrackList::Signals::TrackAdded::ArgumentType> DBusTrackAddedSignal;
73  typedef core::dbus::Signal<mpris::TrackList::Signals::TrackRemoved, mpris::TrackList::Signals::TrackRemoved::ArgumentType> DBusTrackRemovedSignal;
74  typedef core::dbus::Signal<mpris::TrackList::Signals::TrackListReplaced, mpris::TrackList::Signals::TrackListReplaced::ArgumentType> DBusTrackListReplacedSignal;
75  typedef core::dbus::Signal<mpris::TrackList::Signals::TrackChanged, mpris::TrackList::Signals::TrackChanged::ArgumentType> DBusTrackChangedSignal;
76 
77  Signals(const std::shared_ptr<DBusTrackAddedSignal>& track_added,
78  const std::shared_ptr<DBusTrackRemovedSignal>& track_removed,
79  const std::shared_ptr<DBusTrackListReplacedSignal>& track_list_replaced,
80  const std::shared_ptr<DBusTrackChangedSignal>& track_changed)
81  : on_track_added(),
85  dbus
86  {
87  track_added,
88  track_removed,
89  track_list_replaced,
90  track_changed,
91  }
92  {
93  dbus.on_track_added->connect([this](const Track::Id& id)
94  {
95  std::cout << "OnTrackAdded signal arrived via the bus." << std::endl;
96  on_track_added(id);
97  });
98 
99  dbus.on_track_removed->connect([this](const Track::Id& id)
100  {
101  std::cout << "OnTrackRemoved signal arrived via the bus." << std::endl;
102  on_track_removed(id);
103  });
104 
105  dbus.on_track_list_replaced->connect([this](const media::TrackList::ContainerTrackIdTuple& list)
106  {
107  std::cout << "OnTrackListRemoved signal arrived via the bus." << std::endl;
109  });
110 
111  dbus.on_track_changed->connect([this](const Track::Id& id)
112  {
113  std::cout << "OnTrackChanged signal arrived via the bus." << std::endl;
114  on_track_changed(id);
115  });
116  }
117 
118  core::Signal<Track::Id> on_track_added;
119  core::Signal<Track::Id> on_track_removed;
120  core::Signal<media::TrackList::ContainerTrackIdTuple> on_track_list_replaced;
121  core::Signal<Track::Id> on_track_changed;
122  core::Signal<std::pair<Track::Id, bool>> on_go_to_track;
123  core::Signal<void> on_end_of_tracklist;
124 
125  struct DBus
126  {
127  std::shared_ptr<DBusTrackAddedSignal> on_track_added;
128  std::shared_ptr<DBusTrackRemovedSignal> on_track_removed;
129  std::shared_ptr<DBusTrackListReplacedSignal> on_track_list_replaced;
130  std::shared_ptr<DBusTrackChangedSignal> on_track_changed;
131  } dbus;
132  } signals;
133 };
134 
136  const std::shared_ptr<media::Player>& parent,
137  const core::dbus::Object::Ptr& object)
138  : d(new Private(this, parent, object))
139 {
140 }
141 
143 {
144 }
145 
146 const core::Property<bool>& media::TrackListStub::can_edit_tracks() const
147 {
148  return *d->can_edit_tracks;
149 }
150 
151 const core::Property<media::TrackList::Container>& media::TrackListStub::tracks() const
152 {
153  return *d->tracks;
154 }
155 
157 {
158  auto op = d->object->invoke_method_synchronously<
159  mpris::TrackList::GetTracksMetadata,
160  std::map<std::string, std::string>>(id);
161 
162  if (op.is_error())
163  throw std::runtime_error("Problem querying meta data for track: " + op.error());
164 
165  media::Track::MetaData md;
166  for(auto pair : op.value())
167  {
168  md.set(pair.first, pair.second);
169  }
170  return md;
171 }
172 
174 {
175  auto op = d->object->invoke_method_synchronously<
176  mpris::TrackList::GetTracksUri,
177  std::string>(id);
178 
179  if (op.is_error())
180  throw std::runtime_error("Problem querying track for uri: " + op.error());
181 
182  return op.value();
183 }
184 
186  const media::Track::UriType& uri,
187  const media::Track::Id& id,
188  bool make_current)
189 {
190  auto op = d->object->invoke_method_synchronously<mpris::TrackList::AddTrack, void>(
191  uri,
192  id,
193  make_current);
194 
195  if (op.is_error())
196  throw std::runtime_error("Problem adding track: " + op.error());
197 }
198 
200 {
201  auto op = d->object->invoke_method_synchronously<mpris::TrackList::RemoveTrack, void>(
202  track);
203 
204  if (op.is_error())
205  throw std::runtime_error("Problem removing track: " + op.error());
206 }
207 
208 void media::TrackListStub::go_to(const media::Track::Id& track, bool toggle_player_state)
209 {
210  (void) toggle_player_state;
211  auto op = d->object->invoke_method_synchronously<mpris::TrackList::GoTo, void>(
212  track);
213 
214  if (op.is_error())
215  throw std::runtime_error("Problem adding track: " + op.error());
216 }
217 
219 {
220  // TODO: Add this to the dbus interface on the server and implement a proper dbus method call
221  return media::Track::Id{"/empty/track/id"};
222 }
223 
225 {
226  // TODO: Add this to the dbus interface on the server and implement a proper dbus method call
227  return media::Track::Id{"/empty/track/id"};
228 }
229 
231 {
232  std::cerr << "shuffle_tracks() does nothing from the client side" << std::endl;
233 }
234 
236 {
237  std::cerr << "unshuffle_tracks() does nothing from the client side" << std::endl;
238 }
239 
241 {
242  auto op = d->object->invoke_method_synchronously<mpris::TrackList::Reset, void>();
243 
244  if (op.is_error())
245  throw std::runtime_error("Problem resetting tracklist: " + op.error());
246 }
247 
248 const core::Signal<media::TrackList::ContainerTrackIdTuple>& media::TrackListStub::on_track_list_replaced() const
249 {
250  return d->signals.on_track_list_replaced;
251 }
252 
253 const core::Signal<media::Track::Id>& media::TrackListStub::on_track_added() const
254 {
255  return d->signals.on_track_added;
256 }
257 
258 const core::Signal<media::Track::Id>& media::TrackListStub::on_track_removed() const
259 {
260  return d->signals.on_track_removed;
261 }
262 
263 const core::Signal<media::Track::Id>& media::TrackListStub::on_track_changed() const
264 {
265  return d->signals.on_track_changed;
266 }
267 
268 const core::Signal<std::pair<media::Track::Id, bool>>& media::TrackListStub::on_go_to_track() const
269 {
270  return d->signals.on_go_to_track;
271 }
272 
273 const core::Signal<void>& media::TrackListStub::on_end_of_tracklist() const
274 {
275  return d->signals.on_end_of_tracklist;
276 }
Private(TrackListStub *impl, const std::shared_ptr< media::Player > &parent, const dbus::Object::Ptr &object)
core::Signal< Track::Id > on_track_changed
std::shared_ptr< core::dbus::Property< mpris::TrackList::Properties::CanEditTracks > > can_edit_tracks
std::shared_ptr< DBusTrackListReplacedSignal > on_track_list_replaced
std::shared_ptr< DBusTrackRemovedSignal > on_track_removed
const core::Property< bool > & can_edit_tracks() const
void add_track_with_uri_at(const Track::UriType &uri, const Track::Id &position, bool make_current)
Track::MetaData query_meta_data_for_track(const Track::Id &id)
void remove_track(const Track::Id &id)
core::dbus::Signal< mpris::TrackList::Signals::TrackListReplaced, mpris::TrackList::Signals::TrackListReplaced::ArgumentType > DBusTrackListReplacedSignal
void set(const typename Tag::ValueType &value)
Definition: track.h:63
const core::Signal< Track::Id > & on_track_changed() const
core::Signal< std::pair< Track::Id, bool > > on_go_to_track
Track::UriType query_uri_for_track(const Track::Id &id)
std::tuple< std::vector< Track::Id >, Track::Id > ContainerTrackIdTuple
Definition: track_list.h:44
const core::Signal< Track::Id > & on_track_added() const
const core::Signal< std::pair< Track::Id, bool > > & on_go_to_track() const
std::shared_ptr< media::Player > parent
void go_to(const Track::Id &track, bool toggle_player_state)
struct media::TrackListStub::Private::Signals signals
std::shared_ptr< DBusTrackChangedSignal > on_track_changed
TrackListStub(const std::shared_ptr< Player > &parent, const core::dbus::Object::Ptr &object)
const core::Property< Container > & tracks() const
const core::Signal< Track::Id > & on_track_removed() const
struct media::TrackListStub::Private::Signals::DBus dbus
core::dbus::Signal< mpris::TrackList::Signals::TrackRemoved, mpris::TrackList::Signals::TrackRemoved::ArgumentType > DBusTrackRemovedSignal
const core::Signal< ContainerTrackIdTuple > & on_track_list_replaced() const
std::shared_ptr< core::dbus::Property< mpris::TrackList::Properties::Tracks > > tracks
std::string UriType
Definition: track.h:40
core::Signal< Track::Id > on_track_added
Signals(const std::shared_ptr< DBusTrackAddedSignal > &track_added, const std::shared_ptr< DBusTrackRemovedSignal > &track_removed, const std::shared_ptr< DBusTrackListReplacedSignal > &track_list_replaced, const std::shared_ptr< DBusTrackChangedSignal > &track_changed)
core::dbus::Signal< mpris::TrackList::Signals::TrackChanged, mpris::TrackList::Signals::TrackChanged::ArgumentType > DBusTrackChangedSignal
const core::Signal< void > & on_end_of_tracklist() const
core::Signal< Track::Id > on_track_removed
core::Signal< media::TrackList::ContainerTrackIdTuple > on_track_list_replaced
core::dbus::Signal< mpris::TrackList::Signals::TrackAdded, mpris::TrackList::Signals::TrackAdded::ArgumentType > DBusTrackAddedSignal
std::shared_ptr< DBusTrackAddedSignal > on_track_added