Ticket #1704: patch.freebox.v1.17.9856.diff
File patch.freebox.v1.17.9856.diff, 44.2 KB (added by , 18 years ago) |
---|
-
configure
54 54 lirc="yes" 55 55 joystick_menu="yes" 56 56 firewire_cable_box="yes" 57 freebox_box="yes" 57 58 dbox2_dvb_box="yes" 58 59 hdhomerun_box="yes" 59 60 x11_include_path="/usr/X11R6/include" … … 175 176 echo " --disable-lirc disable lirc support (Infrared Remotes)" 176 177 echo " --disable-joystick-menu disable joystick menu" 177 178 echo " --disable-firewire disable support for FireWire cable boxes" 179 echo " --disable-freebox disable support for Freebox" 180 echo " --livelibdir=DIR location of Live streaming library" 181 echo " --liveincludedir=DIR location of Live streaming include files" 178 182 echo " --disable-dbox2 disable support for Nokia DBOX2 DVB boxes (or compatibles)" 179 183 echo " --disable-hdhomerun disable support for HDHomeRun boxes" 180 184 echo " --disable-v4l disable Video4Linux support" … … 813 817 ;; 814 818 --disable-dbox2) dbox2_dvb_box="no" 815 819 ;; 820 --enable-freebox) freebox_box="yes" 821 ;; 822 --disable-freebox) freebox_box="no" 823 ;; 824 --livelibdir=*) live_lib_dir=`echo $opt | cut -d '=' -f 2` 825 ;; 826 --liveincludedir=*) live_include_dir=`echo $opt | cut -d '=' -f 2` 827 ;; 816 828 --enable-hdhomerun) hdhomerun_box="yes" 817 829 ;; 818 830 --disable-hdhomerun) hdhomerun_box="no" … … 2105 2117 fi 2106 2118 fi 2107 2119 2120 if test x"$dvd" = x"yes" ; then 2121 if has_library libdvdnav ; then 2122 if has_header dvdnav/dvdnav.h ; then 2123 dvd="yes" 2124 fi 2125 fi 2126 fi 2127 2128 2108 2129 VENDOR_XVMC_LIBS="" 2109 2130 if test x"$xvmc" = x"yes"; then 2110 2131 xvmc="no" … … 2271 2292 echo "FireWire support $firewire_cable_box" 2272 2293 echo "DVB support $dvb [$dvb_path]" 2273 2294 echo "DBox2 support $dbox2_dvb_box" 2295 echo "freebox support $freebox_box" 2274 2296 echo "HDHomeRun sup. $hdhomerun_box" 2275 2297 fi 2276 2298 … … 2917 2939 CCONFIG="$CCONFIG using_dbox2" 2918 2940 fi 2919 2941 2942 if test x"$freebox_box" = x"yes" ; then 2943 if test "x$live_lib_dir" = "x"; then 2944 if has_library libliveMedia; then 2945 CONFIG_LIVE_LIBS="-lliveMedia -lgroupsock -lBasicUsageEnvironment -lUsageEnvironment" 2946 else 2947 echo "Unable to find Live Media library." 2948 exit 1; 2949 fi 2950 else 2951 if test ! -f "$live_lib_dir/liveMedia/libliveMedia.a"; then 2952 echo "Unable to find Live Media library." 2953 exit 1; 2954 fi 2955 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" 2956 fi 2957 if test "x$live_include_dir" = "x"; then 2958 if has_header liveMedia.hh; then 2959 true 2960 else 2961 echo "Unable to find Live Media headers." 2962 exit 1; 2963 fi 2964 else 2965 if test -f "$live_include_dir/liveMedia/include/liveMedia.hh"; then 2966 LIVE_INCLUDES="$live_include_dir/liveMedia/include $live_include_dir/UsageEnvironment/include $live_include_dir/BasicUsageEnvironment/include $live_include_dir/groupsock/include" 2967 else 2968 if test -f "$live_include_dir/liveMedia/liveMedia.hh"; then 2969 LIVE_INCLUDES="$live_include_dir/liveMedia $live_include_dir/UsageEnvironment $live_include_dir/BasicUsageEnvironment $live_include_dir/groupsock" 2970 else 2971 echo "Unable to find Live Media headers." 2972 exit 1; 2973 fi 2974 fi 2975 fi 2976 CCONFIG="$CCONFIG using_freebox" 2977 CONFIG_DEFINES="$CONFIG_DEFINES USING_FREEBOX" 2978 echo "CONFIG_LIVE_LIBS=$CONFIG_LIVE_LIBS" >> $MYTH_CONFIG_MAK 2979 CONFIG_INCLUDEPATH="$CONFIG_INCLUDEPATH $LIVE_INCLUDES" 2980 fi 2981 2920 2982 if test x"$hdhomerun_box" = x"yes" ; then 2921 2983 CCONFIG="$CCONFIG using_hdhr" 2922 2984 fi -
libs/libmythtv/freeboxchannel.h
1 #ifndef FREEBOXCHANNEL_H 2 #define FREEBOXCHANNEL_H 3 4 #include "channelbase.h" 5 6 class FreeboxDBOptions; 7 class QHttp; 8 9 10 11 class FreeboxChannel : public QObject, public ChannelBase 12 { 13 Q_OBJECT 14 public: 15 FreeboxChannel(TVRec *parent, FreeboxDBOptions *freebox_options, int cardid); 16 ~FreeboxChannel(void) 17 { 18 } 19 20 bool Open(); 21 void Close(); 22 bool SwitchToInput(const QString &inputname, const QString &chan); 23 bool SetChannelByString(const QString &chan); 24 bool IsOpen(void) const; 25 26 QString GetCurrentChannelUrl(); 27 28 bool SwitchToInput(int newcapchannel, bool setstarting) 29 { 30 (void)newcapchannel; 31 (void)setstarting; 32 return false; 33 } 34 35 QString GetChannelUrlFromNumber(const QString& channelnumber); 36 QString GetDefaultChannel(); 37 38 signals: 39 void ChannelChanged(); 40 41 public slots: 42 void HttpRequestDone(bool error); 43 44 private: 45 void LoadChannels(); 46 QString normalize(QString channelName); 47 48 void Log(QString string); 49 50 QHttp *http; 51 FreeboxDBOptions *m_freeboxoptions; 52 53 bool m_channelListReady; 54 QString m_requestChannel; 55 QString m_lastChannel; 56 int m_cardid; 57 58 // the rtsp url for the current channel 59 QString m_currenturl; 60 61 // number of channel support by freebox 62 int m_freeboxchannelcount; 63 64 // map channelNum to channel index in table 65 QMap<int,int> m_freeboxchannelIds; 66 67 // map channel index to channel url 68 QMap<int,QString> m_freeboxchannelUrl; 69 70 // map channel index to channel name 71 QMap<int,QString> m_freeboxchannelNames; 72 73 // map channel index to channel normalize name 74 QMap<int,QString> m_freeboxchannelNamesN; 75 }; 76 77 #endif//FREEBOXCHANNEL_H 78 79 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/libmythtv.pro
348 348 using_dbox2:SOURCES += dbox2recorder.cpp dbox2channel.cpp dbox2epg.cpp 349 349 using_dbox2:HEADERS += dbox2recorder.h dbox2channel.h dbox2epg.h 350 350 using_dbox2:DEFINES += USING_DBOX2 351 352 # Support for freebox (http://adsl.free.fr/) 353 using_freebox:SOURCES += freeboxrecorder.cpp freeboxchannel.cpp freeboxmediasink.cpp 354 using_freebox:HEADERS += freeboxrecorder.h freeboxchannel.h freeboxmediasink.h 355 using_freebox:DEFINES += USING_FREEBOX 351 356 352 357 # Support for HDHomeRun box 353 358 using_hdhr { -
libs/libmythtv/freeboxchannel.cpp
1 /** 2 * FreeboxChannel 3 * Copyright (c) 2005 by Levent Gündogdu 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 13 14 FreeboxChannel::FreeboxChannel(TVRec *parent, FreeboxDBOptions *freebox_options, int cardid): 15 QObject(NULL, "FreeboxChannel"), 16 ChannelBase(parent), 17 http(new QHttp()), 18 m_freeboxoptions(freebox_options), 19 m_channelListReady(false), 20 m_requestChannel(""), 21 m_lastChannel("1"), 22 m_cardid(cardid), 23 m_freeboxchannelcount(0) 24 { 25 connect(http, SIGNAL(done(bool)), 26 this, SLOT(HttpRequestDone(bool))); 27 28 LoadChannels(); 29 } 30 31 bool FreeboxChannel::SwitchToInput(const QString &inputname, const QString &chan) 32 { 33 int inputNum = GetInputByName(inputname); 34 if (inputNum < 0) 35 return false; 36 37 return SetChannelByString(chan); 38 } 39 40 bool FreeboxChannel::SetChannelByString(const QString &newChan) 41 { 42 // Delay set channel when list has not yet been retrieved 43 if (!m_channelListReady) 44 { 45 VERBOSE(VB_IMPORTANT,QString("Freebox # Channel list not received yet. Will switch to channel %1 later...").arg(newChan)); 46 m_requestChannel = newChan; 47 return true; 48 } 49 50 QString chan = newChan; 51 // If chan is empty, use DefautChannel 52 if (chan == "") 53 { 54 VERBOSE(VB_IMPORTANT,QString("Freebox # Empty channel name has been provided. Getting default name.")); 55 chan = GetDefaultChannel(); 56 } 57 58 // update current chanel 59 if (m_lastChannel != curchannelname) 60 m_lastChannel = curchannelname; 61 62 curchannelname = chan; 63 m_currenturl = GetChannelUrlFromNumber(curchannelname); 64 65 // emit signal to recorder 66 emit ChannelChanged(); 67 68 return true; 69 } 70 71 QString FreeboxChannel::GetCurrentChannelUrl() 72 { 73 return m_currenturl; 74 } 75 76 bool FreeboxChannel::IsOpen(void) const 77 { 78 return true; 79 } 80 81 bool FreeboxChannel::Open(void) 82 { 83 if (!InitializeInputs()) 84 return false; 85 86 return true; 87 } 88 89 void FreeboxChannel::Close(void) 90 { 91 } 92 93 94 // ===================================================================================== 95 // 96 // C H A N N E L L O A D I N G 97 // ===================================================================================== 98 99 100 void FreeboxChannel::LoadChannels() 101 { 102 // Request Channel list via http. Signal will be emmitted when list is ready. 103 QUrl url( m_freeboxoptions->mrl ); 104 QHttpRequestHeader header("GET", url.path()); 105 header.setValue("Host", url.host()); 106 int port = url.hasPort() ? url.port() : 80; 107 http->setHost(url.host(), port); 108 http->request(header); 109 } 110 111 112 QString FreeboxChannel::normalize(QString channelName) 113 { 114 // Normalize Channel name so we can try to automap channel return by freebox to channel coming from tv_grab_fr 115 QString res; 116 for (unsigned int i=0;i<channelName.length();i++) 117 { 118 QChar c = channelName[i]; 119 if (c.isSpace()) continue; 120 c = c.lower(); 121 if (c=='é' || c=='ê' || c=='ê') c='e'; 122 if (c=='à') c='a'; 123 if (c=='i' || c=='î') c=='i'; 124 if (c=='ô') c=='o'; 125 126 res += c; 127 } 128 129 return res; 130 } 131 132 // ========================================================================================== 133 // HttpRequestDone : Receive response to channel list request 134 // 135 // ========================================================================================== 136 void FreeboxChannel::HttpRequestDone(bool error) 137 { 138 if (error) 139 { 140 VERBOSE(VB_IMPORTANT,QString("Freebox # Reading channel list failed! (%1)").arg(http->errorString())); 141 return; 142 } 143 144 QString buffer=http->readAll(); 145 m_freeboxchannelcount = 0; 146 147 int sepCount = 0; 148 149 QString header = buffer.section("\n", sepCount, sepCount); 150 sepCount++; 151 152 // Verify header is ok 153 if (header != "#EXTM3U") 154 { 155 VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!")); 156 return; 157 } 158 159 while (true) 160 { 161 QString line1 = buffer.section("\n", sepCount, sepCount); 162 if (line1 == "") 163 break; 164 165 sepCount++; 166 167 QString line2 = buffer.section("\n", sepCount, sepCount); 168 if (line2 == "") 169 break; 170 171 sepCount++; 172 173 // each line contains :// 174 // header:extension,channelNum - channelName rtsp://channelUrl 175 //#EXTINF:0,2 - France 2 rtsp://mafreebox.freebox.fr/freeboxtv/201 176 177 QString lineHead; 178 QString extension; 179 QString channelNum; 180 QString channelName; 181 182 int pos = 0; 183 int oldPos = 0; 184 185 pos = line1.find(":", oldPos); 186 if (pos<0) 187 { 188 VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!")); 189 return; 190 } 191 lineHead = line1.mid(0, pos); 192 193 if (lineHead != "#EXTINF") 194 { 195 VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!")); 196 return; 197 } 198 199 oldPos = pos + 1; 200 pos = line1.find(",", oldPos); 201 if (pos<0) 202 { 203 VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!")); 204 return; 205 } 206 extension = line1.mid(oldPos, pos - oldPos); 207 208 oldPos = pos + 1; 209 pos = line1.find(" ", oldPos); 210 if (pos<0) 211 { 212 VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!")); 213 return; 214 } 215 channelNum = line1.mid(oldPos, pos - oldPos); 216 217 oldPos = pos + 1; 218 pos = line1.find("- ", oldPos); 219 if (pos<0) 220 { 221 VERBOSE(VB_IMPORTANT,QString("Freebox # Invalid header while retrieve channel list.!")); 222 return; 223 } 224 channelName = line1.mid(pos + 2, line1.length()); 225 226 QString channelUrl = line2; 227 228 // save all this information in map for quick access 229 bool ok; 230 int channelNumI = channelNum.toInt( &ok, 10 ); 231 232 QString channelNameN = normalize(channelName); 233 234 m_freeboxchannelIds[channelNumI] = m_freeboxchannelcount; 235 m_freeboxchannelUrl[m_freeboxchannelcount] = channelUrl; 236 m_freeboxchannelNames[m_freeboxchannelcount] = channelName; 237 m_freeboxchannelNamesN[m_freeboxchannelcount] = channelNameN; 238 239 m_freeboxchannelcount++; 240 } 241 242 // Channel list is ready. 243 m_channelListReady = true; 244 245 // Change channel if delayed request is available 246 if (m_requestChannel != "") 247 { 248 SetChannelByString(m_requestChannel); 249 m_requestChannel = ""; 250 } 251 } 252 253 254 // ========================================================================================== 255 // GetChannelUrlFromNumber : Map a channel number to the corresponding rtsp URL 256 // 257 // ========================================================================================== 258 QString FreeboxChannel::GetChannelUrlFromNumber(const QString& channelnumber) 259 { 260 MSqlQuery query(MSqlQuery::InitCon()); 261 262 query.prepare("SELECT name,freqid " 263 "FROM channel,cardinput " 264 "WHERE " 265 "channel.sourceid = cardinput.sourceid AND " 266 "cardinput.cardid = :CARDID AND " 267 "channel.channum = :CHANNUM"); 268 269 query.bindValue(":CARDID", m_cardid); 270 query.bindValue(":CHANNUM", channelnumber); 271 272 if (query.exec() && query.isActive() && query.size() > 0) 273 { 274 query.next(); 275 QString chanName = query.value(0).toString(); 276 277 // if we have a FreqID in the table, use this as the real freebox channel number 278 int mFreqId = query.value(1).toInt(); 279 if (mFreqId!=0) 280 { 281 int channelI = m_freeboxchannelIds[mFreqId]; 282 return m_freeboxchannelUrl[channelI]; 283 } 284 285 // if no freqID, try to map the chanName to an existing channel name 286 for (int i=0;i<m_freeboxchannelcount;i++) 287 { 288 if (m_freeboxchannelNamesN[i] == chanName) 289 { 290 return m_freeboxchannelUrl[i]; 291 } 292 } 293 294 return ""; 295 } 296 return ""; 297 } 298 299 // ========================================================================================== 300 // GetDefaultChannel : Search for default channel 301 // 302 // ========================================================================================== 303 304 QString FreeboxChannel::GetDefaultChannel() 305 { 306 MSqlQuery query(MSqlQuery::InitCon()); 307 query.prepare("SELECT channum " 308 "FROM channel,cardinput " 309 "WHERE " 310 "channel.sourceid = cardinput.sourceid AND " 311 "cardinput.cardid = :CARDID " 312 "ORDER BY channum limit 1"); 313 314 query.bindValue(":CARDID", m_cardid); 315 316 if (query.exec() && query.isActive() && query.size() > 0) 317 { 318 query.next(); 319 return query.value(0).toString(); 320 } 321 return ""; 322 } 323 324 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/freeboxmediasink.cpp
1 #include "freeboxmediasink.h" 2 3 #include "freeboxrecorder.h" 4 5 6 7 FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment& pEnv, FreeboxRecorder &pRecorder) : 8 MediaSink(pEnv), 9 env(pEnv), 10 recorder(pRecorder) 11 { 12 // Setup the data buffer 13 fBufferSize = 20000; 14 fBuffer = new unsigned char[fBufferSize]; 15 } 16 17 FreeboxMediaSink::~FreeboxMediaSink() 18 { 19 // free the data buffer 20 delete[] fBuffer; 21 } 22 23 FreeboxMediaSink* FreeboxMediaSink::createNew(UsageEnvironment& env, FreeboxRecorder &pRecorder) 24 { 25 FreeboxMediaSink* newSink = new FreeboxMediaSink(env, pRecorder); 26 return newSink; 27 } 28 29 Boolean FreeboxMediaSink::continuePlaying() 30 { 31 if (fSource == NULL) return False; 32 33 fSource->getNextFrame(fBuffer, fBufferSize, afterGettingFrame, this, onSourceClosure, this); 34 35 return True; 36 } 37 38 void FreeboxMediaSink::afterGettingFrame(void* clientData, 39 unsigned frameSize, 40 unsigned /*numTruncatedBytes*/, 41 struct timeval presentationTime, 42 unsigned /*durationInMicroseconds*/) 43 { 44 FreeboxMediaSink* sink = (FreeboxMediaSink*)clientData; 45 sink->afterGettingFrame1(frameSize, presentationTime); 46 } 47 48 void FreeboxMediaSink::afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) 49 { 50 addData(fBuffer, frameSize, presentationTime); 51 continuePlaying(); 52 } 53 54 void FreeboxMediaSink::addData(unsigned char* data, unsigned dataSize, struct timeval presentationTime) 55 { 56 recorder.addData(data, dataSize, presentationTime); 57 } -
libs/libmythtv/dbcheck.cpp
10 10 #include "mythdbcon.h" 11 11 12 12 /// This is the DB schema version expected by the running MythTV instance. 13 const QString currentDatabaseVersion = "113 7";13 const QString currentDatabaseVersion = "1138"; 14 14 15 15 static bool UpdateDBVersionNumber(const QString &newnumber); 16 16 static bool performActualUpdate(const QString updates[], QString version, … … 2206 2206 //"ALTER TABLE capturecard DROP COLUMN dvb_hw_decoder;" in 0.21 2207 2207 //"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22 2208 2208 2209 if (dbver == "1137") 2210 { 2211 const QString updates[] = { 2212 "INSERT INTO profilegroups SET name = 'Freebox Input', cardtype = 'Freebox', is_default = 1;", 2213 "ALTER TABLE capturecard ADD COLUMN freebox_mrl varchar(64) DEFAULT 'http://mafreebox.freebox.fr/freeboxtv/playlist.m3u';", 2214 "" 2215 }; 2216 2217 if (!performActualUpdate(updates, "1138", dbver)) 2218 return false; 2219 } 2220 2221 2209 2222 return true; 2210 2223 } 2211 2224 … … 2266 2279 " dbox2_port int(10) unsigned NOT NULL default '31338'," 2267 2280 " dbox2_httpport int(10) unsigned NOT NULL default '80'," 2268 2281 " dbox2_host varchar(32) default NULL," 2282 " freebox_mrl varchar(64) DEFAULT 'http://mafreebox.freebox.fr/freeboxtv/playlist.m3u'," 2269 2283 " signal_timeout int(11) NOT NULL default '1000'," 2270 2284 " channel_timeout int(11) NOT NULL default '3000'," 2271 2285 " PRIMARY KEY (cardid)" … … 2832 2846 "INSERT INTO profilegroups VALUES (8," 2833 2847 " 'USB Mpeg-4 Encoder (Plextor ConvertX, etc)','GO7007',1,NULL);", 2834 2848 "INSERT INTO profilegroups VALUES (9,'DBOX2 Input','DBOX2',1,NULL);", 2849 "INSERT INTO `profilegroups` VALUES (10,'Freebox Input','Freebox',1,NULL);", 2835 2850 "INSERT INTO recordingprofiles VALUES (1,'Default',NULL,NULL,1);", 2836 2851 "INSERT INTO recordingprofiles VALUES (2,'Live TV',NULL,NULL,1);", 2837 2852 "INSERT INTO recordingprofiles VALUES (3,'High Quality',NULL,NULL,1);", -
libs/libmythtv/freeboxrecorder.cpp
1 /** 2 * FreeboxRecorder 3 * Copyright (c) 2005 by Levent G?u (mythtv@feature-it.com) 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 13 #include "mpeg/tspacket.h" 14 #include "freeboxchannel.h" 15 #include "freeboxmediasink.h" 16 17 18 19 // ============================================================================ 20 // FreeboxData : Helper class use for static Callback handler 21 // ============================================================================ 22 class FreeboxData 23 { 24 public: 25 FreeboxData(FreeboxRecorder *pFreeboxRecorder, MediaSubsession *pMediaSubSession) 26 { 27 freeboxRecorder = pFreeboxRecorder; 28 mediaSubSession = pMediaSubSession; 29 } 30 31 FreeboxRecorder *freeboxRecorder; 32 MediaSubsession *mediaSubSession; 33 }; 34 35 36 37 FreeboxRecorder::FreeboxRecorder(TVRec *rec, FreeboxChannel *channel) : 38 DTVRecorder(rec), 39 env(NULL), 40 rtspClient(NULL), 41 session(NULL), 42 _abort_rtsp(0), 43 _abort_recording(false), 44 m_channel(channel) 45 { 46 connect(m_channel, SIGNAL(ChannelChanged()), 47 this, SLOT( ChannelChanged())); 48 } 49 50 51 52 FreeboxRecorder::~FreeboxRecorder() 53 { 54 } 55 56 57 58 bool FreeboxRecorder::Open() 59 { 60 return StartRtsp(); 61 } 62 63 64 65 void FreeboxRecorder::Close() 66 { 67 if (session == NULL) return; 68 69 // Ensure RTSP cleanup, remove old RTSP session 70 MediaSubsessionIterator iter(*session); 71 MediaSubsession* subsession; 72 while ((subsession = iter.next()) != NULL) 73 { 74 Medium::close(subsession->sink); 75 subsession->sink = NULL; 76 } 77 78 if (session == NULL) return; 79 80 rtspClient->teardownMediaSession(*session); 81 82 // Close all RTSP descriptor 83 Medium::close(session); 84 Medium::close(rtspClient); 85 } 86 87 88 89 void FreeboxRecorder::ChannelChanged() 90 { 91 // Channel change, we need to close current RTSP flow, and open a new one 92 ResetEventLoop(); 93 } 94 95 96 97 void FreeboxRecorder::SetOptionsFromProfile(RecordingProfile *profile, 98 const QString &videodev, 99 const QString &audiodev, 100 const QString &vbidev) 101 { 102 (void)videodev; 103 (void)audiodev; 104 (void)vbidev; 105 (void)profile; 106 } 107 108 109 110 void FreeboxRecorder::StartRecording() 111 { 112 while(!_abort_recording && Open()) 113 { 114 _abort_rtsp = 0; 115 _recording = true; 116 // Go into main RTSP loop, feeding data to mythtv 117 env->taskScheduler().doEventLoop(&_abort_rtsp); // does not return 118 119 // Event loop exists, the recording finish 120 FinishRecording(); 121 _recording = false; 122 Close(); 123 } 124 } 125 126 void FreeboxRecorder::StopRecording(void) 127 { 128 _abort_recording = true; 129 ResetEventLoop(); 130 } 131 132 void FreeboxRecorder::ResetEventLoop() 133 { 134 _abort_rtsp = ~0; 135 while( _recording ) usleep(10000); 136 } 137 138 // ====================================================================== 139 // StartRtsp : start a new RTSP session for the current channel 140 // ====================================================================== 141 bool FreeboxRecorder::StartRtsp() 142 { 143 // Retrieve the RTSP channel URL 144 QString url = m_channel->GetCurrentChannelUrl(); 145 146 // Begin by setting up our usage environment: 147 TaskScheduler* scheduler = BasicTaskScheduler::createNew(); 148 env = BasicUsageEnvironment::createNew(*scheduler); 149 150 151 // Create our client object: 152 rtspClient = RTSPClient::createNew(*env, 0, "myRTSP", 0); 153 if (rtspClient == NULL) 154 { 155 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create RTSP client: %1").arg(env->getResultMsg())); 156 return false; 157 } 158 159 // Setup URL for the current session 160 char* sdpDescription = rtspClient->describeURL(url); 161 rtspClient->describeStatus(); 162 163 if (sdpDescription == NULL) 164 { 165 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to get a SDP description from URL: %1 %2").arg(url).arg(env->getResultMsg())); 166 return false; 167 } 168 169 // Create a media session object from this SDP description: 170 session = MediaSession::createNew(*env, sdpDescription); 171 delete[] sdpDescription; 172 if (session == NULL) 173 { 174 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create a MediaSession object from the SDP description: %1").arg(env->getResultMsg())); 175 return false; 176 } 177 else if (!session->hasSubsessions()) 178 { 179 VERBOSE(VB_IMPORTANT, QString("Freebox # This session has no media subsessions")); 180 return false; 181 } 182 183 // Then, setup the "RTPSource"s for the session: 184 MediaSubsessionIterator iter(*session); 185 MediaSubsession *subsession; 186 Boolean madeProgress = False; 187 while ((subsession = iter.next()) != NULL) 188 { 189 if (!subsession->initiate(-1)) 190 { 191 VERBOSE(VB_IMPORTANT, QString("Freebox # Unable to create receiver for: %1 / %2 subsession: %3") 192 .arg(subsession->mediumName()) 193 .arg(subsession->codecName()) 194 .arg(env->getResultMsg())); 195 } 196 else 197 { 198 madeProgress = True; 199 200 if (subsession->rtpSource() != NULL) 201 { 202 unsigned const thresh = 1000000; // 1 second 203 subsession->rtpSource()->setPacketReorderingThresholdTime(thresh); 204 } 205 } 206 } 207 208 if (!madeProgress) return false; 209 210 // Perform additional 'setup' on each subsession, before playing them: 211 madeProgress = false; 212 iter.reset(); 213 while ((subsession = iter.next()) != NULL) 214 { 215 if (subsession->clientPortNum() == 0) continue; // port # was not set 216 217 if (rtspClient->setupMediaSubsession(*subsession, False, false)) 218 { 219 madeProgress = True; 220 } 221 else 222 { 223 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to setup: %1 %2 : %3").arg(subsession->mediumName()).arg(subsession->codecName()).arg(env->getResultMsg())); 224 } 225 } 226 227 if (!madeProgress) return false; 228 229 // Create and start "FileSink"s for each subsession: 230 // FileSink while receive Mpeg2 TS Data & will feed them to mythtv 231 madeProgress = False; 232 iter.reset(); 233 while ((subsession = iter.next()) != NULL) 234 { 235 if (subsession->readSource() == NULL) continue; // was not initiated 236 237 FreeboxMediaSink* freeboxMediaSink = FreeboxMediaSink::createNew(*env, *this); 238 239 subsession->sink = freeboxMediaSink; 240 if (subsession->sink == NULL) 241 { 242 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create sink: %1").arg(env->getResultMsg())); 243 } 244 245 subsession->sink->startPlaying(*(subsession->readSource()), 246 subsessionAfterPlayingCallback, 247 new FreeboxData(this, subsession)); 248 249 if (subsession->rtcpInstance() != NULL) 250 { 251 subsession->rtcpInstance()->setByeHandler(subsessionByeHandlerCallback, 252 new FreeboxData(this, subsession)); 253 } 254 255 madeProgress = True; 256 } 257 258 if (!madeProgress) return false; 259 260 // Setup player 261 if (!(rtspClient->playMediaSession(*session))) 262 { 263 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to start playing session: %1").arg(env->getResultMsg())); 264 return false; 265 } 266 267 return true; 268 } 269 270 // =================================================== 271 // findTSHeader : find a TS Header in flow 272 // =================================================== 273 static int FreeboxRecorder_findTSHeader(const unsigned char *data, unsigned dataSize) 274 { 275 unsigned int pos = 0; 276 while (pos < dataSize) 277 { 278 if (data[pos] == 0x47) 279 return pos; 280 pos++; 281 } 282 return -1; 283 } 284 285 // =================================================== 286 // addData : feed date from RTSP flow to mythtv 287 // =================================================== 288 void FreeboxRecorder::addData(unsigned char* data, unsigned dataSize, struct timeval) 289 { 290 unsigned int readIndex = 0; 291 292 // data may be compose from more than one packet, loop to consume all data 293 while (readIndex < dataSize) 294 { 295 // If recorder is pause, stop there 296 if (PauseAndWait()) 297 { 298 return; 299 } 300 301 // Find the next TS Header in data 302 int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize); 303 304 // if no TS, something bad happens 305 if (tsPos == -1) 306 { 307 VERBOSE(VB_IMPORTANT, QString("FREEBOX: No TS header.")); 308 break; 309 } 310 311 // if TS Header not at start of data, we receive out of sync data 312 if (tsPos > 0) 313 { 314 VERBOSE(VB_IMPORTANT, QString("FREEBOX: TS header at %1, not in sync.").arg(tsPos)); 315 } 316 317 // Check if the next packet in buffer is complete : packet size is 188 bytes long 318 if ((dataSize - tsPos) < 188) 319 { 320 VERBOSE(VB_IMPORTANT, QString("FREEBOX: TS header at %1 but packet not yet complete.").arg(tsPos)); 321 break; 322 } 323 324 // Cast current found TS Packet to TSPacket structure 325 const void *newData = data + tsPos + readIndex; 326 const TSPacket *tspacket = reinterpret_cast<const TSPacket*>(newData); 327 328 // Feed current packet to myth 329 _buffer_packets = !FindKeyframes(tspacket); 330 BufferedWrite(*tspacket); 331 332 // follow to next packet 333 readIndex += tsPos + TSPacket::SIZE; 334 } 335 } 336 337 void FreeboxRecorder::subsessionAfterPlayingCallback(void *clientData) 338 { 339 FreeboxData *myData = (FreeboxData*)clientData; 340 myData->freeboxRecorder->SubsessionAfterPlaying(myData->mediaSubSession); 341 } 342 343 void FreeboxRecorder::subsessionByeHandlerCallback(void *clientData) 344 { 345 FreeboxData *myData = (FreeboxData*)clientData; 346 myData->freeboxRecorder->SubsessionByeHandler(myData->mediaSubSession); 347 } 348 349 void FreeboxRecorder::SubsessionAfterPlaying(MediaSubsession* subsession) 350 { 351 Medium::close(subsession->sink); 352 subsession->sink = NULL; 353 354 MediaSession& session = subsession->parentSession(); 355 MediaSubsessionIterator iter(session); 356 while ((subsession = iter.next()) != NULL) 357 { 358 if (subsession->sink != NULL) return; 359 } 360 } 361 362 363 void FreeboxRecorder::SubsessionByeHandler(MediaSubsession* subsession) 364 { 365 SubsessionAfterPlaying(subsession); 366 } 367 368 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/cardutil.cpp
517 517 518 518 if (("FIREWIRE" == cardtype) || 519 519 ("DBOX2" == cardtype) || 520 ("FREEBOX" == cardtype) || 520 521 ("HDHOMERUN" == cardtype)) 521 522 { 522 523 ret += "MPEG2TS"; … … 709 710 .arg(query.value(1).toString()) 710 711 .arg(query.value(2).toString()); 711 712 } 713 else if (cardtype == "FREEBOX") 714 { 715 MSqlQuery query(MSqlQuery::InitCon()); 716 query.prepare( 717 "SELECT freebox_mrl " 718 "FROM capturecard " 719 "WHERE cardid = :CARDID"); 720 query.bindValue(":CARDID", cardid); 721 722 if (!query.exec() || !query.isActive() || !query.next()) 723 label = "[ DB ERROR ]"; 724 else 725 label = QString("[ FREEBOX : MRL %1 ]") 726 .arg(query.value(0).toString()); 727 } 712 728 else if (cardtype == "HDHOMERUN") 713 729 { 714 730 MSqlQuery query(MSqlQuery::InitCon()); … … 745 761 746 762 if (("FIREWIRE" == cardtype) || 747 763 ("DBOX2" == cardtype) || 764 ("FREEBOX" == cardtype) || 748 765 ("HDHOMERUN" == cardtype)) 749 766 { 750 767 inputs += "MPEG2TS"; -
libs/libmythtv/freeboxmediasink.h
1 #ifndef _FREEBOXMEDIASINK_H_ 2 #define _FREEBOXMEDIASINK_H_ 3 4 #include <MediaSink.hh> 5 6 class FreeboxRecorder; 7 8 9 10 // ============================================================================ 11 // FreeboxMediaSink : Helper class use to receive RTSP data from socket. 12 // ============================================================================ 13 class FreeboxMediaSink: public MediaSink 14 { 15 public: 16 static FreeboxMediaSink* createNew(UsageEnvironment& env, FreeboxRecorder &pRecorder); 17 18 // Callback function when rtsp data are ready 19 void addData(unsigned char* data, unsigned dataSize, struct timeval presentationTime); 20 21 protected: 22 FreeboxMediaSink(UsageEnvironment& env, FreeboxRecorder &pRecorder); 23 virtual ~FreeboxMediaSink(); 24 25 static void afterGettingFrame(void* clientData, 26 unsigned frameSize, 27 unsigned numTruncatedBytes, 28 struct timeval presentationTime, 29 unsigned durationInMicroseconds); 30 virtual void afterGettingFrame1(unsigned frameSize, struct timeval presentationTime); 31 32 private: 33 virtual Boolean continuePlaying(); 34 35 unsigned char* fBuffer; 36 unsigned fBufferSize; 37 UsageEnvironment &env; 38 FreeboxRecorder &recorder; 39 int bufferIndex; 40 }; 41 42 #endif//_FREEBOXMEDIASINK_H_ -
libs/libmythtv/videosource.cpp
927 927 } 928 928 }; 929 929 930 class FreeboxHost : public LineEditSetting, public CCSetting { 931 public: 932 FreeboxHost(const CaptureCard &parent): 933 CCSetting(parent, "freebox_mrl") 934 { 935 setValue("http://mafreebox.freebox.fr/freeboxtv/playlist.m3u"); 936 setLabel(QObject::tr("Freebox MRL")); 937 setHelpText(QObject::tr("The freebox Media Resource Locator (MRL).")); 938 } 939 }; 940 930 941 class HDHomeRunTunerIndex: public ComboBoxSetting, public CCSetting 931 942 { 932 943 public: … … 939 950 } 940 951 }; 941 952 953 class FreeboxConfigurationGroup: public VerticalConfigurationGroup { 954 public: 955 FreeboxConfigurationGroup(CaptureCard& a_parent): 956 ConfigurationGroup(false, true, false, false), 957 VerticalConfigurationGroup(false, true, false, false), 958 parent(a_parent) 959 { 960 setUseLabel(false); 961 addChild(new FreeboxHost(parent)); 962 }; 963 private: 964 CaptureCard& parent; 965 }; 966 942 967 void HDHRCardInput::fillSelections(const QString&) 943 968 { 944 969 clearSelections(); … … 1073 1098 addTarget("DBOX2", new DBOX2ConfigurationGroup(parent)); 1074 1099 #endif // USING_DBOX2 1075 1100 1101 #ifdef USING_FREEBOX 1102 addTarget("FREEBOX", new FreeboxConfigurationGroup(parent)); 1103 #endif // USING_FREEBOX 1104 1076 1105 #ifdef USING_HDHOMERUN 1077 1106 addTarget("HDHOMERUN", new HDHomeRunConfigurationGroup(parent)); 1078 1107 #endif // USING_HDHOMERUN … … 1190 1219 QObject::tr("DBox2 TCP/IP cable box"), "DBOX2"); 1191 1220 #endif // USING_DBOX2 1192 1221 1222 #ifdef USING_FREEBOX 1223 setting->addSelection( 1224 QObject::tr("Freebox"), "FREEBOX"); 1225 #endif // USING_FREEBOX 1226 1193 1227 #ifdef USING_HDHOMERUN 1194 1228 setting->addSelection( 1195 1229 QObject::tr("HDHomeRun DTV tuner box"), "HDHOMERUN"); -
libs/libmythtv/freeboxrecorder.h
1 /** 2 * FreeboxRecorder 3 * Copyright (c) 2005 by Levent Gündogdu 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 12 class FreeboxChannel; 13 class MediaSession; 14 class MediaSubsession; 15 class RTSPClient; 16 class UsageEnvironment; 17 18 19 20 /** 21 * 22 * Constructs a FreeboxRecorder 23 * 24 */ 25 class FreeboxRecorder : 26 public QObject, //FIXME see changeset #9743 for details 27 public DTVRecorder 28 { 29 Q_OBJECT 30 public: 31 FreeboxRecorder(TVRec *rec, FreeboxChannel *channel); 32 ~FreeboxRecorder(); 33 34 void StartRecording(void); //< RecorderBase 35 void StopRecording(void); //< DTVRecorder 36 37 // RecorderBase 38 void SetOptionsFromProfile(RecordingProfile *profile, 39 const QString &videodev, 40 const QString &audiodev, 41 const QString &vbidev); 42 43 public slots: 44 void ChannelChanged(); 45 46 private: 47 friend class FreeboxMediaSink; 48 49 bool Open(); //< RecorderBase 50 void Close(); 51 52 static void subsessionAfterPlayingCallback(void *clientData); 53 static void subsessionByeHandlerCallback(void *clientData); 54 void SubsessionAfterPlaying(MediaSubsession *subsession); 55 void SubsessionByeHandler(MediaSubsession *subsession); 56 57 // Callback function to add MPEG2 TS data 58 void addData(unsigned char* data, unsigned dataSize, struct timeval presentationTime); 59 60 bool StartRtsp(); 61 void ResetEventLoop(); 62 63 private: 64 UsageEnvironment* env; 65 RTSPClient* rtspClient; 66 MediaSession* session; 67 68 // var to check if we need to abort current rtsp session 69 char _abort_rtsp; 70 71 // request abort for StartRecording method 72 bool _abort_recording; 73 74 // Current channel 75 FreeboxChannel *m_channel; 76 }; 77 78 #endif//FREEBOXRECORDER_H_ 79 80 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/tv_rec.cpp
72 72 #include "dbox2channel.h" 73 73 #endif 74 74 75 #ifdef USING_FREEBOX 76 #include "freeboxrecorder.h" 77 #include "freeboxchannel.h" 78 #endif // USING_FREEBOX 79 75 80 #ifdef USING_HDHOMERUN 76 81 #include "hdhrrecorder.h" 77 82 #include "hdhrchannel.h" … … 187 192 init_run = true; 188 193 #endif 189 194 } 195 else if (genOpt.cardtype == "FREEBOX") 196 { 197 #ifdef USING_FREEBOX 198 VERBOSE(VB_IMPORTANT,QString("trye to alloc chan")); 199 channel = new FreeboxChannel(this, &freeboxOpt, cardid); 200 channel->Open(); 201 InitChannel(genOpt.defaultinput, startchannel); 202 init_run = true; 203 VERBOSE(VB_IMPORTANT,QString("end trye to alloc chan")); 204 #endif 205 } 190 206 else if (genOpt.cardtype == "HDHOMERUN") 191 207 { 192 208 #ifdef USING_HDHOMERUN … … 243 259 { 244 260 QMutexLocker lock(&stateChangeLock); 245 261 246 if (!GetDevices(cardid, genOpt, dvbOpt, fwOpt, dboxOpt ))262 if (!GetDevices(cardid, genOpt, dvbOpt, fwOpt, dboxOpt, freeboxOpt)) 247 263 return false; 248 264 249 265 QString startchannel = GetStartChannel(cardid, genOpt.defaultinput); … … 299 315 scanner = NULL; 300 316 } 301 317 318 #ifdef USING_FREEBOX 319 if (GetFreeboxChannel()) 320 GetFreeboxChannel()->deleteLater(); 321 else 322 #endif // USING_FREEBOX 302 323 if (channel) 303 324 { 304 325 delete channel; … … 855 876 recorder->SetOption("httpport", dboxOpt.httpport); 856 877 #endif // USING_DBOX2 857 878 } 879 else if (genOpt.cardtype == "FREEBOX") 880 { 881 #ifdef USING_FREEBOX 882 recorder = new FreeboxRecorder(this, GetFreeboxChannel()); 883 recorder->SetOption("mrl", freeboxOpt.mrl); 884 #endif // USING_FREEBOX 885 } 858 886 else if (genOpt.cardtype == "HDHOMERUN") 859 887 { 860 888 #ifdef USING_HDHOMERUN … … 1098 1126 #endif // USING_DBOX2 1099 1127 } 1100 1128 1129 FreeboxChannel *TVRec::GetFreeboxChannel(void) 1130 { 1131 #ifdef USING_FREEBOX 1132 return dynamic_cast<FreeboxChannel*>(channel); 1133 #else 1134 return NULL; 1135 #endif // USING_FREEBOX 1136 } 1137 1101 1138 HDHRChannel *TVRec::GetHDHRChannel(void) 1102 1139 { 1103 1140 #ifdef USING_HDHOMERUN … … 1428 1465 return ok; 1429 1466 } 1430 1467 1431 bool TVRec::GetDevices(int cardid, 1432 GeneralDBOptions &gen_opts, 1433 DVBDBOptions &dvb_opts, 1434 FireWireDBOptions &firewire_opts, 1435 DBox2DBOptions &dbox2_opts) 1468 bool TVRec::GetDevices(int cardid, 1469 GeneralDBOptions &gen_opts, 1470 DVBDBOptions &dvb_opts, 1471 FireWireDBOptions &firewire_opts, 1472 DBox2DBOptions &dbox2_opts, 1473 FreeboxDBOptions &freebox_opts) 1436 1474 { 1437 1475 int testnum = 0; 1438 1476 QString test; … … 1449 1487 " firewire_port, firewire_node, firewire_speed, " 1450 1488 " firewire_model, firewire_connection, " 1451 1489 "" 1452 " dbox2_port, dbox2_host, dbox2_httpport " 1490 " dbox2_port, dbox2_host, dbox2_httpport, " 1491 " freebox_mrl " 1453 1492 "" 1454 1493 "FROM capturecard " 1455 1494 "WHERE cardid = :CARDID"); … … 1527 1566 1528 1567 dbox2_opts.httpport = query.value(dbox2off + 2).toUInt(); 1529 1568 1569 // Freebox options 1570 uint freeboxoff = dbox2off + 3; 1571 test = query.value(freeboxoff).toString(); 1572 if (test != QString::null) 1573 freebox_opts.mrl = QString::fromUtf8(test); 1574 1530 1575 return true; 1531 1576 } 1532 1577 … … 3586 3631 delete channel; 3587 3632 channel = NULL; 3588 3633 3589 GetDevices(newCardID, genOpt, dvbOpt, fwOpt, dboxOpt );3634 GetDevices(newCardID, genOpt, dvbOpt, fwOpt, dboxOpt, freeboxOpt); 3590 3635 genOpt.defaultinput = inputname; 3591 3636 CreateChannel(channum); 3592 3637 if (!(request.flags & kFlagNoRec)) -
libs/libmythtv/tv_rec.h
39 39 class DVBChannel; 40 40 class Channel; 41 41 42 class FreeboxChannel; 43 44 42 45 class MPEGStreamData; 43 46 class ProgramMapTable; 44 47 … … 130 133 QString host; 131 134 }; 132 135 136 137 class FreeboxDBOptions 138 { 139 public: 140 FreeboxDBOptions() : mrl("http://mafreebox.freebox.fr/freeboxtv/playlist.m3u") {} 141 142 QString mrl; 143 }; 144 145 133 146 class TuningRequest 134 147 { 135 148 public: … … 268 281 void SetPseudoLiveTVRecording(ProgramInfo*); 269 282 void TeardownAll(void); 270 283 271 static bool GetDevices(int cardid,284 static bool GetDevices(int cardid, 272 285 GeneralDBOptions &general_opts, 273 286 DVBDBOptions &dvb_opts, 274 287 FireWireDBOptions &firewire_opts, 275 DBox2DBOptions &dbox2_opts); 288 DBox2DBOptions &dbox2_opts, 289 FreeboxDBOptions &free_opts); 276 290 277 291 278 292 static QString GetStartChannel(int cardid, const QString &defaultinput); … … 286 300 bool CreateChannel(const QString &startChanNum); 287 301 void InitChannel(const QString &inputname, const QString &startchannel); 288 302 void CloseChannel(void); 289 DBox2Channel *GetDBox2Channel(void);290 HDHRChannel *GetHDHRChannel(void);291 DVBChannel *GetDVBChannel(void);292 Channel *GetV4LChannel(void);293 303 304 DBox2Channel *GetDBox2Channel(void); 305 HDHRChannel *GetHDHRChannel(void); 306 DVBChannel *GetDVBChannel(void); 307 FreeboxChannel *GetFreeboxChannel(void); 308 Channel *GetV4LChannel(void); 309 294 310 void SetupSignalMonitor(bool enable_table_monitoring, bool notify); 295 311 bool SetupDTVSignalMonitor(void); 296 312 void TeardownSignalMonitor(void); … … 366 382 DVBDBOptions dvbOpt; 367 383 FireWireDBOptions fwOpt; 368 384 DBox2DBOptions dboxOpt; 385 FreeboxDBOptions freeboxOpt; 369 386 370 387 // State variables 371 388 QMutex stateChangeLock; -
settings.pro
20 20 21 21 INCLUDEPATH += $${PREFIX}/include 22 22 INCLUDEPATH += $$CONFIG_INCLUDEPATH 23 INCLUDEPATH += /usr/include/liveMedia 24 INCLUDEPATH += /usr/include/UsageEnvironment 25 INCLUDEPATH += /usr/include/BasicUsageEnvironment 26 INCLUDEPATH += /usr/include/groupsock 23 27 24 28 # figure out compile flags based on qmake info 25 29 … … 79 83 EXTRA_LIBS += $$CONFIG_AUDIO_JACK_LIBS 80 84 EXTRA_LIBS += $$CONFIG_FIREWIRE_LIBS 81 85 EXTRA_LIBS += $$CONFIG_DIRECTFB_LIBS 86 EXTRA_LIBS += $$CONFIG_LIVE_LIBS 82 87 83 88 EXTRA_LIBS += $$LOCAL_LIBDIR_OGL 84 89 EXTRA_LIBS += $$LOCAL_LIBDIR_X11