Index: libs/libmythtv/freeboxsignalmonitor.cpp
===================================================================
--- libs/libmythtv/freeboxsignalmonitor.cpp	(revision 10961)
+++ libs/libmythtv/freeboxsignalmonitor.cpp	(working copy)
@@ -2,8 +2,9 @@
 
 // MythTV headers
 #include "mpegstreamdata.h"
+#include "freeboxchannel.h"
+#include "freeboxfeederwrapper.h"
 #include "freeboxsignalmonitor.h"
-#include "rtspcomms.h"
 
 #undef DBG_SM
 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
@@ -34,11 +35,10 @@
       dtvMonitorRunning(false)
 {
     bool isLocked = false;
-    if (GetChannel()->GetRTSP()->Init())
+    FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo();
+    if (chaninfo.isValid())
     {
-        FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo();
-        isLocked = (chaninfo.isValid() && 
-                    GetChannel()->GetRTSP()->Open(chaninfo.m_url));
+        isLocked = GetChannel()->GetFeeder()->Open(chaninfo.m_url);
     }
 
     QMutexLocker locker(&statusLock);
@@ -51,7 +51,7 @@
  */
 FreeboxSignalMonitor::~FreeboxSignalMonitor()
 {
-    GetChannel()->GetRTSP()->RemoveListener(this);
+    GetChannel()->GetFeeder()->RemoveListener(this);
     Stop();
 }
 
@@ -63,7 +63,7 @@
 void FreeboxSignalMonitor::deleteLater(void)
 {
     disconnect(); // disconnect signals we may be sending...
-    GetChannel()->GetRTSP()->RemoveListener(this);
+    GetChannel()->GetFeeder()->RemoveListener(this);
     Stop();
     DTVSignalMonitor::deleteLater();
 }
@@ -74,11 +74,11 @@
 void FreeboxSignalMonitor::Stop(void)
 {
     DBG_SM("Stop", "begin");
-    GetChannel()->GetRTSP()->RemoveListener(this);
+    GetChannel()->GetFeeder()->RemoveListener(this);
     SignalMonitor::Stop();
     if (dtvMonitorRunning)
     {
-        GetChannel()->GetRTSP()->Stop();
+        GetChannel()->GetFeeder()->Stop();
         dtvMonitorRunning = false;
         pthread_join(table_monitor_thread, NULL);
     }
@@ -101,18 +101,17 @@
 
     GetStreamData()->AddListeningPID(0);
 
-    GetChannel()->GetRTSP()->AddListener(this);
-    GetChannel()->GetRTSP()->Run();
-    GetChannel()->GetRTSP()->RemoveListener(this);
+    GetChannel()->GetFeeder()->AddListener(this);
+    GetChannel()->GetFeeder()->Run();
+    GetChannel()->GetFeeder()->RemoveListener(this);
 
     dtvMonitorRunning = false;
     DBG_SM("Run", "end");
 }
 
-void FreeboxSignalMonitor::AddData(
-    unsigned char *data, unsigned dataSize, struct timeval)
+void FreeboxSignalMonitor::ProcessTSPacket(const TSPacket &packet)
 {
-    GetStreamData()->ProcessData(data, dataSize);
+    GetStreamData()->ProcessTSPacket(packet);
 }
 
 /** \fn FreeboxSignalMonitor::UpdateValues(void)
Index: libs/libmythtv/freeboxfeederudp.cpp
===================================================================
--- libs/libmythtv/freeboxfeederudp.cpp	(revision 0)
+++ libs/libmythtv/freeboxfeederudp.cpp	(revision 0)
@@ -0,0 +1,130 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederUdp
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "freeboxfeederudp.h"
+
+// Qt headers
+#include <qurl.h>
+
+// Live555 headers
+#include <BasicUsageEnvironment.hh>
+#include <Groupsock.hh>
+#include <GroupsockHelper.hh>
+#include <BasicUDPSource.hh>
+#include <TunnelEncaps.hh>
+
+// MythTV headers
+#include "freeboxmediasink.h"
+#include "mythcontext.h"
+#include "tspacket.h"
+
+#define LOC QString("FbFeedUdp(%1):").arg(pthread_self())
+
+
+FEEDERREG_IMPL(FreeboxFeederUdp,"udp://");
+    
+
+FreeboxFeederUdp::FreeboxFeederUdp(StreamDataListener &listener) :
+    FreeboxFeederLive(listener),
+    _source(NULL),
+    _sink(NULL)
+{
+    VERBOSE(VB_RECORD, LOC + "ctor -- success");
+}
+
+FreeboxFeederUdp::~FreeboxFeederUdp()
+{
+    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
+    Close();
+    VERBOSE(VB_RECORD, LOC + "dtor -- end");
+}
+
+bool FreeboxFeederUdp::Open(const QString &url)
+{
+    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
+
+    QMutexLocker locker(&GetLock());
+
+    if (_source)
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
+        return true;
+    }
+        
+    QUrl parse(url);
+    if (!parse.isValid() || !parse.hasHost() || !parse.hasPort())
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
+        return false;
+    }
+        
+    struct in_addr addr;
+    addr.s_addr = our_inet_addr(parse.host().latin1());
+
+    // Begin by setting up our usage environment:
+    if (!InitEnv())
+        return false;
+    
+    Groupsock *socket = new Groupsock(GetLiveEnv(), addr, parse.port(), 0);
+    if (!socket)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Socket.");
+        FreeEnv();
+        return false;
+    }
+    _source = BasicUDPSource::createNew(GetLiveEnv(), socket);
+    if (!_source)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Source.");
+        delete socket;
+        FreeEnv();
+        return false;
+    }
+
+    _sink = FreeboxMediaSink::CreateNew(
+        GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024);
+    if (!_sink)
+    {
+        VERBOSE(VB_IMPORTANT,
+                QString("Freebox # Failed to create sink: %1")
+                .arg(GetLiveEnv().getResultMsg()));
+        Medium::close(_source);
+        _source = NULL;
+        delete socket;
+        FreeEnv();
+        return false;
+    }
+    _sink->startPlaying(*_source, NULL, NULL);
+        
+    VERBOSE(VB_RECORD, LOC + "Open() -- end");
+    return true;
+}
+
+void FreeboxFeederUdp::Close(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
+    Stop();
+
+    QMutexLocker locker(&GetLock());
+
+    if (_sink)
+    {
+        Medium::close(_sink);
+        _sink = NULL;
+    }
+
+    if (_source)
+    {
+        Groupsock *socket=_source->gs();
+        Medium::close(_source);
+        _source=NULL;
+        delete socket;
+    }
+
+    FreeEnv();
+
+    VERBOSE(VB_RECORD, LOC + "Close() -- end");
+}
Index: libs/libmythtv/tspacketsplitter.h
===================================================================
--- libs/libmythtv/tspacketsplitter.h	(revision 0)
+++ libs/libmythtv/tspacketsplitter.h	(revision 0)
@@ -0,0 +1,40 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederUdp
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _TSPACKETSPLITTER_H_
+#define _TSPACKETSPLITTER_H_
+
+#include "streamdatalistener.h"
+
+class TSPacketListener;
+
+
+class TSPacketSplitter : public StreamDataListener
+{
+  public:
+    explicit TSPacketSplitter(TSPacketListener &listener);
+    ~TSPacketSplitter();
+
+    void Reset(void);
+    
+  public: // implements StreamDataListener
+    void AddData(unsigned char *data, unsigned int dataSize);
+
+  private:
+    TSPacketListener &_listener;
+    unsigned char    *_buffer;
+    int               _bufferIndex;
+
+  private:
+    /// avoid default copy operator
+    TSPacketSplitter& operator=(const TSPacketSplitter&);
+    /// avoid default copy constructor
+    TSPacketSplitter(const TSPacketSplitter&);
+    /// avoid default constructor
+    TSPacketSplitter();
+};
+
+#endif//_TSPACKETSPLITTER_H_
Index: libs/libmythtv/streamdatalistener.h
===================================================================
--- libs/libmythtv/streamdatalistener.h	(revision 0)
+++ libs/libmythtv/streamdatalistener.h	(revision 0)
@@ -0,0 +1,21 @@
+/** -*- Mode: c++ -*-
+ *  StreamDataListener
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+ 
+#ifndef _STREAMDATALISTENER_H_
+#define _STREAMDATALISTENER_H_
+
+
+class StreamDataListener
+{
+  public:
+    /// Callback function to add MPEG2 TS data
+    virtual void AddData(unsigned char *data,
+                         unsigned int   dataSize) = 0;
+  protected:
+    virtual ~StreamDataListener() {}
+};
+
+#endif//_STREAMDATALISTENER_H_
Index: libs/libmythtv/freeboxfeederfile.h
===================================================================
--- libs/libmythtv/freeboxfeederfile.h	(revision 0)
+++ libs/libmythtv/freeboxfeederfile.h	(revision 0)
@@ -0,0 +1,43 @@
+/** -*- Mode: c++ -*
+ *  FreeboxFeederFile
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef FREEBOXFEEDERFILE_H
+#define FREEBOXFEEDERFILE_H
+
+// MythTV headers
+#include "freeboxfeederlive.h"
+#include "freeboxfeederwrapper.h"
+
+class ByteStreamFileSource;
+class FreeboxMediaSink;
+
+
+class FreeboxFeederFile : public FreeboxFeederLive
+{
+  public:
+    FreeboxFeederFile(StreamDataListener &listener);
+    virtual ~FreeboxFeederFile();
+
+    bool Open(const QString &url);
+    bool IsOpen(void) const { return _source; }
+    void Close(void);
+
+  private:
+    ByteStreamFileSource    *_source;
+    FreeboxMediaSink        *_sink;
+
+  private:
+    /// avoid default copy operator
+    FreeboxFeederFile& operator=(const FreeboxFeederFile&);
+    /// avoid default copy constructor
+    FreeboxFeederFile(const FreeboxFeederFile&);
+    /// avoid default constructor
+    FreeboxFeederFile();
+    
+  FEEDERREG_DECL
+};
+
+#endif//FREEBOXFEEDERFILE_H
Index: libs/libmythtv/freeboxchannel.h
===================================================================
--- libs/libmythtv/freeboxchannel.h	(revision 10961)
+++ libs/libmythtv/freeboxchannel.h	(working copy)
@@ -12,7 +12,7 @@
 
 #include <qmutex.h>
 
-class RTSPComms;
+class FreeboxFeederWrapper;
 
 class FreeboxChannel : public ChannelBase
 {
@@ -32,8 +32,8 @@
     FreeboxChannelInfo GetCurrentChanInfo(void) const
         { return GetChanInfo(curchannelname); }
 
-    RTSPComms       *GetRTSP(void)       { return m_rtsp; }
-    const RTSPComms *GetRTSP(void) const { return m_rtsp; }
+    FreeboxFeederWrapper       *GetFeeder(void)       { return m_feeder; }
+    const FreeboxFeederWrapper *GetFeeder(void) const { return m_feeder; }
     
   private:
     FreeboxChannelInfo GetChanInfo(const QString& channum,
@@ -41,7 +41,7 @@
 
     QString               m_videodev;
     fbox_chan_map_t       m_freeboxchannels;
-    RTSPComms            *m_rtsp;
+    FreeboxFeederWrapper *m_feeder;
     mutable QMutex        m_lock;
 
   private:
Index: libs/libmythtv/freeboxchannelfetcher.h
===================================================================
--- libs/libmythtv/freeboxchannelfetcher.h	(revision 10961)
+++ libs/libmythtv/freeboxchannelfetcher.h	(working copy)
@@ -7,10 +7,31 @@
 // Qt headers
 #include <qobject.h>
 #include <qmutex.h>
+#include <qurloperator.h>
 
 // MythTV headers
 #include "freeboxchannelinfo.h"
 
+class FreeboxUrlFetch : public QObject
+{
+    Q_OBJECT
+
+  private:
+    FreeboxUrlFetch(const QString& url);
+    ~FreeboxUrlFetch();
+
+    QUrlOperator *op;
+    QNetworkProtocol::State state;
+    QString str;
+
+  private slots:
+    void finished(QNetworkOperation *op);
+    void data(const QByteArray &data,QNetworkOperation *op);
+
+  public:
+    static QString fetchData(const QString &url,bool inQtThread);
+};
+
 class FreeboxChannelFetcher : public QObject
 {
     Q_OBJECT
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro	(revision 10961)
+++ libs/libmythtv/libmythtv.pro	(working copy)
@@ -396,12 +396,21 @@
     using_freebox {
         HEADERS += freeboxrecorder.h           freeboxmediasink.h
         HEADERS += freeboxchannel.h            freeboxchannelfetcher.h
-        HEADERS += freeboxsignalmonitor.h      rtspcomms.h
-        HEADERS += freeboxchannelinfo.h
+        HEADERS += freeboxsignalmonitor.h      freeboxchannelinfo.h
+        HEADERS += freeboxfeeder.h             freeboxfeederlive.h
+        HEADERS += freeboxfeederrtsp.h         freeboxfeederudp.h
+        HEADERS += freeboxfeederfile.h         freeboxfeederwrapper.h
+        HEADERS += streamdatalistener.h        timeoutedtaskscheduler.h
+        HEADERS += tspacketlistener.h          tspacketsplitter.h
+        HEADERS += freeboxfeederrtp.h
 
         SOURCES += freeboxrecorder.cpp         freeboxmediasink.cpp
         SOURCES += freeboxchannel.cpp          freeboxchannelfetcher.cpp
-        SOURCES += freeboxsignalmonitor.cpp    rtspcomms.cpp
+        SOURCES += freeboxsignalmonitor.cpp    freeboxfeederwrapper.cpp
+        SOURCES += freeboxfeederlive.cpp       freeboxfeederrtsp.cpp
+        SOURCES += freeboxfeederudp.cpp        freeboxfeederfile.cpp
+        SOURCES += timeoutedtaskscheduler.cpp  tspacketsplitter.cpp
+        SOURCES += freeboxfeederrtp.cpp
 
         DEFINES += USING_FREEBOX
     }
Index: libs/libmythtv/freeboxchannel.cpp
===================================================================
--- libs/libmythtv/freeboxchannel.cpp	(revision 10961)
+++ libs/libmythtv/freeboxchannel.cpp	(working copy)
@@ -11,7 +11,7 @@
 #include "libmyth/mythcontext.h"
 #include "libmyth/mythdbcon.h"
 #include "libmythtv/freeboxchannelfetcher.h"
-#include "libmythtv/rtspcomms.h"
+#include "libmythtv/freeboxfeederwrapper.h"
 
 #define LOC QString("FBChan(%1): ").arg(GetCardID())
 #define LOC_ERR QString("FBChan(%1), Error: ").arg(GetCardID())
@@ -20,7 +20,7 @@
                                const QString &videodev)
     : ChannelBase(parent),
       m_videodev(QDeepCopy<QString>(videodev)),
-      m_rtsp(new RTSPComms()),
+      m_feeder(new FreeboxFeederWrapper()),
       m_lock(true)
 {
     VERBOSE(VB_CHANNEL, LOC + "ctor");
@@ -29,10 +29,10 @@
 FreeboxChannel::~FreeboxChannel()
 {
     VERBOSE(VB_CHANNEL, LOC + "dtor -- begin");
-    if (m_rtsp)
+    if (m_feeder)
     {
-        delete m_rtsp;
-        m_rtsp = NULL;
+        delete m_feeder;
+        m_feeder = NULL;
     }
     VERBOSE(VB_CHANNEL, LOC + "dtor -- end");
 }
@@ -193,7 +193,7 @@
         }
 
         // Try to map name to a channel in the map
-        const QString name    = query.value(1).toString();
+        const QString name = QString::fromUtf8(query.value(1).toString());
         for (it = m_freeboxchannels.begin();
              it != m_freeboxchannels.end(); ++it)
         {
Index: libs/libmythtv/freeboxfeederlive.cpp
===================================================================
--- libs/libmythtv/freeboxfeederlive.cpp	(revision 0)
+++ libs/libmythtv/freeboxfeederlive.cpp	(revision 0)
@@ -0,0 +1,93 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederLive -- base class for livemedia based FreeboxFeeders
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "freeboxfeederlive.h"
+
+#include <cassert>
+
+// MythTV headers
+#include "mythcontext.h"
+#include "timeoutedtaskscheduler.h"
+
+#define LOC QString("FbFeedLive(%1):").arg(pthread_self())
+#define LOC_ERR QString("FbFeedLive(%1), Error:").arg(pthread_self())
+
+
+FreeboxFeederLive::FreeboxFeederLive(StreamDataListener &listener) :
+    _abort(0),
+    _running(false),
+    _live_env(NULL),
+    _lock(false),
+    _listener(listener)
+{
+}
+
+FreeboxFeederLive::~FreeboxFeederLive()
+{
+}
+
+bool FreeboxFeederLive::InitEnv(void)
+{
+    TaskScheduler *scheduler = new TimeoutedTaskScheduler(500);
+    if (!scheduler)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create Live Scheduler.");
+        return false;
+    }
+
+    assert(_live_env==NULL);
+    _live_env = BasicUsageEnvironment::createNew(*scheduler);
+    if (!_live_env)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create Live Environment.");
+        delete scheduler;
+        return false;
+    }
+    
+    return true;
+}
+
+void FreeboxFeederLive::FreeEnv(void)
+{
+    if (_live_env)
+    {
+        TaskScheduler *scheduler = &_live_env->taskScheduler();
+        _live_env->reclaim();
+        _live_env = NULL;
+        delete scheduler;
+    }
+}
+
+void FreeboxFeederLive::Run(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Run() -- begin");
+    _lock.lock();
+    _running = true;
+    _abort   = 0;
+    _lock.unlock();
+
+    VERBOSE(VB_RECORD, LOC + "Run() -- loop begin");
+    if (_live_env)
+        _live_env->taskScheduler().doEventLoop(&_abort);
+    VERBOSE(VB_RECORD, LOC + "Run() -- loop end");
+
+    _lock.lock();
+    _running = false;
+    _cond.wakeAll();
+    _lock.unlock();
+    VERBOSE(VB_RECORD, LOC + "Run() -- end");
+}
+
+void FreeboxFeederLive::Stop(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Stop() -- begin");
+    QMutexLocker locker(&_lock);
+    _abort = 0xFF;
+
+    while (_running)
+        _cond.wait(&_lock, 500);
+    VERBOSE(VB_RECORD, LOC + "Stop() -- end");
+}
Index: libs/libmythtv/freeboxmediasink.cpp
===================================================================
--- libs/libmythtv/freeboxmediasink.cpp	(revision 10961)
+++ libs/libmythtv/freeboxmediasink.cpp	(working copy)
@@ -4,20 +4,21 @@
  *  Distributed as part of MythTV under GPL v2 and later.
  */
 
-#include <algorithm>
-using namespace std;
-
-#include "mythcontext.h"
 #include "freeboxmediasink.h"
-#include "rtspcomms.h"
+#include "mythcontext.h"
+#include "streamdatalistener.h"
 
-#define LOC QString("RTSPSink:")
-#define LOC_ERR QString("RTSPSink, Error:")
+#define LOC QString("FbxSink:")
+#define LOC_ERR QString("FbxSink, Error:")
 
-FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment &pEnv,
-                                   unsigned int      bufferSize) :
-    MediaSink(pEnv),    fBufferSize(bufferSize),
-    env(pEnv),          lock(true)
+FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment   &pEnv,
+                                   StreamDataListener &listener,
+                                   unsigned int        bufferSize) :
+    MediaSink(pEnv),
+    fBufferSize(bufferSize),
+    env(pEnv),
+    _listener(listener),
+    lock(true)
 {
     fBuffer = new unsigned char[fBufferSize];
 }
