00001
00007
00008 #include <iostream>
00009 using namespace std;
00010
00011
00012 #include <qdeepcopy.h>
00013 #include <qhttp.h>
00014
00015
00016 #include "mythcontext.h"
00017 #include "dbox2channel.h"
00018 #include "dbox2recorder.h"
00019 #include "dbox2epg.h"
00020
00021
00022
00023 #define LOC QString("DBox2Ch(%1): ").arg(m_cardid)
00024 #define LOC_WARN QString("DBox2Ch(%1) Warning: ").arg(m_cardid)
00025 #define LOC_ERR QString("DBox2Ch(%1) Error: ").arg(m_cardid)
00026
00027 void DBox2CRelay::SetChannel(DBox2Channel *ch)
00028 {
00029 QMutexLocker locker(&m_lock);
00030 m_ch = ch;
00031 }
00032
00033 void DBox2CRelay::HttpChannelChangeDone(bool error)
00034 {
00035 QMutexLocker locker(&m_lock);
00036 if (m_ch)
00037 m_ch->HttpChannelChangeDone(error);
00038 }
00039
00040 void DBox2CRelay::HttpRequestDone(bool error)
00041 {
00042 QMutexLocker locker(&m_lock);
00043 if (m_ch)
00044 m_ch->HttpRequestDone(error);
00045 }
00046
00047 DBox2Channel::DBox2Channel(TVRec *parent, DBox2DBOptions *dbox2_options,
00048 int cardid)
00049 : ChannelBase(parent),
00050 m_dbox2options(dbox2_options), m_cardid(cardid),
00051 m_channelListReady(false), m_lastChannel("1"),
00052 m_requestChannel(""), m_epg(new DBox2EPG()),
00053 m_recorderAlive(false), m_recorder(NULL),
00054 http(new QHttp()), httpChanger(new QHttp()),
00055 m_relay(new DBox2CRelay(this)),
00056 m_dbox2channelcount(0)
00057 {
00058 QObject::connect(http, SIGNAL( done(bool)),
00059 m_relay, SLOT( HttpRequestDone(bool)));
00060 QObject::connect(httpChanger, SIGNAL( done(bool)),
00061 m_relay, SLOT( HttpChannelChangeDone(bool)));
00062
00063
00064 LoadChannels();
00065 }
00066
00067 void DBox2Channel::TeardownAll(void)
00068 {
00069
00070 if (m_epg)
00071 {
00072 m_epg->Shutdown();
00073 m_epg->disconnect();
00074 m_epg->deleteLater();
00075 m_epg = NULL;
00076 }
00077
00078
00079 if (httpChanger)
00080 {
00081 httpChanger->abort();
00082 httpChanger->closeConnection();
00083 httpChanger->disconnect();
00084 httpChanger->deleteLater();
00085 httpChanger = NULL;
00086 }
00087
00088
00089 if (http)
00090 {
00091 http->abort();
00092 http->closeConnection();
00093 http->disconnect();
00094 http->deleteLater();
00095 http = NULL;
00096 }
00097
00098 if (m_relay)
00099 {
00100 m_relay->SetChannel(NULL);
00101 m_relay->deleteLater();
00102 m_relay = NULL;
00103 }
00104 }
00105
00106 void DBox2Channel::SetRecorder(DBox2Recorder *rec)
00107 {
00108 QMutexLocker locker(&m_lock);
00109 m_recorder = rec;
00110 }
00111
00112 void DBox2Channel::SwitchToLastChannel(void)
00113 {
00114 VERBOSE(VB_CHANNEL, LOC + QString("Switching to last channel '%1'.")
00115 .arg(m_lastChannel));
00116
00117 SetChannelByString(m_lastChannel);
00118 }
00119
00120 bool DBox2Channel::SetChannelByString(const QString &newChan)
00121 {
00122
00123 if (!m_channelListReady)
00124 {
00125 VERBOSE(VB_CHANNEL, LOC + "Channel list not received yet. \n\t\t\t" +
00126 QString("Will switch to channel %1 later...").arg(newChan));
00127
00128 m_requestChannel = QDeepCopy<QString>(newChan);
00129 return true;
00130 }
00131
00132 QString chan = QDeepCopy<QString>(newChan);
00133 if (chan.isEmpty())
00134 {
00135 VERBOSE(VB_CHANNEL, LOC + "Empty channel name has been provided. "
00136 "\n\t\t\tGetting default name.");
00137
00138 chan = GetDefaultChannel();
00139 }
00140
00141 VERBOSE(VB_CHANNEL, LOC + QString("Changing to '%1'.").arg(chan));
00142
00143
00144
00145 InputMap::const_iterator it = inputs.find(currentInputID);
00146 if (it == inputs.end())
00147 return false;
00148
00149 uint mplexid_restriction;
00150 if (!IsInputAvailable(currentInputID, mplexid_restriction))
00151 return false;
00152
00153 if (m_lastChannel != curchannelname)
00154 m_lastChannel = curchannelname;
00155 curchannelname = chan;
00156
00157
00158
00159 QString channelName = GetChannelNameFromNumber(chan);
00160 if (channelName.isEmpty())
00161 {
00162 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Changing to '%1' failed. ")
00163 .arg(chan) + "Channel not found!");
00164
00165 QString defaultChannel = GetDefaultChannel();
00166 if (defaultChannel != chan)
00167 {
00168 VERBOSE(VB_CHANNEL, LOC + QString("Trying default channel '%1'")
00169 .arg(defaultChannel));
00170
00171 return SetChannelByString(defaultChannel);
00172 }
00173 return false;
00174 }
00175
00176
00177 QString channelID = GetChannelID(channelName);
00178 if (channelID.isEmpty())
00179 {
00180 VERBOSE(VB_IMPORTANT, LOC_ERR + QString(
00181 "Changing to '%1' failed. "
00182 "DBox2 channel ID for name '%2' not found!")
00183 .arg(chan).arg(channelName));
00184
00185 QString defaultChannel = GetDefaultChannel();
00186 if (defaultChannel != chan)
00187 {
00188 VERBOSE(VB_CHANNEL, LOC + QString("Trying default channel '%1'")
00189 .arg(defaultChannel));
00190
00191 return SetChannelByString(defaultChannel);
00192 }
00193 return false;
00194 }
00195
00196 VERBOSE(VB_CHANNEL, LOC + QString("Channel ID for '%1' is '%2'.")
00197 .arg(chan).arg(channelID));
00198
00199
00200 m_lock.lock();
00201 if (m_recorder)
00202 m_recorder->ChannelChanging();
00203 m_lock.unlock();
00204
00205 RequestChannelChange(channelID);
00206 return true;
00207 }
00208
00209 bool DBox2Channel::Open(void)
00210 {
00211 VERBOSE(VB_CHANNEL, LOC + "Open()");
00212
00213 if (!InitializeInputs())
00214 return false;
00215
00216 return true;
00217 }
00218
00219 void DBox2Channel::Close(void)
00220 {
00221 VERBOSE(VB_CHANNEL, LOC + "Close()");
00222 }
00223
00224 void DBox2Channel::LoadChannels(void)
00225 {
00226 VERBOSE(VB_CHANNEL, LOC + "Loading channels...\n\t\t\t" +
00227 QString("Reading channel list from %1:%2")
00228 .arg(m_dbox2options->host).arg(m_dbox2options->httpport));
00229
00230
00231
00232
00233 QHttpRequestHeader header("GET", "/control/channellist");
00234 header.setValue("Host", m_dbox2options->host);
00235 http->setHost(m_dbox2options->host, m_dbox2options->httpport);
00236 http->request(header);
00237 }
00238
00239 void DBox2Channel::HttpRequestDone(bool error)
00240 {
00241 if (error)
00242 {
00243 VERBOSE(VB_IMPORTANT, LOC_ERR + "Reading channel list failed!");
00244 return;
00245 }
00246
00247 QString buffer = http->readAll();
00248
00249 VERBOSE(VB_CHANNEL, LOC + "Reading channel list succeeded.");
00250
00251 m_dbox2channelcount = 0;
00252
00253 while (true)
00254 {
00255 QString line = buffer.section("\n", m_dbox2channelcount,
00256 m_dbox2channelcount);
00257
00258 if (line.isEmpty())
00259 break;
00260
00261 m_dbox2channelids[m_dbox2channelcount] = line.section(" ", 0, 0);
00262 m_dbox2channelnames[m_dbox2channelcount] = line.section(" ", 1, 5);
00263
00264 #ifdef DBOX2_CHANNEL_DEBUG
00265 VERBOSE(VB_CHANNEL, LOC + QString("Found Channel '%1'.")
00266 .arg(m_dbox2channelnames[m_dbox2channelcount]));
00267 #endif
00268
00269 m_dbox2channelcount++;
00270 }
00271
00272 VERBOSE(VB_CHANNEL, LOC + QString("Read %1 channels.")
00273 .arg(m_dbox2channelcount));
00274
00275
00276 m_epg->Init(m_dbox2options, m_cardid, this);
00277
00278
00279 m_channelListReady = true;
00280
00281
00282 if (!m_requestChannel.isEmpty())
00283 {
00284 SetChannelByString(m_requestChannel);
00285 m_requestChannel = "";
00286 }
00287 }
00288
00289 void DBox2Channel::RequestChannelChange(QString channelID)
00290 {
00291
00292 QString requestString;
00293 requestString = QString("/control/zapto?%1").arg(channelID);
00294
00295 VERBOSE(VB_CHANNEL, LOC +
00296 QString("Changing channel on %1:%2 to channel id %3: %4")
00297 .arg(m_dbox2options->host).arg(m_dbox2options->httpport)
00298 .arg(channelID).arg(requestString));
00299
00300
00301
00302
00303 QHttpRequestHeader header("GET", requestString);
00304 header.setValue("Host", m_dbox2options->host);
00305 httpChanger->setHost(m_dbox2options->host, m_dbox2options->httpport);
00306 httpChanger->request(header);
00307 }
00308
00309 void DBox2Channel::HttpChannelChangeDone(bool error)
00310 {
00311 if (error)
00312 {
00313 VERBOSE(VB_IMPORTANT, LOC_ERR + "Changing channel failed!");
00314 return;
00315 }
00316
00317 QString buffer = httpChanger->readAll();
00318 QString line = buffer;
00319
00320 if (line == "ok")
00321 {
00322 VERBOSE(VB_CHANNEL, LOC + "Changing channel succeeded...");
00323
00324
00325 m_lock.lock();
00326 if (m_recorder)
00327 m_recorder->ChannelChanged();
00328 m_lock.unlock();
00329
00330
00331 if (!m_recorderAlive)
00332 m_epg->ScheduleRequestEPG(curchannelname);
00333 return;
00334 }
00335
00336 VERBOSE(VB_IMPORTANT, LOC_ERR +
00337 QString("Changing channel failed: %1.").arg(line));
00338
00339 return;
00340 }
00341
00342 QString DBox2Channel::GetChannelID(const QString &name)
00343 {
00344 for (int i = m_dbox2channelcount-1; i >= 0; i--)
00345 if (m_dbox2channelnames[i].upper() == name.upper())
00346 return m_dbox2channelids[i];
00347
00348 return "";
00349 }
00350
00351 QString DBox2Channel::GetChannelNameFromNumber(const QString &channelnumber)
00352 {
00353 MSqlQuery query(MSqlQuery::InitCon());
00354 query.prepare(
00355 "SELECT name "
00356 "FROM channel, cardinput "
00357 "WHERE channel.sourceid = cardinput.sourceid AND "
00358 " cardinput.cardid = :CARDID AND "
00359 " channel.channum = :CHANNUM");
00360 query.bindValue(":CARDID", m_cardid);
00361 query.bindValue(":CHANNUM", channelnumber);
00362
00363 if (query.exec() && query.isActive() && query.next())
00364 return query.value(0).toString();
00365
00366 return "";
00367 }
00368
00369 QString DBox2Channel::GetChannelNumberFromName(const QString &channelName)
00370 {
00371 VERBOSE(VB_CHANNEL, LOC + "Getting channel number from " +
00372 QString("channel '%1'.").arg(channelName));
00373
00374 MSqlQuery query(MSqlQuery::InitCon());
00375 query.prepare(
00376 "SELECT channum "
00377 "FROM channel, cardinput "
00378 "WHERE channel.sourceid = cardinput.sourceid AND "
00379 " cardinput.cardid = :CARDID AND "
00380 " channel.name = :NAME");
00381 query.bindValue(":CARDID", m_cardid);
00382 query.bindValue(":NAME", channelName);
00383
00384 if (query.exec() && query.isActive() && query.next())
00385 return query.value(0).toString();
00386
00387 VERBOSE(VB_IMPORTANT, LOC_ERR + "Channel number from channel " +
00388 QString("'%1' is unknown.").arg(channelName));
00389
00390 return "";
00391 }
00392
00393 QString DBox2Channel::GetDefaultChannel(void)
00394 {
00395 MSqlQuery query(MSqlQuery::InitCon());
00396 query.prepare(
00397 "SELECT channum "
00398 "FROM channel, cardinput "
00399 "WHERE channel.sourceid = cardinput.sourceid AND "
00400 " cardinput.cardid = :CARDID "
00401 "ORDER BY channum limit 1");
00402 query.bindValue(":CARDID", m_cardid);
00403
00404 if (query.exec() && query.isActive() && query.next())
00405 return query.value(0).toString();
00406
00407 return "";
00408 }
00409
00410 void DBox2Channel::RecorderAlive(bool alive)
00411 {
00412 if (m_recorderAlive == alive)
00413 return;
00414
00415 m_recorderAlive = alive;
00416 if (m_recorderAlive)
00417 {
00418 VERBOSE(VB_EIT, LOC + "Recorder now online. Deactivating EPG scan");
00419 }
00420 else
00421 {
00422 VERBOSE(VB_EIT, LOC + "Recorder now offline. Reactivating EPG scan");
00423 uint nextchanid = GetNextChannel(0, CHANNEL_DIRECTION_UP);
00424 SetChannelByString(ChannelUtil::GetChanNum(nextchanid));
00425 }
00426 }
00427
00428 void DBox2Channel::EPGFinished(void)
00429 {
00430
00431 if (m_recorderAlive)
00432 {
00433 VERBOSE(VB_EIT, LOC + "EPG finished. Recorder still online. "
00434 "Deactivating EPG scan");
00435 }
00436 else
00437 {
00438 VERBOSE(VB_EIT, LOC + "EPG finished. Recorder still offline. "
00439 "Continuing EPG scan");
00440 uint nextchanid = GetNextChannel(0, CHANNEL_DIRECTION_UP);
00441 SetChannelByString(ChannelUtil::GetChanNum(nextchanid));
00442 }
00443 }