From: Dave Schmitz <schmitzware@xxxxxxxxx> > I was curious to know if anyone is using both video tuning and FM > tuning in the same (bttv) app. Does not work with e.g. one hauppauge card. It has only one tuner and cant tune both, tv and fm. > I was wondering what the best approach is to use both devices. > Do I need to close the /dev/video0 and open /dev/radio0 and vice > versa when switching between functionality? > Is there a way to open both devices? Hm. Depends on the hardware. I've an extra radio card and both devices dont know each other, of course. But with the same tuner on a grabber card... Maybe you could select some other (tunerless) input for video and use the radio part of that card... Try or ask Gerd... (-: > Also, I've noticed a ioctl called VIDIOCGUNIT which is suppose to > "obtain related devices if a driver has multiple components". What > is this information used for? Good question. I tried my litte C code (attached) on various /dev/xyz with bttv 0.7.x. Only /dev/video0 reported something - very usefull to find relationships form /dev/radioX to user things... I wanted to write some radio app that time... Okay, run my piece of C. It's for v4l1. The output here for /dev/radio shows the behavior of "my" miropcm20 driver.... Bye, Robert bash-2.05$ ./v4l-test /dev/radio Found Miro PCM20, which has 1 channel(s). Unable to check for related units... <--------- Sorry, this device is unable to answer on VIDIOGCHAN for channel 0... Setting to channel 0. VIDIOCSCHAN failed. (This is normal...) Tuner0 (FM): low: 87.000, high: 108.000 current frequency (97.150): stereo RDS (auto) signal:48059 Audio0 (Radio): mode: mono stereo flags: unmuted balance:-32768 step:0
/* * Copyright (C) 2000 Robert Siemer <Robert.Siemer@xxxxxx> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ #define _GNU_SOURCE #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <sys/ioctl.h> #include <linux/videodev.h> typedef struct { unsigned int freq; unsigned int signal; unsigned int stereo :1; unsigned int rds :1; } station; int main (int argc, char *argv[]) { int fd, i; struct video_capability vcap; struct video_unit vu; struct video_channel vchan; struct video_tuner vt; unsigned long freq; struct video_audio va; if (argc==0) return 1; fd=open(argv[1], O_RDONLY); if (fd<0) { perror(program_invocation_short_name); return 1; } if (ioctl(fd, VIDIOCGCAP, &vcap)<0) { perror(program_invocation_short_name); return 1; } if (vcap.type&VID_TYPE_TUNER && !vcap.type&VID_TYPE_CAPTURE && !vcap.type&VID_TYPE_OVERLAY) printf("Hmmm, does not look like a radio card - but I don't" " care... [:\n"); if (vcap.audios!=1) printf("Aehm, what does it mean: this device has %d" " audio devices...\n", vcap.audios); printf("Found %s, which has %d channel(s).\n", vcap.name, vcap.channels); if (ioctl(fd, VIDIOCGUNIT, &vu)<0) printf("Unable to check for related units...\n"); else printf("video:%d vbi:%d radio:%d audio:%d teletext:%d\n", vu.video, vu.vbi, vu.radio, vu.audio, vu.teletext); for (vchan.channel=0; vchan.channel<vcap.channels; vchan.channel++) { if (ioctl(fd, VIDIOCGCHAN, &vchan)<0) { printf("Sorry, this device is unable to answer on" " VIDIOGCHAN for channel %d...\n", vchan.channel); continue; } printf("Channel%d (%s): ", vchan.channel, vchan.name); if (vchan.tuners<1 && !(vchan.flags&VIDEO_VC_TUNER)) { printf("no tuner --> no radio\n"); continue; } if ((vchan.tuners<1 && vchan.flags&VIDEO_VC_TUNER) || (vchan.tuners>=1 && !(vchan.flags&VIDEO_VC_TUNER))) printf("device is unsure about having some (%d)" " tuners on this channel...\n", vchan.tuners); if (vchan.type&VIDEO_TYPE_TV || vchan.type&VIDEO_TYPE_CAMERA || !(vchan.flags&VIDEO_VC_AUDIO)) { printf("A radio has audio and no tv/camera input. " "This is not true here...\n"); continue; } printf("\n"); break; } if (vchan.channel==vcap.channels) vchan.channel=0, vchan.tuners=1; printf("Setting to channel %d.\n", vchan.channel); if (ioctl(fd, VIDIOCSCHAN, &vchan)<0) { printf("VIDIOCSCHAN failed. (This is normal...)\n"); } for (vt.tuner=0; vt.tuner<vchan.tuners; vt.tuner++) { if (ioctl(fd, VIDIOCGTUNER, &vt)<0) { printf("ioctl() problem with tuner %d.\n", vt.tuner); continue; } printf("Tuner%d (%s): ", vt.tuner, vt.name); i=(vt.flags&VIDEO_TUNER_LOW)? 16000 : 16; printf("low: %.3f, high: %.3f\n", (double)vt.rangelow/i, (double)vt.rangehigh/i); if (ioctl(fd, VIDIOCSTUNER, &vt)<0 || ioctl(fd, VIDIOCGFREQ, &freq)<0) { printf("Sorry, this tuner is just fucked up...\n"); continue; } printf(" current frequency (%.3f): ", (double)freq/i); if (vt.flags&VIDEO_TUNER_STEREO_ON) printf("stereo "); if (vt.flags&VIDEO_TUNER_RDS_ON) printf("RDS "); if (vt.mode&VIDEO_MODE_AUTO) printf("(auto)"); printf("\n"); printf(" signal:%d\n", vt.signal); } for (va.audio=0; va.audio<vcap.audios; va.audio++) { if (ioctl(fd, VIDIOCGAUDIO, &va)<0) { printf("ioctl() problem with audio %d.\n", va.audio); continue; } printf("Audio%d (%s): ", va.audio, va.name); printf("mode: "); if (va.mode&VIDEO_SOUND_MONO) printf("mono "); if (va.mode&VIDEO_SOUND_STEREO) printf("stereo "); if (va.mode&VIDEO_SOUND_LANG1) printf("lang1 "); if (va.mode&VIDEO_SOUND_LANG2) printf("lang2"); printf("\n"); printf(" flags: "); if (va.flags&VIDEO_AUDIO_MUTABLE) { if (va.flags&VIDEO_AUDIO_MUTE) printf("muted "); else printf("unmuted "); } if (va.flags&VIDEO_AUDIO_VOLUME) printf("volume:%d ", va.volume); if (va.flags&VIDEO_AUDIO_BASS) printf("bass:%d ", va.bass); if (va.flags&VIDEO_AUDIO_TREBLE) printf("treble:%d ", va.treble); printf("balance:%d step:%d\n", va.balance-32768, va.step); } return 0; }