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  std::shared_ptr<Engine::MetaDataExtractor> meta_data_extractor;
150  core::Property<Engine::State> state;
151  core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>> track_meta_data;
152  core::Property<uint64_t> position;
153  core::Property<uint64_t> duration;
154  core::Property<media::Engine::Volume> volume;
155  core::Property<media::Player::AudioStreamRole> audio_role;
156  core::Property<bool> is_video_source;
157  core::Property<bool> is_audio_source;
159  core::ScopedConnection about_to_finish_connection;
160  core::ScopedConnection on_state_changed_connection;
161  core::ScopedConnection on_tag_available_connection;
162  core::ScopedConnection on_volume_changed_connection;
164  core::ScopedConnection on_seeked_to_connection;
165  core::ScopedConnection client_disconnected_connection;
166  core::ScopedConnection on_end_of_stream_connection;
167 
168  core::Signal<void> about_to_finish;
169  core::Signal<uint64_t> seeked_to;
170  core::Signal<void> client_disconnected;
171  core::Signal<void> end_of_stream;
172  core::Signal<media::Player::PlaybackStatus> playback_status_changed;
173 };
174 
176 {
177  cout << "Creating a new Engine instance in " << __PRETTY_FUNCTION__ << endl;
178  d->state = media::Engine::State::ready;
179 }
180 
182 {
183  stop();
184 }
185 
186 const std::shared_ptr<media::Engine::MetaDataExtractor>& gstreamer::Engine::meta_data_extractor() const
187 {
188  return d->meta_data_extractor;
189 }
190 
191 const core::Property<media::Engine::State>& gstreamer::Engine::state() const
192 {
193  return d->state;
194 }
195 
197 {
198  d->playbin.set_uri(uri);
199  return true;
200 }
201 
202 void gstreamer::Engine::create_video_sink(uint32_t texture_id)
203 {
204  d->playbin.create_video_sink(texture_id);
205 }
206 
208 {
209  auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);
210 
211  if (result)
212  {
213  d->state = media::Engine::State::playing;
214  cout << "play" << endl;
215  d->playback_status_changed(media::Player::PlaybackStatus::playing);
216  }
217 
218  return result;
219 }
220 
222 {
223  // No need to wait, and we can immediately return.
224  if (d->state == media::Engine::State::stopped)
225  return true;
226 
227  auto result = d->playbin.set_state_and_wait(GST_STATE_NULL);
228 
229  if (result)
230  {
231  d->state = media::Engine::State::stopped;
232  cout << "stop" << endl;
233  d->playback_status_changed(media::Player::PlaybackStatus::stopped);
234  }
235 
236  return result;
237 }
238 
240 {
241  auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);
242 
243  if (result)
244  {
245  d->state = media::Engine::State::paused;
246  cout << "pause" << endl;
247  d->playback_status_changed(media::Player::PlaybackStatus::paused);
248  }
249 
250  return result;
251 }
252 
253 bool gstreamer::Engine::seek_to(const std::chrono::microseconds& ts)
254 {
255  return d->playbin.seek(ts);
256 }
257 
258 const core::Property<bool>& gstreamer::Engine::is_video_source() const
259 {
260  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
261  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO)
262  d->is_video_source.set(true);
263  else
264  d->is_video_source.set(false);
265 
266  return d->is_video_source;
267 }
268 
269 const core::Property<bool>& gstreamer::Engine::is_audio_source() const
270 {
271  gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
272  if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO)
273  d->is_audio_source.set(true);
274  else
275  d->is_audio_source.set(false);
276 
277  return d->is_audio_source;
278 }
279 
280 const core::Property<uint64_t>& gstreamer::Engine::position() const
281 {
282  d->position.set(d->playbin.position());
283  return d->position;
284 }
285 
286 const core::Property<uint64_t>& gstreamer::Engine::duration() const
287 {
288  d->duration.set(d->playbin.duration());
289  return d->duration;
290 }
291 
292 const core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume() const
293 {
294  return d->volume;
295 }
296 
297 core::Property<core::ubuntu::media::Engine::Volume>& gstreamer::Engine::volume()
298 {
299  return d->volume;
300 }
301 
302 const core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role() const
303 {
304  return d->audio_role;
305 }
306 
307 core::Property<core::ubuntu::media::Player::AudioStreamRole>& gstreamer::Engine::audio_stream_role()
308 {
309  return d->audio_role;
310 }
311 
312 const core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>>&
314 {
315  return d->track_meta_data;
316 }
317 
318 const core::Signal<void>& gstreamer::Engine::about_to_finish_signal() const
319 {
320  return d->about_to_finish;
321 }
322 
323 const core::Signal<uint64_t>& gstreamer::Engine::seeked_to_signal() const
324 {
325  return d->seeked_to;
326 }
327 
328 const core::Signal<void>& gstreamer::Engine::client_disconnected_signal() const
329 {
330  return d->client_disconnected;
331 }
332 
333 const core::Signal<void>& gstreamer::Engine::end_of_stream_signal() const
334 {
335  return d->end_of_stream;
336 }
337 
338 const core::Signal<media::Player::PlaybackStatus>& gstreamer::Engine::playback_status_changed_signal() const
339 {
340  return d->playback_status_changed;
341 }
void on_tag_available(const gstreamer::Bus::Message::Detail::Tag &tag)
Definition: engine.cpp:58
core::ScopedConnection on_state_changed_connection
Definition: engine.cpp:160
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:292
core::Property< bool > is_video_source
Definition: engine.cpp:156
const core::Signal< core::ubuntu::media::Player::PlaybackStatus > & playback_status_changed_signal() const
Definition: engine.cpp:338
const core::Property< core::ubuntu::media::Player::AudioStreamRole > & audio_stream_role() const
Definition: engine.cpp:302
const core::Property< bool > & is_video_source() const
Definition: engine.cpp:258
const core::Signal< void > & client_disconnected_signal() const
Definition: engine.cpp:328
core::Signal< void > end_of_stream
Definition: engine.cpp:171
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:191
core::ScopedConnection on_seeked_to_connection
Definition: engine.cpp:164
core::ScopedConnection on_end_of_stream_connection
Definition: engine.cpp:166
gstreamer::Playbin playbin
Definition: engine.cpp:158
bool seek_to(const std::chrono::microseconds &ts)
Definition: engine.cpp:253
const core::Signal< uint64_t > & seeked_to_signal() const
Definition: engine.cpp:323
struct gstreamer::Init init
void create_video_sink(uint32_t texture_id)
Definition: engine.cpp:202
const core::Property< std::tuple< core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData > > & track_meta_data() const
Definition: engine.cpp:313
core::ScopedConnection client_disconnected_connection
Definition: engine.cpp:165
const core::Property< bool > & is_audio_source() const
Definition: engine.cpp:269
void on_volume_changed(const media::Engine::Volume &new_volume)
Definition: engine.cpp:65
const core::Property< uint64_t > & duration() const
Definition: engine.cpp:286
core::ScopedConnection on_volume_changed_connection
Definition: engine.cpp:162
const core::Signal< void > & about_to_finish_signal() const
Definition: engine.cpp:318
core::Property< media::Player::AudioStreamRole > audio_role
Definition: engine.cpp:155
const core::Signal< void > & end_of_stream_signal() const
Definition: engine.cpp:333
core::Signal< void > client_disconnected
Definition: engine.cpp:170
core::Signal< uint64_t > seeked_to
Definition: engine.cpp:169
std::shared_ptr< Engine::MetaDataExtractor > meta_data_extractor
Definition: engine.cpp:149
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:161
const std::shared_ptr< MetaDataExtractor > & meta_data_extractor() const
Definition: engine.cpp:186
core::Property< media::Engine::Volume > volume
Definition: engine.cpp:154
std::string UriType
Definition: track.h:40
core::ScopedConnection about_to_finish_connection
Definition: engine.cpp:159
core::Property< Engine::State > state
Definition: engine.cpp:150
core::Property< uint64_t > position
Definition: engine.cpp:152
core::Property< std::tuple< media::Track::UriType, media::Track::MetaData > > track_meta_data
Definition: engine.cpp:151
core::Signal< void > about_to_finish
Definition: engine.cpp:168
core::Signal< media::Player::PlaybackStatus > playback_status_changed
Definition: engine.cpp:172
const core::Property< uint64_t > & position() const
Definition: engine.cpp:280
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:157
core::Property< uint64_t > duration
Definition: engine.cpp:153
core::ScopedConnection on_audio_stream_role_changed_connection
Definition: engine.cpp:163