Ticket #1704: 1704-v1.patch

File 1704-v1.patch, 43.6 KB (added by danielk, 18 years ago)

updated patch

  • configure

     
    5454lirc="yes"
    5555joystick_menu="yes"
    5656firewire_cable_box="yes"
     57freebox_box="yes"
    5758dbox2_dvb_box="yes"
    5859ip_network_recorder="yes"
    5960hdhomerun_box="yes"
     
    178179echo "  --disable-lirc           disable lirc support (Infrared Remotes)"
    179180echo "  --disable-joystick-menu  disable joystick menu"
    180181echo "  --disable-firewire       disable support for FireWire cable boxes"
     182echo "  --disable-freebox        disable support for Freebox"
     183echo "  --livelibdir=DIR         location of Live streaming library"
     184echo "  --liveincludedir=DIR     location of Live streaming include files"
    181185echo "  --disable-dbox2          disable support for Nokia DBOX2 DVB boxes (or compatibles)"
    182186echo "  --disable-hdhomerun      disable support for HDHomeRun boxes"
    183187echo "  --disable-crciprec       disable support for Network Recorder"
     
    819823  ;;
    820824  --disable-dbox2) dbox2_dvb_box="no"
    821825  ;;
     826  --enable-freebox) freebox_box="yes"
     827  ;;
     828  --disable-freebox) freebox_box="no"
     829  ;;
     830  --livelibdir=*) live_lib_dir=`echo $opt | cut -d '=' -f 2`
     831  ;;
     832  --liveincludedir=*) live_include_dir=`echo $opt | cut -d '=' -f 2`
     833  ;;
    822834  --enable-hdhomerun) hdhomerun_box="yes"
    823835  ;;
    824836  --disable-hdhomerun) hdhomerun_box="no"
     
    20362048    fi
    20372049fi
    20382050
     2051if test x"$freebox_box" = x"yes" ; then
     2052    if test x"$live_lib_dir" = x""; then
     2053        if has_library libliveMedia; then
     2054            CONFIG_LIVE_LIBS="-lliveMedia -lgroupsock -lBasicUsageEnvironment -lUsageEnvironment"
     2055        else
     2056            echo "Unable to find Live Media library."
     2057            freebox_box="no"
     2058        fi
     2059    else
     2060        if test ! -f "$live_lib_dir/liveMedia/libliveMedia.a"; then
     2061            echo "Unable to find Live Media library."
     2062            freebox_box="no"
     2063        fi
     2064        CONFIG_LIVE_LIBS="-L$live_lib_dir/liveMedia -L$live_lib_dir/UsageEnvironment -L$live_lib_dir/BasicUsageEnvironment -L$live_lib_dir/groupsock -lliveMedia -lgroupsock -lBasicUsageEnvironment -lUsageEnvironment"
     2065    fi
     2066    if test "x$live_include_dir" = "x"; then
     2067        if has_header liveMedia.hh; then
     2068            true
     2069        else
     2070            echo "Unable to find Live Media headers."
     2071            freebox_box="no"
     2072        fi
     2073    else
     2074        if test -f "$live_include_dir/liveMedia/include/liveMedia.hh"; then
     2075            LIVE_INCLUDES="$live_include_dir/liveMedia/include $live_include_dir/UsageEnvironment/include $live_include_dir/BasicUsageEnvironment/include $live_include_dir/groupsock/include"
     2076        else
     2077            if test -f "$live_include_dir/liveMedia/liveMedia.hh"; then
     2078                LIVE_INCLUDES="$live_include_dir/liveMedia $live_include_dir/UsageEnvironment $live_include_dir/BasicUsageEnvironment $live_include_dir/groupsock"
     2079            else
     2080                echo "Unable to find Live Media headers."
     2081                freebox_box="no"
     2082            fi
     2083        fi
     2084    fi
     2085fi
     2086
    20392087lamemp3="no"
    20402088if has_library libmp3lame ; then
    20412089    if has_header lame/lame.h ; then
     
    23222370  echo "FireWire support $firewire_cable_box"
    23232371  echo "DVB support      $dvb [$dvb_path]"
    23242372  echo "DBox2 support    $dbox2_dvb_box"
     2373  echo "freebox support  $freebox_box"
    23252374  echo "HDHomeRun sup.   $hdhomerun_box"
    23262375  echo "CRC Ip Rec sup.  $ip_network_recorder"
    23272376fi
     
    29843033  CCONFIG="$CCONFIG using_ip_rec"
    29853034fi
    29863035
     3036if test x"$freebox_box" = x"yes" ; then
     3037    CCONFIG="$CCONFIG using_freebox"
     3038    CONFIG_DEFINES="$CONFIG_DEFINES USING_FREEBOX"
     3039    echo "CONFIG_LIVE_LIBS=$CONFIG_LIVE_LIBS" >> $MYTH_CONFIG_MAK
     3040    CONFIG_INCLUDEPATH="$CONFIG_INCLUDEPATH $LIVE_INCLUDES"
     3041fi
     3042
    29873043if test x"$lirc" = x"yes" ; then
    29883044  CCONFIG="$CCONFIG using_lirc"
    29893045  echo "CONFIG_LIRC_LIBS=-llirc_client" >> $MYTH_CONFIG_MAK
  • libs/libmythtv/freeboxchannel.h

     
     1/** -*- Mode: c++ -*-
     2 *  FreeboxChannel
     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 FREEBOXCHANNEL_H
     8#define FREEBOXCHANNEL_H
     9
     10#include "freeboxchannel_util.h"
     11#include "channelbase.h"
     12
     13class FreeboxRecorder;
     14
     15class FreeboxChannel : public ChannelBase
     16{
     17    friend class FreeboxRecorder;
     18  public:
     19    FreeboxChannel(TVRec *parent, const QString &videodev);
     20    ~FreeboxChannel(void) { }
     21
     22    bool Open(void);
     23    void Close(void) { m_isopen = false; }
     24
     25    bool    IsOpen(void) const { return m_isopen; }
     26
     27    bool SwitchToInput(const QString &inputname, const QString &channum);
     28    bool SwitchToInput(int inputNum, bool setstarting);
     29    bool SetChannelByString(const QString &channum);
     30
     31    void SetRecorder(FreeboxRecorder *rec)
     32        { QMutexLocker locker(&m_lock); m_recorder = rec; }
     33
     34  private:
     35    FBChanInfo GetChanInfo(const QString &channum, uint sourceid = 0) const;
     36    FBChanInfo GetCurrentChanInfo(void) const
     37        { return GetChanInfo(curchannelname); }
     38
     39    QString               m_videodev;
     40    FreeboxRecorder      *m_recorder;
     41    bool                  m_isopen;
     42    fbox_chan_map_t       m_freeboxchannels;
     43    mutable QMutex        m_lock;
     44};
     45
     46#endif // FREEBOXCHANNEL_H
     47
     48/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/libmythtv.pro

     
    373373    using_dbox2:SOURCES += dbox2recorder.cpp dbox2channel.cpp dbox2epg.cpp
    374374    using_dbox2:HEADERS += dbox2recorder.h dbox2channel.h dbox2epg.h
    375375    using_dbox2:DEFINES += USING_DBOX2
     376   
     377    # Support for freebox (http://adsl.free.fr/)
     378    using_freebox:SOURCES += freeboxrecorder.cpp freeboxmediasink.cpp
     379    using_freebox:SOURCES += freeboxchannel.cpp  freeboxchannel_util.cpp
     380    using_freebox:HEADERS += freeboxrecorder.h   freeboxmediasink.h
     381    using_freebox:HEADERS += freeboxchannel.h    freeboxchannel_util.h
     382    using_freebox:DEFINES += USING_FREEBOX
    376383
    377384    # Support for HDHomeRun box
    378385    using_hdhr {
  • libs/libmythtv/freeboxchannel.cpp

     
     1/** -*- Mode: c++ -*-
     2 *  FreeboxChannel
     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 "freeboxchannel.h"
     8#include "freeboxrecorder.h"
     9#include "libmythtv/tv_rec.h"
     10
     11#define LOC QString("FBChan%1: ").arg(GetCardID())
     12#define LOC_ERR QString("FBChan%1, Error: ").arg(GetCardID())
     13
     14FreeboxChannel::FreeboxChannel(TVRec *parent, const QString &videodev)
     15    : ChannelBase(parent),
     16      m_videodev(videodev),   m_recorder(NULL),
     17      m_isopen(false),        m_lock(true)
     18{
     19}
     20
     21bool FreeboxChannel::Open(void)
     22{
     23    QMutexLocker locker(&m_lock);
     24
     25    if (InitializeInputs())
     26        return false;
     27
     28    m_freeboxchannels = FBChannelFetcher::GetChannels(m_videodev);
     29
     30    return m_isopen = m_freeboxchannels.size();
     31}
     32
     33bool FreeboxChannel::SwitchToInput(const QString &inputname,
     34                                   const QString &channum)
     35{
     36    QMutexLocker locker(&m_lock);
     37
     38    int inputNum = GetInputByName(inputname);
     39    if (inputNum < 0)
     40        return false;
     41
     42    return SetChannelByString(channum);
     43}
     44
     45bool FreeboxChannel::SwitchToInput(int inputNum, bool setstarting)
     46{
     47    QMutexLocker locker(&m_lock);
     48
     49    InputMap::const_iterator it = inputs.find(inputNum);
     50    if (it == inputs.end())
     51        return false;
     52
     53    QString channum = (*it)->startChanNum;
     54
     55    if (setstarting)
     56        return SetChannelByString(channum);
     57
     58    return true;
     59}
     60
     61bool FreeboxChannel::SetChannelByString(const QString &channum)
     62{
     63    QMutexLocker locker(&m_lock);
     64
     65    // Verify that channel exists
     66    if (!GetChanInfo(channum).isValid())
     67    {
     68        VERBOSE(VB_IMPORTANT, LOC_ERR +
     69                QString("SetChannelByString(%1)").arg(channum) +
     70                " Invalid channel");
     71        return false;
     72    }
     73
     74    // Set the channel..
     75    curchannelname = channum;
     76
     77    // Send signal to recorder that channel has changed.
     78    if (m_recorder)
     79        m_recorder->ChannelChanged();
     80
     81    return true;
     82}
     83
     84FBChanInfo FreeboxChannel::GetChanInfo(const QString &channum,
     85                                       uint sourceid) const
     86{
     87    QMutexLocker locker(&m_lock);
     88
     89    FBChanInfo dummy;
     90    QString msg = LOC_ERR + QString("GetChanInfo(%1) failed").arg(channum);
     91
     92    if (channum.isEmpty())
     93    {
     94        VERBOSE(VB_IMPORTANT, msg);
     95        return dummy;
     96    }
     97
     98    if (!sourceid)
     99    {
     100        InputMap::const_iterator it = inputs.find(currentInputID);
     101        if (it == inputs.end())
     102        {
     103            VERBOSE(VB_IMPORTANT, msg);
     104            return dummy;
     105        }
     106        sourceid = (*it)->sourceid;
     107    }
     108
     109    MSqlQuery query(MSqlQuery::InitCon());
     110    query.prepare(
     111        "SELECT freqid, xmltvid, name"
     112        "FROM channel "
     113        "WHERE channum  = :CHANNUM AND "
     114        "      sourceid = :SOURCEID");
     115
     116    query.bindValue(":CHANNUM",  channum);
     117    query.bindValue(":SOURCEID", sourceid);
     118
     119    if (!query.exec() || !query.isActive())
     120    {
     121        MythContext::DBError("fetching chaninfo", query);
     122        VERBOSE(VB_IMPORTANT, msg);
     123        return dummy;
     124    }
     125
     126    while (query.next())
     127    {
     128        // Try to map freqid or name to a channel in the map
     129        const QString freqid = query.value(0).toString();
     130        fbox_chan_map_t::const_iterator it;
     131        if (!freqid.isEmpty())
     132        {
     133            it = m_freeboxchannels.find(freqid);
     134            if (it != m_freeboxchannels.end())
     135                return *it;
     136        }
     137
     138        // Try to map xmltvid or name to a channel in the map
     139        const QString xmltvid = query.value(1).toString();
     140        const QString name    = query.value(2).toString();
     141        for (it = m_freeboxchannels.begin();
     142             it != m_freeboxchannels.end(); ++it)
     143        {
     144            if ((*it).m_xmltvid == xmltvid)
     145                return *it;
     146            if ((*it).m_name == name)
     147                return *it;
     148        }
     149    }
     150
     151    VERBOSE(VB_IMPORTANT, msg);
     152    return dummy;
     153}
     154
     155/* vim: set expandtab tabstop = 4 shiftwidth = 4: */
  • libs/libmythtv/freeboxmediasink.cpp

     
     1/**
     2 *  FreeboxMediaSink
     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 "freeboxmediasink.h"
     8
     9#include "freeboxrecorder.h"
     10
     11
     12
     13FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment& pEnv,
     14                                   FreeboxRecorder&  pRecorder,
     15                                   unsigned          bufferSize) :
     16    MediaSink(pEnv),
     17    fBufferSize(bufferSize),
     18    env(pEnv),
     19    recorder(pRecorder)
     20{
     21    // Setup the data buffer
     22    fBuffer = new unsigned char[fBufferSize];
     23}
     24
     25FreeboxMediaSink::~FreeboxMediaSink()
     26{
     27    // free the data buffer
     28    delete[] fBuffer;
     29}
     30
     31FreeboxMediaSink* FreeboxMediaSink::createNew(UsageEnvironment& env,
     32                                              FreeboxRecorder&  pRecorder,
     33                                              unsigned          bufferSize)
     34{
     35    return new FreeboxMediaSink(env, pRecorder, bufferSize);
     36}
     37
     38Boolean FreeboxMediaSink::continuePlaying()
     39{
     40    if (fSource == NULL) return False;
     41
     42    fSource->getNextFrame(fBuffer, fBufferSize,
     43                          afterGettingFrame, this,
     44                          onSourceClosure, this);
     45    return True;
     46}
     47
     48void FreeboxMediaSink::afterGettingFrame(void*          clientData,
     49                                         unsigned       frameSize,
     50                                         unsigned       /*numTruncatedBytes*/,
     51                                         struct timeval presentationTime,
     52                                         unsigned       /*durationInMicroseconds*/)
     53{
     54    FreeboxMediaSink* sink = (FreeboxMediaSink*)clientData;
     55    sink->afterGettingFrame1(frameSize, presentationTime);
     56}
     57
     58void FreeboxMediaSink::afterGettingFrame1(unsigned       frameSize,
     59                                          struct timeval presentationTime)
     60{
     61    addData(fBuffer, frameSize, presentationTime);
     62    continuePlaying();
     63}
     64
     65void FreeboxMediaSink::addData(unsigned char* data,
     66                               unsigned       dataSize,
     67                               struct timeval presentationTime)
     68{
     69    recorder.addData(data, dataSize, presentationTime);
     70}
  • libs/libmythtv/dbcheck.cpp

     
    1010#include "mythdbcon.h"
    1111
    1212/// This is the DB schema version expected by the running MythTV instance.
    13 const QString currentDatabaseVersion = "1142";
     13const QString currentDatabaseVersion = "1143";
    1414
    1515static bool UpdateDBVersionNumber(const QString &newnumber);
    1616static bool performActualUpdate(const QString updates[], QString version,
     
    22682268//"ALTER TABLE capturecard DROP COLUMN dvb_hw_decoder;" in 0.21
    22692269//"ALTER TABLE cardinput DROP COLUMN  preference;" in 0.22
    22702270
     2271  if (dbver == "1142")
     2272    {
     2273        const QString updates[] = {
     2274"INSERT INTO profilegroups SET name = 'Freebox Input', cardtype = 'Freebox', is_default = 1;",
     2275""
     2276};
     2277
     2278        if (!performActualUpdate(updates, "1143", dbver))
     2279            return false;
     2280    }
     2281
     2282
    22712283    return true;
    22722284}
    22732285
     
    23282340"  dbox2_port int(10) unsigned NOT NULL default '31338',"
    23292341"  dbox2_httpport int(10) unsigned NOT NULL default '80',"
    23302342"  dbox2_host varchar(32) default NULL,"
     2343"  freebox_mrl varchar(64) DEFAULT 'http://mafreebox.freebox.fr/freeboxtv/playlist.m3u',"
    23312344"  signal_timeout int(11) NOT NULL default '1000',"
    23322345"  channel_timeout int(11) NOT NULL default '3000',"
    23332346"  PRIMARY KEY  (cardid)"
     
    28942907"INSERT INTO profilegroups VALUES (8,"
    28952908" 'USB Mpeg-4 Encoder (Plextor ConvertX, etc)','GO7007',1,NULL);",
    28962909"INSERT INTO profilegroups VALUES (9,'DBOX2 Input','DBOX2',1,NULL);",
     2910"INSERT INTO `profilegroups` VALUES (10,'Freebox Input','Freebox',1,NULL);",
    28972911"INSERT INTO recordingprofiles VALUES (1,'Default',NULL,NULL,1);",
    28982912"INSERT INTO recordingprofiles VALUES (2,'Live TV',NULL,NULL,1);",
    28992913"INSERT INTO recordingprofiles VALUES (3,'High Quality',NULL,NULL,1);",
  • libs/libmythtv/freeboxrecorder.cpp

     
     1/**
     2 *  FreeboxRecorder
     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 "freeboxrecorder.h"
     8
     9#include <BasicUsageEnvironment.hh>
     10#include <MediaSession.hh>
     11#include <RTSPClient.hh>
     12#include <qwaitcondition.h>
     13#include <qmutex.h>
     14
     15#include "mpeg/tspacket.h"
     16#include "freeboxchannel.h"
     17#include "freeboxmediasink.h"
     18
     19
     20
     21// ============================================================================
     22// FreeboxData : Helper class use for static Callback handler
     23// ============================================================================
     24class FreeboxData
     25{
     26  public:
     27    FreeboxData(FreeboxRecorder *pFreeboxRecorder, MediaSubsession *pMediaSubSession) :
     28        freeboxRecorder(pFreeboxRecorder),
     29        mediaSubSession(pMediaSubSession)
     30    {
     31    }
     32   
     33    static void subsessionAfterPlayingCallback(void *clientData);
     34    static void subsessionByeHandlerCallback(void *clientData);
     35    void SubsessionAfterPlaying();
     36    void SubsessionByeHandler();
     37
     38  private:
     39    FreeboxRecorder *freeboxRecorder;
     40    MediaSubsession *mediaSubSession;
     41};
     42
     43void FreeboxData::subsessionAfterPlayingCallback(void *clientData)
     44{
     45    ((FreeboxData*)clientData)->SubsessionAfterPlaying();
     46}
     47
     48void FreeboxData::subsessionByeHandlerCallback(void *clientData)
     49{
     50    ((FreeboxData*)clientData)->SubsessionByeHandler();
     51}
     52
     53void FreeboxData::SubsessionAfterPlaying()
     54{
     55    MediaSubsession* subsession = mediaSubSession;
     56    Medium::close(subsession->sink);
     57    subsession->sink = NULL;
     58
     59    MediaSession& session = subsession->parentSession();
     60    MediaSubsessionIterator iter(session);
     61    while ((subsession = iter.next()) != NULL)
     62    {
     63        if (subsession->sink != NULL) return;
     64    }
     65}
     66
     67void FreeboxData::SubsessionByeHandler()
     68{
     69    SubsessionAfterPlaying();
     70}
     71
     72
     73
     74class FreeboxRecorderImpl
     75{
     76  public:
     77    FreeboxRecorderImpl(FreeboxChannel& channel) :
     78        env(NULL),
     79        rtspClient(NULL),
     80        session(NULL),
     81        _channel(channel),
     82        _abort_rtsp(0),
     83        _abort_recording(false)
     84    {
     85    }
     86
     87    // livemedia
     88    UsageEnvironment* env;
     89    RTSPClient* rtspClient;
     90    MediaSession* session;
     91
     92    // Current channel
     93    FreeboxChannel& _channel;
     94
     95    // condition  used to coordinate threads
     96    QWaitCondition _cond;
     97   
     98    // lock  used to coordinate threads
     99    QMutex _lock;
     100
     101    // var to check if we need to abort current rtsp session
     102    char _abort_rtsp;
     103
     104    // request abort for StartRecording method
     105    bool _abort_recording;
     106};
     107
     108
     109
     110FreeboxRecorder::FreeboxRecorder(TVRec *rec, FreeboxChannel *channel) :
     111    DTVRecorder(rec),
     112    _impl(new FreeboxRecorderImpl(*channel))
     113{
     114    channel->SetRecorder(this);
     115}
     116
     117
     118
     119FreeboxRecorder::~FreeboxRecorder()
     120{
     121    _impl->_channel.SetRecorder(NULL);
     122    delete _impl;
     123}
     124
     125
     126
     127bool FreeboxRecorder::Open()
     128{
     129    bool result = StartRtsp();
     130    _error = !result;
     131    return result;
     132}
     133
     134
     135
     136void FreeboxRecorder::Close()
     137{
     138    if (_impl->session == NULL) return;
     139
     140    // Ensure RTSP cleanup, remove old RTSP session
     141    MediaSubsessionIterator iter(*_impl->session);
     142    MediaSubsession* subsession;
     143    while ((subsession = iter.next()) != NULL)
     144    {
     145        Medium::close(subsession->sink);
     146        subsession->sink = NULL;
     147    }
     148
     149    if (_impl->session == NULL) return;
     150
     151    _impl->rtspClient->teardownMediaSession(*_impl->session);
     152
     153    // Close all RTSP descriptor
     154    Medium::close(_impl->session);
     155    Medium::close(_impl->rtspClient);
     156}
     157
     158
     159
     160void FreeboxRecorder::ChannelChanged()
     161{
     162    // Channel change, we need to close current RTSP flow, and open a new one
     163    ResetEventLoop();
     164}
     165
     166
     167
     168void FreeboxRecorder::SetOptionsFromProfile(RecordingProfile *profile,
     169                                            const QString    &videodev,
     170                                            const QString    &audiodev,
     171                                            const QString    &vbidev)
     172{
     173    (void)videodev;
     174    (void)audiodev;
     175    (void)vbidev;
     176    (void)profile;
     177}
     178
     179
     180
     181void FreeboxRecorder::StartRecording()
     182{
     183    _impl->_lock.lock();
     184    _recording = true;
     185    while(!_impl->_abort_recording && Open())
     186    {
     187        _impl->_lock.unlock();
     188        // Go into main RTSP loop, feeding data to mythtv
     189        _impl->env->taskScheduler().doEventLoop(&_impl->_abort_rtsp);
     190
     191        _impl->_lock.lock();
     192        FinishRecording();
     193        Close();
     194
     195        // Reset _abort_rtsp before unlocking ResetEventLoop() to avoid race condition
     196        _impl->_abort_rtsp = 0;
     197        _impl->_cond.wakeAll();
     198    }
     199    _recording = false;
     200    _impl->_lock.unlock();
     201}
     202
     203void FreeboxRecorder::StopRecording(void)
     204{
     205    _impl->_abort_recording = true; // No lock needed
     206    ResetEventLoop();
     207}
     208
     209void FreeboxRecorder::ResetEventLoop()
     210{
     211    _impl->_lock.lock();
     212    _impl->_abort_rtsp = ~0;
     213    while(_recording && _impl->_abort_rtsp)
     214        _impl->_cond.wait(&_impl->_lock, 1000);
     215    _impl->_lock.unlock();
     216}
     217
     218// ======================================================================
     219// StartRtsp : start a new RTSP session for the current channel
     220// ======================================================================
     221bool FreeboxRecorder::StartRtsp()
     222{
     223    // Retrieve the RTSP channel URL
     224    FBChanInfo chaninfo = _impl->_channel.GetCurrentChanInfo();
     225    if (!chaninfo.isValid())
     226        return false;
     227    QString url = chaninfo.m_url;
     228
     229    // Begin by setting up our usage environment:
     230    TaskScheduler* scheduler = BasicTaskScheduler::createNew();
     231    _impl->env = BasicUsageEnvironment::createNew(*scheduler);
     232
     233
     234    // Create our client object:
     235    _impl->rtspClient = RTSPClient::createNew(*_impl->env, 0, "myRTSP", 0);
     236    if (_impl->rtspClient == NULL)
     237    {
     238        VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create RTSP client: %1")
     239            .arg(_impl->env->getResultMsg()));
     240        return false;
     241    }
     242
     243    // Setup URL for the current session
     244    char* sdpDescription = _impl->rtspClient->describeURL(url);
     245    _impl->rtspClient->describeStatus();
     246    if (sdpDescription == NULL)
     247    {
     248        VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to get a SDP description from URL: %1 %2")
     249            .arg(url)
     250            .arg(_impl->env->getResultMsg()));
     251        return false;
     252    }
     253
     254    // Create a media session object from this SDP description:
     255    _impl->session = MediaSession::createNew(*_impl->env, sdpDescription);
     256    delete[] sdpDescription;
     257    if (_impl->session == NULL)
     258    {
     259        VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create MediaSession: %1")
     260            .arg(_impl->env->getResultMsg()));
     261        return false;
     262    }
     263    else if (!_impl->session->hasSubsessions())
     264    {
     265        VERBOSE(VB_IMPORTANT, QString("Freebox # This session has no media subsessions"));
     266        return false;
     267    }
     268
     269    // Then, setup the "RTPSource"s for the session:
     270    MediaSubsessionIterator iter(*_impl->session);
     271    MediaSubsession *subsession;
     272    Boolean madeProgress = False;
     273    while ((subsession = iter.next()) != NULL)
     274    {
     275        if (!subsession->initiate(-1))
     276        {
     277            VERBOSE(VB_IMPORTANT, QString("Freebox # Unable to create receiver for: %1 / %2 subsession: %3")
     278                    .arg(subsession->mediumName())
     279                    .arg(subsession->codecName())
     280                    .arg(_impl->env->getResultMsg()));
     281        }
     282        else
     283        {
     284            madeProgress = True;
     285
     286            if (subsession->rtpSource() != NULL)
     287            {
     288                  unsigned const thresh = 1000000; // 1 second
     289                  subsession->rtpSource()->setPacketReorderingThresholdTime(thresh);
     290            }
     291        }
     292    }
     293
     294    if (!madeProgress) return false;
     295
     296    // Perform additional 'setup' on each subsession, before playing them:
     297    madeProgress = false;
     298    iter.reset();
     299    while ((subsession = iter.next()) != NULL)
     300    {
     301        if (subsession->clientPortNum() == 0) continue; // port # was not set
     302
     303        if (_impl->rtspClient->setupMediaSubsession(*subsession, False, false))
     304        {
     305            madeProgress = True;
     306        }
     307        else
     308        {
     309            VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to setup: %1 %2 : %3")
     310                .arg(subsession->mediumName())
     311                .arg(subsession->codecName())
     312                .arg(_impl->env->getResultMsg()));
     313        }
     314    }
     315
     316    if (!madeProgress) return false;
     317
     318   // Create and start "FileSink"s for each subsession:
     319   // FileSink while receive Mpeg2 TS Data & will feed them to mythtv
     320    madeProgress = False;
     321    iter.reset();
     322    while ((subsession = iter.next()) != NULL)
     323    {
     324        if (subsession->readSource() == NULL) continue; // was not initiated
     325
     326        FreeboxMediaSink* freeboxMediaSink =
     327            FreeboxMediaSink::createNew(*_impl->env, *this, TSPacket::SIZE*128);
     328
     329        subsession->sink = freeboxMediaSink;
     330        if (subsession->sink == NULL)
     331        {
     332            VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create sink: %1")
     333                .arg(_impl->env->getResultMsg()));
     334        }
     335
     336        subsession->sink->startPlaying(
     337                *(subsession->readSource()),
     338                FreeboxData::subsessionAfterPlayingCallback,
     339                new FreeboxData(this, subsession));
     340
     341        if (subsession->rtcpInstance() != NULL)
     342        {
     343            subsession->rtcpInstance()->setByeHandler(
     344                    FreeboxData::subsessionByeHandlerCallback,
     345                    new FreeboxData(this, subsession));
     346        }
     347
     348        madeProgress = True;
     349    }
     350
     351    if (!madeProgress) return false;
     352
     353    // Setup player
     354    if (!(_impl->rtspClient->playMediaSession(*_impl->session)))
     355    {
     356        VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to start playing session: %1")
     357            .arg(_impl->env->getResultMsg()));
     358        return false;
     359    }
     360
     361    return true;
     362}
     363
     364// ===================================================
     365// findTSHeader : find a TS Header in flow
     366// ===================================================
     367static int FreeboxRecorder_findTSHeader(const unsigned char *data, unsigned dataSize)
     368{
     369    unsigned int pos = 0;
     370    while (pos < dataSize)
     371    {
     372        if (data[pos] == 0x47)
     373            return pos;
     374        pos++;
     375    }
     376    return -1;
     377}
     378
     379// ===================================================
     380// addData : feed date from RTSP flow to mythtv
     381// ===================================================
     382void FreeboxRecorder::addData(unsigned char* data, unsigned dataSize, struct timeval)
     383{
     384    unsigned int readIndex = 0;
     385
     386    // data may be compose from more than one packet, loop to consume all data
     387    while (readIndex < dataSize)
     388    {
     389        // If recorder is pause, stop there
     390        if (PauseAndWait())
     391        {
     392            return;
     393        }
     394
     395        // Find the next TS Header in data
     396        int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize);
     397
     398        // if no TS, something bad happens
     399        if (tsPos == -1)
     400        {
     401            VERBOSE(VB_IMPORTANT, QString("FREEBOX: No TS header."));
     402            break;
     403        }
     404
     405        // if TS Header not at start of data, we receive out of sync data
     406        if (tsPos > 0)
     407        {
     408            VERBOSE(VB_IMPORTANT, QString("FREEBOX: TS header at %1, not in sync.").arg(tsPos));
     409        }
     410
     411        // Check if the next packet in buffer is complete : packet size is 188 bytes long
     412        if ((dataSize - tsPos) < TSPacket::SIZE)
     413        {
     414            VERBOSE(VB_IMPORTANT, QString("FREEBOX: TS header at %1 but packet not yet complete.").arg(tsPos));
     415            break;
     416        }
     417
     418        // Cast current found TS Packet to TSPacket structure
     419        const void *newData = data + tsPos + readIndex;
     420        const TSPacket *tspacket = reinterpret_cast<const TSPacket*>(newData);
     421
     422        // Feed current packet to myth
     423        _buffer_packets = !FindMPEG2Keyframes(tspacket);
     424        BufferedWrite(*tspacket);
     425
     426        // follow to next packet
     427        readIndex += tsPos + TSPacket::SIZE;
     428    }
     429}
     430
     431/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/freeboxchannel_util.cpp

     
     1/** -*- Mode: c++ -*-
     2 *  FreeboxChannel utils
     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// Qt headers
     8#include <qhttp.h>
     9#include <qurl.h>
     10
     11// MythTV headers
     12#include "mythcontext.h"
     13#include "freeboxchannel_util.h"
     14
     15#define LOC QString("FBChanFetch: ")
     16#define LOC_ERR QString("FBChanFetch, Error: ")
     17
     18static QString channame_to_xmltvid(const QString &channelName);
     19static bool parse_chan_info(const QString&, QString&, QString&);
     20
     21FBChannelFetcher::FBChannelFetcher()
     22    : m_http(new QHttp())
     23{
     24    connect(m_http, SIGNAL(done(bool)), this, SLOT(HttpRequestDone(bool)));
     25}
     26
     27FBChannelFetcher::~FBChannelFetcher()
     28{
     29    m_http->deleteLater();
     30}
     31
     32fbox_chan_map_t FBChannelFetcher::GetChannels(const QString &videodev)
     33{
     34    FBChannelFetcher fetcher;
     35    return fetcher.LoadChannels(videodev, 10 * 1000);
     36}
     37
     38/** \fn FBChannelFetcher::LoadChannels(const QString&,uint)
     39 *  \brief Request Channel list via http.
     40 *  \return true if we get a channel list, false otherwise.
     41 */
     42fbox_chan_map_t FBChannelFetcher::LoadChannels(const QString &videodev,
     43                                               uint max_wait)
     44{
     45    QMutexLocker locker(&m_lock);
     46    m_freeboxchannels.clear();
     47
     48    QUrl url(videodev);
     49    if (!url.isValid())
     50        return m_freeboxchannels;
     51
     52    m_http->setHost(url.host(), url.hasPort() ? url.port() : 80);
     53
     54    QHttpRequestHeader header("GET", url.path());
     55    header.setValue("Host", url.host());
     56    m_http->request(header);
     57
     58    m_load_channel_wait.wait(&m_lock, max_wait);
     59
     60    m_http->abort();
     61    m_http->closeConnection();
     62    m_http->disconnect();
     63
     64    return m_freeboxchannels;
     65}
     66
     67//
     68// HttpRequestDone : Receive response to channel list request
     69//
     70void FBChannelFetcher::HttpRequestDone(bool error)
     71{
     72    if (error)
     73    {
     74        VERBOSE(VB_IMPORTANT, LOC_ERR +
     75                QString("Reading channel list failed (%1)")
     76                .arg(m_http->errorString()));
     77        return;
     78    }
     79
     80    QString buffer = QString::fromUtf8(m_http->readAll());
     81
     82    m_lock.lock();
     83    m_freeboxchannels = ParseChannelList(buffer);
     84    m_lock.unlock();
     85
     86    m_load_channel_wait.wakeAll();
     87}
     88
     89fbox_chan_map_t FBChannelFetcher::ParseChannelList(const QString &rawdata)
     90{
     91    fbox_chan_map_t chanmap;
     92
     93    // Verify header is ok
     94    QString header = rawdata.section("\n", 0, 0);
     95    if (header != "#EXTM3U")
     96    {
     97        VERBOSE(VB_IMPORTANT, LOC_ERR +
     98                QString("Invalid channel list header (%1)").arg(header));
     99
     100        return chanmap;
     101    }
     102
     103    // Parse each channel
     104    for (int i = 1; true; i += 2)
     105    {
     106        QString tmp = rawdata.section("\n", i+0, i+0);
     107        QString url = rawdata.section("\n", i+1, i+1);
     108        if (tmp.isEmpty() || url.isEmpty())
     109            break;
     110
     111        QString channum, name;
     112        if (parse_chan_info(tmp, channum, name))
     113        {
     114            chanmap[channum] = FBChanInfo(
     115                name, channame_to_xmltvid(name), url);
     116        }
     117    }
     118
     119    return chanmap;
     120}
     121
     122static QString channame_to_xmltvid(const QString &channelName)
     123{
     124    // Normalize Channel name so we can try to automap channel
     125    // return by freebox to channel coming from tv_grab_fr
     126    static const QString map1 = QString::fromUtf8(
     127        "áâÀàãåçéêëÚíîïìñóÎöòõúûÌùÜÿ");
     128    static const QString map2 = QString::fromUtf8(
     129        "aaaaaaceeeeiiiinooooouuuuyy");
     130
     131    QString ret = "";
     132    for (uint i = 0; i < channelName.length(); i++)
     133    {
     134        QChar c = channelName[i].lower();
     135
     136        if (c.isSpace())
     137            continue;
     138
     139        int pos = map1.find(c);
     140        if (pos >= 0)
     141            c = map2[pos];
     142
     143        ret += c;
     144    }
     145
     146    return ret;
     147}
     148
     149static bool parse_chan_info(const QString &line1,
     150                            QString &channum, QString &name)
     151{
     152    // each line contains ://
     153    // header:extension,channelNum - channelName rtsp://channelUrl
     154    //#EXTINF:0,2 - France 2 rtsp://mafreebox.freebox.fr/freeboxtv/201
     155
     156    QString msg = LOC_ERR +
     157        QString("Invalid header in channel list line \n\t\t\t%1").arg(line1);
     158
     159    channum = name = QString::null;
     160
     161    // Verify Line Header
     162    int pos = line1.find(":", 0);
     163    if ((pos < 0) || (line1.mid(0, pos) != "#EXTINF"))
     164    {
     165        VERBOSE(VB_IMPORTANT, msg);
     166        return false;
     167    }
     168
     169    // Parse extension portion
     170    pos = line1.find(",", pos + 1);
     171    if (pos < 0)
     172    {
     173        VERBOSE(VB_IMPORTANT, msg);
     174        return false;
     175    }
     176    //list.push_back(line1.mid(oldPos, pos - oldPos));
     177
     178    // Parse freebox channel number
     179    int oldpos = pos + 1;
     180    pos = line1.find(" ", pos + 1);
     181    if (pos < 0)
     182    {
     183        VERBOSE(VB_IMPORTANT, msg);
     184        return false;
     185    }
     186    channum = line1.mid(oldpos, pos - oldpos);
     187
     188    // Parse freebox channel name
     189    pos = line1.find("- ", pos + 1);
     190    if (pos < 0)
     191    {
     192        VERBOSE(VB_IMPORTANT, msg);
     193        return false;
     194    }
     195    name = line1.mid(pos + 2, line1.length());
     196
     197    return true;
     198}
     199
     200/* vim: set expandtab tabstop = 4 shiftwidth = 4: */
  • libs/libmythtv/cardutil.cpp

     
    571571
    572572    if (("FIREWIRE"  == cardtype) ||
    573573        ("DBOX2"     == cardtype) ||
     574        ("FREEBOX"   == cardtype) ||
    574575        ("HDHOMERUN" == cardtype) ||
    575576        ("CRC_IP"    == cardtype))
    576577    {
     
    804805
    805806    if (("FIREWIRE"  == cardtype) ||
    806807        ("DBOX2"     == cardtype) ||
     808        ("FREEBOX"   == cardtype) ||
    807809        ("HDHOMERUN" == cardtype) ||
    808810        ("CRC_IP"    == cardtype))
    809811    {
  • libs/libmythtv/freeboxmediasink.h

     
     1/**
     2 *  FreeboxMediaSink
     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 _FREEBOXMEDIASINK_H_
     8#define _FREEBOXMEDIASINK_H_
     9
     10#include <MediaSink.hh>
     11
     12class FreeboxRecorder;
     13
     14
     15
     16// ============================================================================
     17// FreeboxMediaSink : Helper class use to receive RTSP data from socket.
     18// ============================================================================
     19class FreeboxMediaSink: public MediaSink
     20{
     21  public:
     22    static FreeboxMediaSink* createNew(UsageEnvironment& env,
     23                                       FreeboxRecorder&  pRecorder,
     24                                       unsigned          bufferSize);
     25
     26    // Callback function when rtsp data are ready
     27    void addData(unsigned char* data, unsigned dataSize, struct timeval presentationTime);
     28
     29  protected:
     30    FreeboxMediaSink(UsageEnvironment& env,
     31                     FreeboxRecorder&  pRecorder,
     32                     unsigned          bufferSize);
     33    virtual ~FreeboxMediaSink();
     34
     35    static void afterGettingFrame(void*          clientData,
     36                                  unsigned       frameSize,
     37                                  unsigned       numTruncatedBytes,
     38                                  struct timeval presentationTime,
     39                                  unsigned       durationInMicroseconds);
     40    virtual void afterGettingFrame1(unsigned frameSize, struct timeval presentationTime);
     41
     42  private:
     43    virtual Boolean continuePlaying();
     44
     45  private:
     46    unsigned char*    fBuffer;
     47    unsigned          fBufferSize;
     48    UsageEnvironment& env;
     49    FreeboxRecorder&  recorder;
     50
     51  private:
     52    // avoid default contructors & operator=
     53    FreeboxMediaSink();
     54    FreeboxMediaSink(const FreeboxMediaSink&);
     55    FreeboxMediaSink& operator=(const FreeboxMediaSink&);
     56};
     57
     58#endif//_FREEBOXMEDIASINK_H_
  • libs/libmythtv/videosource.cpp

     
    993993    }
    994994};
    995995
     996class FreeboxHost : public LineEditSetting, public CCSetting {
     997  public:
     998    FreeboxHost(const CaptureCard &parent):
     999        CCSetting(parent, "freebox_mrl")
     1000    {
     1001        setValue("http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
     1002        setLabel(QObject::tr("Freebox MRL"));
     1003        setHelpText(QObject::tr("The freebox Media Resource Locator (MRL)."));
     1004    }
     1005};
     1006
    9961007class HDHomeRunTunerIndex: public ComboBoxSetting, public CCSetting
    9971008{
    9981009  public:
     
    10051016    }
    10061017};
    10071018
     1019class FreeboxConfigurationGroup: public VerticalConfigurationGroup {
     1020  public:
     1021    FreeboxConfigurationGroup(CaptureCard& a_parent):
     1022       ConfigurationGroup(false, true, false, false),
     1023       VerticalConfigurationGroup(false, true, false, false),
     1024       parent(a_parent)
     1025    {
     1026       setUseLabel(false);
     1027       addChild(new FreeboxHost(parent));
     1028    };
     1029  private:
     1030    CaptureCard& parent;
     1031};
     1032
    10081033void HDHRCardInput::fillSelections(const QString&)
    10091034{
    10101035    clearSelections();
     
    12291254    addTarget("DBOX2",     new DBOX2ConfigurationGroup(parent));
    12301255#endif // USING_DBOX2
    12311256
     1257#ifdef USING_FREEBOX
     1258    addTarget("FREEBOX",   new FreeboxConfigurationGroup(parent));
     1259#endif // USING_FREEBOX
     1260
    12321261#ifdef USING_HDHOMERUN
    12331262    addTarget("HDHOMERUN", new HDHomeRunConfigurationGroup(parent));
    12341263#endif // USING_HDHOMERUN
     
    13501379        QObject::tr("DBox2 TCP/IP cable box"), "DBOX2");
    13511380#endif // USING_DBOX2
    13521381
     1382#ifdef USING_FREEBOX
     1383    setting->addSelection(
     1384        QObject::tr("Freebox"), "FREEBOX");
     1385#endif // USING_FREEBOX
     1386
    13531387#ifdef USING_HDHOMERUN
    13541388    setting->addSelection(
    13551389        QObject::tr("HDHomeRun DTV tuner box"), "HDHOMERUN");
  • libs/libmythtv/freeboxrecorder.h

     
     1/**
     2 *  FreeboxRecorder
     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 FREEBOXRECORDER_H_
     8#define FREEBOXRECORDER_H_
     9
     10#include "dtvrecorder.h"
     11
     12class FreeboxChannel;
     13class FreeboxRecorderImpl;
     14
     15
     16
     17/**
     18 *  Constructs a FreeboxRecorder
     19 */
     20class FreeboxRecorder :
     21    public QObject, //FIXME see changeset #9743 for details
     22    public DTVRecorder
     23{
     24    Q_OBJECT
     25  public:
     26    FreeboxRecorder(TVRec *rec, FreeboxChannel *channel);
     27    ~FreeboxRecorder();
     28   
     29    void StartRecording(void);  //< RecorderBase
     30    void StopRecording(void);   //< DTVRecorder
     31
     32    // RecorderBase
     33    void SetOptionsFromProfile(RecordingProfile *profile,
     34                               const QString    &videodev,
     35                               const QString    &audiodev,
     36                               const QString    &vbidev);
     37
     38  public slots:
     39    void ChannelChanged();
     40
     41  private:
     42    friend class FreeboxMediaSink;
     43
     44    bool Open(); //< RecorderBase
     45    void Close();
     46
     47    // Callback function to add MPEG2 TS data
     48    void addData(unsigned char* data, unsigned dataSize, struct timeval presentationTime);
     49
     50    bool StartRtsp();
     51    void ResetEventLoop();
     52
     53  private:
     54    FreeboxRecorderImpl* _impl;
     55};
     56
     57#endif//FREEBOXRECORDER_H_
     58
     59/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/tv_rec.cpp

     
    4545#include "dvbchannel.h"
    4646#include "dbox2channel.h"
    4747#include "hdhrchannel.h"
     48#include "freeboxchannel.h"
    4849
    4950#include "recorderbase.h"
    5051#include "NuppelVideoRecorder.h"
     
    5354#include "dvbrecorder.h"
    5455#include "dbox2recorder.h"
    5556#include "hdhrrecorder.h"
     57#include "freeboxrecorder.h"
    5658
    5759#ifdef USING_CRC_IP_NETWORK_REC
    5860#include "crcipnetworkrecorder.h"
     
    178180        init_run = true;
    179181#endif
    180182    }
     183    else if (genOpt.cardtype == "FREEBOX")
     184    {
     185#ifdef USING_FREEBOX
     186        channel = new FreeboxChannel(this, getOpt.videodev);
     187        if (!channel->Open())
     188            return false;
     189        InitChannel(genOpt.defaultinput, startchannel);
     190        init_run = true;
     191#endif
     192    }   
    181193    else if (genOpt.cardtype == "HDHOMERUN")
    182194    {
    183195#ifdef USING_HDHOMERUN
     
    867879        recorder->SetOption("httpport", dboxOpt.httpport);
    868880#endif // USING_DBOX2
    869881    }
     882    else if (genOpt.cardtype == "FREEBOX")
     883    {
     884#ifdef USING_FREEBOX
     885        FreeboxChannel chan = dynamic_cast<FreeboxChannel*>(channel);
     886        recorder = new FreeboxRecorder(this, chan);
     887        recorder->SetOption("mrl", genOpt.videodev);
     888#endif // USING_FREEBOX
     889    }
    870890    else if (genOpt.cardtype == "HDHOMERUN")
    871891    {
    872892#ifdef USING_HDHOMERUN
  • libs/libmythtv/freeboxchannel_util.h

     
     1/** -*- Mode: c++ -*-
     2 *  FreeboxChannel utils
     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 _FREEBOXCHANNEL_UTIL_H_
     8#define _FREEBOXCHANNEL_UTIL_H_
     9
     10// Qt headers
     11#include <qwaitcondition.h>
     12#include <qmutex.h>
     13#include <qobject.h>
     14#include <qstring.h>
     15#include <qmap.h>
     16
     17class QHttp;
     18
     19class FBChanInfo
     20{
     21  public:
     22    FBChanInfo() :
     23        m_name(QString::null), m_xmltvid(QString::null),
     24        m_url(QString::null) {}
     25
     26    FBChanInfo(const QString &name, const QString &xmltvid,
     27               const QString &url) :
     28        m_name(name), m_xmltvid(xmltvid), m_url(url) {}
     29
     30    bool isValid(void) const
     31    {
     32        return !m_name.isEmpty() && !m_xmltvid.isEmpty() && !m_url.isEmpty();
     33    }
     34
     35  public:
     36    QString m_name;
     37    QString m_xmltvid;
     38    QString m_url;
     39};
     40typedef QMap<QString,FBChanInfo> fbox_chan_map_t;
     41
     42class FBChannelFetcher : public QObject
     43{
     44    Q_OBJECT
     45  public:
     46    FBChannelFetcher();
     47   ~FBChannelFetcher();
     48
     49    static fbox_chan_map_t GetChannels(const QString &videodev);
     50
     51  private slots:
     52    void HttpRequestDone(bool error);
     53
     54  private:
     55    fbox_chan_map_t LoadChannels(const QString &videodev, uint max_wait);
     56    static fbox_chan_map_t ParseChannelList(const QString &rawdata);
     57
     58  private:
     59    QHttp           *m_http;
     60    QMutex           m_lock;
     61    QWaitCondition   m_load_channel_wait;
     62    fbox_chan_map_t  m_freeboxchannels;
     63};
     64
     65#endif // _FREEBOXCHANNEL_UTIL_H_
     66
     67/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/tv_rec.h

     
    237237    void SetPseudoLiveTVRecording(ProgramInfo*);
    238238    void TeardownAll(void);
    239239
    240     static bool GetDevices(int cardid,
     240    static bool GetDevices(int                cardid,
    241241                           GeneralDBOptions   &general_opts,
    242242                           DVBDBOptions       &dvb_opts,
    243243                           FireWireDBOptions  &firewire_opts,
     
    255255    bool CreateChannel(const QString &startChanNum);
    256256    void InitChannel(const QString &inputname, const QString &startchannel);
    257257    void CloseChannel(void);
    258     DBox2Channel *GetDBox2Channel(void);
    259     HDHRChannel  *GetHDHRChannel(void);
    260     DVBChannel   *GetDVBChannel(void);
    261     Channel      *GetV4LChannel(void);
    262258
     259    DBox2Channel   *GetDBox2Channel(void);
     260    HDHRChannel    *GetHDHRChannel(void);
     261    DVBChannel     *GetDVBChannel(void);
     262    Channel        *GetV4LChannel(void);
     263
    263264    void SetupSignalMonitor(bool enable_table_monitoring, bool notify);
    264265    bool SetupDTVSignalMonitor(void);
    265266    void TeardownSignalMonitor(void);
  • settings.pro

     
    7979EXTRA_LIBS += $$CONFIG_AUDIO_JACK_LIBS
    8080EXTRA_LIBS += $$CONFIG_FIREWIRE_LIBS
    8181EXTRA_LIBS += $$CONFIG_DIRECTFB_LIBS
     82EXTRA_LIBS += $$CONFIG_LIVE_LIBS
    8283
    8384EXTRA_LIBS += $$LOCAL_LIBDIR_OGL
    8485EXTRA_LIBS += $$LOCAL_LIBDIR_X11