X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=mafw-gst-subtitles-renderer%2Flibmafw-gst-renderer%2Fmafw-gst-renderer-state-playing.c;fp=mafw-gst-subtitles-renderer%2Flibmafw-gst-renderer%2Fmafw-gst-renderer-state-playing.c;h=ccb9ecc06f5225b5fb202fc1e5974a2b34cdd626;hb=be2c98fb83895d10ac44af7b9a9c3e00ca54bf49;hp=0000000000000000000000000000000000000000;hpb=c2bbb2bb3bead80144e2dda3ccd40599e4a2b48d;p=mafwsubrenderer diff --git a/mafw-gst-subtitles-renderer/libmafw-gst-renderer/mafw-gst-renderer-state-playing.c b/mafw-gst-subtitles-renderer/libmafw-gst-renderer/mafw-gst-renderer-state-playing.c new file mode 100644 index 0000000..ccb9ecc --- /dev/null +++ b/mafw-gst-subtitles-renderer/libmafw-gst-renderer/mafw-gst-renderer-state-playing.c @@ -0,0 +1,465 @@ +/* + * This file is a part of MAFW + * + * Copyright (C) 2007, 2008, 2009 Nokia Corporation, all rights reserved. + * + * Contact: Visa Smolander + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include "mafw-gst-renderer-state-playing.h" +#include "mafw-gst-renderer-utils.h" +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "mafw-gst-renderer-state-playing" + +/*---------------------------------------------------------------------------- + Playback + ----------------------------------------------------------------------------*/ + +static void _do_play(MafwGstRendererState *self, GError **error); +static void _do_play_object(MafwGstRendererState *self, const gchar *object_id, + GError **error); +static void _do_stop(MafwGstRendererState *self, GError **error); +static void _do_pause(MafwGstRendererState *self, GError **error); +static void _do_set_position(MafwGstRendererState *self, + MafwRendererSeekMode mode, gint seconds, + GError **error); +static void _do_get_position(MafwGstRendererState *self, + gint *seconds, + GError **error); + +/*---------------------------------------------------------------------------- + Playlist + ----------------------------------------------------------------------------*/ + +static void _do_next(MafwGstRendererState *self, GError **error); +static void _do_previous(MafwGstRendererState *self, GError **error); +static void _do_goto_index(MafwGstRendererState *self, guint index, + GError **error); + +/*---------------------------------------------------------------------------- + Notification metatada + ----------------------------------------------------------------------------*/ + +static void _notify_metadata(MafwGstRendererState *self, + const gchar *object_id, + GHashTable *metadata, + GError **error); + +/*---------------------------------------------------------------------------- + Notification worker + ----------------------------------------------------------------------------*/ + +static void _notify_play(MafwGstRendererState *self, GError **error); +static void _notify_pause(MafwGstRendererState *self, GError **error); +static void _notify_seek(MafwGstRendererState *self, GError **error); +static void _notify_buffer_status(MafwGstRendererState *self, gdouble percent, + GError **error); +static void _notify_eos(MafwGstRendererState *self, GError **error); + +/*---------------------------------------------------------------------------- + Playlist editing signals + ----------------------------------------------------------------------------*/ + +static void _playlist_contents_changed(MafwGstRendererState *self, + gboolean clip_changed, + GError **error); + +/*---------------------------------------------------------------------------- + Property methods + ----------------------------------------------------------------------------*/ + +static GValue* _get_property_value(MafwGstRendererState *self, + const gchar *name); + +/*---------------------------------------------------------------------------- + Memory card event handlers + ----------------------------------------------------------------------------*/ + +static void _handle_pre_unmount(MafwGstRendererState *self, + const gchar *mount_point); + +/*---------------------------------------------------------------------------- + GObject initialization + ----------------------------------------------------------------------------*/ + +G_DEFINE_TYPE(MafwGstRendererStatePlaying, mafw_gst_renderer_state_playing, + MAFW_TYPE_GST_RENDERER_STATE); + +static void mafw_gst_renderer_state_playing_init(MafwGstRendererStatePlaying *self) +{ +} + +static void mafw_gst_renderer_state_playing_class_init( + MafwGstRendererStatePlayingClass *klass) +{ + MafwGstRendererStateClass *state_class; + + state_class = MAFW_GST_RENDERER_STATE_CLASS(klass); + g_return_if_fail(state_class != NULL); + + state_class->name = g_strdup("Playing"); + + /* Playback */ + + state_class->play = _do_play; + state_class->play_object = _do_play_object; + state_class->stop = _do_stop; + state_class->pause = _do_pause; + /* state_class->resume is not allowed */ + state_class->set_position = _do_set_position; + state_class->get_position = _do_get_position; + + /* Playlist */ + + state_class->next = _do_next; + state_class->previous = _do_previous; + state_class->goto_index = _do_goto_index; + + /* Notification metadata */ + + state_class->notify_metadata = _notify_metadata; + + /* Notification worker */ + + state_class->notify_play = _notify_play; + state_class->notify_pause = _notify_pause; + state_class->notify_seek = _notify_seek; + state_class->notify_buffer_status = _notify_buffer_status; + state_class->notify_eos = _notify_eos; + + /* Playlist editing signals */ + + state_class->playlist_contents_changed = + _playlist_contents_changed; + + /* Property methods */ + + state_class->get_property_value = _get_property_value; + + /* Memory card event handlers */ + + state_class->handle_pre_unmount = _handle_pre_unmount; +} + +GObject *mafw_gst_renderer_state_playing_new(MafwGstRenderer *renderer) +{ + MafwGstRendererState *state; + + state = MAFW_GST_RENDERER_STATE( + g_object_new(MAFW_TYPE_GST_RENDERER_STATE_PLAYING, NULL)); + state->renderer = renderer; + + return G_OBJECT(state); +} + +/*---------------------------------------------------------------------------- + Playback + ----------------------------------------------------------------------------*/ + +static void _do_play(MafwGstRendererState *self, GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + mafw_gst_renderer_state_do_play(self, error); +} + +static void _do_play_object(MafwGstRendererState *self, const gchar *object_id, + GError **error) +{ + MafwGstRendererPlaybackMode cur_mode, prev_mode; + + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + + prev_mode = mafw_gst_renderer_get_playback_mode(self->renderer); + mafw_gst_renderer_state_do_play_object(self, object_id, error); + cur_mode = mafw_gst_renderer_get_playback_mode(self->renderer); + + /* If this happens it means that we interrupted playlist playback + so let's resume it when play_object is finished */ + if (cur_mode != prev_mode) { + self->renderer->resume_playlist = TRUE; + } +} + +static void _do_stop(MafwGstRendererState *self, GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + + /* Stop playback */ + mafw_gst_renderer_state_do_stop(self, error); +} + +static void _do_pause(MafwGstRendererState *self, GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + + MafwGstRenderer *renderer = MAFW_GST_RENDERER_STATE(self)->renderer; + mafw_gst_renderer_worker_pause(renderer->worker); + + /* Transition will be done when receiving pause + * notification */ +} + +static void _do_set_position(MafwGstRendererState *self, + MafwRendererSeekMode mode, gint seconds, + GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + mafw_gst_renderer_state_do_set_position(self, mode, seconds, error); +} + +static void _do_get_position(MafwGstRendererState *self, + gint *seconds, + GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + mafw_gst_renderer_state_do_get_position(self, seconds, error); +} + + +/*---------------------------------------------------------------------------- + Playlist + ----------------------------------------------------------------------------*/ + +static void _do_next(MafwGstRendererState *self, GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + mafw_gst_renderer_state_do_next(self, error); +} + +static void _do_previous(MafwGstRendererState *self, GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + mafw_gst_renderer_state_do_prev(self, error); +} + +static void _do_goto_index(MafwGstRendererState *self, guint index, + GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + mafw_gst_renderer_state_do_goto_index(self, index, error); +} + + +/*---------------------------------------------------------------------------- + Notification metatada + ----------------------------------------------------------------------------*/ + +static void _notify_metadata(MafwGstRendererState *self, + const gchar *object_id, + GHashTable *metadata, + GError **error) +{ + g_debug("running _notify_metadata..."); + /* Kindly Ignore this notification: + probably a delayed (now useless) metadata resolution */ +} + + +/*---------------------------------------------------------------------------- + Notification worker + ----------------------------------------------------------------------------*/ + +static void _notify_play(MafwGstRendererState *self, GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + /* Kindly ignore this notification: it's received when seeking + * in a stream */ +} + +static void _notify_pause(MafwGstRendererState *self, GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + + MafwGstRenderer *renderer = MAFW_GST_RENDERER_STATE(self)->renderer; + + /* Change status to pause */ + mafw_gst_renderer_set_state(renderer, Paused); +} + +static void _notify_seek(MafwGstRendererState *self, GError **error) +{ + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + mafw_gst_renderer_state_do_notify_seek(self, error); +} + +static void _notify_buffer_status(MafwGstRendererState *self, gdouble percent, + GError **error) +{ + mafw_gst_renderer_state_do_notify_buffer_status (self, percent, error); +} + +static void _notify_eos(MafwGstRendererState *self, GError **error) +{ + MafwGstRenderer *renderer; + MafwGstRendererMovementResult move_type; + MafwGstRendererPlaybackMode mode; + + renderer = MAFW_GST_RENDERER_STATE(self)->renderer; + + /* Update playcount */ + if (renderer->update_playcount_id > 0) { + g_source_remove(renderer->update_playcount_id); + mafw_gst_renderer_update_stats(renderer); + } + + /* Notice: playback has already stopped, so calling + * mafw_gst_renderer_stop or mafw_gst_renderer_state_stop + * here is an error. + * To set the renderer state to Stopped use this instead: + * mafw_gst_renderer_set_state(self->renderer, Stopped); + */ + + /* If we are not in playlist mode, switch to it, + otherwise move to the next in the playlist */ + mode = mafw_gst_renderer_get_playback_mode(renderer); + if (mode == MAFW_GST_RENDERER_MODE_STANDALONE) { + mafw_gst_renderer_worker_stop(self->renderer->worker); + mafw_gst_renderer_set_state(self->renderer, Stopped); + mafw_gst_renderer_set_playback_mode( + renderer, MAFW_GST_RENDERER_MODE_PLAYLIST); + mafw_gst_renderer_set_media_playlist(renderer); + + /* Do we have to resume playlist playback? */ + if (renderer->resume_playlist) { + mafw_gst_renderer_state_play(self, error); + } + } + else + { + gboolean is_stream = uri_is_stream(self->renderer->worker->media.location); + if (is_stream + && self->renderer->error_policy == MAFW_RENDERER_ERROR_POLICY_STOP + && self->renderer->worker->media.length_nanos == -1 + && self->renderer->worker->media.seekable == SEEKABILITY_NO_SEEKABLE + && self->renderer->worker->media.has_visual_content == FALSE) + { + /* Endless Radio stream. Stream has no length, it is not seekable or it is not video. */ + mafw_gst_renderer_worker_stop(self->renderer->worker); + mafw_gst_renderer_set_state(self->renderer, Stopped); + g_signal_emit_by_name(MAFW_EXTENSION(self->renderer), "error", + MAFW_RENDERER_ERROR, MAFW_RENDERER_ERROR_STREAM_DISCONNECTED, + "EOS FOR ENDLESS STREAM"); + } + else + { + /* Move to next in playlist */ + move_type = + mafw_gst_renderer_move(renderer, + MAFW_GST_RENDERER_MOVE_TYPE_NEXT, + 0, error); + + switch (move_type) + { + case MAFW_GST_RENDERER_MOVE_RESULT_OK: + mafw_gst_renderer_state_play(self, error); + break; + case MAFW_GST_RENDERER_MOVE_RESULT_PLAYLIST_LIMIT: + case MAFW_GST_RENDERER_MOVE_RESULT_NO_PLAYLIST: + mafw_gst_renderer_worker_stop(self->renderer->worker); + mafw_gst_renderer_set_state(self->renderer, Stopped); + break; + case MAFW_GST_RENDERER_MOVE_RESULT_ERROR: + break; + default: + g_critical("Movement not controlled"); + } + } + } +} + +/*---------------------------------------------------------------------------- + Playlist editing signals + ----------------------------------------------------------------------------*/ + +static void _playlist_contents_changed(MafwGstRendererState *self, + gboolean clip_changed, + GError **error) +{ + MafwGstRendererPlaybackMode mode; + + g_return_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self)); + + /* Play the new index only if we are not in standalone mode. + Otherwise, when play_object finishes the new item will be + played if that's been suggested with renderer->resume_playlist */ + mode = mafw_gst_renderer_get_playback_mode(self->renderer); + if (clip_changed && mode == MAFW_GST_RENDERER_MODE_PLAYLIST) { + mafw_gst_renderer_state_do_play(self, error); + } +} + +/*---------------------------------------------------------------------------- + Property methods + ----------------------------------------------------------------------------*/ + +GValue* _get_property_value(MafwGstRendererState *self, const gchar *name) +{ + GValue *value = NULL; + + g_return_val_if_fail(MAFW_IS_GST_RENDERER_STATE_PLAYING(self), value); + + if (!g_strcmp0(name, MAFW_PROPERTY_RENDERER_TRANSPORT_ACTIONS)) { + gboolean is_seekable = + mafw_gst_renderer_worker_get_seekable( + self->renderer->worker); + + value = g_new0(GValue, 1); + g_value_init(value, G_TYPE_STRING); + if (is_seekable) { + g_value_set_string(value, "seek"); + } else { + g_value_set_string(value, ""); + } + } + + return value; +} + +/*---------------------------------------------------------------------------- + Memory card event handlers + ----------------------------------------------------------------------------*/ + +static void _handle_pre_unmount(MafwGstRendererState *self, + const gchar *mount_point) +{ + gchar *mount_uri; + + /* If not playing anything, bail out */ + if (!self->renderer->media->uri) { + return; + } + + /* Check if mount point is URI or path, we need URI */ + if (!g_str_has_prefix(mount_point, "file://")) { + mount_uri = g_filename_to_uri(mount_point, NULL, NULL); + } else { + mount_uri = g_strdup(mount_point); + } + + /* Stop if playing from unmounted location */ + if (g_str_has_prefix(self->renderer->media->uri, mount_uri)) { + mafw_gst_renderer_stop(MAFW_RENDERER(self->renderer), + NULL, + NULL); + } + + g_free(mount_uri); +}