Ticket #2152: udp.patch

File udp.patch, 34.7 KB (added by mikemiron@…, 19 years ago)

Alternative version

  • libs/libmythtv/freeboxsignalmonitor.cpp

     
    22
    33// MythTV headers
    44#include "mpegstreamdata.h"
     5#include "freeboxchannel.h"
    56#include "freeboxsignalmonitor.h"
    67#include "rtspcomms.h"
    78
     
    3334    : DTVSignalMonitor(db_cardnum, _channel, _flags, _name),
    3435      dtvMonitorRunning(false)
    3536{
    36     bool isLocked = false;
    37     if (GetChannel()->GetRTSP()->Init())
    38     {
    39         FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo();
    40         isLocked = (chaninfo.isValid() &&
    41                     GetChannel()->GetRTSP()->Open(chaninfo.m_url));
    42     }
     37    FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo();
     38    bool isLocked = (chaninfo.isValid() &&
     39                GetChannel()->StreamOpen(chaninfo.m_url));
    4340
    4441    QMutexLocker locker(&statusLock);
    4542    signalLock.SetValue((isLocked) ? 1 : 0);
     
    5148 */
    5249FreeboxSignalMonitor::~FreeboxSignalMonitor()
    5350{
    54     GetChannel()->GetRTSP()->RemoveListener(this);
     51    GetChannel()->RemoveListener(this);
    5552    Stop();
    5653}
    5754
     
    6360void FreeboxSignalMonitor::deleteLater(void)
    6461{
    6562    disconnect(); // disconnect signals we may be sending...
    66     GetChannel()->GetRTSP()->RemoveListener(this);
     63    GetChannel()->RemoveListener(this);
    6764    Stop();
    6865    DTVSignalMonitor::deleteLater();
    6966}
     
    7471void FreeboxSignalMonitor::Stop(void)
    7572{
    7673    DBG_SM("Stop", "begin");
    77     GetChannel()->GetRTSP()->RemoveListener(this);
     74    GetChannel()->RemoveListener(this);
    7875    SignalMonitor::Stop();
    7976    if (dtvMonitorRunning)
    8077    {
    81         GetChannel()->GetRTSP()->Stop();
     78        GetChannel()->StreamStop();
    8279        dtvMonitorRunning = false;
    8380        pthread_join(table_monitor_thread, NULL);
    8481    }
     
    10198
    10299    GetStreamData()->AddListeningPID(0);
    103100
    104     GetChannel()->GetRTSP()->AddListener(this);
    105     GetChannel()->GetRTSP()->Run();
    106     GetChannel()->GetRTSP()->RemoveListener(this);
     101    GetChannel()->AddListener(this);
     102    GetChannel()->StreamRun();
     103    GetChannel()->RemoveListener(this);
    107104
    108105    dtvMonitorRunning = false;
    109106    DBG_SM("Run", "end");
    110107}
    111108
    112109void FreeboxSignalMonitor::AddData(
    113     unsigned char *data, unsigned dataSize, struct timeval)
     110    unsigned char *data, unsigned dataSize)
    114111{
    115112    GetStreamData()->ProcessData(data, dataSize);
    116113}
  • libs/libmythtv/udpcomms.cpp

     
     1/** -*- Mode: c++ -*-
     2 *  UDPComms
     3 *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
     4 *  Distributed as part of MythTV under GPL v2 and later.
     5 */
     6
     7#include "udpcomms.h"
     8
     9// Qt headers
     10#include <qurl.h>
     11
     12// Live555 headers
     13#include <BasicUsageEnvironment.hh>
     14#include <Groupsock.hh>
     15#include <GroupsockHelper.hh>
     16#include <BasicUDPSource.hh>
     17#include <TunnelEncaps.hh>
     18
     19// MythTV headers
     20#include "mythcontext.h"
     21#include "tspacket.h"
     22#include "freeboxmediasink.h"
     23
     24#define LOC QString("UDPComms(%1):").arg(pthread_self())
     25
     26class TimeoutedTaskScheduler : public BasicTaskScheduler
     27{
     28  public:
     29    TimeoutedTaskScheduler(unsigned maxDelayTime)
     30        : BasicTaskScheduler(), _maxDelayTime(maxDelayTime) {};
     31
     32    virtual void doEventLoop(char* watchVariable);
     33
     34  private:
     35    unsigned _maxDelayTime;
     36};
     37
     38void TimeoutedTaskScheduler::doEventLoop(char* watchVariable)
     39{
     40    // Repeatedly loop, handling readble sockets and timed events:
     41    while (1)
     42    {
     43        if (watchVariable != NULL && *watchVariable != 0)
     44            break;
     45        SingleStep(_maxDelayTime);
     46    }
     47}
     48
     49UDPComms::UDPComms() :
     50    _abort(0),          _running(false),
     51    _live_env(NULL),    _source(NULL),
     52    _sink(NULL),        _lock(false)
     53{
     54    VERBOSE(VB_RECORD, LOC + "ctor -- success");
     55}
     56
     57UDPComms::~UDPComms()
     58{
     59    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
     60    Close();
     61    VERBOSE(VB_RECORD, LOC + "dtor -- end");
     62}
     63
     64bool UDPComms::Open(const QString &url)
     65{
     66    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
     67
     68    QMutexLocker locker(&_lock);
     69
     70    if (_source)
     71    {
     72        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
     73        return true;
     74    }
     75       
     76    QUrl parse(url);
     77    if (!parse.isValid() || !parse.hasHost() || !parse.hasPort())
     78    {
     79        VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
     80        return false;
     81    }
     82       
     83    struct in_addr addr;
     84    addr.s_addr = our_inet_addr(parse.host().latin1());
     85
     86    // Begin by setting up our usage environment:
     87    TaskScheduler *scheduler = new TimeoutedTaskScheduler(3000);
     88
     89    _live_env = BasicUsageEnvironment::createNew(*scheduler);
     90    if (!_live_env)
     91    {
     92        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live Environment.");
     93        delete scheduler;
     94        return false;
     95    }
     96   
     97    Groupsock *socket = new Groupsock(*_live_env, addr, parse.port(), 0);
     98    _source = BasicUDPSource::createNew(*_live_env, socket);
     99    if (!_source)
     100    {
     101        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Source.");
     102        delete socket;
     103        _live_env->reclaim();
     104        _live_env = NULL;
     105        delete scheduler;
     106        return false;
     107    }
     108
     109    _sink = FreeboxMediaSink::CreateNew(*_live_env, TSPacket::SIZE * 128*1024);
     110    if (!_sink)
     111    {
     112        VERBOSE(VB_IMPORTANT,
     113                QString("Freebox # Failed to create sink: %1")
     114                .arg(_live_env->getResultMsg()));
     115        Medium::close(_source);
     116        _source=NULL;
     117        delete socket;
     118        _live_env->reclaim();
     119        _live_env = NULL;
     120        delete scheduler;
     121        return false;
     122    }
     123    _sink->startPlaying(*_source,NULL,NULL);
     124    vector<StreamDataListener*>::iterator it = _listeners.begin();
     125    for (; it != _listeners.end(); ++it)
     126        _sink->AddListener(*it);
     127       
     128    VERBOSE(VB_RECORD, LOC + "Open() -- end");
     129    return true;
     130}
     131
     132void UDPComms::Close(void)
     133{
     134    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
     135    Stop();
     136
     137    QMutexLocker locker(&_lock);
     138
     139    if (_sink)
     140    {
     141        Medium::close(_sink);
     142        _sink = NULL;
     143    }
     144
     145    if (_source)
     146    {
     147        Groupsock *socket=_source->gs();
     148        Medium::close(_source);
     149        _source=NULL;
     150        delete socket;
     151    }
     152
     153    if (_live_env)
     154    {
     155        TaskScheduler *scheduler = &_live_env->taskScheduler();
     156        _live_env->reclaim();
     157        _live_env = NULL;
     158        delete scheduler;
     159    }
     160   
     161    VERBOSE(VB_RECORD, LOC + "Close() -- end");
     162}
     163
     164void UDPComms::Run(void)
     165{
     166    VERBOSE(VB_RECORD, LOC + "Run() -- begin");
     167    {
     168        QMutexLocker locker(&_lock);
     169        _running = true;
     170        _abort   = 0;
     171    }
     172
     173    VERBOSE(VB_RECORD, LOC + "Run() -- loop begin");
     174    if (_live_env)
     175        _live_env->taskScheduler().doEventLoop(&_abort);
     176    VERBOSE(VB_RECORD, LOC + "Run() -- loop end");
     177
     178    {
     179        QMutexLocker locker(&_lock);
     180        _running = false;
     181        _cond.wakeAll();
     182    }
     183    VERBOSE(VB_RECORD, LOC + "Run() -- end");
     184}
     185
     186void UDPComms::Stop(void)
     187{
     188    VERBOSE(VB_RECORD, LOC + "Stop() -- begin");
     189    QMutexLocker locker(&_lock);
     190    _abort = 0xFF;
     191
     192    while (_running)
     193        _cond.wait(&_lock, 500);
     194    VERBOSE(VB_RECORD, LOC + "Stop() -- end");
     195}
     196
     197void UDPComms::AddListener(StreamDataListener *item)
     198{
     199    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
     200    if (!item)
     201    {
     202        VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
     203        return;
     204    }
     205
     206    // avoid duplicates
     207    RemoveListener(item);
     208
     209    // add to local list
     210    QMutexLocker locker(&_lock);
     211    _listeners.push_back(item);
     212   
     213    if (_sink)
     214        _sink->AddListener(item);
     215    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
     216}
     217
     218void UDPComms::RemoveListener(StreamDataListener *item)
     219{
     220    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
     221    QMutexLocker locker(&_lock);
     222    vector<StreamDataListener*>::iterator it =
     223        find(_listeners.begin(), _listeners.end(), item);
     224
     225    if (it == _listeners.end())
     226    {
     227        VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 1");
     228        return;
     229    }
     230
     231    // remove from local list..
     232    *it = *_listeners.rbegin();
     233    _listeners.resize(_listeners.size() - 1);
     234    if (_sink)
     235        _sink->RemoveListener(item);
     236    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 2");
     237}
  • libs/libmythtv/freeboxchannel.h

     
    77#ifndef FREEBOXCHANNEL_H
    88#define FREEBOXCHANNEL_H
    99
     10// C++ headers
     11#include <vector>
     12
    1013#include "channelbase.h"
    1114#include "freeboxchannelinfo.h"
    1215
    1316#include <qmutex.h>
    1417
    15 class RTSPComms;
     18class StreamComms;
     19class StreamDataListener;
    1620
    1721class FreeboxChannel : public ChannelBase
    1822{
     
    3236    FreeboxChannelInfo GetCurrentChanInfo(void) const
    3337        { return GetChanInfo(curchannelname); }
    3438
    35     RTSPComms       *GetRTSP(void)       { return m_rtsp; }
    36     const RTSPComms *GetRTSP(void) const { return m_rtsp; }
    37    
     39    bool StreamOpen(const QString &url);
     40    bool StreamIsOpen(void) const;
     41    void StreamClose(void);
     42
     43    void StreamRun(void);
     44    void StreamStop(void);
     45
     46    void AddListener(StreamDataListener*);
     47    void RemoveListener(StreamDataListener*);
     48
    3849  private:
    3950    FreeboxChannelInfo GetChanInfo(const QString& channum,
    4051                                   uint           sourceid = 0) const;
    4152
     53    std::vector<StreamDataListener*> _listeners;
     54
    4255    QString               m_videodev;
    4356    fbox_chan_map_t       m_freeboxchannels;
    44     RTSPComms            *m_rtsp;
     57    StreamComms          *m_stream;
    4558    mutable QMutex        m_lock;
     59    mutable QMutex        m_list_lock;
    4660
    4761  private:
    4862    FreeboxChannel& operator=(const FreeboxChannel&); //< avoid default impl
  • libs/libmythtv/freeboxchannelfetcher.h

     
    77// Qt headers
    88#include <qobject.h>
    99#include <qmutex.h>
     10#include <qurloperator.h>
    1011
    1112// MythTV headers
    1213#include "freeboxchannelinfo.h"
    1314
     15class FreeboxUrlFetch : public QObject
     16{
     17    Q_OBJECT
     18
     19  private:
     20    FreeboxUrlFetch(const QString& url);
     21    ~FreeboxUrlFetch();
     22
     23    QUrlOperator *op;
     24    QNetworkProtocol::State state;
     25    QString str;
     26
     27  private slots:
     28    void finished(QNetworkOperation *op);
     29    void data(const QByteArray &data,QNetworkOperation *op);
     30
     31  public:
     32    static QString fetchData(const QString &url,bool inQtThread);
     33};
     34
    1435class FreeboxChannelFetcher : public QObject
    1536{
    1637    Q_OBJECT
  • libs/libmythtv/libmythtv.pro

     
    396396    using_freebox {
    397397        HEADERS += freeboxrecorder.h           freeboxmediasink.h
    398398        HEADERS += freeboxchannel.h            freeboxchannelfetcher.h
    399         HEADERS += freeboxsignalmonitor.h      rtspcomms.h
    400         HEADERS += freeboxchannelinfo.h
     399        HEADERS += freeboxsignalmonitor.h      freeboxchannelinfo.h
     400        HEADERS += rtspcomms.h                 udpcomms.h
     401        HEADERS += streamcomms.h
    401402
    402403        SOURCES += freeboxrecorder.cpp         freeboxmediasink.cpp
    403404        SOURCES += freeboxchannel.cpp          freeboxchannelfetcher.cpp
    404405        SOURCES += freeboxsignalmonitor.cpp    rtspcomms.cpp
     406        SOURCES += udpcomms.cpp
    405407
    406408        DEFINES += USING_FREEBOX
    407409    }
  • libs/libmythtv/freeboxchannel.cpp

     
    55 */
    66
    77#include "freeboxchannel.h"
     8using namespace std;
    89
    910#include <qdeepcopy.h>
    1011
    1112#include "libmyth/mythcontext.h"
    1213#include "libmyth/mythdbcon.h"
    1314#include "libmythtv/freeboxchannelfetcher.h"
     15#include "libmythtv/streamcomms.h"
    1416#include "libmythtv/rtspcomms.h"
     17#include "libmythtv/udpcomms.h"
    1518
    1619#define LOC QString("FBChan(%1): ").arg(GetCardID())
    1720#define LOC_ERR QString("FBChan(%1), Error: ").arg(GetCardID())
     
    2023                               const QString &videodev)
    2124    : ChannelBase(parent),
    2225      m_videodev(QDeepCopy<QString>(videodev)),
    23       m_rtsp(new RTSPComms()),
    24       m_lock(true)
     26      m_stream(NULL),
     27      m_lock(true),
     28      m_list_lock(true)
    2529{
    2630    VERBOSE(VB_CHANNEL, LOC + "ctor");
    2731}
     
    2933FreeboxChannel::~FreeboxChannel()
    3034{
    3135    VERBOSE(VB_CHANNEL, LOC + "dtor -- begin");
    32     if (m_rtsp)
     36    if (m_stream)
    3337    {
    34         delete m_rtsp;
    35         m_rtsp = NULL;
     38        delete m_stream;
     39        m_stream = NULL;
    3640    }
    3741    VERBOSE(VB_CHANNEL, LOC + "dtor -- end");
    3842}
     
    206210    return dummy;
    207211}
    208212
     213bool FreeboxChannel::StreamOpen(const QString &url)
     214{
     215    VERBOSE(VB_CHANNEL, LOC + "StreamOpen() -- begin");
     216
     217    if (url.startsWith("rtsp:"))
     218    {
     219        if (!dynamic_cast<RTSPComms *>(m_stream))
     220        {
     221            if (m_stream)
     222            {
     223                m_stream->Stop();
     224                m_stream->Close();
     225                delete m_stream;
     226                m_stream=NULL;
     227            }
     228            m_stream=new RTSPComms();
     229
     230            QMutexLocker locker(&m_list_lock);
     231
     232            vector<StreamDataListener*>::iterator it = _listeners.begin();
     233            for (; it != _listeners.end(); ++it)
     234                m_stream->AddListener(*it);
     235        }
     236    }
     237    else if (url.startsWith("udp:"))
     238    {
     239        if (!dynamic_cast<UDPComms *>(m_stream))
     240        {
     241            if (m_stream)
     242            {
     243                m_stream->Stop();
     244                m_stream->Close();
     245                delete m_stream;
     246                m_stream=NULL;
     247            }
     248            m_stream=new UDPComms();
     249
     250            QMutexLocker locker(&m_list_lock);
     251
     252            vector<StreamDataListener*>::iterator it = _listeners.begin();
     253            for (; it != _listeners.end(); ++it)
     254                m_stream->AddListener(*it);
     255        }
     256    }
     257    VERBOSE(VB_CHANNEL, LOC + "StreamOpen() -- at the end");
     258    if (m_stream)
     259        return m_stream->Open(url);
     260    else
     261        return false;
     262}
     263
     264bool FreeboxChannel::StreamIsOpen(void) const
     265{
     266    if (m_stream)
     267        return m_stream->IsOpen();
     268    else
     269        return false;
     270}
     271
     272void FreeboxChannel::StreamClose(void)
     273{
     274    if (m_stream)
     275        m_stream->Close();
     276}
     277
     278void FreeboxChannel::StreamRun(void)
     279{
     280    if (m_stream)
     281        m_stream->Run();
     282}
     283
     284void FreeboxChannel::StreamStop(void)
     285{
     286    if (m_stream)
     287        m_stream->Stop();
     288}
     289
     290void FreeboxChannel::AddListener(StreamDataListener *item)
     291{
     292    VERBOSE(VB_CHANNEL, LOC + "AddListener() -- begin");
     293
     294    if (!item)
     295        return;
     296
     297    RemoveListener(item);
     298
     299    // add to local list
     300    QMutexLocker locker(&m_list_lock);
     301    _listeners.push_back(item);
     302   
     303    if (m_stream)
     304        m_stream->AddListener(item);
     305    VERBOSE(VB_CHANNEL, LOC + "AddListener() -- end");
     306}
     307
     308void FreeboxChannel::RemoveListener(StreamDataListener *item)
     309{
     310    VERBOSE(VB_CHANNEL, LOC + "RemoveListener() -- begin");
     311
     312    QMutexLocker locker(&m_list_lock);
     313    vector<StreamDataListener*>::iterator it =
     314        find(_listeners.begin(), _listeners.end(), item);
     315
     316    if (it == _listeners.end())
     317    {
     318        VERBOSE(VB_CHANNEL, LOC + "RemoveListener() -- end 1");
     319        return;
     320    }
     321
     322    // remove from local list..
     323    *it = *_listeners.rbegin();
     324    _listeners.resize(_listeners.size() - 1);
     325
     326    if (m_stream)
     327        m_stream->RemoveListener(item);
     328    VERBOSE(VB_CHANNEL, LOC + "RemoveListener() -- end 2");
     329}
     330
    209331/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/freeboxmediasink.cpp

     
    99
    1010#include "mythcontext.h"
    1111#include "freeboxmediasink.h"
    12 #include "rtspcomms.h"
     12#include "tspacket.h"
    1313
    14 #define LOC QString("RTSPSink:")
    15 #define LOC_ERR QString("RTSPSink, Error:")
     14#define LOC QString("FBSink:")
     15#define LOC_ERR QString("FBSink, Error:")
    1616
    1717FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment &pEnv,
    1818                                   unsigned int      bufferSize) :
     
    6161}
    6262
    6363void FreeboxMediaSink::afterGettingFrame1(unsigned int   frameSize,
    64                                           struct timeval presentationTime)
     64                                          struct timeval /*presentationTime*/)
    6565{
    6666    lock.lock();
    67     vector<RTSPListener*>::iterator it = listeners.begin();
     67    vector<StreamDataListener*>::iterator it = listeners.begin();
    6868    for (; it != listeners.end(); ++it)
    69         (*it)->AddData(fBuffer, frameSize, presentationTime);
     69        (*it)->AddData(fBuffer, frameSize);
    7070    lock.unlock();
    7171
    7272    continuePlaying();
    7373}
    7474
    75 void FreeboxMediaSink::AddListener(RTSPListener *item)
     75void FreeboxMediaSink::AddListener(StreamDataListener *item)
    7676{
    7777    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
    7878    if (item)
     
    8484    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");
    8585}
    8686
    87 void FreeboxMediaSink::RemoveListener(RTSPListener *item)
     87void FreeboxMediaSink::RemoveListener(StreamDataListener *item)
    8888{
    8989    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin 1");
    9090    QMutexLocker locker(&lock);
    91     vector<RTSPListener*>::iterator it =
     91    vector<StreamDataListener*>::iterator it =
    9292        find(listeners.begin(), listeners.end(), item);
    9393    if (it != listeners.end())
    9494    {
  • libs/libmythtv/freeboxsignalmonitor.h

     
    44#define _FREEBOXSIGNALMONITOR_H_
    55
    66#include "dtvsignalmonitor.h"
    7 #include "freeboxmediasink.h"
     7#include "streamcomms.h"
    88
    9 class RTSPComms;
    109class FreeboxChannel;
    1110
    12 class FreeboxSignalMonitor : public DTVSignalMonitor, public RTSPListener
     11class FreeboxSignalMonitor : public DTVSignalMonitor, public StreamDataListener
    1312{
    1413    Q_OBJECT
    1514
     
    2120
    2221    void Stop(void);
    2322
    24     // implements RTSPListener
     23    // implements StreamDataListener
    2524    void AddData(unsigned char *data,
    26                  unsigned       dataSize,
    27                  struct timeval);
     25                 unsigned       dataSize);
    2826
    2927  public slots:
    3028    void deleteLater(void);
  • libs/libmythtv/freeboxchannelfetcher.cpp

     
    44#include <cmath>
    55#include <unistd.h>
    66
     7// Qt headers
     8#include <qnetwork.h>
     9#include <qapplication.h>
     10
    711// MythTV headers
    812#include "mythcontext.h"
    913#include "httpcomms.h"
     
    2125static bool parse_extinf(const QString &data,
    2226                         QString &channum, QString &name);
    2327
     28FreeboxUrlFetch::FreeboxUrlFetch(const QString& url)
     29    :   op(new QUrlOperator(url)),
     30    state(QNetworkProtocol::StInProgress),
     31    str("")
     32{
     33    connect(op,   SIGNAL( finished(QNetworkOperation *)),
     34            this, SLOT(   finished(QNetworkOperation *)));
     35    connect(op,   SIGNAL( data(const QByteArray &,QNetworkOperation *)),
     36            this, SLOT(   data(const QByteArray &,QNetworkOperation *)));
     37    op->get();
     38}
     39
     40FreeboxUrlFetch::~FreeboxUrlFetch()
     41{
     42    disconnect();
     43    delete op;
     44    op=NULL;
     45}
     46
     47void FreeboxUrlFetch::finished(QNetworkOperation *op)
     48{
     49    state = op->state();
     50}
     51
     52void FreeboxUrlFetch::data(const QByteArray &data,QNetworkOperation *op)
     53{
     54    if (!data.isNull())
     55        str += QString::fromUtf8(data.data(),data.size());
     56    state = op->state();
     57}
     58
     59QString FreeboxUrlFetch::fetchData(const QString &url,bool inQtThread)
     60{
     61    FreeboxUrlFetch obj(url);
     62    while(obj.state==QNetworkProtocol::StWaiting ||
     63            obj.state==QNetworkProtocol::StInProgress)
     64    {
     65        if (inQtThread)
     66            qApp->processEvents();
     67        usleep(1000);
     68    }
     69    if (obj.state==QNetworkProtocol::StDone)
     70        return obj.str;
     71    else // QNetworkProtocol::StFailed || QNetworkProtocol::StStopped
     72        return QString::null;
     73}
     74
     75
    2476FreeboxChannelFetcher::FreeboxChannelFetcher(unsigned _sourceid,
    2577                                             unsigned _cardid) :
    2678    sourceid(_sourceid),    cardid(_cardid),
     
    177229QString FreeboxChannelFetcher::DownloadPlaylist(const QString &url,
    178230                                                bool inQtThread)
    179231{
    180     QString redirected_url = url;
     232    if (url.startsWith("http:")) {
     233        // Use Myth HttpComms for http URLs
     234        QString redirected_url = url;
    181235
    182     QString tmp = HttpComms::getHttp(
    183         redirected_url,
    184         10000 /* ms        */, 3     /* retries      */,
    185         3     /* redirects */, true  /* allow gzip   */,
    186         NULL  /* login     */, inQtThread);
     236        QString tmp = HttpComms::getHttp(
     237            redirected_url,
     238            10000 /* ms        */, 3     /* retries      */,
     239            3     /* redirects */, true  /* allow gzip   */,
     240            NULL  /* login     */, inQtThread);
    187241
    188     if (redirected_url != url)
    189     {
    190         VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1")
    191                 .arg(redirected_url));
    192     }
     242        if (redirected_url != url)
     243        {
     244            VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1")
     245                    .arg(redirected_url));
     246        }
    193247
    194     return QString::fromUtf8(tmp);
     248        return QString::fromUtf8(tmp);
     249    } else
     250        return FreeboxUrlFetch::fetchData(url,inQtThread);
    195251}
    196252
    197253static uint estimate_number_of_channels(const QString &rawdata)
  • libs/libmythtv/freeboxrecorder.cpp

     
    1515#define LOC_ERR QString("FBRec, Error: ")
    1616
    1717// ============================================================================
    18 // FreeboxRecorder : Processes data from RTSPComms and writes it to disk
     18// FreeboxRecorder : Processes data from StreamDataComms and writes it to disk
    1919// ============================================================================
    2020
    2121FreeboxRecorder::FreeboxRecorder(TVRec *rec, FreeboxChannel *channel) :
     
    2323    _channel(channel),
    2424    _stream_data(NULL)
    2525{
    26     _channel->GetRTSP()->AddListener(this);
     26    _channel->AddListener(this);
    2727}
    2828
    2929FreeboxRecorder::~FreeboxRecorder()
    3030{
    3131    StopRecording();
    32     _channel->GetRTSP()->RemoveListener(this);
     32    _channel->RemoveListener(this);
    3333}
    3434
    3535bool FreeboxRecorder::Open(void)
    3636{
    3737    VERBOSE(VB_RECORD, LOC + "Open() -- begin");
    3838
    39     if (_channel->GetRTSP()->IsOpen())
    40         _channel->GetRTSP()->Close();
     39    if (_channel->StreamIsOpen())
     40        _channel->StreamClose();
    4141
    4242    FreeboxChannelInfo chaninfo = _channel->GetCurrentChanInfo();
    4343    if (!chaninfo.isValid())
     
    4646    }
    4747    else
    4848    {
    49         _error = !(_channel->GetRTSP()->Init());
    50         if (!_error)
    51             _error = !(_channel->GetRTSP()->Open(chaninfo.m_url));
     49        _error = !(_channel->StreamOpen(chaninfo.m_url));
    5250    }
    5351
    5452    VERBOSE(VB_RECORD, LOC + "Open() -- end err("<<_error<<")");
     
    5856void FreeboxRecorder::Close(void)
    5957{
    6058    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
    61     _channel->GetRTSP()->Stop();
    62     _channel->GetRTSP()->Close();
     59    _channel->StreamStop();
     60    _channel->StreamClose();
    6361    VERBOSE(VB_RECORD, LOC + "Close() -- end");
    6462}
    6563
     64void FreeboxRecorder::Reset(void)
     65{
     66    VERBOSE(VB_RECORD, LOC + "Reset() -- begin");
     67    DTVRecorder::Reset();
     68    _channel->StreamStop();
     69    _channel->StreamClose();
     70    if (_stream_data)
     71        _stream_data->Reset(_channel->GetProgramNumber());
     72    VERBOSE(VB_RECORD, LOC + "Reset() -- end");
     73}
     74
    6675void FreeboxRecorder::Pause(bool clear)
    6776{
    6877    VERBOSE(VB_RECORD, LOC + "Pause() -- begin");
    6978    DTVRecorder::Pause(clear);
    70     _channel->GetRTSP()->Stop();
    71     _channel->GetRTSP()->Close();
     79    _channel->StreamStop();
     80    _channel->StreamClose();
    7281    VERBOSE(VB_RECORD, LOC + "Pause() -- end");
    7382}
    7483
    7584void FreeboxRecorder::Unpause(void)
    7685{
    7786    VERBOSE(VB_RECORD, LOC + "Unpause() -- begin");
    78     if (_recording && !_channel->GetRTSP()->IsOpen())
     87    if (_recording && !_channel->StreamIsOpen())
    7988        Open();
    8089    DTVRecorder::Unpause();
    8190    VERBOSE(VB_RECORD, LOC + "Unpause() -- end");
     
    99108        if (PauseAndWait())
    100109            continue;
    101110
    102         if (!_channel->GetRTSP()->IsOpen())
     111        if (!_channel->StreamIsOpen())
    103112        {
    104113            usleep(5000);
    105114            continue;
    106115        }
    107 
    108         // Go into main RTSP loop, feeding data to AddData
    109         _channel->GetRTSP()->Run();
     116       
     117        // Go into main loop, feeding data to AddData
     118        _channel->StreamRun();
    110119    }
    111120
    112121    // Finish up...
     
    122131{
    123132    VERBOSE(VB_RECORD, LOC + "StopRecording() -- begin");
    124133    Pause();
    125     _channel->GetRTSP()->Close();
     134    _channel->StreamClose();
    126135
    127136    _request_recording = false;
    128137    while (_recording)
    129138        _cond_recording.wait(500);
    130 
     139    DTVRecorder::StopRecording();
    131140    VERBOSE(VB_RECORD, LOC + "StopRecording() -- end");
    132141}
    133142
     
    150159}
    151160
    152161// ===================================================
    153 // AddData : feed data from RTSP flow to mythtv
     162// AddData : feed data from flow to mythtv
    154163// ===================================================
    155164void FreeboxRecorder::AddData(unsigned char *data,
    156                               unsigned       dataSize,
    157                               struct timeval)
     165                              unsigned       dataSize)
    158166{
    159167    unsigned int readIndex = 0;
    160168
     
    166174            return;
    167175
    168176        // Find the next TS Header in data
    169         int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize);
    170 
     177        int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize - readIndex);
     178       
    171179        // if no TS, something bad happens
    172180        if (tsPos == -1)
    173181        {
     
    184192
    185193        // Check if the next packet in buffer is complete :
    186194        // packet size is 188 bytes long
    187         if ((dataSize - tsPos) < TSPacket::SIZE)
     195        if ((dataSize - tsPos - readIndex) < TSPacket::SIZE)
    188196        {
    189197            VERBOSE(VB_IMPORTANT, LOC_ERR +
    190198                    "TS packet at stradles end of buffer.");
  • libs/libmythtv/rtspcomms.cpp

     
    270270                    .arg(_live_env->getResultMsg()));
    271271        }
    272272
    273         vector<RTSPListener*>::iterator it = _listeners.begin();
     273        vector<StreamDataListener*>::iterator it = _listeners.begin();
    274274        for (; it != _listeners.end(); ++it)
    275275            freeboxMediaSink->AddListener(*it);
    276276
     
    367367    VERBOSE(VB_RECORD, LOC + "Stop() -- end");
    368368}
    369369
    370 void RTSPComms::AddListener(RTSPListener *item)
     370void RTSPComms::AddListener(StreamDataListener *item)
    371371{
    372372    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
    373373    if (!item)
     
    401401    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 2");
    402402}
    403403
    404 void RTSPComms::RemoveListener(RTSPListener *item)
     404void RTSPComms::RemoveListener(StreamDataListener *item)
    405405{
    406406    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
    407407    QMutexLocker locker(&_lock);
    408     vector<RTSPListener*>::iterator it =
     408    vector<StreamDataListener*>::iterator it =
    409409        find(_listeners.begin(), _listeners.end(), item);
    410410
    411411    if (it == _listeners.end())
  • libs/libmythtv/udpcomms.h

     
     1/** -*- Mode: c++ -*-
     2 *  RTSPComms
     3 *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
     4 *  Distributed as part of MythTV under GPL v2 and later.
     5 */
     6
     7#ifndef UDPCOMMS_H
     8#define UDPCOMMS_H
     9
     10// C++ headers
     11#include <vector>
     12using namespace std;
     13
     14// Qt headers
     15#include <qwaitcondition.h>
     16#include <qmutex.h>
     17
     18// MythTV headers
     19#include "streamcomms.h"
     20
     21class UsageEnvironment;
     22class BasicUDPSource;
     23class FreeboxMediaSink;
     24class StreamDataListener;
     25
     26class UDPComms : public StreamComms
     27{
     28  public:
     29    UDPComms();
     30    virtual ~UDPComms();
     31
     32    bool Open(const QString &url);
     33    bool IsOpen(void) const { return _source; }
     34    void Close(void);
     35
     36    void Run(void);
     37    void Stop(void);
     38
     39    void AddListener(StreamDataListener*);
     40    void RemoveListener(StreamDataListener*);
     41
     42  private:
     43
     44    char                _abort;
     45    bool                _running;
     46    UsageEnvironment   *_live_env;
     47    BasicUDPSource     *_source;
     48    FreeboxMediaSink   *_sink;
     49    vector<StreamDataListener*> _listeners;
     50    QWaitCondition      _cond;       ///< Condition  used to coordinate threads
     51    mutable QMutex      _lock;       ///< Lock  used to coordinate threads
     52};
     53
     54#endif
  • libs/libmythtv/streamcomms.h

     
     1/** -*- Mode: c++ -*-
     2 *  StreamComms
     3 *  Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars
     4 *  Distributed as part of MythTV under GPL v2 and later.
     5 */
     6
     7#ifndef _STREAMCOMMS_H_
     8#define _STREAMCOMMS_H_
     9
     10class StreamDataListener
     11{
     12  public:
     13    /// Callback function to add MPEG2 TS data
     14    virtual void AddData(unsigned char *data,
     15                         unsigned int   dataSize) = 0;
     16  protected:
     17    virtual ~StreamDataListener() {}
     18};
     19
     20class QString;
     21
     22class StreamComms
     23{
     24  public:
     25    StreamComms(){};
     26    virtual ~StreamComms(){};
     27
     28    virtual bool Open(const QString &url) = 0;
     29    virtual bool IsOpen(void) const = 0;
     30    virtual void Close(void) = 0;
     31
     32    virtual void Run(void) = 0;
     33    virtual void Stop(void) = 0;
     34
     35    virtual void AddListener(StreamDataListener*) = 0;
     36    virtual void RemoveListener(StreamDataListener*) = 0;
     37};
     38
     39#endif
  • libs/libmythtv/freeboxmediasink.h

     
    1414
    1515#include <MediaSink.hh>
    1616
    17 class RTSPListener
    18 {
    19   public:
    20     /// Callback function to add MPEG2 TS data
    21     virtual void AddData(unsigned char *data,
    22                          unsigned int   dataSize,
    23                          struct timeval presentationTime) = 0;
    24   protected:
    25     virtual ~RTSPListener() {}
    26 };
     17#include "streamcomms.h"
    2718
    2819// ============================================================================
    2920// FreeboxMediaSink : Helper class use to receive RTSP data from socket.
     
    3425    static FreeboxMediaSink *CreateNew(UsageEnvironment &env,
    3526                                       unsigned          bufferSize);
    3627
    37     void AddListener(RTSPListener*);
    38     void RemoveListener(RTSPListener*);
     28    void AddListener(StreamDataListener*);
     29    void RemoveListener(StreamDataListener*);
    3930
    4031  protected:
    4132    FreeboxMediaSink(UsageEnvironment &env,
     
    5849    unsigned char         *fBuffer;
    5950    unsigned int           fBufferSize;
    6051    UsageEnvironment      &env;
    61     vector<RTSPListener*>  listeners;
     52    vector<StreamDataListener*>  listeners;
    6253    mutable QMutex         lock;
    6354
    6455  private:
  • libs/libmythtv/freeboxrecorder.h

     
    1010#include <qwaitcondition.h>
    1111
    1212#include "dtvrecorder.h"
    13 #include "freeboxmediasink.h"
    14 #include "streamlisteners.h"
     13#include "streamcomms.h"
    1514
    1615class FreeboxChannel;
    1716
    18 /** \brief Processes data from RTSPComms and writes it to disk.
     17/** \brief Processes data from StreamComms and writes it to disk.
    1918 */
    20 class FreeboxRecorder : public DTVRecorder, public RTSPListener,
     19class FreeboxRecorder : public DTVRecorder, public StreamDataListener,
    2120                        public MPEGSingleProgramStreamListener
    2221{
    23     friend class FreeboxMediaSink;
    24     friend class RTSPComms;
    25 
    2622  public:
    2723    FreeboxRecorder(TVRec *rec, FreeboxChannel *channel);
    2824    ~FreeboxRecorder();
    2925
    3026    bool Open(void);
    3127    void Close(void);
     28    void Reset(void);
    3229
    3330    virtual void Pause(bool clear = true);
    3431    virtual void Unpause(void);
     
    4542  private:
    4643    void ProcessTSPacket(const TSPacket& tspacket);
    4744
    48     // implements RTSPListener
     45    // implements StreamDataListener
    4946    void AddData(unsigned char *data,
    50                  unsigned int   dataSize,
    51                  struct timeval presentationTime);
     47                 unsigned int   dataSize);
    5248
    5349    // implements MPEGSingleProgramStreamListener
    5450    void HandleSingleProgramPAT(ProgramAssociationTable *pat);
  • libs/libmythtv/rtspcomms.h

     
    44 *  Distributed as part of MythTV under GPL v2 and later.
    55 */
    66
     7#ifndef RTSPCOMMS_H
     8#define RTSPCOMMS_H
     9
    710// C++ headers
    811#include <vector>
    912using namespace std;
     
    1316#include <qmutex.h>
    1417
    1518// MythTV headers
    16 #include "freeboxchannel.h"
     19#include "streamcomms.h"
    1720
    1821class UsageEnvironment;
    1922class RTSPClient;
    2023class MediaSession;
    21 class RTSPListener;
     24class StreamDataListener;
    2225
    23 class RTSPComms
     26class RTSPComms : public StreamComms
    2427{
    2528  public:
    2629    RTSPComms();
     
    3639    void Run(void);
    3740    void Stop(void);
    3841
    39     void AddListener(RTSPListener*);
    40     void RemoveListener(RTSPListener*);
     42    void AddListener(StreamDataListener*);
     43    void RemoveListener(StreamDataListener*);
    4144
    4245  private:
    4346
     
    4649    UsageEnvironment   *_live_env;
    4750    RTSPClient         *_rtsp_client;
    4851    MediaSession       *_session;
    49     vector<RTSPListener*> _listeners;
     52    vector<StreamDataListener*> _listeners;
    5053    QWaitCondition      _cond;       ///< Condition  used to coordinate threads
    5154    mutable QMutex      _lock;       ///< Lock  used to coordinate threads
    5255};
     56
     57#endif