Index: libs/libmythtv/freeboxsignalmonitor.cpp
===================================================================
--- libs/libmythtv/freeboxsignalmonitor.cpp	(revision 10744)
+++ libs/libmythtv/freeboxsignalmonitor.cpp	(working copy)
@@ -2,6 +2,7 @@
 
 // MythTV headers
 #include "mpegstreamdata.h"
+#include "freeboxchannel.h"
 #include "freeboxsignalmonitor.h"
 #include "rtspcomms.h"
 
@@ -33,13 +34,9 @@
     : DTVSignalMonitor(db_cardnum, _channel, _flags, _name),
       dtvMonitorRunning(false)
 {
-    bool isLocked = false;
-    if (GetChannel()->GetRTSP()->Init())
-    {
-        FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo();
-        isLocked = (chaninfo.isValid() && 
-                    GetChannel()->GetRTSP()->Open(chaninfo.m_url));
-    }
+    FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo();
+    bool isLocked = (chaninfo.isValid() && 
+                GetChannel()->StreamOpen(chaninfo.m_url));
 
     QMutexLocker locker(&statusLock);
     signalLock.SetValue((isLocked) ? 1 : 0);
@@ -51,7 +48,7 @@
  */
 FreeboxSignalMonitor::~FreeboxSignalMonitor()
 {
-    GetChannel()->GetRTSP()->RemoveListener(this);
+    GetChannel()->RemoveListener(this);
     Stop();
 }
 
@@ -63,7 +60,7 @@
 void FreeboxSignalMonitor::deleteLater(void)
 {
     disconnect(); // disconnect signals we may be sending...
-    GetChannel()->GetRTSP()->RemoveListener(this);
+    GetChannel()->RemoveListener(this);
     Stop();
     DTVSignalMonitor::deleteLater();
 }
@@ -74,11 +71,11 @@
 void FreeboxSignalMonitor::Stop(void)
 {
     DBG_SM("Stop", "begin");
-    GetChannel()->GetRTSP()->RemoveListener(this);
+    GetChannel()->RemoveListener(this);
     SignalMonitor::Stop();
     if (dtvMonitorRunning)
     {
-        GetChannel()->GetRTSP()->Stop();
+        GetChannel()->StreamStop();
         dtvMonitorRunning = false;
         pthread_join(table_monitor_thread, NULL);
     }
@@ -101,16 +98,16 @@
 
     GetStreamData()->AddListeningPID(0);
 
-    GetChannel()->GetRTSP()->AddListener(this);
-    GetChannel()->GetRTSP()->Run();
-    GetChannel()->GetRTSP()->RemoveListener(this);
+    GetChannel()->AddListener(this);
+    GetChannel()->StreamRun();
+    GetChannel()->RemoveListener(this);
 
     dtvMonitorRunning = false;
     DBG_SM("Run", "end");
 }
 
 void FreeboxSignalMonitor::AddData(
-    unsigned char *data, unsigned dataSize, struct timeval)
+    unsigned char *data, unsigned dataSize)
 {
     GetStreamData()->ProcessData(data, dataSize);
 }