@@ -31,10 +32,11 @@
     }
 }
 
-FreeboxMediaSink *FreeboxMediaSink::CreateNew(UsageEnvironment &env,
-                                              unsigned int      bufferSize)
+FreeboxMediaSink *FreeboxMediaSink::CreateNew(UsageEnvironment   &env,
+                                              StreamDataListener &listener,
+                                              unsigned int        bufferSize)
 {
-    return new FreeboxMediaSink(env, bufferSize);
+    return new FreeboxMediaSink(env, listener, bufferSize);
 }
 
 Boolean FreeboxMediaSink::continuePlaying(void)
@@ -61,41 +63,10 @@
 }
 
 void FreeboxMediaSink::afterGettingFrame1(unsigned int   frameSize,
-                                          struct timeval presentationTime)
+                                          struct timeval)
 {
-    lock.lock();
-    vector<RTSPListener*>::iterator it = listeners.begin();
-    for (; it != listeners.end(); ++it)
-        (*it)->AddData(fBuffer, frameSize, presentationTime);
-    lock.unlock();
-
+    _listener.AddData(fBuffer, frameSize);
     continuePlaying();
 }
 
-void FreeboxMediaSink::AddListener(RTSPListener *item)
-{
-    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
-    if (item)
-    {
-        RemoveListener(item);
-        QMutexLocker locker(&lock);
-        listeners.push_back(item);
-    }
-    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
-}
-
-void FreeboxMediaSink::RemoveListener(RTSPListener *item)
-{
-    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin 1");
-    QMutexLocker locker(&lock);
-    vector<RTSPListener*>::iterator it =
-        find(listeners.begin(), listeners.end(), item);
-    if (it != listeners.end())
-    {
-        *it = *listeners.rbegin();
-        listeners.resize(listeners.size() - 1);
-    }
-    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 6");
-}
-
 /* vim: set expandtab tabstop=4 shiftwidth=4: */
Index: libs/libmythtv/freeboxsignalmonitor.h
===================================================================
--- libs/libmythtv/freeboxsignalmonitor.h	(revision 10961)
+++ libs/libmythtv/freeboxsignalmonitor.h	(working copy)
@@ -4,12 +4,12 @@
 #define _FREEBOXSIGNALMONITOR_H_
 
 #include "dtvsignalmonitor.h"
-#include "freeboxmediasink.h"
+#include "tspacketlistener.h"
 
-class RTSPComms;
 class FreeboxChannel;
 
