[mythtv] [PATCH] Beginning radio pvr support

Carl mythtv at carldunham.com
Mon Jan 12 11:09:36 EST 2004


How hard would it be to have radio audio play while the UI was up? For that 
matter, sounds as part of the theme would be cool, even if it was an mp3 
loop.

Also, does the card support any of the program information data that is 
encoded with some fm stations now? That would make a nice osd...


On Monday January 12 2004 10:36, John Pullan wrote:
>   If we had the capability to view a dummy video screen then perhaps we
> could use the feature to show or rather not show off air DVB channels.
> E.g when CBBC goes off the air then it's PIDS get taken over by BBC3 (or
> is it BBC4), but it's entry in the EIT table has some nice informative
> text telling you when it'll be back on the air again.
>
> On Mon, 2004-01-12 at 15:03, Malcolm Smith wrote:
> > Wonderful start.
> >
> > Don't forget in input terms (assume you mean broadcast radio rather than
> > webcast) you will need to support
> >
> > 1. analog - Some TV cards support radio as well
> > 2.        DVB - both Terrestrial and Satelite support audio streams
> > 3.        Specialised input cards
> >
> > Guessing from your code you've done 1.
> >
> > I like the overall approach (i.e. integrate as though it was a TV channel
> > but with no picture). Xmltv supports channel lists so the scheduling is
> > seemless as is resource management.
> >
> > Rather than rework large parts of mythtv how about using mythmusic for
> > playback.
> >
> > My current hack soln is for mode 2 (DVB).
> > 1. Record the channel with audio radio and a dummy tv picture.
> > 2. Use a hacked version of Nuvexport to extract the mp3 file (Chris I'll
> > send you the new module once I've finished testing!)
> > 3. Playback mp3 via any appropriate means (mythmusic is handy)
> >
> > -malc-
> >
> > > -----Original Message-----
> > > From: mythtv-dev-bounces at mythtv.org
> > > [mailto:mythtv-dev-bounces at mythtv.org]On Behalf Of Dan Sheridan
> > > Sent: Saturday, January 10, 2004 6:22 PM
> > > To: Development of mythtv
> > > Subject: [mythtv] [PATCH] Beginning radio pvr support
> > >
> > >
> > >
> > > This is a very hacky first attempt (which doesn't work!) at radio
> > > support within mythtv. I am aiming to support radio as another input:
> > > channels can be selected and recorded as if they were TV channels. I
> > > have tuning and input selection sorted out, using an extra column in
> > > the cardinput table to indicate a radio input (though the device name
> > > should probably be in the capturecard table).
> > >
> > > My problems are:
> > >
> > > o  Notifying the various threads that the current stream is
> > >    audio-only. At the moment I have a call to a function in
> > >    ChannelBase, but this feels messy.
> > >
> > > o  NuppelVideoRecorder, when setting up, can select a channel. I think
> > >    for symmetry that it should use the Channel class instead of
> > >    calling the ioctl itself -- is there any reason why it doesn't at
> > >    the moment?
> > >
> > > o  I need to stop the video thread while allowing the audio thread to
> > >    continue. You can see my failed attempt below. Any ideas on how I
> > >    should be going about this?
> > >
> > > When backend support is complete, I'd like to modify the frontend to
> > > simply keep all of the OSDs switch on, with a black bacground, when a
> > > stream without video is played.
> > >
> > >        Dan.
> > >
> > > --
> > > Dan Sheridan -- Research Student -- LFCS, Division of Informatics
> > >  University of Edinburgh, King's Buildings, Mayfield Road EH9 3JZ
> > >
> > >
> > > Index: mythtv/libs/libmythtv/NuppelVideoRecorder.cpp
> > > ===================================================================
> > > RCS file:
> > > /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoRecorder.cpp,v
> > > retrieving revision 1.152
> > > diff -u -r1.152 NuppelVideoRecorder.cpp
> > > --- mythtv/libs/libmythtv/NuppelVideoRecorder.cpp	7 Jan 2004
> > > 06:14:04 -0000	1.152
> > > +++ mythtv/libs/libmythtv/NuppelVideoRecorder.cpp	10 Jan 2004
> > > 18:11:05 -0000
> > > @@ -366,6 +366,7 @@
> > >
> > >  void NuppelVideoRecorder::Unpause(void)
> > >  {
> > > +    isradio = channelObj->GetCurrentInputRadio();
> > >      pausewritethread = false;
> > >      paused = false;
> > >  }
> > > @@ -1027,6 +1028,13 @@
> > >                 gettimeofday(&stm, &tzone);
> > >             continue;
> > >          }
> > > +        if (isradio)
> > > +        {
> > > +           usleep(500);
> > > +           if (cleartimeonpause)
> > > +               gettimeofday(&stm, &tzone);
> > > +           continue;
> > > +        }
> > >
> > >          frame = 0;
> > >          mm.frame = 0;
> > > @@ -2433,7 +2441,7 @@
> > >          } action = ACTION_NONE;
> > >          int firsttimecode = -1;
> > >
> > > -        if (videobuffer[act_video_encode]->freeToEncode)
> > > +        if (!isradio && videobuffer[act_video_encode]->freeToEncode)
> > >          {
> > >              action = ACTION_VIDEO;
> > >              firsttimecode = videobuffer[act_video_encode]->timecode;
> > > Index: mythtv/libs/libmythtv/NuppelVideoRecorder.h
> > > ===================================================================
> > > RCS file:
> > > /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoRecorder.h,v
> > > retrieving revision 1.66
> > > diff -u -r1.66 NuppelVideoRecorder.h
> > > --- mythtv/libs/libmythtv/NuppelVideoRecorder.h	7 Jan 2004
> > > 06:14:04 -0000	1.66
> > > +++ mythtv/libs/libmythtv/NuppelVideoRecorder.h	10 Jan 2004
> > > 18:11:05 -0000
> > > @@ -262,6 +262,8 @@
> > >      ChannelBase *channelObj;
> > >
> > >      bool setorigaudio;
> > > +
> > > +    bool isradio;
> > >  };
> > >
> > >  #endif
> > > Index: mythtv/libs/libmythtv/channel.cpp
> > > ===================================================================
> > > RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channel.cpp,v
> > > retrieving revision 1.60
> > > diff -u -r1.60 channel.cpp
> > > --- mythtv/libs/libmythtv/channel.cpp	9 Jan 2004 21:02:12 -0000	1.60
> > > +++ mythtv/libs/libmythtv/channel.cpp	10 Jan 2004 18:11:05 -0000
> > > @@ -22,6 +22,7 @@
> > >  {
> > >      device = videodevice;
> > >      isopen = false;
> > > +    isradio = false;
> > >      videofd = -1;
> > >      curList = 0;
> > >      defaultFreqTable = 1;
> > > @@ -117,11 +118,26 @@
> > >              inputChannel[vin.index] = "";
> > >              inputTuneTo[vin.index] = "";
> > >              externalChanger[vin.index] = "";
> > > +            inputRadio[vin.index] = "";
> > >              vin.index++;
> > >
> > >              capchannels = vin.index;
> > >          }
> > >
> > > +	// if there is a radio on this card
> > > +	{
> > > +	    QString msg = QString("Probed: %1 - Radio").arg(device);
> > > +            VERBOSE(VB_CHANNEL, msg);
> > > +            channelnames[vin.index] = "Radio";
> > > +            inputChannel[vin.index] = "";
> > > +            inputTuneTo[vin.index] = "";
> > > +            externalChanger[vin.index] = "";
> > > +            inputRadio[vin.index] = ""; // Will be filled in later
> > > +            vin.index++;
> > > +
> > > +            capchannels = vin.index;
> > > +	}
> > > +
> > >          if (fmt == "NTSC")
> > >              videomode = V4L2_STD_NTSC;
> > >          else if (fmt == "ATSC")
> > > @@ -140,7 +156,7 @@
> > >              videomode = V4L2_STD_NTSC_M_JP;
> > >
> > >          pParent->RetrieveInputChannels(inputChannel, inputTuneTo,
> > > -                                       externalChanger);
> > > +                                       externalChanger, inputRadio);
> > >          return;
> > >      }
> > >
> > > @@ -189,8 +205,20 @@
> > >          inputChannel[i] = "";
> > >          inputTuneTo[i] = "";
> > >          externalChanger[i] = "";
> > > +        inputRadio[i] = "";
> > >      }
> > >
> > > +    // if there is a radio on this card
> > > +    {
> > > +        QString msg = QString("Probed: %1 - Radio").arg(device);
> > > +        VERBOSE(VB_CHANNEL, msg);
> > > +        channelnames[capchannels] = "Radio";
> > > +        inputChannel[capchannels] = "";
> > > +        inputTuneTo[capchannels] = "";
> > > +        externalChanger[capchannels] = "";
> > > +        inputRadio[capchannels] = ""; // Will be filled in later
> > > +        capchannels++;
> > > +    }
> > >      struct video_channel vc;
> > >      memset(&vc, 0, sizeof(vc));
> > >      ioctl(videofd, VIDIOCGCHAN, &vc);
> > > @@ -199,7 +227,7 @@
> > >
> > >      videomode = mode;
> > >
> > > -    pParent->RetrieveInputChannels(inputChannel, inputTuneTo,
> > > externalChanger);
> > > +    pParent->RetrieveInputChannels(inputChannel, inputTuneTo,
> > > externalChanger, inputRadio);
> > >  }
> > >
> > >  int Channel::SetDefaultFreqTable(const QString &name)
> > > @@ -254,6 +282,11 @@
> > >      return -1;
> > >  }
> > >
> > > +bool Channel::GetCurrentInputRadio(void)
> > > +{
> > > +  return isradio;
> > > +}
> > > +
> > >  bool Channel::ChannelUp(void)
> > >  {
> > >      if (ChannelBase::ChannelUp())
> > > @@ -369,6 +402,7 @@
> > >      // Tune
> > >      if (externalChanger[currentcapchannel].isEmpty())
> > >      {
> > > +        cerr << "Requesting " << freqid << "\n";
> > >          if (!TuneTo(freqid, finetune))
> > >              return false;
> > >      }
> > > @@ -392,18 +426,29 @@
> > >
> > >  bool Channel::TuneTo(const QString &channum, int finetune)
> > >  {
> > > -    int i = GetCurrentChannelNum(channum);
> > > -    if (i == -1)
> > > -        return false;
> > > -
> > > -    int frequency = curList[i].freq * 16 / 1000 + finetune;
> > > +    int frequency;
> > > +    if (isradio)
> > > +    {
> > > +        frequency = channum.toInt() * 16;
> > > +	cerr << "Tuning to " << frequency << "\n";
> > > +    }
> > > +    else
> > > +    {
> > > +	int i = GetCurrentChannelNum(channum);
> > > +	if (i == -1)
> > > +	    return false;
> > > +        frequency = curList[i].freq * 16 / 1000 + finetune;
> > > +    }
> > >
> > >      if (usingv4l2)
> > >      {
> > >          struct v4l2_frequency vf;
> > >          memset(&vf, 0, sizeof(vf));
> > >          vf.frequency = frequency;
> > > -        vf.type = V4L2_TUNER_ANALOG_TV;
> > > +	if (isradio)
> > > +	    vf.type = V4L2_TUNER_RADIO;
> > > +        else
> > > +            vf.type = V4L2_TUNER_ANALOG_TV;
> > >
> > >          if (ioctl(videofd, VIDIOC_S_FREQUENCY, &vf) < 0)
> > >          {
> > > @@ -424,23 +469,53 @@
> > >
> > >  void Channel::SwitchToInput(int newcapchannel, bool setstarting)
> > >  {
> > > -    if (usingv4l2)
> > > +    if (!inputRadio[newcapchannel].isEmpty())
> > >      {
> > > -        if (ioctl(videofd, VIDIOC_S_INPUT, &newcapchannel) < 0)
> > > -            perror("VIDIOC_S_INPUT");
> > > -
> > > -        if (ioctl(videofd, VIDIOC_S_STD, &videomode) < 0)
> > > -            perror("VIDIOC_S_STD");
> > > +        close(videofd);
> > > +        videofd = open(inputRadio[newcapchannel].ascii(), O_RDWR);
> > > +        if (videofd > 0)
> > > +            isradio = true;
> > > +        else
> > > +        {
> > > +            cerr << "Channel::SwitchToInput(): Can't open: " <<
> > > inputRadio[newcapchannel] << endl;
> > > +            perror(inputRadio[newcapchannel].ascii());
> > > +            return;
> > > +        }
> > > +    } else
> > > +    if (isradio)
> > > +    {
> > > +        close(videofd);
> > > +	videofd = open(device.ascii(), O_RDWR);
> > > +        if (videofd > 0)
> > > +            isradio = false;
> > > +        else
> > > +        {
> > > +             cerr << "Channel::SwitchToInput(): Can't open: " <<
> > > device << endl;
> > > +             perror(device.ascii());
> > > +             return;
> > > +        }
> > >      }
> > > -    else
> > > +
> > > +    if (!isradio)
> > >      {
> > > -        struct video_channel set;
> > > -        memset(&set, 0, sizeof(set));
> > > -        ioctl(videofd, VIDIOCGCHAN, &set);
> > > -        set.channel = newcapchannel;
> > > -        set.norm = videomode;
> > > -        if (ioctl(videofd, VIDIOCSCHAN, &set) < 0)
> > > -           perror("VIDIOCSCHAN");
> > > +        if (usingv4l2)
> > > +        {
> > > +            if (ioctl(videofd, VIDIOC_S_INPUT, &newcapchannel) < 0)
> > > +                perror("VIDIOC_S_INPUT");
> > > +
> > > +            if (ioctl(videofd, VIDIOC_S_STD, &videomode) < 0)
> > > +                perror("VIDIOC_S_STD");
> > > +        }
> > > +        else
> > > +        {
> > > +            struct video_channel set;
> > > +            memset(&set, 0, sizeof(set));
> > > +            ioctl(videofd, VIDIOCGCHAN, &set);
> > > +            set.channel = newcapchannel;
> > > +            set.norm = videomode;
> > > +            if (ioctl(videofd, VIDIOCSCHAN, &set) < 0)
> > > +               perror("VIDIOCSCHAN");
> > > +        }
> > >      }
> > >
> > >      currentcapchannel = newcapchannel;
> > > @@ -476,6 +551,9 @@
> > >      QString field_name = name;
> > >      int field = pParent->GetChannelValue(field_name, this,
> > > curchannelname);
> > >
> > > +    if (isradio)
> > > +        return;
> > > +
> > >      if (usingv4l2)
> > >      {
> > >          struct v4l2_control ctrl;
> > > Index: mythtv/libs/libmythtv/channel.h
> > > ===================================================================
> > > RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channel.h,v
> > > retrieving revision 1.26
> > > diff -u -r1.26 channel.h
> > > --- mythtv/libs/libmythtv/channel.h	9 Jan 2004 21:02:12 -0000	1.26
> > > +++ mythtv/libs/libmythtv/channel.h	10 Jan 2004 18:11:05 -0000
> > > @@ -41,8 +41,9 @@
> > >      void SetHue();
> > >
> > >      void SwitchToInput(int newcapchannel, bool setstarting);
> > > -
> > > +
> > >      void SetFd(int fd);
> > > +    bool GetCurrentInputRadio(void);
> > >
> > >    private:
> > >      int GetCurrentChannelNum(const QString &channame);
> > > @@ -53,6 +54,7 @@
> > >
> > >      QString device;
> > >      bool isopen;
> > > +    bool isradio;
> > >      int videofd;
> > >
> > >      struct CHANLIST *curList;
> > > Index: mythtv/libs/libmythtv/channelbase.cpp
> > > ===================================================================
> > > RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channelbase.cpp,v
> > > retrieving revision 1.6
> > > diff -u -r1.6 channelbase.cpp
> > > --- mythtv/libs/libmythtv/channelbase.cpp	12 Sep 2003
> > > 16:49:53 -0000	1.6
> > > +++ mythtv/libs/libmythtv/channelbase.cpp	10 Jan 2004 18:11:05 -0000
> > > @@ -70,6 +70,11 @@
> > >      return currentcapchannel;
> > >  }
> > >
> > > +bool ChannelBase::GetCurrentInputRadio(void)
> > > +{
> > > +  return false;
> > > +}
> > > +
> > >  void ChannelBase::ToggleInputs(void)
> > >  {
> > >      int newcapchannel = currentcapchannel;
> > > Index: mythtv/libs/libmythtv/channelbase.h
> > > ===================================================================
> > > RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/channelbase.h,v
> > > retrieving revision 1.3
> > > diff -u -r1.3 channelbase.h
> > > --- mythtv/libs/libmythtv/channelbase.h	7 Aug 2003 17:37:41
> > > -0000	1.3
> > > +++ mythtv/libs/libmythtv/channelbase.h	10 Jan 2004 18:11:05 -0000
> > > @@ -55,6 +55,7 @@
> > >      virtual QString GetCurrentInput(void);
> > >
> > >      virtual int GetCurrentInputNum(void);
> > > +    virtual bool GetCurrentInputRadio(void);
> > >
> > >      virtual void SetFd(int fd) { (void)fd; }
> > >
> > > @@ -69,6 +70,7 @@
> > >      map<int, QString> inputChannel;
> > >      map<int, QString> inputTuneTo;
> > >      map<int, QString> externalChanger;
> > > +    map<int, QString> inputRadio;
> > >      // returns index of channame (channel.channum) in curList
> > >
> > >      QString channelorder;
> > > Index: mythtv/libs/libmythtv/tv_rec.cpp
> > > ===================================================================
> > > RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_rec.cpp,v
> > > retrieving revision 1.126
> > > diff -u -r1.126 tv_rec.cpp
> > > --- mythtv/libs/libmythtv/tv_rec.cpp	9 Jan 2004 21:02:13 -0000
> > > 1.126
> > > +++ mythtv/libs/libmythtv/tv_rec.cpp	10 Jan 2004 18:11:06 -0000
> > > @@ -2072,14 +2072,16 @@
> > >
> > >  void TVRec::RetrieveInputChannels(map<int, QString> &inputChannel,
> > >                                    map<int, QString> &inputTuneTo,
> > > -                                  map<int, QString> &externalChanger)
> > > +                                  map<int, QString> &externalChanger,
> > > +                                  map<int, QString> &inputRadio)
> > >  {
> > >      pthread_mutex_lock(&db_lock);
> > >      MythContext::KickDatabase(db_conn);
> > >
> > >      QString query = QString("SELECT inputname, trim(externalcommand),
> > > " "if(tunechan='', 'Undefined', tunechan), " -                         
> > >   "if(startchan, startchan, '') "
> > > +                            "if(startchan, startchan, ''), "
> > > +                            "radiodevice "
> > >                              "FROM capturecard, cardinput "
> > >                              "WHERE capturecard.cardid = %1 "
> > >                              "AND capturecard.cardid =
> > > cardinput.cardid;") @@ -2104,6 +2106,7 @@
> > >              externalChanger[cap] = result.value(1).toString();
> > >              inputTuneTo[cap] = result.value(2).toString();
> > >              inputChannel[cap] = result.value(3).toString();
> > > +            inputRadio[cap] = result.value(4).toString();
> > >          }
> > >      }
> > >
> > > Index: mythtv/libs/libmythtv/tv_rec.h
> > > ===================================================================
> > > RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_rec.h,v
> > > retrieving revision 1.47
> > > diff -u -r1.47 tv_rec.h
> > > --- mythtv/libs/libmythtv/tv_rec.h	30 Dec 2003 07:05:23 -0000	1.47
> > > +++ mythtv/libs/libmythtv/tv_rec.h	10 Jan 2004 18:11:06 -0000
> > > @@ -75,7 +75,8 @@
> > >
> > >      void RetrieveInputChannels(map<int, QString> &inputChannel,
> > >                                 map<int, QString> &inputTuneTo,
> > > -                               map<int, QString> &externalChanger);
> > > +                               map<int, QString> &externalChanger,
> > > +                               map<int, QString> &inputRadio);
> > >      void StoreInputChannels(map<int, QString> &inputChannel);
> > >
> > >      bool IsBusy(void);
> >
> > ______________________________________________________________________
> > _______________________________________________
> > mythtv-dev mailing list
> > mythtv-dev at mythtv.org
> > http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-dev

-- 
Howard Dean for America
http://www.DeanForAmerica.com



More information about the mythtv-dev mailing list