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