man: remove OIL_CPU_FLAGS from man page
[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         PRINT ("Clock lost, selecting a new one\n");
485         gst_element_set_state (pipeline, GST_STATE_PAUSED);
486         gst_element_set_state (pipeline, GST_STATE_PLAYING);
487         break;
488       case GST_MESSAGE_EOS:{
489         waiting_eos = FALSE;
490         PRINT (_("Got EOS from element \"%s\".\n"),
491             GST_MESSAGE_SRC_NAME (message));
492         goto exit;
493       }
494       case GST_MESSAGE_TAG:
495         if (tags) {
496           GstTagList *tags;
497
498           if (GST_IS_ELEMENT (GST_MESSAGE_SRC (message))) {
499             PRINT (_("FOUND TAG      : found by element \"%s\".\n"),
500                 GST_MESSAGE_SRC_NAME (message));
501           } else if (GST_IS_PAD (GST_MESSAGE_SRC (message))) {
502             PRINT (_("FOUND TAG      : found by pad \"%s:%s\".\n"),
503                 GST_DEBUG_PAD_NAME (GST_MESSAGE_SRC (message)));
504           } else if (GST_IS_OBJECT (GST_MESSAGE_SRC (message))) {
505             PRINT (_("FOUND TAG      : found by object \"%s\".\n"),
506                 GST_MESSAGE_SRC_NAME (message));
507           } else {
508             PRINT (_("FOUND TAG\n"));
509           }
510
511           gst_message_parse_tag (message, &tags);
512           gst_tag_list_foreach (tags, print_tag, NULL);
513           gst_tag_list_free (tags);
514         }
515         break;
516       case GST_MESSAGE_INFO:{
517         GError *gerror;
518         gchar *debug;
519         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
520
521         gst_message_parse_info (message, &gerror, &debug);
522         if (debug) {
523           PRINT (_("INFO:\n%s\n"), debug);
524         }
525         g_error_free (gerror);
526         g_free (debug);
527         g_free (name);
528         break;
529       }
530       case GST_MESSAGE_WARNING:{
531         GError *gerror;
532         gchar *debug;
533         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
534
535         /* dump graph on warning */
536         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
537             GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.warning");
538
539         gst_message_parse_warning (message, &gerror, &debug);
540         PRINT (_("WARNING: from element %s: %s\n"), name, gerror->message);
541         if (debug) {
542           PRINT (_("Additional debug info:\n%s\n"), debug);
543         }
544         g_error_free (gerror);
545         g_free (debug);
546         g_free (name);
547         break;
548       }
549       case GST_MESSAGE_ERROR:{
550         /* dump graph on error */
551         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
552             GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error");
553
554         print_error_message (message);
555
556         /* we have an error */
557         res = ELR_ERROR;
558         goto exit;
559       }
560       case GST_MESSAGE_STATE_CHANGED:{
561         GstState old, new, pending;
562
563         gst_message_parse_state_changed (message, &old, &new, &pending);
564
565         /* we only care about pipeline state change messages */
566         if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline))
567           break;
568
569         /* dump graph for pipeline state changes */
570         {
571           gchar *dump_name = g_strdup_printf ("gst-launch.%s_%s",
572               gst_element_state_get_name (old),
573               gst_element_state_get_name (new));
574           GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
575               GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
576           g_free (dump_name);
577         }
578
579         /* ignore when we are buffering since then we mess with the states
580          * ourselves. */
581         if (buffering) {
582           PRINT (_("Prerolled, waiting for buffering to finish...\n"));
583           break;
584         }
585
586         /* if we reached the final target state, exit */
587         if (target_state == GST_STATE_PAUSED && new == target_state)
588           goto exit;
589
590         /* else not an interesting message */
591         break;
592       }
593       case GST_MESSAGE_BUFFERING:{
594         gint percent;
595
596         gst_message_parse_buffering (message, &percent);
597         PRINT ("%s %d%%  \r", _("buffering..."), percent);
598
599         /* no state management needed for live pipelines */
600         if (is_live)
601           break;
602
603         if (percent == 100) {
604           /* a 100% message means buffering is done */
605           buffering = FALSE;
606           /* if the desired state is playing, go back */
607           if (target_state == GST_STATE_PLAYING) {
608             PRINT (_("Done buffering, setting pipeline to PLAYING ...\n"));
609             gst_element_set_state (pipeline, GST_STATE_PLAYING);
610           } else
611             goto exit;
612         } else {
613           /* buffering busy */
614           if (buffering == FALSE && target_state == GST_STATE_PLAYING) {
615             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
616             PRINT (_("Buffering, setting pipeline to PAUSED ...\n"));
617             gst_element_set_state (pipeline, GST_STATE_PAUSED);
618           }
619           buffering = TRUE;
620         }
621         break;
622       }
623       case GST_MESSAGE_LATENCY:
624       {
625         PRINT (_("Redistribute latency...\n"));
626         gst_bin_recalculate_latency (GST_BIN (pipeline));
627         break;
628       }
629       case GST_MESSAGE_REQUEST_STATE:
630       {
631         GstState state;
632         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
633
634         gst_message_parse_request_state (message, &state);
635
636         PRINT (_("Setting state to %s as requested by %s...\n"),
637             gst_element_state_get_name (state), name);
638
639         gst_element_set_state (pipeline, state);
640
641         g_free (name);
642         break;
643       }
644       case GST_MESSAGE_APPLICATION:{
645         const GstStructure *s;
646
647         s = gst_message_get_structure (message);
648
649         if (gst_structure_has_name (s, "GstLaunchInterrupt")) {
650           /* this application message is posted when we caught an interrupt and
651            * we need to stop the pipeline. */
652           PRINT (_("Interrupt: Stopping pipeline ...\n"));
653           res = ELR_INTERRUPT;
654           goto exit;
655         }
656       }
657       default:
658         /* just be quiet by default */
659         break;
660     }
661     if (message)
662       gst_message_unref (message);
663   }
664   g_assert_not_reached ();
665
666 exit:
667   {
668     if (message)
669       gst_message_unref (message);
670     gst_object_unref (bus);
671 #ifndef DISABLE_FAULT_HANDLER
672     g_source_remove (timeout_id);
673 #endif
674     return res;
675   }
676 }
677
678 int
679 main (int argc, char *argv[])
680 {
681   /* options */
682   gboolean verbose = FALSE;
683   gboolean no_fault = FALSE;
684   gboolean no_sigusr_handler = FALSE;
685   gboolean trace = FALSE;
686   gboolean eos_on_shutdown = FALSE;
687   gchar *savefile = NULL;
688   gchar *exclude_args = NULL;
689 #ifndef GST_DISABLE_OPTION_PARSING
690   GOptionEntry options[] = {
691     {"tags", 't', 0, G_OPTION_ARG_NONE, &tags,
692         N_("Output tags (also known as metadata)"), NULL},
693     {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
694         N_("Output status information and property notifications"), NULL},
695     {"quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
696         N_("Do not print any progress information"), NULL},
697     {"messages", 'm', 0, G_OPTION_ARG_NONE, &messages,
698         N_("Output messages"), NULL},
699     {"exclude", 'X', 0, G_OPTION_ARG_NONE, &exclude_args,
700         N_("Do not output status information of TYPE"), N_("TYPE1,TYPE2,...")},
701 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
702     {"output", 'o', 0, G_OPTION_ARG_STRING, &savefile,
703         N_("Save xml representation of pipeline to FILE and exit"), N_("FILE")},
704 #endif
705     {"no-fault", 'f', 0, G_OPTION_ARG_NONE, &no_fault,
706         N_("Do not install a fault handler"), NULL},
707     {"no-sigusr-handler", '\0', 0, G_OPTION_ARG_NONE, &no_sigusr_handler,
708         N_("Do not install signal handlers for SIGUSR1 and SIGUSR2"), NULL},
709     {"trace", 'T', 0, G_OPTION_ARG_NONE, &trace,
710         N_("Print alloc trace (if enabled at compile time)"), NULL},
711     {"eos-on-shutdown", 'e', 0, G_OPTION_ARG_NONE, &eos_on_shutdown,
712         N_("Force EOS on sources before shutting the pipeline down"), NULL},
713     GST_TOOLS_GOPTION_VERSION,
714     {NULL}
715   };
716   GOptionContext *ctx;
717   GError *err = NULL;
718 #endif
719   gchar **argvn;
720   GError *error = NULL;
721   gint res = 0;
722
723   free (malloc (8));            /* -lefence */
724
725 #ifdef ENABLE_NLS
726   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
727   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
728   textdomain (GETTEXT_PACKAGE);
729 #endif
730
731   g_thread_init (NULL);
732
733   gst_tools_set_prgname ("gst-launch");
734
735 #ifndef GST_DISABLE_OPTION_PARSING
736   ctx = g_option_context_new ("PIPELINE-DESCRIPTION");
737   g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
738   g_option_context_add_group (ctx, gst_init_get_option_group ());
739   if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
740     if (err)
741       g_printerr ("Error initializing: %s\n", GST_STR_NULL (err->message));
742     else
743       g_printerr ("Error initializing: Unknown error!\n");
744     exit (1);
745   }
746   g_option_context_free (ctx);
747 #else
748   gst_init (&argc, &argv);
749 #endif
750
751   gst_tools_print_version ("gst-launch");
752
753 #ifndef DISABLE_FAULT_HANDLER
754   if (!no_fault)
755     fault_setup ();
756
757   sigint_setup ();
758
759   if (!no_sigusr_handler)
760     play_signal_setup ();
761 #endif
762
763   if (trace) {
764     if (!gst_alloc_trace_available ()) {
765       g_warning ("Trace not available (recompile with trace enabled).");
766     }
767     gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE |
768         GST_ALLOC_TRACE_MEM_LIVE);
769     gst_alloc_trace_print_live ();
770   }
771
772   /* make a null-terminated version of argv */
773   argvn = g_new0 (char *, argc);
774   memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
775 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
776   if (strstr (argv[0], "gst-xmllaunch")) {
777     /* FIXME 0.11: remove xmllaunch entirely */
778     g_warning ("gst-xmllaunch is deprecated and broken for all but the most "
779         "simple pipelines. It will most likely be removed in future. Don't "
780         "use it.\n");
781     pipeline = xmllaunch_parse_cmdline ((const gchar **) argvn);
782   } else
783 #endif
784   {
785     pipeline =
786         (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error);
787   }
788   g_free (argvn);
789
790   if (!pipeline) {
791     if (error) {
792       g_printerr (_("ERROR: pipeline could not be constructed: %s.\n"),
793           GST_STR_NULL (error->message));
794       g_error_free (error);
795     } else {
796       g_printerr (_("ERROR: pipeline could not be constructed.\n"));
797     }
798     return 1;
799   } else if (error) {
800     g_printerr (_("WARNING: erroneous pipeline: %s\n"),
801         GST_STR_NULL (error->message));
802     g_error_free (error);
803     return 1;
804   }
805
806   if (verbose) {
807     gchar **exclude_list =
808         exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL;
809     g_signal_connect (pipeline, "deep-notify",
810         G_CALLBACK (gst_object_default_deep_notify), exclude_list);
811   }
812 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
813   if (savefile) {
814     g_warning ("Pipeline serialization to XML is deprecated and broken for "
815         "all but the most simple pipelines. It will most likely be removed "
816         "in future. Don't use it.\n");
817
818     gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
819   }
820 #endif
821
822   if (!savefile) {
823     GstState state, pending;
824     GstStateChangeReturn ret;
825
826     /* If the top-level object is not a pipeline, place it in a pipeline. */
827     if (!GST_IS_PIPELINE (pipeline)) {
828       GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL);
829
830       if (real_pipeline == NULL) {
831         g_printerr (_("ERROR: the 'pipeline' element wasn't found.\n"));
832         return 1;
833       }
834       gst_bin_add (GST_BIN (real_pipeline), pipeline);
835       pipeline = real_pipeline;
836     }
837     PRINT (_("Setting pipeline to PAUSED ...\n"));
838     ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
839
840     switch (ret) {
841       case GST_STATE_CHANGE_FAILURE:
842         g_printerr (_("ERROR: Pipeline doesn't want to pause.\n"));
843         res = -1;
844         event_loop (pipeline, FALSE, GST_STATE_VOID_PENDING);
845         goto end;
846       case GST_STATE_CHANGE_NO_PREROLL:
847         PRINT (_("Pipeline is live and does not need PREROLL ...\n"));
848         is_live = TRUE;
849         break;
850       case GST_STATE_CHANGE_ASYNC:
851         PRINT (_("Pipeline is PREROLLING ...\n"));
852         caught_error = event_loop (pipeline, TRUE, GST_STATE_PAUSED);
853         if (caught_error) {
854           g_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
855           goto end;
856         }
857         state = GST_STATE_PAUSED;
858         /* fallthrough */
859       case GST_STATE_CHANGE_SUCCESS:
860         PRINT (_("Pipeline is PREROLLED ...\n"));
861         break;
862     }
863
864     caught_error = event_loop (pipeline, FALSE, GST_STATE_PLAYING);
865
866     if (caught_error) {
867       g_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
868     } else {
869       GstClockTime tfthen, tfnow;
870       GstClockTimeDiff diff;
871
872       PRINT (_("Setting pipeline to PLAYING ...\n"));
873
874       if (gst_element_set_state (pipeline,
875               GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
876         GstMessage *err_msg;
877         GstBus *bus;
878
879         g_printerr (_("ERROR: pipeline doesn't want to play.\n"));
880         bus = gst_element_get_bus (pipeline);
881         if ((err_msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0))) {
882           print_error_message (err_msg);
883           gst_message_unref (err_msg);
884         }
885         gst_object_unref (bus);
886         res = -1;
887         goto end;
888       }
889
890       tfthen = gst_util_get_timestamp ();
891       caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING);
892       if (eos_on_shutdown && caught_error == ELR_INTERRUPT) {
893         PRINT (_("EOS on shutdown enabled -- Forcing EOS on the pipeline\n"));
894         waiting_eos = TRUE;
895         gst_element_send_event (pipeline, gst_event_new_eos ());
896         PRINT (_("Waiting for EOS...\n"));
897         caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING);
898
899         if (caught_error == ELR_NO_ERROR) {
900           /* we got EOS */
901           PRINT (_("EOS received - stopping pipeline...\n"));
902         } else if (caught_error == ELR_ERROR) {
903           PRINT (_("An error happened while waiting for EOS\n"));
904         }
905       }
906       tfnow = gst_util_get_timestamp ();
907
908       diff = GST_CLOCK_DIFF (tfthen, tfnow);
909
910       PRINT (_("Execution ended after %" G_GUINT64_FORMAT " ns.\n"), diff);
911     }
912
913     PRINT (_("Setting pipeline to PAUSED ...\n"));
914     gst_element_set_state (pipeline, GST_STATE_PAUSED);
915     if (caught_error == ELR_NO_ERROR)
916       gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
917
918     /* iterate mainloop to process pending stuff */
919     while (g_main_context_iteration (NULL, FALSE));
920
921     PRINT (_("Setting pipeline to READY ...\n"));
922     gst_element_set_state (pipeline, GST_STATE_READY);
923     gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
924
925   end:
926     PRINT (_("Setting pipeline to NULL ...\n"));
927     gst_element_set_state (pipeline, GST_STATE_NULL);
928     gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
929   }
930
931   PRINT (_("Freeing pipeline ...\n"));
932   gst_object_unref (pipeline);
933
934   gst_deinit ();
935   if (trace)
936     gst_alloc_trace_print_live ();
937
938   return res;
939 }