Ticket #1704: patch.freebox.v1.15.9838.diff
File patch.freebox.v1.15.9838.diff, 44.8 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 354 using_freebox:HEADERS += freeboxrecorder.h freeboxchannel.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/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 16 17 18 // ================================================================================================== 19 // FreeboxData : Helper class use for static Callback handler 20 // ================================================================================================== 21 class FreeboxData 22 { 23 public: 24 FreeboxData(FreeboxRecorder *pFreeboxRecorder, MediaSubsession *pMediaSubSession) 25 { 26 freeboxRecorder = pFreeboxRecorder; 27 mediaSubSession = pMediaSubSession; 28 } 29 30 FreeboxRecorder *freeboxRecorder; 31 MediaSubsession *mediaSubSession; 32 }; 33 34 35 36 // ================================================================================================== 37 // FreeboxSink : Helper class use to receive RTSP data from socket. 38 // ================================================================================================== 39 class FreeboxSink: public MediaSink 40 { 41 public: 42 static FreeboxSink* createNew(UsageEnvironment& env, FreeboxRecorder *pRecorder); 43 44 // Callback function when rtsp data are ready 45 void addData(unsigned char* data, unsigned dataSize, struct timeval presentationTime); 46 47 protected: 48 FreeboxSink(UsageEnvironment& env, FreeboxRecorder *pRecorder); 49 virtual ~FreeboxSink(); 50 51 static void afterGettingFrame(void* clientData, 52 unsigned frameSize, 53 unsigned numTruncatedBytes, 54 struct timeval presentationTime, 55 unsigned durationInMicroseconds); 56 virtual void afterGettingFrame1(unsigned frameSize, struct timeval presentationTime); 57 58 private: 59 virtual Boolean continuePlaying(); 60 61 unsigned char* fBuffer; 62 unsigned fBufferSize; 63 UsageEnvironment *env; 64 FreeboxRecorder *recorder; 65 int bufferIndex; 66 }; 67 68 69 70 FreeboxRecorder::FreeboxRecorder(TVRec *rec, FreeboxChannel *channel) : 71 DTVRecorder(rec), 72 env(NULL), 73 rtspClient(NULL), 74 session(NULL), 75 _request_abort(false), 76 m_channel(channel), 77 waitShutdown(NULL), 78 start_thread(0) 79 { 80 // the var will be use to abort current rtsp session 81 _abort_rtsp = new char(); 82 83 connect(m_channel, SIGNAL(ChannelChanged()), 84 this, SLOT( ChannelChanged())); 85 } 86 87 88 89 FreeboxRecorder::~FreeboxRecorder() 90 { 91 } 92 93 94 95 bool FreeboxRecorder::Open() 96 { 97 // Start a new RTSP flow with current channel 98 pthread_create(&start_thread, NULL, FreeboxRecorder::StartRtspS, this); 99 return true; 100 } 101 102 103 void FreeboxRecorder::Close() 104 { 105 // ask for RTSP shutdown setting abort_rstp=1, and wait effective shutdown on mutex 106 waitShutdown = new QWaitCondition(); 107 *_abort_rtsp = 1; 108 _request_recording = false; 109 waitShutdown->wait(); 110 111 if (session == NULL) return; 112 113 // Ensure RTSP cleanup, remove old RTSP session 114 MediaSubsessionIterator iter(*session); 115 MediaSubsession* subsession; 116 while ((subsession = iter.next()) != NULL) 117 { 118 Medium::close(subsession->sink); 119 subsession->sink = NULL; 120 } 121 122 if (session == NULL) return; 123 124 rtspClient->teardownMediaSession(*session); 125 126 // Close all RTSP descriptor 127 Medium::close(session); 128 Medium::close(rtspClient); 129 } 130 131 132 133 void FreeboxRecorder::ChannelChanged() 134 { 135 // Channel change, we need to close current RTSP flow, and open a new one 136 Close(); 137 Open(); 138 } 139 140 141 142 void FreeboxRecorder::SetOptionsFromProfile(RecordingProfile *profile, 143 const QString &videodev, 144 const QString &audiodev, 145 const QString &vbidev) 146 { 147 (void)videodev; 148 (void)audiodev; 149 (void)vbidev; 150 (void)profile; 151 } 152 153 154 155 void FreeboxRecorder::StartRecording() 156 { 157 // Open RTSP flow for current channel 158 Open(); 159 160 _request_recording = true; 161 _recording = true; 162 _request_abort = false; 163 164 // wait until recorder abot 165 while(_request_recording) 166 { 167 if (_request_abort) 168 break; 169 170 usleep(1000); 171 } 172 } 173 174 void FreeboxRecorder::StopRecording(void) 175 { 176 // Close the current RTSP flow 177 Close(); 178 } 179 180 void *FreeboxRecorder::StartRtspS(void *param) 181 { 182 FreeboxRecorder *recorder = (FreeboxRecorder*)param; 183 recorder->StartRtsp(); 184 return NULL; 185 } 186 187 // ====================================================================== 188 // StartRtsp : start a new RTSP session for the current channel 189 // ====================================================================== 190 void FreeboxRecorder::StartRtsp() 191 { 192 // Retrieve the RTSP channel URL 193 QString url = m_channel->GetCurrentChannelUrl(); 194 195 // Begin by setting up our usage environment: 196 TaskScheduler* scheduler = BasicTaskScheduler::createNew(); 197 env = BasicUsageEnvironment::createNew(*scheduler); 198 199 200 // Create our client object: 201 rtspClient = RTSPClient::createNew(*env, 0, "myRTSP", 0); 202 if (rtspClient == NULL) 203 { 204 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create RTSP client: %1").arg(env->getResultMsg())); 205 shutdown(); 206 } 207 208 // Setup URL for the current session 209 char* sdpDescription = rtspClient->describeURL(url); 210 rtspClient->describeStatus(); 211 212 if (sdpDescription == NULL) 213 { 214 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to get a SDP description from URL: %1 %2").arg(url).arg(env->getResultMsg())); 215 shutdown(); 216 } 217 218 // Create a media session object from this SDP description: 219 session = MediaSession::createNew(*env, sdpDescription); 220 delete[] sdpDescription; 221 if (session == NULL) 222 { 223 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create a MediaSession object from the SDP description: %1").arg(env->getResultMsg())); 224 shutdown(); 225 } 226 else if (!session->hasSubsessions()) 227 { 228 VERBOSE(VB_IMPORTANT, QString("Freebox # This session has no media subsessions")); 229 shutdown(); 230 } 231 232 // Then, setup the "RTPSource"s for the session: 233 MediaSubsessionIterator iter(*session); 234 MediaSubsession *subsession; 235 Boolean madeProgress = False; 236 while ((subsession = iter.next()) != NULL) 237 { 238 if (!subsession->initiate(-1)) 239 { 240 VERBOSE(VB_IMPORTANT, QString("Freebox # Unable to create receiver for: %1 / %2 subsession: %3") 241 .arg(subsession->mediumName()) 242 .arg(subsession->codecName()) 243 .arg(env->getResultMsg())); 244 } 245 else 246 { 247 madeProgress = True; 248 249 if (subsession->rtpSource() != NULL) 250 { 251 unsigned const thresh = 1000000; // 1 second 252 subsession->rtpSource()->setPacketReorderingThresholdTime(thresh); 253 } 254 } 255 } 256 257 if (!madeProgress) shutdown(); 258 259 // Perform additional 'setup' on each subsession, before playing them: 260 madeProgress = false; 261 iter.reset(); 262 while ((subsession = iter.next()) != NULL) 263 { 264 if (subsession->clientPortNum() == 0) continue; // port # was not set 265 266 if (rtspClient->setupMediaSubsession(*subsession, False, false)) 267 { 268 madeProgress = True; 269 } 270 else 271 { 272 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to setup: %1 %2 : %3").arg(subsession->mediumName()).arg(subsession->codecName()).arg(env->getResultMsg())); 273 } 274 } 275 276 if (!madeProgress) shutdown(); 277 278 // Create and start "FileSink"s for each subsession: 279 // FileSink while receive Mpeg2 TS Data & will feed them to mythtv 280 madeProgress = False; 281 iter.reset(); 282 while ((subsession = iter.next()) != NULL) 283 { 284 if (subsession->readSource() == NULL) continue; // was not initiated 285 286 FreeboxSink* FreeboxSink = FreeboxSink::createNew(*env, this); 287 288 subsession->sink = FreeboxSink; 289 if (subsession->sink == NULL) 290 { 291 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to create sink: %1").arg(env->getResultMsg())); 292 } 293 294 subsession->sink->startPlaying(*(subsession->readSource()), 295 subsessionAfterPlayingCallback, 296 new FreeboxData(this, subsession)); 297 298 if (subsession->rtcpInstance() != NULL) 299 { 300 subsession->rtcpInstance()->setByeHandler(subsessionByeHandlerCallback, 301 new FreeboxData(this, subsession)); 302 } 303 304 madeProgress = True; 305 } 306 307 if (!madeProgress) shutdown(); 308 309 // Setup player 310 if (!(rtspClient->playMediaSession(*session))) 311 { 312 VERBOSE(VB_IMPORTANT, QString("Freebox # Failed to start playing session: %1").arg(env->getResultMsg())); 313 shutdown(); 314 } 315 316 request_pause = false; 317 paused = false; 318 _request_recording = true; 319 _recording = true; 320 *_abort_rtsp = 0; 321 322 // Go into main RTSP loop, feeding data to mythtv 323 env->taskScheduler().doEventLoop(_abort_rtsp); // does not return 324 325 // Event loop exists, the recording finish 326 FinishRecording(); 327 _recording = false; 328 329 // wakeUp everibody 330 waitShutdown->wakeAll(); 331 } 332 333 // =================================================== 334 // findTSHeader : find a TS Header in flow 335 // =================================================== 336 static int FreeboxRecorder_findTSHeader(const unsigned char *data, unsigned dataSize) 337 { 338 unsigned int pos = 0; 339 while (pos < dataSize) 340 { 341 if (data[pos] == 0x47) 342 return pos; 343 pos++; 344 } 345 return -1; 346 } 347 348 // =================================================== 349 // addData : feed date from RTSP flow to mythtv 350 // =================================================== 351 void FreeboxRecorder::addData(unsigned char* data, unsigned dataSize, struct timeval) 352 { 353 unsigned int readIndex = 0; 354 355 // data may be compose from more than one packet, loop to consume all data 356 while (readIndex < dataSize) 357 { 358 // If recorder is pause, stop there 359 if (PauseAndWait()) 360 { 361 return; 362 } 363 364 // Find the next TS Header in data 365 int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize); 366 367 // if no TS, something bad happens 368 if (tsPos == -1) 369 { 370 VERBOSE(VB_IMPORTANT, QString("FREEBOX: No TS header.")); 371 break; 372 } 373 374 // if TS Header not at start of data, we receive out of sync data 375 if (tsPos > 0) 376 { 377 VERBOSE(VB_IMPORTANT, QString("FREEBOX: TS header at %1, not in sync.").arg(tsPos)); 378 } 379 380 // Check if the next packet in buffer is complete : packet size is 188 bytes long 381 if ((dataSize - tsPos) < 188) 382 { 383 VERBOSE(VB_IMPORTANT, QString("FREEBOX: TS header at %1 but packet not yet complete.").arg(tsPos)); 384 break; 385 } 386 387 // Cast current found TS Packet to TSPacket structure 388 const void *newData = data + tsPos + readIndex; 389 const TSPacket *tspacket = reinterpret_cast<const TSPacket*>(newData); 390 391 // Feed current packet to myth 392 _buffer_packets = !FindKeyframes(tspacket); 393 BufferedWrite(*tspacket); 394 395 // follow to next packet 396 readIndex += tsPos + TSPacket::SIZE; 397 } 398 } 399 400 401 void FreeboxRecorder::shutdown(int) 402 { 403 } 404 405 406 void FreeboxRecorder::subsessionAfterPlayingCallback(void *clientData) 407 { 408 FreeboxData *myData = (FreeboxData*)clientData; 409 myData->freeboxRecorder->SubsessionAfterPlaying(myData->mediaSubSession); 410 } 411 412 void FreeboxRecorder::subsessionByeHandlerCallback(void *clientData) 413 { 414 FreeboxData *myData = (FreeboxData*)clientData; 415 myData->freeboxRecorder->SubsessionByeHandler(myData->mediaSubSession); 416 } 417 418 void FreeboxRecorder::SubsessionAfterPlaying(MediaSubsession* subsession) 419 { 420 Medium::close(subsession->sink); 421 subsession->sink = NULL; 422 423 MediaSession& session = subsession->parentSession(); 424 MediaSubsessionIterator iter(session); 425 while ((subsession = iter.next()) != NULL) 426 { 427 if (subsession->sink != NULL) return; 428 } 429 430 shutdown(0); 431 } 432 433 434 void FreeboxRecorder::SubsessionByeHandler(MediaSubsession* subsession) 435 { 436 SubsessionAfterPlaying(subsession); 437 } 438 439 440 // ================================================================================================== 441 // FreeboxSink : Helper class use to receive RTSP data from socket. 442 // ================================================================================================== 443 444 FreeboxSink::FreeboxSink(UsageEnvironment& pEnv, FreeboxRecorder *pRecorder) : MediaSink(pEnv) 445 { 446 recorder = pRecorder; 447 env = &pEnv; 448 449 // Setup the data buffer 450 fBufferSize = 20000; 451 fBuffer = new unsigned char[fBufferSize]; 452 } 453 454 FreeboxSink::~FreeboxSink() 455 { 456 // free the data buffer 457 delete[] fBuffer; 458 } 459 460 FreeboxSink* FreeboxSink::createNew(UsageEnvironment& env, FreeboxRecorder *pRecorder) 461 { 462 FreeboxSink* newSink = new FreeboxSink(env, pRecorder); 463 return newSink; 464 } 465 466 Boolean FreeboxSink::continuePlaying() 467 { 468 if (fSource == NULL) return False; 469 470 fSource->getNextFrame(fBuffer, fBufferSize, afterGettingFrame, this, onSourceClosure, this); 471 472 return True; 473 } 474 475 void FreeboxSink::afterGettingFrame(void* clientData, 476 unsigned frameSize, 477 unsigned /*numTruncatedBytes*/, 478 struct timeval presentationTime, 479 unsigned /*durationInMicroseconds*/) 480 { 481 FreeboxSink* sink = (FreeboxSink*)clientData; 482 sink->afterGettingFrame1(frameSize, presentationTime); 483 } 484 485 void FreeboxSink::afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) 486 { 487 addData(fBuffer, frameSize, presentationTime); 488 continuePlaying(); 489 } 490 491 void FreeboxSink::addData(unsigned char* data, unsigned dataSize, struct timeval presentationTime) 492 { 493 recorder->addData(data, dataSize, presentationTime); 494 } 495 496 /* 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/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 FreeboxSink; 48 49 bool Open(void); 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 // Call back function to start RTSP Flow 61 static void *StartRtspS(void *param); 62 void StartRtsp(); 63 64 void shutdown(int exitCode = 1); 65 66 private: 67 UsageEnvironment* env; 68 RTSPClient* rtspClient; 69 MediaSession* session; 70 71 // var to check if we need to abort current rtsp session 72 char* _abort_rtsp; 73 74 // request abort for StartRecording Thread 75 bool _request_abort; 76 77 // Current channel 78 FreeboxChannel *m_channel; 79 80 // Mutex : use to make sure that current RTSP thread as stop 81 QWaitCondition *waitShutdown; 82 83 // The current RTSP thread 84 pthread_t start_thread; 85 }; 86 87 #endif//FREEBOXRECORDER_H_ 88 89 /* 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