po/: Translation string updates
[platform/upstream/gstreamer.git] / sys / v4l / v4l_calls.c
1 /* GStreamer
2  *
3  * v4l_calls.c: generic V4L calls
4  *
5  * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <sys/ioctl.h>
31 #include <sys/mman.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <unistd.h>
35
36 #include <gst/gst.h>
37 #include <gst/interfaces/tuner.h>
38 #include <gst/interfaces/colorbalance.h>
39
40 #include "v4l_calls.h"
41 #include "gstv4ltuner.h"
42 #include "gstv4lcolorbalance.h"
43
44 #include "gstv4lsrc.h"
45 /* #include "gstv4lmjpegsrc.h" */
46 /* #include "gstv4lmjpegsink.h" */
47
48 GST_DEBUG_CATEGORY_EXTERN (v4l_debug);
49 #define GST_CAT_DEFAULT v4l_debug
50
51 static const char *picture_name[] = {
52   "Hue",
53   "Brightness",
54   "Contrast",
55   "Saturation",
56   NULL
57 };
58
59 G_GNUC_UNUSED static const char *audio_name[] = {
60   "Volume",
61   "Mute",
62   "Mode",
63   NULL
64 };
65
66 static const char *norm_name[] = {
67   "PAL",
68   "NTSC",
69   "SECAM",
70   NULL
71 };
72
73 /******************************************************
74  * gst_v4l_get_capabilities():
75  *   get the device's capturing capabilities
76  * sets v4lelement->vcap and v4lelement->vwin
77  * return value: TRUE on success, FALSE on error
78  ******************************************************/
79
80 gboolean
81 gst_v4l_get_capabilities (GstV4lElement * v4lelement)
82 {
83   GST_DEBUG_OBJECT (v4lelement, "getting capabilities");
84   GST_V4L_CHECK_OPEN (v4lelement);
85
86   if (ioctl (v4lelement->video_fd, VIDIOCGCAP, &(v4lelement->vcap)) < 0) {
87     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
88         ("error getting capabilities %s of from device %s",
89             g_strerror (errno), v4lelement->videodev));
90     return FALSE;
91   }
92
93   if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(v4lelement->vwin)) < 0) {
94     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
95         ("error getting window properties %s of from device %s",
96             g_strerror (errno), v4lelement->videodev));
97     return FALSE;
98   }
99
100   return TRUE;
101 }
102
103 /******************************************************
104  * gst_v4l_set_window_properties():
105  *   set the device's capturing parameters (vwin)
106  * return value: TRUE on success, FALSE on error
107  ******************************************************/
108
109 gboolean
110 gst_v4l_set_window_properties (GstV4lElement * v4lelement)
111 {
112   struct video_window vwin;
113
114   GST_DEBUG_OBJECT (v4lelement, "setting window flags 0x%x to device %s",
115       v4lelement->vwin.flags, v4lelement->videodev);
116   GST_V4L_CHECK_OPEN (v4lelement);
117
118   if (ioctl (v4lelement->video_fd, VIDIOCSWIN, &(v4lelement->vwin)) < 0) {
119     GST_DEBUG_OBJECT (v4lelement,
120         "could not ioctl window properties 0x%x to device %s",
121         v4lelement->vwin.flags, v4lelement->videodev);
122     return FALSE;
123   }
124
125   /* get it again to make sure we have it correctly */
126   if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(vwin)) < 0) {
127     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
128         ("error getting window properties %s of from device %s",
129             g_strerror (errno), v4lelement->videodev));
130     return FALSE;
131   }
132   if (vwin.flags != v4lelement->vwin.flags) {
133     GST_DEBUG_OBJECT (v4lelement, "set 0x%x but got 0x%x back",
134         v4lelement->vwin.flags, vwin.flags);
135     return FALSE;
136   }
137
138   return TRUE;
139 }
140
141 /******************************************************
142  * gst_v4l_open():
143  *   open the video device (v4lelement->videodev)
144  * return value: TRUE on success, FALSE on error
145  ******************************************************/
146
147 gboolean
148 gst_v4l_open (GstV4lElement * v4lelement)
149 {
150   int num;
151
152   GST_DEBUG_OBJECT (v4lelement, "opening device %s", v4lelement->videodev);
153   GST_V4L_CHECK_NOT_OPEN (v4lelement);
154   GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
155
156   /* be sure we have a device */
157   if (!v4lelement->videodev) {
158     GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND,
159         (_("No device specified.")), (NULL));
160     return FALSE;
161   }
162
163   /* open the device */
164   v4lelement->video_fd = open (v4lelement->videodev, O_RDWR);
165   if (!GST_V4L_IS_OPEN (v4lelement)) {
166     if (errno == ENODEV || errno == ENOENT) {
167       GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND,
168           (_("Device \"%s\" does not exist."), v4lelement->videodev), (NULL));
169       return FALSE;
170     }
171     GST_ELEMENT_ERROR (v4lelement, RESOURCE, OPEN_READ_WRITE,
172         (_("Could not open device \"%s\" for reading and writing."),
173             v4lelement->videodev), GST_ERROR_SYSTEM);
174     return FALSE;
175   }
176
177   /* get capabilities */
178   if (!gst_v4l_get_capabilities (v4lelement)) {
179     close (v4lelement->video_fd);
180     v4lelement->video_fd = -1;
181     return FALSE;
182   }
183
184   /* device type check */
185   if ((GST_IS_V4LSRC (v4lelement) &&
186           !(v4lelement->vcap.type & VID_TYPE_CAPTURE))) {
187 /*       (GST_IS_V4LMJPEGSRC (v4lelement) && */
188 /*           !(v4lelement->vcap.type & VID_TYPE_MJPEG_ENCODER)) || */
189 /*       (GST_IS_V4LMJPEGSINK (v4lelement) && */
190 /*           !(v4lelement->vcap.type & VID_TYPE_MJPEG_DECODER))) { */
191     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
192         ("Device opened, but wrong type (0x%x)", v4lelement->vcap.type));
193     close (v4lelement->video_fd);
194     v4lelement->video_fd = -1;
195     return FALSE;
196   }
197
198   GST_INFO_OBJECT (v4lelement, "Opened device \'%s\' (\'%s\') successfully",
199       v4lelement->vcap.name, v4lelement->videodev);
200
201   /* norms + inputs, for the tuner interface */
202   for (num = 0; norm_name[num] != NULL; num++) {
203     GstV4lTunerNorm *v4lnorm = g_object_new (GST_TYPE_V4L_TUNER_NORM,
204         NULL);
205     GstTunerNorm *norm = GST_TUNER_NORM (v4lnorm);
206
207     norm->label = g_strdup (norm_name[num]);
208     if (num == 1)
209       gst_value_set_fraction (&norm->framerate, 30000, 1001);
210     else
211       gst_value_set_fraction (&norm->framerate, 25, 1);
212
213     v4lnorm->index = num;
214     v4lelement->norms = g_list_append (v4lelement->norms, (gpointer) norm);
215   }
216   v4lelement->channels = gst_v4l_get_chan_names (v4lelement);
217
218   for (num = 0; picture_name[num] != NULL; num++) {
219     GstV4lColorBalanceChannel *v4lchannel =
220         g_object_new (GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, NULL);
221     GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (v4lchannel);
222
223     channel->label = g_strdup (picture_name[num]);
224     channel->min_value = 0;
225     channel->max_value = 65535;
226     v4lchannel->index = num;
227     v4lelement->colors = g_list_append (v4lelement->colors, channel);
228   }
229
230   GST_DEBUG_OBJECT (v4lelement, "Setting default norm/input");
231   gst_v4l_set_chan_norm (v4lelement, 0, 0);
232
233   return TRUE;
234 }
235
236
237 /******************************************************
238  * gst_v4l_close():
239  *   close the video device (v4lelement->video_fd)
240  * return value: TRUE on success, FALSE on error
241  ******************************************************/
242
243 gboolean
244 gst_v4l_close (GstV4lElement * v4lelement)
245 {
246   GST_DEBUG_OBJECT (v4lelement, "closing device");
247   GST_V4L_CHECK_OPEN (v4lelement);
248   GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
249
250   close (v4lelement->video_fd);
251   v4lelement->video_fd = -1;
252
253   g_list_foreach (v4lelement->channels, (GFunc) g_object_unref, NULL);
254   g_list_free (v4lelement->channels);
255   v4lelement->channels = NULL;
256
257   g_list_foreach (v4lelement->norms, (GFunc) g_object_unref, NULL);
258   g_list_free (v4lelement->norms);
259   v4lelement->norms = NULL;
260
261   g_list_foreach (v4lelement->colors, (GFunc) g_object_unref, NULL);
262   g_list_free (v4lelement->colors);
263   v4lelement->colors = NULL;
264
265   return TRUE;
266 }
267
268
269 /******************************************************
270  * gst_v4l_get_num_chans()
271  * return value: the number of video input channels
272  ******************************************************/
273
274 gint
275 gst_v4l_get_num_chans (GstV4lElement * v4lelement)
276 {
277   GST_DEBUG_OBJECT (v4lelement, "getting number of channels");
278   GST_V4L_CHECK_OPEN (v4lelement);
279
280   return v4lelement->vcap.channels;
281 }
282
283
284 /******************************************************
285  * gst_v4l_get_chan_names()
286  * return value: a GList containing the channel names
287  ******************************************************/
288
289 GList *
290 gst_v4l_get_chan_names (GstV4lElement * v4lelement)
291 {
292   struct video_channel vchan;
293   GList *list = NULL;
294   gint i;
295
296   GST_DEBUG_OBJECT (v4lelement, "getting channel names");
297
298   if (!GST_V4L_IS_OPEN (v4lelement))
299     return NULL;
300
301   for (i = 0; i < gst_v4l_get_num_chans (v4lelement); i++) {
302     GstV4lTunerChannel *v4lchannel = g_object_new (GST_TYPE_V4L_TUNER_CHANNEL,
303         NULL);
304     GstTunerChannel *channel = GST_TUNER_CHANNEL (v4lchannel);
305
306     vchan.channel = i;
307     if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0)
308       return NULL;              /* memleak... */
309     channel->label = g_strdup (vchan.name);
310     channel->flags = GST_TUNER_CHANNEL_INPUT;
311     v4lchannel->index = i;
312     if (vchan.flags & VIDEO_VC_TUNER) {
313       struct video_tuner vtun;
314       gint n;
315
316       for (n = 0;; n++) {
317         if (n >= vchan.tuners) {
318           vtun.tuner = 0;       /* default */
319         } else {
320           vtun.tuner = n;
321           if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
322             continue;           /* no more tuners */
323           if (strcmp (vtun.name, vchan.name) != 0) {
324             continue;           /* not this one */
325           }
326         }
327         v4lchannel->tuner = n;
328         channel->flags |= GST_TUNER_CHANNEL_FREQUENCY;
329         channel->freq_multiplicator =
330             62.5 * ((vtun.flags & VIDEO_TUNER_LOW) ? 1 : 1000);
331         channel->min_frequency = vtun.rangelow;
332         channel->max_frequency = vtun.rangehigh;
333         channel->min_signal = 0;
334         channel->max_signal = 0xffff;
335         break;
336       }
337
338     }
339     if (vchan.flags & VIDEO_VC_AUDIO) {
340       struct video_audio vaud;
341       gint n;
342
343       for (n = 0; n < v4lelement->vcap.audios; n++) {
344         vaud.audio = n;
345         if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vaud) < 0)
346           continue;
347         if (!strcmp (vaud.name, vchan.name)) {
348           v4lchannel->audio = n;
349           channel->flags |= GST_TUNER_CHANNEL_AUDIO;
350           break;
351         }
352       }
353     }
354     list = g_list_append (list, (gpointer) channel);
355   }
356
357   return list;
358 }
359
360
361 /******************************************************
362  * gst_v4l_get_chan_norm():
363  *   get the currently active video-channel and it's
364  *   norm (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO})
365  * return value: TRUE on success, FALSE on error
366  ******************************************************/
367
368 gboolean
369 gst_v4l_get_chan_norm (GstV4lElement * v4lelement, gint * channel, gint * norm)
370 {
371   GST_DEBUG_OBJECT (v4lelement, "getting current channel and norm");
372   GST_V4L_CHECK_OPEN (v4lelement);
373
374   if (channel)
375     *channel = v4lelement->vchan.channel;
376   if (norm)
377     *norm = v4lelement->vchan.norm;
378
379   return TRUE;
380 }
381
382
383 /******************************************************
384  * gst_v4l_set_chan_norm():
385  *   set a new active channel and it's norm
386  *   (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO})
387  * return value: TRUE on success, FALSE on error
388  ******************************************************/
389
390 gboolean
391 gst_v4l_set_chan_norm (GstV4lElement * v4lelement, gint channel, gint norm)
392 {
393   GST_DEBUG_OBJECT (v4lelement, "setting channel = %d, norm = %d (%s)",
394       channel, norm, norm_name[norm]);
395   GST_V4L_CHECK_OPEN (v4lelement);
396   //GST_V4L_CHECK_NOT_ACTIVE (v4lelement);
397
398   v4lelement->vchan.channel = channel;
399   v4lelement->vchan.norm = norm;
400
401   if (ioctl (v4lelement->video_fd, VIDIOCSCHAN, &(v4lelement->vchan)) < 0) {
402     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
403         ("Error setting the channel/norm settings: %s", g_strerror (errno)));
404     return FALSE;
405   }
406
407   if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &(v4lelement->vchan)) < 0) {
408     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
409         ("Error getting the channel/norm settings: %s", g_strerror (errno)));
410     return FALSE;
411   }
412
413   return TRUE;
414 }
415
416
417 /******************************************************
418  * gst_v4l_get_signal():
419  *   get the current signal
420  * return value: TRUE on success, FALSE on error
421  ******************************************************/
422
423 gboolean
424 gst_v4l_get_signal (GstV4lElement * v4lelement, gint tunernum, guint * signal)
425 {
426   struct video_tuner tuner;
427
428   GST_DEBUG_OBJECT (v4lelement, "getting tuner signal");
429   GST_V4L_CHECK_OPEN (v4lelement);
430
431   tuner.tuner = tunernum;
432   if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &tuner) < 0) {
433     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
434         ("Error getting tuner signal: %s", g_strerror (errno)));
435     return FALSE;
436   }
437
438   *signal = tuner.signal;
439
440   return TRUE;
441 }
442
443
444 /******************************************************
445  * gst_v4l_get_frequency():
446  *   get the current frequency
447  * return value: TRUE on success, FALSE on error
448  ******************************************************/
449
450 gboolean
451 gst_v4l_get_frequency (GstV4lElement * v4lelement,
452     gint tunernum, gulong * frequency)
453 {
454   struct video_tuner vtun;
455   GstTunerChannel *channel;
456
457   GST_DEBUG_OBJECT (v4lelement, "getting tuner frequency");
458   GST_V4L_CHECK_OPEN (v4lelement);
459
460   channel = gst_tuner_get_channel (GST_TUNER (v4lelement));
461
462   /* check that this is the current input */
463   vtun.tuner = tunernum;
464   if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
465     return FALSE;
466   if (strcmp (vtun.name, v4lelement->vchan.name))
467     return FALSE;
468
469   if (ioctl (v4lelement->video_fd, VIDIOCGFREQ, frequency) < 0) {
470     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
471         ("Error getting tuner frequency: %s", g_strerror (errno)));
472     return FALSE;
473   }
474
475   *frequency = *frequency * channel->freq_multiplicator;
476
477   return TRUE;
478 }
479
480
481 /******************************************************
482  * gst_v4l_set_frequency():
483  *   set frequency
484  * return value: TRUE on success, FALSE on error
485  ******************************************************/
486
487 gboolean
488 gst_v4l_set_frequency (GstV4lElement * v4lelement,
489     gint tunernum, gulong frequency)
490 {
491   struct video_tuner vtun;
492   GstTunerChannel *channel;
493
494   GST_DEBUG_OBJECT (v4lelement, "setting tuner frequency to %lu", frequency);
495   GST_V4L_CHECK_OPEN (v4lelement);
496
497   channel = gst_tuner_get_channel (GST_TUNER (v4lelement));
498
499   /* check that this is the current input */
500   vtun.tuner = tunernum;
501   if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0)
502     return FALSE;
503   if (strcmp (vtun.name, v4lelement->vchan.name))
504     return FALSE;
505
506   frequency = frequency / channel->freq_multiplicator;
507
508   if (ioctl (v4lelement->video_fd, VIDIOCSFREQ, &frequency) < 0) {
509     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
510         ("Error setting tuner frequency: %s", g_strerror (errno)));
511     return FALSE;
512   }
513
514   return TRUE;
515 }
516
517
518 /******************************************************
519  * gst_v4l_get_picture():
520  *   get a picture value
521  * return value: TRUE on success, FALSE on error
522  ******************************************************/
523
524 gboolean
525 gst_v4l_get_picture (GstV4lElement * v4lelement,
526     GstV4lPictureType type, gint * value)
527 {
528   struct video_picture vpic;
529
530   GST_DEBUG_OBJECT (v4lelement, "getting picture property type %d (%s)", type,
531       picture_name[type]);
532   GST_V4L_CHECK_OPEN (v4lelement);
533
534   if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) {
535     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
536         ("Error getting picture parameters: %s", g_strerror (errno)));
537     return FALSE;
538   }
539
540   switch (type) {
541     case V4L_PICTURE_HUE:
542       *value = vpic.hue;
543       break;
544     case V4L_PICTURE_BRIGHTNESS:
545       *value = vpic.brightness;
546       break;
547     case V4L_PICTURE_CONTRAST:
548       *value = vpic.contrast;
549       break;
550     case V4L_PICTURE_SATURATION:
551       *value = vpic.colour;
552       break;
553     default:
554       GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
555           ("Error getting picture parameters: unknown type %d", type));
556       return FALSE;
557   }
558
559   return TRUE;
560 }
561
562
563 /******************************************************
564  * gst_v4l_set_picture():
565  *   set a picture value
566  * return value: TRUE on success, FALSE on error
567  ******************************************************/
568
569 gboolean
570 gst_v4l_set_picture (GstV4lElement * v4lelement,
571     GstV4lPictureType type, gint value)
572 {
573   struct video_picture vpic;
574
575   GST_DEBUG_OBJECT (v4lelement, "setting picture type %d (%s) to value %d",
576       type, picture_name[type], value);
577   GST_V4L_CHECK_OPEN (v4lelement);
578
579   if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) {
580     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
581         ("Error getting picture parameters: %s", g_strerror (errno)));
582     return FALSE;
583   }
584
585   switch (type) {
586     case V4L_PICTURE_HUE:
587       vpic.hue = value;
588       break;
589     case V4L_PICTURE_BRIGHTNESS:
590       vpic.brightness = value;
591       break;
592     case V4L_PICTURE_CONTRAST:
593       vpic.contrast = value;
594       break;
595     case V4L_PICTURE_SATURATION:
596       vpic.colour = value;
597       break;
598     default:
599       GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
600           ("Error setting picture parameters: unknown type %d", type));
601       return FALSE;
602   }
603
604   if (ioctl (v4lelement->video_fd, VIDIOCSPICT, &vpic) < 0) {
605     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
606         ("Error setting picture parameters: %s", g_strerror (errno)));
607     return FALSE;
608   }
609
610   return TRUE;
611 }
612
613
614 /******************************************************
615  * gst_v4l_get_audio():
616  *   get some audio value
617  * return value: TRUE on success, FALSE on error
618  ******************************************************/
619
620 gboolean
621 gst_v4l_get_audio (GstV4lElement * v4lelement,
622     gint audionum, GstV4lAudioType type, gint * value)
623 {
624   struct video_audio vau;
625
626   GST_DEBUG_OBJECT (v4lelement, "getting audio parameter type %d (%s)", type,
627       audio_name[type]);
628   GST_V4L_CHECK_OPEN (v4lelement);
629
630   vau.audio = audionum;
631   if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) {
632     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
633         ("Error getting audio parameters: %s", g_strerror (errno)));
634     return FALSE;
635   }
636
637   switch (type) {
638     case V4L_AUDIO_MUTE:
639       *value = (vau.flags & VIDEO_AUDIO_MUTE);
640       break;
641     case V4L_AUDIO_VOLUME:
642       *value = vau.volume;
643       break;
644     case V4L_AUDIO_MODE:
645       *value = vau.mode;
646       break;
647     default:
648       GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
649           ("Error getting audio parameters: unknown type %d", type));
650       return FALSE;
651   }
652
653   return TRUE;
654 }
655
656
657 /******************************************************
658  * gst_v4l_set_audio():
659  *   set some audio value
660  * return value: TRUE on success, FALSE on error
661  ******************************************************/
662
663 gboolean
664 gst_v4l_set_audio (GstV4lElement * v4lelement,
665     gint audionum, GstV4lAudioType type, gint value)
666 {
667   struct video_audio vau;
668
669   GST_DEBUG_OBJECT (v4lelement,
670       "setting audio parameter type %d (%s) to value %d", type,
671       audio_name[type], value);
672   GST_V4L_CHECK_OPEN (v4lelement);
673
674   vau.audio = audionum;
675   if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) {
676     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
677         ("Error getting audio parameters: %s", g_strerror (errno)));
678     return FALSE;
679   }
680
681   switch (type) {
682     case V4L_AUDIO_MUTE:
683       if (!(vau.flags & VIDEO_AUDIO_MUTABLE)) {
684         GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL),
685             ("Error setting audio mute: (un)setting mute is not supported"));
686         return FALSE;
687       }
688       if (value)
689         vau.flags |= VIDEO_AUDIO_MUTE;
690       else
691         vau.flags &= ~VIDEO_AUDIO_MUTE;
692       break;
693     case V4L_AUDIO_VOLUME:
694       if (!(vau.flags & VIDEO_AUDIO_VOLUME)) {
695         GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL),
696             ("Error setting audio volume: setting volume is not supported"));
697         return FALSE;
698       }
699       vau.volume = value;
700       break;
701     case V4L_AUDIO_MODE:
702       vau.mode = value;
703       break;
704     default:
705       GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
706           ("Error setting audio parameters: unknown type %d", type));
707       return FALSE;
708   }
709
710   if (ioctl (v4lelement->video_fd, VIDIOCSAUDIO, &vau) < 0) {
711     GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL),
712         ("Error setting audio parameters: %s", g_strerror (errno)));
713     return FALSE;
714   }
715
716   return TRUE;
717 }