Ticket #1704: patch.freebox.v1.23.9974.diff

File patch.freebox.v1.23.9974.diff, 48.0 KB (added by laurent@…, 14 years ago)

Patch against last SVN

  • 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-iprec          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"
     
    21192131    fi
    21202132fi
    21212133
     2134if test x"$dvd" = x"yes" ; then
     2135    if has_library libdvdnav ; then
     2136        if has_header dvdnav/dvdnav.h ; then
     2137            dvd="yes"
     2138        fi
     2139    fi
     2140fi
     2141
     2142
    21222143VENDOR_XVMC_LIBS=""
    21232144if test x"$xvmc" = x"yes"; then
    21242145    xvmc="no"
     
    23062327  echo "FireWire support $firewire_cable_box"
    23072328  echo "DVB support      $dvb [$dvb_path]"
    23082329  echo "DBox2 support    $dbox2_dvb_box"
     2330  echo "freebox support  $freebox_box"
    23092331  echo "HDHomeRun sup.   $hdhomerun_box"
    23102332  echo "CRC Ip Rec sup.  $ip_network_recorder"
    23112333fi
     
    29602982  CCONFIG="$CCONFIG using_dbox2"
    29612983fi
    29622984
     2985if test x"$freebox_box" = x"yes" ; then
     2986  if test "x$live_lib_dir" = "x"; then
     2987    if has_library libliveMedia; then
     2988          CONFIG_LIVE_LIBS="-lliveMedia -lgroupsock -lBasicUsageEnvironment -lUsageEnvironment"
     2989        else
     2990          echo "Unable to find Live Media library."
     2991          exit 1;
     2992        fi
     2993  else
     2994    if test ! -f "$live_lib_dir/liveMedia/libliveMedia.a"; then
     2995          echo "Unable to find Live Media library."
     2996          exit 1;
     2997        fi
     2998        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"
     2999  fi
     3000  if test "x$live_include_dir" = "x"; then
     3001    if has_header liveMedia.hh; then
     3002          true
     3003        else
     3004          echo "Unable to find Live Media headers."
     3005          exit 1;
     3006        fi
     3007  else
     3008    if test -f "$live_include_dir/liveMedia/include/liveMedia.hh"; then
     3009          LIVE_INCLUDES="$live_include_dir/liveMedia/include $live_include_dir/UsageEnvironment/include $live_include_dir/BasicUsageEnvironment/include $live_include_dir/groupsock/include"
     3010        else
     3011          if test -f "$live_include_dir/liveMedia/liveMedia.hh"; then
     3012            LIVE_INCLUDES="$live_include_dir/liveMedia $live_include_dir/UsageEnvironment $live_include_dir/BasicUsageEnvironment $live_include_dir/groupsock"
     3013          else
     3014            echo "Unable to find Live Media headers."
     3015                exit 1;
     3016          fi
     3017        fi
     3018  fi
     3019  CCONFIG="$CCONFIG using_freebox"
     3020  CONFIG_DEFINES="$CONFIG_DEFINES USING_FREEBOX"
     3021  echo "CONFIG_LIVE_LIBS=$CONFIG_LIVE_LIBS" >> $MYTH_CONFIG_MAK
     3022  CONFIG_INCLUDEPATH="$CONFIG_INCLUDEPATH $LIVE_INCLUDES"
     3023fi
     3024
    29633025if test x"$hdhomerun_box" = x"yes" ; then
    29643026  CCONFIG="$CCONFIG using_hdhr"
    29653027fi
  • libs/libmythtv/freeboxchannel.h

     
     1/**
     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 "channelbase.h"
     11
     12class FreeboxDBOptions;
     13class QHttp;
     14
     15
     16
     17class FreeboxChannel : public QObject, public ChannelBase
     18{
     19    Q_OBJECT
     20  public:
     21    FreeboxChannel(TVRec *parent, FreeboxDBOptions *freebox_options, int cardid);
     22    ~FreeboxChannel(void)
     23    {
     24    }
     25
     26    bool Open();
     27    void Close();
     28    bool SwitchToInput(const QString &inputname, const QString &chan);
     29    bool SetChannelByString(const QString &chan);
     30    bool IsOpen(void) const;
     31
     32    QString GetCurrentChannelUrl();
     33
     34    bool SwitchToInput(int newcapchannel, bool setstarting)
     35    {
     36        (void)newcapchannel;
     37        (void)setstarting;
     38        return false;
     39    }
     40
     41    QString GetChannelUrlFromNumber(const QString& channelnumber);
     42    QString GetDefaultChannel();
     43
     44  signals:
     45    void ChannelChanged();
     46
     47  public slots:
     48    void HttpRequestDone(bool error);
     49
     50  private:
     51    void LoadChannels();
     52    QString normalize(QString channelName);
     53
     54    void Log(QString string);
     55
     56    QHttp                *http;
     57    FreeboxDBOptions     *m_freeboxoptions;
     58
     59    bool                  m_channelListReady;
     60    QString               m_requestChannel;
     61    QString               m_lastChannel;
     62    int                   m_cardid;
     63
     64    // the rtsp url for the current channel
     65    QString               m_currenturl;
     66
     67    // number of channel support by freebox
     68    int                   m_freeboxchannelcount;
     69
     70    // map channelNum to channel index in table
     71    QMap<int,int>         m_freeboxchannelIds;
     72
     73    // map channel index to channel url
     74    QMap<int,QString>     m_freeboxchannelUrl;
     75
     76    // map channel index to channel name
     77    QMap<int,QString>     m_freeboxchannelNames;
     78
     79    // map channel index to channel normalize name
     80    QMap<int,QString>     m_freeboxchannelNamesN;
     81};
     82
     83#endif//FREEBOXCHANNEL_H
     84
     85/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/libmythtv.pro

     
    369369    using_dbox2:SOURCES += dbox2recorder.cpp dbox2channel.cpp dbox2epg.cpp
    370370    using_dbox2:HEADERS += dbox2recorder.h dbox2channel.h dbox2epg.h
    371371    using_dbox2:DEFINES += USING_DBOX2
     372   
     373    # Support for freebox (http://adsl.free.fr/)
     374    using_freebox:SOURCES += freeboxrecorder.cpp freeboxchannel.cpp freeboxmediasink.cpp
     375    using_freebox:HEADERS += freeboxrecorder.h freeboxchannel.h freeboxmediasink.h
     376    using_freebox:DEFINES += USING_FREEBOX
    372377
    373378    # Support for HDHomeRun box
    374379    using_hdhr {
  • libs/libmythtv/freeboxchannel.cpp

     
     1/**
     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
     9#include <qhttp.h>
     10#include <qurl.h>
     11
     12#include "libmythtv/tv_rec.h"
     13
     14
     15
     16FreeboxChannel::FreeboxChannel(TVRec *parent, FreeboxDBOptions *freebox_options, int cardid):
     17                               QObject(NULL, "FreeboxChannel"),
     18                               ChannelBase(parent),
     19                               http(new QHttp()),
     20                               m_freeboxoptions(freebox_options),
     21                               m_channelListReady(false),
     22                               m_requestChannel(""),
     23                               m_lastChannel("1"),
     24                               m_cardid(cardid),
     25                               m_freeboxchannelcount(0)
     26{
     27    connect(http, SIGNAL(done(bool)),
     28            this, SLOT(HttpRequestDone(bool)));
     29
     30    LoadChannels();
     31}
     32
     33bool FreeboxChannel::SwitchToInput(const QString &inputname, const QString &chan)
     34{
     35    int inputNum = GetInputByName(inputname);
     36    if (inputNum < 0)
     37        return false;
     38
     39    return SetChannelByString(chan);
     40}
     41
     42bool FreeboxChannel::SetChannelByString(const QString &newChan)
     43{
     44    // Delay set channel when list has not yet been retrieved
     45    if (!m_channelListReady)
     46    {
     47        VERBOSE(VB_IMPORTANT,QString("Freebox # Channel list not received yet. Will switch to channel %1 later...").arg(newChan));
     48        m_requestChannel = newChan;
     49        return true;
     50    }
     51
     52    QString chan = newChan;
     53    // If chan is empty, use DefautChannel
     54    if (chan == "")
     55    {
     56        VERBOSE(VB_IMPORTANT,QString("Freebox # Empty channel name has been provided. Getting default name."));
     57        chan = GetDefaultChannel();
     58    }
     59
     60    // update current chanel
     61    if (m_lastChannel != curchannelname)
     62        m_lastChannel = curchannelname;
     63
     64    curchannelname = chan;
     65    m_currenturl = GetChannelUrlFromNumber(curchannelname);
     66
     67    // emit signal to recorder
     68    emit ChannelChanged();
     69
     70    return true;
     71}
     72
     73QString FreeboxChannel::GetCurrentChannelUrl()
     74{
     75    return m_currenturl;
     76}
     77
     78bool FreeboxChannel::IsOpen(void) const
     79{
     80    return true;
     81}
     82
     83bool FreeboxChannel::Open(void)
     84{
     85    if (!InitializeInputs())
     86        return false;
     87
     88    return true;
     89}
     90
     91void FreeboxChannel::Close(void)
     92{
     93}
     94
     95
     96// =====================================================================================
     97//
     98//  C H A N N E L     L O A D I N G
     99// =====================================================================================
     100
     101
     102void FreeboxChannel::LoadChannels()
     103{
     104    // Request Channel list via http. Signal will be emmitted when list is ready.
     105    QUrl url( m_freeboxoptions->mrl );
     106    QHttpRequestHeader header("GET", url.path());
     107    header.setValue("Host", url.host());
     108    int port = url.hasPort() ? url.port() : 80;
     109    http->setHost(url.host(), port);
     110    http->request(header);
     111}
     112
     113
     114QString FreeboxChannel::normalize(QString channelName)
     115{
     116    // Normalize Channel name so we can try to automap channel return by freebox to channel coming from tv_grab_fr
     117    static const QString map1 = QString::fromUtf8("áâÀàãåçéêëÚíîïìñóÎöòõúûÌùÜÿ");
     118    static const QString map2 = QString::fromUtf8("aaaaaaceeeeiiiinooooouuuuyy");
     119    QString res;
     120    for (unsigned int i=0;i<channelName.length();i++)
     121    {
     122        QChar c = channelName[i].lower();
     123        if (c.isSpace()) continue;
     124        int pos = map1.find(c);
     125        if (pos>=0)
     126        {
     127            res += map2[pos];
     128        }
     129        else
     130        {
     131            res += c;
     132        }
     133    }
     134
     135    return res;
     136}
     137
     138// ==========================================================================================
     139// HttpRequestDone : Receive response to channel list request
     140//
     141// ==========================================================================================
     142void FreeboxChannel::HttpRequestDone(bool error)
     143{
     144    if (error)
     145    {
     146        VERBOSE(VB_IMPORTANT,QString("Freebox # Reading channel list failed! (%1)").arg(http->errorString()));
     147        return;
     148    }
     149
     150    QString buffer = QString::fromUtf8(http->readAll());
     151    m_freeboxchannelcount = 0;
     152
     153    int sepCount = 0;
     154
     155    QString header = buffer.section("\n", sepCount, sepCount);
     156    sepCount++;
     157
     158    // Verify header is ok
     159    if (header != "#EXTM3U")
     160    {
     161        VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!"));
     162        return;
     163    }
     164
     165    while (true)
     166    {
     167        QString line1 = buffer.section("\n", sepCount, sepCount);
     168        if (line1 == "")
     169            break;
     170
     171        sepCount++;
     172
     173        QString line2 = buffer.section("\n", sepCount, sepCount);
     174        if (line2 == "")
     175            break;
     176
     177        sepCount++;
     178
     179        // each line contains ://
     180        // header:extension,channelNum - channelName rtsp://channelUrl
     181        //#EXTINF:0,2 - France 2 rtsp://mafreebox.freebox.fr/freeboxtv/201
     182
     183        QString lineHead;
     184        QString extension;
     185        QString channelNum;
     186        QString channelName;
     187
     188        int pos = 0;
     189        int oldPos = 0;
     190
     191        pos = line1.find(":", oldPos);
     192        if (pos<0)
     193        {
     194            VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!"));
     195            return;
     196        }
     197        lineHead = line1.mid(0, pos);
     198
     199        if (lineHead != "#EXTINF")
     200        {
     201            VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!"));
     202            return;
     203        }
     204
     205        oldPos = pos + 1;
     206        pos = line1.find(",", oldPos);
     207        if (pos<0)
     208        {
     209            VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!"));
     210            return;
     211        }
     212        extension = line1.mid(oldPos, pos - oldPos);
     213
     214        oldPos = pos + 1;
     215        pos = line1.find(" ", oldPos);
     216        if (pos<0)
     217        {
     218            VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!"));
     219            return;
     220        }
     221        channelNum = line1.mid(oldPos, pos - oldPos);
     222
     223        oldPos = pos + 1;
     224        pos = line1.find("- ", oldPos);
     225        if (pos<0)
     226        {
     227            VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!"));
     228            return;
     229        }
     230        channelName = line1.mid(pos + 2, line1.length());
     231
     232        QString channelUrl = line2;
     233
     234        // save all this information in map for quick access
     235        bool ok;
     236        int channelNumI = channelNum.toInt( &ok, 10 );
     237
     238        QString channelNameN = normalize(channelName);
     239
     240        m_freeboxchannelIds[channelNumI] = m_freeboxchannelcount;
     241        m_freeboxchannelUrl[m_freeboxchannelcount] = channelUrl;
     242        m_freeboxchannelNames[m_freeboxchannelcount] = channelName;
     243        m_freeboxchannelNamesN[m_freeboxchannelcount] = channelNameN;
     244
     245        m_freeboxchannelcount++;
     246    }
     247
     248    // Channel list is ready.
     249    m_channelListReady = true;
     250
     251    // Change channel if delayed request is available
     252    if (m_requestChannel != "")
     253    {
     254        SetChannelByString(m_requestChannel);
     255        m_requestChannel = "";
     256    }
     257}
     258
     259
     260// ==========================================================================================
     261// GetChannelUrlFromNumber : Map a channel number to the corresponding rtsp URL
     262//
     263// ==========================================================================================
     264QString FreeboxChannel::GetChannelUrlFromNumber(const QString& channelnumber)
     265{
     266    MSqlQuery query(MSqlQuery::InitCon());
     267
     268    query.prepare("SELECT name,freqid "
     269          "FROM channel,cardinput "
     270                  "WHERE "
     271          "channel.sourceid = cardinput.sourceid AND "
     272          "cardinput.cardid = :CARDID AND "
     273                  "channel.channum = :CHANNUM");
     274
     275    query.bindValue(":CARDID", m_cardid);
     276    query.bindValue(":CHANNUM", channelnumber);
     277
     278    if (query.exec() && query.isActive() && query.size() > 0)
     279    {
     280        query.next();
     281        QString chanName = query.value(0).toString();
     282
     283        // if we have a FreqID in the table, use this as the real freebox channel number
     284        int mFreqId = query.value(1).toInt();
     285        if (mFreqId!=0)
     286        {
     287            int channelI = m_freeboxchannelIds[mFreqId];
     288            return m_freeboxchannelUrl[channelI];
     289        }
     290
     291        // if no freqID, try to map the chanName to an existing channel name
     292        for (int i=0;i<m_freeboxchannelcount;i++)
     293        {
     294            if (m_freeboxchannelNamesN[i] == chanName)
     295            {
     296                return m_freeboxchannelUrl[i];
     297            }
     298        }
     299
     300        VERBOSE(VB_IMPORTANT,QString("Freebox # GetChannelUrlFromNumber(num=%1,name=%2) failed")
     301                .arg(channelnumber)
     302                .arg(chanName));
     303        return "";
     304    }
     305    VERBOSE(VB_IMPORTANT,QString("Freebox # GetChannelUrlFromNumber(num=%1) failed")
     306            .arg(channelnumber));
     307    return "";
     308}
     309
     310// ==========================================================================================
     311// GetDefaultChannel : Search for default channel
     312//
     313// ==========================================================================================
     314
     315QString FreeboxChannel::GetDefaultChannel()
     316{
     317    MSqlQuery query(MSqlQuery::InitCon());   
     318    query.prepare("SELECT channum "
     319          "FROM channel,cardinput "
     320                  "WHERE "
     321          "channel.sourceid = cardinput.sourceid AND "
     322          "cardinput.cardid = :CARDID "
     323          "ORDER BY channum limit 1");
     324
     325    query.bindValue(":CARDID", m_cardid);
     326
     327    if (query.exec() && query.isActive() && query.size() > 0)
     328    {
     329        query.next();
     330        return query.value(0).toString();
     331    }
     332    return "";
     333}
     334
     335/* 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 = "1139";
     13const QString currentDatabaseVersion = "1140";
    1414
    1515static bool UpdateDBVersionNumber(const QString &newnumber);
    1616static bool performActualUpdate(const QString updates[], QString version,
     
    22312231//"ALTER TABLE capturecard DROP COLUMN dvb_hw_decoder;" in 0.21
    22322232//"ALTER TABLE cardinput DROP COLUMN  preference;" in 0.22
    22332233
     2234  if (dbver == "1139")
     2235    {
     2236        const QString updates[] = {
     2237"INSERT INTO profilegroups SET name = 'Freebox Input', cardtype = 'Freebox', is_default = 1;",
     2238"ALTER TABLE capturecard ADD COLUMN freebox_mrl varchar(64) DEFAULT 'http://mafreebox.freebox.fr/freeboxtv/playlist.m3u';",
     2239""
     2240};
     2241
     2242        if (!performActualUpdate(updates, "1140", dbver))
     2243            return false;
     2244    }
     2245
     2246
    22342247    return true;
    22352248}
    22362249
     
    22912304"  dbox2_port int(10) unsigned NOT NULL default '31338',"
    22922305"  dbox2_httpport int(10) unsigned NOT NULL default '80',"
    22932306"  dbox2_host varchar(32) default NULL,"
     2307"  freebox_mrl varchar(64) DEFAULT 'http://mafreebox.freebox.fr/freeboxtv/playlist.m3u',"
    22942308"  signal_timeout int(11) NOT NULL default '1000',"
    22952309"  channel_timeout int(11) NOT NULL default '3000',"
    22962310"  PRIMARY KEY  (cardid)"
     
    28572871"INSERT INTO profilegroups VALUES (8,"
    28582872" 'USB Mpeg-4 Encoder (Plextor ConvertX, etc)','GO7007',1,NULL);",
    28592873"INSERT INTO profilegroups VALUES (9,'DBOX2 Input','DBOX2',1,NULL);",
     2874"INSERT INTO `profilegroups` VALUES (10,'Freebox Input','Freebox',1,NULL);",
    28602875"INSERT INTO recordingprofiles VALUES (1,'Default',NULL,NULL,1);",
    28612876"INSERT INTO recordingprofiles VALUES (2,'Live TV',NULL,NULL,1);",
    28622877"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    connect(channel, SIGNAL(ChannelChanged()),
     115            this,    SLOT(  ChannelChanged()));
     116}
     117
     118
     119
     120FreeboxRecorder::~FreeboxRecorder()
     121{
     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    QString url = _impl->_channel.GetCurrentChannelUrl();
     225
     226    // Begin by setting up our usage environment:
     227    TaskScheduler* scheduler = BasicTaskScheduler::createNew();
     228    _impl->env = BasicUsageEnvironment::createNew(*scheduler);
     229
     230
     231    // Create our client object:
     232    _impl->rtspClient = RTSPClient::createNew(*_impl->env, 0, "myRTSP", 0);
     233    if (_impl->rtspClient == NULL)
     234    {
     235        VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create RTSP client: %1")
     236            .arg(_impl->env->getResultMsg()));
     237        return false;
     238    }
     239
     240    // Setup URL for the current session
     241    char* sdpDescription = _impl->rtspClient->describeURL(url);
     242    _impl->rtspClient->describeStatus();
     243    if (sdpDescription == NULL)
     244    {
     245        VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to get a SDP description from URL: %1 %2")
     246            .arg(url)
     247            .arg(_impl->env->getResultMsg()));
     248        return false;
     249    }
     250
     251    // Create a media session object from this SDP description:
     252    _impl->session = MediaSession::createNew(*_impl->env, sdpDescription);
     253    delete[] sdpDescription;
     254    if (_impl->session == NULL)
     255    {
     256        VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create MediaSession: %1")
     257            .arg(_impl->env->getResultMsg()));
     258        return false;
     259    }
     260    else if (!_impl->session->hasSubsessions())
     261    {
     262        VERBOSE(VB_IMPORTANT, QString("Freebox # This session has no media subsessions"));
     263        return false;
     264    }
     265
     266    // Then, setup the "RTPSource"s for the session:
     267    MediaSubsessionIterator iter(*_impl->session);
     268    MediaSubsession *subsession;
     269    Boolean madeProgress = False;
     270    while ((subsession = iter.next()) != NULL)
     271    {
     272        if (!subsession->initiate(-1))
     273        {
     274            VERBOSE(VB_IMPORTANT, QString("Freebox # Unable to create receiver for: %1 / %2 subsession: %3")
     275                    .arg(subsession->mediumName())
     276                    .arg(subsession->codecName())
     277                    .arg(_impl->env->getResultMsg()));
     278        }
     279        else
     280        {
     281            madeProgress = True;
     282
     283            if (subsession->rtpSource() != NULL)
     284            {
     285                  unsigned const thresh = 1000000; // 1 second
     286                  subsession->rtpSource()->setPacketReorderingThresholdTime(thresh);
     287            }
     288        }
     289    }
     290
     291    if (!madeProgress) return false;
     292
     293    // Perform additional 'setup' on each subsession, before playing them:
     294    madeProgress = false;
     295    iter.reset();
     296    while ((subsession = iter.next()) != NULL)
     297    {
     298        if (subsession->clientPortNum() == 0) continue; // port # was not set
     299
     300        if (_impl->rtspClient->setupMediaSubsession(*subsession, False, false))
     301        {
     302            madeProgress = True;
     303        }
     304        else
     305        {
     306            VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to setup: %1 %2 : %3")
     307                .arg(subsession->mediumName())
     308                .arg(subsession->codecName())
     309                .arg(_impl->env->getResultMsg()));
     310        }
     311    }
     312
     313    if (!madeProgress) return false;
     314
     315   // Create and start "FileSink"s for each subsession:
     316   // FileSink while receive Mpeg2 TS Data & will feed them to mythtv
     317    madeProgress = False;
     318    iter.reset();
     319    while ((subsession = iter.next()) != NULL)
     320    {
     321        if (subsession->readSource() == NULL) continue; // was not initiated
     322
     323        FreeboxMediaSink* freeboxMediaSink =
     324            FreeboxMediaSink::createNew(*_impl->env, *this, TSPacket::SIZE*128);
     325
     326        subsession->sink = freeboxMediaSink;
     327        if (subsession->sink == NULL)
     328        {
     329            VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create sink: %1")
     330                .arg(_impl->env->getResultMsg()));
     331        }
     332
     333        subsession->sink->startPlaying(
     334                *(subsession->readSource()),
     335                FreeboxData::subsessionAfterPlayingCallback,
     336                new FreeboxData(this, subsession));
     337
     338        if (subsession->rtcpInstance() != NULL)
     339        {
     340            subsession->rtcpInstance()->setByeHandler(
     341                    FreeboxData::subsessionByeHandlerCallback,
     342                    new FreeboxData(this, subsession));
     343        }
     344
     345        madeProgress = True;
     346    }
     347
     348    if (!madeProgress) return false;
     349
     350    // Setup player
     351    if (!(_impl->rtspClient->playMediaSession(*_impl->session)))
     352    {
     353        VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to start playing session: %1")
     354            .arg(_impl->env->getResultMsg()));
     355        return false;
     356    }
     357
     358    return true;
     359}
     360
     361// ===================================================
     362// findTSHeader : find a TS Header in flow
     363// ===================================================
     364static int FreeboxRecorder_findTSHeader(const unsigned char *data, unsigned dataSize)
     365{
     366    unsigned int pos = 0;
     367    while (pos < dataSize)
     368    {
     369        if (data[pos] == 0x47)
     370            return pos;
     371        pos++;
     372    }
     373    return -1;
     374}
     375
     376// ===================================================
     377// addData : feed date from RTSP flow to mythtv
     378// ===================================================
     379void FreeboxRecorder::addData(unsigned char* data, unsigned dataSize, struct timeval)
     380{
     381    unsigned int readIndex = 0;
     382
     383    // data may be compose from more than one packet, loop to consume all data
     384    while (readIndex < dataSize)
     385    {
     386        // If recorder is pause, stop there
     387        if (PauseAndWait())
     388        {
     389            return;
     390        }
     391
     392        // Find the next TS Header in data
     393        int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize);
     394
     395        // if no TS, something bad happens
     396        if (tsPos == -1)
     397        {
     398            VERBOSE(VB_IMPORTANT, QString("FREEBOX: No TS header."));
     399            break;
     400        }
     401
     402        // if TS Header not at start of data, we receive out of sync data
     403        if (tsPos > 0)
     404        {
     405            VERBOSE(VB_IMPORTANT, QString("FREEBOX: TS header at %1, not in sync.").arg(tsPos));
     406        }
     407
     408        // Check if the next packet in buffer is complete : packet size is 188 bytes long
     409        if ((dataSize - tsPos) < TSPacket::SIZE)
     410        {
     411            VERBOSE(VB_IMPORTANT, QString("FREEBOX: TS header at %1 but packet not yet complete.").arg(tsPos));
     412            break;
     413        }
     414
     415        // Cast current found TS Packet to TSPacket structure
     416        const void *newData = data + tsPos + readIndex;
     417        const TSPacket *tspacket = reinterpret_cast<const TSPacket*>(newData);
     418
     419        // Feed current packet to myth
     420        _buffer_packets = !FindMPEG2Keyframes(tspacket);
     421        BufferedWrite(*tspacket);
     422
     423        // follow to next packet
     424        readIndex += tsPos + TSPacket::SIZE;
     425    }
     426}
     427
     428/* 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    {
     
    768769                .arg(query.value(1).toString())
    769770                .arg(query.value(2).toString());
    770771    }
     772    else if (cardtype == "FREEBOX")
     773    {
     774        MSqlQuery query(MSqlQuery::InitCon());
     775        query.prepare(
     776            "SELECT freebox_mrl "
     777            "FROM capturecard "
     778            "WHERE cardid = :CARDID");
     779        query.bindValue(":CARDID", cardid);
     780
     781        if (!query.exec() || !query.isActive() || !query.next())
     782            label = "[ DB ERROR ]";
     783        else
     784            label = QString("[ FREEBOX : MRL %1 ]")
     785                .arg(query.value(0).toString());
     786    }
    771787    else if (cardtype == "HDHOMERUN")
    772788    {
    773789        MSqlQuery query(MSqlQuery::InitCon());
     
    804820
    805821    if (("FIREWIRE"  == cardtype) ||
    806822        ("DBOX2"     == cardtype) ||
     823        ("FREEBOX"   == cardtype) ||
    807824        ("HDHOMERUN" == cardtype) ||
    808825        ("CRC_IP"    == cardtype))
    809826    {
  • 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

     
    5454#include "dbox2recorder.h"
    5555#include "hdhrrecorder.h"
    5656
     57#ifdef USING_FREEBOX
     58#include "freeboxrecorder.h"
     59#include "freeboxchannel.h"
     60#endif // USING_FREEBOX
     61
    5762#ifdef USING_CRC_IP_NETWORK_REC
    5863#include "crcipnetworkrecorder.h"
    5964#endif
     
    183188        init_run = true;
    184189#endif
    185190    }
     191    else if (genOpt.cardtype == "FREEBOX")
     192    {
     193#ifdef USING_FREEBOX
     194        channel = new FreeboxChannel(this, &freeboxOpt, cardid);
     195        if (!channel->Open())
     196            return false;
     197        InitChannel(genOpt.defaultinput, startchannel);
     198        init_run = true;
     199#endif
     200    }   
    186201    else if (genOpt.cardtype == "HDHOMERUN")
    187202    {
    188203#ifdef USING_HDHOMERUN
     
    249264{
    250265    QMutexLocker lock(&stateChangeLock);
    251266
    252     if (!GetDevices(cardid, genOpt, dvbOpt, fwOpt, dboxOpt))
     267    if (!GetDevices(cardid, genOpt, dvbOpt, fwOpt, dboxOpt, freeboxOpt))
    253268        return false;
    254269
    255270    // configure the Channel instance
     
    308323        scanner = NULL;
    309324    }
    310325
     326#ifdef USING_FREEBOX
     327    if (GetFreeboxChannel())
     328        GetFreeboxChannel()->deleteLater();
     329    else
     330#endif // USING_FREEBOX
    311331    if (channel)
    312332    {
    313333        delete channel;
     
    871891        recorder->SetOption("httpport", dboxOpt.httpport);
    872892#endif // USING_DBOX2
    873893    }
     894    else if (genOpt.cardtype == "FREEBOX")
     895    {
     896#ifdef USING_FREEBOX
     897        recorder = new FreeboxRecorder(this, GetFreeboxChannel());
     898        recorder->SetOption("mrl", freeboxOpt.mrl);
     899#endif // USING_FREEBOX
     900    }
    874901    else if (genOpt.cardtype == "HDHOMERUN")
    875902    {
    876903#ifdef USING_HDHOMERUN
     
    10811108#endif // USING_DBOX2
    10821109}
    10831110
     1111FreeboxChannel *TVRec::GetFreeboxChannel(void)
     1112{
     1113#ifdef USING_FREEBOX
     1114    return dynamic_cast<FreeboxChannel*>(channel);
     1115#else
     1116    return NULL;
     1117#endif // USING_FREEBOX
     1118}
     1119 
    10841120HDHRChannel *TVRec::GetHDHRChannel(void)
    10851121{
    10861122#ifdef USING_HDHOMERUN
     
    13661402    return ok;
    13671403}
    13681404
    1369 bool TVRec::GetDevices(int cardid,
    1370                        GeneralDBOptions   &gen_opts,
    1371                        DVBDBOptions       &dvb_opts,
    1372                        FireWireDBOptions  &firewire_opts,
    1373                        DBox2DBOptions     &dbox2_opts)
     1405bool TVRec::GetDevices(int               cardid,
     1406                       GeneralDBOptions  &gen_opts,
     1407                       DVBDBOptions      &dvb_opts,
     1408                       FireWireDBOptions &firewire_opts,
     1409                       DBox2DBOptions    &dbox2_opts,
     1410                       FreeboxDBOptions  &freebox_opts)
    13741411{
    13751412    int testnum = 0;
    13761413    QString test;
     
    13871424        "       firewire_port,    firewire_node,       firewire_speed,  "
    13881425        "       firewire_model,   firewire_connection,                  "
    13891426        ""
    1390         "       dbox2_port,       dbox2_host,          dbox2_httpport   "
     1427        "       dbox2_port,       dbox2_host,          dbox2_httpport,  "
     1428        "       freebox_mrl "
    13911429        ""
    13921430        "FROM capturecard "
    13931431        "WHERE cardid = :CARDID");
     
    14651503
    14661504    dbox2_opts.httpport = query.value(dbox2off + 2).toUInt();
    14671505
     1506    // Freebox options
     1507    uint freeboxoff = dbox2off + 3;
     1508    test = query.value(freeboxoff).toString();
     1509    if (test != QString::null)
     1510        freebox_opts.mrl = QString::fromUtf8(test);
     1511
    14681512    return true;
    14691513}
    14701514
     
    32913335        delete channel;
    32923336        channel = NULL;
    32933337
    3294         GetDevices(newCardID, genOpt, dvbOpt, fwOpt, dboxOpt);
     3338        GetDevices(newCardID, genOpt, dvbOpt, fwOpt, dboxOpt, freeboxOpt);
    32953339        genOpt.defaultinput = inputname;
    32963340        CreateChannel(channum);
    32973341        if (!(request.flags & kFlagNoRec))
  • libs/libmythtv/tv_rec.h

     
    3939class DVBChannel;
    4040class Channel;
    4141
     42class FreeboxChannel;
     43
     44
    4245class MPEGStreamData;
    4346class ProgramMapTable;
    4447
     
    130133    QString host;
    131134};
    132135
     136 
     137class FreeboxDBOptions
     138{
     139  public:
     140    FreeboxDBOptions() : mrl("http://mafreebox.freebox.fr/freeboxtv/playlist.m3u") {}
     141
     142        QString mrl;
     143};
     144
     145
    133146class TuningRequest
    134147{
    135148  public:
     
    262275    void SetPseudoLiveTVRecording(ProgramInfo*);
    263276    void TeardownAll(void);
    264277
    265     static bool GetDevices(int cardid,
     278    static bool GetDevices(int                cardid,
    266279                           GeneralDBOptions   &general_opts,
    267280                           DVBDBOptions       &dvb_opts,
    268281                           FireWireDBOptions  &firewire_opts,
    269                            DBox2DBOptions     &dbox2_opts);
     282                           DBox2DBOptions     &dbox2_opts,
     283                           FreeboxDBOptions   &free_opts);
    270284
    271285
    272286    static QString GetStartChannel(int cardid, const QString &defaultinput);
     
    280294    bool CreateChannel(const QString &startChanNum);
    281295    void InitChannel(const QString &inputname, const QString &startchannel);
    282296    void CloseChannel(void);
    283     DBox2Channel *GetDBox2Channel(void);
    284     HDHRChannel  *GetHDHRChannel(void);
    285     DVBChannel   *GetDVBChannel(void);
    286     Channel      *GetV4LChannel(void);
    287297
     298    DBox2Channel   *GetDBox2Channel(void);
     299    HDHRChannel    *GetHDHRChannel(void);
     300    DVBChannel     *GetDVBChannel(void);
     301    FreeboxChannel *GetFreeboxChannel(void);
     302    Channel        *GetV4LChannel(void);
     303
    288304    void SetupSignalMonitor(bool enable_table_monitoring, bool notify);
    289305    bool SetupDTVSignalMonitor(void);
    290306    void TeardownSignalMonitor(void);
     
    361377    DVBDBOptions       dvbOpt;
    362378    FireWireDBOptions  fwOpt;
    363379    DBox2DBOptions     dboxOpt;
     380    FreeboxDBOptions   freeboxOpt;
    364381
    365382    // State variables
    366383    QMutex         stateChangeLock;
  • 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