Imported mafw-gst-renderer_0.1.2009.47-1+0m5
[mafwsubrenderer] / libmafw-gst-renderer / mafw-gst-renderer-state-playing.c
1 /*
2  * This file is a part of MAFW
3  *
4  * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Visa Smolander <visa.smolander@nokia.com>
7  *
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.
12  *
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.
17  *
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
21  * 02110-1301 USA
22  *
23  */
24
25 #include "mafw-gst-renderer-state-playing.h"
26 #include "mafw-gst-renderer-utils.h"
27 #include <libmafw/mafw.h>
28
29 #undef  G_LOG_DOMAIN
30 #define G_LOG_DOMAIN "mafw-gst-renderer-state-playing"
31
32 /*----------------------------------------------------------------------------
33   Playback
34   ----------------------------------------------------------------------------*/
35
36 static void _do_play(MafwGstRendererState *self, GError **error);
37 static void _do_play_object(MafwGstRendererState *self, const gchar *object_id,
38                             GError **error);
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,
43                              GError **error);
44 static void _do_get_position(MafwGstRendererState *self,
45                              gint *seconds,
46                              GError **error);
47
48 /*----------------------------------------------------------------------------
49   Playlist
50   ----------------------------------------------------------------------------*/
51
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,
55                            GError **error);
56
57 /*----------------------------------------------------------------------------
58   Notification metatada
59   ----------------------------------------------------------------------------*/
60
61 static void _notify_metadata(MafwGstRendererState *self,
62                              const gchar *object_id,
63                              GHashTable *metadata,
64                              GError **error);
65
66 /*----------------------------------------------------------------------------
67   Notification worker
68   ----------------------------------------------------------------------------*/
69
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,
74                                   GError **error);
75 static void _notify_eos(MafwGstRendererState *self, GError **error);
76
77 /*----------------------------------------------------------------------------
78   Playlist editing signals
79   ----------------------------------------------------------------------------*/
80
81 static void _playlist_contents_changed(MafwGstRendererState *self,
82                                        gboolean clip_changed,
83                                        GError **error);
84
85 /*----------------------------------------------------------------------------
86   Property methods
87   ----------------------------------------------------------------------------*/
88
89 static GValue* _get_property_value(MafwGstRendererState *self,
90                                    const gchar *name);
91
92 /*----------------------------------------------------------------------------
93   Memory card event handlers
94   ----------------------------------------------------------------------------*/
95
96 static void _handle_pre_unmount(MafwGstRendererState *self,
97                                 const gchar *mount_point);
98
99 /*----------------------------------------------------------------------------
100   GObject initialization
101   ----------------------------------------------------------------------------*/
102
103 G_DEFINE_TYPE(MafwGstRendererStatePlaying, mafw_gst_renderer_state_playing,
104               MAFW_TYPE_GST_RENDERER_STATE);
105
106 static void mafw_gst_renderer_state_playing_init(MafwGstRendererStatePlaying *self)
107 {
108 }
109
110 static void mafw_gst_renderer_state_playing_class_init(
111         MafwGstRendererStatePlayingClass *klass)
112 {
113         MafwGstRendererStateClass *state_class;
114
115         state_class = MAFW_GST_RENDERER_STATE_CLASS(klass);
116         g_return_if_fail(state_class != NULL);
117
118         state_class->name = g_strdup("Playing");
119
120         /* Playback */
121
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;
129
130         /* Playlist */
131
132         state_class->next       = _do_next;
133         state_class->previous   = _do_previous;
134         state_class->goto_index = _do_goto_index;
135
136         /* Notification metadata */
137
138         state_class->notify_metadata = _notify_metadata;
139
140         /* Notification worker */
141
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;
147
148         /* Playlist editing signals */
149
150         state_class->playlist_contents_changed =
151                 _playlist_contents_changed;
152
153         /* Property methods */
154
155         state_class->get_property_value = _get_property_value;
156
157         /* Memory card event handlers */
158
159         state_class->handle_pre_unmount = _handle_pre_unmount;
160 }
161
162 GObject *mafw_gst_renderer_state_playing_new(MafwGstRenderer *renderer)
163 {
164         MafwGstRendererState *state;
165
166         state = MAFW_GST_RENDERER_STATE(
167                 g_object_new(MAFW_TYPE_GST_RENDERER_STATE_PLAYING, NULL));
168         state->renderer = renderer;
169
170         return G_OBJECT(state);
171 }
172
173 /*----------------------------------------------------------------------------
174   Playback
175   ----------------------------------------------------------------------------*/
176
177 static void _do_play(MafwGstRendererState *self, GError **error)
178 {
179         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
180         mafw_gst_renderer_state_do_play(self, error);
181 }
182
183 static void _do_play_object(MafwGstRendererState *self, const gchar *object_id,
184                             GError **error)
185 {
186         MafwGstRendererPlaybackMode cur_mode, prev_mode;
187
188         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
189
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);
193
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;
198         }
199 }
200
201 static void _do_stop(MafwGstRendererState *self, GError **error)
202 {
203         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
204
205         /* Stop playback */
206         mafw_gst_renderer_state_do_stop(self, error);
207 }
208
209 static void _do_pause(MafwGstRendererState *self, GError **error)
210 {
211         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
212
213         MafwGstRenderer *renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
214         mafw_gst_renderer_worker_pause(renderer->worker);
215
216         /* Transition will be done when receiving pause
217          * notification */
218 }
219
220 static void _do_set_position(MafwGstRendererState *self,
221                              MafwRendererSeekMode mode, gint seconds,
222                              GError **error)
223 {
224         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
225         mafw_gst_renderer_state_do_set_position(self, mode, seconds, error);
226 }
227
228 static void _do_get_position(MafwGstRendererState *self,
229                              gint *seconds,
230                              GError **error)
231 {
232         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
233         mafw_gst_renderer_state_do_get_position(self, seconds, error);
234 }
235
236
237 /*----------------------------------------------------------------------------
238   Playlist
239   ----------------------------------------------------------------------------*/
240
241 static void _do_next(MafwGstRendererState *self, GError **error)
242 {
243         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
244         mafw_gst_renderer_state_do_next(self, error);
245 }
246
247 static void _do_previous(MafwGstRendererState *self, GError **error)
248 {
249         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
250         mafw_gst_renderer_state_do_prev(self, error);
251 }
252
253 static void _do_goto_index(MafwGstRendererState *self, guint index,
254                            GError **error)
255 {
256         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
257         mafw_gst_renderer_state_do_goto_index(self, index, error);
258 }
259
260
261 /*----------------------------------------------------------------------------
262   Notification metatada
263   ----------------------------------------------------------------------------*/
264
265 static void _notify_metadata(MafwGstRendererState *self,
266                              const gchar *object_id,
267                              GHashTable *metadata,
268                              GError **error)
269 {
270         g_debug("running _notify_metadata...");
271         /* Kindly Ignore this notification:
272            probably a delayed (now useless) metadata resolution */
273 }
274
275
276 /*----------------------------------------------------------------------------
277   Notification worker
278   ----------------------------------------------------------------------------*/
279
280 static void _notify_play(MafwGstRendererState *self, GError **error)
281 {
282         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
283         /* Kindly ignore this notification: it's received when seeking
284          * in a stream */
285 }
286
287 static void _notify_pause(MafwGstRendererState *self, GError **error)
288 {
289         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
290
291         MafwGstRenderer *renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
292
293         /* Change status to pause */
294         mafw_gst_renderer_set_state(renderer, Paused);
295 }
296
297 static void _notify_seek(MafwGstRendererState *self, GError **error)
298 {
299         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
300         mafw_gst_renderer_state_do_notify_seek(self, error);
301 }
302
303 static void _notify_buffer_status(MafwGstRendererState *self, gdouble percent,
304                                   GError **error)
305 {
306         mafw_gst_renderer_state_do_notify_buffer_status (self, percent, error);
307 }
308
309 static void _notify_eos(MafwGstRendererState *self, GError **error)
310 {
311         MafwGstRenderer *renderer;
312         MafwGstRendererMovementResult move_type;
313         MafwGstRendererPlaybackMode mode;
314
315         renderer = MAFW_GST_RENDERER_STATE(self)->renderer;
316
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);
321         }
322
323         /* Notice: playback has already stopped, so calling
324          * mafw_gst_renderer_stop or mafw_gst_renderer_state_stop
325          * here is an error.
326          * To set the renderer state to Stopped use this instead:
327          * mafw_gst_renderer_set_state(self->renderer, Stopped);
328          */
329
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);
339
340                 /* Do we have to resume playlist playback? */
341                 if (renderer->resume_playlist) {
342                         mafw_gst_renderer_state_play(self, error);
343                 }
344         } else {
345                 /* Move to next in playlist */
346                 move_type =
347                         mafw_gst_renderer_move(renderer,
348                                               MAFW_GST_RENDERER_MOVE_TYPE_NEXT,
349                                               0, error);
350
351                 switch (move_type) {
352                 case MAFW_GST_RENDERER_MOVE_RESULT_OK:
353                         mafw_gst_renderer_state_play(self, error);
354                         break;
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);
359                         break;
360                 case MAFW_GST_RENDERER_MOVE_RESULT_ERROR:
361                         break;
362                 default:
363                         g_critical("Movement not controlled");
364                 }
365         }
366 }
367
368 /*----------------------------------------------------------------------------
369   Playlist editing signals
370   ----------------------------------------------------------------------------*/
371
372 static void _playlist_contents_changed(MafwGstRendererState *self,
373                                        gboolean clip_changed,
374                                        GError **error)
375 {
376         MafwGstRendererPlaybackMode mode;
377
378         g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self));
379
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);
386         }
387 }
388
389 /*----------------------------------------------------------------------------
390   Property methods
391   ----------------------------------------------------------------------------*/
392
393 GValue* _get_property_value(MafwGstRendererState *self, const gchar *name)
394 {
395         GValue *value = NULL;
396
397         g_return_val_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self), value);
398
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);
403
404                 value = g_new0(GValue, 1);
405                 g_value_init(value, G_TYPE_STRING);
406                 if (is_seekable) {
407                         g_value_set_string(value, "seek");
408                 } else {
409                         g_value_set_string(value, "");
410                 }
411         }
412
413         return value;
414 }
415
416 /*----------------------------------------------------------------------------
417   Memory card event handlers
418   ----------------------------------------------------------------------------*/
419
420 static void _handle_pre_unmount(MafwGstRendererState *self,
421                                 const gchar *mount_point)
422 {
423         gchar *mount_uri;
424
425         /* If not playing anything, bail out */
426         if (!self->renderer->media->uri) {
427                 return;
428         }
429
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);
433         } else {
434                 mount_uri = g_strdup(mount_point);
435         }
436
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),
440                                        NULL,
441                                        NULL);
442         }
443
444         g_free(mount_uri);
445 }