Hi guys,

The attached patch contains the initial framework for HDHomeRun support.

Watching live TV gives a picture but it does not have code to control the box yet.

Any feedback is welcome... if there are any issues I it would be good to know before I get too deep into the control code :-)

Thanks,

Nick
Index: configure
===================================================================
--- configure   (revision 8590)
+++ configure   (working copy)
@@ -55,6 +55,7 @@
 joystick_menu="yes"
 firewire_cable_box="yes"
 dbox2_dvb_box="yes"
+hdhomerun_box="yes"
 x11_include_path="/usr/X11R6/include"
 x11="yes"
 xrandr="yes"
@@ -173,6 +174,7 @@
 echo "  --disable-joystick-menu  disable joystick menu"
 echo "  --disable-firewire       disable support for FireWire cable boxes"
 echo "  --disable-dbox2          disable support for Nokia DBOX2 DVB boxes (or 
compatibles)"
+echo "  --disable-hdhomerun      disable support for HDHomeRun boxes"
 echo "  --disable-v4l            disable Video4Linux support"
 echo "  --disable-ivtv           disable ivtv support (PVR-x50) req. v4l 
support"
 #echo "  --enable-ivtv-sys-header use ivtv system headers instead of myth 
headers"
@@ -440,6 +442,7 @@
 dv1394="no"
 ivtv="no"
 dbox2_dvb_box="no"
+hdhomerun_box="no"
 dvb="no"
 backend="no"
 make="gmake"
@@ -788,6 +791,10 @@
   ;;
   --disable-dbox2) dbox2_dvb_box="no"
   ;;
+  --enable-hdhomerun) hdhomerun_box="yes"
+  ;;
+  --disable-hdhomerun) hdhomerun_box="no"
+  ;;
   --enable-dvb) dvb="yes"
   ;;
   --disable-dvb) dvb="no"
@@ -2188,6 +2195,7 @@
   echo "FireWire support $firewire_cable_box"
   echo "DVB support      $dvb [$dvb_path]"
   echo "DBox2 support    $dbox2_dvb_box"
+  echo "HDHomeRun support $hdhomerun_box"
 fi
 
 if test x"$frontend" = x"yes" ; then
@@ -2762,6 +2770,7 @@
     ivtv="no"
     ivtv_header="no"
     dbox2_dvb_box="no"
+    hdhomerun_box="no"
     dvb="no"
     dvb_eit="no"
 fi
@@ -2805,6 +2814,11 @@
   CONFIG_DEFINES="$CONFIG_DEFINES USING_DBOX2"
 fi
 
+if test x"$hdhomerun_box" = x"yes" ; then
+  CCONFIG="$CCONFIG using_hdhomerun"
+  CONFIG_DEFINES="$CONFIG_DEFINES USING_HDHOMERUN"
+fi
+
 if test x"$lirc" = x"yes" ; then
   CCONFIG="$CCONFIG using_lirc"
   echo "CONFIG_LIRC_LIBS=-llirc_client" >> $MYTH_CONFIG_MAK