-class FreeboxSignalMonitor : public DTVSignalMonitor, public RTSPListener
+
+class FreeboxSignalMonitor : public DTVSignalMonitor, public TSPacketListener
 {
     Q_OBJECT
 
@@ -21,10 +21,8 @@
 
     void Stop(void);
 
-    // implements RTSPListener
-    void AddData(unsigned char *data,
-                 unsigned       dataSize,
-                 struct timeval);
+    // implements TSPacketListener
+    void ProcessTSPacket(const TSPacket &packet);
 
   public slots:
     void deleteLater(void);
Index: libs/libmythtv/freeboxfeederwrapper.cpp
===================================================================
--- libs/libmythtv/freeboxfeederwrapper.cpp	(revision 0)
+++ libs/libmythtv/freeboxfeederwrapper.cpp	(revision 0)
@@ -0,0 +1,228 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederWrapper
+ *  Copyright (c) 2006 by Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include <qstring.h>
+#include <vector>
+
+#include "freeboxfeederwrapper.h"
+
+#include "freeboxfeeder.h"
+#include "mythcontext.h"
+
+#define LOC QString("FBFeed: ")
+#define LOC_ERR QString("FBFeed, Error: ")
+
+// Registration of feeders
+class FreeboxRegistratorSinglton
+{
+  public:
+    static FreeboxRegistratorSinglton &getInstance(void);
+
+    void Register(FreeboxFeederWrapper::CanHandleFn,
+                  FreeboxFeederWrapper::FeederConstructorFn);
+    FreeboxFeeder *CreateNew(const QString &url, StreamDataListener &listener);
+    bool HaveHandler(const QString &url);
+
+  private:
+    // default construct is private to force use of getInstance()
+    FreeboxRegistratorSinglton() {}
+    FreeboxFeederWrapper::FeederConstructorFn GetConstructor(const QString &);
+
+  private:
+    typedef std::pair<FreeboxFeederWrapper::CanHandleFn,
+            FreeboxFeederWrapper::FeederConstructorFn> FuncPair;
+    std::vector<FuncPair> _regdata;
+
+  private:
+    // avoid default copy operator
+    FreeboxRegistratorSinglton &operator=(const FreeboxRegistratorSinglton&);
+    // avoid default copy constructor
+    FreeboxRegistratorSinglton(const FreeboxRegistratorSinglton&);
+};
+
+FreeboxRegistratorSinglton &FreeboxRegistratorSinglton::getInstance()
+{
+    static FreeboxRegistratorSinglton instance = FreeboxRegistratorSinglton();
+    return instance;
+}
+
+void FreeboxRegistratorSinglton::Register(
+        FreeboxFeederWrapper::CanHandleFn f1,
+        FreeboxFeederWrapper::FeederConstructorFn f2)
+{
+    _regdata.push_back(FuncPair(f1,f2));
+}
+
+FreeboxFeederWrapper::FeederConstructorFn 
+    FreeboxRegistratorSinglton::GetConstructor(const QString &url)
+{
+    std::vector<FuncPair>::const_iterator it = _regdata.begin();
+    std::vector<FuncPair>::const_iterator end = _regdata.end();
+    for( ; it!=end ; ++it )
+        if (it->first(url))
+            return it->second;
+    return NULL;
+}
+
+FreeboxFeeder *FreeboxRegistratorSinglton::CreateNew(
+        const QString      &url,
+        StreamDataListener &listener)
+{
+    FreeboxFeederWrapper::FeederConstructorFn func = GetConstructor(url);
+    return func ? func(listener) : NULL;
+}
+
+bool FreeboxRegistratorSinglton::HaveHandler(const QString &url)
+{
+    return GetConstructor(url);
+}
+
+
+
+void FreeboxFeederWrapper::RegisterHandler(
+        CanHandleFn         f1,
+        FeederConstructorFn f2)
+{
+    FreeboxRegistratorSinglton::getInstance().Register(f1,f2);
+}
+
+bool FreeboxFeederWrapper::HaveHandler(const QString &url)
+{
+    return FreeboxRegistratorSinglton::getInstance().HaveHandler(url);
+}
+
+FreeboxFeederWrapper::FreeboxFeederWrapper() :
+    _splitter(*this),
+    _feeder(NULL)
+{
+}
+
+FreeboxFeederWrapper::~FreeboxFeederWrapper()
+{
+    if (_feeder)
+    {
+        _feeder->Stop();
+        _feeder->Close();
+        delete _feeder;
+    }
+}
+
+FreeboxFeeder* FreeboxFeederWrapper::NewFeeder(const QString      &url,
+                                               StreamDataListener &listener)
+{
+    FreeboxFeeder *result = FreeboxRegistratorSinglton::getInstance()
+        .CreateNew(url,listener);
+    if (!result)
+    {
+        VERBOSE(VB_RECORD, LOC_ERR +
+            QString("NewFeeder() -- unhandled url (%1)").arg(url));
+    }
+    return result;
+}
+
+bool FreeboxFeederWrapper::InitFeeder(const QString &url)
+{
+    VERBOSE(VB_RECORD, LOC + "Init() -- begin");
+    QMutexLocker locker(&_lock);
+    if (_feeder && _feeder->CanHandle(url))
+    {
+        VERBOSE(VB_RECORD, LOC + "Init() -- end 0");
+        return true;
+    }
+
+    delete _feeder;
+    _feeder = NewFeeder(url, _splitter);
+
+    VERBOSE(VB_RECORD, LOC + "Init() -- end 1");
+    return _feeder != NULL;
+}
+
+bool FreeboxFeederWrapper::Open(const QString& url)
+{
+    VERBOSE(VB_RECORD, LOC + "Open() -- begin");
+    _splitter.Reset();
+    bool result = InitFeeder(url) && _feeder->Open(url);
+    VERBOSE(VB_RECORD, LOC + "Open() -- end");
+    return result;
+}
+
+bool FreeboxFeederWrapper::IsOpen(void) const
+{
+    VERBOSE(VB_RECORD, LOC + "IsOpen() -- begin");
+    bool result = _feeder && _feeder->IsOpen();
+    VERBOSE(VB_RECORD, LOC + "IsOpen() -- end");
+    return result;
+}
+
+void FreeboxFeederWrapper::Close(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
+    _splitter.Reset();
+    if (_feeder) _feeder->Close();
+    VERBOSE(VB_RECORD, LOC + "Close() -- end");
+}
+
+void FreeboxFeederWrapper::Run(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Run() -- begin");
+    _splitter.Reset();
+    if (_feeder) _feeder->Run();
+    VERBOSE(VB_RECORD, LOC + "Run() -- end");
+}
+
+void FreeboxFeederWrapper::Stop(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Stop() -- begin");
+    _splitter.Reset();
+    if (_feeder) _feeder->Stop();
+    VERBOSE(VB_RECORD, LOC + "Stop() -- end");
+}
+
+void FreeboxFeederWrapper::AddListener(TSPacketListener *item)
+{
+    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
+    if (!item)
+    {
+        VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 0");
+        return;
+    }
+
+    QMutexLocker locker(&_lock);
+    std::vector<TSPacketListener*>::iterator it =
+        find(_listeners.begin(), _listeners.end(), item);
+    if (it == _listeners.end()) // avoid duplicates
+        _listeners.push_back(item);
+
+    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 1");
+}
+
+void FreeboxFeederWrapper::RemoveListener(TSPacketListener *item)
+{
+    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
+    QMutexLocker locker(&_lock);
+    std::vector<TSPacketListener*>::iterator it =
+        find(_listeners.begin(), _listeners.end(), item);
+
+    if (it == _listeners.end())
+    {
+        VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end (not found)");
+        return;
+    }
+
+    // remove from local list..
+    *it = *_listeners.rbegin();
+    _listeners.resize(_listeners.size() - 1);
+    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end (ok, removed)");
+}
+
+void FreeboxFeederWrapper::ProcessTSPacket(const TSPacket &packet)
+{
+    QMutexLocker locker(&_lock);
+    std::vector<TSPacketListener*>::iterator it = _listeners.begin();
+    std::vector<TSPacketListener*>::iterator end = _listeners.end();
+    for( ; it!=end ; ++it )
+        (*it)->ProcessTSPacket(packet);
+}
Index: libs/libmythtv/freeboxchannelfetcher.cpp
===================================================================
--- libs/libmythtv/freeboxchannelfetcher.cpp	(revision 10961)
+++ libs/libmythtv/freeboxchannelfetcher.cpp	(working copy)
@@ -4,12 +4,17 @@
 #include <cmath>
 #include <unistd.h>
 
+// Qt headers
+#include <qnetwork.h>
+#include <qapplication.h>
+
 // MythTV headers
 #include "mythcontext.h"
 #include "httpcomms.h"
 #include "cardutil.h"
 #include "channelutil.h"
 #include "freeboxchannelfetcher.h"
+#include "freeboxfeederwrapper.h"
 
 #define LOC QString("FBChanFetch: ")
 #define LOC_ERR QString("FBChanFetch, Error: ")
@@ -21,6 +26,54 @@
 static bool parse_extinf(const QString &data,
                          QString &channum, QString &name);
 
+FreeboxUrlFetch::FreeboxUrlFetch(const QString& url)
+    :   op(new QUrlOperator(url)),
+    state(QNetworkProtocol::StInProgress),
+    str("")
+{
+    connect(op,   SIGNAL( finished(QNetworkOperation *)),
+            this, SLOT(   finished(QNetworkOperation *)));
+    connect(op,   SIGNAL( data(const QByteArray &,QNetworkOperation *)),
+            this, SLOT(   data(const QByteArray &,QNetworkOperation *)));
+    op->get();
+}
+
+FreeboxUrlFetch::~FreeboxUrlFetch()
+{
+    disconnect();
+    delete op;
+    op=NULL;
+}
+
+void FreeboxUrlFetch::finished(QNetworkOperation *op)
+{
+    state = op->state();
+}
+
+void FreeboxUrlFetch::data(const QByteArray &data,QNetworkOperation *op)
+{
+    if (!data.isNull())
+        str += QString::fromUtf8(data.data(),data.size());
+    state = op->state();
+}
+
+QString FreeboxUrlFetch::fetchData(const QString &url,bool inQtThread)
+{
+    FreeboxUrlFetch obj(url);
+    while(obj.state==QNetworkProtocol::StWaiting ||
+            obj.state==QNetworkProtocol::StInProgress)
+    {
+        if (inQtThread)
+            qApp->processEvents();
+        usleep(1000);
+    }
+    if (obj.state==QNetworkProtocol::StDone)
+        return obj.str;
+    else // QNetworkProtocol::StFailed || QNetworkProtocol::StStopped
+        return QString::null;
+}
+
+
 FreeboxChannelFetcher::FreeboxChannelFetcher(unsigned _sourceid,
                                              unsigned _cardid) :
     sourceid(_sourceid),    cardid(_cardid),
@@ -177,21 +230,25 @@
 QString FreeboxChannelFetcher::DownloadPlaylist(const QString &url,
                                                 bool inQtThread)
 {
-    QString redirected_url = url;
+    if (url.startsWith("http:")) {
+        // Use Myth HttpComms for http URLs
+        QString redirected_url = url;
 
-    QString tmp = HttpComms::getHttp(
-        redirected_url,
-        10000 /* ms        */, 3     /* retries      */,
-        3     /* redirects */, true  /* allow gzip   */,
-        NULL  /* login     */, inQtThread);
+        QString tmp = HttpComms::getHttp(
+            redirected_url,
+            10000 /* ms        */, 3     /* retries      */,
+            3     /* redirects */, true  /* allow gzip   */,
+            NULL  /* login     */, inQtThread);
 
-    if (redirected_url != url)
-    {
-        VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1")
-                .arg(redirected_url));
-    }
+        if (redirected_url != url)
+        {
+            VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1")
+                    .arg(redirected_url));
+        }
 
-    return QString::fromUtf8(tmp);
+        return QString::fromUtf8(tmp);
+    } else
+        return FreeboxUrlFetch::fetchData(url,inQtThread);
 }
 
 static uint estimate_number_of_channels(const QString &rawdata)
