Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsgst.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #ifdef __HAVE_GSTREAMER__
00034 
00035 #include <string.h>
00036 #include <signal.h>
00037 #ifdef HAVE_UNISTD_H
00038 #include <unistd.h>
00039 #endif
00040 #ifndef DISABLE_FAULT_HANDLER
00041 #include <sys/wait.h>
00042 #endif
00043 #include <locale.h>             /* for LC_ALL */
00044 #include "mmsmedia/mmsgst.h"
00045 
00046 
00047 
00048 /* FIXME: This is just a temporary hack.  We should have a better
00049  * check for siginfo handling. */
00050 #ifdef SA_SIGINFO
00051 #define USE_SIGINFO
00052 #endif
00053 
00054 extern volatile gboolean glib_on_error_halt;
00055 
00056 #ifndef DISABLE_FAULT_HANDLER
00057 static void fault_restore (void);
00058 static void fault_spin (void);
00059 static void sigint_restore (void);
00060 static gboolean caught_intr = FALSE;
00061 #endif
00062 
00063 static GstElement *pipeline;
00064 static gboolean caught_error = FALSE;
00065 static gboolean tags = FALSE;
00066 static gboolean is_live = FALSE;
00067 
00068 #ifndef DISABLE_FAULT_HANDLER
00069 #ifndef USE_SIGINFO
00070 static void
00071 fault_handler_sighandler (int signum)
00072 {
00073   fault_restore ();
00074 
00075   /* printf is used instead of g_print(), since it's less likely to
00076    * deadlock */
00077   switch (signum) {
00078     case SIGSEGV:
00079       printf ("Caught SIGSEGV\n");
00080       break;
00081     case SIGQUIT:
00082       printf ("Caught SIGQUIT\n");
00083       break;
00084     default:
00085       printf ("signo:  %d\n", signum);
00086       break;
00087   }
00088 
00089   fault_spin ();
00090 }
00091 
00092 #else /* USE_SIGINFO */
00093 
00094 static void
00095 fault_handler_sigaction (int signum, siginfo_t * si, void *misc)
00096 {
00097   fault_restore ();
00098 
00099   /* printf is used instead of g_print(), since it's less likely to
00100    * deadlock */
00101   switch (si->si_signo) {
00102     case SIGSEGV:
00103       printf ("Caught SIGSEGV accessing address %p\n", si->si_addr);
00104       break;
00105     case SIGQUIT:
00106       printf ("Caught SIGQUIT\n");
00107       break;
00108     default:
00109       printf ("signo:  %d\n", si->si_signo);
00110       printf ("errno:  %d\n", si->si_errno);
00111       printf ("code:   %d\n", si->si_code);
00112       break;
00113   }
00114 
00115   fault_spin ();
00116 }
00117 #endif /* USE_SIGINFO */
00118 
00119 static void
00120 fault_spin (void)
00121 {
00122   int spinning = TRUE;
00123 
00124   glib_on_error_halt = FALSE;
00125   g_on_error_stack_trace ("gst-launch");
00126 
00127   wait (NULL);
00128 
00129   /* FIXME how do we know if we were run by libtool? */
00130   printf ("Spinning.  Please run 'gdb gst-launch %d' to continue debugging, "
00131       "Ctrl-C to quit, or Ctrl-\\ to dump core.\n", (gint) getpid ());
00132   while (spinning)
00133     g_usleep (1000000);
00134 }
00135 
00136 static void
00137 fault_restore (void)
00138 {
00139   struct sigaction action;
00140 
00141   memset (&action, 0, sizeof (action));
00142   action.sa_handler = SIG_DFL;
00143 
00144   sigaction (SIGSEGV, &action, NULL);
00145   sigaction (SIGQUIT, &action, NULL);
00146 }
00147 
00148 static void
00149 fault_setup (void)
00150 {
00151   struct sigaction action;
00152 
00153   memset (&action, 0, sizeof (action));
00154 #ifdef USE_SIGINFO
00155   action.sa_sigaction = fault_handler_sigaction;
00156   action.sa_flags = SA_SIGINFO;
00157 #else
00158   action.sa_handler = fault_handler_sighandler;
00159 #endif
00160 
00161   sigaction (SIGSEGV, &action, NULL);
00162   sigaction (SIGQUIT, &action, NULL);
00163 }
00164 #endif /* DISABLE_FAULT_HANDLER */
00165 
00166 static void
00167 print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
00168 {
00169   gint i, count;
00170 
00171   count = gst_tag_list_get_tag_size (list, tag);
00172 
00173   for (i = 0; i < count; i++) {
00174     gchar *str;
00175 
00176     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
00177       if (!gst_tag_list_get_string_index (list, tag, i, &str))
00178         g_assert_not_reached ();
00179     } else if (gst_tag_get_type (tag) == GST_TYPE_BUFFER) {
00180       GstBuffer *img;
00181 
00182       img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i));
00183       if (img) {
00184         gchar *caps_str;
00185 
00186         caps_str = GST_BUFFER_CAPS (img) ?
00187             gst_caps_to_string (GST_BUFFER_CAPS (img)) : g_strdup ("unknown");
00188         str = g_strdup_printf ("buffer of %u bytes, type: %s",
00189             GST_BUFFER_SIZE (img), caps_str);
00190         g_free (caps_str);
00191       } else {
00192         str = g_strdup ("NULL buffer");
00193       }
00194     } else {
00195       str =
00196           g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
00197     }
00198 
00199     if (i == 0) {
00200       g_print ("%16s: %s\n", gst_tag_get_nick (tag), str);
00201     } else {
00202       g_print ("%16s: %s\n", "", str);
00203     }
00204 
00205     g_free (str);
00206   }
00207 }
00208 
00209 #ifndef DISABLE_FAULT_HANDLER
00210 /* we only use sighandler here because the registers are not important */
00211 static void
00212 sigint_handler_sighandler (int signum)
00213 {
00214   g_print ("Caught interrupt -- ");
00215 
00216   sigint_restore ();
00217 
00218   /* we set a flag that is checked by the mainloop, we cannot do much in the
00219    * interrupt handler (no mutex or other blocking stuff) */
00220   caught_intr = TRUE;
00221 }
00222 
00223 /* is called every 50 milliseconds (20 times a second), the interrupt handler
00224  * will set a flag for us. We react to this by posting a message. */
00225 static gboolean
00226 check_intr (GstElement * pipeline)
00227 {
00228   if (!caught_intr) {
00229     return TRUE;
00230   } else {
00231     caught_intr = FALSE;
00232     g_print ("handling interrupt.\n");
00233 
00234     /* post an application specific message */
00235     gst_element_post_message (GST_ELEMENT (pipeline),
00236         gst_message_new_application (GST_OBJECT (pipeline),
00237             gst_structure_new ("GstLaunchInterrupt",
00238                 "message", G_TYPE_STRING, "Pipeline interrupted", NULL)));
00239 
00240     /* remove timeout handler */
00241     return FALSE;
00242   }
00243 }
00244 
00245 static void
00246 sigint_setup (void)
00247 {
00248   struct sigaction action;
00249 
00250   memset (&action, 0, sizeof (action));
00251   action.sa_handler = sigint_handler_sighandler;
00252 
00253   sigaction (SIGINT, &action, NULL);
00254 }
00255 
00256 static void
00257 sigint_restore (void)
00258 {
00259   struct sigaction action;
00260 
00261   memset (&action, 0, sizeof (action));
00262   action.sa_handler = SIG_DFL;
00263 
00264   sigaction (SIGINT, &action, NULL);
00265 }
00266 
00267 static void
00268 play_handler (int signum)
00269 {
00270   switch (signum) {
00271     case SIGUSR1:
00272       g_print ("Caught SIGUSR1 - Play request.\n");
00273       gst_element_set_state (pipeline, GST_STATE_PLAYING);
00274       break;
00275     case SIGUSR2:
00276       g_print ("Caught SIGUSR2 - Stop request.\n");
00277       gst_element_set_state (pipeline, GST_STATE_NULL);
00278       break;
00279   }
00280 }
00281 
00282 static void
00283 play_signal_setup (void)
00284 {
00285   struct sigaction action;
00286 
00287   memset (&action, 0, sizeof (action));
00288   action.sa_handler = play_handler;
00289   sigaction (SIGUSR1, &action, NULL);
00290   sigaction (SIGUSR2, &action, NULL);
00291 }
00292 #endif /* DISABLE_FAULT_HANDLER */
00293 
00294 /* returns TRUE if there was an error or we caught a keyboard interrupt. */
00295 static gboolean
00296 event_loop (GstElement * pipeline, gboolean blocking, GstState target_state)
00297 {
00298   GstBus *bus;
00299   GstMessage *message = NULL;
00300   gboolean res = FALSE;
00301   gboolean buffering = FALSE;
00302 
00303   bus = gst_element_get_bus (GST_ELEMENT (pipeline));
00304 
00305 #ifndef DISABLE_FAULT_HANDLER
00306   g_timeout_add (50, (GSourceFunc) check_intr, pipeline);
00307 #endif
00308 
00309   while (TRUE) {
00310     message = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0);
00311 
00312     /* if the poll timed out, only when !blocking */
00313     if (message == NULL)
00314       goto exit;
00315 
00316     switch (GST_MESSAGE_TYPE (message)) {
00317       case GST_MESSAGE_NEW_CLOCK:
00318       {
00319         GstClock *clock;
00320 
00321         gst_message_parse_new_clock (message, &clock);
00322 
00323         g_print ("New clock: %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
00324         break;
00325       }
00326       case GST_MESSAGE_EOS:
00327         g_print ("Got EOS from element \"%s\".\n",
00328             GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
00329         goto exit;
00330       case GST_MESSAGE_TAG:
00331         if (tags) {
00332           GstTagList *tags;
00333 
00334           gst_message_parse_tag (message, &tags);
00335           g_print ("FOUND TAG      : found by element \"%s\".\n",
00336               GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
00337           gst_tag_list_foreach (tags, print_tag, NULL);
00338           gst_tag_list_free (tags);
00339         }
00340         break;
00341       case GST_MESSAGE_INFO:{
00342         GError *gerror;
00343         gchar *debug;
00344         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
00345 
00346         gst_message_parse_info (message, &gerror, &debug);
00347         if (debug) {
00348           g_print ("INFO:\n%s\n", debug);
00349         }
00350         g_error_free (gerror);
00351         g_free (debug);
00352         g_free (name);
00353         break;
00354       }
00355       case GST_MESSAGE_WARNING:{
00356         GError *gerror;
00357         gchar *debug;
00358         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
00359 
00360         /* dump graph on warning */
00361         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
00362             GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.warning");
00363 
00364         gst_message_parse_warning (message, &gerror, &debug);
00365         g_print ("WARNING: from element %s: %s\n", name, gerror->message);
00366         if (debug) {
00367           g_print ("Additional debug info:\n%s\n", debug);
00368         }
00369         g_error_free (gerror);
00370         g_free (debug);
00371         g_free (name);
00372         break;
00373       }
00374       case GST_MESSAGE_ERROR:{
00375         GError *gerror;
00376         gchar *debug;
00377 
00378         /* dump graph on error */
00379         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
00380             GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error");
00381 
00382         gst_message_parse_error (message, &gerror, &debug);
00383         gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
00384         g_error_free (gerror);
00385         g_free (debug);
00386         /* we have an error */
00387         res = TRUE;
00388         goto exit;
00389       }
00390       case GST_MESSAGE_STATE_CHANGED:{
00391         GstState old, newX, pending;
00392 
00393         gst_message_parse_state_changed (message, &old, &newX, &pending);
00394 
00395         /* we only care about pipeline state change messages */
00396         if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline))
00397           break;
00398 
00399         /* dump graph for pipeline state changes */
00400         {
00401           gchar *dump_name = g_strdup_printf ("gst-launch.%s_%s",
00402               gst_element_state_get_name (old),
00403               gst_element_state_get_name (newX));
00404           GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
00405               GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
00406           g_free (dump_name);
00407         }
00408 
00409         /* ignore when we are buffering since then we mess with the states
00410          * ourselves. */
00411         if (buffering) {
00412           fprintf (stderr,
00413               "Prerolled, waiting for buffering to finish...\n");
00414           break;
00415         }
00416 
00417         /* if we reached the final target state, exit */
00418         if (target_state == GST_STATE_PAUSED && newX == target_state)
00419           goto exit;
00420 
00421         /* else not an interesting message */
00422         break;
00423       }
00424       case GST_MESSAGE_BUFFERING:{
00425         gint percent;
00426 
00427         gst_message_parse_buffering (message, &percent);
00428         fprintf (stderr, "%s %d%%  \r", "buffering...", percent);
00429 
00430         /* no state management needed for live pipelines */
00431         if (is_live)
00432           break;
00433 
00434         if (percent == 100) {
00435           /* a 100% message means buffering is done */
00436           buffering = FALSE;
00437           /* if the desired state is playing, go back */
00438           if (target_state == GST_STATE_PLAYING) {
00439             fprintf (stderr,
00440                 "Done buffering, setting pipeline to PLAYING ...\n");
00441             gst_element_set_state (pipeline, GST_STATE_PLAYING);
00442           } else
00443             goto exit;
00444         } else {
00445           /* buffering busy */
00446           if (buffering == FALSE && target_state == GST_STATE_PLAYING) {
00447             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
00448             fprintf (stderr, "Buffering, setting pipeline to PAUSED ...\n");
00449             gst_element_set_state (pipeline, GST_STATE_PAUSED);
00450           }
00451           buffering = TRUE;
00452         }
00453         break;
00454       }
00455       case GST_MESSAGE_LATENCY:
00456       {
00457         fprintf (stderr, "Redistribute latency...\n");
00458         gst_bin_recalculate_latency (GST_BIN (pipeline));
00459         break;
00460       }
00461       case GST_MESSAGE_APPLICATION:{
00462         const GstStructure *s;
00463 
00464         s = gst_message_get_structure (message);
00465 
00466         if (gst_structure_has_name (s, "GstLaunchInterrupt")) {
00467           /* this application message is posted when we caught an interrupt and
00468            * we need to stop the pipeline. */
00469           fprintf (stderr, "Interrupt: Stopping pipeline ...\n");
00470           /* return TRUE when we caught an interrupt */
00471           res = TRUE;
00472           goto exit;
00473         }
00474       }
00475       default:
00476         /* just be quiet by default */
00477         break;
00478     }
00479     if (message)
00480       gst_message_unref (message);
00481   }
00482   g_assert_not_reached ();
00483 
00484 exit:
00485   {
00486     if (message)
00487       gst_message_unref (message);
00488     gst_object_unref (bus);
00489     return res;
00490   }
00491 }
00492 
00493 
00494 void mmsGstFree() {
00495 
00496     if (pipeline) {
00497         GstState state, pending;
00498 
00499         fprintf (stderr, "Setting pipeline to NULL ...\n");
00500         gst_element_set_state (pipeline, GST_STATE_NULL);
00501         gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
00502 
00503         fprintf (stderr, "FREEING pipeline ...\n");
00504         gst_object_unref (pipeline);
00505     }
00506 
00507     gst_deinit ();
00508 }
00509 
00510 
00511 GstElement *mmsGstLaunch(const char *pipeline_description) {
00512     GError *error = NULL;
00513     gint res = 0;
00514 
00515 #ifdef ENABLE_NLS
00516     bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
00517     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
00518     textdomain (GETTEXT_PACKAGE);
00519 #endif
00520 
00521     if (!g_thread_supported ())
00522         g_thread_init (NULL);
00523 
00524     gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE);
00525 
00526 #ifndef DISABLE_FAULT_HANDLER
00527     fault_setup ();
00528 
00529     sigint_setup ();
00530     play_signal_setup ();
00531 #endif
00532 
00533     // parse the pipeline description
00534     pipeline = gst_parse_launch(pipeline_description, &error);
00535 
00536     if (!pipeline) {
00537         if (error) {
00538             fprintf (stderr, "ERROR: pipeline could not be constructed: %s.\n",
00539             GST_STR_NULL (error->message));
00540             g_error_free (error);
00541         } else {
00542             fprintf (stderr, "ERROR: pipeline could not be constructed.\n");
00543         }
00544         return NULL;
00545     } else if (error) {
00546         fprintf (stderr, "WARNING: erroneous pipeline: %s\n",
00547         GST_STR_NULL (error->message));
00548         g_error_free (error);
00549         return NULL;
00550     }
00551 
00552 
00553     GstState state;
00554     GstStateChangeReturn ret;
00555 
00556     /* If the top-level object is not a pipeline, place it in a pipeline. */
00557     if (!GST_IS_PIPELINE (pipeline)) {
00558       GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL);
00559 
00560       if (real_pipeline == NULL) {
00561         fprintf (stderr, "ERROR: the 'pipeline' element wasn't found.\n");
00562         return NULL;
00563       }
00564       gst_bin_add (GST_BIN (real_pipeline), pipeline);
00565       pipeline = real_pipeline;
00566     }
00567     fprintf (stderr, "Setting pipeline to PAUSED ...\n");
00568     ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
00569 
00570     switch (ret) {
00571     case GST_STATE_CHANGE_FAILURE:
00572         fprintf (stderr, "ERROR: Pipeline doesn't want to pause.\n");
00573         res = -1;
00574         event_loop (pipeline, FALSE, GST_STATE_VOID_PENDING);
00575         goto end;
00576     case GST_STATE_CHANGE_NO_PREROLL:
00577         fprintf (stderr, "Pipeline is live and does not need PREROLL ...\n");
00578         is_live = TRUE;
00579         break;
00580     case GST_STATE_CHANGE_ASYNC:
00581         fprintf (stderr, "Pipeline is PREROLLING ...\n");
00582         caught_error = event_loop (pipeline, TRUE, GST_STATE_PAUSED);
00583         if (caught_error) {
00584           fprintf (stderr, "ERROR: pipeline doesn't want to preroll.\n");
00585           goto end;
00586         }
00587         state = GST_STATE_PAUSED;
00588         // fallthrough
00589     case GST_STATE_CHANGE_SUCCESS:
00590         fprintf (stderr, "Pipeline is PREROLLED ...\n");
00591         break;
00592     }
00593 
00594     // pipe successfully created
00595     return pipeline;
00596 
00597 end:
00598     mmsGstFree();
00599 
00600     return NULL;
00601 }
00602 
00603 
00604 
00605 
00606 GstElement *mmsGstInit(const string uri, MMSFBSurface *surface) {
00607 
00608     // initialize gstreamer
00609     gst_init(NULL, NULL);
00610     if (uri == "")
00611         return NULL;
00612 
00613     if (strToUpr(uri.substr(0,6)) == "GST://") {
00614         // the uri is an gstreamer pipeline
00615         // so we use the pipeline and do NOT use playbin with disko video sink
00616         return mmsGstLaunch(uri.substr(6).c_str());
00617     }
00618     else {
00619         // create top-level pipe element
00620         pipeline = gst_element_factory_make("playbin", "player");
00621 
00622         // get the diskovideosink element
00623         GstElement *videosink = gst_element_factory_make("diskovideosink", "diskovideosink");
00624 
00625         // set the surface to the diskovideosink element
00626         g_object_set(videosink, "surface", surface, NULL);
00627 
00628         // set videosink to the player
00629         g_object_set(G_OBJECT(pipeline), "video-sink", videosink, NULL);
00630 
00631         // set the uri to the player
00632         g_object_set(G_OBJECT(pipeline), "uri", uri.c_str(), NULL);
00633 
00634         return pipeline;
00635     }
00636 }
00637 
00638 GstElement *mmsGstInit(const string uri, MMSWindow *window) {
00639 
00640     // initialize gstreamer
00641     gst_init(NULL, NULL);
00642     if (uri == "")
00643         return NULL;
00644 
00645     if (strToUpr(uri.substr(0,6)) == "GST://") {
00646         // the uri is an gstreamer pipeline
00647         // so we use the pipeline and do NOT use playbin with disko video sink
00648         return mmsGstLaunch(uri.substr(6).c_str());
00649     }
00650     else {
00651         // create top-level pipe element
00652         pipeline = gst_element_factory_make("playbin", "player");
00653 
00654         // get the diskovideosink element
00655         GstElement *videosink = gst_element_factory_make("diskovideosink", "diskovideosink");
00656 
00657         // set the surface to the diskovideosink element
00658         // note: if using a window, the diskovideosink can handle keyboard,
00659         //       mouse, touchscreen inputs which are delivered to the MMSWindow
00660         g_object_set(videosink, "window", window, NULL);
00661 
00662         // set videosink to the player
00663         g_object_set(G_OBJECT(pipeline), "video-sink", videosink, NULL);
00664 
00665         // set the uri to the player
00666         g_object_set(G_OBJECT(pipeline), "uri", uri.c_str(), NULL);
00667 
00668         return pipeline;
00669     }
00670 }
00671 
00672 
00673 bool mmsGstPlay(GstElement *pipelineX) {
00674 
00675     pipeline = pipelineX;
00676 
00677 
00678     GstState state, pending;
00679 
00680 
00681     caught_error = event_loop (pipeline, FALSE, GST_STATE_PLAYING);
00682 
00683     if (caught_error) {
00684       fprintf (stderr, "ERROR: pipeline doesn't want to preroll.\n");
00685     } else {
00686       GstClockTime tfthen, tfnow;
00687       GstClockTimeDiff diff;
00688 
00689       fprintf (stderr, "Setting pipeline to PLAYING ...\n");
00690       if (gst_element_set_state (pipeline,
00691               GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
00692         GstMessage *err_msg;
00693         GstBus *bus;
00694 
00695         fprintf (stderr, "ERROR: pipeline doesn't want to play.\n");
00696         bus = gst_element_get_bus (pipeline);
00697         if ((err_msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0))) {
00698           GError *gerror;
00699           gchar *debug;
00700 
00701           gst_message_parse_error (err_msg, &gerror, &debug);
00702           gst_object_default_error (GST_MESSAGE_SRC (err_msg), gerror, debug);
00703           gst_message_unref (err_msg);
00704           g_error_free (gerror);
00705           g_free (debug);
00706         }
00707         gst_object_unref (bus);
00708 
00709         mmsGstFree();
00710 
00711         return false;
00712       }
00713 
00714       tfthen = gst_util_get_timestamp ();
00715       caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING);
00716       tfnow = gst_util_get_timestamp ();
00717 
00718       diff = GST_CLOCK_DIFF (tfthen, tfnow);
00719 
00720       g_print ("Execution ended after %" G_GUINT64_FORMAT " ns.\n", diff);
00721     }
00722 
00723     /* iterate mainloop to process pending stuff */
00724     while (g_main_context_iteration (NULL, FALSE));
00725 
00726     fprintf (stderr, "Setting pipeline to PAUSED ...\n");
00727     gst_element_set_state (pipeline, GST_STATE_PAUSED);
00728     if (!caught_error)
00729       gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
00730     fprintf (stderr, "Setting pipeline to READY ...\n");
00731     gst_element_set_state (pipeline, GST_STATE_READY);
00732     gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
00733 
00734     // playback is finished
00735     return true;
00736 }
00737 
00738 
00739 bool mmsGstSendKeyPress(GstElement *pipeline, MMSKeySymbol key) {
00740     if (!pipeline)
00741         return false;
00742 
00743     // if keysym string is empty, do nothing but return success
00744     const char *ks = convertMMSKeySymbolToXKeysymString(key);
00745     if (!*ks)
00746         return true;
00747 
00748     // construct event
00749     GstStructure *structure =
00750         gst_structure_new(  "application/x-gst-navigation",
00751                             "event",    G_TYPE_STRING,  "key-press",
00752                             "key",      G_TYPE_STRING,  ks,
00753                             NULL);
00754     if (!structure)
00755         return false;
00756     GstEvent *event = gst_event_new_navigation(structure);
00757     if (!event)
00758         return false;
00759 
00760     // send event
00761     return gst_element_send_event(pipeline, event);
00762 }
00763 
00764 bool mmsGstSendKeyRelease(GstElement *pipeline, MMSKeySymbol key) {
00765     if (!pipeline)
00766         return false;
00767 
00768     // if keysym string is empty, do nothing but return success
00769     const char *ks = convertMMSKeySymbolToXKeysymString(key);
00770     if (!*ks)
00771         return true;
00772 
00773     // construct event
00774     GstStructure *structure =
00775         gst_structure_new(  "application/x-gst-navigation",
00776                             "event",    G_TYPE_STRING,  "key-release",
00777                             "key",      G_TYPE_STRING,  ks,
00778                             NULL);
00779     if (!structure)
00780         return false;
00781     GstEvent *event = gst_event_new_navigation(structure);
00782     if (!event)
00783         return false;
00784 
00785     // send event
00786     return gst_element_send_event(pipeline, event);
00787 }
00788 
00789 bool mmsGstSendButtonPress(GstElement *pipeline, int posx, int posy) {
00790     if (!pipeline)
00791         return false;
00792 
00793     // construct event
00794     GstStructure *structure =
00795         gst_structure_new(  "application/x-gst-navigation",
00796                             "event",    G_TYPE_STRING,  "mouse-button-press",
00797                             "button",   G_TYPE_INT,     0,
00798                             "pointer_x",G_TYPE_DOUBLE,  (double)posx,
00799                             "pointer_y",G_TYPE_DOUBLE,  (double)posy,
00800                             NULL);
00801     if (!structure)
00802         return false;
00803     GstEvent *event = gst_event_new_navigation(structure);
00804     if (!event)
00805         return false;
00806 
00807     // send event
00808     return gst_element_send_event(pipeline, event);
00809 }
00810 
00811 bool mmsGstSendButtonRelease(GstElement *pipeline, int posx, int posy) {
00812     if (!pipeline)
00813         return false;
00814 
00815     // construct event
00816     GstStructure *structure =
00817         gst_structure_new(  "application/x-gst-navigation",
00818                             "event",    G_TYPE_STRING,  "mouse-button-release",
00819                             "button",   G_TYPE_INT,     0,
00820                             "pointer_x",G_TYPE_DOUBLE,  (double)posx,
00821                             "pointer_y",G_TYPE_DOUBLE,  (double)posy,
00822                             NULL);
00823     if (!structure)
00824         return false;
00825     GstEvent *event = gst_event_new_navigation(structure);
00826     if (!event)
00827         return false;
00828 
00829     // send event
00830     return gst_element_send_event(pipeline, event);
00831 }
00832 
00833 bool mmsGstSendAxisMotion(GstElement *pipeline, int posx, int posy) {
00834     if (!pipeline)
00835         return false;
00836 
00837     // construct event
00838     GstStructure *structure =
00839         gst_structure_new(  "application/x-gst-navigation",
00840                             "event",    G_TYPE_STRING,  "mouse-move",
00841                             "button",   G_TYPE_INT,     0,
00842                             "pointer_x",G_TYPE_DOUBLE,  (double)posx,
00843                             "pointer_y",G_TYPE_DOUBLE,  (double)posy,
00844                             NULL);
00845     if (!structure)
00846         return false;
00847     GstEvent *event = gst_event_new_navigation(structure);
00848     if (!event)
00849         return false;
00850 
00851     // send event
00852     return gst_element_send_event(pipeline, event);
00853 }
00854 
00855 
00856 #endif
00857 

Generated by doxygen