Index: libs/libmythtv/hdhomerunrecorder.h
===================================================================
--- libs/libmythtv/hdhomerunrecorder.h  (revision 0)
+++ libs/libmythtv/hdhomerunrecorder.h  (revision 0)
@@ -0,0 +1,43 @@
+/**
+ *  HDHomeRunRecorder
+ *  Copyright (c) 2006 by Silicondust Engineering Ltd.
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef HDHOMERUNRECORDER_H_
+#define HDHOMERUNRECORDER_H_
+
+#include "dtvrecorder.h"
+#include "mpeg/tspacket.h"
+#include "hdhomerunchannel.h"
+
+class HDHomeRunRecorder : public DTVRecorder
+{
+Q_OBJECT
+public:
+    HDHomeRunRecorder(TVRec *rec, HDHomeRunChannel *channel);
+    ~HDHomeRunRecorder();
+
+    void SetOption(const QString &name, int value);
+    void SetOptionsFromProfile(RecordingProfile *profile,
+                               const QString &videodev,
+                               const QString &audiodev,
+                               const QString &vbidev);
+
+    bool Open(void);
+    void Close(void);
+
+    void StartRecording(void);
+
+public slots:
+    void deleteLater(void);
+    
+private:
+    HDHomeRunChannel *m_channel;
+    int VideoSock;
+
+    void TeardownAll(void);
+    void ReceiveTSData(void);
+};
+
+#endif
Index: libs/libmythtv/hdhomerunrecorder.cpp
===================================================================
--- libs/libmythtv/hdhomerunrecorder.cpp        (revision 0)
+++ libs/libmythtv/hdhomerunrecorder.cpp        (revision 0)
@@ -0,0 +1,160 @@
+/**
+ *  HDHomeRunRecorder
+ *  Copyright (c) 2006 by Silicondust Engineering Ltd.
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+// C includes
+#include <pthread.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <netinet/in.h>    // For sockaddr_in on OS X
+
+// C++ includes
+#include <iostream>
+using namespace std;
+
+// MythTV includes
+#include "RingBuffer.h"
+#include "hdhomerunrecorder.h"
+
+HDHomeRunRecorder::HDHomeRunRecorder(TVRec *rec, HDHomeRunChannel *channel)
+    : DTVRecorder(rec, "HDHomeRunRecorder")
+{
+    m_channel = channel;
+    VideoSock = -1;
+}
+
+HDHomeRunRecorder::~HDHomeRunRecorder()
+{
+    TeardownAll();
+}
+
+void HDHomeRunRecorder::TeardownAll(void)
+{
+    StopRecording();
+    Close();
+}
+
+void HDHomeRunRecorder::deleteLater(void)
+{
+    TeardownAll();
+    DTVRecorder::deleteLater();
+}
+
+void HDHomeRunRecorder::SetOption(const QString &name, int value)
+{
+}
+
+void HDHomeRunRecorder::SetOptionsFromProfile(RecordingProfile*, 
+                                        const QString &videodev,
+                                        const QString &audiodev,
+                                        const QString &vbidev)
+{
+}
+
+bool HDHomeRunRecorder::Open(void)
+{
+    if (VideoSock != -1) {
+        VERBOSE(VB_GENERAL, QString("Card already open"));
+        return true;
+    }
+
+    /* Create TS socket. */
+    VideoSock = socket(AF_INET, SOCK_DGRAM, 0);
+    if (VideoSock == -1) {
+        VERBOSE(VB_IMPORTANT, QString("Unable to create socket for TS"));
+        return false;
+    }
+
+    /* Bind socket. */
+    struct sockaddr_in SockAddr;
+    memset(&SockAddr, 0, sizeof(SockAddr));
+    SockAddr.sin_family = AF_INET;
+    SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    SockAddr.sin_port = htons(5002); /* Quick hack for testing - this should 
be "any" and then passed to tuner. */
+    if (bind(VideoSock, (struct sockaddr *)&SockAddr, sizeof(SockAddr)) != 0) {
+        VERBOSE(VB_IMPORTANT, QString("Unable to bind TS socket"));
+        Close();
+        return false;
+    }
+
+    /* Success. */
+    return true;
+}
+
+void HDHomeRunRecorder::Close(void)
+{
+    if (VideoSock != -1) {
+        close(VideoSock);
+        VideoSock = -1;
+    }
+}
+
+void HDHomeRunRecorder::ReceiveTSData(void)
+{
+    uint8_t Buffer[188 * 7];
+    int Length = recv(VideoSock, (char *)Buffer, sizeof(Buffer), 0);
+    if (Length <= 0) {
+        return;
+    }
+
+    uint8_t *Data = Buffer;
+    uint8_t *End = Buffer + Length;
+    while (Data + 188 <= End) {
+        if (Data[0] != 0x47) {
+            return;
+        }
+        const TSPacket *tspacket = reinterpret_cast<const TSPacket*>(Data);
+
+        _buffer_packets = !FindKeyframes(tspacket);
+        BufferedWrite(*tspacket);
+
+        Data += 188;
+    }
+}
+
+void HDHomeRunRecorder::StartRecording(void)
+{
+    VERBOSE(VB_RECORD, QString("StartRecording"));
+
+    if (!Open()) {
+        VERBOSE(VB_GENERAL, QString("Error starting recording. Aborting."));
+        _error = true;
+        return;
+    }
+
+    _request_recording = true;
+    _recording = true;
+
+    while (_request_recording && !_error) {
+        if (PauseAndWait()) {
+            continue;
+        }
+
+        fd_set ReadFDs;
+        FD_ZERO(&ReadFDs);
+        FD_SET(VideoSock, &ReadFDs);
+
+        struct timeval t;
+        t.tv_sec = 0;
+        t.tv_usec = 100000;
+
+        if (select(VideoSock+1, &ReadFDs, NULL, NULL, &t) < 0) {
+            VERBOSE(VB_IMPORTANT, QString("Socket/select error. Aborting"));
+            break;
+        }
+
+        if (FD_ISSET(VideoSock, &ReadFDs)) {
+            ReceiveTSData();
+       }
+    }
+
+    Close();
+    FinishRecording();
+    _recording = false;
+}
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro        (revision 8590)
+++ libs/libmythtv/libmythtv.pro        (working copy)
@@ -261,6 +261,10 @@
     using_dbox2:SOURCES += dbox2recorder.cpp dbox2channel.cpp dbox2epg.cpp
     using_dbox2:HEADERS += dbox2recorder.h dbox2channel.h dbox2epg.h
 
