[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