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