+    # Support for HDHomeRun box
+    using_hdhomerun:SOURCES += hdhomerunrecorder.cpp hdhomerunchannel.cpp
+    using_hdhomerun:HEADERS += hdhomerunrecorder.h hdhomerunchannel.h
+
     # Support for PVR-150/250/350/500, etc. on Linux
     using_ivtv:HEADERS += mpegrecorder.h
     using_ivtv:SOURCES += mpegrecorder.cpp
Index: libs/libmythtv/videosource.cpp
===================================================================
--- libs/libmythtv/videosource.cpp      (revision 8590)
+++ libs/libmythtv/videosource.cpp      (working copy)
@@ -1390,8 +1390,38 @@
      CaptureCard& parent;
  };
 
+class HDHomeRunDeviceID: public LineEditSetting, public CCSetting {
+public:
+    HDHomeRunDeviceID(const CaptureCard& parent):
+    CCSetting(parent, "dbox2_host") {
+        setValue("00000000");
+        setLabel(QObject::tr("Device ID"));
+        setHelpText(QObject::tr("Device ID from the back of the HDHomeRun 
unit."));
+    }
+};
 
+class HDHomeRunTunerIndex: public ComboBoxSetting, public CCSetting
+{
+public:
+    HDHomeRunTunerIndex(const CaptureCard& parent):
+    CCSetting(parent, "dbox2_port") {
+        setLabel(QObject::tr("Tuner"));
+        addSelection("0");
+        addSelection("1");
+    }
+};
 
+class HDHomeRunConfigurationGroup: public VerticalConfigurationGroup {
+public:
+    HDHomeRunConfigurationGroup(CaptureCard& a_parent):
+    parent(a_parent) {
+        setUseLabel(false);
+        addChild(new HDHomeRunDeviceID(parent));
+        addChild(new HDHomeRunTunerIndex(parent));
+    };
+private:
+    CaptureCard& parent;
+};
 
 class V4LConfigurationGroup: public VerticalConfigurationGroup
 {
@@ -1485,6 +1515,7 @@
     addTarget("MPEG", new MPEGConfigurationGroup(parent));
     addTarget("FIREWIRE", new FirewireConfigurationGroup(parent));
     addTarget("DBOX2", new DBOX2ConfigurationGroup(parent));
+    addTarget("HDHOMERUN", new HDHomeRunConfigurationGroup(parent));
 }
 
 void CaptureCardGroup::triggerChanged(const QString& value) 
@@ -1536,6 +1567,14 @@
                     "Http-Port: " + query.value(7).toString() + 
                     "] ", query.value(2).toString());
            }
