gst-launch: pretty-print datetime tags
[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 if (gst_tag_get_type (tag) == GST_TYPE_DATE_TIME) {
300       GstDateTime *dt = NULL;
301
302       gst_tag_list_get_date_time_index (list, tag, i, &dt);
303       if (gst_date_time_get_hour (dt) < 0) {
304         str = g_strdup_printf ("%02u-%02u-%04u", gst_date_time_get_day (dt),
305             gst_date_time_get_month (dt), gst_date_time_get_year (dt));
306       } else {
307         gdouble tz_offset = gst_date_time_get_time_zone_offset (dt);
308         gchar tz_str[32];
309
310         if (tz_offset != 0.0) {
311           g_snprintf (tz_str, sizeof (tz_str), "(UTC %s%gh)",
312               (tz_offset > 0.0) ? "+" : "", tz_offset);
313         } else {
314           g_snprintf (tz_str, sizeof (tz_str), "(UTC)");
315         }
316
317         str = g_strdup_printf ("%04u-%02u-%02u %02u:%02u:%02u %s",
318             gst_date_time_get_year (dt), gst_date_time_get_month (dt),
319             gst_date_time_get_day (dt), gst_date_time_get_hour (dt),
320             gst_date_time_get_minute (dt), gst_date_time_get_second (dt),
321             tz_str);
322       }
323       gst_date_time_unref (dt);
324     } else {
325       str =
326           g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i));
327     }
328
329     if (i == 0) {
330       PRINT ("%16s: %s\n", gst_tag_get_nick (tag), str);
331     } else {
332       PRINT ("%16s: %s\n", "", str);
333     }
334
335     g_free (str);
336   }
337 }
338
339 #ifndef DISABLE_FAULT_HANDLER
340 /* we only use sighandler here because the registers are not important */
341 static void
342 sigint_handler_sighandler (int signum)
343 {
344   PRINT ("Caught interrupt -- ");
345
346   /* If we were waiting for an EOS, we still want to catch
347    * the next signal to shutdown properly (and the following one
348    * will quit the program). */
349   if (waiting_eos) {
350     waiting_eos = FALSE;
351   } else {
352     sigint_restore ();
353   }
354   /* we set a flag that is checked by the mainloop, we cannot do much in the
355    * interrupt handler (no mutex or other blocking stuff) */
356   caught_intr = TRUE;
357 }
358
359 /* is called every 250 milliseconds (4 times a second), the interrupt handler
360  * will set a flag for us. We react to this by posting a message. */
361 static gboolean
362 check_intr (GstElement * pipeline)
363 {
364   if (!caught_intr) {
365     return TRUE;
366   } else {
367     caught_intr = FALSE;
368     PRINT ("handling interrupt.\n");
369
370     /* post an application specific message */
371     gst_element_post_message (GST_ELEMENT (pipeline),
372         gst_message_new_application (GST_OBJECT (pipeline),
373             gst_structure_new ("GstLaunchInterrupt",
374                 "message", G_TYPE_STRING, "Pipeline interrupted", NULL)));
375
376     /* remove timeout handler */
377     return FALSE;
378   }
379 }
380
381 static void
382 sigint_setup (void)
383 {
384   struct sigaction action;
385
386   memset (&action, 0, sizeof (action));
387   action.sa_handler = sigint_handler_sighandler;
388
389   sigaction (SIGINT, &action, NULL);
390 }
391
392 static void
393 sigint_restore (void)
394 {
395   struct sigaction action;
396
397   memset (&action, 0, sizeof (action));
398   action.sa_handler = SIG_DFL;
399
400   sigaction (SIGINT, &action, NULL);
401 }
402
403 /* FIXME 0.11: remove SIGUSR handling (also from man page) */
404 static void
405 play_handler (int signum)
406 {
407   switch (signum) {
408     case SIGUSR1:
409       PRINT ("Caught SIGUSR1 - Play request.\n");
410       gst_element_set_state (pipeline, GST_STATE_PLAYING);
411       break;
412     case SIGUSR2:
413       PRINT ("Caught SIGUSR2 - Stop request.\n");
414       gst_element_set_state (pipeline, GST_STATE_NULL);
415       break;
416   }
417 }
418
419 static void
420 play_signal_setup (void)
421 {
422   struct sigaction action;
423
424   memset (&action, 0, sizeof (action));
425   action.sa_handler = play_handler;
426   sigaction (SIGUSR1, &action, NULL);
427   sigaction (SIGUSR2, &action, NULL);
428 }
429 #endif /* DISABLE_FAULT_HANDLER */
430
431 /* returns ELR_ERROR if there was an error
432  * or ELR_INTERRUPT if we caught a keyboard interrupt
433  * or ELR_NO_ERROR otherwise. */
434 static EventLoopResult
435 event_loop (GstElement * pipeline, gboolean blocking, GstState target_state)
436 {
437 #ifndef DISABLE_FAULT_HANDLER
438   gulong timeout_id;
439 #endif
440   GstBus *bus;
441   GstMessage *message = NULL;
442   EventLoopResult res = ELR_NO_ERROR;
443   gboolean buffering = FALSE;
444
445   bus = gst_element_get_bus (GST_ELEMENT (pipeline));
446
447 #ifndef DISABLE_FAULT_HANDLER
448   timeout_id = g_timeout_add (250, (GSourceFunc) check_intr, pipeline);
449 #endif
450
451   while (TRUE) {
452     message = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0);
453
454     /* if the poll timed out, only when !blocking */
455     if (message == NULL)
456       goto exit;
457
458     /* check if we need to dump messages to the console */
459     if (messages) {
460       GstObject *src_obj;
461       const GstStructure *s;
462       guint32 seqnum;
463
464       seqnum = gst_message_get_seqnum (message);
465
466       s = gst_message_get_structure (message);
467
468       src_obj = GST_MESSAGE_SRC (message);
469
470       if (GST_IS_ELEMENT (src_obj)) {
471         PRINT (_("Got message #%u from element \"%s\" (%s): "),
472             (guint) seqnum, GST_ELEMENT_NAME (src_obj),
473             GST_MESSAGE_TYPE_NAME (message));
474       } else if (GST_IS_PAD (src_obj)) {
475         PRINT (_("Got message #%u from pad \"%s:%s\" (%s): "),
476             (guint) seqnum, GST_DEBUG_PAD_NAME (src_obj),
477             GST_MESSAGE_TYPE_NAME (message));
478       } else if (GST_IS_OBJECT (src_obj)) {
479         PRINT (_("Got message #%u from object \"%s\" (%s): "),
480             (guint) seqnum, GST_OBJECT_NAME (src_obj),
481             GST_MESSAGE_TYPE_NAME (message));
482       } else {
483         PRINT (_("Got message #%u (%s): "), (guint) seqnum,
484             GST_MESSAGE_TYPE_NAME (message));
485       }
486
487       if (s) {
488         gchar *sstr;
489
490         sstr = gst_structure_to_string (s);
491         PRINT ("%s\n", sstr);
492         g_free (sstr);
493       } else {
494         PRINT ("no message details\n");
495       }
496     }
497
498     switch (GST_MESSAGE_TYPE (message)) {
499       case GST_MESSAGE_NEW_CLOCK:
500       {
501         GstClock *clock;
502
503         gst_message_parse_new_clock (message, &clock);
504
505         PRINT ("New clock: %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
506         break;
507       }
508       case GST_MESSAGE_CLOCK_LOST:
509         PRINT ("Clock lost, selecting a new one\n");
510         gst_element_set_state (pipeline, GST_STATE_PAUSED);
511         gst_element_set_state (pipeline, GST_STATE_PLAYING);
512         break;
513       case GST_MESSAGE_EOS:{
514         waiting_eos = FALSE;
515         PRINT (_("Got EOS from element \"%s\".\n"),
516             GST_MESSAGE_SRC_NAME (message));
517         goto exit;
518       }
519       case GST_MESSAGE_TAG:
520         if (tags) {
521           GstTagList *tags;
522
523           if (GST_IS_ELEMENT (GST_MESSAGE_SRC (message))) {
524             PRINT (_("FOUND TAG      : found by element \"%s\".\n"),
525                 GST_MESSAGE_SRC_NAME (message));
526           } else if (GST_IS_PAD (GST_MESSAGE_SRC (message))) {
527             PRINT (_("FOUND TAG      : found by pad \"%s:%s\".\n"),
528                 GST_DEBUG_PAD_NAME (GST_MESSAGE_SRC (message)));
529           } else if (GST_IS_OBJECT (GST_MESSAGE_SRC (message))) {
530             PRINT (_("FOUND TAG      : found by object \"%s\".\n"),
531                 GST_MESSAGE_SRC_NAME (message));
532           } else {
533             PRINT (_("FOUND TAG\n"));
534           }
535
536           gst_message_parse_tag (message, &tags);
537           gst_tag_list_foreach (tags, print_tag, NULL);
538           gst_tag_list_free (tags);
539         }
540         break;
541       case GST_MESSAGE_INFO:{
542         GError *gerror;
543         gchar *debug;
544         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
545
546         gst_message_parse_info (message, &gerror, &debug);
547         if (debug) {
548           PRINT (_("INFO:\n%s\n"), debug);
549         }
550         g_error_free (gerror);
551         g_free (debug);
552         g_free (name);
553         break;
554       }
555       case GST_MESSAGE_WARNING:{
556         GError *gerror;
557         gchar *debug;
558         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
559
560         /* dump graph on warning */
561         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
562             GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.warning");
563
564         gst_message_parse_warning (message, &gerror, &debug);
565         PRINT (_("WARNING: from element %s: %s\n"), name, gerror->message);
566         if (debug) {
567           PRINT (_("Additional debug info:\n%s\n"), debug);
568         }
569         g_error_free (gerror);
570         g_free (debug);
571         g_free (name);
572         break;
573       }
574       case GST_MESSAGE_ERROR:{
575         /* dump graph on error */
576         GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
577             GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error");
578
579         print_error_message (message);
580
581         /* we have an error */
582         res = ELR_ERROR;
583         goto exit;
584       }
585       case GST_MESSAGE_STATE_CHANGED:{
586         GstState old, new, pending;
587
588         /* we only care about pipeline state change messages */
589         if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline))
590           break;
591
592         /* ignore when we are buffering since then we mess with the states
593          * ourselves. */
594         if (buffering) {
595           PRINT (_("Prerolled, waiting for buffering to finish...\n"));
596           break;
597         }
598
599         gst_message_parse_state_changed (message, &old, &new, &pending);
600
601         /* if we reached the final target state, exit */
602         if (target_state == GST_STATE_PAUSED && new == target_state)
603           goto exit;
604
605         /* else not an interesting message */
606         break;
607       }
608       case GST_MESSAGE_BUFFERING:{
609         gint percent;
610
611         gst_message_parse_buffering (message, &percent);
612         PRINT ("%s %d%%  \r", _("buffering..."), percent);
613
614         /* no state management needed for live pipelines */
615         if (is_live)
616           break;
617
618         if (percent == 100) {
619           /* a 100% message means buffering is done */
620           buffering = FALSE;
621           /* if the desired state is playing, go back */
622           if (target_state == GST_STATE_PLAYING) {
623             PRINT (_("Done buffering, setting pipeline to PLAYING ...\n"));
624             gst_element_set_state (pipeline, GST_STATE_PLAYING);
625           } else
626             goto exit;
627         } else {
628           /* buffering busy */
629           if (buffering == FALSE && target_state == GST_STATE_PLAYING) {
630             /* we were not buffering but PLAYING, PAUSE  the pipeline. */
631             PRINT (_("Buffering, setting pipeline to PAUSED ...\n"));
632             gst_element_set_state (pipeline, GST_STATE_PAUSED);
633           }
634           buffering = TRUE;
635         }
636         break;
637       }
638       case GST_MESSAGE_LATENCY:
639       {
640         PRINT (_("Redistribute latency...\n"));
641         gst_bin_recalculate_latency (GST_BIN (pipeline));
642         break;
643       }
644       case GST_MESSAGE_REQUEST_STATE:
645       {
646         GstState state;
647         gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));
648
649         gst_message_parse_request_state (message, &state);
650
651         PRINT (_("Setting state to %s as requested by %s...\n"),
652             gst_element_state_get_name (state), name);
653
654         gst_element_set_state (pipeline, state);
655
656         g_free (name);
657         break;
658       }
659       case GST_MESSAGE_APPLICATION:{
660         const GstStructure *s;
661
662         s = gst_message_get_structure (message);
663
664         if (gst_structure_has_name (s, "GstLaunchInterrupt")) {
665           /* this application message is posted when we caught an interrupt and
666            * we need to stop the pipeline. */
667           PRINT (_("Interrupt: Stopping pipeline ...\n"));
668           res = ELR_INTERRUPT;
669           goto exit;
670         }
671       }
672       default:
673         /* just be quiet by default */
674         break;
675     }
676     if (message)
677       gst_message_unref (message);
678   }
679   g_assert_not_reached ();
680
681 exit:
682   {
683     if (message)
684       gst_message_unref (message);
685     gst_object_unref (bus);
686 #ifndef DISABLE_FAULT_HANDLER
687     g_source_remove (timeout_id);
688 #endif
689     return res;
690   }
691 }
692
693 static GstBusSyncReply
694 bus_sync_handler (GstBus * bus, GstMessage * message, gpointer data)
695 {
696   GstElement *pipeline = (GstElement *) data;
697
698   switch (GST_MESSAGE_TYPE (message)) {
699     case GST_MESSAGE_STATE_CHANGED:
700       /* we only care about pipeline state change messages */
701       if (GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (pipeline)) {
702         GstState old, new, pending;
703         gchar *state_transition_name;
704
705         gst_message_parse_state_changed (message, &old, &new, &pending);
706
707         state_transition_name = g_strdup_printf ("%s_%s",
708             gst_element_state_get_name (old), gst_element_state_get_name (new));
709
710         /* dump graph for (some) pipeline state changes */
711         {
712           gchar *dump_name = g_strconcat ("gst-launch.", state_transition_name,
713               NULL);
714           GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
715               GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
716           g_free (dump_name);
717         }
718
719         /* place a marker into e.g. strace logs */
720         {
721           gchar *access_name = g_strconcat (g_get_tmp_dir (), G_DIR_SEPARATOR_S,
722               "gst-launch", G_DIR_SEPARATOR_S, state_transition_name, NULL);
723           g_file_test (access_name, G_FILE_TEST_EXISTS);
724           g_free (access_name);
725         }
726
727         g_free (state_transition_name);
728       }
729     default:
730       break;
731   }
732   return GST_BUS_PASS;
733 }
734
735 int
736 main (int argc, char *argv[])
737 {
738   /* options */
739   gboolean verbose = FALSE;
740   gboolean no_fault = FALSE;
741   gboolean no_sigusr_handler = FALSE;
742   gboolean trace = FALSE;
743   gboolean eos_on_shutdown = FALSE;
744   gchar *savefile = NULL;
745   gchar *exclude_args = NULL;
746 #ifndef GST_DISABLE_OPTION_PARSING
747   GOptionEntry options[] = {
748     {"tags", 't', 0, G_OPTION_ARG_NONE, &tags,
749         N_("Output tags (also known as metadata)"), NULL},
750     {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
751         N_("Output status information and property notifications"), NULL},
752     {"quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
753         N_("Do not print any progress information"), NULL},
754     {"messages", 'm', 0, G_OPTION_ARG_NONE, &messages,
755         N_("Output messages"), NULL},
756     {"exclude", 'X', 0, G_OPTION_ARG_NONE, &exclude_args,
757         N_("Do not output status information of TYPE"), N_("TYPE1,TYPE2,...")},
758 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
759     {"output", 'o', 0, G_OPTION_ARG_STRING, &savefile,
760         N_("Save xml representation of pipeline to FILE and exit"), N_("FILE")},
761 #endif
762     {"no-fault", 'f', 0, G_OPTION_ARG_NONE, &no_fault,
763         N_("Do not install a fault handler"), NULL},
764     {"no-sigusr-handler", '\0', 0, G_OPTION_ARG_NONE, &no_sigusr_handler,
765         N_("Do not install signal handlers for SIGUSR1 and SIGUSR2"), NULL},
766     {"trace", 'T', 0, G_OPTION_ARG_NONE, &trace,
767         N_("Print alloc trace (if enabled at compile time)"), NULL},
768     {"eos-on-shutdown", 'e', 0, G_OPTION_ARG_NONE, &eos_on_shutdown,
769         N_("Force EOS on sources before shutting the pipeline down"), NULL},
770     GST_TOOLS_GOPTION_VERSION,
771     {NULL}
772   };
773   GOptionContext *ctx;
774   GError *err = NULL;
775 #endif
776   gchar **argvn;
777   GError *error = NULL;
778   gint res = 0;
779
780   free (malloc (8));            /* -lefence */
781
782 #ifdef ENABLE_NLS
783   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
784   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
785   textdomain (GETTEXT_PACKAGE);
786 #endif
787
788   g_thread_init (NULL);
789
790   gst_tools_set_prgname ("gst-launch");
791
792 #ifndef GST_DISABLE_OPTION_PARSING
793   ctx = g_option_context_new ("PIPELINE-DESCRIPTION");
794   g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
795   g_option_context_add_group (ctx, gst_init_get_option_group ());
796   if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
797     if (err)
798       g_printerr ("Error initializing: %s\n", GST_STR_NULL (err->message));
799     else
800       g_printerr ("Error initializing: Unknown error!\n");
801     exit (1);
802   }
803   g_option_context_free (ctx);
804 #else
805   gst_init (&argc, &argv);
806 #endif
807
808   gst_tools_print_version ("gst-launch");
809
810 #ifndef DISABLE_FAULT_HANDLER
811   if (!no_fault)
812     fault_setup ();
813
814   sigint_setup ();
815
816   if (!no_sigusr_handler)
817     play_signal_setup ();
818 #endif
819
820   if (trace) {
821     if (!gst_alloc_trace_available ()) {
822       g_warning ("Trace not available (recompile with trace enabled).");
823     }
824     gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE |
825         GST_ALLOC_TRACE_MEM_LIVE);
826     gst_alloc_trace_print_live ();
827   }
828
829   /* make a null-terminated version of argv */
830   argvn = g_new0 (char *, argc);
831   memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
832 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
833   if (strstr (argv[0], "gst-xmllaunch")) {
834     /* FIXME 0.11: remove xmllaunch entirely */
835     g_warning ("gst-xmllaunch is deprecated and broken for all but the most "
836         "simple pipelines. It will most likely be removed in future. Don't "
837         "use it.\n");
838     pipeline = xmllaunch_parse_cmdline ((const gchar **) argvn);
839   } else
840 #endif
841   {
842     pipeline =
843         (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error);
844   }
845   g_free (argvn);
846
847   if (!pipeline) {
848     if (error) {
849       g_printerr (_("ERROR: pipeline could not be constructed: %s.\n"),
850           GST_STR_NULL (error->message));
851       g_error_free (error);
852     } else {
853       g_printerr (_("ERROR: pipeline could not be constructed.\n"));
854     }
855     return 1;
856   } else if (error) {
857     g_printerr (_("WARNING: erroneous pipeline: %s\n"),
858         GST_STR_NULL (error->message));
859     g_error_free (error);
860     return 1;
861   }
862
863   if (verbose) {
864     gchar **exclude_list =
865         exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL;
866     g_signal_connect (pipeline, "deep-notify",
867         G_CALLBACK (gst_object_default_deep_notify), exclude_list);
868   }
869 #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
870   if (savefile) {
871     g_warning ("Pipeline serialization to XML is deprecated and broken for "
872         "all but the most simple pipelines. It will most likely be removed "
873         "in future. Don't use it.\n");
874
875     gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
876   }
877 #endif
878
879   if (!savefile) {
880     GstState state, pending;
881     GstStateChangeReturn ret;
882     GstBus *bus;
883
884     /* If the top-level object is not a pipeline, place it in a pipeline. */
885     if (!GST_IS_PIPELINE (pipeline)) {
886       GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL);
887
888       if (real_pipeline == NULL) {
889         g_printerr (_("ERROR: the 'pipeline' element wasn't found.\n"));
890         return 1;
891       }
892       gst_bin_add (GST_BIN (real_pipeline), pipeline);
893       pipeline = real_pipeline;
894     }
895
896     bus = gst_element_get_bus (pipeline);
897     gst_bus_set_sync_handler (bus, bus_sync_handler, (gpointer) pipeline);
898     gst_object_unref (bus);
899
900     PRINT (_("Setting pipeline to PAUSED ...\n"));
901     ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);
902
903     switch (ret) {
904       case GST_STATE_CHANGE_FAILURE:
905         g_printerr (_("ERROR: Pipeline doesn't want to pause.\n"));
906         res = -1;
907         event_loop (pipeline, FALSE, GST_STATE_VOID_PENDING);
908         goto end;
909       case GST_STATE_CHANGE_NO_PREROLL:
910         PRINT (_("Pipeline is live and does not need PREROLL ...\n"));
911         is_live = TRUE;
912         break;
913       case GST_STATE_CHANGE_ASYNC:
914         PRINT (_("Pipeline is PREROLLING ...\n"));
915         caught_error = event_loop (pipeline, TRUE, GST_STATE_PAUSED);
916         if (caught_error) {
917           g_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
918           goto end;
919         }
920         state = GST_STATE_PAUSED;
921         /* fallthrough */
922       case GST_STATE_CHANGE_SUCCESS:
923         PRINT (_("Pipeline is PREROLLED ...\n"));
924         break;
925     }
926
927     caught_error = event_loop (pipeline, FALSE, GST_STATE_PLAYING);
928
929     if (caught_error) {
930       g_printerr (_("ERROR: pipeline doesn't want to preroll.\n"));
931     } else {
932       GstClockTime tfthen, tfnow;
933       GstClockTimeDiff diff;
934
935       PRINT (_("Setting pipeline to PLAYING ...\n"));
936
937       if (gst_element_set_state (pipeline,
938               GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
939         GstMessage *err_msg;
940         GstBus *bus;
941
942         g_printerr (_("ERROR: pipeline doesn't want to play.\n"));
943         bus = gst_element_get_bus (pipeline);
944         if ((err_msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0))) {
945           print_error_message (err_msg);
946           gst_message_unref (err_msg);
947         }
948         gst_object_unref (bus);
949         res = -1;
950         goto end;
951       }
952
953       tfthen = gst_util_get_timestamp ();
954       caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING);
955       if (eos_on_shutdown && caught_error == ELR_INTERRUPT) {
956         PRINT (_("EOS on shutdown enabled -- Forcing EOS on the pipeline\n"));
957         waiting_eos = TRUE;
958         gst_element_send_event (pipeline, gst_event_new_eos ());
959         PRINT (_("Waiting for EOS...\n"));
960         caught_error = event_loop (pipeline, TRUE, GST_STATE_PLAYING);
961
962         if (caught_error == ELR_NO_ERROR) {
963           /* we got EOS */
964           PRINT (_("EOS received - stopping pipeline...\n"));
965         } else if (caught_error == ELR_ERROR) {
966           PRINT (_("An error happened while waiting for EOS\n"));
967         }
968       }
969       tfnow = gst_util_get_timestamp ();
970
971       diff = GST_CLOCK_DIFF (tfthen, tfnow);
972
973       PRINT (_("Execution ended after %" G_GUINT64_FORMAT " ns.\n"), diff);
974     }
975
976     PRINT (_("Setting pipeline to PAUSED ...\n"));
977     gst_element_set_state (pipeline, GST_STATE_PAUSED);
978     if (caught_error == ELR_NO_ERROR)
979       gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
980
981     /* iterate mainloop to process pending stuff */
982     while (g_main_context_iteration (NULL, FALSE));
983
984     PRINT (_("Setting pipeline to READY ...\n"));
985     gst_element_set_state (pipeline, GST_STATE_READY);
986     gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
987
988   end:
989     PRINT (_("Setting pipeline to NULL ...\n"));
990     gst_element_set_state (pipeline, GST_STATE_NULL);
991     gst_element_get_state (pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
992   }
993
994   PRINT (_("Freeing pipeline ...\n"));
995   gst_object_unref (pipeline);
996
997   gst_deinit ();
998   if (trace)
999     gst_alloc_trace_print_live ();
1000
1001   return res;
1002 }