Index: libs/libmythtv/udpcomms.cpp
===================================================================
--- libs/libmythtv/udpcomms.cpp	(revision 0)
+++ libs/libmythtv/udpcomms.cpp	(revision 0)
@@ -0,0 +1,237 @@
+/** -*- Mode: c++ -*-
+ *  UDPComms
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#include "udpcomms.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 "mythcontext.h"
+#include "tspacket.h"
+#include "freeboxmediasink.h"
+
+#define LOC QString("UDPComms(%1):").arg(pthread_self())
+
+class TimeoutedTaskScheduler : public BasicTaskScheduler 
+{
+  public:
+    TimeoutedTaskScheduler(unsigned maxDelayTime)
+        : BasicTaskScheduler(), _maxDelayTime(maxDelayTime) {};
+
+    virtual void doEventLoop(char* watchVariable);
+
+  private:
+    unsigned _maxDelayTime;
+};
+
+void TimeoutedTaskScheduler::doEventLoop(char* watchVariable)
+{
+    // Repeatedly loop, handling readble sockets and timed events:
+    while (1)
+    {
+        if (watchVariable != NULL && *watchVariable != 0)
+            break;
+        SingleStep(_maxDelayTime);
+    }
+}
+
+UDPComms::UDPComms() :
+    _abort(0),          _running(false),
+    _live_env(NULL),    _source(NULL),
+    _sink(NULL),        _lock(false)
+{
+    VERBOSE(VB_RECORD, LOC + "ctor -- success");
+}
+
+UDPComms::~UDPComms()
+{
+    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
+    Close();
+    VERBOSE(VB_RECORD, LOC + "dtor -- end");
+}
+
+bool UDPComms::Open(const QString &url)
+{
+    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
+
+    QMutexLocker locker(&_lock);
+
+    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:
+    TaskScheduler *scheduler = new TimeoutedTaskScheduler(3000);
+
+    _live_env = BasicUsageEnvironment::createNew(*scheduler);
+    if (!_live_env)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live Environment.");
+        delete scheduler;
+        return false;
+    }
+    
+    Groupsock *socket = new Groupsock(*_live_env, addr, parse.port(), 0);
+    _source = BasicUDPSource::createNew(*_live_env, socket);
+    if (!_source)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Source.");
+        delete socket;
+        _live_env->reclaim();
+        _live_env = NULL;
+        delete scheduler;
+        return false;
+    }
+
+    _sink = FreeboxMediaSink::CreateNew(*_live_env, TSPacket::SIZE * 128*1024);
+    if (!_sink)
+    {
+        VERBOSE(VB_IMPORTANT,
+                QString("Freebox # Failed to create sink: %1")
+                .arg(_live_env->getResultMsg()));
+        Medium::close(_source);
+        _source=NULL;
+        delete socket;
+        _live_env->reclaim();
+        _live_env = NULL;
+        delete scheduler;
+        return false;
+    }
+    _sink->startPlaying(*_source,NULL,NULL);
+    vector<StreamDataListener*>::iterator it = _listeners.begin();
+    for (; it != _listeners.end(); ++it)
+        _sink->AddListener(*it);
+        
+    VERBOSE(VB_RECORD, LOC + "Open() -- end");
+    return true;
+}
+
+void UDPComms::Close(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
+    Stop();
+
+    QMutexLocker locker(&_lock);
+
+    if (_sink)
+    {
+        Medium::close(_sink);
+        _sink = NULL;
+    }
+
+    if (_source)
+    {
+        Groupsock *socket=_source->gs();
+        Medium::close(_source);
+        _source=NULL;
+        delete socket;
+    }
+
+    if (_live_env)
+    {
+        TaskScheduler *scheduler = &_live_env->taskScheduler();
+        _live_env->reclaim();
+        _live_env = NULL;
+        delete scheduler;
+    }
+    
+    VERBOSE(VB_RECORD, LOC + "Close() -- end");
+}
+
+void UDPComms::Run(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Run() -- begin");
+    {
+        QMutexLocker locker(&_lock);
+        _running = true;
+        _abort   = 0;
+    }
+
+    VERBOSE(VB_RECORD, LOC + "Run() -- loop begin");
+    if (_live_env)
+        _live_env->taskScheduler().doEventLoop(&_abort);
+    VERBOSE(VB_RECORD, LOC + "Run() -- loop end");
+
+    {
+        QMutexLocker locker(&_lock);
+        _running = false;
+        _cond.wakeAll();
+    }
+    VERBOSE(VB_RECORD, LOC + "Run() -- end");
+}
+
+void UDPComms::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 UDPComms::AddListener(StreamDataListener *item)
+{
+    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
+    if (!item)
+    {
+        VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
+        return;
+    }
+
+    // avoid duplicates
+    RemoveListener(item);
+
+    // add to local list
+    QMutexLocker locker(&_lock);
+    _listeners.push_back(item);
+    
+    if (_sink)
+        _sink->AddListener(item);
+    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
+}
+
+void UDPComms::RemoveListener(StreamDataListener *item)
+{
+    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
+    QMutexLocker locker(&_lock);
+    vector<StreamDataListener*>::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 (_sink)
+        _sink->RemoveListener(item);
+    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 2");
+}
Index: libs/libmythtv/freeboxchannel.h
===================================================================
--- libs/libmythtv/freeboxchannel.h	(revision 10744)
+++ libs/libmythtv/freeboxchannel.h	(working copy)
@@ -7,12 +7,16 @@
 #ifndef FREEBOXCHANNEL_H
 #define FREEBOXCHANNEL_H
 
+// C++ headers
+#include <vector>
+
 #include "channelbase.h"
 #include "freeboxchannelinfo.h"
 
 #include <qmutex.h>
 
-class RTSPComms;
+class StreamComms;
+class StreamDataListener;
 
 class FreeboxChannel : public ChannelBase
 {
@@ -32,17 +36,27 @@
     FreeboxChannelInfo GetCurrentChanInfo(void) const
         { return GetChanInfo(curchannelname); }
 
-    RTSPComms       *GetRTSP(void)       { return m_rtsp; }
-    const RTSPComms *GetRTSP(void) const { return m_rtsp; }
-    
+    bool StreamOpen(const QString &url);
+    bool StreamIsOpen(void) const;
+    void StreamClose(void);
+
+    void StreamRun(void);
+    void StreamStop(void);
+
+    void AddListener(StreamDataListener*);
+    void RemoveListener(StreamDataListener*);
+
   private:
     FreeboxChannelInfo GetChanInfo(const QString& channum,
                                    uint           sourceid = 0) const;
 
+    std::vector<StreamDataListener*> _listeners;
+
     QString               m_videodev;
     fbox_chan_map_t       m_freeboxchannels;
-    RTSPComms            *m_rtsp;
+    StreamComms          *m_stream;
     mutable QMutex        m_lock;
+    mutable QMutex        m_list_lock;
 
   private:
     FreeboxChannel& operator=(const FreeboxChannel&); //< avoid default impl
Index: libs/libmythtv/freeboxchannelfetcher.h
===================================================================
--- libs/libmythtv/freeboxchannelfetcher.h	(revision 10744)
+++ 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 10744)
+++ libs/libmythtv/libmythtv.pro	(working copy)
@@ -396,12 +396,14 @@
     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 += rtspcomms.h                 udpcomms.h
+        HEADERS += streamcomms.h
 
         SOURCES += freeboxrecorder.cpp         freeboxmediasink.cpp
         SOURCES += freeboxchannel.cpp          freeboxchannelfetcher.cpp
         SOURCES += freeboxsignalmonitor.cpp    rtspcomms.cpp
+        SOURCES += udpcomms.cpp
 
         DEFINES += USING_FREEBOX
     }
Index: libs/libmythtv/freeboxchannel.cpp
===================================================================
--- libs/libmythtv/freeboxchannel.cpp	(revision 10744)
+++ libs/libmythtv/freeboxchannel.cpp	(working copy)
@@ -5,13 +5,16 @@
  */
 
 #include "freeboxchannel.h"
