[mythtv] Directv and channel changing problem
Andy Davidoff
dert at pobox.com
Tue Mar 11 05:37:46 EST 2003
Here's an updated version with GUI widgets for setup/setup, persistent
last-viewed channel, and a few fixes as pointed out by Isaac.
#if Andy Davidoff /* Mar 11, 00:55 */
> I'd greatly appreciate it if those with multiple inputs could test
> this and let me know of anything fishy. I'd like to eliminate the
> DefaultTVChannel option by simply saving the last channel tuned to
> in the new cardinput columns.
#endif /* dert at pobox.com */
-------------- next part --------------
alter table cardinput add tunechan char(5) not null, add startchan char(5) not null;
-------------- next part --------------
Index: MC/libs/libmythtv/channel.cpp
===================================================================
RCS file: /var/lib/cvs/MC/libs/libmythtv/channel.cpp,v
retrieving revision 1.30
diff -d -u -r1.30 channel.cpp
--- MC/libs/libmythtv/channel.cpp 10 Mar 2003 23:09:20 -0000 1.30
+++ MC/libs/libmythtv/channel.cpp 11 Mar 2003 10:29:57 -0000
@@ -99,6 +99,9 @@
cout << "Probed: " << device << " - " << test.name << endl;
channelnames[i] = test.name;
+ inputChannel[i] = "";
+ inputTuneTo[i] = "";
+ externalChanger[i] = "";
}
struct video_channel vc;
@@ -108,6 +111,10 @@
ioctl(videofd, VIDIOCSCHAN, &vc);
videomode = mode;
+
+ pParent->RetrieveInputChannels( inputChannel,
+ inputTuneTo,
+ externalChanger);
}
void Channel::SetFreqTable(const QString &name)
@@ -144,45 +151,38 @@
if (curchannelname == chan)
return true;
- int finetune = 0;
-
- if (pParent->CheckChannel(this, chan, finetune))
+ if (externalChanger[currentcapchannel].isEmpty())
{
+ int i = GetCurrentChannelNum(chan);
+ if (i == -1 || !TuneTo(chan))
+ return false;
+ }
+ else if (!ChangeExternalChannel(chan))
+ return false;
- if (GetCurrentInput() == "Television")
- {
- int i = GetCurrentChannelNum(chan);
- if (i == -1)
- return false;
+ curchannelname = chan;
+ pParent->SetVideoFiltersForChannel(this, chan);
+ SetContrast();
+ SetColour();
+ SetBrightness();
+ inputChannel[currentcapchannel] = curchannelname;
- int frequency = curList[i].freq * 16 / 1000 + finetune;
- if (ioctl(videofd, VIDIOCSFREQ, &frequency) == -1)
- perror("channel set:");
+ return true;
+}
- curchannelname = chan;
+bool Channel::TuneTo(const QString &chan)
+{
+ int finetune;
- pParent->SetVideoFiltersForChannel(this, chan);
- SetContrast();
- SetColour();
- SetBrightness();
- return true;
- }
- else
- {
- if (pParent->ChangeExternalChannel(chan))
- {
- curchannelname = chan;
+ if (!pParent->CheckChannel(this, chan, finetune))
+ return false;
- pParent->SetVideoFiltersForChannel(this, chan);
- SetContrast();
- SetColour();
- SetBrightness();
- return true;
- }
- }
- }
+ int i = GetCurrentChannelNum(chan);
+ int frequency = curList[i].freq * 16 / 1000 + finetune;
+ if (ioctl(videofd, VIDIOCSFREQ, &frequency) == -1)
+ perror("channel set:");
- return false;
+ return true;
}
int Channel::GetCurrentChannelNum(const QString &channame)
@@ -289,41 +289,72 @@
void Channel::ToggleInputs(void)
{
- currentcapchannel++;
- if (currentcapchannel >= capchannels)
- currentcapchannel = 0;
+ int newcapchannel = currentcapchannel;
- struct video_channel set;
- memset(&set, 0, sizeof(set));
- ioctl(videofd, VIDIOCGCHAN, &set);
- set.channel = currentcapchannel;
- set.norm = videomode;
- ioctl(videofd, VIDIOCSCHAN, &set);
+ do {
+ newcapchannel = (newcapchannel+1) % capchannels;
+ } while (inputTuneTo[newcapchannel].isEmpty());
+
+ SwitchToInput(newcapchannel, true);
}
-void Channel::SwitchToInput(const QString &input)
+QString Channel::GetInputByNum(int capchannel)
{
- int inputnum = 0;
- for (int i = 0; i < capchannels; i++)
- {
+ if (capchannel > capchannels)
+ return "";
+ return channelnames[capchannel];
+}
+
+int Channel::GetInputByName(const QString &input)
+{
+ for (int i = capchannels-1; i >= 0; i--)
if (channelnames[i] == input)
- inputnum = i;
+ return i;
+ return -1;
+}
+
+void Channel::SwitchToInput(const QString &inputname)
+{
+ int input = GetInputByName(inputname);
+
+ if (input >= 0)
+ SwitchToInput(input, true);
+}
+
+void Channel::SwitchToInput(const QString &inputname, const QString &chan)
+{
+ int input = GetInputByName(inputname);
+
+ if (input >= 0)
+ {
+ SwitchToInput(input, false);
+ SetChannelByString(chan);
}
+}
- if (inputnum == currentcapchannel)
+void Channel::SwitchToInput(int newcapchannel, bool setstarting)
+{
+ if (newcapchannel == currentcapchannel)
return;
- currentcapchannel = inputnum;
-
struct video_channel set;
memset(&set, 0, sizeof(set));
ioctl(videofd, VIDIOCGCHAN, &set);
- set.channel = currentcapchannel;
+ set.channel = newcapchannel;
set.norm = videomode;
if (ioctl(videofd, VIDIOCSCHAN, &set) < 0)
{
perror("VIDIOCSCHAN: ");
}
+
+ currentcapchannel = newcapchannel;
+ curchannelname = "";
+
+ if (inputTuneTo[currentcapchannel] != "Undefined")
+ TuneTo(inputTuneTo[currentcapchannel]);
+
+ if (setstarting && !inputChannel[currentcapchannel].isEmpty())
+ SetChannelByString(inputChannel[currentcapchannel]);
}
void Channel::SetContrast()
@@ -583,3 +614,21 @@
return vid_pic.colour;
}
+bool Channel::ChangeExternalChannel(const QString &channum)
+{
+ if (externalChanger[currentcapchannel].isEmpty())
+ return false;
+
+ QString command = QString("%1 %2")
+ .arg(externalChanger[currentcapchannel])
+ .arg(channum);
+ cout << "External channel change: " << command << endl;
+ system(command.ascii());
+
+ return true;
+}
+
+void Channel::StoreInputChannels(void)
+{
+ pParent->StoreInputChannels(inputChannel);
+}
Index: MC/libs/libmythtv/channel.h
===================================================================
RCS file: /var/lib/cvs/MC/libs/libmythtv/channel.h,v
retrieving revision 1.16
diff -d -u -r1.16 channel.h
--- MC/libs/libmythtv/channel.h 10 Mar 2003 23:09:20 -0000 1.16
+++ MC/libs/libmythtv/channel.h 11 Mar 2003 10:29:57 -0000
@@ -38,9 +38,16 @@
void ToggleInputs(void);
void SwitchToInput(const QString &input);
+ void SwitchToInput(const QString &input, const QString &chan);
+ void SwitchToInput(int newcapchannel, bool setstarting);
+ bool TuneTo(const QString &chan);
+ bool ChangeExternalChannel(const QString &newchan);
+ void StoreInputChannels(void);
QString GetCurrentName(void);
QString GetCurrentInput(void);
+ int GetInputByName(const QString &input);
+ QString GetInputByNum(int capchannel);
void SetFd(int fd) { videofd = fd; }
QString GetDevice() { return device; }
@@ -65,6 +72,9 @@
int capchannels;
int currentcapchannel;
map<int, QString> channelnames;
+ map<int, QString> inputTuneTo;
+ map<int, QString> externalChanger;
+ map<int, QString> inputChannel;
QString channelorder;
};
Index: MC/libs/libmythtv/tv_rec.cpp
===================================================================
RCS file: /var/lib/cvs/MC/libs/libmythtv/tv_rec.cpp,v
retrieving revision 1.48
diff -d -u -r1.48 tv_rec.cpp
--- MC/libs/libmythtv/tv_rec.cpp 11 Mar 2003 04:07:19 -0000 1.48
+++ MC/libs/libmythtv/tv_rec.cpp 11 Mar 2003 10:29:58 -0000
@@ -30,7 +30,7 @@
return NULL;
}
-TVRec::TVRec(const QString &startchannel, int capturecardnum)
+TVRec::TVRec(int capturecardnum, const QString &input, const QString &startchannel)
{
db_conn = NULL;
channel = NULL;
@@ -59,9 +59,12 @@
channel->Open();
channel->SetFormat(gContext->GetSetting("TVFormat"));
channel->SetFreqTable(gContext->GetSetting("FreqTable"));
- if (inputname != "")
- channel->SwitchToInput(inputname);
- channel->SetChannelByString(startchannel);
+ if (!input.isEmpty())
+ SwitchToInput(input, startchannel);
+ else if (inputname.isEmpty())
+ SwitchToInput(channel->GetCurrentInput(), startchannel);
+ else
+ SwitchToInput(inputname, startchannel);
channel->SetChannelOrdering(chanorder);
channel->Close();
}
@@ -580,8 +583,8 @@
pthread_mutex_unlock(&db_lock);
- channel->SwitchToInput(inputname);
- channel->SetChannelByString(chanstr);
+ if (!chanstr.isEmpty())
+ SwitchToInput(inputname, chanstr);
if (needopen)
channel->Close();
@@ -605,7 +608,11 @@
while (runMainLoop)
{
if (changeState)
+ {
+ if (watchingLiveTV)
+ channel->StoreInputChannels();
HandleStateChange();
+ }
usleep(1000);
@@ -1171,44 +1178,6 @@
return ret;
}
-bool TVRec::ChangeExternalChannel(const QString& channum)
-{
- QString query = QString("SELECT cardinput.externalcommand "
- "FROM cardinput,channel,capturecard "
- "WHERE channel.channum = %1 "
- "AND channel.sourceid = cardinput.sourceid "
- "AND cardinput.inputname = '%2' "
- "AND cardinput.cardid = capturecard.cardid "
- "AND capturecard.videodevice = '%3' "
- "AND capturecard.hostname = \"%4\";")
- .arg(channum).arg(channel->GetCurrentInput())
- .arg(channel->GetDevice())
- .arg(gContext->GetHostName());
-
- QString command(QString::null);
-
- pthread_mutex_lock(&db_lock);
-
- QSqlQuery result = db_conn->exec(query);
- if (!result.isActive())
- MythContext::DBError("changeexternalchannel", result);
- else if (result.numRowsAffected()) {
- result.next();
- command = QString("%1 %2")
- .arg(result.value(0).toString())
- .arg(channum);
-
- }
- pthread_mutex_unlock(&db_lock);
-
- if (command != QString::null) {
- cout << "External channel change: " << command << endl;
- system(command.ascii());
- }
-
- return true;
-}
-
bool TVRec::IsReallyRecording(void)
{
if (nvr && nvr->IsRecording())
@@ -1329,10 +1298,20 @@
UnpauseRingBuffer();
}
+void TVRec::SwitchToInput(QString inputname)
+{
+ channel->SwitchToInput(inputname);
+}
+
+void TVRec::SwitchToInput(QString inputname, QString start)
+{
+ channel->SwitchToInput(inputname, start);
+}
+
void TVRec::ChangeChannel(int channeldirection)
{
rbuffer->Reset();
-
+
if (channeldirection == CHANNEL_DIRECTION_FAVORITE)
channel->NextFavorite();
else if (channeldirection == CHANNEL_DIRECTION_UP)
@@ -1438,18 +1417,14 @@
void TVRec::SetChannel(QString name)
{
- rbuffer->Reset();
-
- QString chan = name.stripWhiteSpace();
- QString prevchan = channel->GetCurrentName();
-
- if (!channel->SetChannelByString(chan))
- channel->SetChannelByString(prevchan);
-
- nvr->Reset();
- nvr->Unpause();
+ if (!name.isEmpty())
+ {
+ QString chan = name.stripWhiteSpace();
+ QString prevchan = channel->GetCurrentName();
- UnpauseRingBuffer();
+ if (!channel->SetChannelByString(chan))
+ channel->SetChannelByString(prevchan);
+ }
}
bool TVRec::CheckChannel(QString name)
@@ -1617,4 +1592,77 @@
comm_breaks);
curRecording->SetCommBreakList(comm_breaks, db_conn);
}
+}
+
+void TVRec::RetrieveInputChannels(map<int, QString> &inputChannel,
+ map<int, QString> &inputTuneTo,
+ map<int, QString> &externalChanger)
+{
+ pthread_mutex_lock(&db_lock);
+ MythContext::KickDatabase(db_conn);
+
+ QString query = QString("SELECT "
+ "inputname, "
+ "trim(externalcommand), "
+ "if(tunechan='', 'Undefined', tunechan), "
+ "if(startchan, startchan, '') "
+ "FROM capturecard, cardinput "
+ "WHERE capturecard.cardid = %1 "
+ "AND capturecard.cardid = cardinput.cardid;")
+ .arg(m_capturecardnum);
+
+ QSqlQuery result = db_conn->exec(query);
+
+ if (!result.isActive())
+ MythContext::DBError("RetrieveInputChannels", result);
+ else if (!result.numRowsAffected())
+ {
+ cerr << "Error getting inputs for the capturecard. Perhaps you have\n"
+ "forgotten to bind video sources to your card's inputs?" << endl;
+ }
+ else
+ {
+ int cap;
+
+ while (result.next())
+ {
+ cap = channel->GetInputByName(result.value(0).toString());
+ externalChanger[cap] = result.value(1).toString();
+ inputTuneTo[cap] = result.value(2).toString();
+ inputChannel[cap] = result.value(3).toString();
+ }
+ }
+
+ pthread_mutex_unlock(&db_lock);
+}
+
+void TVRec::StoreInputChannels(map<int, QString> &inputChannel)
+{
+ QString query, input;
+ QSqlQuery result;
+
+ pthread_mutex_lock(&db_lock);
+ MythContext::KickDatabase(db_conn);
+
+ for (int i = 0;; i++)
+ {
+ input = channel->GetInputByNum(i);
+ if (input.isEmpty())
+ break;
+
+ query = QString("UPDATE cardinput "
+ "set startchan = '%1' "
+ "WHERE cardid = %2 "
+ "AND inputname = '%3';")
+ .arg(inputChannel[i])
+ .arg(m_capturecardnum)
+ .arg(input);
+
+ result = db_conn->exec(query);
+
+ if (!result.isActive())
+ MythContext::DBError("StoreInputChannels", result);
+ }
+
+ pthread_mutex_unlock(&db_lock);
}
Index: MC/libs/libmythtv/tv_rec.h
===================================================================
RCS file: /var/lib/cvs/MC/libs/libmythtv/tv_rec.h,v
retrieving revision 1.22
diff -d -u -r1.22 tv_rec.h
--- MC/libs/libmythtv/tv_rec.h 10 Mar 2003 23:09:20 -0000 1.22
+++ MC/libs/libmythtv/tv_rec.h 11 Mar 2003 10:29:58 -0000
@@ -1,12 +1,15 @@
#ifndef TVREC_H
#define TVREC_H
+#include <map>
#include <qstring.h>
#include <pthread.h>
#include <qdatetime.h>
#include "tv.h"
+using namespace std;
+
class QSqlDatabase;
class QSocket;
class Channel;
@@ -17,7 +20,7 @@
class TVRec
{
public:
- TVRec(const QString &startchannel, int capturecardnum);
+ TVRec(int capturecardnum, const QString &input, const QString &startchannel);
~TVRec(void);
void Init(void);
@@ -41,7 +44,6 @@
bool CheckChannel(Channel *chan, const QString &channum, int &finetuning);
void SetChannelValue(QString &field_name,int value, Channel *chan, const QString &channum);
int GetChannelValue(const QString &channel_field,Channel *chan, const QString &channum);
- bool ChangeExternalChannel(const QString &channum);
bool SetVideoFiltersForChannel(Channel *chan, const QString &channum);
QString GetNextChannel(Channel *chan, int channeldirection);
@@ -58,6 +60,12 @@
void SpawnLiveTV(void);
void StopLiveTV(void);
void PauseRecorder(void);
+ void RetrieveInputChannels(map<int, QString> &inputChannel,
+ map<int, QString> &inputTuneTo,
+ map<int, QString> &externalChanger);
+ void StoreInputChannels(map<int, QString> &inputChannel);
+ void SwitchToInput(QString inputname);
+ void SwitchToInput(QString inputname, QString channel);
void ToggleInputs(void);
void ToggleChannelFavorite(void);
void ChangeChannel(int channeldirection);
Index: MC/libs/libmythtv/videosource.h
===================================================================
RCS file: /var/lib/cvs/MC/libs/libmythtv/videosource.h,v
retrieving revision 1.25
diff -d -u -r1.25 videosource.h
--- MC/libs/libmythtv/videosource.h 10 Mar 2003 23:09:20 -0000 1.25
+++ MC/libs/libmythtv/videosource.h 11 Mar 2003 10:29:58 -0000
@@ -428,6 +428,29 @@
};
};
+class PresetTuner: public LineEditSetting, public CISetting {
+public:
+ PresetTuner(const CardInput& parent):
+ CISetting(parent, "tunechan") {
+ setLabel("Preset tuner to channel");
+ setValue("");
+ setHelpText("If specified, the tuner will change to this channel "
+ "when the input is selected. This is useful if you "
+ "use your tuner input with an external channel changer");
+ };
+};
+
+class StartingChannel: public LineEditSetting, public CISetting {
+public:
+ StartingChannel(const CardInput& parent):
+ CISetting(parent, "startchan") {
+ setLabel("Starting channel");
+ setValue("3");
+ setHelpText("LiveTV will change to the above channel when the "
+ "input is first selected");
+ };
+};
+
class CardInput: public VerticalConfigurationGroup, public ConfigurationDialog {
public:
CardInput() {
@@ -437,6 +460,8 @@
addChild(inputname = new InputName(*this));
addChild(sourceid = new SourceID(*this));
addChild(new ExternalChannelCommand(*this));
+ addChild(new PresetTuner(*this));
+ addChild(new StartingChannel(*this));
};
int getInputID(void) const { return id->intValue(); };
Index: MC/programs/mythbackend/main.cpp
===================================================================
RCS file: /var/lib/cvs/MC/programs/mythbackend/main.cpp,v
retrieving revision 1.17
diff -d -u -r1.17 main.cpp
--- MC/programs/mythbackend/main.cpp 5 Mar 2003 02:27:14 -0000 1.17
+++ MC/programs/mythbackend/main.cpp 11 Mar 2003 10:29:58 -0000
@@ -24,15 +24,19 @@
void setupTVs(bool ismaster)
{
- QString startchannel = gContext->GetSetting("DefaultTVChannel");
- if (startchannel == "")
- startchannel = "3";
-
QString localhostname = gContext->GetHostName();
QSqlQuery query;
- query.exec("SELECT cardid,hostname FROM capturecard ORDER BY cardid;");
+ query.exec( "SELECT "
+ "capturecard.cardid, "
+ "capturecard.hostname, "
+ "capturecard.defaultinput, "
+ "if(cardinput.startchan, cardinput.startchan, '3') "
+ "FROM capturecard, cardinput "
+ "WHERE capturecard.cardid = cardinput.cardid "
+ "AND capturecard.defaultinput = cardinput.inputname "
+ "ORDER BY capturecard.cardid, cardinput.cardinputid;");
if (query.isActive() && query.numRowsAffected())
{
@@ -40,6 +44,8 @@
{
int cardid = query.value(0).toInt();
QString host = query.value(1).toString();
+ QString input = query.value(2).toString();
+ QString startchannel = query.value(3).toString();
if (host.isNull() || host.isEmpty())
{
@@ -53,7 +59,7 @@
{
if (host == localhostname)
{
- TVRec *tv = new TVRec(startchannel, cardid);
+ TVRec *tv = new TVRec(cardid, input, startchannel);
tv->Init();
EncoderLink *enc = new EncoderLink(cardid, tv);
tvList[cardid] = enc;
@@ -63,7 +69,7 @@
{
if (host == localhostname)
{
- TVRec *tv = new TVRec(startchannel, cardid);
+ TVRec *tv = new TVRec(cardid, input, startchannel);
tv->Init();
EncoderLink *enc = new EncoderLink(cardid, tv);
tvList[cardid] = enc;
Index: MC/programs/mythfrontend/globalsettings.cpp
===================================================================
RCS file: /var/lib/cvs/MC/programs/mythfrontend/globalsettings.cpp,v
retrieving revision 1.55
diff -d -u -r1.55 globalsettings.cpp
--- MC/programs/mythfrontend/globalsettings.cpp 5 Mar 2003 22:18:43 -0000 1.55
+++ MC/programs/mythfrontend/globalsettings.cpp 11 Mar 2003 10:29:58 -0000
@@ -726,7 +726,7 @@
public:
DefaultTVChannel():
SpinBoxSetting(1, 1024, 1), GlobalSetting("DefaultTVChannel") {
- setLabel("Starting channel");
+ setLabel("Guide starts at channel");
setValue(3);
};
};
More information about the mythtv-dev
mailing list