Small updates to avimux and the v4l plugins for usability in general
[platform/upstream/gstreamer.git] / sys / v4l / v4l_calls.c
1 /* G-Streamer generic V4L element - generic V4L calls handling
2  * Copyright (C) 2001-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 //#define DEBUG
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <sys/ioctl.h>
26 #include <sys/mman.h>
27 #include <string.h>
28 #include <errno.h>
29 #include "v4l_calls.h"
30
31
32 char *picture_name[] = { "Hue", "Brightness", "Contrast", "Saturation", NULL };
33
34 char *audio_name[] = { "Volume", "Mute", "Mode", NULL };
35
36 char *norm_name[] = { "PAL", "NTSC", "SECAM", NULL };
37
38 /******************************************************
39  * gst_v4l_get_capabilities():
40  *   get the device's capturing capabilities
41  * return value: TRUE on success, FALSE on error
42  ******************************************************/
43
44 static gboolean
45 gst_v4l_get_capabilities (GstV4lElement *v4lelement)
46 {
47 #ifdef DEBUG
48   fprintf(stderr, "V4L: gst_v4l_get_capabilities()\n");
49 #endif
50
51   GST_V4L_CHECK_OPEN(v4lelement);
52
53   if (ioctl(v4lelement->video_fd, VIDIOCGCAP, &(v4lelement->vcap)) < 0)
54   {
55     gst_element_error(GST_ELEMENT(v4lelement),
56       "Error getting \'%s\' capabilities: %s",
57       v4lelement->videodev, sys_errlist[errno]);
58     return FALSE;
59   }
60
61   return TRUE;
62 }
63
64
65 /******************************************************
66  * gst_v4l_open():
67  *   open the video device (v4lelement->videodev)
68  * return value: TRUE on success, FALSE on error
69  ******************************************************/
70
71 gboolean
72 gst_v4l_open (GstV4lElement *v4lelement)
73 {
74 #ifdef DEBUG
75   fprintf(stderr, "V4L: gst_v4l_open()\n");
76 #endif
77
78   GST_V4L_CHECK_NOT_OPEN(v4lelement);
79   GST_V4L_CHECK_NOT_ACTIVE(v4lelement);
80
81   /* be sure we have a device */
82   if (!v4lelement->videodev)
83     v4lelement->videodev = g_strdup("/dev/video");
84
85   /* open the device */
86   v4lelement->video_fd = open(v4lelement->videodev, O_RDWR);
87   if (!GST_V4L_IS_OPEN(v4lelement))
88   {
89     gst_element_error(GST_ELEMENT(v4lelement),
90       "Failed to open device (\'%s\'): %s",
91       v4lelement->videodev, sys_errlist[errno]);
92     return FALSE;
93   }
94
95   /* get capabilities */
96   if (!gst_v4l_get_capabilities(v4lelement))
97   {
98     close(v4lelement->video_fd);
99     v4lelement->video_fd = -1;
100     return FALSE;
101   }
102
103   gst_info("Opened device \'%s\' (\'%s\') successfully\n",
104     v4lelement->vcap.name, v4lelement->videodev);
105
106   return TRUE;
107 }
108
109
110 /******************************************************
111  * gst_v4l_close():
112  *   close the video device (v4lelement->video_fd)
113  * return value: TRUE on success, FALSE on error
114  ******************************************************/
115
116 gboolean
117 gst_v4l_close (GstV4lElement *v4lelement)
118 {
119 #ifdef DEBUG
120   fprintf(stderr, "V4L: gst_v4l_close()\n");
121 #endif
122
123   GST_V4L_CHECK_OPEN(v4lelement);
124   GST_V4L_CHECK_NOT_ACTIVE(v4lelement);
125
126   close(v4lelement->video_fd);
127   v4lelement->video_fd = -1;
128
129   return TRUE;
130 }
131
132
133 /******************************************************
134  * gst_v4l_get_num_chans()
135  * return value: the numver of video input channels
136  ******************************************************/
137
138 gint
139 gst_v4l_get_num_chans (GstV4lElement *v4lelement)
140 {
141 #ifdef DEBUG
142   fprintf(stderr, "V4L: gst_v4l_get_num_chans()\n");
143 #endif
144
145   GST_V4L_CHECK_OPEN(v4lelement);
146
147   return v4lelement->vcap.channels;
148 }
149
150
151 /******************************************************
152  * gst_v4l_get_chan_names()
153  * return value: a GList containing the channel names
154  ******************************************************/
155
156 GList *
157 gst_v4l_get_chan_names (GstV4lElement *v4lelement)
158 {
159   struct video_channel vchan;
160   GList *list = NULL;
161   gint i;
162
163 #ifdef DEBUG
164   fprintf(stderr, "V4L: gst_v4l_get_chan_names()\n");
165 #endif
166
167   if (!GST_V4L_IS_OPEN(v4lelement))
168     return NULL;
169
170   for (i=0;i<gst_v4l_get_num_chans(v4lelement);i++)
171   {
172     vchan.channel = i;
173     if (ioctl(v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0)
174       return NULL;
175     list = g_list_append(list, (gpointer)g_strdup(vchan.name));
176   }
177
178   return list;
179 }
180
181
182 /******************************************************
183  * gst_v4l_get_chan_norm():
184  *   get the currently active video-channel and it's
185  *   norm (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO})
186  * return value: TRUE on success, FALSE on error
187  ******************************************************/
188
189 gboolean
190 gst_v4l_get_chan_norm (GstV4lElement *v4lelement,
191                        gint          *channel,
192                        gint          *norm)
193 {
194 #ifdef DEBUG
195   fprintf(stderr, "V4L: gst_v4l_get_chan_norm()\n");
196 #endif
197
198   GST_V4L_CHECK_OPEN(v4lelement);
199
200   if (channel)
201     *channel = v4lelement->vchan.channel;
202   if (norm)
203     *norm = v4lelement->vchan.norm;
204
205   return TRUE;
206 }
207
208
209 /******************************************************
210  * gst_v4l_set_chan_norm():
211  *   set a new active channel and it's norm
212  *   (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO})
213  * return value: TRUE on success, FALSE on error
214  ******************************************************/
215
216 gboolean
217 gst_v4l_set_chan_norm (GstV4lElement *v4lelement,
218                        gint          channel,
219                        gint          norm)
220 {
221 #ifdef DEBUG
222   fprintf(stderr, "V4L: gst_v4l_set_chan_norm(), channel = %d, norm = %d (%s)\n",
223     channel, norm, norm_name[norm]);
224 #endif
225
226   GST_V4L_CHECK_OPEN(v4lelement);
227   GST_V4L_CHECK_NOT_ACTIVE(v4lelement);
228
229   v4lelement->vchan.channel = channel;
230   v4lelement->vchan.norm = norm;
231
232   if (ioctl(v4lelement->video_fd, VIDIOCSCHAN, &(v4lelement->vchan)) < 0)
233   {
234     gst_element_error(GST_ELEMENT(v4lelement),
235       "Error setting the channel/norm settings: %s",
236       sys_errlist[errno]);
237     return FALSE;
238   }
239
240   if (ioctl(v4lelement->video_fd, VIDIOCGCHAN, &(v4lelement->vchan)) < 0)
241   {
242     gst_element_error(GST_ELEMENT(v4lelement),
243       "Error getting the channel/norm settings: %s",
244       sys_errlist[errno]);
245     return FALSE;
246   }
247
248   return TRUE;
249 }
250
251
252 /******************************************************
253  * gst_v4l_has_tuner():
254  * return value: TRUE if it has a tuner, else FALSE
255  ******************************************************/
256
257 gboolean
258 gst_v4l_has_tuner (GstV4lElement *v4lelement)
259 {
260 #ifdef DEBUG
261   fprintf(stderr, "V4L: gst_v4l_has_tuner()\n");
262 #endif
263
264   GST_V4L_CHECK_OPEN(v4lelement);
265
266   return (v4lelement->vcap.type & VID_TYPE_TUNER &&
267           v4lelement->vchan.flags & VIDEO_VC_TUNER);
268 }
269
270
271 /******************************************************
272  * gst_v4l_get_frequency():
273  *   get the current frequency
274  * return value: TRUE on success, FALSE on error
275  ******************************************************/
276
277 gboolean
278 gst_v4l_get_frequency (GstV4lElement *v4lelement,
279                        gulong        *frequency)
280 {
281 #ifdef DEBUG
282   fprintf(stderr, "V4L: gst_v4l_get_frequency()\n");
283 #endif
284
285   GST_V4L_CHECK_OPEN(v4lelement);
286
287   if (!gst_v4l_has_tuner(v4lelement))
288     return FALSE;
289
290   if (ioctl(v4lelement->video_fd, VIDIOCGFREQ, frequency) < 0)
291   {
292     gst_element_error(GST_ELEMENT(v4lelement),
293       "Error getting tuner frequency: %s",
294       sys_errlist[errno]);
295     return FALSE;
296   }
297
298   return TRUE;
299 }
300
301
302 /******************************************************
303  * gst_v4l_set_frequency():
304  *   set frequency
305  * return value: TRUE on success, FALSE on error
306  ******************************************************/
307
308 gboolean
309 gst_v4l_set_frequency (GstV4lElement *v4lelement,
310                        gulong        frequency)
311 {
312 #ifdef DEBUG
313   fprintf(stderr, "gst_v4l_set_frequency(), frequency = %ul\n",
314     frequency);
315 #endif
316
317   GST_V4L_CHECK_OPEN(v4lelement);
318   GST_V4L_CHECK_NOT_ACTIVE(v4lelement);
319
320   if (!gst_v4l_has_tuner(v4lelement))
321     return FALSE;
322
323   if (ioctl(v4lelement->video_fd, VIDIOCSFREQ, &frequency) < 0)
324   {
325     gst_element_error(GST_ELEMENT(v4lelement),
326       "Error setting tuner frequency: %s",
327       sys_errlist[errno]);
328     return FALSE;
329   }
330
331   return TRUE;
332 }
333
334
335 /******************************************************
336  * gst_v4l_get_picture():
337  *   get a picture value
338  * return value: TRUE on success, FALSE on error
339  ******************************************************/
340
341 gboolean
342 gst_v4l_get_picture (GstV4lElement     *v4lelement,
343                      GstV4lPictureType type,
344                      gint              *value)
345 {
346   struct video_picture vpic;
347
348 #ifdef DEBUG
349   fprintf(stderr, "V4L: gst_v4l_get_picture(), type = %d (%s)\n",
350     type, picture_name[type]);
351 #endif
352
353   GST_V4L_CHECK_OPEN(v4lelement);
354
355   if (ioctl(v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0)
356   {
357     gst_element_error(GST_ELEMENT(v4lelement),
358       "Error getting picture parameters: %s",
359       sys_errlist[errno]);
360     return FALSE;
361   }
362
363   switch (type)
364   {
365     case V4L_PICTURE_HUE:
366       *value = vpic.hue;
367       break;
368     case V4L_PICTURE_BRIGHTNESS:
369       *value = vpic.brightness;
370       break;
371     case V4L_PICTURE_CONTRAST:
372       *value = vpic.contrast;
373       break;
374     case V4L_PICTURE_SATURATION:
375       *value = vpic.colour;
376       break;
377     default:
378       gst_element_error(GST_ELEMENT(v4lelement),
379         "Error getting picture parameters: unknown type %d",
380         type);
381       return FALSE;
382   }
383
384   return TRUE;
385 }
386
387
388 /******************************************************
389  * gst_v4l_set_picture():
390  *   set a picture value
391  * return value: TRUE on success, FALSE on error
392  ******************************************************/
393
394 gboolean
395 gst_v4l_set_picture (GstV4lElement     *v4lelement,
396                      GstV4lPictureType type,
397                      gint              value)
398 {
399   struct video_picture vpic;
400
401 #ifdef DEBUG
402   fprintf(stderr, "V4L: gst_v4l_set_picture(), type = %d (%s), value = %d\n",
403     type, picture_name[type], value);
404 #endif
405
406   GST_V4L_CHECK_OPEN(v4lelement);
407
408   if (ioctl(v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0)
409   {
410     gst_element_error(GST_ELEMENT(v4lelement),
411       "Error getting picture parameters: %s",
412       sys_errlist[errno]);
413     return FALSE;
414   }
415
416   switch (type)
417   {
418     case V4L_PICTURE_HUE:
419       vpic.hue = value;
420       break;
421     case V4L_PICTURE_BRIGHTNESS:
422       vpic.brightness = value;
423       break;
424     case V4L_PICTURE_CONTRAST:
425       vpic.contrast = value;
426       break;
427     case V4L_PICTURE_SATURATION:
428       vpic.colour = value;
429       break;
430     default:
431       gst_element_error(GST_ELEMENT(v4lelement),
432         "Error setting picture parameters: unknown type %d",
433         type);
434       return FALSE;
435   }
436
437   if (ioctl(v4lelement->video_fd, VIDIOCSPICT, &vpic) < 0)
438   {
439     gst_element_error(GST_ELEMENT(v4lelement),
440       "Error setting picture parameters: %s",
441       sys_errlist[errno]);
442     return FALSE;
443   }
444
445   return TRUE;
446 }
447
448
449 /******************************************************
450  * gst_v4l_has_audio():
451  * return value: TRUE if it can do audio, else FALSE
452  ******************************************************/
453
454 gboolean
455 gst_v4l_has_audio (GstV4lElement *v4lelement)
456 {
457 #ifdef DEBUG
458   fprintf(stderr, "V4L: gst_v4l_has_audio()\n");
459 #endif
460
461   GST_V4L_CHECK_OPEN(v4lelement);
462
463   return (v4lelement->vcap.audios > 0 &&
464           v4lelement->vchan.flags & VIDEO_VC_AUDIO);
465 }
466
467
468 /******************************************************
469  * gst_v4l_get_audio():
470  *   get some audio value
471  * return value: TRUE on success, FALSE on error
472  ******************************************************/
473
474 gboolean
475 gst_v4l_get_audio (GstV4lElement   *v4lelement,
476                    GstV4lAudioType type,
477                    gint            *value)
478 {
479   struct video_audio vau;
480
481 #ifdef DEBUG
482   fprintf(stderr, "V4L: v4l_gst_get_audio(), type = %d (%s)\n",
483     type, audio_name[type]);
484 #endif
485
486   GST_V4L_CHECK_OPEN(v4lelement);
487
488   if (!gst_v4l_has_audio(v4lelement))
489     return FALSE;
490
491   if (ioctl(v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0)
492   {
493     gst_element_error(GST_ELEMENT(v4lelement),
494       "Error getting audio parameters: %s",
495       sys_errlist[errno]);
496     return FALSE;
497   }
498
499   switch (type)
500   {
501     case V4L_AUDIO_MUTE:
502       *value = (vau.flags & VIDEO_AUDIO_MUTE);
503       break;
504     case V4L_AUDIO_VOLUME:
505       *value = vau.volume;
506       break;
507     case V4L_AUDIO_MODE:
508       *value = vau.mode;
509       break;
510     default:
511       gst_element_error(GST_ELEMENT(v4lelement),
512         "Error getting audio parameters: unknown type %d",
513         type);
514       return FALSE;
515   }
516
517   return TRUE;
518 }
519
520
521 /******************************************************
522  * gst_v4l_set_audio():
523  *   set some audio value
524  * return value: TRUE on success, FALSE on error
525  ******************************************************/
526
527 gboolean
528 gst_v4l_set_audio (GstV4lElement   *v4lelement,
529                    GstV4lAudioType type,
530                    gint            value)
531 {
532   struct video_audio vau;
533
534 #ifdef DEBUG
535   fprintf(stderr, "V4L: v4l_gst_set_audio(), type = %d (%s), value = %d\n",
536     type, audio_name[type], value);
537 #endif
538
539   GST_V4L_CHECK_OPEN(v4lelement);
540
541   if (!gst_v4l_has_audio(v4lelement))
542     return FALSE;
543
544   if (ioctl(v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0)
545   {
546     gst_element_error(GST_ELEMENT(v4lelement),
547       "Error getting audio parameters: %s",
548       sys_errlist[errno]);
549     return FALSE;
550   }
551
552   switch (type)
553   {
554     case V4L_AUDIO_MUTE:
555       if (!(vau.flags & VIDEO_AUDIO_MUTABLE))
556       {
557         gst_element_error(GST_ELEMENT(v4lelement),
558           "Error setting audio mute: (un)setting mute is not supported");
559         return FALSE;
560       }
561       if (value)
562         vau.flags |= VIDEO_AUDIO_MUTE;
563       else
564         vau.flags &= ~VIDEO_AUDIO_MUTE;
565       break;
566     case V4L_AUDIO_VOLUME:
567       if (!(vau.flags & VIDEO_AUDIO_VOLUME))
568       {
569         gst_element_error(GST_ELEMENT(v4lelement),
570           "Error setting audio volume: setting volume is not supported");
571         return FALSE;
572       }
573       vau.volume = value;
574       break;
575     case V4L_AUDIO_MODE:
576       vau.mode = value;
577       break;
578     default:
579       gst_element_error(GST_ELEMENT(v4lelement),
580         "Error setting audio parameters: unknown type %d",
581         type);
582       return FALSE;
583   }
584
585   if (ioctl(v4lelement->video_fd, VIDIOCSAUDIO, &vau) < 0)
586   {
587     gst_element_error(GST_ELEMENT(v4lelement),
588       "Error setting audio parameters: %s",
589       sys_errlist[errno]);
590     return FALSE;
591   }
592
593   return TRUE;
594 }