The test application and the plgind error messages has been improved.
[platform/upstream/gst-plugins-good.git] / tests / icles / v4l2src-test.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <getopt.h>
4
5 #include <gst/gst.h>
6 #include <gst/interfaces/tuner.h>
7 #include <gst/interfaces/colorbalance.h>
8
9 GstElement *pipeline, *source, *sink;
10 GMainLoop *loop;
11 volatile int exit_read = 0;
12
13 void
14 print_options ()
15 {
16   printf ("\nf - to change the fequency\n");
17   printf ("i - to change the input\n");
18   printf ("n - to change the norm\n");
19   printf ("c - list color balance\n");
20   printf ("e - to exit\n");
21 }
22
23 void
24 run_options (char opt)
25 {
26   switch (opt) {
27     case 'f':
28     {
29       GstTuner *tuner = GST_TUNER (source);
30       GstTunerChannel *channel;
31       guint freq;
32
33       channel = gst_tuner_get_channel (tuner);
34
35       freq = gst_tuner_get_frequency (tuner, channel);
36
37       printf ("type the new frequency (current = %lu) (-1 to cancel): ", freq);
38       scanf ("%u", &freq);
39       if (freq != -1)
40         gst_tuner_set_frequency (tuner, channel, freq);
41     }
42       break;
43     case 'n':
44     {
45       GstTuner *tuner = GST_TUNER (source);
46       const GList *item, *list;
47       const GstTunerNorm *current_norm;
48       GstTunerNorm *norm = NULL;
49       gint index, next_norm;
50
51
52       list = gst_tuner_list_norms (tuner);
53
54       current_norm = gst_tuner_get_norm (tuner);
55
56       printf ("\nlist of norms:\n");
57       for (item = list, index = 0; item != NULL; item = item->next, ++index) {
58         norm = item->data;
59         if (current_norm == norm) {
60           printf (" * %u - %s\n", index, norm->label);
61         } else {
62           printf ("   %u - %s\n", index, norm->label);
63         }
64       }
65       printf ("\ntype the number of norm you want (-1 to cancel): ");
66       scanf ("%d", &next_norm);
67       if (next_norm < 0) {
68         break;
69       }
70       if (index <= next_norm) {
71         printf ("Norm %d not available\n", next_norm);
72         break;
73       }
74       for (item = list, index = 0; item != NULL && index <= next_norm;
75           item = item->next, ++index) {
76         norm = item->data;
77       }
78       if (norm)
79         gst_tuner_set_norm (tuner, norm);
80     }
81       break;
82     case 'i':
83     {
84       GstTuner *tuner = GST_TUNER (source);
85       const GList *item, *list;
86       const GstTunerChannel *current_channel;
87       GstTunerChannel *channel = NULL;
88       gint index, next_channel;
89
90
91       list = gst_tuner_list_channels (tuner);
92
93       current_channel = gst_tuner_get_channel (tuner);
94
95       printf ("\nlist of inputs:\n");
96       for (item = list, index = 0; item != NULL; item = item->next, ++index) {
97         channel = item->data;
98         if (current_channel == channel) {
99           printf (" * %u - %s\n", index, channel->label);
100         } else {
101           printf ("   %u - %s\n", index, channel->label);
102         }
103       }
104       printf ("\ntype the number of input you want (-1 to cancel): ");
105       scanf ("%d", &next_channel);
106       if (next_channel < 0) {
107         break;
108       }
109       if (index <= next_channel) {
110         printf ("Input %d not available\n", next_channel);
111         break;
112       }
113       for (item = list, index = 0; item != NULL && index <= next_channel;
114           item = item->next, ++index) {
115         channel = item->data;
116       }
117       if (channel)
118         gst_tuner_set_channel (tuner, channel);
119     }
120       break;
121     case 'e':
122       gst_element_set_state (pipeline, GST_STATE_NULL);
123       g_main_loop_quit (loop);
124       printf ("Bye\n");
125       g_thread_exit (0);
126       break;
127     case 'c':
128     {
129       GstColorBalance *balance = GST_COLOR_BALANCE (source);
130       const GList *controls;
131       GstColorBalanceChannel *channel;
132       const GList *item;
133       gint index, new_value;
134
135       controls = gst_color_balance_list_channels (balance);
136
137       if (controls == NULL) {
138         printf ("There is no list of colorbalance controls\n");
139         goto done;
140       }
141
142       if (controls) {
143         printf ("\nlist of controls:\n");
144         for (item = controls, index = 0; item != NULL;
145             item = item->next, ++index) {
146           channel = item->data;
147           printf ("   %u - %s (%d - %d) = %d\n", index, channel->label,
148               channel->min_value, channel->max_value,
149               gst_color_balance_get_value (balance, channel));
150         }
151         printf ("\ntype the number of color control you want (-1 to cancel): ");
152         scanf ("%d", &new_value);
153         if (new_value == -1)
154           break;
155         for (item = controls, index = 0; item != NULL && index <= new_value;
156             item = item->next, ++index) {
157           channel = item->data;
158         }
159         printf ("   %u - %s (%d - %d) = %d, type the new value: ", index - 1,
160             channel->label, channel->min_value, channel->max_value,
161             gst_color_balance_get_value (balance, channel));
162         scanf ("%d", &new_value);
163         if (new_value == -1)
164           break;
165         gst_color_balance_set_value (balance, channel, new_value);
166       }
167     }
168       break;
169     default:
170       if (opt != 10)
171         printf ("error: invalid option %c", opt);
172       break;
173   }
174
175 done:
176
177   return;
178
179 }
180
181 gpointer
182 read_user (gpointer data)
183 {
184
185   char opt;
186
187   while (!exit_read) {
188
189     print_options ();
190
191     do {
192       opt = getchar ();
193       if (exit_read) {
194         break;
195       }
196     } while (opt == '\n');
197
198     run_options (opt);
199
200   }
201
202   return NULL;
203
204 }
205
206 static gboolean
207 my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
208 {
209
210   switch (GST_MESSAGE_TYPE (message)) {
211     case GST_MESSAGE_ERROR:{
212       GError *err;
213       gchar *debug;
214
215       gst_message_parse_error (message, &err, &debug);
216       g_print ("%s error: %s\n",
217           gst_element_get_name (message->src), err->message);
218       g_print ("Debug: %s\n", debug);
219
220       g_error_free (err);
221       g_free (debug);
222
223       printf ("presse <ENTER> key to exit\n");
224       exit_read = 1;
225       g_main_loop_quit (loop);
226       break;
227     case GST_MESSAGE_EOS:
228       /* end-of-stream */
229       printf ("presse any key to exit\n");
230       exit_read = 1;
231       g_main_loop_quit (loop);
232       break;
233     default:
234       break;
235     }
236   }
237   return TRUE;
238 }
239
240 int
241 main (int argc, char *argv[])
242 {
243
244   GThread *input_thread;
245   gint numbuffers = -1;
246   gchar device[128] = { '\0' };
247   gchar input[128] = { '\0' };
248   gulong frequency = 0;
249   gboolean nofixedfps = TRUE;
250
251
252   /* see for input option */
253
254   int c;
255
256   while (1) {
257     static char long_options_desc[][64] = {
258       {"Number of buffers to output before sending EOS"},
259       {"Device location. Common in /dev/video0"},
260       {"input/output (channel) to switch to"},
261       {"frequency to tune to (in Hz)"},
262       {"set use-fixed-fps to FALSE"},
263       {0, 0, 0, 0}
264     };
265     static struct option long_options[] = {
266       {"numbuffers", 1, 0, 'n'},
267       {"device", 1, 0, 'd'},
268       {"input", 1, 0, 'i'},
269       {"frequency", 1, 0, 'f'},
270       {"nofixedfps", 0, 0, 's'},
271       {0, 0, 0, 0}
272     };
273     /* getopt_long stores the option index here. */
274     int option_index = 0;
275
276     c = getopt_long (argc, argv, "n:d:i:f:sh:", long_options, &option_index);
277
278     /* Detect the end of the options. */
279     if (c == -1) {
280       printf ("tip: use -h to see help message.\n");
281       break;
282     }
283
284     switch (c) {
285       case 0:
286         /* If this option set a flag, do nothing else now. */
287         if (long_options[option_index].flag != 0)
288           break;
289         printf ("option %s", long_options[option_index].name);
290         if (optarg)
291           printf (" with arg %s", optarg);
292         printf ("\n");
293         break;
294
295       case 'n':
296         numbuffers = atoi (optarg);
297         break;
298
299       case 'd':
300         strncpy (device, optarg, sizeof (device) / sizeof (device[0]));
301         break;
302
303       case 'i':
304         strncpy (input, optarg, sizeof (input) / sizeof (input[0]));
305         break;
306
307       case 'f':
308         frequency = atol (optarg);
309         break;
310
311       case 's':
312         nofixedfps = FALSE;
313         break;
314
315       case 'h':
316         printf ("Usage: v4l2src-test [OPTION]...\n");
317         for (c = 0; long_options[c].name; ++c) {
318           printf ("-%c, --%s\r\t\t\t\t%s\n", long_options[c].val,
319               long_options[c].name, long_options_desc[c]);
320         }
321         exit (0);
322         break;
323
324       case '?':
325         /* getopt_long already printed an error message. */
326         printf ("Use -h to see help message.\n");
327         break;
328
329       default:
330         abort ();
331     }
332   }
333
334
335   /* Print any remaining command line arguments (not options). */
336   if (optind < argc) {
337     printf ("Use -h to see help message.\n" "non-option ARGV-elements: ");
338     while (optind < argc)
339       printf ("%s ", argv[optind++]);
340     putchar ('\n');
341   }
342
343
344
345   /* init */
346   gst_init (&argc, &argv);
347
348   /* create elements */
349   if (!(pipeline = gst_pipeline_new ("my_pipeline"))) {
350     fprintf (stderr, "error: gst_pipeline_new return NULL");
351     return -1;
352   }
353
354   if (!(source = gst_element_factory_make ("v4l2src", NULL))) {
355     fprintf (stderr,
356         "error: gst_element_factory_make (\"v4l2src\", NULL) return NULL");
357     return -1;
358   }
359
360   if (!(sink = gst_element_factory_make ("xvimagesink", NULL))) {
361     fprintf (stderr,
362         "error: gst_element_factory_make (\"xvimagesink\", NULL) return NULL");
363     return -1;
364   }
365
366   if (numbuffers > -1) {
367     g_object_set (source, "num-buffers", numbuffers, NULL);
368   }
369   if (device[0]) {
370     g_object_set (source, "device", device, NULL);
371   }
372   if (input[0]) {
373     g_object_set (source, "input", input, NULL);
374   }
375   if (frequency) {
376     g_object_set (source, "frequency", frequency, NULL);
377   }
378   if (!nofixedfps) {
379     g_object_set (source, "use-fixed-fps", nofixedfps, NULL);
380   }
381
382   /* you would normally check that the elements were created properly */
383   gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (pipeline)),
384       my_bus_callback, NULL);
385
386   /* put together a pipeline */
387   gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
388   gst_element_link_pads (source, "src", sink, "sink");
389
390   /* start the pipeline */
391   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
392   loop = g_main_loop_new (NULL, FALSE);
393
394   if (!(input_thread = g_thread_create (read_user, source, TRUE, NULL))) {
395     fprintf (stderr, "error: g_thread_create return NULL");
396     return -1;
397   }
398
399   g_main_loop_run (loop);
400   g_thread_join (input_thread);
401
402   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
403
404   gst_object_unref (pipeline);
405
406   gst_deinit ();
407
408   return 0;
409
410 }