|
MythTV
0.26-pre
|
00001 #include <unistd.h> 00002 00003 #include <QStringList> 00004 00005 #include "remoteencoder.h" 00006 #include "programinfo.h" 00007 #include "mythmiscutil.h" 00008 #include "mythcorecontext.h" 00009 #include "signalmonitor.h" 00010 #include "videooutbase.h" 00011 #include "mythdb.h" 00012 #include "mythsocket.h" 00013 #include "mythlogging.h" 00014 00015 using namespace std; 00016 00017 #define LOC QString("RemoteEncoder(%1): ").arg(recordernum) 00018 00019 RemoteEncoder::RemoteEncoder(int num, const QString &host, short port) 00020 : recordernum(num), controlSock(NULL), remotehost(host), 00021 remoteport(port), lastchannel(""), lastinput(""), 00022 backendError(false), cachedFramesWritten(0) 00023 { 00024 } 00025 00026 RemoteEncoder::~RemoteEncoder() 00027 { 00028 if (controlSock) 00029 controlSock->DownRef(); 00030 } 00031 00032 bool RemoteEncoder::Setup(void) 00033 { 00034 if (!controlSock) 00035 { 00036 LOG(VB_NETWORK, LOG_DEBUG, "RemoteEncoder::Setup(): Connecting..."); 00037 00038 QString ann = QString("ANN Playback %1 %2") 00039 .arg(gCoreContext->GetHostName()).arg(false); 00040 00041 controlSock = gCoreContext->ConnectCommandSocket( 00042 remotehost, remoteport, ann); 00043 00044 if (controlSock) 00045 { 00046 LOG(VB_NETWORK, LOG_DEBUG, "RemoteEncoder::Setup(): Connected"); 00047 } 00048 else 00049 { 00050 LOG(VB_GENERAL, LOG_ERR, 00051 "RemoteEncoder::Setup(): Failed to connect to backend"); 00052 } 00053 } 00054 else 00055 { 00056 LOG(VB_NETWORK, LOG_DEBUG, "RemoteEncoder::Setup(): Already connected"); 00057 } 00058 return controlSock; 00059 } 00060 00061 bool RemoteEncoder::IsValidRecorder(void) const 00062 { 00063 return (recordernum >= 0); 00064 } 00065 00066 int RemoteEncoder::GetRecorderNumber(void) const 00067 { 00068 return recordernum; 00069 } 00070 00071 bool RemoteEncoder::SendReceiveStringList( 00072 QStringList &strlist, uint min_reply_length) 00073 { 00074 QMutexLocker locker(&lock); 00075 if (!controlSock) 00076 Setup(); 00077 00078 backendError = false; 00079 00080 if (!controlSock) 00081 { 00082 LOG(VB_GENERAL, LOG_ERR, "RemoteEncoder::SendReceiveStringList(): " 00083 "Failed to reconnect with backend."); 00084 backendError = true; 00085 return false; 00086 } 00087 00088 if (!controlSock->writeStringList(strlist)) 00089 { 00090 LOG(VB_GENERAL, LOG_ERR, "RemoteEncoder::SendReceiveStringList(): " 00091 "Failed to write data."); 00092 backendError = true; 00093 } 00094 00095 if (!backendError && 00096 !controlSock->readStringList(strlist, MythSocket::kShortTimeout)) 00097 { 00098 LOG(VB_GENERAL, LOG_ERR, 00099 "RemoteEncoder::SendReceiveStringList(): No response."); 00100 backendError = true; 00101 } 00102 00103 if (!backendError && 00104 min_reply_length && ((uint)strlist.size() < min_reply_length)) 00105 { 00106 LOG(VB_GENERAL, LOG_ERR, 00107 "RemoteEncoder::SendReceiveStringList(): Response too short"); 00108 backendError = true; 00109 } 00110 00111 if (backendError) 00112 { 00113 controlSock->DownRef(); 00114 controlSock = NULL; 00115 return false; 00116 } 00117 00118 return true; 00119 } 00120 00121 bool RemoteEncoder::IsRecording(bool *ok) 00122 { 00123 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00124 strlist << "IS_RECORDING"; 00125 00126 bool ret = SendReceiveStringList(strlist, 1); 00127 if (!ret) 00128 { 00129 if (ok) 00130 *ok = false; 00131 00132 return false; 00133 } 00134 00135 if (ok) 00136 *ok = true; 00137 00138 return strlist[0].toInt(); 00139 } 00140 00141 ProgramInfo *RemoteEncoder::GetRecording(void) 00142 { 00143 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00144 strlist << "GET_RECORDING"; 00145 00146 if (SendReceiveStringList(strlist)) 00147 { 00148 ProgramInfo *proginfo = new ProgramInfo(strlist); 00149 if (proginfo->GetChanID()) 00150 return proginfo; 00151 delete proginfo; 00152 } 00153 00154 return NULL; 00155 } 00156 00163 float RemoteEncoder::GetFrameRate(void) 00164 { 00165 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00166 strlist << "GET_FRAMERATE"; 00167 00168 bool ok = false; 00169 float retval = 30.0f; 00170 00171 if (SendReceiveStringList(strlist, 1)) 00172 { 00173 retval = strlist[0].toFloat(&ok); 00174 00175 if (!ok) 00176 { 00177 LOG(VB_GENERAL, LOG_ERR, LOC + 00178 QString("GetFrameRate() failed to parse response '%1'") 00179 .arg(strlist[0])); 00180 } 00181 } 00182 else 00183 { 00184 LOG(VB_GENERAL, LOG_ERR, LOC + 00185 "GetFrameRate(): SendReceiveStringList() failed"); 00186 } 00187 00188 return (ok) ? retval : 30.0f; 00189 } 00190 00198 long long RemoteEncoder::GetFramesWritten(void) 00199 { 00200 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00201 strlist << "GET_FRAMES_WRITTEN"; 00202 00203 if (!SendReceiveStringList(strlist, 1)) 00204 { 00205 LOG(VB_GENERAL, LOG_ERR, LOC + "GetFramesWritten() -- network error"); 00206 return -1; 00207 } 00208 00209 cachedFramesWritten = strlist[0].toLongLong(); 00210 return cachedFramesWritten; 00211 } 00212 00219 long long RemoteEncoder::GetFilePosition(void) 00220 { 00221 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00222 strlist << "GET_FILE_POSITION"; 00223 00224 if (SendReceiveStringList(strlist, 1)) 00225 return strlist[0].toLongLong(); 00226 00227 return -1; 00228 } 00229 00234 long long RemoteEncoder::GetMaxBitrate(void) 00235 { 00236 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00237 strlist << "GET_MAX_BITRATE"; 00238 00239 if (SendReceiveStringList(strlist, 1)) 00240 return strlist[0].toLongLong(); 00241 00242 return 20200000LL; // Peek bit rate for HD-PVR 00243 } 00244 00252 int64_t RemoteEncoder::GetKeyframePosition(uint64_t desired) 00253 { 00254 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00255 strlist << "GET_KEYFRAME_POS"; 00256 strlist << QString::number(desired); 00257 00258 if (SendReceiveStringList(strlist, 1)) 00259 return strlist[0].toLongLong(); 00260 00261 return -1; 00262 } 00263 00264 void RemoteEncoder::FillPositionMap(long long start, long long end, 00265 QMap<long long, long long> &positionMap) 00266 { 00267 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00268 strlist << "FILL_POSITION_MAP"; 00269 strlist << QString::number(start); 00270 strlist << QString::number(end); 00271 00272 if (!SendReceiveStringList(strlist)) 00273 return; 00274 00275 QStringList::const_iterator it = strlist.begin(); 00276 for (; it != strlist.end(); ++it) 00277 { 00278 bool ok; 00279 long long index = (*it).toLongLong(&ok); 00280 if (++it == strlist.end() || !ok) 00281 break; 00282 00283 long long pos = (*it).toLongLong(&ok); 00284 if (!ok) 00285 break; 00286 00287 positionMap[index] = pos; 00288 } 00289 } 00290 00291 void RemoteEncoder::CancelNextRecording(bool cancel) 00292 { 00293 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00294 strlist << "CANCEL_NEXT_RECORDING"; 00295 strlist << QString::number((cancel) ? 1 : 0); 00296 00297 SendReceiveStringList(strlist); 00298 } 00299 00300 void RemoteEncoder::FrontendReady(void) 00301 { 00302 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00303 strlist << "FRONTEND_READY"; 00304 00305 SendReceiveStringList(strlist); 00306 } 00307 00312 void RemoteEncoder::StopPlaying(void) 00313 { 00314 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00315 strlist << "STOP_PLAYING"; 00316 00317 SendReceiveStringList(strlist); 00318 } 00319 00325 void RemoteEncoder::SpawnLiveTV(QString chainId, bool pip, QString startchan) 00326 { 00327 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00328 strlist << "SPAWN_LIVETV"; 00329 strlist << chainId; 00330 strlist << QString::number((int)pip); 00331 strlist << startchan; 00332 00333 SendReceiveStringList(strlist); 00334 } 00335 00341 void RemoteEncoder::StopLiveTV(void) 00342 { 00343 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00344 strlist << "STOP_LIVETV"; 00345 00346 SendReceiveStringList(strlist); 00347 } 00348 00354 void RemoteEncoder::PauseRecorder(void) 00355 { 00356 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00357 strlist << "PAUSE"; 00358 00359 if (SendReceiveStringList(strlist)) 00360 lastinput = ""; 00361 } 00362 00363 void RemoteEncoder::FinishRecording(void) 00364 { 00365 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00366 strlist << "FINISH_RECORDING"; 00367 00368 SendReceiveStringList(strlist); 00369 } 00370 00371 void RemoteEncoder::SetLiveRecording(bool recording) 00372 { 00373 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00374 strlist << "SET_LIVE_RECORDING"; 00375 strlist << QString::number(recording); 00376 00377 SendReceiveStringList(strlist); 00378 } 00379 00380 QString RemoteEncoder::GetInput(void) 00381 { 00382 if (!lastinput.isEmpty()) 00383 return lastinput; 00384 00385 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00386 strlist << "GET_INPUT"; 00387 00388 if (SendReceiveStringList(strlist, 1)) 00389 { 00390 lastinput = strlist[0]; 00391 return lastinput; 00392 } 00393 00394 return "Error"; 00395 } 00396 00397 QString RemoteEncoder::SetInput(QString input) 00398 { 00399 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00400 strlist << "SET_INPUT"; 00401 strlist << input; 00402 00403 if (SendReceiveStringList(strlist, 1)) 00404 { 00405 lastchannel = ""; 00406 lastinput = ""; 00407 return strlist[0]; 00408 } 00409 00410 return (lastinput.isEmpty()) ? "Error" : lastinput; 00411 } 00412 00413 void RemoteEncoder::ToggleChannelFavorite(QString changroupname) 00414 { 00415 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00416 strlist << "TOGGLE_CHANNEL_FAVORITE"; 00417 strlist << changroupname; 00418 00419 SendReceiveStringList(strlist); 00420 } 00421 00422 void RemoteEncoder::ChangeChannel(int channeldirection) 00423 { 00424 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00425 strlist << "CHANGE_CHANNEL"; 00426 strlist << QString::number(channeldirection); 00427 00428 if (!SendReceiveStringList(strlist)) 00429 return; 00430 00431 lastchannel = ""; 00432 lastinput = ""; 00433 } 00434 00435 void RemoteEncoder::SetChannel(QString channel) 00436 { 00437 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00438 strlist << "SET_CHANNEL"; 00439 strlist << channel; 00440 00441 if (!SendReceiveStringList(strlist)) 00442 return; 00443 00444 lastchannel = ""; 00445 lastinput = ""; 00446 } 00447 00464 int RemoteEncoder::SetSignalMonitoringRate(int rate, bool notifyFrontend) 00465 { 00466 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00467 strlist << "SET_SIGNAL_MONITORING_RATE"; 00468 strlist << QString::number(rate); 00469 strlist << QString::number((int)notifyFrontend); 00470 00471 if (SendReceiveStringList(strlist, 1)) 00472 return strlist[0].toInt(); 00473 00474 return 0; 00475 } 00476 00477 uint RemoteEncoder::GetSignalLockTimeout(QString input) 00478 { 00479 QMutexLocker locker(&lock); 00480 00481 QMap<QString,uint>::const_iterator it = cachedTimeout.find(input); 00482 if (it != cachedTimeout.end()) 00483 return *it; 00484 00485 uint cardid = recordernum; 00486 uint timeout = 0xffffffff; 00487 MSqlQuery query(MSqlQuery::InitCon()); 00488 query.prepare( 00489 "SELECT channel_timeout, cardtype " 00490 "FROM cardinput, capturecard " 00491 "WHERE cardinput.inputname = :INNAME AND " 00492 " cardinput.cardid = :CARDID AND " 00493 " cardinput.cardid = capturecard.cardid"); 00494 query.bindValue(":INNAME", input); 00495 query.bindValue(":CARDID", cardid); 00496 if (!query.exec() || !query.isActive()) 00497 MythDB::DBError("Getting timeout", query); 00498 else if (query.next() && 00499 SignalMonitor::IsRequired(query.value(1).toString())) 00500 timeout = max(query.value(0).toInt(), 500); 00501 00502 #if 0 00503 LOG(VB_PLAYBACK, LOG_DEBUG, "RemoteEncoder: " + 00504 QString("GetSignalLockTimeout(%1): Set lock timeout to %2 ms") 00505 .arg(cardid).arg(timeout)); 00506 #endif 00507 cachedTimeout[input] = timeout; 00508 return timeout; 00509 } 00510 00511 00512 int RemoteEncoder::GetPictureAttribute(PictureAttribute attr) 00513 { 00514 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00515 00516 if (kPictureAttribute_Contrast == attr) 00517 strlist << "GET_CONTRAST"; 00518 else if (kPictureAttribute_Brightness == attr) 00519 strlist << "GET_BRIGHTNESS"; 00520 else if (kPictureAttribute_Colour == attr) 00521 strlist << "GET_COLOUR"; 00522 else if (kPictureAttribute_Hue == attr) 00523 strlist << "GET_HUE"; 00524 else 00525 return -1; 00526 00527 if (SendReceiveStringList(strlist, 1)) 00528 return strlist[0].toInt(); 00529 00530 return -1; 00531 } 00532 00540 int RemoteEncoder::ChangePictureAttribute( 00541 PictureAdjustType type, PictureAttribute attr, bool up) 00542 { 00543 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00544 00545 if (kPictureAttribute_Contrast == attr) 00546 strlist << "CHANGE_CONTRAST"; 00547 else if (kPictureAttribute_Brightness == attr) 00548 strlist << "CHANGE_BRIGHTNESS"; 00549 else if (kPictureAttribute_Colour == attr) 00550 strlist << "CHANGE_COLOUR"; 00551 else if (kPictureAttribute_Hue == attr) 00552 strlist << "CHANGE_HUE"; 00553 else 00554 return -1; 00555 00556 strlist << QString::number(type); 00557 strlist << QString::number((int)up); 00558 00559 if (SendReceiveStringList(strlist, 1)) 00560 return strlist[0].toInt(); 00561 00562 return -1; 00563 } 00564 00565 void RemoteEncoder::ChangeDeinterlacer(int deint_mode) 00566 { 00567 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00568 strlist << "CHANGE_DEINTERLACER"; 00569 strlist << QString::number((int)deint_mode); 00570 00571 SendReceiveStringList(strlist); 00572 } 00573 00583 bool RemoteEncoder::CheckChannel(QString channel) 00584 { 00585 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00586 strlist << "CHECK_CHANNEL"; 00587 strlist << channel; 00588 00589 if (SendReceiveStringList(strlist, 1)) 00590 return strlist[0].toInt(); 00591 00592 return false; 00593 } 00594 00604 bool RemoteEncoder::ShouldSwitchToAnotherCard(QString channelid) 00605 { 00606 // this function returns true if the channelid is not a valid 00607 // channel on the current recorder. It queries to server in order 00608 // to determine this. 00609 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00610 strlist << "SHOULD_SWITCH_CARD"; 00611 strlist << channelid; 00612 00613 if (SendReceiveStringList(strlist, 1)) 00614 return strlist[0].toInt(); 00615 00616 return false; 00617 } 00618 00625 bool RemoteEncoder::CheckChannelPrefix( 00626 const QString &prefix, 00627 uint &is_complete_valid_channel_on_rec, 00628 bool &is_extra_char_useful, 00629 QString &needed_spacer) 00630 { 00631 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00632 strlist << "CHECK_CHANNEL_PREFIX"; 00633 strlist << prefix; 00634 00635 if (!SendReceiveStringList(strlist, 4)) 00636 return false; 00637 00638 is_complete_valid_channel_on_rec = strlist[1].toInt(); 00639 is_extra_char_useful = strlist[2].toInt(); 00640 needed_spacer = (strlist[3] == "X") ? "" : strlist[3]; 00641 00642 return strlist[0].toInt(); 00643 } 00644 00645 static QString cleanup(const QString &str) 00646 { 00647 if (str == " ") 00648 return ""; 00649 return str; 00650 } 00651 00652 static QString make_safe(const QString &str) 00653 { 00654 if (str.isEmpty()) 00655 return " "; 00656 return str; 00657 } 00658 00665 void RemoteEncoder::GetNextProgram(int direction, 00666 QString &title, QString &subtitle, 00667 QString &desc, QString &category, 00668 QString &starttime, QString &endtime, 00669 QString &callsign, QString &iconpath, 00670 QString &channelname, QString &chanid, 00671 QString &seriesid, QString &programid) 00672 { 00673 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum) ); 00674 strlist << "GET_NEXT_PROGRAM_INFO"; 00675 strlist << channelname; 00676 strlist << chanid; 00677 strlist << QString::number((int)direction); 00678 strlist << starttime; 00679 00680 if (!SendReceiveStringList(strlist, 12)) 00681 return; 00682 00683 title = cleanup(strlist[0]); 00684 subtitle = cleanup(strlist[1]); 00685 desc = cleanup(strlist[2]); 00686 category = cleanup(strlist[3]); 00687 starttime = cleanup(strlist[4]); 00688 endtime = cleanup(strlist[5]); 00689 callsign = cleanup(strlist[6]); 00690 iconpath = cleanup(strlist[7]); 00691 channelname = cleanup(strlist[8]); 00692 chanid = cleanup(strlist[9]); 00693 seriesid = cleanup(strlist[10]); 00694 programid = cleanup(strlist[11]); 00695 } 00696 00697 void RemoteEncoder::GetChannelInfo(InfoMap &infoMap, uint chanid) 00698 { 00699 QStringList strlist( QString("QUERY_RECORDER %1").arg(recordernum)); 00700 strlist << "GET_CHANNEL_INFO"; 00701 strlist << QString::number(chanid); 00702 00703 if (!SendReceiveStringList(strlist, 6)) 00704 return; 00705 00706 infoMap["chanid"] = cleanup(strlist[0]); 00707 infoMap["sourceid"] = cleanup(strlist[1]); 00708 infoMap["callsign"] = cleanup(strlist[2]); 00709 infoMap["channum"] = cleanup(strlist[3]); 00710 infoMap["channame"] = cleanup(strlist[4]); 00711 infoMap["XMLTV"] = cleanup(strlist[5]); 00712 00713 infoMap["oldchannum"] = infoMap["channum"]; 00714 } 00715 00716 bool RemoteEncoder::SetChannelInfo(const InfoMap &infoMap) 00717 { 00718 QStringList strlist( "SET_CHANNEL_INFO" ); 00719 strlist << make_safe(infoMap["chanid"]); 00720 strlist << make_safe(infoMap["sourceid"]); 00721 strlist << make_safe(infoMap["oldchannum"]); 00722 strlist << make_safe(infoMap["callsign"]); 00723 strlist << make_safe(infoMap["channum"]); 00724 strlist << make_safe(infoMap["channame"]); 00725 strlist << make_safe(infoMap["XMLTV"]); 00726 00727 if (SendReceiveStringList(strlist, 1)) 00728 return strlist[0].toInt(); 00729 00730 return false; 00731 }
1.7.6.1