ab5e660358c8b0f1a698c987f56b496178dfa17c
[platform/upstream/gstreamer.git] / tools / gst-launch.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *               2000 Wim Taymans <wtay@chello.be>
4  *               2004 Thomas Vander Stichele <thomas@apestaart.org>
5  *
6  * gst-launch.c: tool to launch GStreamer pipelines from the command line
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 /* FIXME: hack alert */
29 #ifdef HAVE_WIN32
30 #define DISABLE_FAULT_HANDLER
31 #endif
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <signal.h>
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #ifndef DISABLE_FAULT_HANDLER
40 #include <sys/wait.h>
41 #endif
42 #include <locale.h>             /* for LC_ALL */
43 #include "tools.h"
44
45 /* FIXME: This is just a temporary hack.  We should have a better
46  * check for siginfo handling. */
47 #ifdef SA_SIGINFO
48 #define USE_SIGINFO
49 #endif
50
51 extern volatile gboolean glib_on_error_halt;
52
53 #ifndef DISABLE_FAULT_HANDLER
54 static void fault_restore (void);
55 static void fault_spin (void);
56 static void sigint_restore (void);
57 static gboolean caught_intr = FALSE;
58 #endif
59
60 /* event_loop return codes */
61 typedef enum _EventLoopResult
62 {
63   ELR_NO_ERROR = 0,
64   ELR_ERROR,
65   ELR_INTERRUPT
66 } EventLoopResult;
67
68 static GstElement *pipeline;
69 static EventLoopResult caught_error = ELR_NO_ERROR;
70 static gboolean quiet = FALSE;
71 static gboolean tags = FALSE;
72 static gboolean messages = FALSE;
73 static gboolean is_live = FALSE;
74 static gboolean waiting_eos = FALSE;
75
76 /* convenience macro so we don't have to litter the code with if(!quiet) */
77 #define PRINT if(!quiet)g_print
78
79 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
80 static GstElement *
81 xmllaunch_parse_cmdline (const gchar ** argv)
82 {
83   GstElement *pipeline = NULL, *e;
84   GstXML *xml;
85   gboolean err;
86   const gchar *arg;
87   gchar *element, *property, *value;
88   GList *l;
89   gint i = 0;
90
91   if (!(arg = argv[0])) {
92     g_printerr ("%s",
93         _("Usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n"));
94     exit (1);
95   }
96
97   xml = gst_xml_new ();
98   /* FIXME guchar from gstxml.c */
99   err = gst_xml_parse_file (xml, (guchar *) arg, NULL);
100
101   if (err != TRUE) {
102     g_printerr (_("ERROR: parse of xml file '%s' failed.\n"), arg);
103     exit (1);
104   }
105
106   l = gst_xml_get_topelements (xml);
107   if (!l) {
108     g_printerr (_("ERROR: no toplevel pipeline element in file '%s'.\n"), arg);
109     exit (1);
110   }
111
112   if (l->next) {
113     g_printerr ("%s",
114         _("WARNING: only one toplevel element is supported at this time.\n"));
115   }
116
117   pipeline = GST_ELEMENT (l->data);
118
119   while ((arg = argv[++i])) {
120     element = g_strdup (arg);
121     property = strchr (element, '.');
122     value = strchr (element, '=');
123
124     if (!(element < property && property < value)) {
125       g_printerr (_("ERROR: could not parse command line argument %d: %s.\n"),
126           i, element);
127       g_free (element);
128       exit (1);
129     }
130
131     *property++ = '\0';
132     *value++ = '\0';
133
134     e = gst_bin_get_by_name (GST_BIN (pipeline), element);
135     if (!e) {
136       g_printerr (_("WARNING: element named '%s' not found.\n"), element);
137     } else {
138       gst_util_set_object_arg (G_OBJECT (e), property, value);
139     }
140     g_free (element);
141   }
142
143   if (!l)
144     return NULL;
145
146   gst_object_ref (pipeline);
147   gst_object_unref (xml);
148   return pipeline;
149 }
150 #endif
151
152 #ifndef DISABLE_FAULT_HANDLER
153 #ifndef USE_SIGINFO
154 static void
155 fault_handler_sighandler (int signum)
156 {
157   fault_restore ();
158
159   /* printf is used instead of g_print(), since it's less likely to
160    * deadlock */
161   switch (signum) {
162     case SIGSEGV:
163       fprintf (stderr, "Caught SIGSEGV\n");
164       break;
165     case SIGQUIT:
166       if (!quiet)
167         printf ("Caught SIGQUIT\n");
168       break;
169     default:
170       fprintf (stderr, "signo:  %d\n", signum);
171       break;
172   }
173
174   fault_spin ();
175 }
176
177 #else /* USE_SIGINFO */
178
179 static void
180 fault_handler_sigaction (int signum, siginfo_t * si, void *misc)
181 {
182   fault_restore ();
183
184   /* printf is used instead of g_print(), since it's less likely to
185    * deadlock */
186   switch (si->si_signo) {
187     case SIGSEGV:
188       fprintf (stderr, "Caught SIGSEGV accessing address %p\n", si->si_addr);
189       break;
190     case SIGQUIT:
191       if (!quiet)
192         printf ("Caught SIGQUIT\n");
193       break;
194     default:
195       fprintf (stderr, "signo:  %d\n", si->si_signo);
196       fprintf (stderr, "errno:  %d\n", si->si_errno);
197       fprintf (stderr, "code:   %d\n", si->si_code);
198       break;
199   }
200
201   fault_spin ();
202 }
203 #endif /* USE_SIGINFO */
204
205 static void
206 fault_spin (void)
207 {
208   int spinning = TRUE;
209
210   glib_on_error_halt = FALSE;
211   g_on_error_stack_trace ("gst-launch");
212
213   wait (NULL);
214
215   /* FIXME how do we know if we were run by libtool? */
216   fprintf (stderr,
217       "Spinning.  Please run 'gdb gst-launch %d' to continue debugging, "
218       "Ctrl-C to quit, or Ctrl-\\ to dump core.\n", (gint) getpid ());
219   while (spinning)
220     g_usleep (1000000);
221 }
222
223 static void
224 fault_restore (void)
225 {
226   struct sigaction action;
227
228   memset (&action, 0, sizeof (action));
229   action.sa_handler = SIG_DFL;
230
231   sigaction (SIGSEGV, &action, NULL);
232   sigaction (SIGQUIT, &action, NULL);
233 }
234
235 static void
236 fault_setup (void)
237 {
238   struct sigaction action;
239
240   memset (&action, 0, sizeof (action));
241 #ifdef USE_SIGINFO
242   action.sa_sigaction = fault_handler_sigaction;
243   action.sa_flags = SA_SIGINFO;
244 #else
245   action.sa_handler = fault_handler_sighandler;
246 #endif
247
248   sigaction (SIGSEGV, &action, NULL);
249   sigaction (SIGQUIT, &action, NULL);
250 }
251 #endif /* DISABLE_FAULT_HANDLER */
252
253 static void
254 print_error_message (GstMessage * msg)
255 {
256   GError *err = NULL;
257   gchar *name, *debug = NULL;
258
259   name = gst_object_get_path_string (msg->src);
260   gst_message_parse_error (msg, &err, &debug);
261
262   g_printerr (_("ERROR: from element %s: %s\n"), name, err->message);
263   if (debug != NULL)
264     g_printerr (_("Additional debug info:\n%s\n"), debug);
265
266   g_error_free (err);
267   g_free (debug);
268   g_free (name);
269 }
270
271 static void
272 print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
273 {
274   gint i, count;
275
276   count = gst_tag_list_get_tag_size (list, tag);
277
278   for (i = 0; i < count; i++) {
279     gchar *str;
280
281     if (gst_tag_get_type (tag) == G_TYPE_STRING) {
282       if (!gst_tag_list_get_string_index (list, tag, i, &str))
283         g_assert_not_reached ();
284     } else if (gst_tag_get_type (tag) == GST_TYPE_BUFFER) {
285       GstBuffer *img;
286
287       img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i));
288       if (img) {
289         gchar *caps_str;
290
291         caps_str = GST_BUFFER_CAPS (img) ?
292             gst_caps_to_string (GST_BUFFER_CAPS (img)) : g_strdup ("unknown");
293         str = g_strdup_printf ("buffer of %u bytes, type: %s",
294             GST_BUFFER_SIZE (img), caps_str);
295         g_free (caps_str);
296       } else {
297         str = g_strdup ("NULL buffer");
298       }
299     } else {
300       str =
301           g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
302     }
303
304     if (i == 0) {
305       PRINT ("%16s: %s\n", gst_tag_get_nick (tag), str);
306     } else {
307       PRINT ("%16s: %s\n", "", str);
308     }
309
310     g_free (str);
311   }
312 }
313
314 #ifndef DISABLE_FAULT_HANDLER
315 /* we only use sighandler here because the registers are not important */
316 static void
317 sigint_handler_sighandler (int signum)
318 {
319   PRINT ("Caught interrupt -- ");
320
321   /* If we were waiting for an EOS, we still want to catch
322    * the next signal to shutdown properly (and the following one
323    * will quit the program). */
324   if (waiting_eos) {
325     waiting_eos = FALSE;
326   } else {
327     sigint_restore ();
328   }
329   /* we set a flag that is checked by the mainloop, we cannot do much in the
330    * interrupt handler (no mutex or other blocking stuff) */
331   caught_intr = TRUE;
332 }
333
334 /* is called every 250 milliseconds (4 times a second), the interrupt handler
335  * will set a flag for us. We react to this by posting a message. */
336 static gboolean
337 check_intr (GstElement * pipeline)
338 {
339   if (!caught_intr) {
340     return TRUE;
341   } else {
342     caught_intr = FALSE;
343     PRINT ("handling interrupt.\n");
344
345     /* post an application specific message */
346     gst_element_post_message (GST_ELEMENT (pipeline),
347         gst_message_new_application (GST_OBJECT (pipeline),
348             gst_structure_new ("GstLaunchInterrupt",
349                 "message", G_TYPE_STRING, "Pipeline interrupted", NULL)));
350
351     /* remove timeout handler */
352     return FALSE;
353   }
354 }
355
356 static void
357 sigint_setup (void)
358 {
359   struct sigaction action;
360
361   memset (&action, 0, sizeof (action));
362   action.sa_handler = sigint_handler_sighandler;
363
364   sigaction (SIGINT, &action, NULL);
365 }
366
367 static void
368 sigint_restore (void)
369 {
370   struct sigaction action;
371
372   memset (&action, 0, sizeof (action));
373   action.sa_handler = SIG_DFL;
374
375   sigaction (SIGINT, &action, NULL);
376 }
377
378 /* FIXME 0.11: remove SIGUSR handling (also from man page) */
379 static void
380 play_handler (int signum)
381 {
382   switch (signum) {
383     case SIGUSR1:
384       PRINT ("Caught SIGUSR1 - Play request.\n");
385       gst_element_set_state (pipeline, GST_STATE_PLAYING);
386       break;
387     case SIGUSR2:
388       PRINT ("Caught SIGUSR2 - Stop request.\n");
389       gst_element_set_state (pipeline, GST_STATE_NULL);
390       break;
391   }
392 }
393
394 static void
395 play_signal_setup (void)
396 {
397   struct sigaction action;
398
399   memset (&action, 0, sizeof (action));
400   action.sa_handler = play_handler;
401   sigaction (SIGUSR1, &action, NULL);
402   sigaction (SIGUSR2, &action, NULL);
403 }
404 #endif /* DISABLE_FAULT_HANDLER */
405
406 /* returns ELR_ERROR if there was an error
407  * or ELR_INTERRUPT if we caught a keyboard interrupt
408  * or ELR_NO_ERROR otherwise. */
409 static EventLoopResult
410 event_loop (GstElement * pipeline, gboolean blocking, GstState target_state)
411 {
412 #ifndef DISABLE_FAULT_HANDLER
413   gulong timeout_id;
414 #endif
415   GstBus *bus;
416   GstMessage *message = NULL;
417   EventLoopResult res = ELR_NO_ERROR;
418   gboolean buffering = FALSE;
419
420   bus = gst_element_get_bus (GST_ELEMENT (pipeline));
421
422 #ifndef DISABLE_FAULT_HANDLER
423   timeout_id = g_timeout_add (250, (GSourceFunc) check_intr, pipeline);
424 #endif
425
426   while (TRUE) {
427     message = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0);
428
429     /* if the poll timed out, only when !blocking */
430     if (message == NULL)
431       goto exit;
432
433     /* check if we need to dump messages to the console */
434     if (messages) {
435       GstObject *src_obj;
436       const GstStructure *s;
437       guint32 seqnum;
438
439       seqnum = gst_message_get_seqnum (message);
440
441       s = gst_message_get_structure (message);
442
443       src_obj = GST_MESSAGE_SRC (message);
444
445       if (GST_IS_ELEMENT (src_obj)) {
446         PRINT (_("Got message #%u from element \"%s\" (%s): "),
447             (guint) seqnum, GST_ELEMENT_NAME (src_obj),
448             GST_MESSAGE_TYPE_NAME (message));
449       } else if (GST_IS_PAD (src_obj)) {
450         PRINT (_("Got message #%u from pad \"%s:%s\" (%s): "),
451             (guint) seqnum, GST_DEBUG_PAD_NAME (src_obj),
452             GST_MESSAGE_TYPE_NAME (message));
453       } else if (GST_IS_OBJECT (src_obj)) {
454         PRINT (_("Got message #%u from object \"%s\" (%s): "),
455             (guint) seqnum, GST_OBJECT_NAME (src_obj),
456             GST_MESSAGE_TYPE_NAME (message));
457       } else {
458         PRINT (_("Got message #%u (%s): "), (guint) seqnum,
459             GST_MESSAGE_TYPE_NAME (message));
460       }
461
462       if (s) {
463         gchar *sstr;
464
465         sstr = gst_structure_to_string (s);
466         PRINT ("%s\n", sstr);
467         g_free (sstr);
468       } else {
469         PRINT ("no message details\n");
470       }
471     }
472
473     switch (GST_MESSAGE_TYPE (message)) {
474       case GST_MESSAGE_NEW_CLOCK:
475       {
476         GstClock *clock;
477
478         gst_message_parse_new_clock (message, &clock);
479
480         PRINT ("New clock: %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
481         break;
482       }
483       case GST_MESSAGE_CLOCK_LOST:
484 #if 0
485         /* disabled for now as it caused problems with rtspsrc. We need to fix
486          * rtspsrc first, then release -good before we can reenable this again
487          */
488         PRINT ("Clock lost, selecting a new one\n");
489         gst_element_set_state (pipeline, GST_STATE_PAUSED);
490         gst_element_set_state (pipeline, GST_STATE_PLAYING);
491 #endif
492         break;
493       case GST_MESSAGE_EOS:{
494         waiting_eos = FALSE;
495         PRINT (_("Got EOS from element \"%s\".\n"),
496             GST_MESSAGE_SRC_NAME (message));
497         goto exit;
498       }
499       case GST_MESSAGE_TAG:
500         if (tags) {
501           GstTagList *tags;
502
503           if (GST_IS_ELEMENT (GST_MESSAGE_SRC (message))) {
504             PRINT (_("FOUND TAG      : found by element \"%s\".\n"),
505                 GST_MESSAGE_SRC_NAME (message));
506           } else if (GST_IS_PAD (GST_MESSAGE_SRC (message))) {
507             PRINT (_("FOUND TAG      : found by pad \"%s:%s\".\n"),
508                 GST_DEBUG_PAD_NAME (GST_MESSAGE_SRC (message)));
509           } else if (GST_IS_OBJECT (GST_MESSAGE_SRC (message))) {
510             PRINT (_("FOUND TAG      : found by object \"%s\".\n"),
511                 GST_MESSAGE_SRC_NAME (message));
512           } else {
513             PRINT (_("FOUND TAG\n"));
514           }
515
516           gst_message_parse_tag (message, &tags);
517           gst_tag_list_foreach (tags, print_tag, NULL);
518           gst_tag_list_free (tags);
519         }
520         break;
521       case GST_MESSAGE_INFO:{
522         GError *gerror;
523         gchar *debug;
524         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
525
526         gst_message_parse_info (message, &gerror, &debug);
527         if (debug) {
528           PRINT (_("INFO:\n%s\n"), debug);
529         }
530         g_error_free (gerror);
531         g_free (debug);
532         g_free (name);
533         break;
534       }
535       case GST_MESSAGE_WARNING:{
536         GError *gerror;
537         gchar *debug;
538         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
539
540         /* dump graph on warning */
541         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
542             GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.warning");
543
544         gst_message_parse_warning (message, &gerror, &debug);
545         PRINT (_("WARNING: from element %s: %s\n"), name, gerror->message);
546         if (debug) {
547           PRINT (_("Additional debug info:\n%s\n"), debug);
548         }
549         g_error_free (gerror);
550         g_free (debug);
551         g_free (name);
552         break;
553       }
554       case GST_MESSAGE_ERROR:{
555         /* dump graph on error */
556         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
557             GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error");
558
559         print_error_message (message);
560
561         /* we have an error */
562         res = ELR_ERROR;
563         goto exit;
564       }
565       case GST_MESSAGE_STATE_CHANGED:{
566         GstState old, new, pending;
567
568         gst_message_parse_state_changed (message, &old, &new, &pending);
569
570         /* we only care about pipeline state change messages */
571         if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline))
572           break;
573
574         /* dump graph for pipeline state changes */
575         {
576           gchar *dump_name = g_strdup_printf ("gst-launch.%s_%s",
577               gst_element_state_get_name (old),
578               gst_element_state_get_name (new));
579           GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
580               GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
581           g_free (dump_name);
582         }
583
584         /* ignore when we are buffering since then we mess with the states
585          * ourselves. */
586         if (buffering) {
587           PRINT (_("Prerolled, waiting for buffering to finish...\n"));
588           break;
589         }
590
591         /* if we reached the final target state, exit */
592         if (target_state == GST_STATE_PAUSED && new == target_state)
593           goto exit;
594
595         /* else not an interesting message */
596         break;
597       }
598       case GST_MESSAGE_BUFFERING:{
599         gint percent;
600
601         gst_message_parse_buffering (message, &percent);
602         PRINT ("%s %d%%  \r", _("buffering..."), percent);
603
604         /* no state management needed for live pipelines */
605         if (is_live)
606           break;
607
608         if (percent == 100) {
609           /* a 100% message means buffering is done */
610           buffering = FALSE;
611           /* if the desired state is playing, go back */
612           if (target_state == GST_STATE_PLAYING) {
613             PRINT (_("Done buffering, setting pipeline to PLAYING ...\n"));
614             gst_element_set_state (pipeline, GST_STATE_PLAYING);
615           } else
616             goto exit;
617         } else {
618           /* buffering busy */
619           if (buffering == FALSE && target_state == GST_STATE_PLAYING) {
620             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
621             PRINT (_("Buffering, setting pipeline to PAUSED ...\n"));
622             gst_element_set_state (pipeline, GST_STATE_PAUSED);
623           }
624           buffering = TRUE;
625         }
626         break;
627       }
628       case GST_MESSAGE_LATENCY:
629       {
630         PRINT (_("Redistribute latency...\n"));
631         gst_bin_recalculate_latency (GST_BIN (pipeline));
632         break;
633       }
634       case GST_MESSAGE_REQUEST_STATE:
635       {
636         GstState state;
637         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
638
639         gst_message_parse_request_state (message, &state);
640
641         PRINT (_("Setting state to %s as requested by %s...\n"),
642             gst_element_state_get_name (state), name);
643
644         gst_element_set_state (pipeline, state);
645
646         g_free (name);
647         break;
648       }
649       case GST_MESSAGE_APPLICATION:{
650         const GstStructure *s;
651
652         s = gst_message_get_structure (message);
653
654         if (gst_structure_has_name (s, "GstLaunchInterrupt")) {
655           /* this application message is posted when we caught an interrupt and
656            * we need to stop the pipeline. */
657           PRINT (_("Interrupt: Stopping pipeline ...\n"));
658           res = ELR_INTERRUPT;
659           goto exit;
660         }
661       }
662       default:
663         /* just be quiet by default */
664         break;
665     }
666     if (message)
667       gst_message_unref (message);
668   }
669   g_assert_not_reached ();
670
671 exit:
672   {
673     if (message)
674       gst_message_unref (message);
675     gst_object_unref (bus);
676 #ifndef DISABLE_FAULT_HANDLER
677     g_source_remove (timeout_id);
678 #endif
679     return res;
680   }
681 }
682
683 int
684 main (int argc, char *argv[])
685 {
686   /* options */
687   gboolean verbose = FALSE;
688   gboolean no_fault = FALSE;
689   gboolean no_sigusr_handler = FALSE;
690   gboolean trace = FALSE;
691   gboolean eos_on_shutdown = FALSE;
692   gchar *savefile = NULL;
693   gchar *exclude_args = NULL;
694 #ifndef GST_DISABLE_OPTION_PARSING
695   GOptionEntry options[] = {
696     {"tags", 't', 0, G_OPTION_ARG_NONE, &tags,
697         N_("Output tags (also known as metadata)"), NULL},
698     {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
699         N_("Output status information and property notifications"), NULL},
700     {"quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
701         N_("Do not print any progress information"), NULL},
702     {"messages", 'm', 0, G_OPTION_ARG_NONE, &messages,
703         N_("Output messages"), NULL},
704     {"exclude", 'X', 0, G_OPTION_ARG_NONE, &exclude_args,
705         N_("Do not output status information of TYPE"), N_("TYPE1,TYPE2,...")},
706 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
707     {"output", 'o', 0, G_OPTION_ARG_STRING, &savefile,
708         N_("Save xml representation of pipeline to FILE and exit"), N_("FILE")},
709 #endif
710     {"no-fault", 'f', 0, G_OPTION_ARG_NONE, &no_fault,
711         N_("Do not install a fault handler"), NULL},
712     {"no-sigusr-handler", 'p', 0, G_OPTION_ARG_NONE, &no_sigusr_handler,
713         N_("Do not install signal handlers for SIGUSR1 and SIGUSR2"), NULL},
714     {"trace", 'T', 0, G_OPTION_ARG_NONE, &trace,
715         N_("Print alloc trace (if enabled at compile time)"), NULL},
716     {"eos-on-shutdown", 'e', 0, G_OPTION_ARG_NONE, &eos_on_shutdown,
717         N_("Force EOS on sources before shutting the pipeline down"), NULL},
718     GST_TOOLS_GOPTION_VERSION,
719     {NULL}
720   };
721   GOptionContext *ctx;
722   GError *err = NULL;
723 #endif
724   gchar **argvn;
725   GError *error = NULL;
726   gint res = 0;
727
728   free (malloc (8));            /* -lefence */
729
730 #ifdef ENABLE_NLS
731   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
732   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
733   textdomain (GETTEXT_PACKAGE);
734 #endif
735
736   g_thread_init (NULL);
737
738   gst_tools_set_prgname ("gst-launch");
739
740 #ifndef GST_DISABLE_OPTION_PARSING
741   ctx = g_option_context_new ("PIPELINE-DESCRIPTION");
742   g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
743   g_option_context_add_group (ctx, gst_init_get_option_group ());
744   if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
745     if (err)
746       g_printerr ("Error initializing: %s\n", GST_STR_NULL (err->message));
747     else
748       g_printerr ("Error initializing: Unknown error!\n");
749     exit (1);
750   }
751   g_option_context_free (ctx);
752 #else
753   gst_init (&argc, &argv);
754 #endif
755
756   gst_tools_print_version ("gst-launch");
757
758 #ifndef DISABLE_FAULT_HANDLER
759   if (!no_fault)
760     fault_setup ();
761
762   sigint_setup ();
763
764   if (!no_sigusr_handler)
765     play_signal_setup ();
766 #endif
767
768   if (trace) {
769     if (!gst_alloc_trace_available ()) {
770       g_warning ("Trace not available (recompile with trace enabled).");
771     }
772     gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE |
773         GST_ALLOC_TRACE_MEM_LIVE);
774     gst_alloc_trace_print_live ();
775   }
776
777   /* make a null-terminated version of argv */
778   argvn = g_new0 (char *, argc);
779   memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
780 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
781   if (strstr (argv[0], "gst-xmllaunch")) {
782     /* FIXME 0.11: remove xmllaunch entirely */
783     g_warning ("gst-xmllaunch is deprecated and broken for all but the most "
784         "simple pipelines. It will most likely be removed in future. Don't "
785         "use it.\n");
786     pipeline = xmllaunch_parse_cmdline ((const gchar **) argvn);
787   } else
788 #endif
789   {
790     pipeline =
791         (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error);
792   }
793   g_free (argvn);
794
795   if (!pipeline) {
796     if (error) {
797       g_printerr (_("ERROR: pipeline could not be constructed: %s.\n"),
798           GST_STR_NULL (error->message));
799       g_error_free (error);
800     } else {
801       g_printerr (_("ERROR: pipeline could not be constructed.\n"));
802     }
803     return 1;
804   } else if (error) {
805     g_printerr (_("WARNING: erroneous pipeline: %s\n"),
806         GST_STR_NULL (error->message));
807     g_error_free (error);
808     return 1;
809   }
810
811   if (verbose) {
812     gchar **exclude_list =
813         exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL;
814     g_signal_connect (pipeline, "deep-notify",
815         G_CALLBACK (gst_object_default_deep_notify), exclude_list);
816   }
817 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
818   if (savefile) {
819     g_warning ("Pipeline serialization to XML is deprecated and broken for "
820         "all but the most simple pipelines. It will most likely be removed "
821         "in future. Don't use it.\n");
822
823     gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
824   }
825 #endif
826
827   if (!savefile) {
828     GstState state, pending;
829     GstStateChangeReturn ret;
830
831     /* If the top-level object is not a pipeline, place it in a pipeline. */
832     if (!GST_IS_PIPELINE (pipeline)) {
833       GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL);
834
835       if (real_pipeline == NULL) {
836         g_printerr (_("ERROR: the 'pipeline' element wasn't found.\n"));
837         return 1;
838       }
839       gst_bin_add (GST_BIN (real_pipeline), pipeline);
840       pipeline = real_pipeline;
841     }
842     PRINT (_("Setting pipeline to PAUSED ...\n"));
843     ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
844
845     switch (ret) {
846       case GST_STATE_CHANGE_FAILURE:
847         g_printerr (_("ERROR: Pipeline doesn't want to pause.\n"));
848         res = -1;
849         event_loop (pipeline, FALSE, GST_STATE_VOID_PENDING);
850         goto end;
851       case GST_STATE_CHANGE_NO_PREROLL:
852         PRINT (_("Pipeline is live and does not need PREROLL ...\n"));
853         is_live = TRUE;
854         break;
855       case GST_STATE_CHANGE_ASYNC:
856         PRINT (_("Pipeline is PREROLLING ...\n"));
857         caught_error = event_loop (pipeline, TRUE, GST_STATE_PAUSED);
858         if (caught_error) {
859           g_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
860           goto end;
861         }
862         state = GST_STATE_PAUSED;
863         /* fallthrough */
864       case GST_STATE_CHANGE_SUCCESS:
865         PRINT (_("Pipeline is PREROLLED ...\n"));
866         break;
867     }
868
869     caught_error = event_loop (pipeline, FALSE, GST_STATE_PLAYING);
870
871     if (caught_error) {
872       g_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
873     } else {
874       GstClockTime tfthen, tfnow;
875       GstClockTimeDiff diff;
876
877       PRINT (_("Setting pipeline to PLAYING ...\n"));
878
879       if (gst_element_set_state (pipeline,
880               GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
881         GstMessage *err_msg;
882         GstBus *bus;
883
884         g_printerr (_("ERROR: pipeline doesn't want to play.\n"));
885         bus = gst_element_get_bus (pipeline);
886         if ((err_msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0))) {
887           print_error_message (err_msg);
888           gst_message_unref (err_msg);
889         }
890         gst_object_unref (bus);
891         res = -1;
892         goto end;
893       }
894
895       tfthen = gst_util_get_timestamp ();
896       caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING);
897       if (eos_on_shutdown && caught_error == ELR_INTERRUPT) {
898         PRINT (_("EOS on shutdown enabled -- Forcing EOS on the pipeline\n"));
899         waiting_eos = TRUE;
900         gst_element_send_event (pipeline, gst_event_new_eos ());
901         PRINT (_("Waiting for EOS...\n"));
902         caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING);
903
904         if (caught_error == ELR_NO_ERROR) {
905           /* we got EOS */
906           PRINT (_("EOS received - stopping pipeline...\n"));
907         } else if (caught_error == ELR_ERROR) {
908           PRINT (_("An error happened while waiting for EOS\n"));
909         }
910       }
911       tfnow = gst_util_get_timestamp ();
912
913       diff = GST_CLOCK_DIFF (tfthen, tfnow);
914
915       PRINT (_("Execution ended after %" G_GUINT64_FORMAT " ns.\n"), diff);
916     }
917
918     PRINT (_("Setting pipeline to PAUSED ...\n"));
919     gst_element_set_state (pipeline, GST_STATE_PAUSED);
920     if (caught_error == ELR_NO_ERROR)
921       gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
922
923     /* iterate mainloop to process pending stuff */
924     while (g_main_context_iteration (NULL, FALSE));
925
926     PRINT (_("Setting pipeline to READY ...\n"));
927     gst_element_set_state (pipeline, GST_STATE_READY);
928     gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
929
930   end:
931     PRINT (_("Setting pipeline to NULL ...\n"));
932     gst_element_set_state (pipeline, GST_STATE_NULL);
933     gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
934   }
935
936   PRINT (_("Freeing pipeline ...\n"));
937   gst_object_unref (pipeline);
938
939   gst_deinit ();
940   if (trace)
941     gst_alloc_trace_print_live ();
942
943   return res;
944 }