Convert %lld and %llu in printf formats to G_G[U]INT64_FORMAT. Fix pointer<->int...
[platform/upstream/gstreamer.git] / tools / gst-launch.c
1 #include <string.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <sys/wait.h>
5 #include <gst/gst.h>
6
7 static guint64 iterations = 0;
8 static guint64 sum = 0;
9 static guint64 min = G_MAXINT64;
10 static guint64 max = 0;
11 static GstClock *s_clock;
12
13 gboolean
14 idle_func (gpointer data)
15 {
16   gboolean busy;
17   GTimeVal tfthen, tfnow;
18   GstClockTimeDiff diff;
19
20   if (s_clock) {
21     //g_print ("%" G_GINT64_FORMAT "\n", gst_clock_get_time (s_clock));
22   }
23
24   g_get_current_time (&tfthen);
25   busy = gst_bin_iterate (GST_BIN (data));
26   iterations++;
27   g_get_current_time (&tfnow);
28
29   diff = GST_TIMEVAL_TO_TIME (tfnow) -
30          GST_TIMEVAL_TO_TIME (tfthen);
31
32   sum += diff; 
33   min = MIN (min, diff);
34   max = MAX (max, diff);
35
36   if (!busy) {
37     gst_main_quit ();
38     g_print ("execution ended after %" G_GUINT64_FORMAT " iterations (sum %" G_GUINT64_FORMAT " ns, average %" G_GUINT64_FORMAT " ns, min %" G_GUINT64_FORMAT " ns, max %" G_GUINT64_FORMAT " ns)\n", 
39                     iterations, sum, sum/iterations, min, max);
40   }
41
42   return busy;
43 }
44
45 static GstElement*
46 xmllaunch_parse_cmdline (const gchar **argv) 
47 {
48   GstElement *pipeline = NULL, *e;
49   GstXML *xml;
50   gboolean err;
51   const gchar *arg;
52   gchar *element, *property, *value;
53   GList *l;
54   gint i = 0;
55   
56   if (!(arg = argv[0])) {
57     g_print ("usage: gst-xmllaunch <file.xml> [ element.property=value ... ]\n");
58     exit (1);
59   }
60   
61   xml = gst_xml_new ();
62   err = gst_xml_parse_file(xml, arg, NULL);
63   
64   if (err != TRUE) {
65     fprintf (stderr, "ERROR: parse of xml file '%s' failed\n", arg);
66     exit (1);
67   }
68   
69   l = gst_xml_get_topelements (xml);
70   if (!l) {
71     fprintf (stderr, "ERROR: no toplevel pipeline element in file '%s'\n", arg);
72     exit (1);
73   }
74     
75   if (l->next)
76     g_warning ("only one toplevel element is supported at this time");
77   
78   pipeline = GST_ELEMENT (l->data);
79   
80   while ((arg = argv[++i])) {
81     element = g_strdup (arg);
82     property = strchr (element, '.');
83     value = strchr (element, '=');
84     
85     if (!(element < property && property < value)) {
86       fprintf (stderr, "ERROR: could not parse command line argument %d: %s", i, element);
87       g_free (element);
88       exit (1);
89     }
90     
91     *property++ = '\0';
92     *value++ = '\0';
93     
94     e = gst_bin_get_by_name (GST_BIN (pipeline), element);
95     if (!e) {
96       g_warning ("element named '%s' not found", element);
97     } else {
98       gst_util_set_object_arg (G_OBJECT (e), property, value);
99     }
100     g_free (element);
101   }
102   
103   if (!l)
104     return NULL;
105   else
106     return l->data;
107 }
108
109 extern volatile gboolean glib_on_error_halt;
110 static void fault_restore(void);
111
112 static void 
113 fault_handler (int signum, siginfo_t *si, void *misc)
114 {
115   int spinning = TRUE;
116
117   fault_restore ();
118
119   if (si->si_signo == SIGSEGV) {
120     g_print ("Caught SIGSEGV accessing address %p\n", si->si_addr);
121   }
122   else if (si->si_signo == SIGQUIT){
123     g_print ("Caught SIGQUIT\n");
124   }
125   else {
126     g_print ("signo:  %d\n", si->si_signo);
127     g_print ("errno:  %d\n", si->si_errno);
128     g_print ("code:   %d\n", si->si_code);
129   }
130
131   glib_on_error_halt = FALSE;
132   g_on_error_stack_trace ("gst-launch");
133
134   wait (NULL);
135
136 #if 1
137   /* FIXME how do we know if we were run by libtool? */
138   g_print ("Spinning.  Please run 'gdb gst-launch %d' to continue debugging, "
139            "Ctrl-C to quit, or Ctrl-\\ to dump core.\n",
140             getpid ());
141   while (spinning) usleep (1000000);
142 #else
143   /* This spawns a gdb and attaches it to gst-launch. */
144   {
145     char str[40];
146     sprintf (str, "gdb -quiet gst-launch %d", getpid ());
147     system (str);
148   }
149
150   _exit(0);
151 #endif
152
153 }
154
155 static void 
156 fault_restore (void)
157 {
158   struct sigaction action;
159
160   memset (&action, 0, sizeof (action));
161   action.sa_handler = SIG_DFL;
162
163   sigaction(SIGSEGV, &action, NULL);
164   sigaction(SIGQUIT, &action, NULL);
165 }
166
167 static void 
168 fault_setup (void)
169 {
170   struct sigaction action;
171
172   memset (&action, 0, sizeof (action));
173   action.sa_sigaction = fault_handler;
174   action.sa_flags = SA_SIGINFO;
175
176   sigaction (SIGSEGV, &action, NULL);
177   sigaction (SIGQUIT, &action, NULL);
178 }
179
180 int
181 main(int argc, char *argv[])
182 {
183   /* options */
184   gboolean silent = FALSE;
185   gboolean no_fault = FALSE;
186   gchar *savefile = NULL;
187   gchar *exclude_args = NULL;
188   struct poptOption options[] = {
189     {"silent",  's',  POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   &silent,   0,
190      "do not output status information", NULL},
191     {"exclude", 'X',  POPT_ARG_STRING|POPT_ARGFLAG_STRIP, &exclude_args,  0,
192      "do not output status information of TYPE", "TYPE1,TYPE2,..."},
193     {"output",  'o',  POPT_ARG_STRING|POPT_ARGFLAG_STRIP, &savefile, 0,
194      "save xml representation of pipeline to FILE and exit", "FILE"},
195     {"no_fault", 'f',  POPT_ARG_NONE|POPT_ARGFLAG_STRIP,   &no_fault,   0,
196      "Do not install a fault handler", NULL},
197     POPT_TABLEEND
198   };
199
200   GstElement *pipeline;
201   gchar **argvn;
202   GError *error = NULL;
203   gint res = 0;
204
205   free (malloc (8)); /* -lefence */
206
207   gst_init_with_popt_table (&argc, &argv, options);
208
209   if (!no_fault)
210     fault_setup();
211   
212   /* make a null-terminated version of argv */
213   argvn = g_new0 (char*, argc);
214   memcpy (argvn, argv+1, sizeof (char*) * (argc-1));
215   if (strstr (argv[0], "gst-xmllaunch")) {
216     pipeline = xmllaunch_parse_cmdline ((const gchar**)argvn);
217   } else {
218     pipeline = (GstElement*) gst_parse_launchv ((const gchar**)argvn, &error);
219   }
220   g_free (argvn);
221
222   if (!pipeline) {
223     if (error)
224       fprintf(stderr, "ERROR: pipeline could not be constructed: %s\n", error->message);
225     else
226       fprintf(stderr, "ERROR: pipeline could not be constructed\n");
227     exit(1);
228   }
229   
230   if (!silent)
231   {
232     gchar **exclude_list = exclude_args ? g_strsplit (exclude_args, ",", 0) : NULL;
233     g_signal_connect (pipeline, "deep_notify", G_CALLBACK (gst_element_default_deep_notify), exclude_list);
234   }
235   g_signal_connect (pipeline, "error", G_CALLBACK (gst_element_default_error), NULL);
236   
237 #ifndef GST_DISABLE_LOADSAVE
238   if (savefile) {
239     gst_xml_write_file (GST_ELEMENT (pipeline), fopen (savefile, "w"));
240   }
241 #endif
242   
243   if (!savefile) {
244     gst_buffer_print_stats();
245     gst_event_print_stats();
246
247     fprintf(stderr,"RUNNING pipeline\n");
248     if (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_FAILURE) {
249       fprintf(stderr,"pipeline doesn't want to play\n");
250       res = -1;
251       goto end;
252     }
253
254     s_clock = gst_bin_get_clock (GST_BIN (pipeline));
255
256     if (!GST_FLAG_IS_SET (GST_OBJECT (pipeline), GST_BIN_SELF_SCHEDULABLE)) {
257         g_idle_add (idle_func, pipeline);
258         gst_main ();
259     } else {
260         g_print ("waiting for the state change...\n");
261         gst_element_wait_state_change (pipeline);
262         g_print ("got the state change...\n");
263     }
264
265     gst_element_set_state (pipeline, GST_STATE_NULL);
266   }
267
268 end:
269   gst_buffer_print_stats();
270   gst_event_print_stats();
271
272   gst_object_unref (GST_OBJECT (pipeline));
273
274   return res;
275 }
276