[mythtv] [PATCH] Beginning radio pvr support
Dan Sheridan
djs52 at postman.org.uk
Sat Jan 10 13:22:02 EST 2004
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);
More information about the mythtv-dev
mailing list