+using namespace std;
 
 #include <qdeepcopy.h>
 
 #include "libmyth/mythcontext.h"
 #include "libmyth/mythdbcon.h"
 #include "libmythtv/freeboxchannelfetcher.h"
+#include "libmythtv/streamcomms.h"
 #include "libmythtv/rtspcomms.h"
+#include "libmythtv/udpcomms.h"
 
 #define LOC QString("FBChan(%1): ").arg(GetCardID())
 #define LOC_ERR QString("FBChan(%1), Error: ").arg(GetCardID())
@@ -20,8 +23,9 @@
                                const QString &videodev)
     : ChannelBase(parent),
       m_videodev(QDeepCopy<QString>(videodev)),
-      m_rtsp(new RTSPComms()),
-      m_lock(true)
+      m_stream(NULL),
+      m_lock(true),
+      m_list_lock(true)
 {
     VERBOSE(VB_CHANNEL, LOC + "ctor");
 }
@@ -29,10 +33,10 @@
 FreeboxChannel::~FreeboxChannel()
 {
     VERBOSE(VB_CHANNEL, LOC + "dtor -- begin");
-    if (m_rtsp)
+    if (m_stream)
     {
-        delete m_rtsp;
-        m_rtsp = NULL;
+        delete m_stream;
+        m_stream = NULL;
     }
     VERBOSE(VB_CHANNEL, LOC + "dtor -- end");
 }
@@ -206,4 +210,122 @@
     return dummy;
 }
 
