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
25 #include "mafw-gst-renderer-state-playing.h"
26 #include "mafw-gst-renderer-utils.h"
27 #include <libmafw/mafw.h>
30 #define G_LOG_DOMAIN "mafw-gst-renderer-state-playing"
32 /*----------------------------------------------------------------------------
34 ----------------------------------------------------------------------------*/
36 static void _do_play(MafwGstRendererState *self, GError **error);
37 static void _do_play_object(MafwGstRendererState *self, const gchar *object_id,
39 static void _do_stop(MafwGstRendererState *self, GError **error);
40 static void _do_pause(MafwGstRendererState *self, GError **error);
41 static void _do_set_position(MafwGstRendererState *self,
42 MafwRendererSeekMode mode, gint seconds,
44 static void _do_get_position(MafwGstRendererState *self,
48 /*----------------------------------------------------------------------------
50 ----------------------------------------------------------------------------*/
52 static void _do_next(MafwGstRendererState *self, GError **error);
53 static void _do_previous(MafwGstRendererState *self, GError **error);
54 static void _do_goto_index(MafwGstRendererState *self, guint index,
57 /*----------------------------------------------------------------------------
59 ----------------------------------------------------------------------------*/
61 static void _notify_metadata(MafwGstRendererState *self,
62 const gchar *object_id,
66 /*----------------------------------------------------------------------------
68 ----------------------------------------------------------------------------*/
70 static void _notify_play(MafwGstRendererState *self, GError **error);
71 static void _notify_pause(MafwGstRendererState *self, GError **error);
72 static void _notify_seek(MafwGstRendererState *self, GError **error);
73 static void _notify_buffer_status(MafwGstRendererState *self, gdouble percent,
75 static void _notify_eos(MafwGstRendererState *self, GError **error);
77 /*----------------------------------------------------------------------------
78 Playlist editing signals
79 ----------------------------------------------------------------------------*/
81 static void _playlist_contents_changed(MafwGstRendererState *self,
82 gboolean clip_changed,
85 /*----------------------------------------------------------------------------
87 ----------------------------------------------------------------------------*/
89 static GValue* _get_property_value(MafwGstRendererState *self,
92 /*----------------------------------------------------------------------------
93 Memory card event handlers
94 ----------------------------------------------------------------------------*/
96 static void _handle_pre_unmount(MafwGstRendererState *self,
97 const gchar *mount_point);
99 /*----------------------------------------------------------------------------
100 GObject initialization
101 ----------------------------------------------------------------------------*/
103 G_DEFINE_TYPE(MafwGstRendererStatePlaying, mafw_gst_renderer_state_playing,
104 MAFW_TYPE_GST_RENDERER_STATE);
106 static void mafw_gst_renderer_state_playing_init(MafwGstRendererStatePlaying *self)
110 static void mafw_gst_renderer_state_playing_class_init(
111 MafwGstRendererStatePlayingClass *klass)
113 MafwGstRendererStateClass *state_class;
115 state_class = MAFW_GST_RENDERER_STATE_CLASS(klass);
116 g_return_if_fail(state_class != NULL);
118 state_class->name = g_strdup("Playing");
122 state_class->play = _do_play;
123 state_class->play_object = _do_play_object;
124 state_class->stop = _do_stop;
125 state_class->pause = _do_pause;
126 /* state_class->resume is not allowed */
127 state_class->set_position = _do_set_position;
128 state_class->get_position = _do_get_position;
132 state_class->next = _do_next;
133 state_class->previous = _do_previous;
134 state_class->goto_index = _do_goto_index;
136 /* Notification metadata */
138 state_class->notify_metadata = _notify_metadata;
140 /* Notification worker */
142 state_class->notify_play = _notify_play;
143 state_class->notify_pause = _notify_pause;
144 state_class->notify_seek = _notify_seek;
145 state_class->notify_buffer_status = _notify_buffer_status;
146 state_class->notify_eos = _notify_eos;
148 /* Playlist editing signals */
150 state_class->playlist_contents_changed =
151 _playlist_contents_changed;
153 /* Property methods */
155 state_class->get_property_value = _get_property_value;
157 /* Memory card event handlers */
159 state_class->handle_pre_unmount = _handle_pre_unmount;
162 GObject *mafw_gst_renderer_state_playing_new(MafwGstRenderer *renderer)
164 MafwGstRendererState *state;
166 state = MAFW_GST_RENDERER_STATE(
167 g_object_new(MAFW_TYPE_GST_RENDERER_STATE_PLAYING, NULL));
168 state->renderer = renderer;
170 return G_OBJECT(state);
173 /*----------------------------------------------------------------------------
175 ----------------------------------------------------------------------------*/
177 static void _do_play(MafwGstRendererState *self, GError **error)
179 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
180 mafw_gst_renderer_state_do_play(self, error);
183 static void _do_play_object(MafwGstRendererState *self, const gchar *object_id,
186 MafwGstRendererPlaybackMode cur_mode, prev_mode;
188 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
190 prev_mode = mafw_gst_renderer_get_playback_mode(self->renderer);
191 mafw_gst_renderer_state_do_play_object(self, object_id, error);
192 cur_mode = mafw_gst_renderer_get_playback_mode(self->renderer);
194 /* If this happens it means that we interrupted playlist playback
195 so let's resume it when play_object is finished */
196 if (cur_mode != prev_mode) {
197 self->renderer->resume_playlist = TRUE;
201 static void _do_stop(MafwGstRendererState *self, GError **error)
203 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
206 mafw_gst_renderer_state_do_stop(self, error);
209 static void _do_pause(MafwGstRendererState *self, GError **error)
211 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
213 MafwGstRenderer *renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
214 mafw_gst_renderer_worker_pause(renderer->worker);
216 /* Transition will be done when receiving pause
220 static void _do_set_position(MafwGstRendererState *self,
221 MafwRendererSeekMode mode, gint seconds,
224 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
225 mafw_gst_renderer_state_do_set_position(self, mode, seconds, error);
228 static void _do_get_position(MafwGstRendererState *self,
232 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
233 mafw_gst_renderer_state_do_get_position(self, seconds, error);
237 /*----------------------------------------------------------------------------
239 ----------------------------------------------------------------------------*/
241 static void _do_next(MafwGstRendererState *self, GError **error)
243 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
244 mafw_gst_renderer_state_do_next(self, error);
247 static void _do_previous(MafwGstRendererState *self, GError **error)
249 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
250 mafw_gst_renderer_state_do_prev(self, error);
253 static void _do_goto_index(MafwGstRendererState *self, guint index,
256 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
257 mafw_gst_renderer_state_do_goto_index(self, index, error);
261 /*----------------------------------------------------------------------------
262 Notification metatada
263 ----------------------------------------------------------------------------*/
265 static void _notify_metadata(MafwGstRendererState *self,
266 const gchar *object_id,
267 GHashTable *metadata,
270 g_debug("running _notify_metadata...");
271 /* Kindly Ignore this notification:
272 probably a delayed (now useless) metadata resolution */
276 /*----------------------------------------------------------------------------
278 ----------------------------------------------------------------------------*/
280 static void _notify_play(MafwGstRendererState *self, GError **error)
282 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
283 /* Kindly ignore this notification: it's received when seeking
287 static void _notify_pause(MafwGstRendererState *self, GError **error)
289 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
291 MafwGstRenderer *renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
293 /* Change status to pause */
294 mafw_gst_renderer_set_state(renderer, Paused);
297 static void _notify_seek(MafwGstRendererState *self, GError **error)
299 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
300 mafw_gst_renderer_state_do_notify_seek(self, error);
303 static void _notify_buffer_status(MafwGstRendererState *self, gdouble percent,
306 mafw_gst_renderer_state_do_notify_buffer_status (self, percent, error);
309 static void _notify_eos(MafwGstRendererState *self, GError **error)
311 MafwGstRenderer *renderer;
312 MafwGstRendererMovementResult move_type;
313 MafwGstRendererPlaybackMode mode;
315 renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
317 /* Update playcount */
318 if (renderer->update_playcount_id > 0) {
319 g_source_remove(renderer->update_playcount_id);
320 mafw_gst_renderer_update_stats(renderer);
323 /* Notice: playback has already stopped, so calling
324 * mafw_gst_renderer_stop or mafw_gst_renderer_state_stop
326 * To set the renderer state to Stopped use this instead:
327 * mafw_gst_renderer_set_state(self->renderer, Stopped);
330 /* If we are not in playlist mode, switch to it,
331 otherwise move to the next in the playlist */
332 mode = mafw_gst_renderer_get_playback_mode(renderer);
333 if (mode == MAFW_GST_RENDERER_MODE_STANDALONE) {
334 mafw_gst_renderer_worker_stop(self->renderer->worker);
335 mafw_gst_renderer_set_state(self->renderer, Stopped);
336 mafw_gst_renderer_set_playback_mode(
337 renderer, MAFW_GST_RENDERER_MODE_PLAYLIST);
338 mafw_gst_renderer_set_media_playlist(renderer);
340 /* Do we have to resume playlist playback? */
341 if (renderer->resume_playlist) {
342 mafw_gst_renderer_state_play(self, error);
345 /* Move to next in playlist */
347 mafw_gst_renderer_move(renderer,
348 MAFW_GST_RENDERER_MOVE_TYPE_NEXT,
352 case MAFW_GST_RENDERER_MOVE_RESULT_OK:
353 mafw_gst_renderer_state_play(self, error);
355 case MAFW_GST_RENDERER_MOVE_RESULT_PLAYLIST_LIMIT:
356 case MAFW_GST_RENDERER_MOVE_RESULT_NO_PLAYLIST:
357 mafw_gst_renderer_worker_stop(self->renderer->worker);
358 mafw_gst_renderer_set_state(self->renderer, Stopped);
360 case MAFW_GST_RENDERER_MOVE_RESULT_ERROR:
363 g_critical("Movement not controlled");
368 /*----------------------------------------------------------------------------
369 Playlist editing signals
370 ----------------------------------------------------------------------------*/
372 static void _playlist_contents_changed(MafwGstRendererState *self,
373 gboolean clip_changed,
376 MafwGstRendererPlaybackMode mode;
378 g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
380 /* Play the new index only if we are not in standalone mode.
381 Otherwise, when play_object finishes the new item will be
382 played if that's been suggested with renderer->resume_playlist */
383 mode = mafw_gst_renderer_get_playback_mode(self->renderer);
384 if (clip_changed && mode == MAFW_GST_RENDERER_MODE_PLAYLIST) {
385 mafw_gst_renderer_state_do_play(self, error);
389 /*----------------------------------------------------------------------------
391 ----------------------------------------------------------------------------*/
393 GValue* _get_property_value(MafwGstRendererState *self, const gchar *name)
395 GValue *value = NULL;
397 g_return_val_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self), value);
399 if (!g_strcmp0(name, MAFW_PROPERTY_RENDERER_TRANSPORT_ACTIONS)) {
400 gboolean is_seekable =
401 mafw_gst_renderer_worker_get_seekable(
402 self->renderer->worker);
404 value = g_new0(GValue, 1);
405 g_value_init(value, G_TYPE_STRING);
407 g_value_set_string(value, "seek");
409 g_value_set_string(value, "");
416 /*----------------------------------------------------------------------------
417 Memory card event handlers
418 ----------------------------------------------------------------------------*/
420 static void _handle_pre_unmount(MafwGstRendererState *self,
421 const gchar *mount_point)
425 /* If not playing anything, bail out */
426 if (!self->renderer->media->uri) {
430 /* Check if mount point is URI or path, we need URI */
431 if (!g_str_has_prefix(mount_point, "file://")) {
432 mount_uri = g_filename_to_uri(mount_point, NULL, NULL);
434 mount_uri = g_strdup(mount_point);
437 /* Stop if playing from unmounted location */
438 if (g_str_has_prefix(self->renderer->media->uri, mount_uri)) {
439 mafw_gst_renderer_stop(MAFW_RENDERER(self->renderer),