diff --git a/src/gui.c b/src/gui.c
index 3d4991d314276494ce4644058440e9fd44803986..a217ade9d85eadceca1aad78544a42972847e3bf 100644 (file)
--- a/src/gui.c
+++ b/src/gui.c
-/*\r
- * Copyright (c) 2010-2011, Texas Instruments Incorporated\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- *\r
- * * Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- *\r
- * * Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- *\r
- * * Neither the name of Texas Instruments Incorporated nor the names of\r
- * its contributors may be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- *\r
- * Contact information for paper mail:\r
- * Texas Instruments\r
- * Post Office Box 655303\r
- * Dallas, Texas 75265\r
- * Contact information:\r
- * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?\r
- * DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact\r
- * ============================================================================\r
- *\r
- */\r
-\r
-/**\r
- * @file gui.c\r
- *\r
- * @brief Implements a user interface for GStreamer A/V playback application.\r
- *\r
- * The user interface is designed using gtk library. The interaction between \r
- * user interface and backend GStreamer application happens through a shared\r
- * GStreamer element.\r
- */\r
-\r
-#include <stdint.h>\r
-#include <gtk/gtk.h>\r
-#include <gst/gst.h>\r
-\r
-/*\r
-this is required for storing the scale widget event handler id which is \r
-unregistered and registered at every timer event.\r
-*/\r
-static gint handlerId = -1;\r
-\r
-/*\r
-this pipeline is the playbin2 element used for playback for single stream.\r
-*/\r
-static GstElement *gPipeline = NULL;\r
-\r
-static GtkWidget *window = NULL; \r
-static GtkWidget *scaleSeek = NULL; \r
-static GtkWidget *labelTime = NULL; \r
-\r
-/*\r
-this variable stores the total duration of the media for global reference.\r
-*/\r
-static gint64 gTotalDuration = 0; \r
-\r
-#ifdef GST_APP_DEBUG \r
-#define debug(args...) g_print(args) \r
-#else\r
-#define debug(args...)\r
-#endif\r
-\r
-/**\r
- * @brief The close event handler for the window\r
- *\r
- * @param [IN] widget Pointer to the widget being closed\r
- * @param [IN] data user supplied data\r
- *\r
- * called from: Callback function. Called when the window widget is closed \r
- */\r
-static void close_callback (GtkWidget *widget, gpointer data){\r
- GstBus *bus = NULL;\r
- GstMessage *msg = NULL;\r
-\r
- /*window is being closed. post an EOS message on the pipeline's bus*/\r
- bus = gst_pipeline_get_bus(GST_PIPELINE(gPipeline));\r
- msg = gst_message_new_eos (NULL); \r
- gst_bus_post(bus,msg);\r
- gst_object_unref(bus);\r
-}\r
-\r
-/**\r
- * @brief The value change event handler for the scale widget\r
- *\r
- * @param [IN] widget Pointer to the widget whose value is being changed\r
- * @param [IN] data user supplied data\r
- *\r
- * called from: Callback function. Called when the value of the scaleSeek widget\r
- * is changed\r
- */\r
-static void scale_callback (GtkWidget *widget, gpointer data){\r
- gdouble percent = gtk_range_get_value((GtkRange *)widget);\r
- gint64 seek_point=(gint64)(gTotalDuration * percent/(gdouble)100);\r
-\r
- debug("seeking to %g secs\n",seek_point/(gdouble)1e9);\r
-\r
- gst_element_seek_simple (gPipeline,GST_FORMAT_TIME,\r
- GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_KEY_UNIT,seek_point);\r
- \r
-}\r
-\r
-/**\r
- * @brief The thread function to actually start gtk_main and wait for it to \r
- * complete\r
- *\r
- * @param [IN] data user supplied data\r
- *\r
- * called from: Callback function. Called when the idle thread is started from \r
- * init_gui() \r
- */\r
-\r
-static gboolean runFunc(gpointer data){\r
- gtk_main();\r
-}\r
-\r
-/*******************************************************************************\r
- * see gui.h\r
- ******************************************************************************/\r
-void exit_application(){\r
- gtk_widget_destroy(window);\r
- gtk_main_quit(); \r
-}\r
-\r
-/*******************************************************************************\r
- * see gui.h\r
- ******************************************************************************/\r
-void init_gui (int *argc, char **argv[], GstElement *inpipeline){ \r
- GtkWidget *buttonPlayPause; \r
- GtkWidget *buttonStop; \r
- GtkWidget *buttonOpen; \r
- GtkWidget *boxPacker; \r
-\r
- gPipeline = inpipeline; \r
-\r
- /*TODO: error handling. what if no X11 support is there?*/\r
-\r
- gtk_init (argc, argv);\r
- \r
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);\r
- gtk_window_set_title (GTK_WINDOW (window), "Player");\r
- gtk_window_resize (GTK_WINDOW (window), 1200, 50);\r
-\r
- buttonPlayPause = gtk_button_new_with_label ("Play");\r
- gtk_widget_set_sensitive(buttonPlayPause,FALSE);\r
- buttonOpen = gtk_button_new_with_label ("Open");\r
- gtk_widget_set_sensitive(buttonOpen,FALSE);\r
- buttonStop = gtk_button_new_with_label ("Stop");\r
- gtk_widget_set_sensitive(buttonStop,FALSE);\r
- scaleSeek = gtk_hscale_new_with_range (0.0, 100.0, 2.0);\r
- labelTime = gtk_label_new ("--/--");\r
-\r
- handlerId = g_signal_connect (scaleSeek, "value_changed", \r
- G_CALLBACK(scale_callback), NULL);\r
- g_signal_connect (window, "delete_event", G_CALLBACK (close_callback), NULL);\r
-\r
- boxPacker = gtk_table_new (2, 10, TRUE);\r
-\r
- gtk_table_attach_defaults (GTK_TABLE (boxPacker), buttonOpen, 0, 2, 0, 1);\r
- gtk_table_attach_defaults (GTK_TABLE (boxPacker), buttonPlayPause, \r
- 0, 1, 1, 2);\r
- gtk_table_attach_defaults (GTK_TABLE (boxPacker), buttonStop, 1, 2, 1, 2);\r
- gtk_table_attach_defaults (GTK_TABLE (boxPacker), scaleSeek, 2, 9, 0, 2);\r
- gtk_table_attach_defaults (GTK_TABLE (boxPacker), labelTime, 9, 10, 0, 2);\r
- \r
- gtk_container_add (GTK_CONTAINER (window), boxPacker); \r
-\r
- gtk_widget_show_all (window);\r
- \r
- /*return from the function. an idle thread will continue the gtk_main loop*/\r
- gdk_threads_add_idle(runFunc,NULL);\r
- \r
-} \r
-\r
-/*******************************************************************************\r
- * see gui.h\r
- ******************************************************************************/\r
-void set_duration (gint64 totalDuration, gint64 currPosition){\r
- /*\r
- 100 char string, very blind estimation. later seconds will be changed to \r
- hh:mm:ss format. the actual length will be decided at that time. \r
- */\r
- gchar *str = NULL;\r
- gdouble newTrackVal = 0;\r
-\r
- gTotalDuration = totalDuration;\r
- str=g_malloc(100);\r
- if(NULL == str)\r
- return;\r
- \r
- newTrackVal = (gdouble)currPosition / (gdouble)totalDuration * 100; \r
-\r
- /*\r
- this is required to disconnect the value-changed signal handler. otherwise\r
- the next statement will also trigger the value changed signal handler\r
- */\r
- gtk_signal_disconnect (scaleSeek, handlerId);\r
-\r
- gtk_range_set_value (GTK_RANGE (scaleSeek), (gdouble)newTrackVal);\r
-\r
- /*connect the event handler again*/\r
- handlerId = g_signal_connect (scaleSeek, "value_changed", \r
- G_CALLBACK(scale_callback), NULL);\r
-\r
- g_sprintf(str,"%ld/%ld",currPosition/(gint64)1e9,totalDuration/(gint64)1e9); \r
- gtk_label_set_text ((GtkLabel *)labelTime, str);\r
- g_free(str);\r
-}\r
+/*
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contact information for paper mail:
+ * Texas Instruments
+ * Post Office Box 655303
+ * Dallas, Texas 75265
+ * Contact information:
+ * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm
+ * ?DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
+ * ============================================================================
+ *
+ */
+
+/**
+ * @file gui.c
+ *
+ * @brief Defines the functions exported by the GUI.
+ * Also, defines the static functions and the callback funtions
+ */
+#include <string.h>
+#include <linux/limits.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gst/interfaces/xoverlay.h>
+
+#include <gui.h>
+#include <common.h>
+#include <gst-controller.h>
+
+/******************************************************************************
+
+ Static variables declaration
+
+*****************************************************************************/
+static GUIWindow *window[] = {NULL, NULL};
+static Pipeline *pipes[] = {NULL, NULL};
+static GtkWidget *logWindow[] = {NULL, NULL};
+static GtkWidget *helpWindow = NULL;
+
+
+/******************************************************************************
+
+ Static functions declaration
+
+ ******************************************************************************/
+static gint setAbsolutePathname (gchar *file, gchar **uri) ;
+static void setControlMode (GUIWindow *thisWindow,gint modeFlag,gint activeFlag);
+static void setControlActive (GUIWindow *window, gboolean activeFlag);
+static void setup();
+static void setDecodeSwitch (gint decodeSwitch);
+static GtkWidget *createLogWindow();
+static GtkWidget *createHelpWindow();
+static GstElement *createImageSinkFromWindow (GtkWidget * window, gchar *name);
+static void setWindowSizeLocation();
+static GUIWindow *createWindow();
+
+static gboolean cbOpenClicked (GtkWidget *widget, gpointer data);
+static gboolean cbPlayClicked (GtkWidget *widget, gpointer data);
+static gboolean cbPauseClicked (GtkWidget *widget, gpointer data);
+static gboolean cbStopClicked (GtkWidget *widget, gpointer data);
+static gboolean cbForwardClicked (GtkWidget *widget, gpointer data);
+static gboolean cbRewindClicked (GtkWidget *widget, gpointer data);
+static gboolean cbWindowClosed (GtkWidget *widget, gpointer data);
+static gboolean cbHelpClicked (GtkWidget *widget, gpointer data);
+static gboolean cbTimerInterval (gpointer data);
+static gboolean cbSeekValueChanged (GtkWidget *widget, gpointer data);
+static gboolean cbSwitchButtonClicked (GtkWidget *widget, gpointer data);
+static gboolean cbHelpClosed (GtkWidget *widget, gpointer data);
+//static void logGUI (GtkWidget *logWindow, gchar *format, ...);
+
+static gint setAbsolutePathname (gchar *file, gchar **uri)
+{
+ gchar *realPath = NULL;
+ gint ret = ERR_SUCCESS;
+
+ if(NULL == uri){
+ return ERR_INVALIDPARAM;
+ }
+
+ if(NULL == file){
+ /*A BUG Here*/
+ g_printerr("BUG: file: " __FILE__ " line: %d" "\n", __LINE__);
+ return ERR_BUG;
+ }
+
+ *uri = (gchar *) g_malloc (sizeof(gchar) * PATH_MAX_LEN);
+ realPath = realpath (file, realPath);
+ if (NULL == realPath) {
+ /*TODO: a debug trace here*/
+ g_printerr ("File %s not found\n", file);
+ ret = ERR_FILENOTFOUND;
+ goto destroy;
+ }
+ g_snprintf(*uri,PATH_MAX_LEN,"file://%s",realPath);
+
+ goto last;
+
+destroy:
+ g_free(*uri);
+ *uri=NULL;
+last:
+ free (realPath);
+ return ret;
+}
+/******************************************************************************
+
+ Callback functions definition
+
+ ******************************************************************************/
+
+/*Timer Interval Callback Function*/
+static gboolean cbTimerInterval(gpointer data)
+{
+ gdouble seekScaleValue = 0.0;
+ gchar *timeLabelText = TIME_LABEL_ORIGIN;
+ GUIWindow *thisWindow = (GUIWindow *)data;
+ gboolean ret = TRUE;
+
+ //g_print ("IN timer");
+ if (DECODE_MODE_SINGLE == decodeMode){
+ ret = DualDecode_getMediaPosition(pipes[DECODER_INDEX_SINGLE],
+ &seekScaleValue,
+ &timeLabelText);
+ //g_print ("Seek Value %f", seekScaleValue);
+
+ g_signal_handler_block (window[DECODER_INDEX_SINGLE]->seekScale,
+ window[DECODER_INDEX_SINGLE]->seekSignal);
+ gtk_range_set_value (GTK_RANGE(window[DECODER_INDEX_SINGLE]->seekScale),
+ seekScaleValue);
+ gtk_label_set_text (GTK_LABEL (window[DECODER_INDEX_SINGLE]->timeLabel),
+ timeLabelText);
+ g_signal_handler_unblock (GTK_RANGE(window[DECODER_INDEX_SINGLE]->seekScale),
+ window[DECODER_INDEX_SINGLE]->seekSignal);
+
+ g_signal_handler_block (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
+ window[DECODER_INDEX_DOUBLE]->seekSignal);
+ gtk_range_set_value(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
+ seekScaleValue);
+ gtk_label_set_text(GTK_LABEL (window[DECODER_INDEX_DOUBLE]->timeLabel),
+ timeLabelText);
+ g_signal_handler_unblock(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
+ window[DECODER_INDEX_DOUBLE]->seekSignal);
+ }else{
+ if (window[DECODER_INDEX_SINGLE] == thisWindow){
+ ret = DualDecode_getMediaPosition(pipes[DECODER_INDEX_SINGLE],
+ &seekScaleValue,
+ &timeLabelText);
+
+ g_signal_handler_block (GTK_RANGE(window[DECODER_INDEX_SINGLE]->seekScale),
+ window[DECODER_INDEX_SINGLE]->seekSignal);
+ gtk_range_set_value (GTK_RANGE (window[DECODER_INDEX_SINGLE]->seekScale),
+ seekScaleValue);
+ gtk_label_set_text (GTK_LABEL (window[DECODER_INDEX_SINGLE]->timeLabel),
+ timeLabelText);
+ g_signal_handler_unblock (GTK_RANGE (window[DECODER_INDEX_SINGLE]->seekScale),
+ window[DECODER_INDEX_SINGLE]->seekSignal);
+ }else{
+ ret = DualDecode_getMediaPosition (pipes[DECODER_INDEX_DOUBLE],
+ &seekScaleValue,
+ &timeLabelText);
+
+ g_signal_handler_block (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
+ window[DECODER_INDEX_DOUBLE]->seekSignal);
+ gtk_range_set_value (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
+ seekScaleValue);
+ gtk_label_set_text (GTK_LABEL(window[DECODER_INDEX_DOUBLE]->timeLabel),
+ timeLabelText);
+ g_signal_handler_unblock(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
+ window[DECODER_INDEX_DOUBLE]->seekSignal);
+ }
+ }
+ if(ret){
+ g_free(timeLabelText);
+ }
+ return ret;
+}
+
+/*Seek Scale Changed Value Callback Function*/
+static gboolean cbSeekValueChanged(GtkWidget *widget, gpointer data)
+{
+ gboolean ret = TRUE;
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 duration = 0;
+ gint seekPoint = 0;
+ gdouble percent = gtk_range_get_value ((GtkRange *)widget);
+ g_print ("PERCENT %f\n", percent);
+ GUIWindow *thisWindow = (GUIWindow *)data;
+
+ g_print ("IN SEEK VALUE CHANGED\n");
+ if (DECODE_MODE_SINGLE == decodeMode){
+
+ gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format,&duration);
+ seekPoint = (gint64) (duration * percent/ (gdouble)100);
+ g_print ("SEEK POINT %d\n", seekPoint);
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_SINGLE], seekPoint);
+ }
+ else{
+ if(window[DECODER_INDEX_SINGLE] == thisWindow){
+ gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format,&duration);
+ seekPoint = (gint64) (duration * percent/ (gdouble)100);
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_SINGLE], seekPoint);
+ }
+ else {
+ gst_element_query_duration(pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format,&duration);
+ seekPoint = (gint64) (duration * percent/ (gdouble)100);
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_DOUBLE], seekPoint);
+ }
+ }
+
+ return ret;
+}
+
+/*Open Button Clicked Callback Function*/
+static gboolean cbOpenClicked(GtkWidget *widget, gpointer data)
+{
+ gboolean ret = TRUE;
+ gchar *uri = NULL;
+ gchar *file = NULL;
+ GUIWindow *thisWindow = (GUIWindow *)data;
+ GtkWidget *fileChooser = gtk_file_chooser_dialog_new(
+ "Open",
+ GTK_WINDOW(thisWindow->window),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_OK,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ NULL);
+ gtk_window_set_modal(GTK_WINDOW(fileChooser),TRUE);
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(fileChooser),TRUE);
+ gtk_widget_set_sensitive(thisWindow->window,FALSE);
+
+ if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(fileChooser))){
+
+ file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileChooser));
+
+ if (ERR_SUCCESS != setAbsolutePathname (file, &uri)){
+ ret = FALSE;
+ goto last;
+ }
+ //g_print ("FILE URI :%s", uri);
+ if(DECODE_MODE_SINGLE == decodeMode){
+ filename[DECODER_INDEX_SINGLE] = uri;
+ setControlMode(window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_PLAYING,
+ window[DECODER_INDEX_SINGLE]->activeFlag);
+ setControlMode(window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_PLAYING,
+ window[DECODER_INDEX_DOUBLE]->activeFlag);
+ DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
+ filename[DECODER_INDEX_SINGLE],
+ SEEK_START);
+ }else{
+ filename[DECODER_INDEX_SINGLE] = uri;
+ if(window[DECODER_INDEX_SINGLE] == thisWindow){
+ setControlMode(window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_PLAYING,
+ window[DECODER_INDEX_SINGLE]->activeFlag);
+ DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
+ filename[DECODER_INDEX_SINGLE],
+ SEEK_START);
+ }else{
+ filename[DECODER_INDEX_DOUBLE] = uri;
+ setControlMode(window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_PLAYING,
+ window[DECODER_INDEX_DOUBLE]->activeFlag);
+ DualDecode_playMedia(pipes[DECODER_INDEX_DOUBLE],
+ filename[DECODER_INDEX_DOUBLE],
+ SEEK_START);
+ }
+ }
+ }
+ if (GTK_IS_WIDGET (fileChooser))
+ gtk_widget_destroy (fileChooser);
+
+ if( GTK_IS_WIDGET (thisWindow->window))
+ gtk_widget_set_sensitive (thisWindow->window,TRUE);
+
+last: return ret;
+}
+
+/*Play Button Clicked Callback Function*/
+static gboolean cbPlayClicked(GtkWidget *widget, gpointer data)
+{
+ gboolean ret = TRUE;
+ GUIWindow *thisWindow = (GUIWindow *)data;
+
+ if(DECODE_MODE_SINGLE == decodeMode){
+ setControlMode(window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_PLAYING,
+ window[DECODER_INDEX_SINGLE]->activeFlag);
+ setControlMode(window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_PLAYING,
+ window[DECODER_INDEX_DOUBLE]->activeFlag);
+ if(GST_STATE_PAUSED ==
+ DualDecode_getMediaState(pipes[DECODER_INDEX_SINGLE])){
+ DualDecode_resumeMedia(pipes[DECODER_INDEX_SINGLE]);
+ }else{
+ DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
+ filename[DECODER_INDEX_SINGLE],
+ SEEK_START);
+ }
+ }else{
+ if (window[DECODER_INDEX_SINGLE] == thisWindow){
+ setControlMode (window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_PLAYING,
+ window[DECODER_INDEX_SINGLE]->activeFlag);
+ if (GST_STATE_PAUSED ==
+ DualDecode_getMediaState(pipes[DECODER_INDEX_SINGLE])){
+ DualDecode_resumeMedia(pipes[DECODER_INDEX_SINGLE]);
+ }else if (GST_STATE_READY ==
+ DualDecode_getMediaState(pipes[DECODER_INDEX_SINGLE])){
+ g_print ("\nPipeline state is READY\n");
+ DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE],
+ window[DECODER_INDEX_SINGLE]->sink,
+ NULL);
+ DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE], filename[0],0);
+ //DualDecode_seekMedia (pipes[DECODER_INDEX_SINGLE], 0);
+ }
+
+ else {
+ DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
+ filename[DECODER_INDEX_SINGLE],
+ SEEK_START);
+ }
+ }else{
+ setControlMode(window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_PLAYING,
+ window[DECODER_INDEX_DOUBLE]->activeFlag);
+ if(GST_STATE_PAUSED ==
+ DualDecode_getMediaState(pipes[DECODER_INDEX_DOUBLE])){
+ DualDecode_resumeMedia(pipes[DECODER_INDEX_DOUBLE]);
+ }
+ else if (GST_STATE_READY ==
+ DualDecode_getMediaState(pipes[DECODER_INDEX_DOUBLE])){
+ DualDecode_resumeMedia (pipes[DECODER_INDEX_DOUBLE]);
+ //DualDecode_seekMedia (pipes[DECODER_INDEX_SINGLE], 0);
+ }
+
+ else{
+ DualDecode_playMedia(pipes[DECODER_INDEX_DOUBLE],
+ filename[DECODER_INDEX_DOUBLE],
+ SEEK_START);
+ }
+ }
+ }
+ return ret;
+}
+
+/*Pause Button Clicked Callback Function*/
+static gboolean cbPauseClicked(GtkWidget *widget, gpointer data)
+{
+ gboolean ret = TRUE;
+ GUIWindow *thisWindow = (GUIWindow *)data;
+
+ if(DECODE_MODE_SINGLE == decodeMode){
+ setControlMode(window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_PAUSED,
+ window[DECODER_INDEX_SINGLE]->activeFlag);
+ setControlMode(window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_PAUSED,
+ window[DECODER_INDEX_DOUBLE]->activeFlag);
+ DualDecode_pauseMedia(pipes[DECODER_INDEX_SINGLE]);
+ }else{
+ if(window[DECODER_INDEX_SINGLE] == thisWindow){
+ setControlMode(window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_PAUSED,
+ window[DECODER_INDEX_SINGLE]->activeFlag);
+ DualDecode_pauseMedia(pipes[DECODER_INDEX_SINGLE]);
+ }else{
+ setControlMode(window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_PAUSED,
+ window[DECODER_INDEX_DOUBLE]->activeFlag);
+ DualDecode_pauseMedia(pipes[DECODER_INDEX_DOUBLE]);
+ }
+ }
+ return ret;
+}
+
+/*Stop Button Clicked Callback Function*/
+static gboolean cbStopClicked(GtkWidget *widget, gpointer data)
+{
+ gboolean ret = TRUE;
+ GUIWindow *thisWindow = (GUIWindow *)data;
+
+
+ if (DECODE_MODE_SINGLE == decodeMode){
+ setControlMode (window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_STOPPED,
+ window[DECODER_INDEX_SINGLE]->activeFlag);
+ setControlMode (window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_STOPPED,
+ window[DECODER_INDEX_DOUBLE]->activeFlag);
+ DualDecode_stopMedia (pipes[DECODER_INDEX_SINGLE]);
+ }else{
+ if (window[DECODER_INDEX_SINGLE] == thisWindow){
+ setControlMode(window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_STOPPED,
+ window[DECODER_INDEX_SINGLE]->activeFlag);
+ DualDecode_stopMedia(pipes[DECODER_INDEX_SINGLE]);
+ }else{
+ setControlMode (window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_STOPPED,
+ window[DECODER_INDEX_DOUBLE]->activeFlag);
+ DualDecode_stopMedia (pipes[DECODER_INDEX_DOUBLE]);
+ }
+ }
+ return ret;
+}
+static gboolean cbForwardClicked(GtkWidget *widget, gpointer data)
+{
+ gboolean ret = TRUE;
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 duration = 0;
+ gint64 seekPoint = 0;
+ GUIWindow *thisWindow = (GUIWindow *)data;
+ gdouble percent = gtk_range_get_value ((GtkRange *) (thisWindow->seekScale));
+
+ g_print ("IN FORWARD CLICKED\n");
+ if (DECODE_MODE_SINGLE == decodeMode){
+
+ gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format,&duration);
+ seekPoint = (duration * percent/ (gdouble)100)+ FORWARD;
+ g_print ("SEEK POINT %d\n", seekPoint);
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_SINGLE], seekPoint);
+ }
+ else{
+ if(window[DECODER_INDEX_SINGLE] == thisWindow){
+ gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format, &duration);
+ seekPoint = (duration * percent/ (gdouble)100) + FORWARD;
+ g_print ("SEEK POINT %d\n", seekPoint);
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_SINGLE], seekPoint);
+ }
+ else {
+ gst_element_query_duration(pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format,&duration);
+ seekPoint = (duration * percent/ (gdouble)100)+ FORWARD;
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_DOUBLE], seekPoint);
+ }
+ }
+
+ return ret;
+}
+static gboolean cbRewindClicked(GtkWidget *widget, gpointer data)
+{
+ gboolean ret = TRUE;
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 duration = 0;
+ gint64 seekPoint = 0;
+ GUIWindow *thisWindow = (GUIWindow *)data;
+ gdouble percent = gtk_range_get_value ((GtkRange *) (thisWindow->seekScale));
+
+ g_print ("IN FORWARD CLICKED\n");
+ if (DECODE_MODE_SINGLE == decodeMode){
+
+ gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format,&duration);
+ seekPoint = (duration * percent/ (gdouble)100) - REWIND;
+ g_print ("SEEK POINT %d\n", seekPoint);
+ seekPoint = (seekPoint < 0) ? 0 : seekPoint;
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_SINGLE], seekPoint);
+ }
+ else{
+ if(window[DECODER_INDEX_SINGLE] == thisWindow){
+ gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format, &duration);
+ seekPoint = (duration * percent/ (gdouble)100) - REWIND;
+ g_print ("SEEK POINT %d\n", seekPoint);
+ seekPoint = (seekPoint < 0) ? 0 : seekPoint;
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_SINGLE], seekPoint);
+ }
+ else {
+ gst_element_query_duration(pipes[DECODER_INDEX_SINGLE]->pipe,
+ &format,&duration);
+ seekPoint = (duration * percent/ (gdouble)100) - REWIND;
+ seekPoint = (seekPoint < 0) ? 0 : seekPoint;
+ ret = DualDecode_seekMedia(pipes[DECODER_INDEX_DOUBLE], seekPoint);
+ }
+ }
+
+ return ret;
+}
+static gboolean cbSwitchButtonClicked (GtkWidget *widget, gpointer data)
+{
+ gboolean ret = TRUE;
+ gboolean noFile = FALSE;
+ GUIWindow *thisWindow = (GUIWindow *) data;
+ gint otherWindowIndex = 0;
+ gint thisWindowIndex = 0;
+
+ /*No file is given yet to play. Application may be just started. */
+ if (NULL == filename[DECODER_INDEX_SINGLE])
+ noFile = TRUE;
+
+
+
+
+ if (thisWindow == window[DECODER_INDEX_SINGLE]){
+ thisWindowIndex = DECODER_INDEX_SINGLE;
+ otherWindowIndex = DECODER_INDEX_DOUBLE;
+ }
+ else {
+ otherWindowIndex = DECODER_INDEX_SINGLE;
+ thisWindowIndex = DECODER_INDEX_DOUBLE;
+ }
+
+ switch (decodeMode)
+ {
+ case DECODE_MODE_SINGLE :
+ setControlMode (window[otherWindowIndex], window[otherWindowIndex]->modeFlag,
+ CONTROL_MODE_ACTIVE);
+ setControlMode (thisWindow, thisWindow->modeFlag,
+ CONTROL_MODE_ACTIVE);
+
+ if (FALSE == noFile) {
+ ret = DualDecode_singleToDual (pipes,
+ window[otherWindowIndex]->sink,
+ thisWindowIndex, otherWindowIndex,
+ filename[DECODER_INDEX_SINGLE]);
+ }
+ decodeMode = DECODE_MODE_DUAL;
+ setDecodeSwitch(DECODE_MODE_SINGLE);
+ break;
+
+ case DECODE_MODE_DUAL :
+ setControlMode (window[otherWindowIndex], thisWindow->modeFlag,
+ CONTROL_MODE_INACTIVE);
+
+ if (FALSE == noFile) {
+ ret = DualDecode_dualToSingle (pipes,
+ window[otherWindowIndex]->sink,
+ thisWindowIndex, otherWindowIndex);
+ }
+ decodeMode = DECODE_MODE_SINGLE;
+ setDecodeSwitch(DECODE_MODE_DUAL);
+
+ break;
+ }
+
+
+ return ret;
+}
+/*Window Close Callback Function*/
+static gboolean cbWindowClosed(GtkWidget *widget, gpointer data){
+ DualDecode_exitApplication();
+ return TRUE;
+}
+
+static gboolean cbHelpClicked (GtkWidget *widget, gpointer data){
+ g_print ("HELP BUTTON CLICKED\n");
+ gtk_widget_show (helpWindow);
+ return TRUE;
+}
+
+static gboolean cbHelpClosed (GtkWidget *widget, gpointer data){
+ g_print ("IN HELP CLOSED\n");
+ gtk_widget_hide (helpWindow);
+ return TRUE;
+}
+/******************************************************************************
+
+ Static utility functions definition
+
+ ******************************************************************************/
+static void setControlActive(GUIWindow *window, gboolean activeFlag)
+{
+ gtk_widget_set_sensitive(window->playButton,activeFlag);
+ gtk_widget_set_sensitive(window->pauseButton,activeFlag);
+ gtk_widget_set_sensitive(window->stopButton,activeFlag);
+ gtk_widget_set_sensitive(window->rewindButton,activeFlag);
+ gtk_widget_set_sensitive(window->forwardButton,activeFlag);
+ gtk_widget_set_sensitive(window->openButton,activeFlag);
+ gtk_widget_set_sensitive(window->seekScale,activeFlag);
+ gtk_widget_set_sensitive (window->switchButton, activeFlag);
+
+}
+
+static void setControlMode(GUIWindow *thisWindow,
+ gint modeFlag,
+ gint activeFlag)
+{
+ setControlActive(thisWindow, activeFlag);
+ if(activeFlag){
+ switch(modeFlag){
+ case CONTROL_MODE_NO_FILE:
+ gtk_widget_set_sensitive(thisWindow->playButton,FALSE);
+ gtk_widget_set_sensitive(thisWindow->pauseButton,FALSE);
+
+ gtk_widget_set_sensitive(thisWindow->stopButton,FALSE);
+ gtk_widget_set_sensitive(thisWindow->rewindButton,FALSE);
+ gtk_widget_set_sensitive(thisWindow->forwardButton,FALSE);
+ gtk_widget_set_sensitive(thisWindow->seekScale,FALSE);
+
+ break;
+ case CONTROL_MODE_PLAYING:
+ gtk_widget_set_sensitive(thisWindow->playButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->pauseButton,TRUE);
+
+ gtk_widget_set_sensitive(thisWindow->stopButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->rewindButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->forwardButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->seekScale,TRUE);
+
+ break;
+ case CONTROL_MODE_STOPPED:
+ gtk_widget_set_sensitive(thisWindow->playButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->pauseButton,TRUE);
+
+ gtk_widget_set_sensitive(thisWindow->stopButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->rewindButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->forwardButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->seekScale,FALSE);
+
+ break;
+ case CONTROL_MODE_PAUSED:
+ gtk_widget_set_sensitive(thisWindow->playButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->pauseButton,TRUE);
+
+ gtk_widget_set_sensitive(thisWindow->stopButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->rewindButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->forwardButton,TRUE);
+ gtk_widget_set_sensitive(thisWindow->seekScale,TRUE);
+
+ break;
+ }
+ }
+ switch(modeFlag){
+ case CONTROL_MODE_NO_FILE:
+ gtk_widget_show(thisWindow->playButton);
+ gtk_widget_hide(thisWindow->pauseButton);
+
+ gtk_label_set_text(GTK_LABEL(thisWindow->statusLabel),
+ LABEL_TEXT_NO_FILE);
+ gtk_label_set_text(GTK_LABEL(thisWindow->timeLabel),
+ TIME_LABEL_ORIGIN);
+ if(thisWindow->timerSignal != TIMER_SIGNAL_NONE){
+ g_source_remove(thisWindow->timerSignal);
+ thisWindow->timerSignal = TIMER_SIGNAL_NONE;
+ }
+ break;
+ case CONTROL_MODE_PLAYING:
+ gtk_widget_show(thisWindow->pauseButton);
+ gtk_widget_hide(thisWindow->playButton);
+
+ gtk_label_set_text(GTK_LABEL(thisWindow->statusLabel),
+ LABEL_TEXT_PLAYING);
+ gtk_label_set_text(GTK_LABEL(thisWindow->timeLabel),
+ TIME_LABEL_ORIGIN);
+
+ if(thisWindow->timerSignal != TIMER_SIGNAL_NONE){
+ g_source_remove(thisWindow->timerSignal);
+ }
+ thisWindow->timerSignal = g_timeout_add(TIMER_INTERVAL,
+ cbTimerInterval,
+ thisWindow);
+
+ break;
+ case CONTROL_MODE_STOPPED:
+ gtk_widget_show(thisWindow->playButton);
+ gtk_widget_hide(thisWindow->pauseButton);
+
+ gtk_label_set_text(GTK_LABEL(thisWindow->statusLabel),
+ LABEL_TEXT_STOPPED);
+ gtk_label_set_text(GTK_LABEL(thisWindow->timeLabel),
+ TIME_LABEL_ORIGIN);
+
+ if(thisWindow->timerSignal != TIMER_SIGNAL_NONE){
+ g_source_remove(thisWindow->timerSignal);
+ thisWindow->timerSignal = TIMER_SIGNAL_NONE;
+ }
+ break;
+ case CONTROL_MODE_PAUSED:
+ gtk_widget_show(thisWindow->playButton);
+ gtk_widget_hide(thisWindow->pauseButton);
+
+ gtk_label_set_text(GTK_LABEL(thisWindow->statusLabel),
+ LABEL_TEXT_PAUSED);
+ break;
+
+ }
+ thisWindow->modeFlag = modeFlag;
+ thisWindow->activeFlag = activeFlag;
+}
+
+static void setDecodeSwitch(gint decodeSwitch)
+{
+ switch (decodeSwitch){
+ case DECODE_MODE_SINGLE:
+ gtk_button_set_label(
+ GTK_BUTTON(window[DECODER_INDEX_SINGLE]->switchButton),
+ SWITCH_TEXT_SINGLE);
+ gtk_button_set_label(
+ GTK_BUTTON(window[DECODER_INDEX_DOUBLE]->switchButton),
+ SWITCH_TEXT_SINGLE);
+ break;
+ case DECODE_MODE_DUAL:
+ gtk_button_set_label(
+ GTK_BUTTON(window[DECODER_INDEX_SINGLE]->switchButton),
+ SWITCH_TEXT_DUAL);
+ gtk_button_set_label(
+ GTK_BUTTON(window[DECODER_INDEX_DOUBLE]->switchButton),
+ SWITCH_TEXT_DUAL);
+ }
+}
+
+static void setup()
+{
+
+ g_print ("SINK TO BE USED %s\n", sink);
+ gtk_widget_show_all (window[DECODER_INDEX_SINGLE]->window);
+ gtk_widget_show_all (window[DECODER_INDEX_DOUBLE]->window);
+
+ window[DECODER_INDEX_SINGLE]->sink = createImageSinkFromWindow (
+ window[DECODER_INDEX_SINGLE]->drawArea,
+ "windowsink0");
+
+ window[DECODER_INDEX_DOUBLE]->sink = createImageSinkFromWindow (
+ window[DECODER_INDEX_DOUBLE]->drawArea,
+ "windowsink1");
+
+ /*If any of the sinks is NULL the application exits*/
+
+ if (NULL == window[DECODER_INDEX_SINGLE]->sink ||
+ NULL == window[DECODER_INDEX_DOUBLE]->sink) {
+ DualDecode_exitApplication();
+
+ }
+ switch(decodeMode){
+ case DECODE_MODE_NONE:
+ setControlMode(window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_NO_FILE,
+ CONTROL_MODE_ACTIVE);
+ setControlMode(window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_NO_FILE,
+ CONTROL_MODE_ACTIVE);
+ DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE],
+ window[DECODER_INDEX_SINGLE]->sink,
+ NULL);
+ DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE],
+ window[DECODER_INDEX_DOUBLE]->sink,
+ NULL);
+ decodeMode = DECODE_MODE_DUAL;
+ setDecodeSwitch(DECODE_MODE_SINGLE);
+ break;
+ case DECODE_MODE_SINGLE:
+ setControlMode (window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_PLAYING,
+ CONTROL_MODE_ACTIVE);
+ setControlMode (window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_PLAYING,
+ CONTROL_MODE_INACTIVE);
+ DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE],
+ window[DECODER_INDEX_SINGLE]->sink,
+ window[DECODER_INDEX_DOUBLE]->sink);
+ DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE], NULL,
+ NULL);
+ DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE],
+ filename[DECODER_INDEX_SINGLE],
+ SEEK_START);
+ setDecodeSwitch(DECODE_MODE_DUAL);
+ break;
+ case DECODE_MODE_DUAL:
+ setControlMode(window[DECODER_INDEX_SINGLE],
+ CONTROL_MODE_PLAYING,
+ CONTROL_MODE_ACTIVE);
+ DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE],
+ window[DECODER_INDEX_SINGLE]->sink,
+ NULL);
+ DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE],
+ window[DECODER_INDEX_DOUBLE]->sink,
+ NULL);
+
+ DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
+ filename[DECODER_INDEX_SINGLE],
+ SEEK_START);
+ setControlMode(window[DECODER_INDEX_DOUBLE],
+ CONTROL_MODE_PLAYING,
+ CONTROL_MODE_ACTIVE);
+ DualDecode_playMedia(pipes[DECODER_INDEX_DOUBLE],
+ filename[DECODER_INDEX_DOUBLE],
+ SEEK_START);
+ setDecodeSwitch(DECODE_MODE_SINGLE);
+ break;
+ }
+}
+
+static GUIWindow *createWindow()
+{
+ GUIWindow *ret = NULL;
+ ret = g_malloc0(sizeof(GUIWindow));
+ if(NULL == ret){
+ return ret;
+ }
+ DualDecode_builderCreate();
+
+ ret->window = DualDecode_getWidget("decodeWindowSingle");
+ if(NULL == ret->window){
+ goto memCleanup;
+ }
+ ret->windowCloseSignal = g_signal_connect(G_OBJECT(ret->window),
+ "delete-event",
+ G_CALLBACK(cbWindowClosed),
+ NULL);
+
+ GtkWidget *toolbar = DualDecode_getWidget("toolbarSingle");
+ if(NULL == toolbar){
+ goto memCleanup;
+ }
+ ret->drawArea = DualDecode_getWidget("videoViewerSingle");
+ if(NULL == ret->drawArea){
+ goto memCleanup;
+ }
+
+ ret->openButton = GTK_WIDGET(
+ gtk_tool_button_new_from_stock(GTK_STOCK_OPEN));
+ if(NULL == ret->openButton){
+ goto memCleanup;
+ }
+ ret->rewindButton = GTK_WIDGET(
+ gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_REWIND));
+ if(NULL == ret->rewindButton){
+ goto memCleanup;
+ }
+ ret->playButton = GTK_WIDGET(
+ gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PLAY));
+ if(NULL == ret->playButton){
+ goto memCleanup;
+ }
+ ret->pauseButton = GTK_WIDGET(
+ gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PAUSE));
+ if(NULL == ret->pauseButton){
+ goto memCleanup;
+ }
+ ret->stopButton = GTK_WIDGET(
+ gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_STOP));
+ if(NULL == ret->stopButton){
+ goto memCleanup;
+ }
+ ret->forwardButton = GTK_WIDGET(
+ gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_FORWARD));
+ if(NULL == ret->forwardButton){
+ goto memCleanup;
+ }
+ ret->helpButton = GTK_WIDGET(
+ gtk_tool_button_new_from_stock(GTK_STOCK_HELP));
+ if(NULL == ret->helpButton){
+ goto memCleanup;
+ }
+
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ GTK_TOOL_ITEM(ret->openButton),
+ -1);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ gtk_separator_tool_item_new(),
+ -1);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ GTK_TOOL_ITEM(ret->rewindButton),
+ -1);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ GTK_TOOL_ITEM(ret->playButton),
+ -1);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ GTK_TOOL_ITEM(ret->pauseButton),
+ -1);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ GTK_TOOL_ITEM(ret->stopButton),
+ -1);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ GTK_TOOL_ITEM(ret->forwardButton),
+ -1);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ gtk_separator_tool_item_new(),
+ -1);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
+ GTK_TOOL_ITEM(ret->helpButton),
+ -1);
+
+ ret->openSignal = g_signal_connect(G_OBJECT(ret->openButton),
+ "clicked",
+ G_CALLBACK(cbOpenClicked),
+ ret);
+ ret->stopSignal = g_signal_connect(G_OBJECT(ret->stopButton),
+ "clicked",
+ G_CALLBACK(cbStopClicked),
+ ret);
+ ret->pauseSignal = g_signal_connect(G_OBJECT(ret->pauseButton),
+ "clicked",
+ G_CALLBACK(cbPauseClicked),
+ ret);
+ ret->playSignal = g_signal_connect(G_OBJECT(ret->playButton),
+ "clicked",
+ G_CALLBACK(cbPlayClicked),
+ ret);
+ ret->forwardSignal = g_signal_connect(G_OBJECT(ret->forwardButton),
+ "clicked",
+ G_CALLBACK(cbForwardClicked),
+ ret);
+ ret->rewindSignal = g_signal_connect(G_OBJECT(ret->rewindButton),
+ "clicked",
+ G_CALLBACK(cbRewindClicked),
+ ret);
+
+ ret->helpSignal = g_signal_connect(G_OBJECT(ret->helpButton),
+ "clicked",
+ G_CALLBACK(cbHelpClicked),
+ ret);
+
+
+ ret->switchButton = DualDecode_getWidget("switchButtonSingle");
+ if(NULL == ret->switchButton){
+ goto memCleanup;
+ }
+
+ ret->switchSignal = g_signal_connect (G_OBJECT (ret->switchButton),
+ "clicked",
+ G_CALLBACK (cbSwitchButtonClicked),
+ ret);
+
+ ret->seekScale = DualDecode_getWidget("seekScaleSingle");
+ if(NULL == ret->seekScale){
+ goto memCleanup;
+ }
+
+ ret->seekSignal = g_signal_connect (G_OBJECT (ret->seekScale),
+ "value_changed",
+ G_CALLBACK (cbSeekValueChanged),
+ ret);
+
+
+ ret->statusLabel = DualDecode_getWidget("statusLabelSingle");
+ if(NULL == ret->statusLabel){
+ goto memCleanup;
+ }
+
+ ret->timeLabel = DualDecode_getWidget("timeLabelSingle");
+ if(NULL == ret->timeLabel){
+ goto memCleanup;
+ }
+ ret->activeFlag = FALSE;
+
+ goto last;
+
+ gtk_widget_destroy(ret->window);
+memCleanup:
+ g_free(ret);
+last:
+ DualDecode_builderClose();
+ return ret;
+}
+
+static GtkWidget *createLogWindow()
+{
+ /*TODO: create help window*/
+ return gtk_window_new(GTK_WINDOW_TOPLEVEL);
+}
+
+static GtkWidget *createHelpWindow()
+{
+ GtkWidget * helpWindow;
+ gint width;
+ gint height;
+
+ helpWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title ( (GtkWindow *) helpWindow, "Help");
+ gtk_window_set_resizable ( (GtkWindow * )helpWindow, FALSE);
+
+ /*Set size same as display windows*/
+ gtk_widget_get_size_request (window[DECODER_INDEX_SINGLE]->window,
+ &width,
+ &height);
+ gtk_widget_set_size_request (helpWindow, width, height);
+ /*Connect signal to close button handler*/
+ g_signal_connect(G_OBJECT (helpWindow), "delete-event",
+ G_CALLBACK (cbHelpClosed), NULL);
+ g_print ("RETURNING FROM CREATE HELP\n");
+ return helpWindow;
+}
+
+
+
+/*static void logGUI(GtkWidget *logWindow, gchar *format, ...)
+{
+ //TODO: dummy now
+}*/
+static void setWindowSizeLocation()
+{
+ GdkScreen *screen = NULL;
+ gint screenWidth = -1;
+ gint screenHeight = -1;
+ gint windowWidth = -1;
+ gint windowHeight = -1;
+
+ screen = gdk_screen_get_default();
+ screenWidth = gdk_screen_get_width(screen);
+ screenHeight = gdk_screen_get_height(screen);
+ windowWidth = screenWidth/SCREEN_WIDTH_FACTOR;
+ windowHeight = screenHeight/SCREEN_HEIGHT_FACTOR;
+
+ gtk_widget_set_size_request(window[DECODER_INDEX_SINGLE]->window,
+ windowWidth,windowHeight);
+ gtk_widget_set_size_request(window[DECODER_INDEX_DOUBLE]->window,
+ windowWidth,windowHeight);
+ gtk_window_move(GTK_WINDOW(window[DECODER_INDEX_SINGLE]->window),
+ (screenWidth-2*windowWidth)/2,
+ 0);
+ gtk_window_move(GTK_WINDOW(window[DECODER_INDEX_DOUBLE]->window),
+ (screenWidth-2*windowWidth)/2+windowWidth,
+ 0);
+}
+
+static GstElement *createImageSinkFromWindow (GtkWidget * window, gchar *name)
+{
+ GstElement *sinkElement = NULL;
+ XID xid = 0;
+ GdkDrawable *drawable = NULL;
+
+ /*make an xvimagesink element from factory*/
+
+ sinkElement = gst_element_factory_make (sink,name);
+ if (NULL == sinkElement){
+ g_print ("%s sink cannot be created\n", sink);
+ goto return_pos;
+ }
+
+ /*get the XID of the display window's drawable*/
+ drawable = gtk_widget_get_window (GTK_WIDGET (window));
+ if(FALSE == GDK_IS_DRAWABLE(drawable)){
+ /*TODO: A BUG HERE?*/
+ g_object_unref (G_OBJECT (sinkElement));
+ sinkElement=NULL;
+ goto return_pos;
+ }
+ xid = gdk_x11_drawable_get_xid(drawable);
+
+ /*link the gst sink element to the XID*/
+ gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (sinkElement),xid);
+
+return_pos:
+ return sinkElement;
+}
+
+/******************************************************************************
+ * Exported Function Definition
+ ******************************************************************************/
+
+/******************************************************************************
+ * See gui.h
+ ******************************************************************************/
+void DualDecode_startApplication()
+{
+
+ window[DECODER_INDEX_SINGLE] = createWindow();
+ g_assert(window[DECODER_INDEX_SINGLE] != NULL);
+
+ /*window[DECODER_INDEX_SINGLE]->sink = createImageSinkFromWindow (
+ window[DECODER_INDEX_SINGLE]->drawArea,
+ "sink0");
+
+ */
+ window[DECODER_INDEX_DOUBLE] = createWindow();
+ g_assert(window[DECODER_INDEX_DOUBLE] != NULL);
+
+ /* window[DECODER_INDEX_DOUBLE]->sink = createImageSinkFromWindow (
+ window[DECODER_INDEX_DOUBLE]->drawArea,
+ "sink1");
+ */
+ setWindowSizeLocation();
+
+ helpWindow = createHelpWindow();
+ g_assert (helpWindow != NULL);
+
+ logWindow[DECODER_INDEX_SINGLE] = createLogWindow();
+ g_assert (logWindow[DECODER_INDEX_SINGLE] != NULL);
+
+ logWindow[DECODER_INDEX_DOUBLE] = createLogWindow();
+ g_assert (logWindow[DECODER_INDEX_DOUBLE] != NULL);
+
+ pipes[DECODER_INDEX_SINGLE] = DualDecode_createPipeline();
+/* DualDecode_setLogFunction(pipes[DECODER_INDEX_SINGLE],
+ logGUI,
+ logWindow[DECODER_INDEX_SINGLE]);
+*/
+ pipes[DECODER_INDEX_DOUBLE] = DualDecode_createPipeline();
+/* DualDecode_setLogFunction(pipes[DECODER_INDEX_DOUBLE],
+ logGUI,
+ logWindow[DECODER_INDEX_DOUBLE]);
+*/
+ setup();
+
+ gtk_main();
+
+}
+
+/******************************************************************************
+ * See gui.h
+ ******************************************************************************/
+void DualDecode_exitApplication()
+{
+ gtk_widget_destroy(window[DECODER_INDEX_SINGLE]->window);
+ gtk_widget_destroy(window[DECODER_INDEX_DOUBLE]->window);
+ g_free(window[DECODER_INDEX_SINGLE]);
+ g_free(window[DECODER_INDEX_DOUBLE]);
+ gtk_widget_destroy(logWindow[DECODER_INDEX_SINGLE]);
+ gtk_widget_destroy(logWindow[DECODER_INDEX_DOUBLE]);
+ gtk_widget_destroy (helpWindow);
+
+ /*TODO: destroy pipes here*/
+
+ if (gtk_main_level())
+ gtk_main_quit();
+ exit(0);
+}
+
+/******************************************************************************
+ * See gui.h
+ ******************************************************************************/
+gboolean DualDecode_initGUI(gint *argc, char **argv[])
+{
+ return gtk_init_check(argc,argv);
+}