+bool FreeboxChannel::StreamOpen(const QString &url)
+{
+    VERBOSE(VB_CHANNEL, LOC + "StreamOpen() -- begin");
+
+    if (url.startsWith("rtsp:"))
+    {
+        if (!dynamic_cast<RTSPComms *>(m_stream))
+        {
+            if (m_stream)
+            {
+                m_stream->Stop();
+                m_stream->Close();
+                delete m_stream;
+                m_stream=NULL;
+            }
+            m_stream=new RTSPComms();
+
+            QMutexLocker locker(&m_list_lock);
+
+            vector<StreamDataListener*>::iterator it = _listeners.begin();
+            for (; it != _listeners.end(); ++it)
+                m_stream->AddListener(*it);
+        }
+    }
+    else if (url.startsWith("udp:")) 
+    {
+        if (!dynamic_cast<UDPComms *>(m_stream))
+        {
+            if (m_stream)
+            {
+                m_stream->Stop();
+                m_stream->Close();
+                delete m_stream;
+                m_stream=NULL;
+            }
+            m_stream=new UDPComms();
+
+            QMutexLocker locker(&m_list_lock);
+
+            vector<StreamDataListener*>::iterator it = _listeners.begin();
+            for (; it != _listeners.end(); ++it)
+                m_stream->AddListener(*it);
+        }
+    }
+    VERBOSE(VB_CHANNEL, LOC + "StreamOpen() -- at the end");
+    if (m_stream)
+        return m_stream->Open(url);
+    else
+        return false;
+}
+
+bool FreeboxChannel::StreamIsOpen(void) const
+{
+    if (m_stream)
+        return m_stream->IsOpen();
+    else
+        return false;
+}
+
+void FreeboxChannel::StreamClose(void)
+{
+    if (m_stream)
+        m_stream->Close();
+}
+
+void FreeboxChannel::StreamRun(void)
+{
+    if (m_stream)
+        m_stream->Run();
+}
+
+void FreeboxChannel::StreamStop(void)
+{
+    if (m_stream)
+        m_stream->Stop();
+}
+
+void FreeboxChannel::AddListener(StreamDataListener *item)
+{
+    VERBOSE(VB_CHANNEL, LOC + "AddListener() -- begin");
+
+    if (!item)
+        return;
+
+    RemoveListener(item);
+
+    // add to local list
+    QMutexLocker locker(&m_list_lock);
+    _listeners.push_back(item);
+    
+    if (m_stream)
+        m_stream->AddListener(item);
+    VERBOSE(VB_CHANNEL, LOC + "AddListener() -- end");
+}
+
+void FreeboxChannel::RemoveListener(StreamDataListener *item)
+{
+    VERBOSE(VB_CHANNEL, LOC + "RemoveListener() -- begin");
+
+    QMutexLocker locker(&m_list_lock);
+    vector<StreamDataListener*>::iterator it =
+        find(_listeners.begin(), _listeners.end(), item);
+
+    if (it == _listeners.end())
+    {
+        VERBOSE(VB_CHANNEL, LOC + "RemoveListener() -- end 1");
+        return;
+    }
+
+    // remove from local list..
+    *it = *_listeners.rbegin();
+    _listeners.resize(_listeners.size() - 1);
+
+    if (m_stream)
+        m_stream->RemoveListener(item);
+    VERBOSE(VB_CHANNEL, LOC + "RemoveListener() -- end 2");
+}
+
 /* vim: set expandtab tabstop=4 shiftwidth=4: */
Index: libs/libmythtv/freeboxmediasink.cpp
===================================================================
--- libs/libmythtv/freeboxmediasink.cpp	(revision 10744)
+++ libs/libmythtv/freeboxmediasink.cpp	(working copy)
@@ -9,10 +9,10 @@
 
 #include "mythcontext.h"
 #include "freeboxmediasink.h"
-#include "rtspcomms.h"
+#include "tspacket.h"
 
-#define LOC QString("RTSPSink:")
-#define LOC_ERR QString("RTSPSink, Error:")
+#define LOC QString("FBSink:")
+#define LOC_ERR QString("FBSink, Error:")
 
 FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment &pEnv,
                                    unsigned int      bufferSize) :
