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  state = Engine::State::ready;
78  about_to_finish();
79  }
80 
81  void on_seeked_to(uint64_t value)
82  {
83  seeked_to(value);
84  }
85 
87  {
88  client_disconnected();
89  }
90 
92  {
93  end_of_stream();
94  }
95 
97  : meta_data_extractor(new gstreamer::MetaDataExtractor()),
98  volume(media::Engine::Volume(1.)),
99  is_video_source(false),
100  is_audio_source(false),
101  about_to_finish_connection(
102  playbin.signals.about_to_finish.connect(
103  std::bind(
104  &Private::on_about_to_finish,
105  this))),
106  on_state_changed_connection(
107  playbin.signals.on_state_changed.connect(
108  std::bind(
109  &Private::on_playbin_state_changed,
110  this,
111  std::placeholders::_1))),
112  on_tag_available_connection(
113  playbin.signals.on_tag_available.connect(
114  std::bind(
115  &Private::on_tag_available,
116  this,
117  std::placeholders::_1))),
118  on_volume_changed_connection(
119  volume.changed().connect(
120  std::bind(
121  &Private::on_volume_changed,
122  this,
123  std::placeholders::_1))),
124  on_audio_stream_role_changed_connection(
125  audio_role.changed().connect(
126  std::bind(
127  &Private::on_audio_stream_role_changed,
128  this,
129  std::placeholders::_1))),
130  on_seeked_to_connection(
131  playbin.signals.on_seeked_to.connect(
132  std::bind(
133  &Private::on_seeked_to,
134  this,
135  std::placeholders::_1))),
136  client_disconnected_connection(
137  playbin.signals.client_disconnected.connect(
138  std::bind(
139  &Private::on_client_disconnected,
140  this))),
141  on_end_of_stream_connection(
142  playbin.signals.on_end_of_stream.connect(
143  std::bind(
144  &Private::on_end_of_stream,
145  this)))
146  {
147  }
148 
149  // Ensure the playbin is the last item destroyed
150  // otherwise properties could try to access a dead playbin object
152 
153  std::shared_ptr<Engine::MetaDataExtractor> meta_data_extractor;
154  core::Property<Engine::State> state;
155  core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>> track_meta_data;
156  core::Property<uint64_t> position;
157  core::Property<uint64_t> duration;
158  core::Property<media::Engine::Volume> volume;
159  core::Property<media::Player::AudioStreamRole> audio_role;
160  core::Property<bool> is_video_source;
161  core::Property<bool> is_audio_source;
162 
163  core::ScopedConnection about_to_finish_connection;
164  core::ScopedConnection on_state_changed_connection;
165  core::ScopedConnection on_tag_available_connection;
166  core::ScopedConnection on_volume_changed_connection;
168  core::ScopedConnection on_seeked_to_connection;
169  core::ScopedConnection client_disconnected_connection;
170  core::ScopedConnection on_end_of_stream_connection;
171 
172  core::Signal<void> about_to_finish;
173  core::Signal<uint64_t> seeked_to;
174  core::Signal<void> client_disconnected;
175  core::Signal<void> end_of_stream;
176  core::Signal<media::Player::PlaybackStatus> playback_status_changed;
177 };
178 
180 {
181  cout << "Creating a new Engine instance in " << __PRETTY_FUNCTION__ << endl;
182  d->state = media::Engine::State::ready;
183 }
184 
186 {
187  stop();
188 }
189 
190 const std::shared_ptr<media::Engine::MetaDataExtractor>& gstreamer::Engine::meta_data_extractor() const
191 {
192  return d->meta_data_extractor;
193 }
194 
195 const core::Property<media::Engine::State>& gstreamer::Engine::state() const
196 {
197  return d->state;
198 }
199 
201 {
202  d->playbin.set_uri(uri);
203  return true;
204 }
205 
206 void gstreamer::Engine::create_video_sink(uint32_t texture_id)
207 {
208  d->playbin.create_video_sink(texture_id);
209 }
210 
212 {
213  auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);
214 
215  if (result)
216  {
217  d->state = media::Engine::State::playing;
218  cout << "play" << endl;
219  d->playback_status_changed(media::Player::PlaybackStatus::playing);
220  }
221 
222  return result;
223 }
224 
226 {
227  // No need to wait, and we can immediately return.
228  if (d->state == media::Engine::State::stopped)
229  return true;
230 
231  auto result = d->playbin.set_state_and_wait(GST_STATE_NULL);
232 
233  if (result)
234  {
235  d->state = media::Engine::State::stopped;
236  cout << "stop" << endl;
237  d->playback_status_changed(media::Player::PlaybackStatus::stopped);
238  }
239 
240  return result;
241 }
242 
244 {
245  auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);
246 
247  if (result)
248  {
249  d->state = media::Engine::State::paused;
250  cout << "pause" << endl;
251  d->playback_status_changed(media::Player::PlaybackStatus::paused);
252  }
253 
254  return result;
255 }
256 
257 bool gstreamer::Engine::seek_to(const std::chrono::microseconds& ts)
258 {
259  return d->playbin.seek(ts);
260 }
261 
262 const core::Property<bool>& gstreamer::Engine::is_video_source() const
263 {
264  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
265  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO)
266  d->is_video_source.set(true);
267  else
268  d->is_video_source.set(false);
269 
270  return d->is_video_source;
271 }
272 
273 const core::Property<bool>& gstreamer::Engine::is_audio_source() const
274 {
275  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
276  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO)
277  d->is_audio_source.set(true);
278  else
279  d->is_audio_source.set(false);
280 
281  return d->is_audio_source;
282 }
283 
284 const core::Property<uint64_t>& gstreamer::Engine::position() const
285 {
286  d->position.set(d->playbin.position());
287  return d->position;
288 }
289 
290 const core::Property<uint64_t>& gstreamer::Engine::duration() const
291 {
292  d->duration.set(d->playbin.duration());
293  return d->duration;
294 }
295 
296 const core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume() const
297 {
298  return d->volume;
299 }
300 
301 core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume()
302 {
303  return d->volume;
304 }
305 
306 const core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role() const
307 {
308  return d->audio_role;
309 }
310 
311 core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role()
312 {
313  return d->audio_role;
314 }
315 
316 const core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>>&
318 {
319  return d->track_meta_data;
320 }
321 
322 const core::Signal<void>& gstreamer::Engine::about_to_finish_signal() const
323 {
324  return d->about_to_finish;
325 }
326 
327 const core::Signal<uint64_t>& gstreamer::Engine::seeked_to_signal() const
328 {
329  return d->seeked_to;
330 }
331 
332 const core::Signal<void>& gstreamer::Engine::client_disconnected_signal() const
333 {
334  return d->client_disconnected;
335 }
336 
337 const core::Signal<void>& gstreamer::Engine::end_of_stream_signal() const
338 {
339  return d->end_of_stream;
340 }
341 
342 const core::Signal<media::Player::PlaybackStatus>& gstreamer::Engine::playback_status_changed_signal() const
343 {
344  return d->playback_status_changed;
345 }
void on_tag_available(const gstreamer::Bus::Message::Detail::Tag &tag)
Definition: engine.cpp:58
core::ScopedConnection on_state_changed_connection
Definition: engine.cpp:164
bool open_resource_for_uri(const core::ubuntu::media::Track::UriType &uri)
const core::Property< core::ubuntu::media::Engine::Volume > & volume() const
Definition: engine.cpp:296
core::Property< bool > is_video_source
Definition: engine.cpp:160
const core::Signal< core::ubuntu::media::Player::PlaybackStatus > & playback_status_changed_signal() const
Definition: engine.cpp:342
const core::Property< core::ubuntu::media::Player::AudioStreamRole > & audio_stream_role() const
Definition: engine.cpp:306
const core::Property< bool > & is_video_source() const
Definition: engine.cpp:262
const core::Signal< void > & client_disconnected_signal() const
Definition: engine.cpp:332
core::Signal< void > end_of_stream
Definition: engine.cpp:175
Definition: bus.h:33
void on_seeked_to(uint64_t value)
Definition: engine.cpp:81
STL namespace.
const core::Property< State > & state() const
Definition: engine.cpp:195
core::ScopedConnection on_seeked_to_connection
Definition: engine.cpp:168
core::ScopedConnection on_end_of_stream_connection
Definition: engine.cpp:170
gstreamer::Playbin playbin
Definition: engine.cpp:151
bool seek_to(const std::chrono::microseconds &ts)
Definition: engine.cpp:257
const core::Signal< uint64_t > & seeked_to_signal() const
Definition: engine.cpp:327
struct gstreamer::Init init
void create_video_sink(uint32_t texture_id)
Definition: engine.cpp:206
const core::Property< std::tuple< core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData > > & track_meta_data() const
Definition: engine.cpp:317
core::ScopedConnection client_disconnected_connection
Definition: engine.cpp:169
const core::Property< bool > & is_audio_source() const
Definition: engine.cpp:273
void on_volume_changed(const media::Engine::Volume &new_volume)
Definition: engine.cpp:65
const core::Property< uint64_t > & duration() const
Definition: engine.cpp:290
core::ScopedConnection on_volume_changed_connection
Definition: engine.cpp:166
const core::Signal< void > & about_to_finish_signal() const
Definition: engine.cpp:322
core::Property< media::Player::AudioStreamRole > audio_role
Definition: engine.cpp:159
const core::Signal< void > & end_of_stream_signal() const
Definition: engine.cpp:337
core::Signal< void > client_disconnected
Definition: engine.cpp:174
core::Signal< uint64_t > seeked_to
Definition: engine.cpp:173
std::shared_ptr< Engine::MetaDataExtractor > meta_data_extractor
Definition: engine.cpp:153
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:165
const std::shared_ptr< MetaDataExtractor > & meta_data_extractor() const
Definition: engine.cpp:190
core::Property< media::Engine::Volume > volume
Definition: engine.cpp:158
std::string UriType
Definition: track.h:40
core::ScopedConnection about_to_finish_connection
Definition: engine.cpp:163
core::Property< Engine::State > state
Definition: engine.cpp:154
core::Property< uint64_t > position
Definition: engine.cpp:156
core::Property< std::tuple< media::Track::UriType, media::Track::MetaData > > track_meta_data
Definition: engine.cpp:155
core::Signal< void > about_to_finish
Definition: engine.cpp:172
core::Signal< media::Player::PlaybackStatus > playback_status_changed
Definition: engine.cpp:176
const core::Property< uint64_t > & position() const
Definition: engine.cpp:284
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:161
core::Property< uint64_t > duration
Definition: engine.cpp:157
core::ScopedConnection on_audio_stream_role_changed_connection
Definition: engine.cpp:167