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