1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/maemo-ui/src/mmyth_tvplayer.c Thu Sep 28 16:11:10 2006 +0100
1.3 @@ -0,0 +1,684 @@
1.4 +/**
1.5 + * GMyth Library
1.6 + *
1.7 + * @file gmyth/mmyth_tvplayer.c
1.8 + *
1.9 + * @brief <p> This component provides playback of the remote A/V using
1.10 + * GStreamer.
1.11 + *
1.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
1.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
1.14 + *
1.15 + *//*
1.16 + *
1.17 + * This program is free software; you can redistribute it and/or modify
1.18 + * it under the terms of the GNU Lesser General Public License as published by
1.19 + * the Free Software Foundation; either version 2 of the License, or
1.20 + * (at your option) any later version.
1.21 + *
1.22 + * This program is distributed in the hope that it will be useful,
1.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.25 + * GNU General Public License for more details.
1.26 + *
1.27 + * You should have received a copy of the GNU Lesser General Public License
1.28 + * along with this program; if not, write to the Free Software
1.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.30 + */
1.31 +
1.32 +#include "mmyth_tvplayer.h"
1.33 +
1.34 +#include <gdk/gdkx.h>
1.35 +
1.36 +#include "gmyth_context.h"
1.37 +#include "gmyth_remote_util.h"
1.38 +
1.39 +typedef struct _GstPlayerWindowStateChange
1.40 +{
1.41 + GstElement *play;
1.42 + GstState old_state, new_state;
1.43 + MMythTVPlayer *tvplayer;
1.44 +} GstPlayerWindowStateChange;
1.45 +
1.46 +typedef struct _GstPlayerWindowTagFound
1.47 +{
1.48 + GstElement *play;
1.49 + GstTagList *taglist;
1.50 + MMythTVPlayer *tvplayer;
1.51 +} GstPlayerWindowTagFound;
1.52 +
1.53 +/*
1.54 +static gboolean idle_state (gpointer data);
1.55 +*/
1.56 +static gboolean bus_call (GstBus * bus, GstMessage * msg, gpointer data);
1.57 +
1.58 +static void mmyth_tvplayer_class_init (MMythTVPlayerClass *klass);
1.59 +static void mmyth_tvplayer_init (MMythTVPlayer *object);
1.60 +
1.61 +static void mmyth_tvplayer_dispose (GObject *object);
1.62 +static void mmyth_tvplayer_finalize (GObject *object);
1.63 +
1.64 +G_DEFINE_TYPE(MMythTVPlayer, mmyth_tvplayer, G_TYPE_OBJECT)
1.65 +
1.66 +static gboolean mmyth_tvplayer_create_pipeline (MMythTVPlayer* tvplayer);
1.67 +static void new_pad_cb (GstElement *element,
1.68 + GstPad *pad, gpointer data);
1.69 +
1.70 +static gboolean expose_cb (GtkWidget * widget,
1.71 + GdkEventExpose * event,
1.72 + gpointer user_data);
1.73 +
1.74 +static void
1.75 +mmyth_tvplayer_class_init (MMythTVPlayerClass *klass)
1.76 +{
1.77 + GObjectClass *gobject_class;
1.78 +
1.79 + gobject_class = (GObjectClass *) klass;
1.80 +
1.81 + gobject_class->dispose = mmyth_tvplayer_dispose;
1.82 + gobject_class->finalize = mmyth_tvplayer_finalize;
1.83 +}
1.84 +
1.85 +static void
1.86 +new_pad_cb (GstElement *element, GstPad *pad, gpointer data)
1.87 +{
1.88 + MMythTVPlayer *tvplayer = MMYTH_TVPLAYER (data);
1.89 + GstPadLinkReturn ret;
1.90 + char *s;
1.91 +
1.92 + s = gst_caps_to_string (pad->caps);
1.93 +
1.94 + if ( s[0] == 'a') {
1.95 + ret = gst_pad_link (pad, gst_element_get_pad (tvplayer->audioqueue, "sink"));
1.96 + } else {
1.97 + ret = gst_pad_link (pad, gst_element_get_pad (tvplayer->videoqueue, "sink"));
1.98 + }
1.99 +
1.100 + g_free(s);
1.101 +}
1.102 +
1.103 +static gboolean
1.104 +expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer user_data)
1.105 +{
1.106 + MMythTVPlayer *tvplayer = MMYTH_TVPLAYER (user_data);
1.107 +
1.108 + if (tvplayer && tvplayer->videow) {
1.109 + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (tvplayer->gst_videosink),
1.110 + GDK_WINDOW_XWINDOW (widget->window));
1.111 + return TRUE;
1.112 + }
1.113 +
1.114 + g_warning ("MMythTVPlayer expose called before setting video window\n");
1.115 +
1.116 + return FALSE;
1.117 +}
1.118 +
1.119 +static void
1.120 +mmyth_tvplayer_init (MMythTVPlayer *tvplayer)
1.121 +{
1.122 + tvplayer->gst_pipeline = NULL;
1.123 + tvplayer->gst_source = NULL;
1.124 + tvplayer->gst_videodec = NULL;
1.125 + tvplayer->gst_videosink = NULL;
1.126 + tvplayer->videoqueue = NULL;
1.127 + tvplayer->audioqueue = NULL;
1.128 +
1.129 + /* GTKWidget for rendering the video */
1.130 + tvplayer->videow = NULL;
1.131 + tvplayer->expose_handler = 0;
1.132 +
1.133 + tvplayer->backend_hostname = NULL;
1.134 + tvplayer->backend_port = 0;
1.135 + tvplayer->local_hostname = NULL;
1.136 +
1.137 + tvplayer->remote_encoder = NULL;
1.138 + tvplayer->tvchain = NULL;
1.139 + tvplayer->proginfo = NULL;
1.140 +}
1.141 +
1.142 +static void
1.143 +mmyth_tvplayer_dispose (GObject *object)
1.144 +{
1.145 +
1.146 + G_OBJECT_CLASS (mmyth_tvplayer_parent_class)->dispose (object);
1.147 +}
1.148 +
1.149 +static void
1.150 +mmyth_tvplayer_finalize (GObject *object)
1.151 +{
1.152 + g_signal_handlers_destroy (object);
1.153 +
1.154 + MMythTVPlayer *tvplayer = MMYTH_TVPLAYER (object);
1.155 +
1.156 + g_debug ("[%s] Finalizing tvplayer", __FUNCTION__);
1.157 +
1.158 + if (tvplayer->videow != NULL) {
1.159 + if (g_signal_handler_is_connected (tvplayer->videow,
1.160 + tvplayer->expose_handler)) {
1.161 + g_signal_handler_disconnect (tvplayer->videow,
1.162 + tvplayer->expose_handler);
1.163 + }
1.164 + g_object_unref (tvplayer->videow);
1.165 + }
1.166 +
1.167 + if ( tvplayer->remote_encoder != NULL )
1.168 + g_object_unref (tvplayer->remote_encoder);
1.169 + if ( tvplayer->tvchain != NULL )
1.170 + g_object_unref (tvplayer->tvchain);
1.171 + if ( tvplayer->proginfo != NULL )
1.172 + g_object_unref (tvplayer->proginfo);
1.173 +
1.174 + // Release Gstreamer elements
1.175 + if ( tvplayer->gst_pipeline != NULL )
1.176 + g_object_unref (tvplayer->gst_pipeline);
1.177 + if ( tvplayer->gst_source != NULL )
1.178 + g_object_unref (tvplayer->gst_source);
1.179 + if ( tvplayer->gst_videodec != NULL )
1.180 + g_object_unref (tvplayer->gst_videodec);
1.181 + if ( tvplayer->gst_videosink != NULL )
1.182 + g_object_unref (tvplayer->gst_videosink);
1.183 + if ( tvplayer->videoqueue != NULL )
1.184 + g_object_unref (tvplayer->videoqueue);
1.185 + if ( tvplayer->audioqueue != NULL )
1.186 + g_object_unref (tvplayer->audioqueue);
1.187 +
1.188 + G_OBJECT_CLASS (mmyth_tvplayer_parent_class)->finalize (object);
1.189 +}
1.190 +
1.191 +/** Creates a new instance of MMythTVPlayer.
1.192 + *
1.193 + * @return a new instance of MMythTVPlayer.
1.194 + */
1.195 +MMythTVPlayer *
1.196 +mmyth_tvplayer_new ()
1.197 +{
1.198 + MMythTVPlayer *tvplayer =
1.199 + MMYTH_TVPLAYER (g_object_new(MMYTH_TVPLAYER_TYPE, NULL));
1.200 +
1.201 + return tvplayer;
1.202 +}
1.203 +
1.204 +/** Initializes the tv player.
1.205 + *
1.206 + * @param tvplayer the object instance.
1.207 + * @return gboolean TRUE if the pipeline was created
1.208 + * successfully, FALSE otherwise.
1.209 + */
1.210 +gboolean
1.211 +mmyth_tvplayer_initialize (MMythTVPlayer *tvplayer)
1.212 +{
1.213 +
1.214 + if (!mmyth_tvplayer_create_pipeline (tvplayer)) {
1.215 + g_warning ("[%s] Error while creating pipeline. TV Player not initialized", __FUNCTION__);
1.216 + return FALSE;
1.217 + } else {
1.218 + g_debug ("[%s] GStreamer pipeline created", __FUNCTION__);
1.219 + }
1.220 +
1.221 + return TRUE;
1.222 +}
1.223 +
1.224 +/** Creates the GStreamer pipeline used by the player.
1.225 + *
1.226 + * @param tvplayer the object instance.
1.227 + * @return gboolean TRUE if the pipeline was created
1.228 + * successfully, FALSE otherwise.
1.229 + */
1.230 +static gboolean
1.231 +mmyth_tvplayer_create_pipeline (MMythTVPlayer* tvplayer)
1.232 +{
1.233 + GstElement *pipeline;
1.234 + GstElement *source, *parser;
1.235 + GstElement *videodec, *videosink;
1.236 +#ifndef MAEMO_PLATFORM
1.237 + GstElement *audiodec, *audioconv;
1.238 +#endif
1.239 + GstElement *audiosink;
1.240 + GstElement *videoqueue, *audioqueue;
1.241 +
1.242 + g_debug ("MMythTVPlayer: Setting the Gstreamer pipeline\n");
1.243 +
1.244 + pipeline = gst_pipeline_new ("video-player");
1.245 + source = gst_element_factory_make ("mythtvsrc", "myth-source");
1.246 + parser = gst_element_factory_make ("ffdemux_nuv", "nuv-demux");
1.247 +
1.248 + /* Gstreamer Video elements */
1.249 + videoqueue = gst_element_factory_make ("queue", "video-queue");
1.250 + videodec = gst_element_factory_make ("ffdec_mpeg4", "video-decoder");
1.251 +#ifdef MAEMO_PLATFORM
1.252 + videosink = gst_element_factory_make ("sdlvideosink", "image-output");
1.253 +#else
1.254 + videosink = gst_element_factory_make ("xvimagesink", "image-output");
1.255 +#endif
1.256 +
1.257 + /* Gstreamer Audio elements */
1.258 + audioqueue = gst_element_factory_make ("queue", "audio-queue");
1.259 +#ifdef MAEMO_PLATFORM
1.260 + audiosink = gst_element_factory_make ("dspmp3sink", "audio-output");
1.261 +#else
1.262 + audiodec = gst_element_factory_make ("ffdec_mp3", "audio-decoder");
1.263 + audioconv = gst_element_factory_make ("audioconvert", "audio-converter");
1.264 + audiosink = gst_element_factory_make ("alsasink", "audio-output");
1.265 +#endif
1.266 +
1.267 + if (!(pipeline && source && parser && videodec && videosink) ||
1.268 + !(videoqueue && audioqueue && audiosink)) {
1.269 + /* FIXME: hanlde the error correctly */
1.270 + /* video_alignment is not being created (below)
1.271 + and is causing problems to the ui */
1.272 +
1.273 + tvplayer->gst_pipeline = NULL;
1.274 + tvplayer->gst_videodec = NULL;
1.275 + tvplayer->gst_videosink = NULL;
1.276 +
1.277 + g_warning ("GstElement creation error!\n");
1.278 + return FALSE;
1.279 + }
1.280 +
1.281 +#ifndef MAEMO_PLATFORM
1.282 + if (!(audiodec && audioconv)) {
1.283 + g_warning ("GstElement for audio stream creation error!");
1.284 + return FALSE;
1.285 + }
1.286 +#endif
1.287 +
1.288 +
1.289 + tvplayer->gst_pipeline = pipeline;
1.290 + tvplayer->gst_source = source;
1.291 + tvplayer->gst_videodec = videodec;
1.292 + tvplayer->gst_videosink = videosink;
1.293 + g_object_ref (tvplayer->gst_pipeline);
1.294 + g_object_ref (tvplayer->gst_source);
1.295 + g_object_ref (tvplayer->gst_videodec);
1.296 + g_object_ref (tvplayer->gst_videosink);
1.297 +
1.298 + tvplayer->videoqueue = videoqueue;
1.299 + tvplayer->audioqueue = audioqueue;
1.300 + g_object_ref (tvplayer->videoqueue);
1.301 + g_object_ref (tvplayer->audioqueue);
1.302 +
1.303 + g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL);
1.304 + g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL);
1.305 +
1.306 + gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (tvplayer->gst_pipeline)),
1.307 + bus_call, tvplayer);
1.308 +
1.309 + gst_bin_add_many (GST_BIN (pipeline), source, parser, videoqueue,
1.310 + videodec, videosink, audioqueue, audiodec, audioconv, audiosink, NULL);
1.311 +
1.312 + {
1.313 +// GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", NULL);
1.314 +// gst_element_link_filtered(source, parser, rtpcaps);
1.315 + }
1.316 +
1.317 + gst_element_link (source, parser);
1.318 + gst_element_link_many (videoqueue, videodec, videosink, NULL);
1.319 + gst_element_link_many (audioqueue, audiodec, audioconv, audiosink, NULL);
1.320 +
1.321 + g_signal_connect (parser, "pad-added", G_CALLBACK (new_pad_cb), tvplayer);
1.322 +
1.323 + return TRUE;
1.324 +}
1.325 +
1.326 +/** Configures the backend and the tv player
1.327 + * for playing the recorded content A/V.
1.328 + *
1.329 + * FIXME: Change filename to program info or other structure about the recorded
1.330 + *
1.331 + * @param tvplayer the object instance.
1.332 + * @param filename the file uri of the recorded content to be played.
1.333 + * @return TRUE if successfull, FALSE if any error happens.
1.334 + */
1.335 +gboolean
1.336 +mmyth_tvplayer_record_setup (MMythTVPlayer *tvplayer, gchar *filename)
1.337 +{
1.338 + GMythSettings *msettings = gmyth_context_get_settings();
1.339 +
1.340 + // FIXME: we should receive the uri instead of filename
1.341 + GString *hostname = gmyth_settings_get_backend_hostname (msettings);
1.342 + int port = gmyth_settings_get_backend_port(msettings);
1.343 +
1.344 + GString *fullpath = g_string_new ("myth://");
1.345 + g_string_append_printf (fullpath, "%s:%d/%s", hostname->str, port, filename);
1.346 +
1.347 + tvplayer->is_livetv = FALSE;
1.348 +
1.349 + g_debug ("[%s] Setting record uri to gstreamer pipeline to %s", __FUNCTION__, fullpath->str);
1.350 +
1.351 + g_object_set (G_OBJECT (tvplayer->gst_source), "location",
1.352 + fullpath->str, NULL);
1.353 +
1.354 + return TRUE;
1.355 +}
1.356 +
1.357 +/** Configures the backend and the tv player
1.358 + * for playing the live tv.
1.359 + *
1.360 + * @param tvplayer the object instance.
1.361 + * @return TRUE if successfull, FALSE if any error happens.
1.362 + */
1.363 +gboolean
1.364 +mmyth_tvplayer_livetv_setup (MMythTVPlayer *tvplayer)
1.365 +{
1.366 + GMythSettings *msettings = gmyth_context_get_settings ();
1.367 + gboolean res = TRUE;
1.368 +
1.369 + res = gmyth_context_check_connection();
1.370 + if (!res) {
1.371 + g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__);
1.372 + res = FALSE;
1.373 + goto error;
1.374 + }
1.375 +
1.376 + tvplayer->backend_hostname = gmyth_settings_get_backend_hostname(msettings);
1.377 + tvplayer->backend_port = gmyth_settings_get_backend_port (msettings);
1.378 +
1.379 + tvplayer->local_hostname = g_string_new("");
1.380 + gmyth_context_get_local_hostname (tvplayer->local_hostname);
1.381 +
1.382 + if ( tvplayer->local_hostname == NULL ) {
1.383 + res = FALSE;
1.384 + goto error;
1.385 + }
1.386 +
1.387 + // Gets the remote encoder num
1.388 + tvplayer->remote_encoder = remote_request_next_free_recorder (-1);
1.389 +
1.390 + if ( tvplayer->remote_encoder == NULL ) {
1.391 + g_warning ("[%s] None remote encoder available", __FUNCTION__);
1.392 + res = FALSE;
1.393 + goto error;
1.394 + }
1.395 +
1.396 + // Creates livetv chain handler
1.397 + tvplayer->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) );
1.398 + gmyth_tvchain_initialize ( tvplayer->tvchain, tvplayer->local_hostname );
1.399 +
1.400 + if ( tvplayer->tvchain == NULL || tvplayer->tvchain->tvchain_id == NULL ) {
1.401 + res = FALSE;
1.402 + goto error;
1.403 + }
1.404 +
1.405 + // Init remote encoder. Opens its control socket.
1.406 + res = gmyth_remote_encoder_setup(tvplayer->remote_encoder);
1.407 + if ( !res ) {
1.408 + g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__);
1.409 + res = FALSE;
1.410 + goto error;
1.411 + }
1.412 + // Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly)
1.413 + res = gmyth_remote_encoder_spawntv ( tvplayer->remote_encoder,
1.414 + gmyth_tvchain_get_id(tvplayer->tvchain) );
1.415 + if (!res) {
1.416 + g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__);
1.417 + res = FALSE;
1.418 + goto error;
1.419 + }
1.420 +
1.421 + // Reload all TV chain from Mysql database.
1.422 + gmyth_tvchain_reload_all (tvplayer->tvchain);
1.423 +
1.424 + if ( tvplayer->tvchain == NULL ) {
1.425 + res = FALSE;
1.426 + goto error;
1.427 + }
1.428 +
1.429 + // Get program info from database using chanid and starttime
1.430 + tvplayer->proginfo = gmyth_tvchain_get_program_at (tvplayer->tvchain, -1);
1.431 + if ( tvplayer->proginfo == NULL ) {
1.432 + g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ );
1.433 + res = FALSE;
1.434 + goto error;
1.435 + } else {
1.436 + g_debug ("[%s] MythLiveTV: All requests to backend to start TV were OK.\n", __FUNCTION__ );
1.437 + }
1.438 +
1.439 + return res;
1.440 +
1.441 +error:
1.442 + if ( tvplayer->backend_hostname != NULL ) {
1.443 + g_string_free( tvplayer->backend_hostname, TRUE );
1.444 + res = FALSE;
1.445 + }
1.446 +
1.447 + if ( tvplayer->local_hostname != NULL ) {
1.448 + g_string_free( tvplayer->local_hostname, TRUE );
1.449 + res = FALSE;
1.450 + }
1.451 +
1.452 + if ( tvplayer->remote_encoder != NULL ) {
1.453 + g_object_unref (tvplayer->remote_encoder);
1.454 + tvplayer->remote_encoder = NULL;
1.455 + }
1.456 +
1.457 + if ( tvplayer->tvchain != NULL ) {
1.458 + g_object_unref (tvplayer->tvchain);
1.459 + tvplayer->tvchain = NULL;
1.460 + }
1.461 +
1.462 + if ( tvplayer->proginfo != NULL ) {
1.463 + g_object_unref (tvplayer->proginfo);
1.464 + tvplayer->proginfo = NULL;
1.465 + }
1.466 +
1.467 + return res;
1.468 +
1.469 +}
1.470 +
1.471 +/** Sets the GTK video widget for the tv player.
1.472 + *
1.473 + * @param tvplayer the object instance.
1.474 + * @param videow the GTK video window.
1.475 + * @return TRUE if successfull, FALSE if any error happens.
1.476 + */
1.477 +gboolean
1.478 +mmyth_tvplayer_set_widget (MMythTVPlayer *tvplayer, GtkWidget *videow)
1.479 +{
1.480 + tvplayer->videow = videow;
1.481 + g_object_ref (videow);
1.482 +
1.483 + g_debug ("[%s] Setting widget for tv player render", __FUNCTION__);
1.484 +
1.485 + tvplayer->expose_handler = g_signal_connect (tvplayer->videow, "expose-event",
1.486 + G_CALLBACK (expose_cb), tvplayer);
1.487 +
1.488 + //g_signal_connect(miptv_ui->videow, "size_request", G_CALLBACK(cb_preferred_video_size), miptv_ui);
1.489 +
1.490 + return TRUE;
1.491 +}
1.492 +
1.493 +static gboolean
1.494 +bus_call (GstBus * bus, GstMessage * msg, gpointer data)
1.495 +{
1.496 + //MMythTVPlayer *tvplayer = MMYTH_TVPLAYER ( data );
1.497 + //GMainLoop *loop = tvplayer->loop;
1.498 +
1.499 + switch (GST_MESSAGE_TYPE (msg)) {
1.500 + case GST_MESSAGE_EOS:
1.501 + printf ("End of stream\n");
1.502 + //g_idle_add ((GSourceFunc) idle_eos, data);
1.503 + gst_element_set_state ( GST_ELEMENT (GST_MESSAGE_SRC (msg)), GST_STATE_NULL );
1.504 + gst_element_set_locked_state ( GST_ELEMENT (GST_MESSAGE_SRC (msg)), FALSE );
1.505 + break;
1.506 + case GST_MESSAGE_ERROR:
1.507 + {
1.508 + gchar *debug;
1.509 + GError *err;
1.510 +
1.511 + gst_message_parse_error (msg, &err, &debug);
1.512 + g_free (debug);
1.513 +
1.514 + printf ("Error: %s\n", err->message);
1.515 + g_error_free (err);
1.516 +
1.517 + //g_main_loop_quit (loop);
1.518 + }
1.519 + break;
1.520 + default:
1.521 + printf (gst_message_type_get_name (GST_MESSAGE_TYPE (msg)));
1.522 + printf ("\n");
1.523 + break;
1.524 + }
1.525 +
1.526 + return TRUE;
1.527 +}
1.528 +
1.529 +
1.530 +#if 0
1.531 +static gboolean
1.532 +idle_state (gpointer data)
1.533 +{
1.534 + GstPlayerWindowStateChange *st = data;
1.535 +
1.536 + if (st->old_state == GST_STATE_PLAYING) {
1.537 + if (st->miptv_ui->idle_id != 0) {
1.538 + g_source_remove (st->miptv_ui->idle_id);
1.539 + st->miptv_ui->idle_id = 0;
1.540 + }
1.541 + }
1.542 + else if (st->new_state == GST_STATE_PLAYING) {
1.543 + if (st->miptv_ui->idle_id != 0)
1.544 + g_source_remove (st->miptv_ui->idle_id);
1.545 +
1.546 + st->miptv_ui->idle_id = g_idle_add (cb_iterate, st->miptv_ui);
1.547 + }
1.548 +
1.549 + /* new movie loaded? */
1.550 + if (st->old_state == GST_STATE_READY && st->new_state > GST_STATE_READY) {
1.551 +
1.552 + /* gboolean have_video = FALSE; */
1.553 +
1.554 + gtk_widget_show (st->miptv_ui->videow);
1.555 +
1.556 + gtk_window_resize (GTK_WINDOW (st->miptv_ui->main_window), 1, 1);
1.557 +
1.558 + }
1.559 +
1.560 + /* discarded movie? */
1.561 + if (st->old_state > GST_STATE_READY && st->new_state == GST_STATE_READY) {
1.562 +
1.563 + if (st->miptv_ui->tagcache) {
1.564 + gst_tag_list_free (st->miptv_ui->tagcache);
1.565 + st->miptv_ui->tagcache = NULL;
1.566 + }
1.567 + }
1.568 +
1.569 + gst_object_unref (GST_OBJECT (st->play));
1.570 + //g_object_unref (G_OBJECT (st->win));
1.571 + g_free (st);
1.572 +
1.573 + /* once */
1.574 + return FALSE;
1.575 +}
1.576 +
1.577 +#endif
1.578 +
1.579 +/** Stops playing the current A/V.
1.580 + *
1.581 + * FIXME: How to proceed differently between livetv
1.582 + * and recorded content?
1.583 + *
1.584 + * @param tvplayer the object instance.
1.585 + * @return void
1.586 + */
1.587 +void
1.588 +mmyth_tvplayer_stop_playing (MMythTVPlayer *tvplayer)
1.589 +{
1.590 + g_debug ("[%s] Setting gstreamer pipeline state to NULL", __FUNCTION__);
1.591 +
1.592 + gst_element_set_state (tvplayer->gst_pipeline, GST_STATE_NULL);
1.593 +
1.594 + if (tvplayer->is_livetv) {
1.595 + if (!gmyth_remote_encoder_stop_livetv (tvplayer->remote_encoder)) {
1.596 + g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__);
1.597 + }
1.598 + }
1.599 +}
1.600 +
1.601 +/** Queries if the tvplayer is active playing A/V content.
1.602 + *
1.603 + * @param tvplayer the object instance.
1.604 + * @return TRUE if the tvplayer is active, FALSE otherwise.
1.605 + */
1.606 +gboolean
1.607 +mmyth_tvplayer_is_playing (MMythTVPlayer *tvplayer)
1.608 +{
1.609 + return (GST_STATE (tvplayer->gst_pipeline) == GST_STATE_PLAYING);
1.610 +}
1.611 +
1.612 +/** Static function that sets the tvplayer state to PLAYING.
1.613 + *
1.614 + * @param tvplayer the object instance.
1.615 + * @return TRUE if the tvplayer is active, FALSE otherwise.
1.616 + */
1.617 +static gboolean
1.618 +idle_play (gpointer data)
1.619 +{
1.620 + MMythTVPlayer *tvplayer = MMYTH_TVPLAYER (data);
1.621 +
1.622 + g_debug ("MMythTVPlayer: Setting pipeline state to PLAYING\n");
1.623 +
1.624 + gst_element_set_state (tvplayer->gst_pipeline, GST_STATE_PLAYING);
1.625 +
1.626 + return FALSE;
1.627 +}
1.628 +
1.629 +/** Start playing A/V with the tvplayer attributes.
1.630 + *
1.631 + * @param tvplayer the object instance.
1.632 + */
1.633 +void
1.634 +mmyth_tvplayer_start_playing (MMythTVPlayer *tvplayer)
1.635 +{
1.636 +
1.637 + // FIXME: Move this to livetv_setup??
1.638 + if (tvplayer->is_livetv) {
1.639 +
1.640 + #if 0
1.641 + if (!tvplayer || !(tvplayer->proginfo) || !(tvplayer->local_hostname)
1.642 + || !(tvplayer->gst_source)) {
1.643 + g_warning ("GMythtvPlayer not ready to start playing\n");
1.644 + }
1.645 +
1.646 + if (!(tvplayer->proginfo->pathname)) {
1.647 + g_warning ("[%s] Playback url is null, could not play the myth content", __FUNCTION__);
1.648 + return;
1.649 + }
1.650 +
1.651 + g_debug ("MMythTVPlayer: Start playing %s", tvplayer->proginfo->pathname->str);
1.652 +#endif
1.653 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live",
1.654 + TRUE, NULL);
1.655 +#if 0
1.656 + if ( tvplayer->tvchain != NULL ) {
1.657 + GString *str_chainid = gmyth_tvchain_get_id(tvplayer->tvchain);
1.658 + g_print( "[%s]\tCHAIN ID: %s\n", __FUNCTION__, str_chainid->str );
1.659 +
1.660 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live-chainid",
1.661 + g_strdup( str_chainid->str ), NULL);
1.662 + if ( str_chainid!=NULL)
1.663 + g_string_free( str_chainid, FALSE );
1.664 + }
1.665 +
1.666 + if ( tvplayer->remote_encoder != NULL )
1.667 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live-id",
1.668 + tvplayer->remote_encoder->recorder_num, NULL );
1.669 + g_debug ("[%s] Setting location to %s", __FUNCTION__,
1.670 + tvplayer->proginfo->pathname->str);
1.671 +
1.672 + /* Sets the gstreamer properties acording to the service access address */
1.673 + g_object_set (G_OBJECT (tvplayer->gst_source), "location",
1.674 + tvplayer->proginfo->pathname->str, NULL);
1.675 +#endif
1.676 + }
1.677 +
1.678 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-version",
1.679 + MYTHTV_VERSION_DEFAULT, NULL);
1.680 +
1.681 + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-debug",
1.682 + TRUE, NULL);
1.683 +
1.684 + g_idle_add (idle_play, tvplayer);
1.685 +
1.686 +}
1.687 +