Fix missing config.h and unistd.h includes which were apparently removed from gst...
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / v4l2_calls.c
1 /* G-Streamer generic V4L2 element - generic V4L2 calls handling
2  * Copyright (C) 2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include "v4l2_calls.h"
33
34 #define DEBUG(format, args...) \
35         GST_DEBUG_OBJECT (\
36                 GST_ELEMENT(v4l2element), \
37                 "V4L2: " format, ##args)
38
39
40 /******************************************************
41  * gst_v4l2_get_capabilities():
42  *   get the device's capturing capabilities
43  * return value: TRUE on success, FALSE on error
44  ******************************************************/
45
46 static gboolean
47 gst_v4l2_get_capabilities (GstV4l2Element *v4l2element)
48 {
49         DEBUG("getting capabilities");
50         GST_V4L2_CHECK_OPEN(v4l2element);
51
52         if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCAP, &(v4l2element->vcap)) < 0) {
53                 gst_element_error(GST_ELEMENT(v4l2element),
54                         "Error getting %s capabilities: %s",
55                         v4l2element->device, g_strerror(errno));
56                 return FALSE;
57         }
58
59         return TRUE;
60 }
61
62
63 /******************************************************
64  * gst_v4l2_empty_lists() and gst_v4l2_fill_lists():
65  *   fill/empty the lists of enumerations
66  * return value: TRUE on success, FALSE on error
67  ******************************************************/
68
69 static gboolean
70 gst_v4l2_fill_lists (GstV4l2Element *v4l2element)
71 {
72         gint n;
73
74         DEBUG("getting enumerations");
75         GST_V4L2_CHECK_OPEN(v4l2element);
76
77         /* and now, the inputs */
78         for (n=0;;n++) {
79                 struct v4l2_input input, *inpptr;
80                 input.index = n;
81                 if (ioctl(v4l2element->video_fd, VIDIOC_ENUMINPUT, &input) < 0) {
82                         if (errno == EINVAL)
83                                 break; /* end of enumeration */
84                         else {
85                                 gst_element_error(GST_ELEMENT(v4l2element),
86                                         "Failed to get no. %d in input enumeration for %s: %s",
87                                         n, v4l2element->device, g_strerror(errno));
88                                 return FALSE;
89                         }
90                 }
91                 inpptr = g_malloc(sizeof(input));
92                 memcpy(inpptr, &input, sizeof(input));
93                 v4l2element->inputs = g_list_append(v4l2element->inputs, inpptr);
94
95                 v4l2element->input_names = g_list_append(v4l2element->input_names, inpptr->name);
96         }
97
98         /* outputs */
99         for (n=0;;n++) {
100                 struct v4l2_output output, *outptr;
101                 output.index = n;
102                 if (ioctl(v4l2element->video_fd, VIDIOC_ENUMOUTPUT, &output) < 0) {
103                         if (errno == EINVAL)
104                                 break; /* end of enumeration */
105                         else {
106                                 gst_element_error(GST_ELEMENT(v4l2element),
107                                         "Failed to get no. %d in output enumeration for %s: %s",
108                                         n, v4l2element->device, g_strerror(errno));
109                                 return FALSE;
110                         }
111                 }
112                 outptr = g_malloc(sizeof(output));
113                 memcpy(outptr, &output, sizeof(output));
114                 v4l2element->outputs = g_list_append(v4l2element->outputs, outptr);
115
116                 v4l2element->output_names = g_list_append(v4l2element->output_names, outptr->name);
117         }
118
119         /* norms... */
120         for (n=0;;n++) {
121                 struct v4l2_standard standard, *stdptr;
122                 standard.index = n;
123                 if (ioctl(v4l2element->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
124                         if (errno == EINVAL)
125                                 break; /* end of enumeration */
126                         else {
127                                 gst_element_error(GST_ELEMENT(v4l2element),
128                                         "Failed to get no. %d in norm enumeration for %s: %s",
129                                         n, v4l2element->device, g_strerror(errno));
130                                 return FALSE;
131                         }
132                 }
133                 stdptr = g_malloc(sizeof(standard));
134                 memcpy(stdptr, &standard, sizeof(standard));
135                 v4l2element->norms = g_list_append(v4l2element->norms, stdptr);
136
137                 v4l2element->norm_names = g_list_append(v4l2element->norm_names, stdptr->name);
138         }
139
140         /* and lastly, controls+menus (if appropriate) */
141         for (n=V4L2_CID_BASE;;n++) {
142                 struct v4l2_queryctrl control, *ctrlptr;
143                 GList *menus = NULL;
144                 GParamSpec *spec = NULL;
145                 /* hacky... */
146                 if (n == V4L2_CID_LASTP1)
147                         n = V4L2_CID_PRIVATE_BASE;
148                 control.id = n;
149                 if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
150                         if (errno == EINVAL) {
151                                 if (n < V4L2_CID_PRIVATE_BASE)
152                                         continue;
153                                 else
154                                         break;
155                         } else {
156                                 gst_element_error(GST_ELEMENT(v4l2element),
157                                         "Failed to get no. %d in control enumeration for %s: %s",
158                                         n, v4l2element->device, g_strerror(errno));
159                                 return FALSE;
160                         }
161                 }
162                 if (control.flags & V4L2_CTRL_FLAG_DISABLED)
163                         continue;
164                 ctrlptr = g_malloc(sizeof(control));
165                 memcpy(ctrlptr, &control, sizeof(control));
166                 v4l2element->controls = g_list_append(v4l2element->controls, ctrlptr);
167                 if (control.type == V4L2_CTRL_TYPE_MENU) {
168                         struct v4l2_querymenu menu, *mptr;
169                         int i;
170                         menu.id = n;
171                         for (i=0;;i++) {
172                                 menu.index = i;
173                                 if (ioctl(v4l2element->video_fd, VIDIOC_QUERYMENU, &menu) < 0) {
174                                         if (errno == EINVAL)
175                                                 break; /* end of enumeration */
176                                         else {
177                                                 gst_element_error(GST_ELEMENT(v4l2element),
178                                                         "Failed to get no. %d in menu %d enumeration for %s: %s",
179                                                         i, n, v4l2element->device, g_strerror(errno));
180                                                 return FALSE;
181                                         }
182                                 }
183                                 mptr = g_malloc(sizeof(menu));
184                                 memcpy(mptr, &menu, sizeof(menu));
185                                 menus = g_list_append(menus, mptr);
186                         }
187                 }
188                 v4l2element->menus = g_list_append(v4l2element->menus, menus);
189
190                 switch (control.type) {
191                         case V4L2_CTRL_TYPE_INTEGER:
192                                 spec = g_param_spec_int(ctrlptr->name, ctrlptr->name,
193                                                         ctrlptr->name, ctrlptr->minimum, ctrlptr->maximum,
194                                                         ctrlptr->default_value, G_PARAM_READWRITE);
195                                 break;
196                         case V4L2_CTRL_TYPE_BOOLEAN:
197                                 spec = g_param_spec_boolean(ctrlptr->name, ctrlptr->name,
198                                                         ctrlptr->name, ctrlptr->default_value,
199                                                         G_PARAM_READWRITE);
200                                 break;
201                         case V4L2_CTRL_TYPE_MENU:
202                                 /* hacky... we abuse pointer for 'no value' */
203                                 spec = g_param_spec_pointer(ctrlptr->name, ctrlptr->name,
204                                                         ctrlptr->name, G_PARAM_WRITABLE);
205                                 break;
206                         case V4L2_CTRL_TYPE_BUTTON:
207                                 /* help?!? */
208                                 spec = NULL;
209                                 break;
210                 }
211
212                 v4l2element->control_specs = g_list_append(v4l2element->control_specs, spec);
213         }
214
215         return TRUE;
216 }
217
218
219 static void
220 gst_v4l2_empty_lists (GstV4l2Element *v4l2element)
221 {
222         DEBUG("deleting enumerations");
223
224         /* empty lists */
225         while (g_list_length(v4l2element->inputs) > 0) {
226                 gpointer data = g_list_nth_data(v4l2element->inputs, 0);
227                 v4l2element->inputs = g_list_remove(v4l2element->inputs, data);
228                 g_free(data);
229         }
230         g_list_free(v4l2element->input_names);
231         v4l2element->input_names = NULL;
232         while (g_list_length(v4l2element->outputs) > 0) {
233                 gpointer data = g_list_nth_data(v4l2element->outputs, 0);
234                 v4l2element->outputs = g_list_remove(v4l2element->outputs, data);
235                 g_free(data);
236         }
237         g_list_free(v4l2element->output_names);
238         v4l2element->output_names = NULL;
239         while (g_list_length(v4l2element->norms) > 0) {
240                 gpointer data = g_list_nth_data(v4l2element->norms, 0);
241                 v4l2element->norms = g_list_remove(v4l2element->norms, data);
242                 g_free(data);
243         }
244         g_list_free(v4l2element->norm_names);
245         v4l2element->norm_names = NULL;
246         while (g_list_length(v4l2element->controls) > 0) {
247                 gpointer data = g_list_nth_data(v4l2element->controls, 0);
248                 v4l2element->controls = g_list_remove(v4l2element->controls, data);
249                 g_free(data);
250         }
251         v4l2element->menus = g_list_remove_all(v4l2element->menus, NULL);
252         while (g_list_length(v4l2element->menus) > 0) {
253                 GList *items = (GList *) g_list_nth_data(v4l2element->menus, 0);
254                 v4l2element->inputs = g_list_remove(v4l2element->inputs, items);
255                 while (g_list_length(items) > 0) {
256                         gpointer data = g_list_nth_data(v4l2element->menus, 0);
257                         items = g_list_remove(items, data);
258                         g_free(data);
259                 }
260         }
261         while (g_list_length(v4l2element->control_specs) > 0) {
262                 gpointer data = g_list_nth_data(v4l2element->control_specs, 0);
263                 v4l2element->control_specs = g_list_remove(v4l2element->control_specs, data);
264                 g_param_spec_unref(G_PARAM_SPEC(data));
265         }
266 }
267
268
269 /******************************************************
270  * gst_v4l2_open():
271  *   open the video device (v4l2element->device)
272  * return value: TRUE on success, FALSE on error
273  ******************************************************/
274
275 gboolean
276 gst_v4l2_open (GstV4l2Element *v4l2element)
277 {
278         DEBUG("Trying to open device %s", v4l2element->device);
279         GST_V4L2_CHECK_NOT_OPEN(v4l2element);
280         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
281
282         /* be sure we have a device */
283         if (!v4l2element->device)
284                 v4l2element->device = g_strdup("/dev/video");
285
286         /* open the device */
287         v4l2element->video_fd = open(v4l2element->device, O_RDWR);
288         if (!GST_V4L2_IS_OPEN(v4l2element)) {
289                 gst_element_error(GST_ELEMENT(v4l2element),
290                         "Failed to open device %s: %s",
291                         v4l2element->device, g_strerror(errno));
292                 goto error;
293         }
294
295         /* get capabilities */
296         if (!gst_v4l2_get_capabilities(v4l2element)) {
297                 goto error;
298         }
299
300         /* create enumerations */
301         if (!gst_v4l2_fill_lists(v4l2element))
302                 goto error;
303
304         gst_info("Opened device '%s' (%s) successfully\n",
305                 v4l2element->vcap.card, v4l2element->device);
306
307         return TRUE;
308
309 error:
310         if (GST_V4L2_IS_OPEN(v4l2element)) {
311                 /* close device */
312                 close(v4l2element->video_fd);
313                 v4l2element->video_fd = -1;
314         }
315         /* empty lists */
316         gst_v4l2_empty_lists(v4l2element);
317
318         return FALSE;
319 }
320
321
322 /******************************************************
323  * gst_v4l2_close():
324  *   close the video device (v4l2element->video_fd)
325  * return value: TRUE on success, FALSE on error
326  ******************************************************/
327
328 gboolean
329 gst_v4l2_close (GstV4l2Element *v4l2element)
330 {
331         DEBUG("Trying to close %s", v4l2element->device);
332         GST_V4L2_CHECK_OPEN(v4l2element);
333         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
334
335         /* close device */
336         close(v4l2element->video_fd);
337         v4l2element->video_fd = -1;
338
339         /* empty lists */
340         gst_v4l2_empty_lists(v4l2element);
341
342         return TRUE;
343 }
344
345
346 /******************************************************
347  * gst_v4l2_get_norm()
348  *   Get the norm of the current device
349  * return value: TRUE on success, FALSE on error
350  ******************************************************/
351
352 gboolean
353 gst_v4l2_get_norm (GstV4l2Element *v4l2element,
354                    gint           *norm)
355 {
356         v4l2_std_id std_id;
357         gint n;
358
359         DEBUG("getting norm");
360         GST_V4L2_CHECK_OPEN(v4l2element);
361
362         if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, &std_id) < 0) {
363                 gst_element_error(GST_ELEMENT(v4l2element),
364                         "Failed to get the current norm for device %s: %s",
365                         v4l2element->device, g_strerror(errno));
366                 return FALSE;
367         }
368
369         /* try to find out what norm number this actually is */
370         for (n=0;n<g_list_length(v4l2element->norms);n++) {
371                 struct v4l2_standard *stdptr = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n);
372                 if (stdptr->id == std_id) {
373                         *norm = n;
374                         return TRUE;
375                 }
376         }
377
378         gst_element_error(GST_ELEMENT(v4l2element),
379                 "Failed to find norm '%llu' in our list of available norms for device %s",
380                 std_id, v4l2element->device);
381         return FALSE;
382 }
383
384
385 /******************************************************
386  * gst_v4l2_set_norm()
387  *   Set the norm of the current device
388  * return value: TRUE on success, FALSE on error
389  ******************************************************/
390
391 gboolean
392 gst_v4l2_set_norm (GstV4l2Element *v4l2element,
393                    gint            norm)
394 {
395         struct v4l2_standard *standard;
396
397         DEBUG("trying to set norm to %d", norm);
398         GST_V4L2_CHECK_OPEN(v4l2element);
399         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
400
401         if (norm < 0 || norm >= g_list_length(v4l2element->norms)) {
402                 gst_element_error(GST_ELEMENT(v4l2element),
403                         "Invalid norm number %d (%d-%d)",
404                         norm, 0, g_list_length(v4l2element->norms));
405                 return FALSE;
406         }
407
408         standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, norm);
409
410         if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &standard->id) < 0) {
411                 gst_element_error(GST_ELEMENT(v4l2element),
412                         "Failed to set norm '%s' (%llu) for device %s: %s",
413                         standard->name, standard->id, v4l2element->device, g_strerror(errno));
414                 return FALSE;
415         }
416
417         return TRUE;
418 }
419
420
421 /******************************************************
422  * gst_v4l2_get_input()
423  *   Get the input of the current device
424  * return value: TRUE on success, FALSE on error
425  ******************************************************/
426
427 gboolean
428 gst_v4l2_get_input (GstV4l2Element *v4l2element,
429                     gint           *input)
430 {
431         gint n;
432
433         DEBUG("trying to get input");
434         GST_V4L2_CHECK_OPEN(v4l2element);
435
436         if (ioctl(v4l2element->video_fd, VIDIOC_G_INPUT, &n) < 0) {
437                 gst_element_error(GST_ELEMENT(v4l2element),
438                         "Failed to get current input on device %s: %s",
439                         v4l2element->device, g_strerror(errno));
440                 return FALSE;
441         }
442
443         *input = n;
444
445         return TRUE;
446 }
447
448
449 /******************************************************
450  * gst_v4l2_set_input()
451  *   Set the input of the current device
452  * return value: TRUE on success, FALSE on error
453  ******************************************************/
454
455 gboolean
456 gst_v4l2_set_input (GstV4l2Element *v4l2element,
457                     gint            input)
458 {
459         DEBUG("trying to set input to %d", input);
460         GST_V4L2_CHECK_OPEN(v4l2element);
461         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
462
463         if (input < 0 || input >= g_list_length(v4l2element->inputs)) {
464                 gst_element_error(GST_ELEMENT(v4l2element),
465                         "Invalid input number %d (%d-%d)",
466                         input, 0, g_list_length(v4l2element->inputs));
467                 return FALSE;
468         }
469
470         if (ioctl(v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) {
471                 gst_element_error(GST_ELEMENT(v4l2element),
472                         "Failed to set input %d on device %s: %s",
473                         input, v4l2element->device, g_strerror(errno));
474                 return FALSE;
475         }
476
477         return TRUE;
478 }
479
480
481 /******************************************************
482  * gst_v4l2_get_output()
483  *   Get the output of the current device
484  * return value: TRUE on success, FALSE on error
485  ******************************************************/
486
487 gboolean
488 gst_v4l2_get_output (GstV4l2Element *v4l2element,
489                      gint           *output)
490 {
491         gint n;
492
493         DEBUG("trying to get output");
494         GST_V4L2_CHECK_OPEN(v4l2element);
495
496         if (ioctl(v4l2element->video_fd, VIDIOC_G_OUTPUT, &n) < 0) {
497                 gst_element_error(GST_ELEMENT(v4l2element),
498                         "Failed to get current output on device %s: %s",
499                         v4l2element->device, g_strerror(errno));
500                 return FALSE;
501         }
502
503         *output = n;
504
505         return TRUE;
506 }
507
508
509 /******************************************************
510  * gst_v4l2_set_output()
511  *   Set the output of the current device
512  * return value: TRUE on success, FALSE on error
513  ******************************************************/
514
515 gboolean
516 gst_v4l2_set_output (GstV4l2Element *v4l2element,
517                      gint            output)
518 {
519         DEBUG("trying to set output to %d", output);
520         GST_V4L2_CHECK_OPEN(v4l2element);
521         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
522
523         if (output < 0 || output >= g_list_length(v4l2element->outputs)) {
524                 gst_element_error(GST_ELEMENT(v4l2element),
525                         "Invalid output number %d (%d-%d)",
526                         output, 0, g_list_length(v4l2element->outputs));
527                 return FALSE;
528         }
529
530         if (ioctl(v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) {
531                 gst_element_error(GST_ELEMENT(v4l2element),
532                         "Failed to set output %d on device %s: %s",
533                         output, v4l2element->device, g_strerror(errno));
534                 return FALSE;
535         }
536
537         return TRUE;
538 }
539
540
541 /******************************************************
542  * gst_v4l2_has_tuner():
543  *   Check whether the device has a tuner
544  * return value: TRUE if it has a tuner, else FALSE
545  ******************************************************/
546
547 gint
548 gst_v4l2_has_tuner (GstV4l2Element *v4l2element,
549                     gint           *tuner_num)
550 {
551         gint input_num;
552         struct v4l2_input *input;
553
554         DEBUG("detecting whether device has a tuner");
555         GST_V4L2_CHECK_OPEN(v4l2element);
556
557         if (!gst_v4l2_get_input(v4l2element, &input_num))
558                 return FALSE;
559
560         input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
561
562         if (input->type == V4L2_INPUT_TYPE_TUNER &&
563             v4l2element->vcap.capabilities & V4L2_CAP_TUNER) {
564                 *tuner_num = input->tuner;
565                 return TRUE;
566         }
567         return FALSE;
568 }
569
570
571 /******************************************************
572  * gst_v4l2_get_frequency():
573  *   get the current frequency
574  * return value: TRUE on success, FALSE on error
575  ******************************************************/
576
577 gboolean
578 gst_v4l2_get_frequency (GstV4l2Element *v4l2element,
579                         gulong         *frequency)
580 {
581         struct v4l2_frequency freq;
582
583         DEBUG("getting current tuner frequency");
584         GST_V4L2_CHECK_OPEN(v4l2element);
585
586         if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner))
587                 return FALSE;
588
589         freq.type = 0;
590
591         if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
592                 gst_element_error(GST_ELEMENT(v4l2element),
593                         "Failed to get current tuner frequency for device %s: %s",
594                         v4l2element->device, g_strerror(errno));
595                 return FALSE;
596         }
597
598         *frequency = freq.frequency;
599
600         return TRUE;
601 }
602
603
604 /******************************************************
605  * gst_v4l2_set_frequency():
606  *   set frequency
607  * return value: TRUE on success, FALSE on error
608  ******************************************************/
609
610 gboolean
611 gst_v4l2_set_frequency (GstV4l2Element *v4l2element,
612                         gulong          frequency)
613 {
614         struct v4l2_frequency freq;
615
616         DEBUG("setting current tuner frequency to %lu", frequency);
617         GST_V4L2_CHECK_OPEN(v4l2element);
618         GST_V4L2_CHECK_NOT_ACTIVE(v4l2element);
619
620         if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner))
621                 return FALSE;
622
623         freq.frequency = frequency;
624         freq.type = 0;
625
626         if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) {
627                 gst_element_error(GST_ELEMENT(v4l2element),
628                         "Failed to set tuner frequency to %lu for device %s: %s",
629                         frequency, v4l2element->device, g_strerror(errno));
630                 return FALSE;
631         }
632
633         return TRUE;
634 }
635
636
637 /******************************************************
638  * gst_v4l2_signal_strength():
639  *   get the strength of the signal on the current input
640  * return value: TRUE on success, FALSE on error
641  ******************************************************/
642
643 gboolean
644 gst_v4l2_signal_strength (GstV4l2Element *v4l2element,
645                           gulong         *signal_strength)
646 {
647         struct v4l2_tuner tuner;
648
649         DEBUG("trying to get signal strength");
650         GST_V4L2_CHECK_OPEN(v4l2element);
651
652         if (ioctl(v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) {
653                 gst_element_error(GST_ELEMENT(v4l2element),
654                         "Failed to get signal strength for device %s: %s",
655                         v4l2element->device, g_strerror(errno));
656                 return FALSE;
657         }
658
659         *signal_strength = tuner.signal;
660
661         return TRUE;
662 }
663
664
665 /******************************************************
666  * gst_v4l2_has_audio():
667  *   Check whether the device has audio capabilities
668  * return value: TRUE if it has a tuner, else FALSE
669  ******************************************************/
670
671 gboolean
672 gst_v4l2_has_audio (GstV4l2Element *v4l2element)
673 {
674         gint input_num;
675         struct v4l2_input *input;
676
677         DEBUG("detecting whether device has audio");
678         GST_V4L2_CHECK_OPEN(v4l2element);
679
680         if (!gst_v4l2_get_input(v4l2element, &input_num))
681                 return FALSE;
682
683         input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num);
684
685         return (input->audioset != 0);
686 }
687
688
689 /******************************************************
690  * gst_v4l2_control_name_to_num():
691  *   convert name to num (-1 if nothing)
692  ******************************************************/
693
694 static gint
695 gst_v4l2_control_name_to_num (GstV4l2Element *v4l2element,
696                               const gchar    *name)
697 {
698         GList *item;
699
700         for (item = v4l2element->controls; item != NULL; item = item->next) {
701                 struct v4l2_queryctrl *ctrl = item->data;
702                 if (!strcmp(ctrl->name, name))
703                         return ctrl->id;
704         }
705
706         return -1;
707 }
708
709
710 /******************************************************
711  * gst_v4l2_get_attribute():
712  *   try to get the value of one specific attribute
713  * return value: TRUE on success, FALSE on error
714  ******************************************************/
715
716 gboolean
717 gst_v4l2_get_attribute  (GstElement  *element,
718                          const gchar *name,
719                          int         *value)
720 {
721         struct v4l2_control control;
722         GstV4l2Element *v4l2element;
723         gint attribute_num = -1;
724
725         g_return_val_if_fail(element != NULL && name != NULL && value != NULL, FALSE);
726         g_return_val_if_fail(GST_IS_V4L2ELEMENT(element), FALSE);
727         v4l2element = GST_V4L2ELEMENT(element);
728
729         DEBUG("getting value of attribute %d", attribute_num);
730         GST_V4L2_CHECK_OPEN(v4l2element);
731
732         attribute_num = gst_v4l2_control_name_to_num(v4l2element, name);
733
734         if (attribute_num < 0) {
735                 gst_element_error(GST_ELEMENT(v4l2element),
736                         "Invalid control %s", name);
737                 return FALSE;
738         }
739
740         control.id = attribute_num;
741
742         if (ioctl(v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) {
743                 gst_element_error(GST_ELEMENT(v4l2element),
744                         "Failed to get value for control %s (%d) on device %s: %s",
745                         name, attribute_num, v4l2element->device, g_strerror(errno));
746                 return FALSE;
747         }
748
749         *value = control.value;
750
751         return TRUE;
752 }
753
754
755 /******************************************************
756  * gst_v4l2_set_attribute():
757  *   try to set the value of one specific attribute
758  * return value: TRUE on success, FALSE on error
759  ******************************************************/
760
761 gboolean
762 gst_v4l2_set_attribute  (GstElement  *element,
763                          const gchar *name,
764                          const int    value)
765 {
766         struct v4l2_control control;
767         GstV4l2Element *v4l2element;
768         gint attribute_num = -1;
769
770         g_return_val_if_fail(element != NULL && name != NULL, FALSE);
771         g_return_val_if_fail(GST_IS_V4L2ELEMENT(element), FALSE);
772         v4l2element = GST_V4L2ELEMENT(element);
773
774         DEBUG("setting value of attribute %d to %d", attribute_num, value);
775         GST_V4L2_CHECK_OPEN(v4l2element);
776
777         attribute_num = gst_v4l2_control_name_to_num(v4l2element, name);
778
779         if (attribute_num < 0) {
780                 gst_element_error(GST_ELEMENT(v4l2element),
781                         "Invalid control %s", name);
782                 return FALSE;
783         }
784
785         control.id = attribute_num;
786         control.value = value;
787
788         if (ioctl(v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) {
789                 gst_element_error(GST_ELEMENT(v4l2element),
790                         "Failed to set value %d for control %s (%d) on device %s: %s",
791                         value, name, attribute_num, v4l2element->device, g_strerror(errno));
792                 return FALSE;
793         }
794
795         return TRUE;
796 }
797