Ticket #866: 866-v1.patch
File 866-v1.patch, 36.6 KB (added by , 18 years ago) |
---|
-
libs/libmythtv/osd.h
77 77 void SetSettingsText(const QString &text, int length); 78 78 79 79 void NewDialogBox(const QString &name, const QString &message, 80 QStringList &options, int length );80 QStringList &options, int length, int sel = 0); 81 81 void DialogUp(const QString &name); 82 82 void DialogDown(const QString &name); 83 83 bool DialogShowing(const QString &name); -
libs/libmythtv/tv_play.cpp
246 246 // Program Info for currently playing video 247 247 recorderPlaybackInfo(NULL), 248 248 playbackinfo(NULL), inputFilename(""), playbackLen(0), 249 lastProgram(NULL), jumpToProgram(false), 249 250 // Video Players 250 251 nvp(NULL), pipnvp(NULL), activenvp(NULL), 251 252 // Remote Encoders … … 262 263 // Window info (GUI is optional, transcoding, preview img, etc) 263 264 myWindow(NULL), embedWinID(0), embedBounds(0,0,0,0) 264 265 { 266 for (uint i = 0; i < 2; i++) 267 { 268 pseudoLiveTVRec[i] = NULL; 269 pseudoLiveTVState[i] = kPseudoNormalLiveTV; 270 } 271 265 272 lastLcdUpdate = QDateTime::currentDateTime(); 266 273 lastLcdUpdate.addYears(-1); // make last LCD update last year.. 267 274 lastSignalMsgTime.start(); … … 335 342 float wmult, hmult; 336 343 gContext->GetScreenSettings(xbase, width, wmult, 337 344 ybase, height, hmult); 338 if ( abs(saved_gui_bounds.x()-xbase< 3) &&339 abs(saved_gui_bounds.y()-ybase< 3))345 if ((abs(saved_gui_bounds.x()-xbase) < 3) && 346 (abs(saved_gui_bounds.y()-ybase) < 3)) 340 347 { 341 saved_gui_bounds .setX(xbase);342 saved_gui_bounds.setY(ybase);348 saved_gui_bounds = QRect(QPoint(xbase, ybase), 349 mainWindow->size()); 343 350 } 344 351 } 345 352 … … 574 581 activerecorder->FinishRecording(); 575 582 } 576 583 577 void TV::AskAllowRecording(const QStringList &messages, int timeuntil) 584 void TV::AskAllowRecording(const QStringList &messages, int timeuntil, 585 bool hasrec) 578 586 { 579 587 if (!StateIsLiveTV(GetState())) 580 588 return; … … 605 613 options += tr("Record and watch while it records"); 606 614 options += tr("Let it record and go back to the Main Menu"); 607 615 options += tr("Don't let it record, I want to watch TV"); 616 int sel = (hasrec) ? 2 : 0; 608 617 609 618 dialogname = "allowrecordingbox"; 610 GetOSD()->NewDialogBox(dialogname, message, options, timeuntil );619 GetOSD()->NewDialogBox(dialogname, message, options, timeuntil, sel); 611 620 } 612 621 613 622 void TV::setLastProgram(ProgramInfo *rcinfo) … … 1489 1498 exitPlayer = false; 1490 1499 } 1491 1500 1501 for (uint i = InStateChange() ? 2 : 0; i < 2; i++) 1502 { 1503 if (kPseudoChangeChannel != pseudoLiveTVState[i]) 1504 continue; 1505 1506 VERBOSE(VB_PLAYBACK, "REC_PROGRAM -- channel change "<<i); 1507 if (activerecorder != recorder) 1508 ToggleActiveWindow(); 1509 1510 uint chanid = pseudoLiveTVRec[i]->chanid.toUInt(); 1511 QString channum = pseudoLiveTVRec[i]->chanstr; 1512 str_vec_t tmp = prevChan; 1513 prevChan.clear(); 1514 if (i && activenvp == nvp) 1515 ToggleActiveWindow(); 1516 ChangeChannel(chanid, channum); 1517 prevChan = tmp; 1518 pseudoLiveTVState[i] = kPseudoRecording; 1519 1520 if (i && pipnvp) 1521 TogglePIPView(); 1522 } 1523 1492 1524 if ((doing_ff_rew || speed_index) && 1493 1525 activenvp && activenvp->AtNormalSpeed()) 1494 1526 { … … 1848 1880 else if (dialogname == "allowrecordingbox") 1849 1881 { 1850 1882 int result = GetOSD()->GetDialogResponse(dialogname); 1851 1852 if (result == 2) 1883 1884 if (result == 1) 1885 recorder->CancelNextRecording(false); 1886 else if (result == 2) 1853 1887 StopLiveTV(); 1854 1888 else if (result == 3) 1855 recorder->CancelNextRecording( );1889 recorder->CancelNextRecording(true); 1856 1890 } 1857 1891 else if (dialogname == "channel_timed_out") 1858 1892 { … … 2212 2246 } 2213 2247 else if (StateIsLiveTV(GetState())) 2214 2248 { 2215 ChangeState(kState_None);2216 2249 exitPlayer = true; 2217 2250 wantsToQuit = true; 2218 2251 } … … 2292 2325 } 2293 2326 } 2294 2327 2295 if (StateIsLiveTV(GetState()) )2328 if (StateIsLiveTV(GetState()) || StateIsPlaying(internalState)) 2296 2329 { 2297 2330 for (unsigned int i = 0; i < actions.size() && !handled; i++) 2298 2331 { … … 2306 2339 else 2307 2340 ToggleOSD(true); 2308 2341 } 2309 else if (action == "CHANNELUP") 2310 { 2311 if (persistentbrowsemode) 2312 BrowseDispInfo(BROWSE_UP); 2313 else 2314 ChangeChannel(CHANNEL_DIRECTION_UP); 2315 } 2316 else if (action == "CHANNELDOWN") 2317 { 2318 if (persistentbrowsemode) 2319 BrowseDispInfo(BROWSE_DOWN); 2320 else 2321 ChangeChannel(CHANNEL_DIRECTION_DOWN); 2322 } 2323 else if (action == "TOGGLERECORD") 2342 else if (action == "TOGGLESLEEP") 2343 ToggleSleepTimer(); 2344 else 2345 handled = false; 2346 } 2347 } 2348 2349 uint aindx = (activenvp == nvp) ? 0 : 1; 2350 if (StateIsLiveTV(GetState())) 2351 { 2352 for (unsigned int i = 0; i < actions.size() && !handled; i++) 2353 { 2354 QString action = actions[i]; 2355 handled = true; 2356 2357 if (action == "TOGGLERECORD") 2324 2358 ToggleRecord(); 2325 else if (action == "NEXTFAV")2326 ChangeChannel(CHANNEL_DIRECTION_FAVORITE);2327 2359 else if (action == "TOGGLEFAV") 2328 2360 ToggleChannelFavorite(); 2361 else if (action == "SELECT") 2362 CommitQueuedInput(); 2363 else if (action == "TOGGLERECCONTROLS") 2364 DoToggleRecPictureAttribute(); 2365 else if (action == "TOGGLEBROWSE" && pseudoLiveTVState[aindx]) 2366 ShowOSDTreeMenu(); 2367 else 2368 handled = false; 2369 } 2370 2371 if (redisplayBrowseInfo) 2372 BrowseStart(); 2373 } 2374 2375 if (StateIsLiveTV(GetState()) && !pseudoLiveTVState[aindx]) 2376 { 2377 for (unsigned int i = 0; i < actions.size() && !handled; i++) 2378 { 2379 QString action = actions[i]; 2380 handled = true; 2381 2382 if (action == "NEXTFAV") 2383 ChangeChannel(CHANNEL_DIRECTION_FAVORITE); 2329 2384 else if (action == "TOGGLEINPUTS") 2330 2385 ToggleInputs(); 2331 2386 else if (action == "SWITCHCARDS") 2332 2387 SwitchCards(); 2333 else if (action == "SELECT")2334 CommitQueuedInput();2335 2388 else if (action == "GUIDE") 2336 2389 LoadMenu(); 2337 2390 else if (action == "TOGGLEPIPMODE") … … 2340 2393 ToggleActiveWindow(); 2341 2394 else if (action == "SWAPPIP") 2342 2395 SwapPIP(); 2343 else if (action == "TOGGLERECCONTROLS")2344 DoToggleRecPictureAttribute();2345 2396 else if (action == "TOGGLEBROWSE") 2346 2397 BrowseStart(); 2347 2398 else if (action == "PREVCHAN") 2348 2399 PreviousChannel(); 2349 else if (action == "TOGGLESLEEP") 2350 ToggleSleepTimer(); 2400 else if (action == "CHANNELUP") 2401 { 2402 if (persistentbrowsemode) 2403 BrowseDispInfo(BROWSE_UP); 2404 else 2405 ChangeChannel(CHANNEL_DIRECTION_UP); 2406 } 2407 else if (action == "CHANNELDOWN") 2408 { 2409 if (persistentbrowsemode) 2410 BrowseDispInfo(BROWSE_DOWN); 2411 else 2412 ChangeChannel(CHANNEL_DIRECTION_DOWN); 2413 } 2351 2414 else 2352 2415 handled = false; 2353 2416 } … … 2362 2425 QString action = actions[i]; 2363 2426 handled = true; 2364 2427 2365 if (action == " INFO")2428 if (action == "SELECT") 2366 2429 { 2367 if (HasQueuedInput())2368 DoArbSeek(ARBSEEK_SET);2369 else2370 ToggleOSD(true);2371 }2372 else if (action == "SELECT")2373 {2374 2430 if (!was_doing_ff_rew) 2375 2431 { 2376 2432 if (gContext->GetNumSetting("AltClearSavedPosition", 1) … … 2422 2478 DoSeek(jumptime * 60, tr("Jump Ahead")); 2423 2479 } 2424 2480 } 2425 else if (action == "TOGGLESLEEP")2426 ToggleSleepTimer();2427 2481 else 2428 2482 handled = false; 2429 2483 } … … 2485 2539 else 2486 2540 { 2487 2541 VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP player failed to start"); 2542 delete pipnvp; 2543 pipnvp = NULL; 2488 2544 TeardownPipPlayer(); 2489 2545 } 2490 2546 } … … 2513 2569 piprecorder->StopLiveTV(); 2514 2570 2515 2571 TeardownPipPlayer(); 2572 2573 SetPseudoLiveTV(1, NULL, kPseudoNormalLiveTV); 2516 2574 } 2517 2575 } 2518 2576 … … 3313 3371 if (HasQueuedInput()) 3314 3372 DoArbSeek(ARBSEEK_FORWARD); 3315 3373 } 3316 else if (StateIsLiveTV(GetState())) 3374 else if (StateIsLiveTV(GetState()) && 3375 !pseudoLiveTVState[(activenvp == nvp) ? 0 : 1]) 3317 3376 { 3318 3377 QString channum = GetQueuedChanNum(); 3319 3378 if (browsemode) … … 3322 3381 if (activenvp == nvp && GetOSD()) 3323 3382 GetOSD()->HideSet("channel_number"); 3324 3383 } 3325 else if (activerecorder->CheckChannel(channum)) 3384 else if (GetQueuedChanID() || 3385 (!channum.isEmpty() && activerecorder->CheckChannel(channum))) 3326 3386 ChangeChannel(GetQueuedChanID(), channum); 3327 else if ( GetQueuedInput() != "")3387 else if (!GetQueuedInput().isEmpty()) 3328 3388 ChangeChannel(GetQueuedChanID(), GetQueuedInput()); 3329 3389 } 3330 3390 … … 4368 4428 QStringList tokens = QStringList::split(" ", message); 4369 4429 int cardnum = tokens[1].toInt(); 4370 4430 int timeuntil = tokens[2].toInt(); 4431 int hasrec = tokens[3].toInt(); 4432 VERBOSE(VB_IMPORTANT, LOC + message << " hasrec: "<<hasrec); 4371 4433 4372 4434 if (cardnum == recorder->GetRecorderNumber()) 4373 4435 { 4374 4436 menurunning = false; 4375 AskAllowRecording(me->ExtraDataList(), timeuntil );4437 AskAllowRecording(me->ExtraDataList(), timeuntil, hasrec); 4376 4438 } 4439 else if (piprecorder && 4440 cardnum == piprecorder->GetRecorderNumber()) 4441 { 4442 VERBOSE(VB_GENERAL, LOC + "Disabling PiP for recording"); 4443 TogglePIPView(); 4444 } 4377 4445 } 4378 4446 else if (recorder && message.left(11) == "QUIT_LIVETV") 4379 4447 { … … 4387 4455 wantsToQuit = false; 4388 4456 exitPlayer = true; 4389 4457 } 4458 else if (piprecorder && 4459 cardnum == piprecorder->GetRecorderNumber()) 4460 { 4461 VERBOSE(VB_GENERAL, LOC + "Disabling PiP for QUIT_LIVETV"); 4462 TogglePIPView(); 4463 } 4390 4464 } 4465 else if (recorder && message.left(12) == "LIVETV_WATCH") 4466 { 4467 message = message.simplifyWhiteSpace(); 4468 QStringList tokens = QStringList::split(" ", message); 4469 int cardnum = tokens[1].toInt(); 4470 int watch = tokens[2].toInt(); 4471 4472 uint s = (cardnum == recorder->GetRecorderNumber()) ? 0 : 1; 4473 4474 if (cardnum == recorder->GetRecorderNumber() || 4475 (piprecorder && cardnum == piprecorder->GetRecorderNumber())) 4476 { 4477 if (watch) 4478 { 4479 ProgramInfo *pi = new ProgramInfo(); 4480 QStringList list = me->ExtraDataList(); 4481 if (pi->FromStringList(list, 0)) 4482 SetPseudoLiveTV(s, pi, kPseudoChangeChannel); 4483 delete pi; 4484 4485 if (!s && pipnvp) 4486 TogglePIPView(); 4487 } 4488 else 4489 SetPseudoLiveTV(s, NULL, kPseudoNormalLiveTV); 4490 } 4491 } 4391 4492 else if (tvchain && message.left(12) == "LIVETV_CHAIN") 4392 4493 { 4393 4494 message = message.simplifyWhiteSpace(); … … 4575 4676 delete program_info; 4576 4677 } 4577 4678 4679 void TV::SetPseudoLiveTV(uint i, const ProgramInfo *pi, PseudoState new_state) 4680 { 4681 ProgramInfo *old_rec = pseudoLiveTVRec[i]; 4682 ProgramInfo *new_rec = NULL; 4683 4684 if (pi) 4685 { 4686 new_rec = new ProgramInfo(*pi); 4687 QString msg = QString("Wants to record: %1 %2 %3 %4") 4688 .arg(new_rec->title).arg(new_rec->chanstr) 4689 .arg(new_rec->recstartts.toString()) 4690 .arg(new_rec->recendts.toString()); 4691 VERBOSE(VB_PLAYBACK, LOC + msg); 4692 } 4693 4694 pseudoLiveTVRec[i] = new_rec; 4695 pseudoLiveTVState[i] = new_state; 4696 4697 if (old_rec) 4698 { 4699 QString msg = QString("Done to recording: %1 %2 %3 %4") 4700 .arg(old_rec->title).arg(old_rec->chanstr) 4701 .arg(old_rec->recstartts.toString()) 4702 .arg(old_rec->recendts.toString()); 4703 VERBOSE(VB_PLAYBACK, LOC + msg); 4704 delete old_rec; 4705 } 4706 } 4707 4578 4708 void TV::ToggleRecord(void) 4579 4709 { 4580 4710 if (browsemode) … … 4609 4739 } 4610 4740 4611 4741 QString cmdmsg(""); 4742 uint s = (activenvp == nvp) ? 0 : 1; 4612 4743 if (playbackinfo->GetAutoExpireFromRecorded() == kLiveTVAutoExpire) 4613 4744 { 4614 4745 int autoexpiredef = gContext->GetNumSetting("AutoExpireDefault", 0); 4615 4746 playbackinfo->SetAutoExpire(autoexpiredef); 4616 4747 playbackinfo->ApplyRecordRecGroupChange("Default"); 4617 4748 cmdmsg = tr("Record"); 4749 SetPseudoLiveTV(s, playbackinfo, kPseudoRecording); 4750 VERBOSE(VB_RECORD, LOC + "Toggling Record on"); 4618 4751 } 4619 4752 else 4620 4753 { 4621 4754 playbackinfo->SetAutoExpire(kLiveTVAutoExpire); 4622 4755 playbackinfo->ApplyRecordRecGroupChange("LiveTV"); 4623 4756 cmdmsg = tr("Cancel Record"); 4757 SetPseudoLiveTV(s, playbackinfo, kPseudoNormalLiveTV); 4758 VERBOSE(VB_RECORD, LOC + "Toggling Record off"); 4624 4759 } 4625 4760 4626 4761 QString msg = cmdmsg + "\"" + playbackinfo->title + "\""; -
libs/libmythtv/remoteencoder.h
36 36 void PauseRecorder(void); 37 37 void FinishRecording(void); 38 38 void FrontendReady(void); 39 void CancelNextRecording( void);39 void CancelNextRecording(bool cancel); 40 40 41 41 void ToggleInputs(void); 42 42 int ChangeContrast(bool direction); -
libs/libmythtv/tv_play.h
53 53 } 54 54 }; 55 55 56 typedef enum 57 { 58 kPseudoNormalLiveTV = 0, 59 kPseudoChangeChannel = 1, 60 kPseudoRecording = 2, 61 } PseudoState; 62 56 63 class TV : public QObject 57 64 { 58 65 Q_OBJECT … … 97 104 // Various commands 98 105 void ShowNoRecorderDialog(void); 99 106 void FinishRecording(void); 100 void AskAllowRecording(const QStringList &messages, int timeuntil);107 void AskAllowRecording(const QStringList&, int, bool); 101 108 102 109 // Boolean queries 103 110 … … 302 309 303 310 void GetPlayGroupSettings(const QString &group); 304 311 312 void SetPseudoLiveTV(uint, const ProgramInfo*, PseudoState); 313 305 314 static QStringList GetValidRecorderList(uint chanid); 306 315 static QStringList GetValidRecorderList(const QString &channum); 307 316 static QStringList GetValidRecorderList(uint, const QString&); … … 442 451 ProgramInfo *lastProgram; ///< last program played with this player 443 452 bool jumpToProgram; 444 453 454 // Recording to play next, after LiveTV 455 ProgramInfo *pseudoLiveTVRec[2]; 456 PseudoState pseudoLiveTVState[2]; 457 445 458 // Video Players 446 459 NuppelVideoPlayer *nvp; 447 460 NuppelVideoPlayer *pipnvp; -
libs/libmythtv/remoteencoder.cpp
227 227 } 228 228 } 229 229 230 void RemoteEncoder::CancelNextRecording( void)230 void RemoteEncoder::CancelNextRecording(bool cancel) 231 231 { 232 232 QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum); 233 233 strlist << "CANCEL_NEXT_RECORDING"; 234 VERBOSE(VB_IMPORTANT, QString("Sending QUERY_RECORDER %1 - CANCEL_NEXT_RECORDING") 235 .arg(recordernum)); 234 strlist << QString::number((cancel) ? 1 : 0); 236 235 237 236 SendReceiveStringList(strlist); 238 237 } -
libs/libmythtv/tv_rec.cpp
120 120 curRecording(NULL), autoRunJobs(JOB_NONE), 121 121 // Pending recording info 122 122 pendingRecording(NULL), 123 // Pseudo LiveTV recording 124 pseudoLiveTVRecording(NULL), 123 125 // tvchain 124 126 tvchain(NULL), 125 127 // RingBuffer info … … 348 350 SetFlags(kFlagAskAllowRecording); 349 351 } 350 352 353 /** \fn TVRec::SetPseudoLiveTVRecording(ProgramInfo*) 354 * \brief Sets the pseudo LiveTV ProgramInfo 355 */ 356 void TVRec::SetPseudoLiveTVRecording(ProgramInfo *pi) 357 { 358 ProgramInfo *old_rec = pseudoLiveTVRecording; 359 pseudoLiveTVRecording = pi; 360 if (old_rec) 361 delete old_rec; 362 } 363 364 /** \fn TVRec::GetRecordEndTime(const ProgramInfo*) const 365 * \brief Returns recording end time with proper post-roll 366 */ 367 QDateTime TVRec::GetRecordEndTime(const ProgramInfo *pi) const 368 { 369 bool spcat = (pi->category == overRecordCategory); 370 int secs = (spcat) ? overRecordSecCat : overRecordSecNrml; 371 return pi->recendts.addSecs(secs); 372 } 373 374 /** \fn TVRec::CancelNextRecording(bool) 375 * \brief Tells TVRec to cancel the upcoming recording. 376 * \sa RecordPending(const ProgramInfo*,int), 377 * TV::AskAllowRecording(const QStringList&,int) 378 */ 379 void TVRec::CancelNextRecording(bool cancel) 380 { 381 if (cancel) 382 SetFlags(kFlagCancelNextRecording); 383 else 384 ClearFlags(kFlagCancelNextRecording); 385 } 386 351 387 /** \fn TVRec::StartRecording(const ProgramInfo*) 352 388 * \brief Tells TVRec to Start recording the program "rcinfo" 353 389 * as soon as possible. … … 409 445 WaitForEventThreadSleep(); 410 446 411 447 // If in post-roll, end recording 412 if (GetState() == kState_RecordingOnly) 448 if (GetState() == kState_RecordingOnly && 449 !HasFlags(kFlagCancelNextRecording)) 413 450 { 414 451 stateChangeLock.unlock(); 415 452 StopRecording(); 416 453 stateChangeLock.lock(); 417 454 } 418 455 419 // Request tuner from Live TV instance420 if (internalState == kState_WatchingLiveTV &&421 !HasFlags(kFlagCancelNextRecording))422 {423 QString message = QString("QUIT_LIVETV %1").arg(cardid);424 MythEvent me(message);425 gContext->dispatch(me);426 427 MythTimer timer;428 timer.start();429 430 // Wait at least 10 seconds for response431 while ((internalState != kState_None) && timer.elapsed() < 10000)432 WaitForEventThreadSleep(false, max(10000 - timer.elapsed(), 100));433 434 // Try again435 if (internalState != kState_None)436 {437 gContext->dispatch(me);438 439 timer.restart();440 // Wait at least 10 seconds for response441 while ((internalState != kState_None) && timer.elapsed() < 10000)442 WaitForEventThreadSleep(443 false, max(10000 - timer.elapsed(), 100));444 }445 446 // Try harder447 if (internalState != kState_None)448 {449 SetFlags(kFlagExitPlayer);450 WaitForEventThreadSleep();451 }452 }453 454 456 if (internalState == kState_None) 455 457 { 456 458 if (tvchain) … … 461 463 tvchain = NULL; 462 464 } 463 465 464 // Add post-roll to new recording end time. 465 bool spcat = (rcinfo->category == overRecordCategory); 466 int secs = (spcat) ? overRecordSecCat : overRecordSecNrml; 467 recordEndTime = rcinfo->recendts.addSecs(secs); 466 recordEndTime = GetRecordEndTime(rcinfo); 468 467 469 468 // Tell event loop to begin recording. 470 469 curRecording = new ProgramInfo(*rcinfo); … … 475 474 476 475 retval = rsRecording; 477 476 } 477 else if (!HasFlags(kFlagCancelNextRecording) && 478 (GetState() == kState_WatchingLiveTV)) 479 { 480 SetPseudoLiveTVRecording(new ProgramInfo(*rcinfo)); 481 recordEndTime = GetRecordEndTime(rcinfo); 482 483 // We want the frontend to to change channel for recording 484 // and disable the UI for channel change, PiP, etc. 485 486 QString message = QString("LIVETV_WATCH %1 1").arg(cardid); 487 QStringList prog; 488 rcinfo->ToStringList(prog); 489 MythEvent me(message, prog); 490 gContext->dispatch(me); 491 492 retval = rsRecording; 493 } 478 494 else if (!HasFlags(kFlagCancelNextRecording)) 479 495 { 480 496 msg = QString("Wanted to record: %1 %2 %3 %4\n" … … 493 509 retval = rsTunerBusy; 494 510 } 495 511 496 ClearFlags(kFlagCancelNextRecording);497 498 512 WaitForEventThreadSleep(); 499 513 500 514 return retval; … … 512 526 ChangeState(RemoveRecording(GetState())); 513 527 // wait for state change to take effect 514 528 WaitForEventThreadSleep(); 529 ClearFlags(kFlagCancelNextRecording); 515 530 } 516 531 } 517 532 … … 675 690 tuningRequests.enqueue(TuningRequest(kFlagKillRec|kFlagKillRingBuffer)); 676 691 SET_NEXT(); 677 692 } 693 else if (TRANSITION(kState_WatchingLiveTV, kState_RecordingOnly)) 694 { 695 SetPseudoLiveTVRecording(NULL); 696 697 SET_NEXT(); 698 } 678 699 else if (TRANSITION(kState_None, kState_RecordingOnly)) 679 700 { 680 701 tuningRequests.enqueue(TuningRequest(kFlagRecording, curRecording)); … … 1135 1156 1136 1157 // If we have a pending recording and AskAllowRecording is set 1137 1158 // and the frontend is ready send an ASK_RECORDING query to frontend. 1138 if (pendingRecording && 1139 HasFlags(kFlagAskAllowRecording | kFlagFrontendReady)) 1159 if (pendingRecording && HasFlags(kFlagAskAllowRecording)) 1140 1160 { 1141 1161 ClearFlags(kFlagAskAllowRecording); 1142 1162 1143 int timeuntil = QDateTime::currentDateTime() 1144 .secsTo(recordPendingStart); 1163 CheckForRecGroupChange(); 1164 if (pseudoLiveTVRecording) 1165 SetFlags(kFlagCancelNextRecording); 1145 1166 1146 QString query = QString("ASK_RECORDING %1 %2") 1147 .arg(cardid).arg(timeuntil); 1148 QStringList messages; 1149 messages << pendingRecording->title 1150 << pendingRecording->chanstr 1151 << pendingRecording->chansign 1152 << pendingRecording->channame; 1153 1154 MythEvent me(query, messages); 1167 if (GetState() == kState_WatchingLiveTV) 1168 { 1169 int timeuntil = QDateTime::currentDateTime() 1170 .secsTo(recordPendingStart); 1155 1171 1156 gContext->dispatch(me); 1172 QString query = QString("ASK_RECORDING %1 %2 %3") 1173 .arg(cardid).arg(timeuntil) 1174 .arg(pseudoLiveTVRecording ? 1 : 0); 1175 VERBOSE(VB_IMPORTANT, LOC + query); 1176 QStringList messages; 1177 messages << pendingRecording->title 1178 << pendingRecording->chanstr 1179 << pendingRecording->chansign 1180 << pendingRecording->channame; 1181 MythEvent me(query, messages); 1182 gContext->dispatch(me); 1183 } 1157 1184 } 1158 1185 1159 1186 // If we are recording a program, check if the recording is … … 1169 1196 if (curRecording) 1170 1197 curRecording->UpdateInUseMark(); 1171 1198 1172 if (GetState() == kState_WatchingLiveTV && curRecording && 1173 !pendingRecording) 1199 if (GetState() == kState_WatchingLiveTV) 1174 1200 { 1175 if (QDateTime::currentDateTime() >= curRecording->endts) // change to curRecording->recstartts.addSecs(60) for testing 1176 SwitchLiveTVRingBuffer(); 1201 bool enable_livetv_ui = false; 1202 if (pseudoLiveTVRecording && 1203 (QDateTime::currentDateTime() > recordEndTime || 1204 HasFlags(kFlagFinishRecording))) 1205 { 1206 SetPseudoLiveTVRecording(NULL); 1207 enable_livetv_ui = true; 1208 } 1209 else if (curRecording && 1210 !pseudoLiveTVRecording && !pendingRecording) 1211 { 1212 //#define TESTING_RING_BUFFER_SWITCHING 1213 #ifdef TESTING_RING_BUFFER_SWITCHING 1214 if ((QDateTime::currentDateTime() >= 1215 curRecording->recstartts.addSecs(60))) 1216 #else 1217 if ((QDateTime::currentDateTime() >= curRecording->endts)) 1218 #endif 1219 { 1220 SwitchLiveTVRingBuffer(); 1221 enable_livetv_ui = true; 1222 } 1223 } 1224 if (enable_livetv_ui) 1225 { 1226 VERBOSE(VB_IMPORTANT, LOC + "Enabling Full LiveTV UI."); 1227 QString message = QString("LIVETV_WATCH %1 0").arg(cardid); 1228 MythEvent me(message); 1229 gContext->dispatch(me); 1230 } 1177 1231 } 1178 1232 1179 1233 // Check for ExitPlayer flag, and if set change to a non-watching … … 2459 2513 return ""; 2460 2514 } 2461 2515 2462 /** \fn TVRec::StopLiveTV() 2516 /** \fn TVRec::CheckForRecGroupChange(void) 2517 * \brief Check if frontend changed the recording group. 2518 * 2519 * This is needed because the frontend may toggle whether something 2520 * should be kept as a recording in the frontend, but this class may 2521 * not find out about it in time unless we check the DB when this 2522 * information is important. 2523 */ 2524 void TVRec::CheckForRecGroupChange(void) 2525 { 2526 QMutexLocker lock(&stateChangeLock); 2527 2528 if (internalState == kState_None) 2529 return; // already stopped 2530 2531 ProgramInfo *pi = NULL; 2532 if (curRecording) 2533 { 2534 pi = ProgramInfo::GetProgramFromRecorded( 2535 curRecording->chanid, curRecording->recstartts); 2536 } 2537 2538 if (pi && pi->recgroup != "LiveTV" && !pseudoLiveTVRecording) 2539 { 2540 // User wants this recording to continue 2541 SetPseudoLiveTVRecording(pi); 2542 pi = NULL; 2543 } 2544 else if (pi->recgroup == "LiveTV" && pseudoLiveTVRecording) 2545 { 2546 // User wants to abandon scheduled recording 2547 SetPseudoLiveTVRecording(NULL); 2548 } 2549 2550 if (pi) 2551 delete pi; 2552 } 2553 2554 /** \fn TVRec::StopLiveTV(void) 2463 2555 * \brief Tells TVRec to stop a "Live TV" recorder. 2464 2556 * \sa EncoderLink::StopLiveTV(), RemoteEncoder::StopLiveTV() 2465 2557 */ 2466 2558 void TVRec::StopLiveTV(void) 2467 2559 { 2468 if (GetState() != kState_None) 2560 QMutexLocker lock(&stateChangeLock); 2561 VERBOSE(VB_RECORD, "StopLiveTV(void) curRec: "<<curRecording 2562 <<" pseudoRec: "<<pseudoLiveTVRecording); 2563 2564 if (internalState == kState_None) 2565 return; // already stopped 2566 2567 CheckForRecGroupChange(); 2568 2569 // Figure out next state and if needed recording end time. 2570 TVState next_state = kState_None; 2571 bool has_cancel = true; 2572 if (pseudoLiveTVRecording) 2469 2573 { 2470 QMutexLocker lock(&stateChangeLock);2471 ChangeState(kState_None);2472 // Wait for state change to take effect...2473 WaitForEventThreadSleep();2574 recordEndTime = GetRecordEndTime(pseudoLiveTVRecording); 2575 next_state = kState_RecordingOnly; 2576 has_cancel = HasFlags(kFlagCancelNextRecording); 2577 } 2474 2578 2475 tvchain = NULL; 2476 } 2579 // Change to the appropriate state 2580 ChangeState(next_state); 2581 2582 // Wait for state change to take effect... 2583 WaitForEventThreadSleep(); 2584 2585 if (has_cancel) 2586 SetFlags(kFlagCancelNextRecording); 2587 2588 // We are done with the tvchain... 2589 tvchain = NULL; 2477 2590 } 2478 2591 2479 2592 /** \fn TVRec::PauseRecorder(void) … … 3069 3182 { 3070 3183 // We need there to be a ringbuffer for these modes 3071 3184 bool ok; 3185 ProgramInfo *tmp = pseudoLiveTVRecording; 3186 pseudoLiveTVRecording = NULL; 3072 3187 if (!ringBuffer) 3073 3188 ok = CreateLiveTVRingBuffer(); 3074 3189 else 3075 3190 ok = SwitchLiveTVRingBuffer(true, false); 3191 pseudoLiveTVRecording = tmp; 3076 3192 if (!ok) 3077 3193 { 3078 3194 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create RingBuffer 1"); … … 3450 3566 // Some recorders unpause on Reset, others do not... 3451 3567 recorder->Unpause(); 3452 3568 3569 if (pseudoLiveTVRecording) 3570 { 3571 ProgramInfo *rcinfo1 = pseudoLiveTVRecording; 3572 QString msg1 = QString("Recording: %1 %2 %3 %4") 3573 .arg(rcinfo1->title).arg(rcinfo1->chanid) 3574 .arg(rcinfo1->recstartts.toString()) 3575 .arg(rcinfo1->recendts.toString()); 3576 ProgramInfo *rcinfo2 = tvchain->GetProgramAt(-1); 3577 QString msg2 = QString("Recording: %1 %2 %3 %4") 3578 .arg(rcinfo2->title).arg(rcinfo2->chanid) 3579 .arg(rcinfo2->recstartts.toString()) 3580 .arg(rcinfo2->recendts.toString()); 3581 delete rcinfo2; 3582 VERBOSE(VB_RECORD, LOC + "Pseudo LiveTV recording starting." + 3583 "\n\t\t\t" + msg1 + "\n\t\t\t" + msg2); 3584 3585 int autoexpiredef = gContext->GetNumSetting("AutoExpireDefault", 0); 3586 curRecording->SetAutoExpire(autoexpiredef); 3587 curRecording->ApplyRecordRecGroupChange("Default"); 3588 } 3589 3453 3590 ClearFlags(kFlagNeedToStartRecorder); 3454 3591 } 3455 3592 … … 3578 3715 } 3579 3716 3580 3717 QString chanids = QString::number(chanid); 3581 ProgramInfo *prog = ProgramInfo::GetProgramAtDateTime(chanids,3582 mythCurrentDateTime(),3583 true);3584 3718 3719 ProgramInfo *prog = NULL; 3720 if (pseudoLiveTVRecording) 3721 prog = new ProgramInfo(*pseudoLiveTVRecording); 3722 else 3723 prog = ProgramInfo::GetProgramAtDateTime( 3724 chanids, mythCurrentDateTime(), true); 3725 3585 3726 if (prog->recstartts == prog->recendts) 3586 3727 { 3587 3728 VERBOSE(VB_IMPORTANT, LOC_ERR + "GetProgramRingBufferForLiveTV()" -
libs/libmythtv/osd.cpp
1676 1676 } 1677 1677 1678 1678 void OSD::NewDialogBox(const QString &name, const QString &message, 1679 QStringList &options, int length) 1679 QStringList &options, int length, 1680 int initial_selection) 1680 1681 { 1681 1682 osdlock.lock(); 1682 1683 OSDSet *container = GetSet(name); … … 1716 1717 while (text); 1717 1718 1718 1719 int numoptions = options.size(); 1720 int offset = availoptions - numoptions; 1721 initial_selection = max(min(numoptions - 1, initial_selection), 0); 1719 1722 1720 1723 for (int i = 1; i <= numoptions && i <= availoptions; i++) 1721 1724 { 1722 QString name = QString("option%1").arg( availoptions - numoptions+ i);1725 QString name = QString("option%1").arg(offset + i); 1723 1726 text = (OSDTypeText *)container->GetType(name); 1724 1727 if (!text) 1725 1728 { … … 1740 1743 return; 1741 1744 } 1742 1745 1743 opr->SetOffset( availoptions - numoptions);1744 opr->SetPosition( 0);1746 opr->SetOffset(offset); 1747 opr->SetPosition(initial_selection); 1745 1748 1746 1749 dialogResponseList[name] = 0; 1747 1750 1748 HighlightDialogSelection(container, availoptions - numoptions);1751 HighlightDialogSelection(container, offset + initial_selection); 1749 1752 1750 1753 if (length > 0) 1751 1754 container->DisplayFor(length * 1000000); -
libs/libmythtv/tv_rec.h
144 144 void FinishRecording(void) { SetFlags(kFlagFinishRecording); } 145 145 /// \brief Tells TVRec that the frontend's TV class is ready for messages. 146 146 void FrontendReady(void) { SetFlags(kFlagFrontendReady); } 147 /** \brief Tells TVRec to cancel the upcoming recording. 148 * \sa RecordPending(const ProgramInfo*,int), 149 * TV::AskAllowRecording(const QStringList&,int) */ 150 void CancelNextRecording(void) { SetFlags(kFlagCancelNextRecording); } 147 void CancelNextRecording(bool cancel); 151 148 ProgramInfo *GetRecording(void); 152 149 153 150 /// \brief Returns true if event loop has not been told to shut down … … 234 231 235 232 private: 236 233 void SetRingBuffer(RingBuffer *); 234 void SetPseudoLiveTVRecording(ProgramInfo*); 237 235 void TeardownAll(void); 238 236 239 237 static bool GetDevices(int cardid, … … 290 288 291 289 void StartedRecording(ProgramInfo*); 292 290 void FinishedRecording(ProgramInfo*); 291 QDateTime GetRecordEndTime(const ProgramInfo*) const; 292 void CheckForRecGroupChange(void); 293 293 294 294 void SetOption(RecordingProfile &profile, const QString &name); 295 295 … … 349 349 ProgramInfo *pendingRecording; 350 350 QDateTime recordPendingStart; 351 351 352 // Pseudo LiveTV recording 353 ProgramInfo *pseudoLiveTVRecording; 354 352 355 // LiveTV file chain 353 356 LiveTVChain *tvchain; 354 357 -
libs/libmyth/mythcontext.h
221 221 * You must also update this value in 222 222 * mythplugins/mythweb/includes/mythbackend.php 223 223 */ 224 #define MYTH_PROTO_VERSION "2 2"224 #define MYTH_PROTO_VERSION "23" 225 225 226 226 /** \class MythContext 227 227 * \brief This class contains the runtime context for MythTV. -
programs/mythbackend/encoderlink.h
62 62 void StopRecording(void); 63 63 void FinishRecording(void); 64 64 void FrontendReady(void); 65 void CancelNextRecording( void);65 void CancelNextRecording(bool); 66 66 bool WouldConflict(const ProgramInfo *rec); 67 67 68 68 bool IsReallyRecording(void); -
programs/mythbackend/mainserver.cpp
2420 2420 } 2421 2421 else if (command == "CANCEL_NEXT_RECORDING") 2422 2422 { 2423 VERBOSE(VB_IMPORTANT, "Received: CANCEL_NEXT_RECORDING"); 2424 enc->CancelNextRecording(); 2423 QString cancel = slist[2]; 2424 VERBOSE(VB_IMPORTANT, "Received: CANCEL_NEXT_RECORDING "<<cancel); 2425 enc->CancelNextRecording(cancel == "1"); 2425 2426 retlist << "ok"; 2426 2427 } 2427 2428 else if (command == "SPAWN_LIVETV") … … 3596 3597 for (; iter != encoderList->end(); ++iter) 3597 3598 { 3598 3599 EncoderLink *elink = iter.data(); 3599 elink->CancelNextRecording( );3600 elink->CancelNextRecording(true); 3600 3601 ProgramInfo *pinfo = elink->GetRecording(); 3601 3602 pinfo->ToStringList(strlist); 3602 3603 delete pinfo; -
programs/mythbackend/encoderlink.cpp
203 203 * \brief Tells TVRec there is a pending recording "rec" in "secsleft" seconds. 204 204 * \param rec Recording to make. 205 205 * \param secsleft Seconds to wait before starting recording. 206 * \sa StartRecording(const ProgramInfo*), CancelNextRecording( )206 * \sa StartRecording(const ProgramInfo*), CancelNextRecording(bool) 207 207 */ 208 208 void EncoderLink::RecordPending(const ProgramInfo *rec, int secsleft) 209 209 { … … 568 568 VERBOSE(VB_IMPORTANT, "Should be local only query: FrontendReady"); 569 569 } 570 570 571 /** \fn EncoderLink::CancelNextRecording( )571 /** \fn EncoderLink::CancelNextRecording(bool) 572 572 * \brief Tells TVRec to cancel the next recording. 573 573 * <b>This only works on local recorders.</b> 574 574 * … … 577 577 * 578 578 * \sa RecordPending(const ProgramInfo*,int) 579 579 */ 580 void EncoderLink::CancelNextRecording( void)580 void EncoderLink::CancelNextRecording(bool cancel) 581 581 { 582 582 if (local) 583 tv->CancelNextRecording( );583 tv->CancelNextRecording(cancel); 584 584 else 585 585 VERBOSE(VB_IMPORTANT, "Should be local only query: CancelNextRecording"); 586 586 }