Music Hub  ..
A session-wide music playback service
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
player.h
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  * Jim Hodapp <jim.hodapp@canonical.com>
18  */
19 
20 #ifndef MPRIS_PLAYER_H_
21 #define MPRIS_PLAYER_H_
22 
23 #include <core/media/player.h>
24 #include <core/media/track.h>
25 
26 #include "core/media/codec.h"
27 
28 #include <core/dbus/bus.h>
29 #include <core/dbus/macros.h>
30 #include <core/dbus/object.h>
31 #include <core/dbus/property.h>
32 #include <core/dbus/interfaces/properties.h>
33 #include <core/dbus/types/any.h>
34 #include <core/dbus/types/object_path.h>
35 #include <core/dbus/types/variant.h>
36 
37 #include <boost/utility/identity_type.hpp>
38 
39 #include <string>
40 #include <tuple>
41 #include <vector>
42 
43 namespace dbus = core::dbus;
44 
45 namespace mpris
46 {
47 struct Player
48 {
49  static const std::string& name()
50  {
51  static const std::string s{"org.mpris.MediaPlayer2.Player"};
52  return s;
53  }
54 
55  struct LoopStatus
56  {
57  LoopStatus() = delete;
58 
59  static const char* from(core::ubuntu::media::Player::LoopStatus status)
60  {
61  switch(status)
62  {
63  case core::ubuntu::media::Player::LoopStatus::none:
64  return LoopStatus::none;
65  case core::ubuntu::media::Player::LoopStatus::track:
66  return LoopStatus::track;
67  case core::ubuntu::media::Player::LoopStatus::playlist:
68  return LoopStatus::playlist;
69  }
70 
71  return nullptr;
72  }
73 
74  static constexpr const char* none{"None"};
75  static constexpr const char* track{"Track"};
76  static constexpr const char* playlist{"Playlist"};
77  };
78 
80  {
81  PlaybackStatus() = delete;
82 
84  {
85  switch(status)
86  {
87  case core::ubuntu::media::Player::PlaybackStatus::null:
88  case core::ubuntu::media::Player::PlaybackStatus::ready:
89  case core::ubuntu::media::Player::PlaybackStatus::stopped:
91 
92  case core::ubuntu::media::Player::PlaybackStatus::playing:
94  case core::ubuntu::media::Player::PlaybackStatus::paused:
96  }
97 
98  return nullptr;
99  }
100 
101  static constexpr const char* playing{"Playing"};
102  static constexpr const char* paused{"Paused"};
103  static constexpr const char* stopped{"Stopped"};
104  };
105 
106  typedef std::map<std::string, core::dbus::types::Variant> Dictionary;
107 
108  DBUS_CPP_METHOD_DEF(Next, Player)
109  DBUS_CPP_METHOD_DEF(Previous, Player)
110  DBUS_CPP_METHOD_DEF(Pause, Player)
111  DBUS_CPP_METHOD_DEF(PlayPause, Player)
112  DBUS_CPP_METHOD_DEF(Stop, Player)
113  DBUS_CPP_METHOD_DEF(Play, Player)
114  DBUS_CPP_METHOD_DEF(Seek, Player)
115  DBUS_CPP_METHOD_DEF(SetPosition, Player)
116  DBUS_CPP_METHOD_DEF(CreateVideoSink, Player)
117  DBUS_CPP_METHOD_DEF(Key, Player)
118  DBUS_CPP_METHOD_DEF(OpenUri, Player)
119 
120  struct Signals
121  {
122  DBUS_CPP_SIGNAL_DEF(Seeked, Player, std::int64_t)
123  DBUS_CPP_SIGNAL_DEF(EndOfStream, Player, void)
124  DBUS_CPP_SIGNAL_DEF(PlaybackStatusChanged, Player, core::ubuntu::media::Player::PlaybackStatus)
125  };
126 
127  struct Properties
128  {
129  DBUS_CPP_READABLE_PROPERTY_DEF(PlaybackStatus, Player, std::string)
130  DBUS_CPP_READABLE_PROPERTY_DEF(TypedPlaybackStatus, Player, core::ubuntu::media::Player::PlaybackStatus)
131 
132  DBUS_CPP_WRITABLE_PROPERTY_DEF(LoopStatus, Player, std::string)
133  DBUS_CPP_WRITABLE_PROPERTY_DEF(TypedLoopStatus, Player, core::ubuntu::media::Player::LoopStatus)
134  DBUS_CPP_WRITABLE_PROPERTY_DEF(AudioStreamRole, Player, core::ubuntu::media::Player::AudioStreamRole)
135  DBUS_CPP_WRITABLE_PROPERTY_DEF(PlaybackRate, Player, double)
136  DBUS_CPP_WRITABLE_PROPERTY_DEF(Rate, Player, double)
137  DBUS_CPP_WRITABLE_PROPERTY_DEF(Shuffle, Player, bool)
138  DBUS_CPP_READABLE_PROPERTY_DEF(Metadata, Player, Dictionary)
139  DBUS_CPP_READABLE_PROPERTY_DEF(TypedMetaData, Player, core::ubuntu::media::Track::MetaData)
140  DBUS_CPP_WRITABLE_PROPERTY_DEF(Volume, Player, double)
141  DBUS_CPP_READABLE_PROPERTY_DEF(Position, Player, std::int64_t)
142  DBUS_CPP_READABLE_PROPERTY_DEF(Duration, Player, std::int64_t)
143  DBUS_CPP_READABLE_PROPERTY_DEF(MinimumRate, Player, double)
144  DBUS_CPP_READABLE_PROPERTY_DEF(MaximumRate, Player, double)
145  DBUS_CPP_READABLE_PROPERTY_DEF(IsVideoSource, Player, bool)
146  DBUS_CPP_READABLE_PROPERTY_DEF(IsAudioSource, Player, bool)
147  DBUS_CPP_READABLE_PROPERTY_DEF(CanGoNext, Player, bool)
148  DBUS_CPP_READABLE_PROPERTY_DEF(CanGoPrevious, Player, bool)
149  DBUS_CPP_READABLE_PROPERTY_DEF(CanPlay, Player, bool)
150  DBUS_CPP_READABLE_PROPERTY_DEF(CanPause, Player, bool)
151  DBUS_CPP_READABLE_PROPERTY_DEF(CanSeek, Player, bool)
152  DBUS_CPP_READABLE_PROPERTY_DEF(CanControl, Player, bool)
153  };
154 
155  // Convenience struct to create a skeleton implementation for org.mpris.MediaPlayer2.Player
156  struct Skeleton
157  {
158  static const std::vector<std::string>& the_empty_list_of_invalidated_properties()
159  {
160  static const std::vector<std::string> instance; return instance;
161  }
162 
163  // Creation time options go here.
165  {
166  // The bus connection that should be used
167  core::dbus::Bus::Ptr bus;
168  // The dbus object that should implement org.mpris.MediaPlayer2
169  core::dbus::Object::Ptr object;
170 
171  // Default values for properties
172  struct Defaults
173  {
174  Properties::CanPlay::ValueType can_play{true};
175  Properties::CanPause::ValueType can_pause{true};
176  Properties::CanSeek::ValueType can_seek{true};
177  Properties::CanControl::ValueType can_control{true};
178  Properties::CanGoNext::ValueType can_go_next{true};
179  Properties::CanGoPrevious::ValueType can_go_previous{true};
180  Properties::IsVideoSource::ValueType is_video_source{false};
181  Properties::IsAudioSource::ValueType is_audio_source{true};
182  Properties::PlaybackStatus::ValueType playback_status{PlaybackStatus::stopped};
183  Properties::TypedPlaybackStatus::ValueType typed_playback_status{core::ubuntu::media::Player::PlaybackStatus::null};
184  Properties::LoopStatus::ValueType loop_status{LoopStatus::none};
185  Properties::TypedLoopStatus::ValueType typed_loop_status{core::ubuntu::media::Player::LoopStatus::none};
186  Properties::PlaybackRate::ValueType playback_rate{1.f};
187  Properties::Shuffle::ValueType shuffle{false};
188  Properties::TypedMetaData::ValueType typed_meta_data{};
189  Properties::Volume::ValueType volume{0.f};
190  Properties::Position::ValueType position{0};
191  Properties::Duration::ValueType duration{0};
192  Properties::MinimumRate::ValueType minimum_rate{1.f};
193  Properties::MaximumRate::ValueType maximum_rate{1.f};
194  } defaults;
195  };
196 
198  : configuration(configuration),
199  properties
200  {
201  configuration.object->template get_property<Properties::CanPlay>(),
202  configuration.object->template get_property<Properties::CanPause>(),
203  configuration.object->template get_property<Properties::CanSeek>(),
204  configuration.object->template get_property<Properties::CanControl>(),
205  configuration.object->template get_property<Properties::CanGoNext>(),
206  configuration.object->template get_property<Properties::CanGoPrevious>(),
207  configuration.object->template get_property<Properties::IsVideoSource>(),
208  configuration.object->template get_property<Properties::IsAudioSource>(),
209  configuration.object->template get_property<Properties::PlaybackStatus>(),
210  configuration.object->template get_property<Properties::TypedPlaybackStatus>(),
211  configuration.object->template get_property<Properties::LoopStatus>(),
212  configuration.object->template get_property<Properties::TypedLoopStatus>(),
213  configuration.object->template get_property<Properties::AudioStreamRole>(),
214  configuration.object->template get_property<Properties::PlaybackRate>(),
215  configuration.object->template get_property<Properties::Shuffle>(),
216  configuration.object->template get_property<Properties::TypedMetaData>(),
217  configuration.object->template get_property<Properties::Volume>(),
218  configuration.object->template get_property<Properties::Position>(),
219  configuration.object->template get_property<Properties::Duration>(),
220  configuration.object->template get_property<Properties::MinimumRate>(),
221  configuration.object->template get_property<Properties::MaximumRate>()
222  },
223  signals
224  {
225  configuration.object->template get_signal<Signals::Seeked>(),
226  configuration.object->template get_signal<Signals::EndOfStream>(),
227  configuration.object->template get_signal<Signals::PlaybackStatusChanged>(),
228  configuration.object->template get_signal<core::dbus::interfaces::Properties::Signals::PropertiesChanged>()
229  }
230  {
231  properties.can_play->set(configuration.defaults.can_play);
232  properties.can_pause->set(configuration.defaults.can_pause);
233  properties.can_seek->set(configuration.defaults.can_seek);
234  properties.can_control->set(configuration.defaults.can_control);
235  properties.can_go_next->set(configuration.defaults.can_go_next);
236  properties.can_go_previous->set(configuration.defaults.can_go_previous);
237  properties.is_video_source->set(configuration.defaults.is_video_source);
238  properties.is_audio_source->set(configuration.defaults.is_audio_source);
239  properties.playback_status->set(configuration.defaults.playback_status);
240  properties.typed_playback_status->set(configuration.defaults.typed_playback_status);
241  properties.loop_status->set(configuration.defaults.loop_status);
242  properties.typed_loop_status->set(configuration.defaults.typed_loop_status);
243  properties.audio_stream_role->set(core::ubuntu::media::Player::AudioStreamRole::multimedia);
244  properties.playback_rate->set(configuration.defaults.playback_rate);
245  properties.is_shuffle->set(configuration.defaults.shuffle);
246  properties.position->set(configuration.defaults.position);
247  properties.duration->set(configuration.defaults.duration);
248  properties.minimum_playback_rate->set(configuration.defaults.minimum_rate);
249  properties.maximum_playback_rate->set(configuration.defaults.maximum_rate);
250 
251  properties.position->changed().connect([this](std::int64_t position)
252  {
253  on_property_value_changed<Properties::Position>(position);
254  });
255 
256  properties.duration->changed().connect([this](std::int64_t duration)
257  {
258  on_property_value_changed<Properties::Duration>(duration);
259  });
260 
261  properties.playback_status->changed().connect([this](const std::string& status)
262  {
263  on_property_value_changed<Properties::PlaybackStatus>(status);
264  });
265 
266  properties.loop_status->changed().connect([this](const std::string& status)
267  {
268  on_property_value_changed<Properties::LoopStatus>(status);
269  });
270  }
271 
272  template<typename Property>
273  void on_property_value_changed(const typename Property::ValueType& value)
274  {
275  Dictionary dict; dict[Property::name()] = dbus::types::Variant::encode(value);
276 
277  signals.properties_changed->emit(std::make_tuple(
278  dbus::traits::Service<Player>::interface_name(),
279  dict,
281  }
282 
283  Dictionary get_all_properties()
284  {
285  Dictionary dict;
286  dict[Properties::CanPlay::name()] = dbus::types::Variant::encode(properties.can_play->get());
287  dict[Properties::CanPause::name()] = dbus::types::Variant::encode(properties.can_pause->get());
288  dict[Properties::CanSeek::name()] = dbus::types::Variant::encode(properties.can_seek->get());
289  dict[Properties::CanControl::name()] = dbus::types::Variant::encode(properties.can_control->get());
290  dict[Properties::CanGoNext::name()] = dbus::types::Variant::encode(properties.can_go_next->get());
291  dict[Properties::CanGoPrevious::name()] = dbus::types::Variant::encode(properties.can_go_previous->get());
292  dict[Properties::PlaybackStatus::name()] = dbus::types::Variant::encode(properties.playback_status->get());
293  dict[Properties::TypedPlaybackStatus::name()] = dbus::types::Variant::encode(properties.typed_playback_status->get());
294  dict[Properties::LoopStatus::name()] = dbus::types::Variant::encode(properties.loop_status->get());
295  dict[Properties::TypedLoopStatus::name()] = dbus::types::Variant::encode(properties.typed_loop_status->get());
296  dict[Properties::AudioStreamRole::name()] = dbus::types::Variant::encode(properties.audio_stream_role->get());
297  dict[Properties::PlaybackRate::name()] = dbus::types::Variant::encode(properties.playback_rate->get());
298  dict[Properties::Shuffle::name()] = dbus::types::Variant::encode(properties.is_shuffle->get());
299  dict[Properties::Duration::name()] = dbus::types::Variant::encode(properties.duration->get());
300  dict[Properties::Position::name()] = dbus::types::Variant::encode(properties.position->get());
301  dict[Properties::MinimumRate::name()] = dbus::types::Variant::encode(properties.minimum_playback_rate->get());
302  dict[Properties::MaximumRate::name()] = dbus::types::Variant::encode(properties.maximum_playback_rate->get());
303 
304  return dict;
305  }
306 
307  // We just store creation time properties
309  // All the properties exposed to the bus go here.
310  struct
311  {
312  std::shared_ptr<core::dbus::Property<Properties::CanPlay>> can_play;
313  std::shared_ptr<core::dbus::Property<Properties::CanPause>> can_pause;
314  std::shared_ptr<core::dbus::Property<Properties::CanSeek>> can_seek;
315  std::shared_ptr<core::dbus::Property<Properties::CanControl>> can_control;
316  std::shared_ptr<core::dbus::Property<Properties::CanGoNext>> can_go_next;
317  std::shared_ptr<core::dbus::Property<Properties::CanGoPrevious>> can_go_previous;
318  std::shared_ptr<core::dbus::Property<Properties::IsVideoSource>> is_video_source;
319  std::shared_ptr<core::dbus::Property<Properties::IsAudioSource>> is_audio_source;
320 
321  std::shared_ptr<core::dbus::Property<Properties::PlaybackStatus>> playback_status;
322  std::shared_ptr<core::dbus::Property<Properties::TypedPlaybackStatus>> typed_playback_status;
323  std::shared_ptr<core::dbus::Property<Properties::LoopStatus>> loop_status;
324  std::shared_ptr<core::dbus::Property<Properties::TypedLoopStatus>> typed_loop_status;
325  std::shared_ptr<core::dbus::Property<Properties::AudioStreamRole>> audio_stream_role;
326  std::shared_ptr<core::dbus::Property<Properties::PlaybackRate>> playback_rate;
327  std::shared_ptr<core::dbus::Property<Properties::Shuffle>> is_shuffle;
328  std::shared_ptr<core::dbus::Property<Properties::TypedMetaData>> typed_meta_data_for_current_track;
329  std::shared_ptr<core::dbus::Property<Properties::Volume>> volume;
330  std::shared_ptr<core::dbus::Property<Properties::Position>> position;
331  std::shared_ptr<core::dbus::Property<Properties::Duration>> duration;
332  std::shared_ptr<core::dbus::Property<Properties::MinimumRate>> minimum_playback_rate;
333  std::shared_ptr<core::dbus::Property<Properties::MaximumRate>> maximum_playback_rate;
334  } properties;
335 
336  struct
337  {
338  typename core::dbus::Signal<Signals::Seeked, Signals::Seeked::ArgumentType>::Ptr seeked_to;
339  typename core::dbus::Signal<Signals::EndOfStream, Signals::EndOfStream::ArgumentType>::Ptr end_of_stream;
340  typename core::dbus::Signal<Signals::PlaybackStatusChanged, Signals::PlaybackStatusChanged::ArgumentType>::Ptr playback_status_changed;
341 
342  dbus::Signal
343  <
344  core::dbus::interfaces::Properties::Signals::PropertiesChanged,
345  core::dbus::interfaces::Properties::Signals::PropertiesChanged::ArgumentType
347  } signals;
348  };
349 };
350 }
351 
352 #endif // MPRIS_PLAYER_H_
std::shared_ptr< core::dbus::Property< Properties::Duration > > duration
Definition: player.h:331
void on_property_value_changed(const typename Property::ValueType &value)
Definition: player.h:273
std::shared_ptr< core::dbus::Property< Properties::AudioStreamRole > > audio_stream_role
Definition: player.h:325
Properties::CanGoPrevious::ValueType can_go_previous
Definition: player.h:179
std::shared_ptr< core::dbus::Property< Properties::IsAudioSource > > is_audio_source
Definition: player.h:319
Properties::CanControl::ValueType can_control
Definition: player.h:177
std::shared_ptr< core::dbus::Property< Properties::LoopStatus > > loop_status
Definition: player.h:323
Properties::MaximumRate::ValueType maximum_rate
Definition: player.h:193
Properties::Volume::ValueType volume
Definition: player.h:189
static const std::string & name()
Definition: player.h:49
static constexpr const char * none
Definition: player.h:74
std::shared_ptr< core::dbus::Property< Properties::MinimumRate > > minimum_playback_rate
Definition: player.h:332
Properties::Duration::ValueType duration
Definition: player.h:191
core::dbus::Object::Ptr object
Definition: player.h:169
static constexpr const char * playlist
Definition: player.h:76
static constexpr const char * paused
Definition: player.h:102
std::shared_ptr< core::dbus::Property< Properties::MaximumRate > > maximum_playback_rate
Definition: player.h:333
Properties::CanGoNext::ValueType can_go_next
Definition: player.h:178
static constexpr const char * stopped
Definition: player.h:103
static const char * from(core::ubuntu::media::Player::PlaybackStatus status)
Definition: player.h:83
Properties::CanPause::ValueType can_pause
Definition: player.h:175
static const std::vector< std::string > & the_empty_list_of_invalidated_properties()
Definition: player.h:158
std::shared_ptr< core::dbus::Property< Properties::Shuffle > > is_shuffle
Definition: player.h:327
Properties::TypedPlaybackStatus::ValueType typed_playback_status
Definition: player.h:183
Properties::PlaybackStatus::ValueType playback_status
Definition: player.h:182
struct mpris::Player::Skeleton::Configuration::Defaults defaults
struct mpris::Player::Skeleton::@14 properties
Properties::Position::ValueType position
Definition: player.h:190
std::map< std::string, core::dbus::types::Variant > Dictionary
Definition: player.h:106
static const char * from(core::ubuntu::media::Player::LoopStatus status)
Definition: player.h:59
Configuration configuration
Definition: player.h:308
std::shared_ptr< core::dbus::Property< Properties::IsVideoSource > > is_video_source
Definition: player.h:318
std::shared_ptr< core::dbus::Property< Properties::TypedLoopStatus > > typed_loop_status
Definition: player.h:324
std::shared_ptr< core::dbus::Property< Properties::CanGoPrevious > > can_go_previous
Definition: player.h:317
std::shared_ptr< core::dbus::Property< Properties::CanPause > > can_pause
Definition: player.h:313
Properties::PlaybackRate::ValueType playback_rate
Definition: player.h:186
Properties::TypedLoopStatus::ValueType typed_loop_status
Definition: player.h:185
Properties::CanSeek::ValueType can_seek
Definition: player.h:176
Dictionary get_all_properties()
Definition: player.h:283
struct mpris::Player::Skeleton::@15 signals
std::shared_ptr< core::dbus::Property< Properties::Volume > > volume
Definition: player.h:329
std::shared_ptr< core::dbus::Property< Properties::CanSeek > > can_seek
Definition: player.h:314
static constexpr const char * track
Definition: player.h:75
core::dbus::Signal< Signals::Seeked, Signals::Seeked::ArgumentType >::Ptr seeked_to
Definition: player.h:338
Properties::TypedMetaData::ValueType typed_meta_data
Definition: player.h:188
Properties::IsAudioSource::ValueType is_audio_source
Definition: player.h:181
Skeleton(const Configuration &configuration)
Definition: player.h:197
std::shared_ptr< core::dbus::Property< Properties::TypedPlaybackStatus > > typed_playback_status
Definition: player.h:322
Properties::MinimumRate::ValueType minimum_rate
Definition: player.h:192
std::shared_ptr< core::dbus::Property< Properties::PlaybackStatus > > playback_status
Definition: player.h:321
Properties::CanPlay::ValueType can_play
Definition: player.h:174
std::shared_ptr< core::dbus::Property< Properties::TypedMetaData > > typed_meta_data_for_current_track
Definition: player.h:328
core::dbus::Signal< Signals::EndOfStream, Signals::EndOfStream::ArgumentType >::Ptr end_of_stream
Definition: player.h:339
std::shared_ptr< core::dbus::Property< Properties::CanPlay > > can_play
Definition: player.h:312
Properties::IsVideoSource::ValueType is_video_source
Definition: player.h:180
std::shared_ptr< core::dbus::Property< Properties::CanControl > > can_control
Definition: player.h:315
static constexpr const char * playing
Definition: player.h:101
std::shared_ptr< core::dbus::Property< Properties::Position > > position
Definition: player.h:330
std::shared_ptr< core::dbus::Property< Properties::CanGoNext > > can_go_next
Definition: player.h:316
Properties::LoopStatus::ValueType loop_status
Definition: player.h:184
std::shared_ptr< core::dbus::Property< Properties::PlaybackRate > > playback_rate
Definition: player.h:326
dbus::Signal< core::dbus::interfaces::Properties::Signals::PropertiesChanged, core::dbus::interfaces::Properties::Signals::PropertiesChanged::ArgumentType >::Ptr properties_changed
Definition: player.h:346
core::dbus::Signal< Signals::PlaybackStatusChanged, Signals::PlaybackStatusChanged::ArgumentType >::Ptr playback_status_changed
Definition: player.h:340
Properties::Shuffle::ValueType shuffle
Definition: player.h:187