renatofilho@20: /** renatofilho@20: * GMyth Library renatofilho@20: * renatofilho@20: * @file gmyth/mmyth_tvplayer.c renatofilho@20: * renatofilho@20: * @brief

This component provides playback of the remote A/V using renatofilho@20: * GStreamer. renatofilho@20: * renatofilho@20: * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. renatofilho@20: * @author Hallyson Luiz de Morais Melo renatofilho@20: * renatofilho@754: *//* renatofilho@754: * renatofilho@754: * This program is free software; you can redistribute it and/or modify renatofilho@754: * it under the terms of the GNU Lesser General Public License as published by renatofilho@754: * the Free Software Foundation; either version 2 of the License, or renatofilho@754: * (at your option) any later version. renatofilho@754: * renatofilho@754: * This program is distributed in the hope that it will be useful, renatofilho@754: * but WITHOUT ANY WARRANTY; without even the implied warranty of renatofilho@754: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the renatofilho@754: * GNU General Public License for more details. renatofilho@754: * renatofilho@754: * You should have received a copy of the GNU Lesser General Public License renatofilho@754: * along with this program; if not, write to the Free Software renatofilho@754: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA renatofilho@754: */ renatofilho@20: renatofilho@20: #include "mmyth_tvplayer.h" renatofilho@754: renatofilho@20: #include renatofilho@20: rosfran@208: #include rosfran@208: rosfran@208: #define MYTHTV_VERSION_DEFAULT 30 renatofilho@20: renatofilho@754: typedef struct _GstPlayerWindowStateChange { renatofilho@754: GstElement *play; renatofilho@754: GstState old_state, renatofilho@754: new_state; renatofilho@754: MMythTVPlayer *tvplayer; renatofilho@20: } GstPlayerWindowStateChange; renatofilho@20: renatofilho@754: typedef struct _GstPlayerWindowTagFound { renatofilho@754: GstElement *play; renatofilho@754: GstTagList *taglist; renatofilho@754: MMythTVPlayer *tvplayer; renatofilho@20: } GstPlayerWindowTagFound; renatofilho@20: renatofilho@20: /* renatofilho@754: * static gboolean idle_state (gpointer data); renatofilho@754: */ renatofilho@754: static gboolean bus_call(GstBus * bus, GstMessage * msg, gpointer data); renatofilho@20: renatofilho@754: static void mmyth_tvplayer_class_init(MMythTVPlayerClass * klass); renatofilho@754: static void mmyth_tvplayer_init(MMythTVPlayer * object); renatofilho@20: renatofilho@754: static void mmyth_tvplayer_dispose(GObject * object); renatofilho@754: static void mmyth_tvplayer_finalize(GObject * object); renatofilho@20: renatofilho@20: G_DEFINE_TYPE(MMythTVPlayer, mmyth_tvplayer, G_TYPE_OBJECT) renatofilho@20: renatofilho@754: static gboolean mmyth_tvplayer_create_pipeline(MMythTVPlayer * renatofilho@754: tvplayer); renatofilho@754: static void new_pad_cb(GstElement * element, GstPad * pad, renatofilho@754: gpointer data); renatofilho@20: renatofilho@754: static gboolean expose_cb(GtkWidget * widget, renatofilho@754: GdkEventExpose * event, gpointer user_data); renatofilho@20: renatofilho@754: static void renatofilho@754: mmyth_tvplayer_class_init(MMythTVPlayerClass * klass) renatofilho@20: { renatofilho@754: GObjectClass *gobject_class; renatofilho@20: renatofilho@754: gobject_class = (GObjectClass *) klass; rosfran@208: renatofilho@754: gobject_class->dispose = mmyth_tvplayer_dispose; renatofilho@754: gobject_class->finalize = mmyth_tvplayer_finalize; renatofilho@20: } renatofilho@20: renatofilho@20: static void renatofilho@754: new_pad_cb(GstElement * element, GstPad * pad, gpointer data) renatofilho@20: { renatofilho@754: MMythTVPlayer *tvplayer = MMYTH_TVPLAYER(data); renatofilho@754: GstPadLinkReturn ret; renatofilho@754: char *s; renatofilho@20: renatofilho@754: s = gst_caps_to_string(pad->caps); renatofilho@754: renatofilho@754: if (s[0] == 'a') { renatofilho@754: ret = renatofilho@754: gst_pad_link(pad, renatofilho@754: gst_element_get_pad(tvplayer->audioqueue1, renatofilho@754: "sink")); renatofilho@754: } else { renatofilho@754: ret = renatofilho@754: gst_pad_link(pad, renatofilho@754: gst_element_get_pad(tvplayer->videoqueue1, renatofilho@754: "sink")); renatofilho@754: } renatofilho@754: renatofilho@754: g_free(s); renatofilho@20: } renatofilho@20: renatofilho@754: static gboolean renatofilho@754: expose_cb(GtkWidget * widget, GdkEventExpose * event, gpointer user_data) renatofilho@20: { renatofilho@754: MMythTVPlayer *tvplayer = MMYTH_TVPLAYER(user_data); renatofilho@20: renatofilho@754: if (tvplayer && tvplayer->videow) { renatofilho@754: gst_x_overlay_set_xwindow_id(GST_X_OVERLAY renatofilho@754: (tvplayer->gst_videosink), renatofilho@754: GDK_WINDOW_XWINDOW(widget->window)); renatofilho@754: return TRUE; renatofilho@754: } rosfran@64: renatofilho@754: g_warning("MMythTVPlayer expose called before setting video window\n"); rosfran@64: renatofilho@754: return FALSE; renatofilho@20: } renatofilho@20: renatofilho@20: static void renatofilho@754: mmyth_tvplayer_init(MMythTVPlayer * tvplayer) renatofilho@20: { renatofilho@754: tvplayer->gst_pipeline = NULL; renatofilho@754: tvplayer->gst_source = NULL; renatofilho@754: tvplayer->gst_videodec = NULL; renatofilho@754: tvplayer->gst_videosink = NULL; renatofilho@754: tvplayer->gst_videocolortrs = NULL; renatofilho@754: tvplayer->videoqueue1 = NULL; renatofilho@754: tvplayer->videoqueue2 = NULL; renatofilho@754: tvplayer->audioqueue1 = NULL; renatofilho@754: tvplayer->audioqueue2 = NULL; rosfran@64: renatofilho@754: /* renatofilho@754: * GTKWidget for rendering the video renatofilho@754: */ renatofilho@754: tvplayer->videow = NULL; renatofilho@754: tvplayer->expose_handler = 0; rosfran@64: renatofilho@754: tvplayer->backend_hostname = NULL; renatofilho@754: tvplayer->backend_port = 0; renatofilho@754: tvplayer->local_hostname = NULL; renatofilho@20: renatofilho@754: tvplayer->recorder = NULL; renatofilho@754: tvplayer->tvchain = NULL; renatofilho@754: tvplayer->proginfo = NULL; renatofilho@20: } renatofilho@20: renatofilho@20: static void renatofilho@754: mmyth_tvplayer_dispose(GObject * object) renatofilho@20: { renatofilho@20: renatofilho@754: G_OBJECT_CLASS(mmyth_tvplayer_parent_class)->dispose(object); renatofilho@20: } renatofilho@20: renatofilho@20: static void renatofilho@754: mmyth_tvplayer_finalize(GObject * object) renatofilho@20: { renatofilho@754: g_signal_handlers_destroy(object); renatofilho@20: renatofilho@754: MMythTVPlayer *tvplayer = MMYTH_TVPLAYER(object); renatofilho@20: renatofilho@754: g_debug("[%s] Finalizing tvplayer", __FUNCTION__); renatofilho@20: renatofilho@754: if (tvplayer->videow != NULL) { renatofilho@754: if (g_signal_handler_is_connected(tvplayer->videow, renatofilho@754: tvplayer->expose_handler)) { renatofilho@754: g_signal_handler_disconnect(tvplayer->videow, renatofilho@754: tvplayer->expose_handler); renatofilho@754: } renatofilho@754: g_object_unref(tvplayer->videow); renatofilho@754: } renatofilho@20: renatofilho@754: if (tvplayer->recorder != NULL) renatofilho@754: g_object_unref(tvplayer->recorder); renatofilho@754: if (tvplayer->tvchain != NULL) renatofilho@754: g_object_unref(tvplayer->tvchain); renatofilho@754: if (tvplayer->proginfo != NULL) renatofilho@754: g_object_unref(tvplayer->proginfo); renatofilho@754: renatofilho@754: // Release Gstreamer elements renatofilho@754: if (tvplayer->gst_pipeline != NULL) renatofilho@754: g_object_unref(tvplayer->gst_pipeline); renatofilho@754: if (tvplayer->gst_source != NULL) renatofilho@754: g_object_unref(tvplayer->gst_source); renatofilho@754: if (tvplayer->gst_videodec != NULL) renatofilho@754: g_object_unref(tvplayer->gst_videodec); renatofilho@754: if (tvplayer->gst_videocolortrs != NULL) renatofilho@754: g_object_unref(tvplayer->gst_videocolortrs); renatofilho@754: if (tvplayer->gst_videosink != NULL) renatofilho@754: g_object_unref(tvplayer->gst_videosink); renatofilho@754: if (tvplayer->videoqueue1 != NULL) renatofilho@754: g_object_unref(tvplayer->videoqueue1); renatofilho@754: if (tvplayer->videoqueue2 != NULL) renatofilho@754: g_object_unref(tvplayer->videoqueue2); renatofilho@754: if (tvplayer->audioqueue1 != NULL) renatofilho@754: g_object_unref(tvplayer->audioqueue1); renatofilho@754: if (tvplayer->audioqueue2 != NULL) renatofilho@754: g_object_unref(tvplayer->audioqueue2); renatofilho@754: renatofilho@754: G_OBJECT_CLASS(mmyth_tvplayer_parent_class)->finalize(object); renatofilho@20: } renatofilho@20: renatofilho@20: /** Creates a new instance of MMythTVPlayer. renatofilho@20: * renatofilho@20: * @return a new instance of MMythTVPlayer. renatofilho@20: */ renatofilho@754: MMythTVPlayer * renatofilho@754: mmyth_tvplayer_new() renatofilho@20: { renatofilho@754: MMythTVPlayer *tvplayer = renatofilho@754: MMYTH_TVPLAYER(g_object_new(MMYTH_TVPLAYER_TYPE, NULL)); renatofilho@754: renatofilho@20: return tvplayer; renatofilho@20: } renatofilho@20: renatofilho@20: /** Initializes the tv player. renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: * @return gboolean TRUE if the pipeline was created renatofilho@20: * successfully, FALSE otherwise. renatofilho@20: */ renatofilho@20: gboolean renatofilho@754: mmyth_tvplayer_initialize(MMythTVPlayer * tvplayer, renatofilho@754: GMythBackendInfo * backend_info) renatofilho@20: { renatofilho@754: tvplayer->backend_info = backend_info; rosfran@208: renatofilho@754: if (!mmyth_tvplayer_create_pipeline(tvplayer)) { renatofilho@754: g_warning renatofilho@754: ("[%s] Error while creating pipeline. TV Player not initialized", renatofilho@754: __FUNCTION__); renatofilho@754: return FALSE; renatofilho@754: } else { renatofilho@754: g_debug("[%s] GStreamer pipeline created", __FUNCTION__); renatofilho@754: } renatofilho@20: renatofilho@754: return TRUE; renatofilho@20: } renatofilho@20: renatofilho@20: /** Creates the GStreamer pipeline used by the player. renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: * @return gboolean TRUE if the pipeline was created renatofilho@20: * successfully, FALSE otherwise. renatofilho@20: */ renatofilho@754: static gboolean renatofilho@754: mmyth_tvplayer_create_pipeline(MMythTVPlayer * tvplayer) renatofilho@20: { renatofilho@754: GstElement *pipeline; renatofilho@754: GstElement *source, renatofilho@754: *parser; renatofilho@754: GstElement *videodec, renatofilho@754: *videosink; renatofilho@754: GstElement *videocolortrs; renatofilho@754: #ifndef MAEMO_PLATFORM renatofilho@754: GstElement *audiodec, renatofilho@754: *audioconv, renatofilho@754: *audioqueue2; renatofilho@20: #endif renatofilho@754: GstElement *audiosink; renatofilho@754: GstElement *videoqueue1, renatofilho@754: *videoqueue2, renatofilho@754: *audioqueue1; renatofilho@20: renatofilho@754: g_debug("MMythTVPlayer: Setting the Gstreamer pipeline\n"); renatofilho@20: renatofilho@754: pipeline = gst_pipeline_new("video-player"); renatofilho@754: source = gst_element_factory_make("mythtvsrc", "myth-source"); renatofilho@754: parser = gst_element_factory_make("nuvdemux", "nuv-demux"); renatofilho@754: renatofilho@754: /* renatofilho@754: * Gstreamer Video elements renatofilho@754: */ renatofilho@754: videoqueue1 = gst_element_factory_make("queue", "video-queue1"); renatofilho@754: videodec = gst_element_factory_make("ffdec_mpeg4", "video-decoder"); renatofilho@754: videoqueue2 = gst_element_factory_make("queue", "video-queue2"); renatofilho@754: videocolortrs = renatofilho@754: gst_element_factory_make("ffmpegcolorspace", renatofilho@754: "image-color-transforms"); rosfran@64: renatofilho@20: #ifdef MAEMO_PLATFORM renatofilho@754: videosink = gst_element_factory_make("sdlvideosink", "image-output"); renatofilho@20: #else renatofilho@754: videosink = gst_element_factory_make("xvimagesink", "image-output"); renatofilho@20: #endif renatofilho@754: renatofilho@754: /* renatofilho@754: * Gstreamer Audio elements renatofilho@754: */ renatofilho@754: audioqueue1 = gst_element_factory_make("queue", "audio-queue1"); renatofilho@754: #ifdef MAEMO_PLATFORM renatofilho@754: audiosink = gst_element_factory_make("dspmp3sink", "audio-output"); renatofilho@754: #else renatofilho@754: audioqueue2 = gst_element_factory_make("queue", "audio-queue2"); renatofilho@754: audiodec = gst_element_factory_make("mad", "audio-decoder"); renatofilho@754: audioconv = renatofilho@754: gst_element_factory_make("audioconvert", "audio-converter"); renatofilho@754: audiosink = gst_element_factory_make("alsasink", "audio-output"); renatofilho@754: #endif renatofilho@754: renatofilho@20: if (!(pipeline && source && parser && videodec && videosink) || renatofilho@754: !(videoqueue1 && videoqueue2 && audioqueue1 && audiosink)) { renatofilho@754: /* renatofilho@754: * FIXME: hanlde the error correctly renatofilho@754: */ renatofilho@754: /* renatofilho@754: * video_alignment is not being created (below) and is causing renatofilho@754: * problems to the ui renatofilho@754: */ renatofilho@20: renatofilho@754: tvplayer->gst_pipeline = NULL; renatofilho@754: tvplayer->gst_videodec = NULL; renatofilho@754: tvplayer->gst_videosink = NULL; renatofilho@754: tvplayer->gst_videocolortrs = NULL; renatofilho@754: renatofilho@754: g_warning("GstElement creation error!\n"); renatofilho@20: return FALSE; renatofilho@20: } renatofilho@754: #ifndef MAEMO_PLATFORM renatofilho@20: if (!(audiodec && audioconv)) { renatofilho@754: g_warning("GstElement for audio stream creation error!"); renatofilho@20: return FALSE; renatofilho@20: } renatofilho@754: #endif renatofilho@754: renatofilho@20: tvplayer->gst_pipeline = pipeline; renatofilho@20: tvplayer->gst_source = source; renatofilho@20: tvplayer->gst_videodec = videodec; renatofilho@20: tvplayer->gst_videosink = videosink; rosfran@64: tvplayer->gst_videocolortrs = videocolortrs; renatofilho@754: g_object_ref(tvplayer->gst_pipeline); renatofilho@754: g_object_ref(tvplayer->gst_source); renatofilho@754: g_object_ref(tvplayer->gst_videodec); renatofilho@754: g_object_ref(tvplayer->gst_videosink); renatofilho@754: g_object_ref(tvplayer->gst_videocolortrs); renatofilho@20: rosfran@64: tvplayer->videoqueue1 = videoqueue1; rosfran@64: tvplayer->videoqueue2 = videoqueue2; rosfran@64: tvplayer->audioqueue1 = audioqueue1; renatofilho@754: g_object_ref(tvplayer->videoqueue1); renatofilho@754: g_object_ref(tvplayer->videoqueue2); renatofilho@754: g_object_ref(tvplayer->audioqueue1); renatofilho@754: rosfran@414: #ifndef MAEMO_PLATFORM rosfran@415: tvplayer->audioqueue2 = audioqueue2; renatofilho@754: g_object_ref(tvplayer->audioqueue2); rosfran@414: #endif renatofilho@20: renatofilho@754: // g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL); renatofilho@754: g_object_set(G_OBJECT(audiosink), "sync", FALSE, NULL); renatofilho@20: renatofilho@754: gst_bus_add_watch(gst_pipeline_get_bus renatofilho@754: (GST_PIPELINE(tvplayer->gst_pipeline)), bus_call, renatofilho@754: tvplayer); renatofilho@754: renatofilho@754: gst_bin_add_many(GST_BIN(pipeline), source, parser, videoqueue1, renatofilho@754: videodec, videoqueue2, videocolortrs, videosink, renatofilho@754: NULL); rosfran@414: rosfran@414: #ifndef MAEMO_PLATFORM renatofilho@754: gst_bin_add_many(GST_BIN(pipeline), audioqueue1, audiodec, audioconv, renatofilho@754: audioqueue2, audiosink, NULL); rosfran@414: #else renatofilho@754: gst_bin_add_many(GST_BIN(pipeline), audioqueue1, audiosink, NULL); rosfran@414: #endif renatofilho@20: renatofilho@20: { renatofilho@754: // GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", renatofilho@754: // NULL); renatofilho@754: // gst_element_link_filtered(source, parser, rtpcaps); renatofilho@20: } renatofilho@754: renatofilho@754: gst_element_link(source, parser); renatofilho@754: gst_element_link_many(videoqueue1, videodec, videoqueue2, renatofilho@754: videocolortrs, videosink, NULL); renatofilho@754: rosfran@414: #ifndef MAEMO_PLATFORM renatofilho@754: gst_element_link_many(videosink, audioqueue1, audiodec, audioconv, renatofilho@754: audioqueue2, audiosink, NULL); rosfran@414: #else renatofilho@754: gst_element_link_many(videosink, audioqueue1, audiosink, NULL); rosfran@414: #endif renatofilho@754: renatofilho@754: g_signal_connect(parser, "pad-added", G_CALLBACK(new_pad_cb), renatofilho@754: tvplayer); renatofilho@754: renatofilho@20: return TRUE; renatofilho@20: } renatofilho@20: renatofilho@20: /** Configures the backend and the tv player renatofilho@20: * for playing the recorded content A/V. renatofilho@20: * renatofilho@20: * FIXME: Change filename to program info or other structure about the recorded renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: * @param filename the file uri of the recorded content to be played. renatofilho@20: * @return TRUE if successfull, FALSE if any error happens. renatofilho@20: */ renatofilho@20: gboolean renatofilho@754: mmyth_tvplayer_record_setup(MMythTVPlayer * tvplayer, renatofilho@754: const gchar * filename) renatofilho@20: { renatofilho@754: // FIXME: we should receive the uri instead of filename renatofilho@754: const gchar *hostname = renatofilho@754: gmyth_backend_info_get_hostname(tvplayer->backend_info); renatofilho@754: const gint port = renatofilho@754: gmyth_backend_info_get_port(tvplayer->backend_info); renatofilho@20: renatofilho@754: GString *fullpath = g_string_new("myth://"); renatofilho@754: g_string_append_printf(fullpath, "%s:%d/%s", hostname, port, filename); renatofilho@754: renatofilho@754: tvplayer->is_livetv = FALSE; renatofilho@754: renatofilho@754: g_debug("[%s] Setting record uri to gstreamer pipeline to %s", renatofilho@754: __FUNCTION__, fullpath->str); renatofilho@754: renatofilho@754: g_object_set(G_OBJECT(tvplayer->gst_source), "location", renatofilho@754: fullpath->str, NULL); renatofilho@754: renatofilho@20: return TRUE; renatofilho@20: } renatofilho@20: renatofilho@20: /** Configures the backend and the tv player renatofilho@20: * for playing the live tv. renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: * @return TRUE if successfull, FALSE if any error happens. renatofilho@20: */ renatofilho@20: gboolean renatofilho@754: mmyth_tvplayer_livetv_setup(MMythTVPlayer * tvplayer) renatofilho@20: { renatofilho@754: gboolean res = TRUE; renatofilho@20: renatofilho@754: tvplayer->livetv = gmyth_livetv_new(); rosfran@208: renatofilho@754: if (!gmyth_livetv_setup(tvplayer->livetv, tvplayer->backend_info)) renatofilho@754: goto error; renatofilho@20: renatofilho@754: return res; renatofilho@20: renatofilho@754: error: renatofilho@754: res = FALSE; renatofilho@754: if (tvplayer->livetv != NULL) { renatofilho@754: g_object_unref(tvplayer->livetv); renatofilho@754: } renatofilho@20: renatofilho@754: if (tvplayer->local_hostname != NULL) { renatofilho@754: g_string_free(tvplayer->local_hostname, TRUE); renatofilho@754: } renatofilho@20: renatofilho@754: if (tvplayer->recorder != NULL) { renatofilho@754: g_object_unref(tvplayer->recorder); renatofilho@754: tvplayer->recorder = NULL; renatofilho@754: } renatofilho@20: renatofilho@754: if (tvplayer->tvchain != NULL) { renatofilho@754: g_object_unref(tvplayer->tvchain); renatofilho@754: tvplayer->tvchain = NULL; renatofilho@754: } renatofilho@20: renatofilho@754: if (tvplayer->proginfo != NULL) { renatofilho@754: g_object_unref(tvplayer->proginfo); renatofilho@754: tvplayer->proginfo = NULL; renatofilho@754: } renatofilho@754: renatofilho@754: return res; renatofilho@20: renatofilho@20: } renatofilho@20: renatofilho@20: /** Sets the GTK video widget for the tv player. renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: * @param videow the GTK video window. renatofilho@20: * @return TRUE if successfull, FALSE if any error happens. renatofilho@20: */ renatofilho@20: gboolean renatofilho@754: mmyth_tvplayer_set_widget(MMythTVPlayer * tvplayer, GtkWidget * videow) renatofilho@20: { renatofilho@754: tvplayer->videow = videow; renatofilho@754: g_object_ref(videow); renatofilho@20: renatofilho@754: g_debug("[%s] Setting widget for tv player render", __FUNCTION__); renatofilho@754: renatofilho@754: tvplayer->expose_handler = renatofilho@754: g_signal_connect(tvplayer->videow, "expose-event", renatofilho@754: G_CALLBACK(expose_cb), tvplayer); renatofilho@754: renatofilho@754: // g_signal_connect(miptv_ui->videow, "size_request", renatofilho@754: // G_CALLBACK(cb_preferred_video_size), miptv_ui); renatofilho@20: renatofilho@20: return TRUE; renatofilho@20: } renatofilho@20: renatofilho@754: static gboolean renatofilho@754: bus_call(GstBus * bus, GstMessage * msg, gpointer data) renatofilho@20: { renatofilho@754: // MMythTVPlayer *tvplayer = MMYTH_TVPLAYER ( data ); renatofilho@754: // GMainLoop *loop = tvplayer->loop; renatofilho@20: renatofilho@754: switch (GST_MESSAGE_TYPE(msg)) { renatofilho@754: case GST_MESSAGE_EOS: renatofilho@754: printf("End of stream\n"); renatofilho@754: // g_idle_add ((GSourceFunc) idle_eos, data); renatofilho@754: gst_element_set_state(GST_ELEMENT(GST_MESSAGE_SRC(msg)), renatofilho@754: GST_STATE_NULL); renatofilho@754: gst_element_set_locked_state(GST_ELEMENT(GST_MESSAGE_SRC(msg)), renatofilho@754: TRUE); renatofilho@754: break; renatofilho@754: case GST_MESSAGE_ERROR: renatofilho@20: { renatofilho@754: gchar *debug; renatofilho@754: GError *err; renatofilho@20: renatofilho@754: gst_message_parse_error(msg, &err, &debug); renatofilho@754: g_free(debug); renatofilho@20: renatofilho@754: printf("Error: %s\n", err->message); renatofilho@754: g_error_free(err); renatofilho@20: renatofilho@754: // g_main_loop_quit (loop); renatofilho@20: } renatofilho@754: break; renatofilho@754: default: renatofilho@754: printf(gst_message_type_get_name(GST_MESSAGE_TYPE(msg))); renatofilho@754: printf("\n"); renatofilho@754: break; renatofilho@20: } renatofilho@20: renatofilho@20: return TRUE; renatofilho@20: } renatofilho@20: renatofilho@20: renatofilho@20: #if 0 renatofilho@754: static gboolean renatofilho@754: idle_state(gpointer data) renatofilho@20: { renatofilho@20: GstPlayerWindowStateChange *st = data; renatofilho@20: renatofilho@20: if (st->old_state == GST_STATE_PLAYING) { renatofilho@20: if (st->miptv_ui->idle_id != 0) { renatofilho@754: g_source_remove(st->miptv_ui->idle_id); renatofilho@20: st->miptv_ui->idle_id = 0; renatofilho@20: } renatofilho@754: } else if (st->new_state == GST_STATE_PLAYING) { renatofilho@20: if (st->miptv_ui->idle_id != 0) renatofilho@754: g_source_remove(st->miptv_ui->idle_id); renatofilho@20: renatofilho@754: st->miptv_ui->idle_id = g_idle_add(cb_iterate, st->miptv_ui); renatofilho@20: } renatofilho@20: renatofilho@754: /* renatofilho@754: * new movie loaded? renatofilho@754: */ renatofilho@754: if (st->old_state == GST_STATE_READY renatofilho@754: && st->new_state > GST_STATE_READY) { renatofilho@20: renatofilho@754: /* renatofilho@754: * gboolean have_video = FALSE; renatofilho@754: */ renatofilho@20: renatofilho@754: gtk_widget_show(st->miptv_ui->videow); renatofilho@20: renatofilho@754: gtk_window_resize(GTK_WINDOW(st->miptv_ui->main_window), 1, 1); renatofilho@20: renatofilho@20: } renatofilho@20: renatofilho@754: /* renatofilho@754: * discarded movie? renatofilho@754: */ renatofilho@754: if (st->old_state > GST_STATE_READY renatofilho@754: && st->new_state == GST_STATE_READY) { renatofilho@20: renatofilho@20: if (st->miptv_ui->tagcache) { renatofilho@754: gst_tag_list_free(st->miptv_ui->tagcache); renatofilho@20: st->miptv_ui->tagcache = NULL; renatofilho@20: } renatofilho@20: } renatofilho@20: renatofilho@754: gst_object_unref(GST_OBJECT(st->play)); renatofilho@754: // g_object_unref (G_OBJECT (st->win)); renatofilho@754: g_free(st); renatofilho@20: renatofilho@754: /* renatofilho@754: * once renatofilho@754: */ renatofilho@20: return FALSE; renatofilho@20: } renatofilho@20: renatofilho@20: #endif renatofilho@20: renatofilho@20: /** Stops playing the current A/V. renatofilho@20: * renatofilho@20: * FIXME: How to proceed differently between livetv renatofilho@20: * and recorded content? renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: * @return void renatofilho@20: */ renatofilho@20: void renatofilho@754: mmyth_tvplayer_stop_playing(MMythTVPlayer * tvplayer) renatofilho@20: { renatofilho@754: g_debug("[%s] Setting gstreamer pipeline state to NULL", __FUNCTION__); renatofilho@20: renatofilho@754: gst_element_set_state(tvplayer->gst_pipeline, GST_STATE_NULL); renatofilho@754: renatofilho@20: if (tvplayer->is_livetv) { renatofilho@754: if (!gmyth_recorder_stop_livetv(tvplayer->recorder)) { renatofilho@754: g_warning("[%s] Error while stoping remote encoder", renatofilho@754: __FUNCTION__); renatofilho@754: } renatofilho@20: } renatofilho@20: } renatofilho@20: renatofilho@20: /** Queries if the tvplayer is active playing A/V content. renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: * @return TRUE if the tvplayer is active, FALSE otherwise. renatofilho@20: */ renatofilho@20: gboolean renatofilho@754: mmyth_tvplayer_is_playing(MMythTVPlayer * tvplayer) renatofilho@20: { renatofilho@754: return (GST_STATE(tvplayer->gst_pipeline) == GST_STATE_PLAYING); renatofilho@20: } renatofilho@20: renatofilho@20: /** Static function that sets the tvplayer state to PLAYING. renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: * @return TRUE if the tvplayer is active, FALSE otherwise. renatofilho@20: */ renatofilho@754: static gboolean renatofilho@754: idle_play(gpointer data) renatofilho@20: { renatofilho@754: MMythTVPlayer *tvplayer = MMYTH_TVPLAYER(data); renatofilho@20: renatofilho@754: g_debug("MMythTVPlayer: Setting pipeline state to PLAYING\n"); renatofilho@20: renatofilho@754: gst_element_set_state(tvplayer->gst_pipeline, GST_STATE_PLAYING); renatofilho@20: renatofilho@20: return FALSE; renatofilho@20: } renatofilho@20: renatofilho@20: /** Start playing A/V with the tvplayer attributes. renatofilho@20: * renatofilho@20: * @param tvplayer the object instance. renatofilho@20: */ renatofilho@20: void renatofilho@754: mmyth_tvplayer_start_playing(MMythTVPlayer * tvplayer) renatofilho@20: { renatofilho@20: renatofilho@754: // FIXME: Move this to livetv_setup?? renatofilho@754: if (tvplayer->is_livetv) { renatofilho@20: renatofilho@754: #if 0 renatofilho@754: if (!tvplayer || !(tvplayer->proginfo) renatofilho@754: || !(tvplayer->local_hostname) renatofilho@754: || !(tvplayer->gst_source)) { renatofilho@754: g_warning("GMythtvPlayer not ready to start playing\n"); renatofilho@754: } renatofilho@20: renatofilho@754: if (!(tvplayer->proginfo->pathname)) { renatofilho@754: g_warning renatofilho@754: ("[%s] Playback url is null, could not play the myth content", renatofilho@754: __FUNCTION__); renatofilho@754: return; renatofilho@754: } renatofilho@20: renatofilho@754: g_debug("MMythTVPlayer: Start playing %s", renatofilho@754: tvplayer->proginfo->pathname->str); renatofilho@20: #endif renatofilho@754: g_object_set(G_OBJECT(tvplayer->gst_source), "mythtv-live", renatofilho@754: TRUE, NULL); renatofilho@20: #if 0 renatofilho@754: if (tvplayer->tvchain != NULL) { renatofilho@754: GString *str_chainid = renatofilho@754: gmyth_tvchain_get_id(tvplayer->tvchain); renatofilho@754: g_print("[%s]\tCHAIN ID: %s\n", __FUNCTION__, renatofilho@754: str_chainid->str); renatofilho@20: renatofilho@754: g_object_set(G_OBJECT(tvplayer->gst_source), renatofilho@754: "mythtv-live-chainid", g_strdup(str_chainid->str), renatofilho@754: NULL); renatofilho@754: if (str_chainid != NULL) renatofilho@754: g_string_free(str_chainid, FALSE); renatofilho@754: } renatofilho@20: renatofilho@754: if (tvplayer->recorder != NULL) renatofilho@754: g_object_set(G_OBJECT(tvplayer->gst_source), "mythtv-live-id", renatofilho@754: tvplayer->recorder->recorder_num, NULL); renatofilho@754: g_debug("[%s] Setting location to %s", __FUNCTION__, renatofilho@754: tvplayer->proginfo->pathname->str); renatofilho@20: renatofilho@754: /* renatofilho@754: * Sets the gstreamer properties acording to the service access renatofilho@754: * address renatofilho@754: */ renatofilho@754: g_object_set(G_OBJECT(tvplayer->gst_source), "location", renatofilho@754: tvplayer->proginfo->pathname->str, NULL); renatofilho@20: #endif renatofilho@754: } renatofilho@20: renatofilho@754: g_object_set(G_OBJECT(tvplayer->gst_source), "mythtv-version", renatofilho@754: MYTHTV_VERSION_DEFAULT, NULL); renatofilho@20: renatofilho@754: g_object_set(G_OBJECT(tvplayer->gst_source), "mythtv-debug", renatofilho@754: TRUE, NULL); renatofilho@20: renatofilho@754: g_idle_add(idle_play, tvplayer); renatofilho@20: renatofilho@20: }