+            else if (query.value(0).toString() == "HDHOMERUN")
+            {
+                setting->addSelection(
+                    "[ " + query.value(0).toString() + " : " + 
+                           query.value(6).toString() + "/" +
+                           query.value(5).toString() + " ]",
+                           query.value(2).toString());
+           }
             else 
             {
                 setting->addSelection(
@@ -1581,6 +1620,8 @@
         "GO7007");
     setting->addSelection(
         QObject::tr("DBox2 TCP/IP cable box"), "DBOX2");
+    setting->addSelection(
+        QObject::tr("HDHomeRun DTV tuner box"), "HDHOMERUN");
 }
 
 class CardID: public SelectLabelSetting, public CISetting {
@@ -2366,6 +2407,28 @@
                     addSelection(label, index);
                 }
             }
+            else if (capturecards.value(2).toString() == "HDHOMERUN")
+            {
+                inputs = QStringList("MPEG2TS");
+                for (QStringList::iterator i = inputs.begin();
+                     i != inputs.end(); ++i)
+                { 
+                    CardInput* cardinput = new CardInput(false);
+                    cardinput->loadByInput(cardid, *i);   
+                    cardinputs.push_back(cardinput);
+                    QString index = QString::number(cardinputs.size()-1);
+
+                    QString label;
+                    label = QString("%1 (%2) -> %3")
+                        .arg("[ " + capturecards.value(2).toString() + " " +
+                             capturecards.value(7).toString() + "/" +
+                             capturecards.value(6).toString() +
+                             " ]")
+                        .arg(*i)
+                        .arg(cardinput->getSourceName());
+                    addSelection(label, index);
+                }
+            }
             else
             {
                 inputs = VideoDevice::probeInputs(videodevice);
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp   (revision 8590)
+++ libs/libmythtv/tv_rec.cpp   (working copy)
@@ -68,6 +68,11 @@
 #include "dbox2channel.h"
 #endif
 
+#ifdef USING_HDHOMERUN
+#include "hdhomerunrecorder.h"
+#include "hdhomerunchannel.h"
+#endif
+
 #define LOC QString("TVRec(%1): ").arg(cardid)
 #define LOC_ERR QString("TVRec(%1) Error: ").arg(cardid)
 
@@ -180,6 +185,16 @@
         init_run = true;
 #endif
     }
