-#include <lib/dvb/idvb.h>
#include <lib/base/eerror.h>
+#include <lib/base/filepush.h>
+#include <lib/dvb/idvb.h>
#include <lib/dvb/dvb.h>
#include <lib/dvb/sec.h>
-#include <errno.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <fcntl.h>
DEFINE_REF(eDVBRegisteredFrontend);
DEFINE_REF(eDVBRegisteredDemux);
RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux)
{
- /* find first unused demux which is on same adapter as frontend */
+ /* find first unused demux which is on same adapter as frontend (or any, if PVR) */
for (eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin()); i != m_demux.end(); ++i)
- if ((!i->m_inuse) && (i->m_adapter == fe->m_adapter))
+ if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
{
demux = new eDVBAllocatedDemux(i);
return 0;
return 0;
}
-RESULT eDVBResourceManager::allocatePVRChannel(int caps)
+
+RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
{
- return -1; // will nicht, mag nicht, und das interface ist auch kaputt
+ ePtr<eDVBAllocatedDemux> demux;
+
+ if (allocateDemux(0, demux))
+ return errNoDemux;
+
+ eDVBChannel *ch;
+ ch = new eDVBChannel(this, 0, demux);
+
+ channel = ch;
+ return 0;
}
RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
{
m_frontend = frontend;
m_demux = demux;
+
+ m_pvr_thread = 0;
if (m_frontend)
m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
{
if (m_channel_id)
m_mgr->removeChannel(this);
+
+ if (m_pvr_thread)
+ {
+ m_pvr_thread->stop();
+ delete m_pvr_thread;
+ }
}
void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
else
return -ENODEV;
}
+
+RESULT eDVBChannel::playFile(const char *file)
+{
+ ASSERT(!m_frontend);
+ if (m_pvr_thread)
+ {
+ m_pvr_thread->stop();
+ delete m_pvr_thread;
+ m_pvr_thread = 0;
+ }
+
+ /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
+ THEN DO A REAL FIX HERE! */
+
+
+ /* (this codepath needs to be improved anyway.) */
+ int dest = open("/dev/misc/pvr", O_WRONLY);
+ if (dest < 0)
+ {
+ eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
+ return -ENODEV;
+ }
+
+ int source = open(file, O_RDONLY);
+ if (source < 0)
+ {
+ eDebug("can't open PVR source file %s (%m)", file);
+ close(dest);
+ return -ENOENT;
+ }
+
+ m_state = state_ok;
+ m_stateChanged(this);
+
+ m_pvr_thread = new eFilePushThread();
+ m_pvr_thread->start(source, dest);
+}
/* allocate channel... */
RESULT allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel);
RESULT allocateRawChannel(eUsePtr<iDVBChannel> &channel);
- RESULT allocatePVRChannel(int caps);
+ RESULT allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel);
RESULT connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection);
RESULT connectChannelRemoved(const Slot1<void,eDVBChannel*> &channelRemoved, ePtr<eConnection> &connection);
RESULT connectChannelRunning(const Slot1<void,iDVBChannel*> &channelRemoved, ePtr<eConnection> &connection);
};
-class eDVBChannel: public iDVBChannel, public Object
+class eFilePushThread;
+
+ /* iDVBPVRChannel includes iDVBChannel. don't panic. */
+class eDVBChannel: public iDVBPVRChannel, public Object
{
DECLARE_REF(eDVBChannel);
private:
void frontendStateChanged(iDVBFrontend*fe);
ePtr<eConnection> m_conn_frontendStateChanged;
+
+ /* for PVR playback */
+ eFilePushThread *m_pvr_thread;
friend class eUsePtr<eDVBChannel>;
/* use count */
virtual ~eDVBChannel();
/* only for managed channels - effectively tunes to the channelid. should not be used... */
+ /* cannot be used for PVR channels. */
RESULT setChannel(const eDVBChannelID &id);
eDVBChannelID getChannelID() { return m_channel_id; }
RESULT setCIRouting(const eDVBCIRouting &routing);
RESULT getDemux(ePtr<iDVBDemux> &demux);
RESULT getFrontend(ePtr<iDVBFrontend> &frontend);
+
+ /* iDVBPVRChannel */
+ RESULT playFile(const char *file);
};
#endif
virtual void ReleaseUse() = 0;
};
+class iDVBPVRChannel: public iDVBChannel
+{
+public:
+ enum
+ {
+ state_eof = state_release + 1 /* end-of-file reached. */
+ };
+
+ /* FIXME: there are some very ugly buffer-end and ... related problems */
+ /* so this is VERY UGLY. */
+ virtual RESULT playFile(const char *file) = 0;
+};
+
class iDVBSectionReader;
class iDVBTSRecorder;
class iTSMPEGDecoder;
int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref)
{
RESULT res;
- m_channel = 0;
- m_channelStateChanged_connection = 0;
m_reference = ref;
- eDVBChannelID chid;
- ref.getChannelID(chid);
- res = m_resourceManager->allocateChannel(chid, m_channel);
- eDebug("eDVBServicePMTHandler: tune %d", res);
+
+// ref.path = "/viva.ts"; // hrhr.
+
+ /* is this a normal (non PVR) channel? */
+ if (ref.path.empty())
+ {
+ eDVBChannelID chid;
+ ref.getChannelID(chid);
+ res = m_resourceManager->allocateChannel(chid, m_channel);
+ } else
+ {
+ eDebug("alloc PVR");
+ /* allocate PVR */
+ res = m_resourceManager->allocatePVRChannel(m_pvr_channel);
+ if (res)
+ eDebug("allocatePVRChannel failed!\n");
+ m_channel = m_pvr_channel;
+ }
+
if (m_channel)
{
m_channel->connectStateChange(
m_last_channel_state = -1;
channelStateChanged(m_channel);
}
+
+ if (m_pvr_channel)
+ m_pvr_channel->playFile(ref.path.c_str());
+
return res;
}
eAUTable<eTable<ProgramAssociationTable> > m_PAT;
eUsePtr<iDVBChannel> m_channel;
+ eUsePtr<iDVBPVRChannel> m_pvr_channel;
ePtr<eDVBResourceManager> m_resourceManager;
ePtr<iDVBDemux> m_demux;