@@ -251,13 +308,21 @@
         QString msg = tr("Encountered malformed channel");
         if (!channum.isEmpty())
         {
-            chanmap[channum] = info;
-
-            msg = tr("Parsing Channel #%1 : %2 : %3")
-                .arg(channum).arg(info.m_name).arg(info.m_url);
-            VERBOSE(VB_CHANNEL, msg);
-
-            msg = QString::null; // don't tell fetcher
+            if (FreeboxFeederWrapper::HaveHandler(info.m_url))
+            {
+                chanmap[channum] = info;
+    
+                msg = tr("Parsing Channel #%1 : %2 : %3")
+                    .arg(channum).arg(info.m_name).arg(info.m_url);
+                VERBOSE(VB_CHANNEL, msg);
+    
+                msg = QString::null; // don't tell fetcher
+            }
+            else
+            {
+                msg = tr("Unhandled url %1").arg(info.m_url);
+                VERBOSE(VB_CHANNEL, msg);
+            }
         }
 
         if (fetcher)
Index: libs/libmythtv/tspacketsplitter.cpp
===================================================================
--- libs/libmythtv/tspacketsplitter.cpp	(revision 0)
+++ libs/libmythtv/tspacketsplitter.cpp	(revision 0)
@@ -0,0 +1,129 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederUdp
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include <cassert>
+
+#include "tspacketsplitter.h"
+
+#include "mythcontext.h"
+#include "tspacket.h"
+#include "tspacketlistener.h"
+
+#define LOC_ERR QString("TSSplit, Error: ")
+#define LOC_WARN QString("TSSplit, Warning: ")
+
+
+TSPacketSplitter::TSPacketSplitter(TSPacketListener &listener) :
+    _listener(listener),
+    _buffer(new unsigned char[TSPacket::SIZE]),
+    _bufferIndex(0)
+{
+}
+
+TSPacketSplitter::~TSPacketSplitter()
+{
+    delete[] _buffer;
+}
+
+void TSPacketSplitter::Reset(void)
+{
+    _bufferIndex = 0;
+}
+
+// ===================================================
+// findTSHeader : find a TS Header in flow
+// ===================================================
+static int TSPacketSplitter_findTSHeader(const unsigned char *data,
+                                             uint dataSize)
+{
+    //TODO improve this with code from MPEGStreamData::ResyncStream()
+    for(unsigned pos = 0; pos < dataSize; ++pos)
+        if (data[pos] == 0x47)
+            return pos;
+
+    return -1;
+}
+
+// ===================================================
+// AddData : feed data from flow to listeners
+// ===================================================
+void TSPacketSplitter::AddData(unsigned char *data,
+                               unsigned       dataSize)
+{
+    if (_bufferIndex)
+    {
+        // Have old data in buffer
+        unsigned reminder = TSPacket::SIZE - _bufferIndex;
+        memcpy(_buffer + _bufferIndex, data, min(reminder, dataSize));
+        if (dataSize < reminder)
+        {
+            _bufferIndex += dataSize;
+            return;
+        }
+        else
+        {
+            // We got full packet
+            data += reminder;
+            dataSize -= reminder;
+            // Cast current found TS Packet to TSPacket structure
+            const TSPacket &packet = *reinterpret_cast<const TSPacket*>(_buffer);
+            _listener.ProcessTSPacket(packet);
+        }
+    }
+
+    unsigned int readIndex = 0;
+    
+    // data may be compose from more than one packet, loop to consume all data
+    while (readIndex < dataSize)
+    {
+        // Find the next TS Header in data
+        int tsPos = TSPacketSplitter_findTSHeader(
+                        data + readIndex, dataSize - readIndex);
+
+        // if no TS, something bad happens
+        if (-1 == tsPos)
+        {
+            readIndex = dataSize;
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "No TS header.");
+            break;
+        }
+
+        // if TS Header not at start of data, we receive out of sync data
+        if (tsPos > 0)
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    QString("TS packet at %1, not in sync.").arg(tsPos));
+        }
+
+        // Check if the next packet in buffer is complete :
+        // packet size is 188 bytes long
+        if ((dataSize - tsPos - readIndex) < TSPacket::SIZE)
+        {
+            readIndex += tsPos;
+            VERBOSE(VB_IMPORTANT, LOC_ERR +
+                    "TS packet at stradles end of buffer.");
+            break;
+        }
+
+        // Cast current found TS Packet to TSPacket structure
+        const void *p = data + tsPos + readIndex;
+        const TSPacket &packet = *reinterpret_cast<const TSPacket*>(p);
+        _listener.ProcessTSPacket(packet);
+
+        // follow to next packet
+        readIndex += tsPos + TSPacket::SIZE;
+    }
+
+    // write in buffer synced data
+    if (readIndex < dataSize)
+    {
+        assert(dataSize - readIndex < TSPacket::SIZE);
+        memcpy(_buffer, data + readIndex, dataSize - readIndex);
+        _bufferIndex = dataSize - readIndex;
+    }
+    else
+        _bufferIndex = 0;
+}
Index: libs/libmythtv/freeboxfeederrtsp.h
===================================================================
--- libs/libmythtv/freeboxfeederrtsp.h	(revision 0)
+++ libs/libmythtv/freeboxfeederrtsp.h	(revision 0)
@@ -0,0 +1,43 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederRtsp
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef FREEBOXFEEDERRTSP_H
+#define FREEBOXFEEDERRTSP_H
+
+// MythTV headers
+#include "freeboxfeederwrapper.h"
+#include "freeboxfeederlive.h"
+
+class RTSPClient;
+class MediaSession;
+
+
+class FreeboxFeederRtsp : public FreeboxFeederLive
+{
+  public:
+    FreeboxFeederRtsp(StreamDataListener &listener);
+    virtual ~FreeboxFeederRtsp();
+
+    bool Open(const QString &url);
+    bool IsOpen(void) const { return _session; }
+    void Close(void);
+
+  private:
+    RTSPClient         *_rtsp_client;
+    MediaSession       *_session;
+
+  private:
+    /// avoid default copy operator
+    FreeboxFeederRtsp& operator=(const FreeboxFeederRtsp&);
+    /// avoid default copy constructor
+    FreeboxFeederRtsp(const FreeboxFeederRtsp&);
+    /// avoid default constructor
+    FreeboxFeederRtsp();
+    
+  FEEDERREG_DECL
+};
+
+#endif//FREEBOXFEEDERRTSP_H
Index: libs/libmythtv/freeboxfeederfile.cpp
===================================================================
--- libs/libmythtv/freeboxfeederfile.cpp	(revision 0)
+++ libs/libmythtv/freeboxfeederfile.cpp	(revision 0)
@@ -0,0 +1,117 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederFile
+ *
+ *  Please, don't submit bug reports if it
+ *  can't read your file. Just use MythVideo!
+ *
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "freeboxfeederfile.h"
+
+// Qt headers
+#include <qurl.h>
+
+// Live555 headers
+#include <BasicUsageEnvironment.hh>
+#include <Groupsock.hh>
+#include <GroupsockHelper.hh>
+#include <ByteStreamFileSource.hh>
+#include <TunnelEncaps.hh>
+
+// MythTV headers
+#include "freeboxmediasink.h"
+#include "mythcontext.h"
+#include "tspacket.h"
+
+#define LOC QString("FbFeedFile:")
+
+
+FEEDERREG_IMPL(FreeboxFeederFile,"file:");
+
+
+FreeboxFeederFile::FreeboxFeederFile(StreamDataListener &listener) :
+    FreeboxFeederLive(listener),
+    _source(NULL),
+    _sink(NULL)
+{
+}
+
+FreeboxFeederFile::~FreeboxFeederFile()
+{
+    Close();
+}
+
+bool FreeboxFeederFile::Open(const QString &url)
+{
+    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
+
+    QMutexLocker locker(&GetLock());
+
+    if (_source)
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
+        return true;
+    }
+        
+    QUrl parse(url);
+    if (!parse.hasPath() || !parse.isLocalFile())
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
+        return false;
+    }
+        
+    // Begin by setting up our usage environment:
+    if (!InitEnv())
+        return false;
+    
+    _source = ByteStreamFileSource::createNew(GetLiveEnv(), parse.path().local8Bit());
+    if (!_source)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live File Source.");
+        FreeEnv();
+        return false;
+    }
+
+    _sink = FreeboxMediaSink::CreateNew(
+        GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024);
+    if (!_sink)
+    {
+        VERBOSE(VB_IMPORTANT,
+                QString("Freebox # Failed to create sink: %1")
+                .arg(GetLiveEnv().getResultMsg()));
+        Medium::close(_source);
+        _source = NULL;
+        FreeEnv();
+        return false;
+    }
+    _sink->startPlaying(*_source, NULL, NULL);
+        
+    VERBOSE(VB_RECORD, LOC + "Open() -- end");
+    return true;
+}
+
+void FreeboxFeederFile::Close(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
+    Stop();
+
+    QMutexLocker locker(&GetLock());
+
+    if (_sink)
+    {
+        Medium::close(_sink);
+        _sink = NULL;
+    }
+
+    if (_source)
+    {
+        Medium::close(_source);
+        _source=NULL;
+    }
+
+    FreeEnv();
+
+    VERBOSE(VB_RECORD, LOC + "Close() -- end");
+}
Index: libs/libmythtv/freeboxrecorder.cpp
===================================================================
--- libs/libmythtv/freeboxrecorder.cpp	(revision 10961)
+++ libs/libmythtv/freeboxrecorder.cpp	(working copy)
@@ -8,8 +8,8 @@
 #include "mpegstreamdata.h"
 #include "tspacket.h"
 #include "freeboxchannel.h"
+#include "freeboxfeederwrapper.h"
 #include "freeboxrecorder.h"
-#include "rtspcomms.h"
 
 #define LOC QString("FBRec: ")
 #define LOC_ERR QString("FBRec, Error: ")
@@ -23,33 +23,25 @@
     _channel(channel),
     _stream_data(NULL)
 {
-    _channel->GetRTSP()->AddListener(this);
+    _channel->GetFeeder()->AddListener(this);
 }
 
 FreeboxRecorder::~FreeboxRecorder()
 {
     StopRecording();
-    _channel->GetRTSP()->RemoveListener(this);
+    _channel->GetFeeder()->RemoveListener(this);
 }
 
 bool FreeboxRecorder::Open(void)
 {
     VERBOSE(VB_RECORD, LOC + "Open() -- begin");
 
-    if (_channel->GetRTSP()->IsOpen())
-        _channel->GetRTSP()->Close();
+    if (_channel->GetFeeder()->IsOpen())
+        _channel->GetFeeder()->Close();
 
     FreeboxChannelInfo chaninfo = _channel->GetCurrentChanInfo();
-    if (!chaninfo.isValid())
-    {
-        _error = true;
-    }
-    else
-    {
-        _error = !(_channel->GetRTSP()->Init()); 
-        if (!_error)
-            _error = !(_channel->GetRTSP()->Open(chaninfo.m_url));
-    }
+    _error = !chaninfo.isValid()
+          || !_channel->GetFeeder()->Open(chaninfo.m_url);
 
     VERBOSE(VB_RECORD, LOC + "Open() -- end err("<<_error<<")");
     return !_error;
@@ -58,8 +50,8 @@
 void FreeboxRecorder::Close(void)
 {
     VERBOSE(VB_RECORD, LOC + "Close() -- begin");
-    _channel->GetRTSP()->Stop();
-    _channel->GetRTSP()->Close();
+    _channel->GetFeeder()->Stop();
+    _channel->GetFeeder()->Close();
     VERBOSE(VB_RECORD, LOC + "Close() -- end");
 }
 
@@ -67,16 +59,18 @@
 {
     VERBOSE(VB_RECORD, LOC + "Pause() -- begin");
     DTVRecorder::Pause(clear);
-    _channel->GetRTSP()->Stop();
-    _channel->GetRTSP()->Close();
+    _channel->GetFeeder()->Stop();
+    _channel->GetFeeder()->Close();
     VERBOSE(VB_RECORD, LOC + "Pause() -- end");
 }
 
 void FreeboxRecorder::Unpause(void)
 {
     VERBOSE(VB_RECORD, LOC + "Unpause() -- begin");
-    if (_recording && !_channel->GetRTSP()->IsOpen())
+    if (_recording && !_channel->GetFeeder()->IsOpen())
         Open();
+    if (_stream_data)
+        _stream_data->Reset(_stream_data->DesiredProgram());
     DTVRecorder::Unpause();
     VERBOSE(VB_RECORD, LOC + "Unpause() -- end");
 }
@@ -99,14 +93,14 @@
         if (PauseAndWait())
             continue;
 
-        if (!_channel->GetRTSP()->IsOpen())
+        if (!_channel->GetFeeder()->IsOpen())
         {
             usleep(5000);
             continue;
         }
 
         // Go into main RTSP loop, feeding data to AddData
-        _channel->GetRTSP()->Run();
+        _channel->GetFeeder()->Run();
     }
 
     // Finish up...