+    else if (genOpt.cardtype == "HDHOMERUN")
+    {
+#ifdef USING_HDHOMERUN
+        channel = new HDHomeRunChannel(this);
+        channel->Open();
+        VERBOSE(VB_IMPORTANT, QString("HDHomeRun start channel: 
'%1'").arg(startchannel));
+        InitChannel(genOpt.defaultinput, startchannel);
+        init_run = true;
+#endif
+    }
     else if (genOpt.cardtype == "MPEG" &&
              genOpt.videodev.lower().left(5) == "file:")
     {
@@ -814,6 +829,12 @@
         recorder->SetOption("httpport", dboxOpt.httpport);
 #endif // USING_DBOX2
     }
+    else if (genOpt.cardtype == "HDHOMERUN")
+    {
+#ifdef USING_HDHOMERUN
+        recorder = new HDHomeRunRecorder(this, GetHDHomeRunChannel());
+#endif // USING_HDHOMERUN
+    }
     else if (genOpt.cardtype == "DVB")
     {
 #ifdef USING_DVB
@@ -1023,6 +1044,15 @@
 #endif // USING_DBOX2
 }
 
+HDHomeRunChannel *TVRec::GetHDHomeRunChannel(void)
+{
+#ifdef USING_HDHOMERUN
+    return dynamic_cast<HDHomeRunChannel*>(channel);
+#else
+    return NULL;
+#endif // USING_HDHOMERUN
+}
+
 DVBChannel *TVRec::GetDVBChannel(void)
 {
 #ifdef USING_DVB
Index: libs/libmythtv/hdhomerunchannel.cpp
===================================================================
--- libs/libmythtv/hdhomerunchannel.cpp (revision 0)
+++ libs/libmythtv/hdhomerunchannel.cpp (revision 0)
@@ -0,0 +1,53 @@
+/**
+ *  DBox2Channel
+ *  Copyright (c) 2006 by Silicondust Engineering Ltd.
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include <iostream>
+#include <qsqldatabase.h>
+#include "mythdbcon.h"
+#include "mythcontext.h"
+#include "hdhomerunchannel.h"
+
+HDHomeRunChannel::HDHomeRunChannel(TVRec *parent)
+    : QObject(NULL, "HDHomeRunChannel"), ChannelBase(parent)
+{
+    channelnames[0] = "MPEG2TS";
+    currentcapchannel = 0;
+
+    OpenState = false;
+}
+
+HDHomeRunChannel::~HDHomeRunChannel(void)
+{
+}
+
+bool HDHomeRunChannel::Open(void)
+{
+    OpenState = true;
+    return true;
+}
+
+void HDHomeRunChannel::Close(void)
+{
+    OpenState = false;
+}
+
+bool HDHomeRunChannel::SetChannelByString(const QString &chan)
+{
+    VERBOSE(VB_IMPORTANT, QString("HDHomeRunChannel->SetChannelByString: 
'%1'").arg(chan));
+    curchannelname = chan;
+    return true;
+}
+
+bool HDHomeRunChannel::SwitchToInput(const QString &inputname, const QString 
&chan)
+{
+    currentcapchannel = 0;
+    return SetChannelByString(chan);
+}
+
+bool HDHomeRunChannel::SwitchToInput(int newcapchannel, bool setstarting)
+{
+    return false;
+}
Index: libs/libmythtv/tv_rec.h
===================================================================
--- libs/libmythtv/tv_rec.h     (revision 8590)
+++ libs/libmythtv/tv_rec.h     (working copy)
@@ -32,6 +32,7 @@
 
 class ChannelBase;
 class DBox2Channel;
+class HDHomeRunChannel;
 class DVBChannel;
 class Channel;
 
@@ -251,6 +252,7 @@
     void InitChannel(const QString &inputname, const QString &startchannel);
     void CloseChannel(void);
     DBox2Channel *GetDBox2Channel(void);
+    HDHomeRunChannel *GetHDHomeRunChannel(void);
     DVBChannel   *GetDVBChannel(void);
     Channel      *GetV4LChannel(void);
 
Index: libs/libmythtv/hdhomerunchannel.h
===================================================================
--- libs/libmythtv/hdhomerunchannel.h   (revision 0)
+++ libs/libmythtv/hdhomerunchannel.h   (revision 0)
@@ -0,0 +1,35 @@
+/**
+ *  Dbox2Channel
+ *  Copyright (c) 2006 by Silicondust Engineering Ltd.
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef HDHOMERUNCHANNEL_H
+#define HDHOMERUNCHANNEL_H
+
+#include <qstring.h>
+
+#include "mythcontext.h"
+#include "mythdbcon.h"
+#include "channelbase.h"
+
+class HDHomeRunChannel : public QObject, public ChannelBase
+{
+    Q_OBJECT
+public:
+    HDHomeRunChannel(TVRec *parent);
+    ~HDHomeRunChannel(void);
+
+    bool Open(void);
+    void Close(void);
+    bool IsOpen(void) const { return OpenState; }
+
+    bool SetChannelByString(const QString &chan);
+    bool SwitchToInput(const QString &inputname, const QString &chan);
+    bool SwitchToInput(int newcapchannel, bool setstarting);
+
+private:
+    bool OpenState;
+};
+
+#endif
_______________________________________________
mythtv-dev mailing list
[email protected]
http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-dev

Reply via email to