Music Hub  ..
A session-wide music playback service
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
engine.cpp
Go to the documentation of this file.
1 /*
2  * Copyright © 2013-2014 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 #include <stdio.h>
21 #include <stdlib.h>
22 
23 #include "bus.h"
24 #include "engine.h"
25 #include "meta_data_extractor.h"
26 #include "playbin.h"
27 
28 #include <cassert>
29 
30 namespace media = core::ubuntu::media;
31 
32 using namespace std;
33 
34 namespace gstreamer
35 {
36 struct Init
37 {
38  Init()
39  {
40  gst_init(nullptr, nullptr);
41  }
42 
44  {
45  gst_deinit();
46  }
47 } init;
48 }
49 
51 {
54  {
55  (void) state_change;
56  }
57 
59  {
60  media::Track::MetaData md;
62  track_meta_data.set(std::make_tuple(playbin.uri(), md));
63  }
64 
65  void on_volume_changed(const media::Engine::Volume& new_volume)
66  {
67  playbin.set_volume(new_volume.value);
68  }
69 
71  {
72  playbin.set_audio_stream_role(new_audio_role);
73  }
74 
76  {
77  // Update the local orientation Property, which should then update the Player
78  // orientation Property
79  orientation.set(o);
80  }
81 
83  {
84  state = Engine::State::ready;
85  about_to_finish();
86  }
87 
88  void on_seeked_to(uint64_t value)
89  {
90  seeked_to(value);
91  }
92 
94  {
95  client_disconnected();
96  }
97 
99  {
100  end_of_stream();
101  }
102 
103  void on_video_dimension_changed(uint32_t height, uint32_t width)
104  {
105  video_dimension_changed(height, width);
106  }
107 
109  : meta_data_extractor(new gstreamer::MetaDataExtractor()),
110  volume(media::Engine::Volume(1.)),
111  orientation(media::Player::Orientation::rotate0),
112  is_video_source(false),
113  is_audio_source(false),
114  about_to_finish_connection(
115  playbin.signals.about_to_finish.connect(
116  std::bind(
117  &Private::on_about_to_finish,
118  this))),
119  on_state_changed_connection(
120  playbin.signals.on_state_changed.connect(
121  std::bind(
122  &Private::on_playbin_state_changed,
123  this,
124  std::placeholders::_1))),
125  on_tag_available_connection(
126  playbin.signals.on_tag_available.connect(
127  std::bind(
128  &Private::on_tag_available,
129  this,
130  std::placeholders::_1))),
131  on_volume_changed_connection(
132  volume.changed().connect(
133  std::bind(
134  &Private::on_volume_changed,
135  this,
136  std::placeholders::_1))),
137  on_audio_stream_role_changed_connection(
138  audio_role.changed().connect(
139  std::bind(
140  &Private::on_audio_stream_role_changed,
141  this,
142  std::placeholders::_1))),
143  on_orientation_changed_connection(
144  playbin.signals.on_orientation_changed.connect(
145  std::bind(
146  &Private::on_orientation_changed,
147  this,
148  std::placeholders::_1))),
149  on_seeked_to_connection(
150  playbin.signals.on_seeked_to.connect(
151  std::bind(
152  &Private::on_seeked_to,
153  this,
154  std::placeholders::_1))),
155  client_disconnected_connection(
156  playbin.signals.client_disconnected.connect(
157  std::bind(
158  &Private::on_client_disconnected,
159  this))),
160  on_end_of_stream_connection(
161  playbin.signals.on_end_of_stream.connect(
162  std::bind(
163  &Private::on_end_of_stream,
164  this))),
165  on_video_dimension_changed_connection(
166  playbin.signals.on_add_frame_dimension.connect(
167  std::bind(
168  &Private::on_video_dimension_changed,
169  this,
170  std::placeholders::_1,
171  std::placeholders::_2)))
172  {
173  }
174 
175  // Ensure the playbin is the last item destroyed
176  // otherwise properties could try to access a dead playbin object
178 
179  std::shared_ptr<Engine::MetaDataExtractor> meta_data_extractor;
180  core::Property<Engine::State> state;
181  core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>> track_meta_data;
182  core::Property<uint64_t> position;
183  core::Property<uint64_t> duration;
184  core::Property<media::Engine::Volume> volume;
185  core::Property<media::Player::AudioStreamRole> audio_role;
186  core::Property<media::Player::Orientation> orientation;
187  core::Property<bool> is_video_source;
188  core::Property<bool> is_audio_source;
189 
190  core::ScopedConnection about_to_finish_connection;
191  core::ScopedConnection on_state_changed_connection;
192  core::ScopedConnection on_tag_available_connection;
193  core::ScopedConnection on_volume_changed_connection;
195  core::ScopedConnection on_orientation_changed_connection;
196  core::ScopedConnection on_seeked_to_connection;
197  core::ScopedConnection client_disconnected_connection;
198  core::ScopedConnection on_end_of_stream_connection;
200 
201  core::Signal<void> about_to_finish;
202  core::Signal<uint64_t> seeked_to;
203  core::Signal<void> client_disconnected;
204  core::Signal<void> end_of_stream;
205  core::Signal<media::Player::PlaybackStatus> playback_status_changed;
206  core::Signal<uint32_t, uint32_t> video_dimension_changed;
207 };
208 
210 {
211  cout << "Creating a new Engine instance in " << __PRETTY_FUNCTION__ << endl;
212  d->state = media::Engine::State::ready;
213 }
214 
216 {
217  stop();
218 }
219 
220 const std::shared_ptr<media::Engine::MetaDataExtractor>& gstreamer::Engine::meta_data_extractor() const
221 {
222  return d->meta_data_extractor;
223 }
224 
225 const core::Property<media::Engine::State>& gstreamer::Engine::state() const
226 {
227  return d->state;
228 }
229 
231 {
232  d->playbin.set_uri(uri);
233  return true;
234 }
235 
236 void gstreamer::Engine::create_video_sink(uint32_t texture_id)
237 {
238  d->playbin.create_video_sink(texture_id);
239 }
240 
242 {
243  auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);
244 
245  if (result)
246  {
247  d->state = media::Engine::State::playing;
248  cout << "play" << endl;
249  d->playback_status_changed(media::Player::PlaybackStatus::playing);
250  }
251 
252  return result;
253 }
254 
256 {
257  // No need to wait, and we can immediately return.
258  if (d->state == media::Engine::State::stopped)
259  return true;
260 
261  auto result = d->playbin.set_state_and_wait(GST_STATE_NULL);
262 
263  if (result)
264  {
265  d->state = media::Engine::State::stopped;
266  cout << "stop" << endl;
267  d->playback_status_changed(media::Player::PlaybackStatus::stopped);
268  }
269 
270  return result;
271 }
272 
274 {
275  auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);
276 
277  if (result)
278  {
279  d->state = media::Engine::State::paused;
280  cout << "pause" << endl;
281  d->playback_status_changed(media::Player::PlaybackStatus::paused);
282  }
283 
284  return result;
285 }
286 
287 bool gstreamer::Engine::seek_to(const std::chrono::microseconds& ts)
288 {
289  return d->playbin.seek(ts);
290 }
291 
292 const core::Property<bool>& gstreamer::Engine::is_video_source() const
293 {
294  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
295  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO)
296  d->is_video_source.set(true);
297  else
298  d->is_video_source.set(false);
299 
300  return d->is_video_source;
301 }
302 
303 const core::Property<bool>& gstreamer::Engine::is_audio_source() const
304 {
305  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
306  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO)
307  d->is_audio_source.set(true);
308  else
309  d->is_audio_source.set(false);
310 
311  return d->is_audio_source;
312 }
313 
314 const core::Property<uint64_t>& gstreamer::Engine::position() const
315 {
316  d->position.set(d->playbin.position());
317  return d->position;
318 }
319 
320 const core::Property<uint64_t>& gstreamer::Engine::duration() const
321 {
322  d->duration.set(d->playbin.duration());
323  return d->duration;
324 }
325 
326 const core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume() const
327 {
328  return d->volume;
329 }
330 
331 core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume()
332 {
333  return d->volume;
334 }
335 
336 const core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role() const
337 {
338  return d->audio_role;
339 }
340 
341 core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role()
342 {
343  return d->audio_role;
344 }
345 
346 const core::Property<core::ubuntu::media::Player::Orientation>& gstreamer::Engine::orientation() const
347 {
348  return d->orientation;
349 }
350 
351 const core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>>&
353 {
354  return d->track_meta_data;
355 }
356 
357 const core::Signal<void>& gstreamer::Engine::about_to_finish_signal() const
358 {
359  return d->about_to_finish;
360 }
361 
362 const core::Signal<uint64_t>& gstreamer::Engine::seeked_to_signal() const
363 {
364  return d->seeked_to;
365 }
366 
367 const core::Signal<void>& gstreamer::Engine::client_disconnected_signal() const
368 {
369  return d->client_disconnected;
370 }
371 
372 const core::Signal<void>& gstreamer::Engine::end_of_stream_signal() const
373 {
374  return d->end_of_stream;
375 }
376 
377 const core::Signal<media::Player::PlaybackStatus>& gstreamer::Engine::playback_status_changed_signal() const
378 {
379  return d->playback_status_changed;
380 }
381 
382 const core::Signal<uint32_t, uint32_t>& gstreamer::Engine::video_dimension_changed_signal() const
383 {
384  return d->video_dimension_changed;
385 }
386 
388 {
389  d->playbin.reset();
390 }
void on_tag_available(const gstreamer::Bus::Message::Detail::Tag &tag)
Definition: engine.cpp:58
core::ScopedConnection on_state_changed_connection
Definition: engine.cpp:191
bool open_resource_for_uri(const core::ubuntu::media::Track::UriType &uri)
core::ScopedConnection on_video_dimension_changed_connection
Definition: engine.cpp:199
const core::Property< core::ubuntu::media::Engine::Volume > & volume() const
Definition: engine.cpp:326
core::Property< bool > is_video_source
Definition: engine.cpp:187
const core::Signal< core::ubuntu::media::Player::PlaybackStatus > & playback_status_changed_signal() const
Definition: engine.cpp:377
const core::Property< core::ubuntu::media::Player::AudioStreamRole > & audio_stream_role() const
Definition: engine.cpp:336
const core::Property< bool > & is_video_source() const
Definition: engine.cpp:292
void on_video_dimension_changed(uint32_t height, uint32_t width)
Definition: engine.cpp:103
const core::Signal< void > & client_disconnected_signal() const
Definition: engine.cpp:367
core::Signal< void > end_of_stream
Definition: engine.cpp:204
Definition: bus.h:33
void on_seeked_to(uint64_t value)
Definition: engine.cpp:88
STL namespace.
const core::Property< State > & state() const
Definition: engine.cpp:225
core::ScopedConnection on_seeked_to_connection
Definition: engine.cpp:196
core::ScopedConnection on_end_of_stream_connection
Definition: engine.cpp:198
void on_orientation_changed(const media::Player::Orientation &o)
Definition: engine.cpp:75
gstreamer::Playbin playbin
Definition: engine.cpp:177
bool seek_to(const std::chrono::microseconds &ts)
Definition: engine.cpp:287
const core::Signal< uint64_t > & seeked_to_signal() const
Definition: engine.cpp:362
struct gstreamer::Init init
void create_video_sink(uint32_t texture_id)
Definition: engine.cpp:236
const core::Property< std::tuple< core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData > > & track_meta_data() const
Definition: engine.cpp:352
core::ScopedConnection client_disconnected_connection
Definition: engine.cpp:197
const core::Signal< uint32_t, uint32_t > & video_dimension_changed_signal() const
Definition: engine.cpp:382
const core::Property< bool > & is_audio_source() const
Definition: engine.cpp:303
void on_volume_changed(const media::Engine::Volume &new_volume)
Definition: engine.cpp:65
const core::Property< uint64_t > & duration() const
Definition: engine.cpp:320
core::ScopedConnection on_volume_changed_connection
Definition: engine.cpp:193
const core::Signal< void > & about_to_finish_signal() const
Definition: engine.cpp:357
core::Property< media::Player::Orientation > orientation
Definition: engine.cpp:186
core::Property< media::Player::AudioStreamRole > audio_role
Definition: engine.cpp:185
core::Signal< uint32_t, uint32_t > video_dimension_changed
Definition: engine.cpp:206
const core::Signal< void > & end_of_stream_signal() const
Definition: engine.cpp:372
core::Signal< void > client_disconnected
Definition: engine.cpp:203
core::Signal< uint64_t > seeked_to
Definition: engine.cpp:202
std::shared_ptr< Engine::MetaDataExtractor > meta_data_extractor
Definition: engine.cpp:179
void on_playbin_state_changed(const gstreamer::Bus::Message::Detail::StateChanged &state_change)
Definition: engine.cpp:52
static void on_tag_available(const gstreamer::Bus::Message::Detail::Tag &tag, core::ubuntu::media::Track::MetaData &md)
core::ScopedConnection on_tag_available_connection
Definition: engine.cpp:192
const std::shared_ptr< MetaDataExtractor > & meta_data_extractor() const
Definition: engine.cpp:220
core::Property< media::Engine::Volume > volume
Definition: engine.cpp:184
std::string UriType
Definition: track.h:40
core::ScopedConnection about_to_finish_connection
Definition: engine.cpp:190
core::Property< Engine::State > state
Definition: engine.cpp:180
const core::Property< core::ubuntu::media::Player::Orientation > & orientation() const
Definition: engine.cpp:346
core::Property< uint64_t > position
Definition: engine.cpp:182
core::Property< std::tuple< media::Track::UriType, media::Track::MetaData > > track_meta_data
Definition: engine.cpp:181
core::Signal< void > about_to_finish
Definition: engine.cpp:201
core::Signal< media::Player::PlaybackStatus > playback_status_changed
Definition: engine.cpp:205
const core::Property< uint64_t > & position() const
Definition: engine.cpp:314
core::ScopedConnection on_orientation_changed_connection
Definition: engine.cpp:195
void on_audio_stream_role_changed(const media::Player::AudioStreamRole &new_audio_role)
Definition: engine.cpp:70
core::Property< bool > is_audio_source
Definition: engine.cpp:188
core::Property< uint64_t > duration
Definition: engine.cpp:183
core::ScopedConnection on_audio_stream_role_changed_connection
Definition: engine.cpp:194