@@ -122,7 +116,7 @@
 {
     VERBOSE(VB_RECORD, LOC + "StopRecording() -- begin");
     Pause();
-    _channel->GetRTSP()->Close();
+    _channel->GetFeeder()->Close();
 
     _request_recording = false;
     while (_recording)
@@ -131,77 +125,12 @@
     VERBOSE(VB_RECORD, LOC + "StopRecording() -- end");
 }
 
-// ===================================================
-// findTSHeader : find a TS Header in flow
-// ===================================================
-static int FreeboxRecorder_findTSHeader(const unsigned char *data,
-                                        uint dataSize)
-{
-    unsigned int pos = 0;
-
-    while (pos < dataSize)
-    {
-        if (data[pos] == 0x47)
-            return pos;
-        pos++;
-    }
-
-    return -1;
-}
-
-// ===================================================
-// AddData : feed data from RTSP flow to mythtv
-// ===================================================
-void FreeboxRecorder::AddData(unsigned char *data,
-                              unsigned       dataSize,
-                              struct timeval)
-{
-    unsigned int readIndex = 0;
-
-    // data may be compose from more than one packet, loop to consume all data
-    while (readIndex < dataSize)
-    {
-        // If recorder is paused, stop there
-        if (IsPaused())
-            return;
-
-        // Find the next TS Header in data
-        int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize);
-
-        // if no TS, something bad happens
-        if (tsPos == -1)
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR + "No TS header.");
-            break;
-        }
-
-        // if TS Header not at start of data, we receive out of sync data
-        if (tsPos > 0)
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR +
-                    QString("TS packet at %1, not in sync.").arg(tsPos));
-        }
-
-        // Check if the next packet in buffer is complete :
-        // packet size is 188 bytes long
-        if ((dataSize - tsPos) < TSPacket::SIZE)
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR +
-                    "TS packet at stradles end of buffer.");
-            break;
-        }
-
-        // Cast current found TS Packet to TSPacket structure
-        const void *newData = data + tsPos + readIndex;
-        ProcessTSPacket(*reinterpret_cast<const TSPacket*>(newData));
-
-        // follow to next packet
-        readIndex += tsPos + TSPacket::SIZE;
-    }
-}
-
 void FreeboxRecorder::ProcessTSPacket(const TSPacket& tspacket)
 {
+    // If recorder is paused, stop there
+    if (IsPaused())
+        return;
+
     if (!_stream_data)
         return;
 
@@ -232,9 +161,12 @@
 
 void FreeboxRecorder::SetStreamData(MPEGStreamData *data)
 {
-    VERBOSE(VB_RECORD, LOC + "SetStreamData()");
+    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin");
     if (data == _stream_data)
+    {
+        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0");
         return;
+    }
 
     MPEGStreamData *old_data = _stream_data;
     _stream_data = data;
@@ -243,6 +175,7 @@
 
     if (data)
         data->AddMPEGSPListener(this);
+    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1");
 }
 
 void FreeboxRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
Index: libs/libmythtv/rtspcomms.cpp
===================================================================
--- libs/libmythtv/rtspcomms.cpp	(revision 10961)
+++ libs/libmythtv/rtspcomms.cpp	(working copy)
@@ -1,437 +0,0 @@
-/** -*- Mode: c++ -*-
- *  RTSPComms
- *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
- *  Distributed as part of MythTV under GPL v2 and later.
- */
-
-#include "rtspcomms.h"
-
-// Live555 headers
-#include <RTSPClient.hh>
-#include <BasicUsageEnvironment.hh>
-#include <MediaSession.hh>
-
-// MythTV headers
-#include "freeboxmediasink.h"
-#include "mythcontext.h"
-#include "tspacket.h"
-
-#define LOC QString("RTSPData:")
-#define LOC_ERR QString("RTSPData, Error:")
-
-// ============================================================================
-// RTSPData : Helper class use for static Callback handler
-// ============================================================================
-class RTSPData
-{
-  public:
-    RTSPData(MediaSubsession *pMediaSubSession) :
-        mediaSubSession(pMediaSubSession)
-    {
-    }
-
-    void SubsessionAfterPlayingCB(void);
-    void SubsessionByeHandlerCB(void);
-
-  private:
-    MediaSubsession *mediaSubSession;
-};
-
-void RTSPData::SubsessionAfterPlayingCB(void)
-{
-    MediaSubsession *subsession = mediaSubSession;
-    Medium::close(subsession->sink);
-    subsession->sink = NULL;
-
-    MediaSession &session = subsession->parentSession();
-    MediaSubsessionIterator iter(session);
-
-    while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */
-    {
-        if (subsession->sink)
-            return;
-    }
-}
-
-static void sub_after_playing_cb(void *clientData)
-{
-    ((RTSPData*)clientData)->SubsessionAfterPlayingCB();
-}
-
-void RTSPData::SubsessionByeHandlerCB(void)
-{
-    SubsessionAfterPlayingCB();
-}
-
-static void sub_bye_handler_cb(void *clientData)
-{
-    ((RTSPData*)clientData)->SubsessionByeHandlerCB();
-}
-
-RTSPComms::RTSPComms() :
-    _abort(0),          _running(false),
-    _live_env(NULL),    _rtsp_client(NULL),
-    _session(NULL),     _lock(false)
-{
-    //Init();
-}
-
-RTSPComms::~RTSPComms()
-{
-    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
-    //Stop();
-    Close();
-    //Deinit();
-    VERBOSE(VB_RECORD, LOC + "dtor -- end");
-}
-
-bool RTSPComms::Init(void)
-{
-    VERBOSE(VB_RECORD, LOC + "Init() -- begin");
-    QMutexLocker locker(&_lock);
-
-    if (_rtsp_client)
-        return true;
-
-    // Begin by setting up our usage environment:
-    TaskScheduler *scheduler = BasicTaskScheduler::createNew();
-    if (!scheduler)
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create Live Scheduler.");
-        return false;
-    }
-
-    _live_env = BasicUsageEnvironment::createNew(*scheduler);
-    if (!_live_env)
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create Live Environment.");
-        delete scheduler;
-        return false;
-    }
-
-    // Create our client object:
-    _rtsp_client = RTSPClient::createNew(*_live_env, 0, "myRTSP", 0);
-
-    if (!_rtsp_client)
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR +
-                QString("Failed to create RTSP client: %1")
-                .arg(_live_env->getResultMsg()));
-
-        _live_env->reclaim();
-        _live_env = NULL;
-        delete scheduler;
-    }
-
-    VERBOSE(VB_RECORD, LOC + "Init() -- end");
-    return _rtsp_client;
-}
-
-void RTSPComms::Deinit(void)
-{
-    VERBOSE(VB_RECORD, LOC + "Deinit() -- begin");
-
-    if (_session)
-        Close();
-
-    if (_rtsp_client)
-    {
-        Medium::close(_rtsp_client);
-        _rtsp_client = NULL;
-    }
-
-    if (_live_env)
-    {
-        TaskScheduler *scheduler = &_live_env->taskScheduler();
-        _live_env->reclaim();
-        _live_env = NULL;
-        delete scheduler;
-    }
-    VERBOSE(VB_RECORD, LOC + "Deinit() -- end");
-}
-
-bool RTSPComms::Open(const QString &url)
-{
-    VERBOSE(VB_RECORD, LOC + "Open() -- begin");
-
-    if (!Init())
-        return false;
-
-    QMutexLocker locker(&_lock);
-
-    // Setup URL for the current session
-    char *sdpDescription = _rtsp_client->describeURL(url);
-    _rtsp_client->describeStatus();
-
-    if (!sdpDescription)
-    {
-        VERBOSE(VB_IMPORTANT, LOC + QString(
-                    "Failed to get a SDP "
-                    "description from URL: %1 %2")
-                .arg(url).arg(_live_env->getResultMsg()));
-        return false;
-    }
-
-    // Create a media session object from this SDP description:
-    _session = MediaSession::createNew(*_live_env, sdpDescription);
-
-    delete[] sdpDescription;
-
-    if (!_session)
-    {
-        VERBOSE(VB_IMPORTANT, LOC +
-                QString("Failed to create MediaSession: %1")
-                .arg(_live_env->getResultMsg()));
-        return false;
-    }
-    else if (!_session->hasSubsessions())
-    {
-        VERBOSE(VB_IMPORTANT, LOC +
-                "This session has no media subsessions");
-        Close();
-        return false;
-    }
-
-    // Then, setup the "RTPSource"s for the session:
-    MediaSubsessionIterator iter(*_session);
-    MediaSubsession *subsession;
-    bool madeProgress = false;
-
-    while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */
-    {
-        if (!subsession->initiate(-1))
-        {
-            VERBOSE(VB_IMPORTANT, LOC +
-                    QString("Can't create receiver for: "
-                            "%1 / %2 subsession: %3")
-                    .arg(subsession->mediumName())
-                    .arg(subsession->codecName())
-                    .arg(_live_env->getResultMsg()));
-        }
-        else
-        {
-            madeProgress = true;
-
-            if (subsession->rtpSource() != NULL)
-            {
-                unsigned const thresh = 1000000; // 1 second
-                subsession->rtpSource()->
-                    setPacketReorderingThresholdTime(thresh);
-            }
-        }
-    }
-
-    if (!madeProgress)
-        return false;
-
-    // Perform additional 'setup' on each subsession, before playing them:
-    madeProgress = false;
-    iter.reset();
-    while ((subsession = iter.next()) != NULL)
-    {
-        if (subsession->clientPortNum() == 0)
-            continue; // port # was not set
-
-        if (_rtsp_client->setupMediaSubsession(*subsession, false, false))
-        {
-            madeProgress = true;
-        }
-        else
-        {
-            VERBOSE(VB_IMPORTANT, LOC +
-                    QString("Failed to setup: %1 %2 : %3")
-                    .arg(subsession->mediumName())
-                    .arg(subsession->codecName())
-                    .arg(_live_env->getResultMsg()));
-        }
-    }
-
-    if (!madeProgress)
-        return false;
-
-    // Create and start "FileSink"s for each subsession:
-    // FileSink while receive Mpeg2 TS Data & will feed them to mythtv
-    madeProgress = false;
-    iter.reset();
-
-    while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */
-    {
-        if (!subsession->readSource())
-            continue; // was not initiated
-
-        FreeboxMediaSink *freeboxMediaSink = FreeboxMediaSink::CreateNew(
-            *_live_env, TSPacket::SIZE * 128*1024);
-
-        subsession->sink = freeboxMediaSink;
-        if (!subsession->sink)
-        {
-            VERBOSE(VB_IMPORTANT,
-                    QString("Freebox # Failed to create sink: %1")
-                    .arg(_live_env->getResultMsg()));
-        }
-
-        vector<RTSPListener*>::iterator it = _listeners.begin();
-        for (; it != _listeners.end(); ++it)
-            freeboxMediaSink->AddListener(*it);
-
-        subsession->sink->startPlaying(*(subsession->readSource()),
-                                       sub_after_playing_cb,
-                                       new RTSPData(subsession));
-
-        if (subsession->rtcpInstance())
-        {
-            subsession->rtcpInstance()->setByeHandler(
-                sub_bye_handler_cb, new RTSPData(subsession));
-        }
-
-        madeProgress = true;
-    }
-
-    if (!madeProgress)
-        return false;
-
-    // Setup player
-    if (!(_rtsp_client->playMediaSession(*_session)))
-    {
-        VERBOSE(VB_IMPORTANT, LOC +
-                QString("Failed to start playing session: %1")
-                .arg(_live_env->getResultMsg()));
-        return false;
-    }
-
-    VERBOSE(VB_RECORD, LOC + "Open() -- end");
-    return true;
-}
-
-void RTSPComms::Close(void)
-{
-    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
-    Stop();
-
-    VERBOSE(VB_RECORD, LOC + "Close() -- middle 1");
-
-    _lock.lock();
-    if (_session)
-    {
-        // Ensure RTSP cleanup, remove old RTSP session
-        MediaSubsessionIterator iter(*_session);
-        MediaSubsession *subsession;
-        while ((subsession = iter.next())) /*<-extra braces for pedantic gcc*/
-        {
-            Medium::close(subsession->sink);
-            subsession->sink = NULL;
-        }
-
-        _rtsp_client->teardownMediaSession(*_session);
-
-        // Close all RTSP descriptor
-        Medium::close(_session);
-        _session = NULL;
-    }
-    _lock.unlock();
-
-    VERBOSE(VB_RECORD, LOC + "Close() -- middle 2");
-
-    Deinit();
-    VERBOSE(VB_RECORD, LOC + "Close() -- end");
-}
-
-void RTSPComms::Run(void)
-{
-    VERBOSE(VB_RECORD, LOC + "Run() -- begin");
-    _lock.lock();
-    _running = true;
-    _abort   = 0;
-    _lock.unlock();
-
-    VERBOSE(VB_RECORD, LOC + "Run() -- loop begin");
-    if (_live_env)
-        _live_env->taskScheduler().doEventLoop(&_abort);
-    VERBOSE(VB_RECORD, LOC + "Run() -- loop end");
-
-    _lock.lock();
-    _running = false;
-    _cond.wakeAll();
-    _lock.unlock();
-    VERBOSE(VB_RECORD, LOC + "Run() -- end");
-}
-
-void RTSPComms::Stop(void)
-{
-    VERBOSE(VB_RECORD, LOC + "Stop() -- begin");
-    QMutexLocker locker(&_lock);
-    _abort = 0xFF;
-
-    while (_running)
-        _cond.wait(&_lock, 500);
-    VERBOSE(VB_RECORD, LOC + "Stop() -- end");
-}
-
-void RTSPComms::AddListener(RTSPListener *item)
-{
-    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
-    if (!item)
-    {
-        VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 0");
-        return;
-    }
-
-    // avoid duplicates
-    RemoveListener(item);
-
-    // add to local list
-    QMutexLocker locker(&_lock);
-    _listeners.push_back(item);
-
-    // if there is a session, add to each subsession->sink
-    if (!_session)
-    {
-        VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 1");
-        return;
-    }
-
-    MediaSubsessionIterator mit(*_session);
-    MediaSubsession *subsession;
-    while ((subsession = mit.next())) /* <- extra braces for pedantic gcc */
-    {
-        FreeboxMediaSink *sink = NULL;
-        if ((sink = dynamic_cast<FreeboxMediaSink*>(subsession->sink)))
-            sink->AddListener(item);
-    }
-    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 2");
-}
-
-void RTSPComms::RemoveListener(RTSPListener *item)
-{
-    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
-    QMutexLocker locker(&_lock);
-    vector<RTSPListener*>::iterator it =
-        find(_listeners.begin(), _listeners.end(), item);
-
-    if (it == _listeners.end())
-    {
-        VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 1");
-        return;
-    }
-
-    // remove from local list..
-    *it = *_listeners.rbegin();
-    _listeners.resize(_listeners.size() - 1);
-
-    // if there is a session, remove from each subsession->sink
-    if (!_session)
-    {
-        VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 2");
-        return;
-    }
-
-    MediaSubsessionIterator mit(*_session);
-    MediaSubsession *subsession;
-    while ((subsession = mit.next())) /* <- extra braces for pedantic gcc */
-    {
-        FreeboxMediaSink *sink = NULL;
-        if ((sink = dynamic_cast<FreeboxMediaSink*>(subsession->sink)))
-            sink->RemoveListener(item);
-    }
-    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 3");
-}
Index: libs/libmythtv/timeoutedtaskscheduler.cpp
===================================================================
--- libs/libmythtv/timeoutedtaskscheduler.cpp	(revision 0)
+++ libs/libmythtv/timeoutedtaskscheduler.cpp	(revision 0)
@@ -0,0 +1,24 @@
+/** -*- Mode: c++ -*-
+ *  TimeoutedTaskScheduler
+ *  Copyright (c) 2006 by Mike Mironov
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "timeoutedtaskscheduler.h"
+
+
+TimeoutedTaskScheduler::TimeoutedTaskScheduler(unsigned maxDelayTimeMS) :
+    _maxDelayTimeUS(maxDelayTimeMS*1000)
+{
+}
+
+void TimeoutedTaskScheduler::doEventLoop(char* watchVariable)
+{
+    // Repeatedly loop, handling readble sockets and timed events:
+    while (1)
+    {
+        if (watchVariable != NULL && *watchVariable != 0)
+            break;
+        SingleStep(_maxDelayTimeUS);
+    }
+}
Index: libs/libmythtv/freeboxfeederudp.h
===================================================================
--- libs/libmythtv/freeboxfeederudp.h	(revision 0)
+++ libs/libmythtv/freeboxfeederudp.h	(revision 0)
@@ -0,0 +1,43 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederUdp
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef FREEBOXFEEDERUDP_H
+#define FREEBOXFEEDERUDP_H
+
+// MythTV headers
+#include "freeboxfeederwrapper.h"
+#include "freeboxfeederlive.h"
+
+class BasicUDPSource;
+class FreeboxMediaSink;
+
+
+class FreeboxFeederUdp : public FreeboxFeederLive
+{
+  public:
+    FreeboxFeederUdp(StreamDataListener &listener);
+    virtual ~FreeboxFeederUdp();
+
+    bool Open(const QString &url);
+    bool IsOpen(void) const { return _source; }
+    void Close(void);
+
+  private:
+    BasicUDPSource     *_source;
+    FreeboxMediaSink   *_sink;
+
+  private:
+    /// avoid default copy operator
+    FreeboxFeederUdp& operator=(const FreeboxFeederUdp&);
+    /// avoid default copy constructor
+    FreeboxFeederUdp(const FreeboxFeederUdp&);
+    /// avoid default constructor
+    FreeboxFeederUdp();
+    
+  FEEDERREG_DECL  
+};
+
+#endif//FREEBOXFEEDERUDP_H
Index: libs/libmythtv/tspacketlistener.h
===================================================================
--- libs/libmythtv/tspacketlistener.h	(revision 0)
+++ libs/libmythtv/tspacketlistener.h	(revision 0)
@@ -0,0 +1,21 @@
+/** -*- Mode: c++ -*-
+ *  StreamDataListener
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+ 
+#ifndef _TSPACKETLISTENER_H_
+#define _TSPACKETLISTENER_H_
+
+class TSPacket;
+
+class TSPacketListener
+{
+  public:
+    /// Callback function to process MPEG2 TS packet
+    virtual void ProcessTSPacket(const TSPacket &packet) = 0;
+  protected:
+    virtual ~TSPacketListener() {}
+};
+
+#endif//_TSPACKETLISTENER_H_
Index: libs/libmythtv/freeboxmediasink.h
===================================================================
--- libs/libmythtv/freeboxmediasink.h	(revision 10961)
+++ libs/libmythtv/freeboxmediasink.h	(working copy)
@@ -7,39 +7,27 @@
 #ifndef _FREEBOXMEDIASINK_H_
 #define _FREEBOXMEDIASINK_H_
 
-#include <vector>
-using namespace std;
-
 #include <qmutex.h>
 
 #include <MediaSink.hh>
 
-class RTSPListener
-{
-  public:
-    /// Callback function to add MPEG2 TS data
-    virtual void AddData(unsigned char *data,
-                         unsigned int   dataSize,
-                         struct timeval presentationTime) = 0;
-  protected:
-    virtual ~RTSPListener() {}
-};
+class StreamDataListener;
 
+
 // ============================================================================
 // FreeboxMediaSink : Helper class use to receive RTSP data from socket.
 // ============================================================================
 class FreeboxMediaSink : public MediaSink
 {
   public:
-    static FreeboxMediaSink *CreateNew(UsageEnvironment &env,
-                                       unsigned          bufferSize);
+    static FreeboxMediaSink *CreateNew(UsageEnvironment   &env,
+                                       StreamDataListener &listener,
+                                       unsigned            bufferSize);
 
-    void AddListener(RTSPListener*);
-    void RemoveListener(RTSPListener*);
-
   protected:
-    FreeboxMediaSink(UsageEnvironment &env,
-                     unsigned int      bufferSize);
+    FreeboxMediaSink(UsageEnvironment   &env,
+                     StreamDataListener &listener,
+                     unsigned int        bufferSize);
     virtual ~FreeboxMediaSink();
 
     virtual void afterGettingFrame1(unsigned       frameSize,
@@ -58,7 +46,7 @@
     unsigned char         *fBuffer;
     unsigned int           fBufferSize;
     UsageEnvironment      &env;
-    vector<RTSPListener*>  listeners;
+    StreamDataListener    &_listener;
     mutable QMutex         lock;
 
   private:
Index: libs/libmythtv/freeboxrecorder.h
===================================================================
--- libs/libmythtv/freeboxrecorder.h	(revision 10961)
+++ libs/libmythtv/freeboxrecorder.h	(working copy)
@@ -10,18 +10,18 @@
 #include <qwaitcondition.h>
 
 #include "dtvrecorder.h"
-#include "freeboxmediasink.h"
+#include "tspacketlistener.h"
 #include "streamlisteners.h"
 
 class FreeboxChannel;
 
-/** \brief Processes data from RTSPComms and writes it to disk.
+/** \brief Processes data from StreamDataListener and writes it to disk.
  */
