00001 #include <qapplication.h>
00002
00003 #include <unistd.h>
00004
00005 using namespace std;
00006
00007 #include "remoteencoder.h"
00008 #include "programinfo.h"
00009 #include "util.h"
00010 #include "mythcontext.h"
00011 #include "signalmonitor.h"
00012 #include "videooutbase.h"
00013 #include "mythsocket.h"
00014
00015 RemoteEncoder::RemoteEncoder(int num, const QString &host, short port)
00016 : recordernum(num), controlSock(NULL), remotehost(host),
00017 remoteport(port), lastchannel(""), lastinput(""),
00018 backendError(false), cachedFramesWritten(0)
00019 {
00020 }
00021
00022 RemoteEncoder::~RemoteEncoder()
00023 {
00024 if (controlSock)
00025 controlSock->DownRef();
00026 }
00027
00028 void RemoteEncoder::Setup(void)
00029 {
00030 if (!controlSock)
00031 {
00032 controlSock = openControlSocket(remotehost, remoteport);
00033 }
00034 }
00035
00036 bool RemoteEncoder::IsValidRecorder(void)
00037 {
00038 return (recordernum >= 0);
00039 }
00040
00041 int RemoteEncoder::GetRecorderNumber(void)
00042 {
00043 return recordernum;
00044 }
00045
00046 void RemoteEncoder::SendReceiveStringList(QStringList &strlist)
00047 {
00048 QMutexLocker locker(&lock);
00049 if (!controlSock)
00050 return;
00051
00052 backendError = false;
00053
00054 controlSock->writeStringList(strlist);
00055 if (!controlSock->readStringList(strlist, true))
00056 {
00057 VERBOSE(VB_IMPORTANT,
00058 "RemoteEncoder::SendReceiveStringList(): No response.");
00059 backendError = true;
00060 }
00061 }
00062
00063 MythSocket *RemoteEncoder::openControlSocket(const QString &host, short port)
00064 {
00065 MythSocket *sock = new MythSocket();
00066 if (!sock->connect(host, port))
00067 {
00068 VERBOSE(VB_IMPORTANT,
00069 "RemoteEncoder::openControlSocket(): Connection timed out.");
00070 sock->DownRef();
00071 sock = NULL;
00072 }
00073 else
00074 {
00075 if (gContext->CheckProtoVersion(sock))
00076 {
00077 QString hostname = gContext->GetHostName();
00078 QStringList strlist = QString("ANN Playback %1 %2").arg(hostname).arg(false);
00079 sock->writeStringList(strlist);
00080 sock->readStringList(strlist, true);
00081 }
00082 else
00083 {
00084 sock->DownRef();
00085 sock = NULL;
00086 }
00087 }
00088
00089 return sock;
00090 }
00091
00092 bool RemoteEncoder::IsRecording(void)
00093 {
00094 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00095 strlist << "IS_RECORDING";
00096
00097 SendReceiveStringList(strlist);
00098
00099 bool retval = strlist[0].toInt();
00100 return retval;
00101 }
00102
00103 ProgramInfo *RemoteEncoder::GetRecording(void)
00104 {
00105 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00106 strlist << "GET_RECORDING";
00107
00108 SendReceiveStringList(strlist);
00109
00110 ProgramInfo *proginfo = new ProgramInfo;
00111 proginfo->FromStringList(strlist, 0);
00112 return proginfo;
00113 }
00114
00121 float RemoteEncoder::GetFrameRate(void)
00122 {
00123 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00124 strlist << "GET_FRAMERATE";
00125
00126 SendReceiveStringList(strlist);
00127
00128 float retval = strlist[0].toFloat();
00129 return retval;
00130 }
00131
00139 long long RemoteEncoder::GetFramesWritten(void)
00140 {
00141 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00142 strlist << "GET_FRAMES_WRITTEN";
00143
00144 SendReceiveStringList(strlist);
00145
00146 cachedFramesWritten = decodeLongLong(strlist, 0);
00147
00148 return cachedFramesWritten;
00149 }
00150
00157 long long RemoteEncoder::GetFilePosition(void)
00158 {
00159 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00160 strlist << "GET_FILE_POSITION";
00161
00162 SendReceiveStringList(strlist);
00163
00164 long long retval = decodeLongLong(strlist, 0);
00165
00166 return retval;
00167 }
00168
00173 long long RemoteEncoder::GetMaxBitrate(void)
00174 {
00175 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00176 strlist << "GET_MAX_BITRATE";
00177
00178 SendReceiveStringList(strlist);
00179
00180 long long retval = decodeLongLong(strlist, 0);
00181
00182 return retval;
00183 }
00184
00192 long long RemoteEncoder::GetKeyframePosition(long long desired)
00193 {
00194 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00195 strlist << "GET_KEYFRAME_POS";
00196 encodeLongLong(strlist, desired);
00197
00198 SendReceiveStringList(strlist);
00199
00200 long long retval = decodeLongLong(strlist, 0);
00201
00202 return retval;
00203 }
00204
00205 void RemoteEncoder::FillPositionMap(int start, int end,
00206 QMap<long long, long long> &positionMap)
00207 {
00208 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00209 strlist << "FILL_POSITION_MAP";
00210 strlist << QString::number(start);
00211 strlist << QString::number(end);
00212
00213 SendReceiveStringList(strlist);
00214
00215 int listpos = 0;
00216 int listsize = strlist.size();
00217
00218 if (listsize < 4)
00219 return;
00220
00221 for(int i = start; listpos < listsize ; i++)
00222 {
00223 long long index = decodeLongLong(strlist, listpos);
00224 positionMap[index] = decodeLongLong(strlist, listpos+2);
00225 listpos += 4;
00226 }
00227 }
00228
00229 void RemoteEncoder::CancelNextRecording(bool cancel)
00230 {
00231 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00232 strlist << "CANCEL_NEXT_RECORDING";
00233 strlist << QString::number((cancel) ? 1 : 0);
00234
00235 SendReceiveStringList(strlist);
00236 }
00237
00238 void RemoteEncoder::FrontendReady(void)
00239 {
00240 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00241 strlist << "FRONTEND_READY";
00242
00243 SendReceiveStringList(strlist);
00244 }
00245
00250 void RemoteEncoder::StopPlaying(void)
00251 {
00252 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00253 strlist << "STOP_PLAYING";
00254
00255 SendReceiveStringList(strlist);
00256 }
00257
00263 void RemoteEncoder::SpawnLiveTV(QString chainId, bool pip, QString startchan)
00264 {
00265 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00266 strlist << "SPAWN_LIVETV";
00267 strlist << chainId;
00268 strlist << QString::number((int)pip);
00269 strlist << startchan;
00270
00271 SendReceiveStringList(strlist);
00272 }
00273
00279 void RemoteEncoder::StopLiveTV(void)
00280 {
00281 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00282 strlist << "STOP_LIVETV";
00283
00284 SendReceiveStringList(strlist);
00285 }
00286
00292 void RemoteEncoder::PauseRecorder(void)
00293 {
00294 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00295 strlist << "PAUSE";
00296
00297 SendReceiveStringList(strlist);
00298
00299 lastinput = "";
00300 }
00301
00302 void RemoteEncoder::FinishRecording(void)
00303 {
00304 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00305 strlist << "FINISH_RECORDING";
00306
00307 SendReceiveStringList(strlist);
00308 }
00309
00310 void RemoteEncoder::SetLiveRecording(bool recording)
00311 {
00312 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00313 strlist << "SET_LIVE_RECORDING";
00314 strlist << QString::number(recording);
00315
00316 SendReceiveStringList(strlist);
00317 }
00318
00319 QString RemoteEncoder::GetInput(void)
00320 {
00321 if (lastinput.length() > 2)
00322 return lastinput;
00323
00324 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00325 strlist << "GET_INPUT";
00326
00327 SendReceiveStringList(strlist);
00328
00329 lastinput = strlist[0];
00330 return lastinput;
00331 }
00332
00333 QString RemoteEncoder::SetInput(QString input)
00334 {
00335 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00336 strlist << "SET_INPUT";
00337 strlist << input;
00338
00339 SendReceiveStringList(strlist);
00340
00341 lastchannel = "";
00342 lastinput = "";
00343
00344 return strlist[0];
00345 }
00346
00347 void RemoteEncoder::ToggleChannelFavorite(void)
00348 {
00349 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00350 strlist << "TOGGLE_CHANNEL_FAVORITE";
00351
00352 SendReceiveStringList(strlist);
00353 }
00354
00355 void RemoteEncoder::ChangeChannel(int channeldirection)
00356 {
00357 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00358 strlist << "CHANGE_CHANNEL";
00359 strlist << QString::number(channeldirection);
00360
00361 SendReceiveStringList(strlist);
00362
00363 lastchannel = "";
00364 lastinput = "";
00365 }
00366
00367 void RemoteEncoder::SetChannel(QString channel)
00368 {
00369 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00370 strlist << "SET_CHANNEL";
00371 strlist << channel;
00372
00373 SendReceiveStringList(strlist);
00374
00375 lastchannel = "";
00376 lastinput = "";
00377 }
00378
00395 int RemoteEncoder::SetSignalMonitoringRate(int rate, bool notifyFrontend)
00396 {
00397 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00398 strlist << "SET_SIGNAL_MONITORING_RATE";
00399 strlist << QString::number(rate);
00400 strlist << QString::number((int)notifyFrontend);
00401
00402 SendReceiveStringList(strlist);
00403
00404 int retval = strlist[0].toInt();
00405 return retval;
00406 }
00407
00408 uint RemoteEncoder::GetSignalLockTimeout(QString input)
00409 {
00410 QMutexLocker locker(&lock);
00411
00412 QMap<QString,uint>::const_iterator it = cachedTimeout.find(input);
00413 if (it != cachedTimeout.end())
00414 return *it;
00415
00416 uint cardid = recordernum;
00417 uint timeout = 0xffffffff;
00418 MSqlQuery query(MSqlQuery::InitCon());
00419 query.prepare(
00420 "SELECT channel_timeout, cardtype "
00421 "FROM cardinput, capturecard "
00422 "WHERE cardinput.inputname = :INNAME AND "
00423 " cardinput.cardid = :CARDID AND "
00424 " cardinput.cardid = capturecard.cardid");
00425 query.bindValue(":INNAME", input);
00426 query.bindValue(":CARDID", cardid);
00427 if (!query.exec() || !query.isActive())
00428 MythContext::DBError("Getting timeout", query);
00429 else if (query.next() &&
00430 SignalMonitor::IsRequired(query.value(1).toString()))
00431 timeout = max(query.value(0).toInt(), 500);
00432
00433
00434
00435
00436
00437
00438 cachedTimeout[input] = timeout;
00439 return timeout;
00440 }
00441
00442
00443 int RemoteEncoder::GetPictureAttribute(PictureAttribute attr)
00444 {
00445 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00446
00447 if (kPictureAttribute_Contrast == attr)
00448 strlist << "GET_CONTRAST";
00449 else if (kPictureAttribute_Brightness == attr)
00450 strlist << "GET_BRIGHTNESS";
00451 else if (kPictureAttribute_Colour == attr)
00452 strlist << "GET_COLOUR";
00453 else if (kPictureAttribute_Hue == attr)
00454 strlist << "GET_HUE";
00455 else
00456 return -1;
00457
00458 SendReceiveStringList(strlist);
00459
00460 int retval = strlist[0].toInt();
00461 return retval;
00462 }
00463
00471 int RemoteEncoder::ChangePictureAttribute(
00472 PictureAdjustType type, PictureAttribute attr, bool up)
00473 {
00474 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00475
00476 if (kPictureAttribute_Contrast == attr)
00477 strlist << "CHANGE_CONTRAST";
00478 else if (kPictureAttribute_Brightness == attr)
00479 strlist << "CHANGE_BRIGHTNESS";
00480 else if (kPictureAttribute_Colour == attr)
00481 strlist << "CHANGE_COLOUR";
00482 else if (kPictureAttribute_Hue == attr)
00483 strlist << "CHANGE_HUE";
00484 else
00485 return -1;
00486
00487 strlist << QString::number(type);
00488 strlist << QString::number((int)up);
00489
00490 SendReceiveStringList(strlist);
00491
00492 int retval = strlist[0].toInt();
00493 return retval;
00494 }
00495
00496 void RemoteEncoder::ChangeDeinterlacer(int deint_mode)
00497 {
00498 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00499 strlist << "CHANGE_DEINTERLACER";
00500 strlist << QString::number((int)deint_mode);
00501
00502 SendReceiveStringList(strlist);
00503 }
00504
00514 bool RemoteEncoder::CheckChannel(QString channel)
00515 {
00516 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00517 strlist << "CHECK_CHANNEL";
00518 strlist << channel;
00519
00520 SendReceiveStringList(strlist);
00521
00522 bool retval = strlist[0].toInt();
00523 return retval;
00524 }
00525
00535 bool RemoteEncoder::ShouldSwitchToAnotherCard(QString channelid)
00536 {
00537
00538
00539
00540 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00541 strlist << "SHOULD_SWITCH_CARD";
00542 strlist << channelid;
00543
00544 SendReceiveStringList(strlist);
00545
00546 bool retval = strlist[0].toInt();
00547 return retval;
00548 }
00549
00556 bool RemoteEncoder::CheckChannelPrefix(
00557 const QString &prefix,
00558 uint &is_complete_valid_channel_on_rec,
00559 bool &is_extra_char_useful,
00560 QString &needed_spacer)
00561 {
00562 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00563 strlist << "CHECK_CHANNEL_PREFIX";
00564 strlist << prefix;
00565
00566 SendReceiveStringList(strlist);
00567
00568 is_complete_valid_channel_on_rec = strlist[1].toInt();
00569 is_extra_char_useful = strlist[2].toInt();
00570 needed_spacer = (strlist[3] == "X") ? "" : strlist[3];
00571
00572 return strlist[0].toInt();
00573 }
00574
00575 static QString cleanup(const QString &str)
00576 {
00577 if (str == " ")
00578 return "";
00579 return str;
00580 }
00581
00582 static QString make_safe(const QString &str)
00583 {
00584 if (str.isEmpty())
00585 return " ";
00586 return str;
00587 }
00588
00595 void RemoteEncoder::GetNextProgram(int direction,
00596 QString &title, QString &subtitle,
00597 QString &desc, QString &category,
00598 QString &starttime, QString &endtime,
00599 QString &callsign, QString &iconpath,
00600 QString &channelname, QString &chanid,
00601 QString &seriesid, QString &programid)
00602 {
00603 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00604 strlist << "GET_NEXT_PROGRAM_INFO";
00605 strlist << channelname;
00606 strlist << chanid;
00607 strlist << QString::number((int)direction);
00608 strlist << starttime;
00609
00610 SendReceiveStringList(strlist);
00611
00612 title = cleanup(strlist[0]);
00613 subtitle = cleanup(strlist[1]);
00614 desc = cleanup(strlist[2]);
00615 category = cleanup(strlist[3]);
00616 starttime = cleanup(strlist[4]);
00617 endtime = cleanup(strlist[5]);
00618 callsign = cleanup(strlist[6]);
00619 iconpath = cleanup(strlist[7]);
00620 channelname = cleanup(strlist[8]);
00621 chanid = cleanup(strlist[9]);
00622 seriesid = cleanup(strlist[10]);
00623 programid = cleanup(strlist[11]);
00624 }
00625
00626 void RemoteEncoder::GetChannelInfo(QMap<QString, QString> &infoMap,
00627 uint chanid)
00628 {
00629 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
00630 strlist << "GET_CHANNEL_INFO";
00631 strlist << QString::number(chanid);
00632
00633 SendReceiveStringList(strlist);
00634
00635 infoMap["chanid"] = cleanup(strlist[0]);
00636 infoMap["sourceid"] = cleanup(strlist[1]);
00637 infoMap["callsign"] = cleanup(strlist[2]);
00638 infoMap["channum"] = cleanup(strlist[3]);
00639 infoMap["channame"] = cleanup(strlist[4]);
00640 infoMap["XMLTV"] = cleanup(strlist[5]);
00641
00642 infoMap["oldchannum"] = infoMap["channum"];
00643 }
00644
00645 bool RemoteEncoder::SetChannelInfo(const QMap<QString, QString> &infoMap)
00646 {
00647 QStringList strlist = "SET_CHANNEL_INFO";
00648 strlist << make_safe(infoMap["chanid"]);
00649 strlist << make_safe(infoMap["sourceid"]);
00650 strlist << make_safe(infoMap["oldchannum"]);
00651 strlist << make_safe(infoMap["callsign"]);
00652 strlist << make_safe(infoMap["channum"]);
00653 strlist << make_safe(infoMap["channame"]);
00654 strlist << make_safe(infoMap["XMLTV"]);
00655
00656 SendReceiveStringList(strlist);
00657
00658 return strlist[0].toInt();
00659 }