@@ -61,18 +61,18 @@
 }
 
 void FreeboxMediaSink::afterGettingFrame1(unsigned int   frameSize,
-                                          struct timeval presentationTime)
+                                          struct timeval /*presentationTime*/)
 {
     lock.lock();
-    vector<RTSPListener*>::iterator it = listeners.begin();
+    vector<StreamDataListener*>::iterator it = listeners.begin();
     for (; it != listeners.end(); ++it)
-        (*it)->AddData(fBuffer, frameSize, presentationTime);
+        (*it)->AddData(fBuffer, frameSize);
     lock.unlock();
 
     continuePlaying();
 }
 
-void FreeboxMediaSink::AddListener(RTSPListener *item)
+void FreeboxMediaSink::AddListener(StreamDataListener *item)
 {
     VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
     if (item)
@@ -84,11 +84,11 @@
     VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
 }
 
-void FreeboxMediaSink::RemoveListener(RTSPListener *item)
+void FreeboxMediaSink::RemoveListener(StreamDataListener *item)
 {
     VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin 1");
     QMutexLocker locker(&lock);
-    vector<RTSPListener*>::iterator it =
+    vector<StreamDataListener*>::iterator it =
         find(listeners.begin(), listeners.end(), item);
     if (it != listeners.end())
     {
Index: libs/libmythtv/freeboxsignalmonitor.h
===================================================================
--- libs/libmythtv/freeboxsignalmonitor.h	(revision 10744)
+++ libs/libmythtv/freeboxsignalmonitor.h	(working copy)
@@ -4,12 +4,11 @@
 #define _FREEBOXSIGNALMONITOR_H_
 
 #include "dtvsignalmonitor.h"
-#include "freeboxmediasink.h"
+#include "streamcomms.h"
 
-class RTSPComms;
 class FreeboxChannel;
 
-class FreeboxSignalMonitor : public DTVSignalMonitor, public RTSPListener
+class FreeboxSignalMonitor : public DTVSignalMonitor, public StreamDataListener
 {
     Q_OBJECT
 
@@ -21,10 +20,9 @@
 
     void Stop(void);
 
-    // implements RTSPListener
+    // implements StreamDataListener
     void AddData(unsigned char *data,
-                 unsigned       dataSize,
-                 struct timeval);
+                 unsigned       dataSize);
 
   public slots:
     void deleteLater(void);
Index: libs/libmythtv/freeboxchannelfetcher.cpp
===================================================================
--- libs/libmythtv/freeboxchannelfetcher.cpp	(revision 10744)
+++ libs/libmythtv/freeboxchannelfetcher.cpp	(working copy)
@@ -4,6 +4,10 @@
 #include <cmath>
 #include <unistd.h>
 
+// Qt headers
+#include <qnetwork.h>
+#include <qapplication.h>
+
 // MythTV headers
 #include "mythcontext.h"
 #include "httpcomms.h"
@@ -21,6 +25,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 +229,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)
Index: libs/libmythtv/freeboxrecorder.cpp
===================================================================
--- libs/libmythtv/freeboxrecorder.cpp	(revision 10744)
+++ libs/libmythtv/freeboxrecorder.cpp	(working copy)
@@ -15,7 +15,7 @@
 #define LOC_ERR QString("FBRec, Error: ")
 
 // ============================================================================
-// FreeboxRecorder : Processes data from RTSPComms and writes it to disk
+// FreeboxRecorder : Processes data from StreamDataComms and writes it to disk
 // ============================================================================
 
 FreeboxRecorder::FreeboxRecorder(TVRec *rec, FreeboxChannel *channel) :
@@ -23,21 +23,21 @@
     _channel(channel),
     _stream_data(NULL)
 {
-    _channel->GetRTSP()->AddListener(this);
+    _channel->AddListener(this);
 }
 
 FreeboxRecorder::~FreeboxRecorder()
 {
     StopRecording();
-    _channel->GetRTSP()->RemoveListener(this);
+    _channel->RemoveListener(this);
 }
 
 bool FreeboxRecorder::Open(void)
 {
     VERBOSE(VB_RECORD, LOC + "Open() -- begin");
 
-    if (_channel->GetRTSP()->IsOpen())
-        _channel->GetRTSP()->Close();
+    if (_channel->StreamIsOpen())
+        _channel->StreamClose();
 
     FreeboxChannelInfo chaninfo = _channel->GetCurrentChanInfo();
     if (!chaninfo.isValid())
@@ -46,9 +46,7 @@
     }
     else
     {
-        _error = !(_channel->GetRTSP()->Init()); 
-        if (!_error)
-            _error = !(_channel->GetRTSP()->Open(chaninfo.m_url));
+        _error = !(_channel->StreamOpen(chaninfo.m_url));
     }
 
     VERBOSE(VB_RECORD, LOC + "Open() -- end err("<<_error<<")");
@@ -58,24 +56,35 @@
 void FreeboxRecorder::Close(void)
 {
     VERBOSE(VB_RECORD, LOC + "Close() -- begin");
-    _channel->GetRTSP()->Stop();
-    _channel->GetRTSP()->Close();
+    _channel->StreamStop();
+    _channel->StreamClose();
     VERBOSE(VB_RECORD, LOC + "Close() -- end");
 }
 
+void FreeboxRecorder::Reset(void)
+{
+    VERBOSE(VB_RECORD, LOC + "Reset() -- begin");
+    DTVRecorder::Reset();
+    _channel->StreamStop();
+    _channel->StreamClose();
+    if (_stream_data)
+        _stream_data->Reset(_channel->GetProgramNumber());
+    VERBOSE(VB_RECORD, LOC + "Reset() -- end");
+}
+
 void FreeboxRecorder::Pause(bool clear)
 {
     VERBOSE(VB_RECORD, LOC + "Pause() -- begin");
     DTVRecorder::Pause(clear);
-    _channel->GetRTSP()->Stop();
-    _channel->GetRTSP()->Close();
+    _channel->StreamStop();
+    _channel->StreamClose();
     VERBOSE(VB_RECORD, LOC + "Pause() -- end");
 }
 
 void FreeboxRecorder::Unpause(void)
 {
     VERBOSE(VB_RECORD, LOC + "Unpause() -- begin");
-    if (_recording && !_channel->GetRTSP()->IsOpen())
+    if (_recording && !_channel->StreamIsOpen())
         Open();
     DTVRecorder::Unpause();
     VERBOSE(VB_RECORD, LOC + "Unpause() -- end");
@@ -99,14 +108,14 @@
         if (PauseAndWait())
             continue;
 
-        if (!_channel->GetRTSP()->IsOpen())
+        if (!_channel->StreamIsOpen())
         {
             usleep(5000);
             continue;
         }
-
-        // Go into main RTSP loop, feeding data to AddData
-        _channel->GetRTSP()->Run();
+        
+        // Go into main loop, feeding data to AddData
+        _channel->StreamRun();
     }
 
     // Finish up...
@@ -122,12 +131,12 @@
 {
     VERBOSE(VB_RECORD, LOC + "StopRecording() -- begin");
     Pause();
-    _channel->GetRTSP()->Close();
+    _channel->StreamClose();
 
     _request_recording = false;
     while (_recording)
         _cond_recording.wait(500);
-
+    DTVRecorder::StopRecording();
     VERBOSE(VB_RECORD, LOC + "StopRecording() -- end");
 }
 
@@ -150,11 +159,10 @@
 }
 
 // ===================================================