-class FreeboxRecorder : public DTVRecorder, public RTSPListener,
+class FreeboxRecorder : public DTVRecorder,
+                        public TSPacketListener,
                         public MPEGSingleProgramStreamListener
 {
     friend class FreeboxMediaSink;
-    friend class RTSPComms;
 
   public:
     FreeboxRecorder(TVRec *rec, FreeboxChannel *channel);
@@ -43,13 +43,9 @@
     virtual MPEGStreamData *GetStreamData(void) { return _stream_data; }
 
   private:
+    // implements TSPacketListener
     void ProcessTSPacket(const TSPacket& tspacket);
 
-    // implements RTSPListener
-    void AddData(unsigned char *data,
-                 unsigned int   dataSize,
-                 struct timeval presentationTime);
-
     // implements MPEGSingleProgramStreamListener
     void HandleSingleProgramPAT(ProgramAssociationTable *pat);
     void HandleSingleProgramPMT(ProgramMapTable *pmt);
@@ -59,7 +55,6 @@
     MPEGStreamData *_stream_data;
     QWaitCondition  _cond_recording;
 
-
   private:
     FreeboxRecorder& operator=(const FreeboxRecorder&); //< avoid default impl
     FreeboxRecorder(const FreeboxRecorder&);            //< avoid default impl
Index: libs/libmythtv/timeoutedtaskscheduler.h
===================================================================
--- libs/libmythtv/timeoutedtaskscheduler.h	(revision 0)
+++ libs/libmythtv/timeoutedtaskscheduler.h	(revision 0)
@@ -0,0 +1,26 @@
+/** -*- Mode: c++ -*-
+ *  TimeoutedTaskScheduler
+ *  Copyright (c) 2006 by Mike Mironov
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _TIMEOUTEDTASKSCHEDULER_H_
+#define _TIMEOUTEDTASKSCHEDULER_H_
+
+// Live555 headers
+#include <BasicUsageEnvironment.hh>
+
+
+class TimeoutedTaskScheduler : public BasicTaskScheduler
+{
+  public:
+    TimeoutedTaskScheduler(unsigned maxDelayTimeMS);
+
+  public:
+    virtual void doEventLoop(char* watchVariable);
+
+  private:
+    unsigned _maxDelayTimeUS;
+};
+
+#endif//_TIMEOUTEDTASKSCHEDULER_H_
Index: libs/libmythtv/freeboxfeeder.h
===================================================================
--- libs/libmythtv/freeboxfeeder.h	(revision 0)
+++ libs/libmythtv/freeboxfeeder.h	(revision 0)
@@ -0,0 +1,57 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeeder
+ *  Copyright (c) 2006 by Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef FREEBOXFEEDER_H
+#define FREEBOXFEEDER_H
+
+class QString;
+
+
+/** \interface FreeboxFeeder
+**  \brief This is the interface that need to be implemented to support new
+**         protocols in the FreeboxRecorder.
+**
+**  To add a new implementation, sub-class FreeboxFeederFactory and register
+**  it using FreeboxFeederFactory::Register()
+**
+**  \sa FreeboxFeederFactory
+**  \sa FreeboxFeederFactory::Register()
+*/
+class FreeboxFeeder
+{
+  public:
+    virtual ~FreeboxFeeder() {}
+
+    /** \brief Returns true if the feeder can handle url
+    **  \sa FreeboxFeederFactory::CanHandle(const QString&)
+    */
+    virtual bool CanHandle(const QString &url) const = 0;
+
+    /// \brief Inits the feeder and opens the stream identified by url
+    virtual bool Open(const QString &url) = 0;
+
+    /// \brief Returns true if the feeder is currently open
+    virtual bool IsOpen(void) const = 0;
+
+    /// \brief Closes the stream and frees resources allocated in Open()
+    virtual void Close(void) = 0;
+
+    /** \brief Reads the stream and sends data to its StreamDataListener. This
+    **         is a blocking call : it should not exit until Stop() is called.
+    **  \sa Stop()
+    */
+    virtual void Run(void) = 0;
+
+    /** \brief Signals to the Run() function that it should stop and exit
+    **         cleanly.
+    **
+    **  This function should block until Run() has finished up.
+    **  \sa Run()
+    */
+    virtual void Stop(void) = 0;
+};
+
+#endif//FREEBOXFEEDER_H
Index: libs/libmythtv/freeboxfeederrtsp.cpp
===================================================================
--- libs/libmythtv/freeboxfeederrtsp.cpp	(revision 0)
+++ libs/libmythtv/freeboxfeederrtsp.cpp	(revision 0)
@@ -0,0 +1,281 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederRtsp
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "freeboxfeederrtsp.h"
+
+// Live555 headers
+#include <RTSPClient.hh>
+#include <BasicUsageEnvironment.hh>
+#include <MediaSession.hh>
+
+// MythTV headers
+#include "freeboxmediasink.h"
+#include "mythcontext.h"
+#include "tspacket.h"
+
+#define LOC QString("FbFeedRtsp(%1):").arg(pthread_self())
+#define LOC_ERR QString("FbFeedRtsp(%1), Error:").arg(pthread_self())
+
+// ============================================================================
+// RTSPData : Helper class use for static Callback handler
+// ============================================================================
+class RTSPData
+{
+  public:
+    RTSPData(MediaSubsession *pMediaSubSession) :
+        mediaSubSession(pMediaSubSession)
+    {
+    }
+
+    void SubsessionAfterPlayingCB(void);
+    void SubsessionByeHandlerCB(void);
+
+  private:
+    MediaSubsession *mediaSubSession;
+};
+
+void RTSPData::SubsessionAfterPlayingCB(void)
+{
+    MediaSubsession *subsession = mediaSubSession;
+    Medium::close(subsession->sink);
+    subsession->sink = NULL;
+}
+
+static void sub_after_playing_cb(void *clientData)
+{
+    ((RTSPData*)clientData)->SubsessionAfterPlayingCB();
+}
+
+void RTSPData::SubsessionByeHandlerCB(void)
+{
+    SubsessionAfterPlayingCB();
+}
+
+static void sub_bye_handler_cb(void *clientData)
+{
+    ((RTSPData*)clientData)->SubsessionByeHandlerCB();
+}
+
+
+FEEDERREG_IMPL(FreeboxFeederRtsp,"rtsp://");
+
+
+FreeboxFeederRtsp::FreeboxFeederRtsp(StreamDataListener &listener) :
+    FreeboxFeederLive(listener),
+    _rtsp_client(NULL),
+    _session(NULL)
+{
+    VERBOSE(VB_RECORD, LOC + "ctor -- success");
+}
+
+FreeboxFeederRtsp::~FreeboxFeederRtsp()
+{
+    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
+    Close();
+    VERBOSE(VB_RECORD, LOC + "dtor -- end");
+}
+
+bool FreeboxFeederRtsp::Open(const QString &url)
+{
+    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
+
+    QMutexLocker locker(&GetLock());
+
+    if (_rtsp_client)
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
+        return true;
+    }
+
+    // Begin by setting up our usage environment:
+    if (!InitEnv())
+        return false;
+
+    // Create our client object:
+    _rtsp_client = RTSPClient::createNew(GetLiveEnv(), 0, "myRTSP", 0);
+    if (!_rtsp_client)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                QString("Failed to create RTSP client: %1")
+                .arg(GetLiveEnv().getResultMsg()));
+        FreeEnv();
+    }
+
+    // Setup URL for the current session
+    char *sdpDescription = _rtsp_client->describeURL(url);
+    _rtsp_client->describeStatus();
+
+    if (!sdpDescription)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + QString(
+                    "Failed to get a SDP "
+                    "description from URL: %1 %2")
+                .arg(url).arg(GetLiveEnv().getResultMsg()));
+        return false;
+    }
+
+    // Create a media session object from this SDP description:
+    _session = MediaSession::createNew(GetLiveEnv(), sdpDescription);
+
+    delete[] sdpDescription;
+
+    if (!_session)
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                QString("Failed to create MediaSession: %1")
+                .arg(GetLiveEnv().getResultMsg()));
+        return false;
+    }
+    else if (!_session->hasSubsessions())
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                "This session has no media subsessions");
+        Close();
+        return false;
+    }
+
+    // Then, setup the "RTPSource"s for the session:
+    MediaSubsessionIterator iter(*_session);
+    MediaSubsession *subsession;
+    bool madeProgress = false;
+
+    while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */
+    {
+        if (!subsession->initiate(-1))
+        {
+            VERBOSE(VB_IMPORTANT, LOC +
+                    QString("Can't create receiver for: "
+                            "%1 / %2 subsession: %3")
+                    .arg(subsession->mediumName())
+                    .arg(subsession->codecName())
+                    .arg(GetLiveEnv().getResultMsg()));
+        }
+        else
+        {
+            madeProgress = true;
+
+            if (subsession->rtpSource() != NULL)
+            {
+                unsigned const thresh = 1000000; // 1 second
+                subsession->rtpSource()->
+                    setPacketReorderingThresholdTime(thresh);
+            }
+        }
+    }
+
+    if (!madeProgress)
+        return false;
+
+    // Perform additional 'setup' on each subsession, before playing them:
+    madeProgress = false;
+    iter.reset();
+    while ((subsession = iter.next()) != NULL)
+    {
+        if (subsession->clientPortNum() == 0)
+            continue; // port # was not set
+
+        if (_rtsp_client->setupMediaSubsession(*subsession, false, false))
+        {
+            madeProgress = true;
+        }
+        else
+        {
+            VERBOSE(VB_IMPORTANT, LOC +
+                    QString("Failed to setup: %1 %2 : %3")
+                    .arg(subsession->mediumName())
+                    .arg(subsession->codecName())
+                    .arg(GetLiveEnv().getResultMsg()));
+        }
+    }
+
+    if (!madeProgress)
+        return false;
+
+    // Create and start "FileSink"s for each subsession:
+    // FileSink while receive Mpeg2 TS Data & will feed them to mythtv
+    madeProgress = false;
+    iter.reset();
+
+    while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */
+    {
+        if (!subsession->readSource())
+            continue; // was not initiated
+
+        FreeboxMediaSink *freeboxMediaSink = FreeboxMediaSink::CreateNew(
+            GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024);
+
+        subsession->sink = freeboxMediaSink;
+        if (!subsession->sink)
+        {
+            VERBOSE(VB_IMPORTANT,
+                    QString("Freebox # Failed to create sink: %1")
+                    .arg(GetLiveEnv().getResultMsg()));
+        }
+
+        subsession->sink->startPlaying(*(subsession->readSource()),
+                                       sub_after_playing_cb,
+                                       new RTSPData(subsession));
+
+        if (subsession->rtcpInstance())
+        {
+            subsession->rtcpInstance()->setByeHandler(
+                sub_bye_handler_cb, new RTSPData(subsession));
+        }
+
+        madeProgress = true;
+    }
+
+    if (!madeProgress)
+        return false;
+
+    // Setup player
+    if (!(_rtsp_client->playMediaSession(*_session)))
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                QString("Failed to start playing session: %1")
+                .arg(GetLiveEnv().getResultMsg()));
+        return false;
+    }
+
+    VERBOSE(VB_RECORD, LOC + "Open() -- end");
+    return true;
+}
+
+void FreeboxFeederRtsp::Close(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
+    Stop();
+
+    QMutexLocker locker(&GetLock());
+
+    if (_session)
+    {
+        // Ensure RTSP cleanup, remove old RTSP session
+        MediaSubsessionIterator iter(*_session);
+        MediaSubsession *subsession;
+        while ((subsession = iter.next())) /*<-extra braces for pedantic gcc*/
+        {
+            Medium::close(subsession->sink);
+            subsession->sink = NULL;
+        }
+
+        _rtsp_client->teardownMediaSession(*_session);
+
+        // Close all RTSP descriptor
+        Medium::close(_session);
+        _session = NULL;
+    }
+
+    if (_rtsp_client)
+    {
+        Medium::close(_rtsp_client);
+        _rtsp_client = NULL;
+    }
+
+    FreeEnv();
+
+    VERBOSE(VB_RECORD, LOC + "Close() -- end");
+}
Index: libs/libmythtv/freeboxfeederrtp.h
===================================================================
--- libs/libmythtv/freeboxfeederrtp.h	(revision 0)
+++ libs/libmythtv/freeboxfeederrtp.h	(revision 0)
@@ -0,0 +1,43 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederRtp
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef FREEBOXFEEDERRTP_H
+#define FREEBOXFEEDERRTP_H
+
+// MythTV headers
+#include "freeboxfeederwrapper.h"
+#include "freeboxfeederlive.h"
+
+class SimpleRTPSource;
+class FreeboxMediaSink;
+
+
+class FreeboxFeederRtp : public FreeboxFeederLive
+{
+  public:
+    FreeboxFeederRtp(StreamDataListener &listener);
+    virtual ~FreeboxFeederRtp();
+
+    bool Open(const QString &url);
+    bool IsOpen(void) const { return _source; }
+    void Close(void);
+
+  private:
+    SimpleRTPSource    *_source;
+    FreeboxMediaSink   *_sink;
+
+  private:
+    /// avoid default copy operator
+    FreeboxFeederRtp& operator=(const FreeboxFeederRtp&);
+    /// avoid default copy constructor
+    FreeboxFeederRtp(const FreeboxFeederRtp&);
+    /// avoid default constructor
+    FreeboxFeederRtp();
+    
+  FEEDERREG_DECL  
+};
+
+#endif//FREEBOXFEEDERRTP_H
Index: libs/libmythtv/freeboxfeederwrapper.h
===================================================================
--- libs/libmythtv/freeboxfeederwrapper.h	(revision 0)
+++ libs/libmythtv/freeboxfeederwrapper.h	(revision 0)
@@ -0,0 +1,101 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederWrapper
+ *  Copyright (c) 2006 by Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef FREEBOXFEEDERWRAPPER_H
+#define FREEBOXFEEDERWRAPPER_H
+
+#include <qmutex.h>
+#include <vector>
+
+#include "tspacketlistener.h"
+#include "tspacketsplitter.h"
+
+class FreeboxFeeder;
+class FreeboxFeederFactory;
+class QString;
+class StreamDataListener;
+
+
+// Helper macros for registration of new feeder
+#define FEEDERREG_DECL                                             \
+  public:                                                          \
+    static bool CanHandleStatic(const QString &url);               \
+    bool CanHandle(const QString &url) const                       \
+    {                                                              \
+        return CanHandleStatic(url);                               \
+    }                                                              \
+    static FreeboxFeeder *createNew(StreamDataListener &listener);
+
+#define FEEDERREG_IMPL(TYPE,PREFIX)                          \
+class TYPE##Reg                                              \
+{                                                            \
+  public:                                                    \
+    TYPE##Reg()                                              \
+    {                                                        \
+        FreeboxFeederWrapper::RegisterHandler(               \
+            TYPE::CanHandleStatic,                           \
+            TYPE::createNew);                                \
+    }                                                        \
+};                                                           \
+static TYPE##Reg TYPE##RegInstance=TYPE##Reg();              \
+bool TYPE::CanHandleStatic(const QString &url)               \
+{                                                            \
+    return url.startsWith(PREFIX,false);                     \
+}                                                            \
+FreeboxFeeder *TYPE::createNew(StreamDataListener &listener) \
+{                                                            \
+    return new TYPE(listener);                               \
+}
+
+    
+/** \class FreeboxFeederWrapper
+**  \brief Handles the various implementations of FeederRecorder.
+*/
+class FreeboxFeederWrapper : private TSPacketListener
+{
+  public:
+    FreeboxFeederWrapper();
+    ~FreeboxFeederWrapper();
+
+  public:
+    bool Open(const QString &url);
+    bool IsOpen(void) const;
+    void Close(void);
+
+    void Run(void);
+    void Stop(void);
+
+    void AddListener(TSPacketListener*);
+    void RemoveListener(TSPacketListener*);
+    
+    // Feeder registration
+    typedef FreeboxFeeder *(*FeederConstructorFn)(StreamDataListener &listener);
+    typedef bool (*CanHandleFn)(const QString &url);
+    static void RegisterHandler(CanHandleFn, FeederConstructorFn);
+    static bool HaveHandler(const QString &url);
+    
+  private:
+    static FreeboxFeeder* NewFeeder(const QString      &url,
+                                    StreamDataListener &listener);
+    bool InitFeeder(const QString &url);
+
+  private: // implements TSPacketListener
+    void ProcessTSPacket(const TSPacket &packet);
+
+  private:
+    TSPacketSplitter _splitter;
+    FreeboxFeeder   *_feeder;
+    mutable QMutex   _lock; ///< Lock  used to coordinate threads
+    std::vector<TSPacketListener*> _listeners;
+
+  private:
+    /// avoid default copy operator
+    FreeboxFeederWrapper& operator=(const FreeboxFeederWrapper&);
+    /// avoid default copy constructor
+    FreeboxFeederWrapper(const FreeboxFeederWrapper&);
+};
+
+#endif//FREEBOXFEEDERWRAPPER_H
Index: libs/libmythtv/freeboxfeederlive.h
===================================================================
--- libs/libmythtv/freeboxfeederlive.h	(revision 0)
+++ libs/libmythtv/freeboxfeederlive.h	(revision 0)
@@ -0,0 +1,59 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederLive -- base class for livemedia based FreeboxFeeders
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _FREEBOXFEEDERLIVE_H_
+#define _FREEBOXFEEDERLIVE_H_
+
+// C++ headers
+#include <vector>
+
+// Qt headers
+#include <qwaitcondition.h>
+#include <qmutex.h>
+
+// Mythtv headers
+#include "freeboxfeeder.h"
+
+class QString;
+class StreamDataListener;
+class UsageEnvironment;
+
+
+class FreeboxFeederLive : public FreeboxFeeder
+{
+  public:
+    FreeboxFeederLive(StreamDataListener &listener);
+
+    void Run(void);
+    void Stop(void);
+    
+  protected:
+    virtual ~FreeboxFeederLive();
+    bool InitEnv(void);
+    void FreeEnv(void);
+
+    UsageEnvironment&   GetLiveEnv()  { return *_live_env; }
+    QMutex&             GetLock()     { return _lock;      }
+    StreamDataListener& GetListener() { return _listener;  }
+
+  private:
+    char              _abort;
+    bool              _running;
+    UsageEnvironment *_live_env;
+    QWaitCondition    _cond; ///< Condition  used to coordinate threads
+    mutable QMutex    _lock; ///< Lock  used to coordinate threads
+    StreamDataListener         &_listener;
+
+  private:
+    /// avoid default copy operator
+    FreeboxFeederLive& operator=(const FreeboxFeederLive&);
+    /// avoid default copy constructor
+    FreeboxFeederLive(const FreeboxFeederLive&);
+    /// avoid default constructor
+    FreeboxFeederLive();
+};
+
+#endif//_FREEBOXFEEDERLIVE_H_
Index: libs/libmythtv/freeboxfeederrtp.cpp
===================================================================
--- libs/libmythtv/freeboxfeederrtp.cpp	(revision 0)
+++ libs/libmythtv/freeboxfeederrtp.cpp	(revision 0)
@@ -0,0 +1,131 @@
+/** -*- Mode: c++ -*-
+ *  FreeboxFeederRtp
+ *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "freeboxfeederrtp.h"
+
+// Qt headers
+#include <qurl.h>
+
+// Live555 headers
+#include <BasicUsageEnvironment.hh>
+#include <Groupsock.hh>
+#include <GroupsockHelper.hh>
+#include <SimpleRTPSource.hh>
+#include <TunnelEncaps.hh>
+
+// MythTV headers
+#include "freeboxmediasink.h"
+#include "mythcontext.h"
+#include "tspacket.h"
+
+#define LOC QString("FbFeedRtp(%1):").arg(pthread_self())
+
+
+FEEDERREG_IMPL(FreeboxFeederRtp,"rtp://");
+    
+
+FreeboxFeederRtp::FreeboxFeederRtp(StreamDataListener &listener) :
+    FreeboxFeederLive(listener),
+    _source(NULL),
+    _sink(NULL)
+{
+    VERBOSE(VB_RECORD, LOC + "ctor -- success");
+}
+
+FreeboxFeederRtp::~FreeboxFeederRtp()
+{
+    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
+    Close();
+    VERBOSE(VB_RECORD, LOC + "dtor -- end");
+}
+
+bool FreeboxFeederRtp::Open(const QString &url)
+{
+    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
+
+    QMutexLocker locker(&GetLock());
+
+    if (_source)
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
+        return true;
+    }
+        
+    QUrl parse(url);
+    if (!parse.isValid() || !parse.hasHost() || !parse.hasPort())
+    {
+        VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
+        return false;
+    }
+        
+    struct in_addr addr;
+    addr.s_addr = our_inet_addr(parse.host().latin1());
+
+    // Begin by setting up our usage environment:
+    if (!InitEnv())
+        return false;
+    
+    Groupsock *socket = new Groupsock(GetLiveEnv(), addr, parse.port(), 0);
+    if (!socket)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live RTP Socket.");
+        FreeEnv();
+        return false;
+    }
+    
+    _source = SimpleRTPSource::createNew(GetLiveEnv(), socket, 33, 90000, "video/MP2T", 0, False);
+    if (!_source)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live RTP Source.");
+        delete socket;
+        FreeEnv();
+        return false;
+    }
+
+    _sink = FreeboxMediaSink::CreateNew(
+        GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024);
+    if (!_sink)
+    {
+        VERBOSE(VB_IMPORTANT,
+                QString("Freebox # Failed to create sink: %1")
+                .arg(GetLiveEnv().getResultMsg()));
+        Medium::close(_source);
+        _source = NULL;
+        delete socket;
+        FreeEnv();
+        return false;
+    }
+    _sink->startPlaying(*_source, NULL, NULL);
+        
+    VERBOSE(VB_RECORD, LOC + "Open() -- end");
+    return true;
+}
+
+void FreeboxFeederRtp::Close(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
+    Stop();
+
+    QMutexLocker locker(&GetLock());
+
+    if (_sink)
+    {
+        Medium::close(_sink);
+        _sink = NULL;
+    }
+
+    if (_source)
+    {
+        Groupsock *socket=_source->RTPgs();
+        Medium::close(_source);
+        _source=NULL;
+        delete socket;
+    }
+
+    FreeEnv();
+
+    VERBOSE(VB_RECORD, LOC + "Close() -- end");
+}
Index: libs/libmythtv/rtspcomms.h
===================================================================
--- libs/libmythtv/rtspcomms.h	(revision 10961)
+++ libs/libmythtv/rtspcomms.h	(working copy)
@@ -1,52 +0,0 @@
-/** -*- Mode: c++ -*-
- *  RTSPComms
- *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
- *  Distributed as part of MythTV under GPL v2 and later.
- */
-
-// C++ headers
-#include <vector>
-using namespace std;
-
-// Qt headers
-#include <qwaitcondition.h>
-#include <qmutex.h>
-
-// MythTV headers
-#include "freeboxchannel.h"
-
-class UsageEnvironment;
-class RTSPClient;
-class MediaSession;
-class RTSPListener;
-
-class RTSPComms 
-{
-  public:
-    RTSPComms();
-    virtual ~RTSPComms();
-
-    bool Init(void);
-    void Deinit(void);
-
-    bool Open(const QString &url);
-    bool IsOpen(void) const { return _session; }
-    void Close(void);
-
-    void Run(void);
-    void Stop(void);
-
-    void AddListener(RTSPListener*);
-    void RemoveListener(RTSPListener*);
-
-  private:
-
-    char                _abort;
-    bool                _running;
-    UsageEnvironment   *_live_env;
-    RTSPClient         *_rtsp_client;
-    MediaSession       *_session;
-    vector<RTSPListener*> _listeners;
-    QWaitCondition      _cond;       ///< Condition  used to coordinate threads
-    mutable QMutex      _lock;       ///< Lock  used to coordinate threads
-};
