2 * This file is a part of MAFW
4 * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
6 * Contact: Visa Smolander <visa.smolander@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 #include "mafw-gst-renderer-state-transitioning.h"
29 #define G_LOG_DOMAIN "mafw-gst-renderer-state-transitioning"
31 #define UPDATE_DELAY 10
33 /*----------------------------------------------------------------------------
35 ----------------------------------------------------------------------------*/
37 static void _do_play(MafwGstRendererState *self, GError **error);
38 static void _do_play_object(MafwGstRendererState *self, const gchar *object_id,
40 static void _do_pause(MafwGstRendererState *self, GError **error);
41 static void _do_stop(MafwGstRendererState *self, GError **error);
42 static void _do_resume(MafwGstRendererState *self, GError **error);
43 static void _do_get_position(MafwGstRendererState *self, gint *seconds,
46 /*----------------------------------------------------------------------------
48 ----------------------------------------------------------------------------*/
50 static void _do_next(MafwGstRendererState *self, GError **error);
51 static void _do_previous(MafwGstRendererState *self,GError **error);
52 static void _do_goto_index(MafwGstRendererState *self, guint index,
55 /*----------------------------------------------------------------------------
57 ----------------------------------------------------------------------------*/
59 static void _notify_metadata(MafwGstRendererState *self,
60 const gchar *object_id,
64 /*----------------------------------------------------------------------------
66 ----------------------------------------------------------------------------*/
68 static void _notify_play(MafwGstRendererState *self, GError **error);
69 static void _notify_pause(MafwGstRendererState *self,GError **error);
71 static void _notify_buffer_status(MafwGstRendererState *self,
75 /*----------------------------------------------------------------------------
76 Playlist editing signals
77 ----------------------------------------------------------------------------*/
79 static void _playlist_contents_changed(MafwGstRendererState *self,
80 gboolean clip_changed,
83 /*----------------------------------------------------------------------------
85 ----------------------------------------------------------------------------*/
87 static GValue* _get_property_value(MafwGstRendererState *self,
90 /*----------------------------------------------------------------------------
91 GObject initialization
92 ----------------------------------------------------------------------------*/
94 G_DEFINE_TYPE(MafwGstRendererStateTransitioning,
95 mafw_gst_renderer_state_transitioning,
96 MAFW_TYPE_GST_RENDERER_STATE);
98 static void mafw_gst_renderer_state_transitioning_init(
99 MafwGstRendererStateTransitioning *self)
103 static void mafw_gst_renderer_state_transitioning_class_init(
104 MafwGstRendererStateTransitioningClass *klass)
106 MafwGstRendererStateClass *state_klass ;
108 state_klass = MAFW_GST_RENDERER_STATE_CLASS(klass);
109 g_return_if_fail(state_klass != NULL);
111 state_klass->name = g_strdup("Transitioning");
115 state_klass->play = _do_play;
116 state_klass->play_object = _do_play_object;
117 state_klass->stop = _do_stop;
118 state_klass->pause = _do_pause;
119 state_klass->resume = _do_resume;
120 state_klass->get_position = _do_get_position;
124 state_klass->next = _do_next;
125 state_klass->previous = _do_previous;
126 state_klass->goto_index = _do_goto_index;
130 state_klass->notify_metadata = _notify_metadata;
132 /* Notification worker */
134 state_klass->notify_play = _notify_play;
135 state_klass->notify_pause = _notify_pause;
136 state_klass->notify_buffer_status = _notify_buffer_status;
138 /* Playlist editing signals */
140 state_klass->playlist_contents_changed =
141 _playlist_contents_changed;
143 /* Property methods */
145 state_klass->get_property_value = _get_property_value;
148 GObject *mafw_gst_renderer_state_transitioning_new(MafwGstRenderer *renderer)
150 MafwGstRendererState *state;
152 state = MAFW_GST_RENDERER_STATE(
153 g_object_new(MAFW_TYPE_GST_RENDERER_STATE_TRANSITIONING, NULL));
154 state->renderer = renderer;
156 return G_OBJECT(state);
159 /*----------------------------------------------------------------------------
161 ----------------------------------------------------------------------------*/
163 static void _do_play(MafwGstRendererState *self, GError **error)
165 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
166 mafw_gst_renderer_state_do_play(self, error);
169 static void _do_play_object(MafwGstRendererState *self, const gchar *object_id,
172 MafwGstRendererPlaybackMode cur_mode, prev_mode;
174 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
176 prev_mode = mafw_gst_renderer_get_playback_mode(self->renderer);
177 mafw_gst_renderer_state_do_play_object(self, object_id, error);
178 cur_mode = mafw_gst_renderer_get_playback_mode(self->renderer);
180 /* If this happens it means that we interrupted playlist playback
181 so let's resume it when play_object is finished */
182 if (cur_mode != prev_mode) {
183 self->renderer->resume_playlist = TRUE;
187 static void _do_stop(MafwGstRendererState *self, GError **error)
189 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
192 mafw_gst_renderer_state_do_stop(self, error);
195 static void _do_pause(MafwGstRendererState *self, GError **error)
197 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
198 g_debug("Got pause while transitioning");
199 self->renderer->worker->stay_paused = TRUE;
202 static void _do_resume(MafwGstRendererState *self, GError **error)
204 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
205 if (self->renderer->worker->stay_paused) {
206 g_debug("Got resume while transitioning/paused");
207 self->renderer->worker->stay_paused = FALSE;
209 g_set_error(error, MAFW_RENDERER_ERROR,
210 MAFW_RENDERER_ERROR_CANNOT_PLAY,
211 "cannot resume in transitioning state without "
212 "having paused before");
216 static void _do_get_position(MafwGstRendererState *self, gint *seconds,
222 /*----------------------------------------------------------------------------
224 ----------------------------------------------------------------------------*/
226 static void _do_next(MafwGstRendererState *self, GError **error)
228 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
229 mafw_gst_renderer_state_do_next(self, error);
232 static void _do_previous(MafwGstRendererState *self, GError **error)
234 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
235 mafw_gst_renderer_state_do_prev(self, error);
238 static void _do_goto_index(MafwGstRendererState *self, guint index,
241 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
242 mafw_gst_renderer_state_do_goto_index(self, index, error);
245 /*----------------------------------------------------------------------------
246 Notification metatada
247 ----------------------------------------------------------------------------*/
249 static void _notify_metadata(MafwGstRendererState *self,
250 const gchar *object_id,
251 GHashTable *metadata,
254 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
256 MafwGstRenderer *renderer;
263 g_debug("running _notify_metadata...");
265 renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
267 /* If we have received metadata for the item that we are playing
269 if (object_id && renderer->media->object_id &&
270 !strcmp(object_id, renderer->media->object_id)) {
271 /* Check how many uris provide the object_id */
272 value = g_hash_table_lookup(metadata, MAFW_METADATA_KEY_URI);
273 nuris = mafw_metadata_nvalues(value);
275 mval = mafw_metadata_first(metadata,
276 MAFW_METADATA_KEY_URI);
278 g_free(renderer->media->uri);
279 renderer->media->uri =
280 g_strdup(g_value_get_string(mval));
281 uri = renderer->media->uri;
282 } else if (nuris > 1) {
283 uris = g_new0(gchar *, nuris + 1);
284 for (i = 0; i < nuris; i++) {
285 mval = g_value_array_get_nth(value, i);
286 uris[i] = (gchar *) g_value_get_string(mval);
289 /* Try the first URI, if that fails to play back another
290 * one will be selected until we get a successful one or
291 * all failed. On success, the selected URI will be
292 * emitted as metadata */
293 g_free(renderer->media->uri);
294 renderer->media->uri = g_strdup(uris[0]);
296 g_assert_not_reached();
299 /* Set seekability property; currently, if several uris are
300 * provided it uses the value of the first uri. If later another
301 * uri is actually played, then this value should be changed. */
302 mval = mafw_metadata_first(metadata,
303 MAFW_METADATA_KEY_IS_SEEKABLE);
305 renderer->media->seekability =
306 g_value_get_boolean(mval) ?
307 SEEKABILITY_SEEKABLE : SEEKABILITY_NO_SEEKABLE;
308 g_debug("_notify_metadata: source seekability %d",
309 renderer->media->seekability);
311 renderer->media->seekability = SEEKABILITY_UNKNOWN;
312 g_debug("_notify_metadata: source seekability unknown");
315 /* Check for source duration to keep it updated if needed */
316 mval = mafw_metadata_first(metadata,
317 MAFW_METADATA_KEY_DURATION);
320 renderer->media->duration = g_value_get_int(mval);
321 g_debug("_notify_metadata: source duration %d",
322 renderer->media->duration);
324 renderer->media->duration = -1;
325 g_debug("_notify_metadata: source duration unknown");
328 /* Play the available uri(s) */
330 mafw_gst_renderer_worker_play(renderer->worker, uri, NULL);
332 mafw_gst_renderer_worker_play_alternatives(
333 renderer->worker, uris);
339 /*----------------------------------------------------------------------------
341 ----------------------------------------------------------------------------*/
343 static void _notify_play(MafwGstRendererState *self, GError **error)
345 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
347 MafwGstRenderer *renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
349 if (renderer->media->object_id)
351 renderer->update_playcount_id = g_timeout_add_seconds(
353 mafw_gst_renderer_update_stats,
357 mafw_gst_renderer_set_state(renderer, Playing);
360 static void _notify_pause(MafwGstRendererState *self, GError **error)
362 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
364 MafwGstRenderer *renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
365 self->renderer->worker->stay_paused = FALSE;
366 mafw_gst_renderer_set_state(renderer, Paused);
369 static void _notify_buffer_status(MafwGstRendererState *self, gdouble percent,
372 mafw_gst_renderer_state_do_notify_buffer_status (self, percent, error);
375 /*----------------------------------------------------------------------------
376 Playlist editing signals
377 ----------------------------------------------------------------------------*/
379 static void _playlist_contents_changed(MafwGstRendererState *self,
380 gboolean clip_changed,
383 MafwGstRendererPlaybackMode mode;
385 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self));
387 /* Play the new index only if we are not in standalone mode.
388 Otherwise, when play_object finishes the new item will be
389 played if that's been suggested with renderer->resume_playlist */
390 mode = mafw_gst_renderer_get_playback_mode(self->renderer);
391 if (clip_changed && mode == MAFW_GST_RENDERER_MODE_PLAYLIST) {
392 mafw_gst_renderer_state_do_play(self, error);
396 /*----------------------------------------------------------------------------
398 ----------------------------------------------------------------------------*/
400 GValue* _get_property_value(MafwGstRendererState *self, const gchar *name)
402 GValue *value = NULL;
404 g_return_val_if_fail(MAFW_IS_GST_RENDERER_STATE_TRANSITIONING(self),
407 if (!g_strcmp0(name, MAFW_PROPERTY_RENDERER_TRANSPORT_ACTIONS)) {
408 value = g_new0(GValue, 1);
409 g_value_init(value, G_TYPE_STRING);
410 g_value_set_string(value, "");