-// AddData : feed data from RTSP flow to mythtv
+// AddData : feed data from flow to mythtv
 // ===================================================
 void FreeboxRecorder::AddData(unsigned char *data,
-                              unsigned       dataSize,
-                              struct timeval)
+                              unsigned       dataSize)
 {
     unsigned int readIndex = 0;
 
@@ -166,8 +174,8 @@
             return;
 
         // Find the next TS Header in data
-        int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize);
-
+        int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize - readIndex);
+        
         // if no TS, something bad happens
         if (tsPos == -1)
         {
@@ -184,7 +192,7 @@
 
         // Check if the next packet in buffer is complete :
         // packet size is 188 bytes long
-        if ((dataSize - tsPos) < TSPacket::SIZE)
+        if ((dataSize - tsPos - readIndex) < TSPacket::SIZE)
         {
             VERBOSE(VB_IMPORTANT, LOC_ERR +
                     "TS packet at stradles end of buffer.");
Index: libs/libmythtv/rtspcomms.cpp
===================================================================
--- libs/libmythtv/rtspcomms.cpp	(revision 10744)
+++ libs/libmythtv/rtspcomms.cpp	(working copy)
@@ -270,7 +270,7 @@
                     .arg(_live_env->getResultMsg()));
         }
 
-        vector<RTSPListener*>::iterator it = _listeners.begin();
+        vector<StreamDataListener*>::iterator it = _listeners.begin();
         for (; it != _listeners.end(); ++it)
             freeboxMediaSink->AddListener(*it);
 
@@ -367,7 +367,7 @@
     VERBOSE(VB_RECORD, LOC + "Stop() -- end");
 }
 
-void RTSPComms::AddListener(RTSPListener *item)
+void RTSPComms::AddListener(StreamDataListener *item)
 {
     VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
     if (!item)
@@ -401,11 +401,11 @@
     VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 2");
 }
 
-void RTSPComms::RemoveListener(RTSPListener *item)
+void RTSPComms::RemoveListener(StreamDataListener *item)
 {
     VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
     QMutexLocker locker(&_lock);
-    vector<RTSPListener*>::iterator it =
+    vector<StreamDataListener*>::iterator it =
         find(_listeners.begin(), _listeners.end(), item);
 
     if (it == _listeners.end())
Index: libs/libmythtv/udpcomms.h
===================================================================
--- libs/libmythtv/udpcomms.h	(revision 0)
+++ libs/libmythtv/udpcomms.h	(revision 0)
@@ -0,0 +1,54 @@
+/** -*- Mode: c++ -*-
+ *  RTSPComms
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef UDPCOMMS_H
+#define UDPCOMMS_H
+
+// C++ headers
+#include <vector>
+using namespace std;
+
+// Qt headers
+#include <qwaitcondition.h>
+#include <qmutex.h>
+
+// MythTV headers
+#include "streamcomms.h"
+
+class UsageEnvironment;
+class BasicUDPSource;
+class FreeboxMediaSink;
+class StreamDataListener;
+
+class UDPComms : public StreamComms
+{
+  public:
+    UDPComms();
+    virtual ~UDPComms();
+
+    bool Open(const QString &url);
+    bool IsOpen(void) const { return _source; }
+    void Close(void);
+
+    void Run(void);
+    void Stop(void);
+
+    void AddListener(StreamDataListener*);
+    void RemoveListener(StreamDataListener*);
+
+  private:
+
+    char                _abort;
+    bool                _running;
+    UsageEnvironment   *_live_env;
+    BasicUDPSource     *_source;
+    FreeboxMediaSink   *_sink;
+    vector<StreamDataListener*> _listeners;
+    QWaitCondition      _cond;       ///< Condition  used to coordinate threads
+    mutable QMutex      _lock;       ///< Lock  used to coordinate threads
+};
+
+#endif
Index: libs/libmythtv/streamcomms.h
===================================================================
--- libs/libmythtv/streamcomms.h	(revision 0)
+++ libs/libmythtv/streamcomms.h	(revision 0)
@@ -0,0 +1,39 @@
+/** -*- Mode: c++ -*-
+ *  StreamComms
+ *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+#ifndef _STREAMCOMMS_H_
+#define _STREAMCOMMS_H_
+
+class StreamDataListener
+{
+  public:
+    /// Callback function to add MPEG2 TS data
+    virtual void AddData(unsigned char *data,
+                         unsigned int   dataSize) = 0;
+  protected:
+    virtual ~StreamDataListener() {}
+};
+
+class QString;
+
+class StreamComms
+{
+  public:
+    StreamComms(){};
+    virtual ~StreamComms(){};
+
+    virtual bool Open(const QString &url) = 0;
+    virtual bool IsOpen(void) const = 0;
+    virtual void Close(void) = 0;
+
+    virtual void Run(void) = 0;
+    virtual void Stop(void) = 0;
+
+    virtual void AddListener(StreamDataListener*) = 0;
+    virtual void RemoveListener(StreamDataListener*) = 0;
+};
+
+#endif
Index: libs/libmythtv/freeboxmediasink.h
===================================================================
--- libs/libmythtv/freeboxmediasink.h	(revision 10744)
+++ libs/libmythtv/freeboxmediasink.h	(working copy)
@@ -14,16 +14,7 @@
 
 #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() {}
-};
+#include "streamcomms.h"
 
 // ============================================================================
 // FreeboxMediaSink : Helper class use to receive RTSP data from socket.
@@ -34,8 +25,8 @@
     static FreeboxMediaSink *CreateNew(UsageEnvironment &env,
                                        unsigned          bufferSize);
 
-    void AddListener(RTSPListener*);
-    void RemoveListener(RTSPListener*);
+    void AddListener(StreamDataListener*);
+    void RemoveListener(StreamDataListener*);
 
   protected:
     FreeboxMediaSink(UsageEnvironment &env,
@@ -58,7 +49,7 @@
     unsigned char         *fBuffer;
     unsigned int           fBufferSize;
     UsageEnvironment      &env;
-    vector<RTSPListener*>  listeners;
+    vector<StreamDataListener*>  listeners;
     mutable QMutex         lock;
 
   private:
Index: libs/libmythtv/freeboxrecorder.h
===================================================================
--- libs/libmythtv/freeboxrecorder.h	(revision 10744)
+++ libs/libmythtv/freeboxrecorder.h	(working copy)
@@ -10,25 +10,22 @@
 #include <qwaitcondition.h>
 
 #include "dtvrecorder.h"
-#include "freeboxmediasink.h"
-#include "streamlisteners.h"
+#include "streamcomms.h"
 
 class FreeboxChannel;
 
-/** \brief Processes data from RTSPComms and writes it to disk.
+/** \brief Processes data from StreamComms and writes it to disk.
  */
-class FreeboxRecorder : public DTVRecorder, public RTSPListener,
+class FreeboxRecorder : public DTVRecorder, public StreamDataListener,
                         public MPEGSingleProgramStreamListener
 {
-    friend class FreeboxMediaSink;
-    friend class RTSPComms;
-
   public:
     FreeboxRecorder(TVRec *rec, FreeboxChannel *channel);
     ~FreeboxRecorder();
 
     bool Open(void);
     void Close(void);
+    void Reset(void);
 
     virtual void Pause(bool clear = true);
     virtual void Unpause(void);
@@ -45,10 +42,9 @@
   private:
     void ProcessTSPacket(const TSPacket& tspacket);
 
-    // implements RTSPListener
+    // implements StreamDataListener
     void AddData(unsigned char *data,
-                 unsigned int   dataSize,
-                 struct timeval presentationTime);
+                 unsigned int   dataSize);
 
     // implements MPEGSingleProgramStreamListener
     void HandleSingleProgramPAT(ProgramAssociationTable *pat);
Index: libs/libmythtv/rtspcomms.h
===================================================================
--- libs/libmythtv/rtspcomms.h	(revision 10744)
+++ libs/libmythtv/rtspcomms.h	(working copy)
@@ -4,6 +4,9 @@
  *  Distributed as part of MythTV under GPL v2 and later.
  */
 
+#ifndef RTSPCOMMS_H
+#define RTSPCOMMS_H
+
 // C++ headers
 #include <vector>
 using namespace std;
@@ -13,14 +16,14 @@
 #include <qmutex.h>
 
 // MythTV headers
-#include "freeboxchannel.h"
+#include "streamcomms.h"
 
 class UsageEnvironment;
 class RTSPClient;
 class MediaSession;
-class RTSPListener;
+class StreamDataListener;
 
-class RTSPComms 
+class RTSPComms : public StreamComms
 {
   public:
     RTSPComms();
@@ -36,8 +39,8 @@
     void Run(void);
     void Stop(void);
 
-    void AddListener(RTSPListener*);
-    void RemoveListener(RTSPListener*);
+    void AddListener(StreamDataListener*);
+    void RemoveListener(StreamDataListener*);
 
   private:
 
@@ -46,7 +49,9 @@
     UsageEnvironment   *_live_env;
     RTSPClient         *_rtsp_client;
     MediaSession       *_session;
-    vector<RTSPListener*> _listeners;
+    vector<StreamDataListener*> _listeners;
     QWaitCondition      _cond;       ///< Condition  used to coordinate threads
     mutable QMutex      _lock;       ///< Lock  used to coordinate threads
 };
+
+#endif
