Ticket #2287: multi-pip-v1.patch
File multi-pip-v1.patch, 140.6 KB (added by , 17 years ago) |
---|
-
libs/libmythtv/NuppelVideoPlayer.cpp
214 214 audio_channels(2), audio_bits(-1), 215 215 audio_samplerate(44100), audio_stretchfactor(1.0f), 216 216 audio_codec(NULL), 217 // Picture-in-Picture 218 pip player(NULL), setpipplayer(NULL), needsetpipplayer(false),217 // Picture-in-Picture stuff 218 pip_active(false), 219 219 // Preview window support 220 220 argb_buf(NULL), argb_size(0,0), 221 221 yuv2argb_conv(yuv2rgb_init_mmx(32, MODE_RGB)), … … 2467 2467 player_ctx->buffer->DVD()->InStillFrame() && 2468 2468 videoOutput->ValidVideoFrames() < 3) 2469 2469 { 2470 videoOutput->ProcessFrame(buffer, NULL, NULL, pipplayer); 2470 videoOutput->ProcessFrame( 2471 buffer, NULL, NULL, pip_players); 2471 2472 } 2472 2473 else 2473 2474 { 2474 2475 videoOutput->ProcessFrame( 2475 buffer, osd, videoFilters, pipplayer); 2476 buffer, osd, videoFilters, 2477 pip_players); 2476 2478 } 2477 2479 videofiltersLock.unlock(); 2478 2480 } … … 2632 2634 DisplayDVDButton(); 2633 2635 2634 2636 videofiltersLock.lock(); 2635 videoOutput->ProcessFrame(NULL, osd, videoFilters, pip player);2637 videoOutput->ProcessFrame(NULL, osd, videoFilters, pip_players); 2636 2638 videofiltersLock.unlock(); 2637 2639 2638 2640 videoOutput->PrepareFrame(NULL, kScan_Ignore); … … 2857 2859 player_ctx->buffer->DVD()->InStillFrame() && 2858 2860 videoOutput->ValidVideoFrames() < 3) 2859 2861 { 2860 videoOutput->ProcessFrame(frame, NULL, NULL, pip player);2862 videoOutput->ProcessFrame(frame, NULL, NULL, pip_players); 2861 2863 } 2862 2864 else 2863 videoOutput->ProcessFrame(frame, osd, videoFilters, pipplayer); 2865 { 2866 videoOutput->ProcessFrame(frame, osd, videoFilters, pip_players); 2867 } 2864 2868 videofiltersLock.unlock(); 2865 2869 2866 2870 if (audioOutput && !audio_paused && audioOutput->IsPaused()) … … 2953 2957 2954 2958 while (!killvideo) 2955 2959 { 2956 if (needsetpipplayer) 2957 { 2958 pipplayer = setpipplayer; 2959 needsetpipplayer = false; 2960 PIPState state = player_ctx->GetPIPState(); 2961 if (m_tv && (state == kPIPOff || state == kPBPLeft)) 2962 m_tv->WakeSetPIPPlayerCond(); 2963 if (videoOutput) 2964 videoOutput->PadPIPImage(false); 2965 } 2960 HandlePIPPlayerLists(4); 2966 2961 2967 2962 if (player_ctx->buffer->isDVD()) 2968 2963 { … … 3045 3040 3046 3041 while (!killvideo) 3047 3042 { 3048 if (needsetpipplayer) 3049 { 3050 pipplayer = setpipplayer; 3051 needsetpipplayer = false; 3052 } 3043 HandlePIPPlayerLists(1); 3053 3044 3054 3045 resetvideo = false; 3055 3046 SetVideoActuallyPaused(pausevideo); … … 3057 3048 if (pausevideo) 3058 3049 { 3059 3050 videofiltersLock.lock(); 3060 videoOutput->ProcessFrame(NULL, osd, videoFilters, pip player);3051 videoOutput->ProcessFrame(NULL, osd, videoFilters, pip_players); 3061 3052 videofiltersLock.unlock(); 3062 3053 } 3063 3054 else … … 3067 3058 ShowText(); 3068 3059 3069 3060 videofiltersLock.lock(); 3070 videoOutput->ProcessFrame(NULL, osd, videoFilters, pip player);3061 videoOutput->ProcessFrame(NULL, osd, videoFilters, pip_players); 3071 3062 videofiltersLock.unlock(); 3072 3063 } 3073 3064 … … 3249 3240 } 3250 3241 else 3251 3242 { 3243 if (player_ctx) 3244 player_ctx->SetNVPChangingBuffers(true); 3252 3245 GetDecoder()->SetReadAdjust(player_ctx->buffer->SetAdjustFilesize()); 3253 3246 GetDecoder()->SetWaitForChange(); 3254 if (m_tv && player_ctx && !player_ctx->isPIP())3255 m_tv->SetIgnoreKeys(true);3256 3247 } 3257 3248 3258 3249 delete pginfo; … … 3292 3283 3293 3284 player_ctx->buffer->Unpause(); 3294 3285 3295 if (m_tv && player_ctx && !player_ctx->isPIP()) 3296 m_tv->SetIgnoreKeys(false); 3286 player_ctx->SetNVPChangingBuffers(false); 3297 3287 3298 3288 player_ctx->LockPlayingInfo(__FILE__, __LINE__); 3299 3289 player_ctx->tvchain->SetProgram(*player_ctx->playingInfo); … … 3866 3856 GetDecoder()->setTranscoding(value); 3867 3857 }; 3868 3858 3859 bool NuppelVideoPlayer::AddPIPPlayer( 3860 NuppelVideoPlayer *pip, PIPLocation loc, uint timeout) 3861 { 3862 QMutexLocker locker(&pip_players_lock); 3863 pip_players_add[pip] = loc; 3864 3865 pip_players_wait.wait(&pip_players_lock, timeout); 3866 3867 if (pip_players.find(pip) != pip_players.end()) 3868 return true; 3869 3870 PIPMap::iterator it = pip_players_add.find(pip); 3871 if (it != pip_players_add.end()) 3872 pip_players_add.erase(it); 3873 3874 return false; 3875 } 3876 3877 bool NuppelVideoPlayer::RemovePIPPlayer(NuppelVideoPlayer *pip, uint timeout) 3878 { 3879 QMutexLocker locker(&pip_players_lock); 3880 3881 pip_players_rm[pip] = kPIP_END; 3882 3883 pip_players_wait.wait(&pip_players_lock, timeout); 3884 3885 if (pip_players.find(pip) == pip_players.end()) 3886 return true; 3887 3888 PIPMap::iterator it = pip_players_rm.find(pip); 3889 if (it != pip_players_rm.end()) 3890 pip_players_rm.erase(it); 3891 3892 return false; 3893 } 3894 3895 void NuppelVideoPlayer::HandlePIPPlayerLists(uint max_cnt) 3896 { 3897 QMutexLocker locker(&pip_players_lock); 3898 PIPMap::const_iterator it = pip_players_rm.begin(); 3899 for (; it != pip_players_rm.end(); ++it) 3900 { 3901 PIPMap::iterator it2 = pip_players.find(it.key()); 3902 if (it2 != pip_players.end()) 3903 pip_players.erase(it2); 3904 } 3905 3906 for (it = pip_players_add.begin(); 3907 (it != pip_players_add.end()) && 3908 ((uint)pip_players.size() <= max_cnt); ++it) 3909 { 3910 if (pip_players.find(it.key()) == pip_players.end() && 3911 pip_players_rm.find(it.key()) == pip_players_rm.end()) 3912 { 3913 pip_players[it.key()] = *it; 3914 } 3915 } 3916 pip_players_add.clear(); 3917 pip_players_rm.clear(); 3918 pip_players_wait.wakeAll(); 3919 } 3920 3921 PIPLocation NuppelVideoPlayer::GetNextPIPLocation(void) const 3922 { 3923 QMutexLocker locker(&pip_players_lock); 3924 PIPMap sim_pip_players = pip_players; 3925 3926 PIPMap::const_iterator it = pip_players_rm.begin(); 3927 for (; it != pip_players_rm.end(); ++it) 3928 { 3929 PIPMap::iterator it2 = sim_pip_players.find(it.key()); 3930 if (it2 != sim_pip_players.end()) 3931 sim_pip_players.erase(it2); 3932 } 3933 3934 for (it = pip_players_add.begin(); it != pip_players_add.end(); ++it) 3935 { 3936 if (sim_pip_players.find(it.key()) == sim_pip_players.end() && 3937 pip_players_rm.find(it.key()) == pip_players_rm.end()) 3938 { 3939 sim_pip_players[it.key()] = *it; 3940 } 3941 } 3942 3943 // order of preference, could be stored in db if we want it configurable 3944 PIPLocation ols[] = 3945 { kPIPTopLeft, kPIPTopRight, kPIPBottomLeft, kPIPBottomRight }; 3946 3947 for (uint i = 0; i < sizeof(ols)/sizeof(PIPLocation); i++) 3948 { 3949 PIPMap::const_iterator it = sim_pip_players.begin(); 3950 for (; it != sim_pip_players.end() && (*it != ols[i]); ++it); 3951 3952 if (it == sim_pip_players.end()) 3953 return ols[i]; 3954 } 3955 3956 return kPIP_END; 3957 } 3958 3869 3959 void NuppelVideoPlayer::WrapTimecode(long long &timecode, TCTypes tc_type) 3870 3960 { 3871 3961 if ((tc_type == TC_AUDIO) && (tc_wrap[TC_AUDIO] == LONG_LONG_MIN)) -
libs/libmythtv/videooutwindow.cpp
54 54 VideoOutWindow::VideoOutWindow() : 55 55 // DB settings 56 56 db_move(0, 0), db_scale_horiz(0.0f), db_scale_vert(0.0f), 57 db_pip_ location(kPIPTopLeft), db_pip_size(26),57 db_pip_size(26), 58 58 db_scaling_allowed(true), 59 59 60 60 // Manual Zoom … … 82 82 embedding(false), needrepaint(false), 83 83 allowpreviewepg(true), pip_state(kPIPOff) 84 84 { 85 db_pip_location = (PIPLocation) gContext->GetNumSetting(86 "PIPLocation", (int) kPIPTopLeft);87 88 85 db_pip_size = gContext->GetNumSetting("PIPSize", 26); 89 86 90 87 db_move = QPoint(gContext->GetNumSetting("xScanDisplacement", 0), … … 732 729 * \brief Determines PIP Window size and Position. 733 730 */ 734 731 QRect VideoOutWindow::GetPIPRect( 735 intlocation, NuppelVideoPlayer *pipplayer, bool do_pixel_adj) const732 PIPLocation location, NuppelVideoPlayer *pipplayer, bool do_pixel_adj) const 736 733 { 737 734 QRect position; 738 735 -
libs/libmythtv/osdlistbtntype.cpp
682 682 m_initialized = true; 683 683 } 684 684 685 #include <cassert> 685 686 void OSDListBtnType::InitItem( 686 687 OSDTypeImage &osdImg, uint width, uint height, 687 688 QColor beg, QColor end, int alpha) … … 698 699 *ptr = black; 699 700 for (uint y = 1; y < height - 1; y++) 700 701 { 702 if ((((uchar*)ptr)-data) >= 4 * width * height) 703 break; 704 705 assert((((uchar*)ptr)-data) < 4 * width * height); 706 *ptr = black; ptr++; 707 701 708 int r = (int) (beg.red() + (y * rstep)); 702 709 int g = (int) (beg.green() + (y * gstep)); 703 710 int b = (int) (beg.blue() + (y * bstep)); 704 711 uint32_t color = qRgba(r,g,b,alpha); 705 *ptr = black; ptr++; 706 for (uint x = 1; x < width - 1; x++, ptr++) 712 for (uint x = 1; 713 (x < width - 1) && ((((uchar*)ptr)-data) < 4 * width * height); 714 x++, ptr++) 715 { 716 assert((((uchar*)ptr)-data) < 4 * width * height); 707 717 *ptr = color; 718 } 719 720 if ((((uchar*)ptr)-data) >= 4 * width * height) 721 break; 722 723 assert((((uchar*)ptr)-data) < 4 * width * height); 708 724 *ptr = black; ptr++; 709 725 } 710 for (uint x = 0; x < width; x++, ptr++) 711 *ptr = black; 726 if ((((uchar*)ptr)-data) < 4 * width * height) 727 { 728 for (uint x = 0; x < width; x++, ptr++) 729 { 730 assert((((uchar*)ptr)-data) < 4 * width * height); 731 *ptr = black; 732 } 733 } 712 734 713 735 { 714 736 QImage img; -
libs/libmythtv/avformatdecoder.cpp
902 902 if (!fmt) 903 903 { 904 904 VERBOSE(VB_IMPORTANT, LOC_ERR + 905 QString("Probe failed for file: \"%1\".").arg(filename)); 905 QString("Probe failed for file: '%1' probe size %2.") 906 .arg(filename).arg(probe.buf_size)); 906 907 return -1; 907 908 } 909 VERBOSE(VB_PLAYBACK, LOC + 910 QString("Probe suceeded for file: '%1' probe size %2.") 911 .arg(filename).arg(probe.buf_size)); 908 912 909 913 fmt->flags |= AVFMT_NOFILE; 910 914 -
libs/libmythtv/tv_play.h
149 149 150 150 // LiveTV commands 151 151 bool LiveTV(bool showDialogs = true, bool startInGuide = false); 152 /// This command is used to exit the player in order to record using153 /// the recording being used by LiveTV.154 void StopLiveTV(void) { SetExitPlayer(true, true); }155 152 156 153 // Embedding commands for the guidegrid to use in LiveTV 157 154 void EmbedOutput(PlayerContext*, WId wid, int x, int y, int w, int h); … … 183 180 bool IsBookmarkAllowed(const PlayerContext*) const; 184 181 bool IsDeleteAllowed(const PlayerContext*) const; 185 182 186 bool CreatePBP(PlayerContext *, const ProgramInfo *info);187 bool CreatePIP(PlayerContext *, const ProgramInfo *info);188 voidResizePIPWindow(PlayerContext*);183 bool CreatePBP(PlayerContext *lctx, const ProgramInfo *info); 184 bool CreatePIP(PlayerContext *lctx, const ProgramInfo *info); 185 bool ResizePIPWindow(PlayerContext*); 189 186 bool IsPIPSupported(const PlayerContext *ctx = NULL) const; 190 187 191 188 // Boolean queries … … 237 234 bool inPlaylist = false, bool initByNetworkCommand = false); 238 235 static void SetFuncPtr(const char *, void *); 239 236 240 void SetIgnoreKeys(bool ignore) { ignoreKeys = ignore; }241 242 237 // Used by EPG 243 238 void ChangeVolume(PlayerContext*, bool up); 244 239 void ToggleMute(PlayerContext*); 245 240 246 void WakeSetPIPPlayerCond(void); 247 void SetNextProgPIPState(PIPState state) { nextProgPIPState = state; } 241 void SetNextProgPIPState(PIPState state) { jumpToProgramPIPState = state; } 248 242 249 243 // Used for UDPNotify 250 244 bool HasUDPNotifyEvent(void) const; … … 275 269 static EMBEDRETURNVOID RunViewScheduledPtr; 276 270 277 271 private: 278 void SetActive(PlayerContext * , int index);272 void SetActive(PlayerContext *lctx, int index, bool osd_msg); 279 273 280 274 PlayerContext *GetPlayerWriteLock( 281 275 int which, const char *file, int location); … … 296 290 297 291 int StartTimer(int interval, int line); 298 292 void KillTimer(int id); 299 void ForceNextStateNone(PlayerContext* );293 void ForceNextStateNone(PlayerContext*, int line); 300 294 void ScheduleStateChange(PlayerContext*); 301 295 void SetErrored(PlayerContext*); 302 void SetExitPlayer (bool set_it, bool wants_to) const;296 void SetExitPlayerReal(bool set_it, bool wants_to, int line) const; 303 297 void SetUpdateOSDPosition(bool set_it); 304 298 305 bool P IPHandleAction(PlayerContext*,const QStringList &actions);299 bool PxPHandleAction(PlayerContext*,const QStringList &actions); 306 300 bool ToggleHandleAction(PlayerContext*, 307 301 const QStringList &actions, bool isDVD); 308 302 bool FFRewHandleAction(PlayerContext*, const QStringList &actions); 309 303 bool ActivePostQHandleAction(PlayerContext*, 310 304 const QStringList &actions, bool isDVD); 305 bool HandleJumpToProgramAction(PlayerContext *ctx, 306 const QStringList &actions); 311 307 312 308 bool RequestNextRecorder(PlayerContext *, bool); 313 309 void DeleteRecorder(); … … 421 417 const QStringList &actions); 422 418 423 419 void DoDisplayJumpMenu(void); 424 void SetJumpToProgram(QString progKey = "", int progIndex = 0);425 420 426 421 bool ClearOSD(const PlayerContext*); 427 422 void ToggleOSD(const PlayerContext*, bool includeStatusOSD); … … 441 436 int editType = kScheduleProgramGuide); 442 437 443 438 void TeardownPlayer(PlayerContext *mctx, PlayerContext *ctx); 444 void TeardownPBP(PlayerContext*);445 439 446 440 void HandleStateChange(PlayerContext *mctx, PlayerContext *ctx); 447 441 448 442 bool StartPlayer(PlayerContext *mctx, PlayerContext *ctx, 449 TVState desiredState, bool ispip = false); 450 bool StartPIPPlayer(PlayerContext *mctx, PlayerContext *pipctx, 451 TVState desiredState); 452 void SetPIPPlayer(PlayerContext *mctx, PlayerContext *pipctx); 453 void TogglePIPView(PlayerContext*, bool ispbp = false); 454 void ToggleActiveWindow(PlayerContext*, int ctx_index); 455 void SwapPIP(PlayerContext *lctx, int ctx_index, bool ispbp); 456 void TogglePIPState(PlayerContext*, PIPState changeTo); 457 void RestartPIPWindows(PlayerContext *lctx, const vector<long long> &pos, 458 MuteState mctx_mute); 459 void TeardownPIPWindows(PlayerContext*); 443 TVState desiredState); 460 444 445 vector<long long> TeardownAllNVPs(PlayerContext*); 446 void RestartAllNVPs(PlayerContext *lctx, 447 const vector<long long> &pos, 448 MuteState mctx_mute); 449 450 void PxPToggleView( PlayerContext *actx, bool wantPBP); 451 void PxPCreateView( PlayerContext *actx, bool wantPBP); 452 void PxPTeardownView(PlayerContext *actx); 453 void PxPToggleType( PlayerContext *mctx, bool wantPBP); 454 void PxPSwap( PlayerContext *mctx, int ctx_index = -1); 455 bool HandlePxPTimerEvent(void); 456 457 bool PIPAddPlayer( PlayerContext *mctx, PlayerContext *ctx); 458 bool PIPRemovePlayer(PlayerContext *mctx, PlayerContext *ctx); 459 void PBPRestartMainNVP(PlayerContext *mctx); 460 461 461 void ToggleAutoExpire(PlayerContext*); 462 462 463 463 void BrowseStart(PlayerContext*); … … 478 478 479 479 void BuildOSDTreeMenu(const PlayerContext*); 480 480 void ShowOSDTreeMenu(const PlayerContext*); 481 void FillMenuPxP(const PlayerContext*, OSDGenericTree *treeMenu, 482 bool freeRecorders); 481 483 void FillMenuLiveTV(OSDGenericTree *treeMenu); 482 484 void FillMenuPlaying(const PlayerContext*, OSDGenericTree *treeMenu); 483 485 … … 508 510 void IdleDialogTimeout(void); 509 511 510 512 // Program jumping stuff 511 void setLastProgram(ProgramInfo *rcinfo);512 ProgramInfo * getLastProgram(void) { return lastProgram; }513 void SetLastProgram(ProgramInfo *rcinfo); 514 ProgramInfo *GetLastProgram(void) const; 513 515 514 516 static bool LoadExternalSubtitles(NuppelVideoPlayer *nvp, 515 517 const QString &videoFile); … … 536 538 QString db_time_format; 537 539 QString db_short_date_format; 538 540 uint db_idle_timeout; 541 uint db_udpnotify_port; 542 int db_playback_exit_prompt; 543 int db_autoexpire_default; 539 544 bool db_auto_set_watched; 540 545 bool db_end_of_rec_exit_prompt; 546 bool db_jump_prefer_osd; 547 bool db_use_gui_size_for_tv; 548 bool db_start_in_guide; 549 bool db_toggle_bookmark; 550 bool db_run_jobs_on_remote; 551 bool db_use_dvd_bookmark; 552 bool db_continue_embedded; 553 bool db_use_fixed_size; 554 541 555 bool smartChannelChange; 542 556 bool MuteIndividualChannels; 543 557 bool arrowAccel; … … 581 595 QMap<QString,AskProgramInfo> askAllowPrograms; 582 596 QMutex askAllowLock; 583 597 584 bool ignoreKeys; 585 PIPState needToMakePIPChange; 586 PIPState nextProgPIPState; 598 MythDeque<QString> changePxP; 599 QMutex progListsLock; 587 600 QMap<QString,ProgramList> progLists; 588 601 589 602 mutable QMutex chanEditMapLock; ///< Lock for chanEditMap and ddMap … … 638 651 639 652 // Program Info for currently playing video 640 653 // (or next video if InChangeState() is true) 654 mutable QMutex lastProgramLock; 641 655 ProgramInfo *lastProgram; ///< last program played with this player 642 bool jumpToProgram;643 644 656 bool inPlaylist; ///< show is part of a playlist 645 657 bool underNetworkControl; ///< initial show started via by the network control interface 646 658 bool isnearend; 647 659 660 // Program Jumping 661 PIPState jumpToProgramPIPState; 662 bool jumpToProgram; 663 648 664 // Video Players 649 665 vector<PlayerContext*> player; 650 666 /// Video Player to which events are sent to 651 667 int playerActive; 652 668 /// lock on player and playerActive changes 653 669 mutable QReadWriteLock playerLock; 654 QWaitCondition pipPlayerSetCondition;655 670 656 671 // Remote Encoders 657 672 /// Main recorder to use after a successful SwitchCards() call. … … 740 755 static const uint kInputKeysMax; ///< When to start discarding early keys 741 756 static const uint kNextSource; 742 757 static const uint kPreviousSource; 758 static const uint kMaxPIPCount; 759 static const uint kMaxPBPCount; 743 760 744 761 ///< Timeout for entry modes in msec 745 762 static const uint kInputModeTimeout; -
libs/libmythtv/videoout_ivtv.h
32 32 void UpdatePauseFrame(void); 33 33 void ProcessFrame(VideoFrame *frame, OSD *osd, 34 34 FilterChain *filterList, 35 NuppelVideoPlayer *pipPlayer);35 const PIPMap &pipPlayers); 36 36 37 37 uint WriteBuffer(unsigned char *buf, int count); 38 38 int Poll(int delay); … … 77 77 kAlpha_Embedded 78 78 } eAlphaState; 79 79 80 void ShowPIP(VideoFrame *frame, NuppelVideoPlayer *pipplayer );80 void ShowPIP(VideoFrame *frame, NuppelVideoPlayer *pipplayer, PIPLocation); 81 81 void SetAlpha(eAlphaState newAlpha); 82 82 void SetColorKey(int state, int color); 83 83 long long GetFirmwareFramesPlayed(void); -
libs/libmythtv/playercontext.cpp
30 30 } 31 31 32 32 PlayerContext::PlayerContext() : 33 nvp(NULL), recorder(NULL),33 nvp(NULL), nvpUnsafe(false), recorder(NULL), 34 34 tvchain(NULL), buffer(NULL), playingInfo(NULL), 35 35 decoding(false), last_cardid(-1), last_framerate(30.0f), 36 36 // Fast forward state … … 102 102 newPlaygroup = playingInfo->playgroup; 103 103 } 104 104 105 ChangeState(newState );105 ChangeState(newState, __LINE__); 106 106 SetPlayGroup(newPlaygroup); 107 107 } 108 108 … … 141 141 if (pos > -1) 142 142 { 143 143 pipLocation = pos; 144 name = QString("pip player %1") 145 .arg(PIPLocationToString()); 144 name = QString("pip player %1").arg(toString((PIPLocation)pos)); 146 145 } 147 146 else 148 147 name = "pip player"; … … 216 215 } 217 216 } 218 217 219 QString PlayerContext::PIPLocationToString(void)220 {221 QString pipstr = QString ("Unknown PIP Location %1").arg(pipLocation);222 switch (pipLocation)223 {224 case (kPIPTopLeft):225 pipstr = "PIP: Top Left";226 break;227 case (kPIPTopRight):228 pipstr = "PIP: Top Right";229 break;230 case (kPIPBottomLeft):231 pipstr = "PIP: Bottom Left";232 break;233 case (kPIPBottomRight):234 pipstr = "PIP: Bottom Right";235 break;236 }237 238 return pipstr;239 }240 241 QString PlayerContext::PIPStateToString(void)242 {243 QString pipstr = QString("Unknown PIP State %1").arg(pipState);244 switch (pipState)245 {246 case (kPIPOff):247 pipstr = "PIP is off";248 break;249 case (kPIPonTV):250 pipstr = "PIP is visible on TV";251 break;252 case (kPIPStandAlone):253 pipstr = "Standalone PIP";254 break;255 case (kPBPLeft):256 pipstr = "Left side Picture-by-Picture";257 break;258 case (kPBPRight):259 pipstr = "Right side Picture-by-Picture";260 break;261 case (kPIPToPBP):262 pipstr = "Preparing to switch from PIP to PBP";263 break;264 case (kPBPToPIP):265 pipstr = "Preparing to switch from PBP to PIP";266 break;267 case (kPBPToggle):268 pipstr = "Disabling PBP/PIP";269 break;270 case (kPIPSwap):271 pipstr = "Swapping PBP/PIP";272 break;273 }274 275 return pipstr;276 }277 278 218 bool PlayerContext::StartPIPPlayer(TV *tv, TVState desiredState) 279 219 { 280 220 bool ok = false; … … 440 380 nvp->SetMuted(true); 441 381 442 382 int maxWait = -1; 443 if (isPIP())444 maxWait = 1000;383 //if (isPIP()) 384 // maxWait = 1000; 445 385 446 386 return StartDecoderThread(maxWait); 447 387 } … … 649 589 /** 650 590 * \brief Puts a state change on the nextState queue. 651 591 */ 652 void PlayerContext::ChangeState(TVState newState )592 void PlayerContext::ChangeState(TVState newState, int line) 653 593 { 594 VERBOSE(VB_IMPORTANT, QString("ChangeState(%1,%2)") 595 .arg(StateToString(newState)).arg(line)); 654 596 QMutexLocker locker(&stateLock); 655 597 nextState.enqueue(newState); 656 598 } … … 664 606 /** 665 607 * \brief Removes any pending state changes, and puts kState_None on the queue. 666 608 */ 667 void PlayerContext::ForceNextStateNone( void)609 void PlayerContext::ForceNextStateNone(int line) 668 610 { 611 VERBOSE(VB_IMPORTANT, QString("ForceNextStateNone(%2)").arg(line)); 669 612 QMutexLocker locker(&stateLock); 670 613 nextState.clear(); 671 614 nextState.push_back(kState_None); -
libs/libmythtv/NuppelVideoPlayer.h
149 149 void SetVideoFilters(const QString &override); 150 150 void SetFramesPlayed(long long played) { framesPlayed = played; } 151 151 void SetEof(void) { eof = true; } 152 void SetPIPPlayer(NuppelVideoPlayer *pip) 153 { setpipplayer = pip; needsetpipplayer = true; } 152 void SetPIPActive(bool is_active) { pip_active = is_active; } 153 bool AddPIPPlayer(NuppelVideoPlayer *pip, PIPLocation loc, uint timeout); 154 bool RemovePIPPlayer(NuppelVideoPlayer *pip, uint timeout); 154 155 155 156 void SetTranscoding(bool value); 156 157 void SetWatchingRecording(bool mode); … … 203 204 QString GetXDS(const QString &key) const; 204 205 QString GetErrorMsg(void) const { return errmsg; } 205 206 bool GetAudioBufferStatus(uint &fill, uint &total) const; 207 PIPLocation GetNextPIPLocation(void) const; 206 208 207 209 // Bool Gets 208 210 bool GetRawAudioState(void) const; 209 211 bool GetLimitKeyRepeat(void) const { return limitKeyRepeat; } 210 212 bool GetEof(void) const { return eof; } 211 bool PipPlayerSet(void) const { return !needsetpipplayer; }212 213 bool IsErrored(void) const { return errored; } 213 214 bool IsPlaying(uint wait_ms = 0, bool wait_for = true) const; 214 215 bool AtNormalSpeed(void) const { return next_normal_speed; } … … 218 219 bool PlayingSlowForPrebuffer(void) const { return m_playing_slower; } 219 220 bool HasAudioIn(void) const { return !no_audio_in; } 220 221 bool HasAudioOut(void) const { return !no_audio_out; } 222 bool IsPIPActive(void) const { return pip_active; } 221 223 bool IsMuted(void) const { return GetMuteState() == kMuteAll; } 222 224 bool IsIVTVDecoder(void) const; 223 225 bool UsingNullVideo(void) const { return using_null_videoout; } … … 530 532 long long GetDVDBookmark(void) const; 531 533 void SetDVDBookmark(long long frames); 532 534 535 // Private PIP stuff 536 void HandlePIPPlayerLists(uint max_pip_players); 537 533 538 private: 534 539 DecoderBase *decoder; 535 540 QMutex decoder_change_lock; … … 702 707 bool audio_passthru; 703 708 704 709 // Picture-in-Picture 705 NuppelVideoPlayer *pipplayer; 706 NuppelVideoPlayer *setpipplayer; 707 bool needsetpipplayer; 710 mutable QMutex pip_players_lock; 711 QWaitCondition pip_players_wait; 712 PIPMap pip_players; 713 PIPMap pip_players_add; 714 PIPMap pip_players_rm; 715 volatile bool pip_active; 708 716 709 717 // Preview window support 710 718 unsigned char *argb_buf; -
libs/libmythtv/tv_play.cpp
65 65 66 66 #define GetPlayer(X,Y) GetPlayerHaveLock(X, Y, __FILE__ , __LINE__) 67 67 #define GetOSDLock(X) GetOSDL(X, __FILE__, __LINE__) 68 #define SetExitPlayer(X,Y) SetExitPlayerReal(X,Y,__LINE__) 68 69 69 70 const int TV::kInitFFRWSpeed = 0; 70 71 const uint TV::kInputKeysMax = 6; 71 72 const uint TV::kNextSource = 1; 72 73 const uint TV::kPreviousSource = 2; 74 const uint TV::kMaxPIPCount = 4; 75 const uint TV::kMaxPBPCount = 2; 73 76 77 74 78 const uint TV::kInputModeTimeout = 5000; 75 79 const uint TV::kMuteTimeout = 800; 76 80 const uint TV::kLCDTimeout = 1000; … … 154 158 if (!lastProgramStringList.empty()) 155 159 { 156 160 ProgramInfo *p = new ProgramInfo(); 157 p->FromStringList(lastProgramStringList, 0);158 tv->setLastProgram(p);161 if (p->FromStringList(lastProgramStringList, 0)) 162 tv->SetLastProgram(p); 159 163 delete p; 160 164 } 161 165 … … 175 179 VERBOSE(VB_PLAYBACK, LOC + "tv->LiveTV() -- begin"); 176 180 if (!tv->LiveTV(showDialogs, startInGuide)) 177 181 { 178 tv->S topLiveTV();182 tv->SetExitPlayerReal(true, true, __LINE__); 179 183 quitAll = true; 180 184 } 181 185 VERBOSE(VB_PLAYBACK, LOC + "tv->LiveTV() -- end"); … … 270 274 271 275 if (tv->getJumpToProgram()) 272 276 { 277 ProgramInfo *nextProgram = tv->GetLastProgram(); 273 278 274 ProgramInfo *tmpProgram = tv->getLastProgram(); 275 ProgramInfo *nextProgram = new ProgramInfo(*tmpProgram); 276 279 tv->SetLastProgram(curProgram); 277 280 if (curProgram) 278 {279 tv->setLastProgram(curProgram);280 281 delete curProgram; 281 }282 else283 tv->setLastProgram(NULL);284 282 285 283 curProgram = nextProgram; 286 284 … … 420 418 REG_KEY("TV Playback", "VOLUMEDOWN", "Volume down", "[,{,F10,Volume Down"); 421 419 REG_KEY("TV Playback", "VOLUMEUP", "Volume up", "],},F11,Volume Up"); 422 420 REG_KEY("TV Playback", "MUTE", "Mute", "|,\\,F9,Volume Mute"); 423 REG_KEY("TV Playback", "TOGGLEPIPMODE", "Toggle Picture-in-Picture mode",421 REG_KEY("TV Playback", "TOGGLEPIPMODE", "Toggle Picture-in-Picture view", 424 422 "V"); 425 REG_KEY("TV Playback", "TOGGLEPBPMODE", "Toggle Picture-by-Picture mode",423 REG_KEY("TV Playback", "TOGGLEPBPMODE", "Toggle Picture-by-Picture view", 426 424 "Ctrl+V"); 427 REG_KEY("TV Playback", "TOGGLEPIPWINDOW", "Toggle active PIP/PBP window", "B"); 425 REG_KEY("TV Playback", "CREATEPIPVIEW", "Create Picture-in-Picture view", 426 "1"); 427 REG_KEY("TV Playback", "CREATEPBPVIEW", "Create Picture-by-Picture view", 428 "Ctrl+1"); 429 REG_KEY("TV Playback", "NEXTPIPWINDOW", "Toggle active PIP/PBP window", "B"); 428 430 REG_KEY("TV Playback", "SWAPPIP", "Swap PBP/PIP Windows", "N"); 429 REG_KEY("TV Playback", "TOGGLEPIPSTATE", "Change PIP from PBP or visa versa" 430 ,""); 431 REG_KEY("TV Playback", "TOGGLEPIPSTATE", "Change PxP view", ""); 431 432 REG_KEY("TV Playback", "TOGGLEASPECT", 432 433 "Toggle the video aspect ratio", "Ctrl+W"); 433 434 REG_KEY("TV Playback", "TOGGLEFILL", "Next Preconfigured Zoom mode", "W"); … … 569 570 baseFilters(""), 570 571 db_channel_format("<num> <sign>"), 571 572 db_time_format("h:mm AP"), db_short_date_format("M/d"), 572 db_idle_timeout(0), 573 db_auto_set_watched(false), 574 db_end_of_rec_exit_prompt(false), 573 db_idle_timeout(0), db_udpnotify_port(0), 574 db_playback_exit_prompt(0), db_autoexpire_default(0), 575 db_auto_set_watched(false), db_end_of_rec_exit_prompt(false), 576 db_jump_prefer_osd(true), db_use_gui_size_for_tv(false), 577 db_start_in_guide(false), db_toggle_bookmark(false), 578 db_run_jobs_on_remote(false), db_use_dvd_bookmark(false), 579 db_continue_embedded(false), db_use_fixed_size(true), 580 575 581 smartChannelChange(false), 576 582 MuteIndividualChannels(false), arrowAccel(false), 577 583 osd_general_timeout(2), osd_prog_info_timeout(3), … … 594 600 adjustingPicture(kAdjustingPicture_None), 595 601 adjustingPictureAttribute(kPictureAttribute_None), 596 602 askAllowType(kAskAllowCancel), askAllowLock(QMutex::Recursive), 597 ignoreKeys(false),598 needToMakePIPChange(kPIPOff),599 nextProgPIPState(kPIPOff),600 603 // Channel Editing 601 604 chanEditMapLock(QMutex::Recursive), 602 605 ddMapSourceId(0), ddMapLoaderRunning(false), … … 615 618 browsemode(false), persistentbrowsemode(false), 616 619 browsechannum(""), browsechanid(""), browsestarttime(""), 617 620 // Program Info for currently playing video 618 lastProgram(NULL), jumpToProgram(false),621 lastProgram(NULL), 619 622 inPlaylist(false), underNetworkControl(false), 620 623 isnearend(false), 624 // Jump to program stuff 625 jumpToProgramPIPState(kPIPOff), 626 jumpToProgram(false), 621 627 // Video Player currently receiving UI input 622 628 playerActive(-1), 623 629 //Recorder switching info … … 647 653 648 654 db_idle_timeout = gContext->GetNumSetting("LiveTVIdleTimeout", 0); 649 655 db_idle_timeout *= 60 * 1000; // convert from minutes to ms. 650 db_auto_set_watched = gContext->GetNumSetting("AutomaticSetWatched", 0); 656 db_udpnotify_port = gContext->GetNumSetting("UDPNotifyPort", 0); 657 db_playback_exit_prompt= gContext->GetNumSetting("PlaybackExitPrompt", 0); 658 db_autoexpire_default = gContext->GetNumSetting("AutoExpireDefault", 0); 659 660 db_auto_set_watched = gContext->GetNumSetting("AutomaticSetWatched", 0); 651 661 db_end_of_rec_exit_prompt = 652 662 gContext->GetNumSetting("EndOfRecordingExitPrompt", 0); 663 db_jump_prefer_osd = gContext->GetNumSetting("JumpToProgramOSD", 1); 664 db_use_gui_size_for_tv = gContext->GetNumSetting("GuiSizeForTV", 0); 665 db_start_in_guide = gContext->GetNumSetting("WatchTVGuide", 0); 666 db_toggle_bookmark = gContext->GetNumSetting("AltClearSavedPosition",1); 667 db_run_jobs_on_remote = gContext->GetNumSetting("JobsRunOnRecordHost", 0); 668 db_use_dvd_bookmark = gContext->GetNumSetting("EnableDVDBookmark", 0); 669 db_continue_embedded = gContext->GetNumSetting( 670 "ContinueEmbeddedTVPlay", 0); 671 db_use_fixed_size = gContext->GetNumSettingOnHost( 672 "UseFixedWindowSize", gContext->GetHostName(), 1); 653 673 654 674 sleep_times.push_back(SleepTimerInfo(QObject::tr("Off"), 0)); 655 675 sleep_times.push_back(SleepTimerInfo(QObject::tr("30m"), 30*60)); … … 662 682 663 683 playerLock.lockForWrite(); 664 684 player.push_back(new PlayerContext()); 685 playerActive = 0; 665 686 playerLock.unlock(); 666 SetActive(NULL, 0);667 687 } 668 688 669 689 /** \fn TV::Init(bool) … … 768 788 } 769 789 } 770 790 771 bool use_fixed_size = gContext->GetNumSettingOnHost(772 "UseFixedWindowSize", gContext->GetHostName(), 1);773 774 791 // player window sizing 775 792 myWindow = new MythDialog(mainWindow, "video playback window"); 776 793 … … 780 797 myWindow->setGeometry(win_bounds); 781 798 myWindow->setBaseSize(win_bounds.size()); 782 799 myWindow->setMinimumSize( 783 ( use_fixed_size) ? win_bounds.size() : QSize(16, 16));800 (db_use_fixed_size) ? win_bounds.size() : QSize(16, 16)); 784 801 myWindow->setMaximumSize( 785 ( use_fixed_size) ? win_bounds.size() :802 (db_use_fixed_size) ? win_bounds.size() : 786 803 QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); 787 804 788 805 // resize main window 789 806 mainWindow->setGeometry(player_bounds); 790 807 mainWindow->setBaseSize(player_bounds.size()); 791 808 mainWindow->setMinimumSize( 792 ( use_fixed_size) ? player_bounds.size() : QSize(16, 16));809 (db_use_fixed_size) ? player_bounds.size() : QSize(16, 16)); 793 810 mainWindow->setMaximumSize( 794 ( use_fixed_size) ? player_bounds.size() :811 (db_use_fixed_size) ? player_bounds.size() : 795 812 QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); 796 813 mainWindow->installEventFilter(this); 797 814 … … 834 851 mwnd->resize(saved_gui_bounds.size()); 835 852 mwnd->setFixedSize(saved_gui_bounds.size()); 836 853 mwnd->show(); 837 if (! gContext->GetNumSetting("GuiSizeForTV", 0))854 if (!db_use_gui_size_for_tv) 838 855 mwnd->move(saved_gui_bounds.topLeft()); 839 856 } 840 857 … … 923 940 .arg(db_idle_timeout*(1.0f/60000.0f))); 924 941 } 925 942 926 if (startInGuide || gContext->GetNumSetting("WatchTVGuide", 0))943 if (startInGuide || db_start_in_guide) 927 944 { 928 945 MSqlQuery query(MSqlQuery::InitCon()); 929 946 query.prepare("SELECT keylist FROM keybindings WHERE " … … 1336 1353 break; 1337 1354 case 2: 1338 1355 // return to main menu 1339 S topLiveTV();1356 SetExitPlayer(true, true); 1340 1357 break; 1341 1358 case 3: 1342 1359 // cancel scheduled recording … … 1353 1370 default: 1354 1371 case 1: 1355 1372 // return to main menu 1356 S topLiveTV();1373 SetExitPlayer(true, true); 1357 1374 break; 1358 1375 case 2: 1359 1376 { … … 1628 1645 { 1629 1646 // Cache starting frame rate for this recorder 1630 1647 ctx->last_framerate = ctx->recorder->GetFrameRate(); 1631 ok = StartPlayer(mctx, ctx, desiredNextState , ctx->isPIP());1648 ok = StartPlayer(mctx, ctx, desiredNextState); 1632 1649 } 1633 1650 if (!ok) 1634 1651 { … … 1648 1665 lockTimerOn = true; 1649 1666 } 1650 1667 } 1668 1669 if (mctx != ctx) 1670 SetActive(ctx, find_player_index(ctx), false); 1651 1671 } 1652 1672 else if (TRANSITION(kState_WatchingLiveTV, kState_None)) 1653 1673 { 1654 1674 SET_NEXT(); 1655 1675 RestoreScreenSaver(ctx); 1656 1676 StopStuff(mctx, ctx, true, true, true); 1677 1678 if ((mctx != ctx) && (GetPlayer(ctx,-1) == ctx)) 1679 SetActive(mctx, 0, true); 1657 1680 } 1658 1681 else if (TRANSITION(kState_WatchingRecording, kState_WatchingPreRecorded)) 1659 1682 { … … 1704 1727 } 1705 1728 } 1706 1729 1707 ok = StartPlayer(mctx, ctx, desiredNextState , ctx->isPIP());1730 ok = StartPlayer(mctx, ctx, desiredNextState); 1708 1731 1709 1732 if (ok) 1710 1733 { … … 1727 1750 SET_LAST(); 1728 1751 SetErrored(ctx); 1729 1752 } 1753 else if (mctx != ctx) 1754 { 1755 SetActive(ctx, find_player_index(ctx), false); 1756 } 1730 1757 } 1731 1758 else if (TRANSITION(kState_WatchingPreRecorded, kState_None) || 1732 1759 TRANSITION(kState_WatchingRecording, kState_None)) … … 1735 1762 1736 1763 RestoreScreenSaver(ctx); 1737 1764 StopStuff(mctx, ctx, true, true, false); 1765 1766 if ((mctx != ctx) && (GetPlayer(ctx,-1) == ctx)) 1767 SetActive(mctx, 0, true); 1738 1768 } 1739 1769 else if (TRANSITION(kState_None, kState_None)) 1740 1770 { … … 1754 1784 1755 1785 nextState = kState_None; 1756 1786 changed = true; 1787 1788 if ((mctx != ctx) && (GetPlayer(ctx,-1) == ctx)) 1789 SetActive(mctx, 0, true); 1757 1790 } 1758 1791 1759 1792 // Print state changed message... … … 1901 1934 LOC + QString("StopStuff() for player ctx %1 -- begin") 1902 1935 .arg(find_player_index(ctx))); 1903 1936 1904 SetActive(mctx, 0 );1937 SetActive(mctx, 0, false); 1905 1938 1906 1939 if (ctx->buffer && ctx->buffer->isDVD()) 1907 1940 { … … 1951 1984 QString loc = LOC + QString("TeardownPlayer() player ctx %1") 1952 1985 .arg(ctx_index); 1953 1986 1954 SetActive(mctx, 0); 1987 if (!mctx || !ctx || ctx_index < 0) 1988 { 1989 VERBOSE(VB_IMPORTANT, loc + "-- error"); 1990 return; 1991 } 1955 1992 1993 VERBOSE(VB_PLAYBACK, loc); 1994 1956 1995 if (mctx != ctx) 1957 1996 { 1958 1997 if (ctx->nvp) 1959 1998 { 1999 PIPRemovePlayer(mctx, ctx); 1960 2000 ctx->nvp->StopPlaying(); 1961 2001 ctx->SetNVP(NULL); 1962 2002 } 1963 2003 1964 SetPIPPlayer(mctx, ctx);1965 2004 player.erase(player.begin() + ctx_index); 1966 2005 delete ctx; 1967 TeardownPBP(ctx); 2006 PBPRestartMainNVP(mctx); 2007 SetActive(mctx, playerActive, false); 1968 2008 return; 1969 2009 } 1970 2010 … … 2022 2062 mctx = GetPlayerWriteLock(0, __FILE__, __LINE__); 2023 2063 if (!mctx->IsErrored() && (GetState(mctx) != kState_None)) 2024 2064 { 2025 mctx->ForceNextStateNone( );2065 mctx->ForceNextStateNone(__LINE__); 2026 2066 HandleStateChange(mctx, mctx); 2027 2067 if (jumpToProgram) 2028 2068 TeardownPlayer(mctx, mctx); … … 2076 2116 HandlePseudoLiveTVTimerEvent(); 2077 2117 else if (timer_id == speedChangeTimerId) 2078 2118 HandleSpeedChangeTimerEvent(); 2119 else if (timer_id == pipChangeTimerId) 2120 HandlePxPTimerEvent(); 2079 2121 else 2080 2122 handled = false; 2081 2123 … … 2275 2317 2276 2318 // Check if it matches networkControlTimerId 2277 2319 QString netCmd = QString::null; 2278 if (!ignoreKeys)2279 2320 { 2280 2321 QMutexLocker locker(&timerIdLock); 2281 2322 if (timer_id == networkControlTimerId) … … 2292 2333 2293 2334 if (!netCmd.isEmpty()) 2294 2335 { 2295 PlayerContext *actx = GetPlayer ReadLock(-1, __FILE__, __LINE__);2336 PlayerContext *actx = GetPlayerWriteLock(-1, __FILE__, __LINE__); 2296 2337 ProcessNetworkControlCommand(actx, netCmd); 2297 2338 ReturnPlayerLock(actx); 2298 2339 handled = true; … … 2329 2370 } 2330 2371 ReturnOSDLock(mctx, osd); 2331 2372 lastProgramStringList.clear(); 2332 setLastProgram(NULL);2373 SetLastProgram(NULL); 2333 2374 VERBOSE(VB_PLAYBACK, LOC_ERR + 2334 2375 "Last Program File does not exist"); 2335 2376 jumpToProgram = false; 2336 2377 } 2337 2378 else 2338 ForceNextStateNone(mctx );2379 ForceNextStateNone(mctx, __LINE__); 2339 2380 } 2340 2381 else 2341 ForceNextStateNone(mctx );2382 ForceNextStateNone(mctx, __LINE__); 2342 2383 2343 2384 ReturnPlayerLock(mctx); 2344 2385 … … 2364 2405 if (handled) 2365 2406 return; 2366 2407 2367 if (timer_id == pipChangeTimerId)2368 {2369 if (needToMakePIPChange > kPIPOff)2370 {2371 PlayerContext *mctx = GetPlayerWriteLock(0, __FILE__, __LINE__);2372 ClearOSD(mctx);2373 2374 switch (needToMakePIPChange)2375 {2376 case (kPIPSwap):2377 SwapPIP(mctx, 1, false);2378 break;2379 case (kPBPSwap):2380 SwapPIP(mctx, 1, true);2381 break;2382 case (kPIPToPBP):2383 TogglePIPState(mctx, needToMakePIPChange);2384 break;2385 case (kPBPToPIP):2386 TogglePIPState(mctx, needToMakePIPChange);2387 break;2388 case (kPBPToggle):2389 {2390 if (mctx && (player.size() > 1))2391 TeardownPlayer(mctx, GetPlayer(mctx, 1));2392 else2393 TogglePIPView(mctx, true);2394 break;2395 }2396 }2397 ReturnPlayerLock(mctx);2398 2399 needToMakePIPChange = kPIPOff;2400 }2401 2402 QMutexLocker locker(&timerIdLock);2403 if (pipChangeTimerId)2404 KillTimer(pipChangeTimerId);2405 pipChangeTimerId = 0;2406 handled = true;2407 }2408 2409 if (handled)2410 return;2411 2412 2408 if (timer_id == udpNotifyTimerId) 2413 2409 { 2414 2410 while (HasUDPNotifyEvent()) … … 2555 2551 { 2556 2552 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 2557 2553 OSD *osd = GetOSDLock(actx); 2558 OSDSet *oset = osd->GetSet("status"); 2554 OSDSet *oset = NULL; 2555 if (osd) 2556 oset = osd->GetSet("status"); 2559 2557 if (osd && oset && oset->Displaying() && 2560 2558 (StateIsLiveTV(actx->GetState()) || 2561 2559 StateIsPlaying(actx->GetState()))) … … 2580 2578 (mctx->nvp && mctx->nvp->IsErrored()) || mctx->IsErrored()) 2581 2579 { 2582 2580 SetExitPlayer(true, false); 2583 ForceNextStateNone(mctx );2581 ForceNextStateNone(mctx, __LINE__); 2584 2582 error = true; 2585 2583 } 2586 2584 … … 2588 2586 { 2589 2587 PlayerContext *ctx = GetPlayer(mctx, i); 2590 2588 if (error || ctx->IsErrored()) 2591 ForceNextStateNone(ctx );2589 ForceNextStateNone(ctx, __LINE__); 2592 2590 } 2593 2591 ReturnPlayerLock(mctx); 2594 2592 … … 2600 2598 } 2601 2599 } 2602 2600 2601 bool TV::HandlePxPTimerEvent(void) 2602 { 2603 QString cmd = QString::null; 2604 2605 { 2606 QMutexLocker locker(&timerIdLock); 2607 if (changePxP.empty()) 2608 { 2609 if (pipChangeTimerId) 2610 KillTimer(pipChangeTimerId); 2611 pipChangeTimerId = 0; 2612 return true; 2613 } 2614 cmd = changePxP.dequeue(); 2615 } 2616 2617 PlayerContext *mctx = GetPlayerWriteLock(0, __FILE__, __LINE__); 2618 PlayerContext *actx = GetPlayer(mctx, -1); 2619 2620 if (cmd == "TOGGLEPIPMODE") 2621 PxPToggleView(actx, false); 2622 else if (cmd == "TOGGLEPBPMODE") 2623 PxPToggleView(actx, true); 2624 else if (cmd == "CREATEPIPVIEW") 2625 PxPCreateView(actx, false); 2626 else if (cmd == "CREATEPBPVIEW") 2627 PxPCreateView(actx, true); 2628 else if (cmd == "SWAPPIP") 2629 PxPSwap(mctx); 2630 else if (cmd == "TOGGLEPIPSTATE") 2631 PxPToggleType(mctx, !mctx->isPBP()); 2632 2633 ReturnPlayerLock(mctx); 2634 2635 QMutexLocker locker(&timerIdLock); 2636 2637 if (pipChangeTimerId) 2638 KillTimer(pipChangeTimerId); 2639 2640 if (changePxP.empty()) 2641 pipChangeTimerId = 0; 2642 else 2643 pipChangeTimerId = StartTimer(20, __LINE__); 2644 2645 return true; 2646 } 2647 2603 2648 bool TV::HandleLCDTimerEvent(void) 2604 2649 { 2605 2650 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); … … 2654 2699 QObject::killTimer(id); 2655 2700 } 2656 2701 2657 void TV::ForceNextStateNone(PlayerContext *ctx )2702 void TV::ForceNextStateNone(PlayerContext *ctx, int line) 2658 2703 { 2659 ctx->ForceNextStateNone( );2704 ctx->ForceNextStateNone(line); 2660 2705 ScheduleStateChange(ctx); 2661 2706 } 2662 2707 … … 2674 2719 errorRecoveryTimerId = StartTimer(1, __LINE__); 2675 2720 } 2676 2721 2677 void TV::SetExitPlayer (bool set_it, bool wants_to) const2722 void TV::SetExitPlayerReal(bool set_it, bool wants_to, int line) const 2678 2723 { 2724 VERBOSE(VB_IMPORTANT, 2725 LOC + "SetExitPlayer("<<set_it<<","<<wants_to<<","<<line<<")"); 2726 2679 2727 QMutexLocker locker(&timerIdLock); 2680 2728 if (set_it) 2681 2729 { … … 2731 2779 continue; 2732 2780 } 2733 2781 2734 ForceNextStateNone(ctx );2782 ForceNextStateNone(ctx, __LINE__); 2735 2783 if (mctx == ctx) 2736 2784 { 2737 2785 endOfRecording = true; … … 3065 3113 3066 3114 void TV::ProcessKeypress(PlayerContext *actx, QKeyEvent *e) 3067 3115 { 3116 bool ignoreKeys = actx->IsNVPChangingBuffers(); 3068 3117 #if DEBUG_ACTIONS 3069 VERBOSE(VB_IMPORTANT, LOC + "ProcessKeypress() ignoreKeys: "<<ignoreKeys); 3118 VERBOSE(VB_IMPORTANT, LOC + QString("ProcessKeypress() ignoreKeys: %1") 3119 .arg(ignoreKeys)); 3070 3120 #endif // DEBUG_ACTIONS 3071 3121 3072 3122 if (db_idle_timeout > 0) … … 3191 3241 handled = handled || DVDMenuHandleAction(actx, actions, isDVD, isDVDStill); 3192 3242 handled = handled || ActiveHandleAction(actx, actions, isDVD, isDVDStill); 3193 3243 handled = handled || ToggleHandleAction(actx, actions, isDVD); 3194 handled = handled || P IPHandleAction(actx, actions);3244 handled = handled || PxPHandleAction(actx, actions); 3195 3245 handled = handled || FFRewHandleAction(actx, actions); 3196 3246 handled = handled || ActivePostQHandleAction(actx, actions, isDVD); 3197 3247 … … 3223 3273 3224 3274 bool TV::BrowseHandleAction(PlayerContext *ctx, const QStringList &actions) 3225 3275 { 3226 bool handled = false;3227 3276 if (!browsemode) 3228 return handled;3277 return false; 3229 3278 3230 handled = true;3279 bool handled = true; 3231 3280 3232 3281 if (has_action("UP", actions) || has_action("CHANNELUP", actions)) 3233 3282 BrowseDispInfo(ctx, BROWSE_UP); … … 3254 3303 ToggleRecord(ctx); 3255 3304 else 3256 3305 { 3306 handled = false; 3257 3307 QStringList::const_iterator it = actions.begin(); 3258 3308 for (; it != actions.end(); ++it) 3259 3309 { … … 3262 3312 { 3263 3313 CommitQueuedInput(ctx); 3264 3314 BrowseEnd(ctx, false); 3315 handled = true; 3265 3316 } 3266 3317 } 3267 3318 } 3268 3319 3269 3320 // only pass-through actions listed below 3270 return !(has_action("VOLUMEDOWN", actions)||3271 has_action("VOLUMEUP",actions) ||3272 has_action("STRETCHINC",actions) ||3273 has_action("STRETCHDEC", actions) ||3274 has_action("MUTE",actions) ||3275 has_action("TOGGLEASPECT",actions) ||3276 has_action("TOGGLEPIPWINDOW",actions) ||3277 3278 3279 has_action("SWAPPIP", actions));3280 3281 // TODO FIXME this is never reached.. must be a logic error3282 return handled;3321 return handled || 3322 !(has_action("VOLUMEDOWN", actions) || 3323 has_action("VOLUMEUP", actions) || 3324 has_action("STRETCHINC", actions) || 3325 has_action("STRETCHDEC", actions) || 3326 has_action("MUTE", actions) || 3327 has_action("TOGGLEASPECT", actions) || 3328 has_action("TOGGLEPIPMODE", actions) || 3329 has_action("TOGGLEPIPSTATE", actions) || 3330 has_action("NEXTPIPWINDOW", actions) || 3331 has_action("CREATEPIPVIEW", actions) || 3332 has_action("CREATEPBPVIEW", actions) || 3333 has_action("SWAPPIP", actions)); 3283 3334 } 3284 3335 3285 3336 bool TV::ManualZoomHandleAction(PlayerContext *actx, const QStringList &actions) … … 3467 3518 } 3468 3519 else if (dialogname == "allowrecordingbox") 3469 3520 { 3470 int result = osd->GetDialogResponse(dialogname); 3471 3472 if (result == 1) 3473 actx->recorder->CancelNextRecording(false); 3474 else if (result == 2) 3475 StopLiveTV(); 3476 else if (result == 3) 3477 actx->recorder->CancelNextRecording(true); 3521 HandleOSDAskAllowResponse(); 3478 3522 } 3479 3523 else if (dialogname == "idletimeout") 3480 3524 { … … 3831 3875 { 3832 3876 ClearOSD(ctx); 3833 3877 } 3834 else if (has_action("JUMPPREV", actions))3835 {3836 if (PromptRecGroupPassword(ctx))3837 {3838 ctx->nvp->SetBookmark();3839 SetExitPlayer(true, true);3840 }3841 }3842 3878 else if (has_action("VIEWSCHEDULED", actions)) 3843 3879 EditSchedule(ctx, kViewSchedule); 3844 else if ( has_action("JUMPREC", actions))3880 else if (HandleJumpToProgramAction(ctx, actions)) 3845 3881 { 3846 if (gContext->GetNumSetting("JumpToProgramOSD", 1) &&3847 StateIsPlaying(ctx->GetState()))3848 {3849 if (jumpMenuTimerId)3850 KillTimer(jumpMenuTimerId);3851 jumpMenuTimerId = StartTimer(1, __LINE__);3852 }3853 else if (RunPlaybackBoxPtr)3854 EditSchedule(ctx, kPlaybackBox);3855 3882 } 3856 3883 else if (has_action("SIGNALMON", actions)) 3857 3884 { … … 3898 3925 } 3899 3926 else if (has_action("ESCAPE", actions)) 3900 3927 { 3901 SetActive(ctx, 0); 3928 VERBOSE(VB_IMPORTANT, LOC + "ESCAPE"); 3929 3902 3930 osd = GetOSDLock(ctx); 3903 3931 if (StateIsLiveTV(ctx->GetState()) && 3904 3932 (ctx->lastSignalMsgTime.elapsed() < … … 3917 3945 3918 3946 StopFFRew(ctx); 3919 3947 3948 bool do_exit = false; 3949 3920 3950 if (StateIsLiveTV(GetState(ctx))) 3921 3951 { 3922 3952 if (ctx->nvp && 3923 (12 & gContext->GetNumSetting("PlaybackExitPrompt")))3953 (12 & db_playback_exit_prompt)) 3924 3954 { 3925 3955 PromptStopWatchingRecording(ctx); 3926 3956 } 3927 3957 else 3928 3958 { 3929 SetExitPlayer(true, true);3959 do_exit = true; 3930 3960 } 3931 3961 } 3932 3962 else 3933 3963 { 3934 3964 if (ctx->nvp && 3935 (5 & gContext->GetNumSetting("PlaybackExitPrompt")) &&3965 (5 & db_playback_exit_prompt) && 3936 3966 !underNetworkControl && !isDVDStill) 3937 3967 { 3938 3968 PromptStopWatchingRecording(ctx); 3939 3969 return handled; 3940 3970 } 3941 3971 else if (ctx->nvp && 3942 ( gContext->GetNumSetting("PlaybackExitPrompt")== 2))3972 (db_playback_exit_prompt == 2)) 3943 3973 { 3944 3974 ctx->nvp->SetBookmark(); 3945 3975 } 3946 3976 if (ctx->nvp && 3947 gContext->GetNumSetting("AutomaticSetWatched", 0))3977 db_auto_set_watched) 3948 3978 { 3949 3979 ctx->nvp->SetWatched(); 3950 3980 } 3951 3981 requestDelete = false; 3952 SetExitPlayer(true, true);3982 do_exit = true; 3953 3983 } 3984 3985 if (do_exit) 3986 { 3987 PlayerContext *mctx = GetPlayer(ctx, 0); 3988 if (mctx != ctx) 3989 { // A PIP is active, just tear it down.. 3990 PxPTeardownView(ctx); 3991 return handled; 3992 } 3993 else 3994 { 3995 SetExitPlayer(true, true); 3996 } 3997 } 3998 3999 SetActive(ctx, 0, false); 3954 4000 } 3955 4001 else if (has_action("VOLUMEDOWN", actions)) 3956 4002 ChangeVolume(ctx, false); … … 4075 4121 return handled; 4076 4122 } 4077 4123 4078 bool TV::P IPHandleAction(PlayerContext *ctx, const QStringList &actions)4124 bool TV::PxPHandleAction(PlayerContext *ctx, const QStringList &actions) 4079 4125 { 4080 bool handled = true;4081 4082 4126 if (!IsPIPSupported(ctx)) 4083 return handled;4127 return false; 4084 4128 4085 if (has_action("TOGGLEPIPMODE", actions)) 4086 TogglePIPView(ctx); 4087 else if (has_action("TOGGLEPBPMODE", actions)) 4129 bool handled = true; 4088 4130 { 4089 needToMakePIPChange = kPBPToggle; 4090 if (pipChangeTimerId) 4091 KillTimer(pipChangeTimerId); 4092 pipChangeTimerId = StartTimer(1, __LINE__); 4131 QMutexLocker locker(&timerIdLock); 4132 4133 if (has_action("TOGGLEPIPMODE", actions)) 4134 changePxP.enqueue("TOGGLEPIPMODE"); 4135 else if (has_action("TOGGLEPBPMODE", actions)) 4136 changePxP.enqueue("TOGGLEPBPMODE"); 4137 else if (has_action("CREATEPIPVIEW", actions)) 4138 changePxP.enqueue("CREATEPIPVIEW"); 4139 else if (has_action("CREATEPBPVIEW", actions)) 4140 changePxP.enqueue("CREATEPBPVIEW"); 4141 else if (has_action("SWAPPIP", actions)) 4142 changePxP.enqueue("SWAPPIP"); 4143 else if (has_action("TOGGLEPIPSTATE", actions)) 4144 changePxP.enqueue("TOGGLEPIPSTATE"); 4145 else 4146 handled = false; 4147 4148 if (!changePxP.empty() && !pipChangeTimerId) 4149 pipChangeTimerId = StartTimer(1, __LINE__); 4093 4150 } 4094 else if (has_action("SWAPPIP", actions)) 4151 4152 if (has_action("NEXTPIPWINDOW", actions)) 4095 4153 { 4096 needToMakePIPChange = (ctx->isPBP()) ? kPBPSwap : kPIPSwap; 4097 if (pipChangeTimerId) 4098 KillTimer(pipChangeTimerId); 4099 pipChangeTimerId = StartTimer(1, __LINE__); 4154 SetActive(ctx, -1, true); 4155 handled = true; 4100 4156 } 4101 else if (has_action("TOGGLEPIPSTATE", actions))4102 {4103 if (ctx && player.size() > 1)4104 {4105 needToMakePIPChange = (ctx->isPBP()) ? kPBPToPIP : kPIPToPBP;4106 if (pipChangeTimerId)4107 KillTimer(pipChangeTimerId);4108 pipChangeTimerId = StartTimer(1, __LINE__);4109 }4110 }4111 else if (has_action("TOGGLEPIPWINDOW", actions))4112 ToggleActiveWindow(ctx, 1);4113 else4114 handled = false;4115 4157 4116 4158 return handled; 4117 4159 } … … 4131 4173 if (isDVD && ctx->buffer && ctx->buffer->DVD()) 4132 4174 ctx->buffer->DVD()->JumpToTitle(false); 4133 4175 4134 int clearpos = gContext->GetNumSetting("AltClearSavedPosition", 1);4135 4176 ctx->LockDeleteNVP(__FILE__, __LINE__); 4136 4177 if (ctx->nvp) 4137 4178 { 4138 if ( clearpos&& ctx->nvp->GetBookmark())4179 if (db_toggle_bookmark && ctx->nvp->GetBookmark()) 4139 4180 ctx->nvp->ClearBookmark(); 4140 4181 else 4141 4182 ctx->nvp->SetBookmark(); … … 4200 4241 void TV::ProcessNetworkControlCommand(PlayerContext *ctx, 4201 4242 const QString &command) 4202 4243 { 4244 bool ignoreKeys = ctx->IsNVPChangingBuffers(); 4203 4245 #ifdef DEBUG_ACTIONS 4204 4246 VERBOSE(VB_IMPORTANT, LOC + "ProcessNetworkControlCommand(" + 4205 QString("%1) ").arg(command));4247 QString("%1) ignoreKeys: %2").arg(command).arg(ignoreKeys)); 4206 4248 #endif 4207 4249 4250 if (ignoreKeys) 4251 { 4252 VERBOSE(VB_IMPORTANT, LOC_WARN + 4253 "Ignoring network control command" 4254 "\n\t\t\tbecause ignoreKeys is set"); 4255 return; 4256 } 4257 4208 4258 QStringList tokens = command.split(" ", QString::SkipEmptyParts); 4209 4259 if (tokens.size() < 2) 4210 4260 { … … 4365 4415 { 4366 4416 if (ctx->nvp) 4367 4417 ctx->nvp->SetBookmark(); 4368 if (ctx->nvp && gContext->GetNumSetting("AutomaticSetWatched", 0))4418 if (ctx->nvp && db_auto_set_watched) 4369 4419 ctx->nvp->SetWatched(); 4370 4420 SetExitPlayer(true, true); 4371 4421 } … … 4549 4599 swap(player[0],player[1]); 4550 4600 player[0]->SetPIPState(kPIPOff); 4551 4601 // End the old main context.. 4552 ForceNextStateNone(mctx );4602 ForceNextStateNone(mctx, __LINE__); 4553 4603 } 4554 4604 4555 4605 VERBOSE(VB_PLAYBACK, LOC + "CreatePBP() -- end : "<<ok); … … 4557 4607 } 4558 4608 4559 4609 /** 4560 * \brief tear down remaining PBP video and restore4561 * fullscreen display4610 * \brief create PIP. 4611 * \param info programinfo for PIP to create. is NULL for LiveTV PIP 4562 4612 */ 4563 void TV::TeardownPBP(PlayerContext *ctx)4613 bool TV::CreatePIP(PlayerContext *ctx, const ProgramInfo *info) 4564 4614 { 4565 4615 PlayerContext *mctx = GetPlayer(ctx, 0); 4616 if (!mctx) 4617 return false; 4566 4618 4567 if (!mctx->nvp || !mctx->nvp->IsPlaying() || 4568 mctx->GetPIPState() < kPBPLeft || exitPlayerTimerId) 4569 { 4570 return; 4571 } 4619 VERBOSE(VB_PLAYBACK, LOC + "CreatePIP -- begin"); 4572 4620 4573 VERBOSE(VB_PLAYBACK, LOC + "TeardownPBP -- begin"); 4574 4575 long long mctx_frame = mctx->nvp->GetFramesPlayed(); 4576 mctx->PIPTeardown(); 4577 mctx->SetPIPState(kPIPOff); 4578 mctx->buffer->Seek(0, SEEK_SET); 4579 if (mctx->CreateNVP(this, myWindow, mctx->GetState(), 4580 embedWinID, &embedBounds)) 4621 if (mctx->isPBP()) 4581 4622 { 4582 ScheduleStateChange(mctx); 4583 mctx->StartOSD(this); 4584 mctx->nvp->JumpToFrame(mctx_frame); 4585 4586 //TODO find out where wantsToQuit is been enabled 4587 wantsToQuit = false; 4588 4589 SetSpeedChangeTimer(25, __LINE__); 4623 VERBOSE(VB_IMPORTANT, LOC_ERR + 4624 "CreatePIP called, but we're in PBP mode already, ignoring."); 4625 return false; 4590 4626 } 4591 else4592 ForceNextStateNone(mctx);4593 4627 4594 VERBOSE(VB_PLAYBACK, LOC + "TeardownPBP -- end"); 4595 } 4628 bool has_vo = false, using_xvmc = false; 4596 4629 4597 /** 4598 * \brief create PIP. 4599 * \param info programinfo for PIP to create. is NULL for LiveTV PIP 4600 */ 4601 bool TV::CreatePIP(PlayerContext *ctx, const ProgramInfo *info) 4602 { 4603 bool ret = false; 4604 PlayerContext *mctx = GetPlayer(ctx, 0); 4605 4606 VERBOSE(VB_PLAYBACK, LOC + "Starting CreatePIP -- begin"); 4607 bool using_xvmc = false; 4608 QRect rect; 4609 int pip_location; 4610 if (mctx && mctx->nvp && mctx->nvp->getVideoOutput()) 4630 mctx->LockDeleteNVP(__FILE__, __LINE__); 4631 if (mctx->nvp && mctx->nvp->getVideoOutput()) 4611 4632 { 4612 pip_location = gContext->GetNumSetting("PIPLocation", 0); 4613 rect = mctx->nvp->getVideoOutput()->GetPIPRect(pip_location, NULL); 4633 has_vo = true; 4614 4634 using_xvmc = mctx->nvp->getVideoOutput()->hasMCAcceleration(); 4615 4635 } 4616 else 4617 { 4618 return ret; 4619 } 4636 mctx->UnlockDeleteNVP(__FILE__, __LINE__); 4620 4637 4638 if (!has_vo) 4639 return false; 4640 4621 4641 /* TODO implement PIP solution for Xvmc playback */ 4622 4642 if (using_xvmc) 4623 4643 { 4624 4644 VERBOSE(VB_IMPORTANT, LOC + "PiP is not supported for XvMC"); 4625 return ret;4645 return false; 4626 4646 } 4627 4647 4628 4648 PlayerContext *pipctx = new PlayerContext(); … … 4643 4663 else 4644 4664 { 4645 4665 delete pipctx; 4646 return ret;4666 return false; 4647 4667 } 4648 4668 4649 4669 // this is safe because we are already holding lock for ctx 4650 4670 player.push_back(pipctx); 4651 4671 4652 ret = true; 4653 return ret; 4672 return true; 4654 4673 } 4655 4674 4656 4675 int TV::find_player_index(const PlayerContext *ctx) const … … 4662 4681 } 4663 4682 4664 4683 bool TV::StartPlayer(PlayerContext *mctx, PlayerContext *ctx, 4665 TVState desiredState , bool ispip)4684 TVState desiredState) 4666 4685 { 4667 if (ispip) 4668 return StartPIPPlayer(mctx, ctx, desiredState); 4686 bool wantPiP = ctx->isPIP(); 4669 4687 4670 VERBOSE(VB_IMPORTANT, LOC + QString("StartPlayer(%1, %2, not pip) -- begin") 4671 .arg(find_player_index(ctx)).arg(StateToString(desiredState))); 4688 VERBOSE(VB_IMPORTANT, LOC + QString("StartPlayer(%1, %2, %3) -- begin") 4689 .arg(find_player_index(ctx)).arg(StateToString(desiredState)) 4690 .arg((wantPiP) ? "PiP" : "main")); 4672 4691 4692 if (wantPiP) 4693 { 4694 if (mctx->nvp && ctx->StartPIPPlayer(this, desiredState) && 4695 ctx->nvp && PIPAddPlayer(mctx, ctx)) 4696 { 4697 ScheduleStateChange(ctx); 4698 VERBOSE(VB_IMPORTANT, "StartPlayer PiP -- end : ok"); 4699 return true; 4700 } 4701 4702 ForceNextStateNone(ctx, __LINE__); 4703 VERBOSE(VB_IMPORTANT, "StartPlayer PiP -- end : !ok"); 4704 return false; 4705 } 4706 4673 4707 InitUDPNotifyEvent(); 4674 4708 bool ok = false; 4675 4709 if (ctx->UseNullVideo()) … … 4677 4711 ok = ctx->CreateNVP(this, NULL, desiredState, 0, NULL); 4678 4712 ScheduleStateChange(ctx); 4679 4713 if (ok) 4680 SetPIPPlayer(mctx, ctx);4714 ok = PIPAddPlayer(mctx, ctx); 4681 4715 } 4682 4716 else 4683 4717 { … … 4692 4726 SetSpeedChangeTimer(25, __LINE__); 4693 4727 } 4694 4728 4695 VERBOSE(VB_IMPORTANT, LOC + 4696 QString("StartPlayer(%1, %2, not pip) -- end %3") 4729 VERBOSE(VB_IMPORTANT, LOC + QString("StartPlayer(%1, %2, %3) -- end %4") 4697 4730 .arg(find_player_index(ctx)).arg(StateToString(desiredState)) 4698 .arg(( ok) ? "ok" : "error"));4731 .arg((wantPiP) ? "PiP" : "main").arg((ok) ? "ok" : "error")); 4699 4732 4700 4733 return ok; 4701 4734 } 4702 4735 4703 bool TV::StartPIPPlayer(PlayerContext *mctx, PlayerContext *ctx, 4704 TVState desiredState)4736 /// \brief Maps NVP of software scaled PIP to the NVP of the main player 4737 bool TV::PIPAddPlayer(PlayerContext *mctx, PlayerContext *pipctx) 4705 4738 { 4706 if (mctx->nvp && ctx->StartPIPPlayer(this, desiredState) && ctx->nvp) 4739 if (!mctx || !pipctx) 4740 return false; 4741 4742 if (!mctx->nvp || !mctx->nvp->IsPlaying()) 4743 return false; 4744 4745 bool ok = false, addCondition = false; 4746 if (pipctx->nvp) 4707 4747 { 4708 SetPIPPlayer(mctx, ctx); 4709 ScheduleStateChange(ctx); 4710 return true; 4748 if (pipctx->nvp->UsingNullVideo()) 4749 { 4750 addCondition = true; 4751 PIPLocation loc = mctx->nvp->GetNextPIPLocation(); 4752 ok = mctx->nvp->AddPIPPlayer(pipctx->nvp, loc, 4000); 4753 } 4754 else if (pipctx->isPIP()) 4755 { 4756 ok = ResizePIPWindow(pipctx); 4757 } 4711 4758 } 4712 return false; 4759 4760 VERBOSE(VB_IMPORTANT, 4761 QString("AddPIPPlayer null: %1 isPIP: %2 addCond: %3 ok: %4") 4762 .arg(pipctx->nvp->UsingNullVideo()) 4763 .arg(pipctx->isPIP()).arg(addCondition).arg(ok)); 4764 4765 return ok; 4713 4766 } 4714 4767 4715 /** 4716 * \brief maps NVP of software scaled PIP to the NVP of player 4717 * context 0. 4718 */ 4719 void TV::SetPIPPlayer(PlayerContext *mctx, PlayerContext *pipctx) 4768 /// \brief Unmaps NVP of software scaled PIP from the NVP of the main player 4769 bool TV::PIPRemovePlayer(PlayerContext *mctx, PlayerContext *pipctx) 4720 4770 { 4721 4771 if (!mctx || !pipctx) 4772 return false; 4773 4774 bool ok = false; 4775 if (mctx->nvp && pipctx->nvp) 4776 ok = mctx->nvp->RemovePIPPlayer(pipctx->nvp, 4000); 4777 4778 VERBOSE(VB_IMPORTANT, QString("PIPRemovePlayer ok: %1").arg(ok)); 4779 4780 return ok; 4781 } 4782 4783 /// \brief start/stop PIP/PBP 4784 void TV::PxPToggleView(PlayerContext *actx, bool wantPBP) 4785 { 4786 if (player.size() <= 1) 4787 PxPCreateView(actx, wantPBP); 4788 else 4789 PxPTeardownView(actx); 4790 } 4791 4792 /// \brief start PIP/PBP 4793 void TV::PxPCreateView(PlayerContext *actx, bool wantPBP) 4794 { 4795 if (!actx) 4722 4796 return; 4723 4797 4724 bool setCondition = false;4725 if ( mctx->nvp && mctx->nvp->IsPlaying())4798 QString err_msg = QString::null; 4799 if ((player.size() > kMaxPBPCount) && (wantPBP || actx->isPBP())) 4726 4800 { 4727 if (pipctx->nvp) 4728 { 4729 if (pipctx->nvp->UsingNullVideo()) 4730 setCondition = true; 4731 else if (playerActive == 0 && pipctx->isPIP()) 4732 ResizePIPWindow(pipctx); 4733 } 4734 else 4735 setCondition = true; 4801 err_msg = tr("Sorry, PBP only supports %1 video streams") 4802 .arg(kMaxPBPCount); 4803 } 4736 4804 4737 if (setCondition) 4738 { 4739 QMutex piplock; 4740 piplock.lock(); 4741 mctx->nvp->SetPIPPlayer(pipctx->nvp); 4742 pipPlayerSetCondition.wait(&piplock); 4743 piplock.unlock(); 4744 } 4805 if ((player.size() > kMaxPIPCount) && 4806 (!wantPBP || GetPlayer(actx,1)->isPIP())) 4807 { 4808 err_msg = tr("Sorry, PIP only supports %1 video streams") 4809 .arg(kMaxPIPCount); 4745 4810 } 4811 4812 if ((player.size() > 1) && (wantPBP ^ actx->isPBP())) 4813 err_msg = tr("Sorry, can not mix PBP and PIP views"); 4814 4815 if (!err_msg.isEmpty()) 4816 { 4817 VERBOSE(VB_IMPORTANT, LOC_ERR + err_msg); 4818 OSD *osd = GetOSDLock(actx); 4819 if (osd) 4820 osd->SetSettingsText(err_msg, 3); 4821 ReturnOSDLock(actx, osd); 4822 return; 4823 } 4824 4825 bool ok = false; 4826 if (wantPBP) 4827 ok = CreatePBP(actx, NULL); 4828 else 4829 ok = CreatePIP(actx, NULL); 4830 actx = GetPlayer(actx, -1); // CreatePBP/PIP mess with ctx's 4831 4832 QString msg = (ok) ? 4833 ((wantPBP) ? tr("Creating PBP") : tr("Creating PIP")) : 4834 ((wantPBP) ? tr("Cannot create PBP") : tr("Cannot create PIP")); 4835 4836 OSD *osd = GetOSDLock(actx); 4837 if (osd) 4838 osd->SetSettingsText(msg, 3); 4839 ReturnOSDLock(actx, osd); 4746 4840 } 4747 4841 4748 /** 4749 * \brief start/stop PIP/PBP 4750 * 4751 */ 4752 void TV::TogglePIPView(PlayerContext *lctx, bool ispbp) 4842 /// \brief stop PIP/PBP 4843 void TV::PxPTeardownView(PlayerContext *actx) 4753 4844 { 4845 VERBOSE(VB_IMPORTANT, "PxPTeardownView()"); 4846 4754 4847 QString msg; 4848 PlayerContext *mctx = GetPlayer(actx, 0); 4849 PlayerContext *dctx = NULL; 4850 dctx = (mctx != actx) ? actx : dctx; 4851 dctx = (2 == player.size()) ? GetPlayer(actx, 1) : dctx; 4755 4852 4756 if (player.size() > 1) 4853 SetActive(actx, 0, false); 4854 4855 PlayerContext *ctx1 = GetPlayer(actx, 1); 4856 msg = (ctx1->isPIP()) ? tr("Stopping PIP") : tr("Stopping PBP"); 4857 if (dctx) 4757 4858 { 4758 PlayerContext *ctx = player.back(); 4759 msg = "Stopping "; 4760 msg += (ctx->isPIP()) ? "PIP" : "PBP"; 4761 if (playerActive != 0) 4762 ToggleActiveWindow(lctx, 1); 4763 ForceNextStateNone(ctx); 4859 ForceNextStateNone(dctx, __LINE__); 4764 4860 } 4765 4861 else 4766 4862 { 4767 bool ok = false; 4768 if (ispbp) 4769 ok = CreatePBP(lctx, NULL); 4770 else 4771 ok = CreatePIP(lctx, NULL); 4772 lctx = GetPlayer(lctx, -1); // CreatePBP/PIP mess with ctx's 4773 4774 if (!ok) 4863 if (player.size() > 2) 4775 4864 { 4776 msg = "Cannot Start ";4777 msg += (ispbp) ? "PBP" : "PIP";4865 msg = (ctx1->isPIP()) ? 4866 tr("Stopping all PIPs") : tr("Stopping all PBPs"); 4778 4867 } 4868 4869 for (uint i = player.size() - 1; i > 0; i--) 4870 ForceNextStateNone(GetPlayer(actx,i), __LINE__); 4779 4871 } 4780 4872 4781 OSD *osd = GetOSDLock( lctx);4873 OSD *osd = GetOSDLock(mctx); 4782 4874 if (osd) 4783 4875 osd->SetSettingsText(msg, 3); 4784 ReturnOSDLock( lctx, osd);4876 ReturnOSDLock(mctx, osd); 4785 4877 } 4786 4878 4787 4879 /** 4788 4880 * \brief Change PIP View from PIP to PBP and visa versa 4789 4881 */ 4790 void TV:: TogglePIPState(PlayerContext *mctx, PIPState changeTo)4882 void TV::PxPToggleType(PlayerContext *mctx, bool wantPBP) 4791 4883 { 4792 QString before = (changeTo == kPIPToPBP) ? "PIP" : "PBP"; 4793 QString after = (changeTo == kPIPToPBP) ? "PBP" : "PIP"; 4884 const QString before = (mctx->isPBP()) ? "PBP" : "PIP"; 4885 const QString after = (wantPBP) ? "PBP" : "PIP"; 4886 4794 4887 VERBOSE(VB_PLAYBACK, LOC + 4795 QString(" TogglePIPState() converting from %1 to %2 -- begin")4796 4888 QString("PxPToggleType() converting from %1 to %2 -- begin") 4889 .arg(before).arg(after)); 4797 4890 4798 if ( 2 != player.size())4891 if (mctx->isPBP() == wantPBP) 4799 4892 { 4800 VERBOSE(VB_IMPORTANT, LOC_ERR + 4801 QString("TogglePIPState() -- end: # player contexts must be 2, " 4802 "but it is currently %1").arg(player.size())); 4893 VERBOSE(VB_IMPORTANT, LOC_WARN + 4894 "PxPToggleType() -- end: already in desired mode"); 4803 4895 return; 4804 4896 } 4805 4897 4806 SetActive(mctx, 0); 4898 uint max_cnt = min(kMaxPBPCount, kMaxPIPCount); 4899 if (player.size() > max_cnt) 4900 { 4901 VERBOSE(VB_IMPORTANT, LOC_ERR + 4902 QString("PxPToggleType() -- end: " 4903 "# player contexts must be %1 or less, " 4904 "but it is currently %1") 4905 .arg(max_cnt).arg(player.size())); 4807 4906 4808 PlayerContext *pipctx = GetPlayer(mctx, 1);4907 QString err_msg = tr("Too many views to switch"); 4809 4908 4810 if (!mctx->nvp || !pipctx->nvp || !pipctx->nvp->IsPlaying()) 4909 PlayerContext *actx = GetPlayer(mctx, -1); 4910 OSD *osd = GetOSDLock(actx); 4911 if (osd) 4912 osd->SetSettingsText(err_msg, 3); 4913 ReturnOSDLock(actx, osd); 4811 4914 return; 4915 } 4812 4916 4917 for (uint i = 0; i < player.size(); i++) 4918 { 4919 PlayerContext *ctx = GetPlayer(mctx, i); 4920 ctx->LockDeleteNVP(__FILE__, __LINE__); 4921 if (!ctx->nvp || !ctx->nvp->IsPlaying()) 4922 { 4923 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 4924 VERBOSE(VB_IMPORTANT, LOC_ERR + "PxPToggleType() -- end: " + 4925 QString("nvp #%1 is not active, exiting without " 4926 "doing anything to avoid danger").arg(i)); 4927 return; 4928 } 4929 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 4930 } 4931 4813 4932 MuteState mctx_mute = mctx->nvp->GetMuteState(); 4814 4933 4815 vector<long long> pos; 4816 pos.push_back(mctx->nvp->GetFramesPlayed()); 4817 pos.push_back(pipctx->nvp->GetFramesPlayed()); 4934 vector<long long> pos = TeardownAllNVPs(mctx); 4818 4935 4819 TeardownPIPWindows(mctx); 4820 4821 if (changeTo == kPIPToPBP) 4936 if (wantPBP) 4822 4937 { 4823 mctx->SetPIPState(kPBPLeft);4824 pipctx->SetPIPState(kPBPRight);4938 GetPlayer(mctx, 0)->SetPIPState(kPBPLeft); 4939 GetPlayer(mctx, 1)->SetPIPState(kPBPRight); 4825 4940 } 4826 4941 else 4827 4942 { 4828 mctx->SetPIPState(kPIPOff); 4829 pipctx->SetPIPState(kPIPonTV); 4830 pipctx->SetNullVideo(true); 4943 GetPlayer(mctx, 0)->SetPIPState(kPIPOff); 4944 for (uint i = 1; i < player.size(); i++) 4945 { 4946 GetPlayer(mctx, i)->SetPIPState(kPIPonTV); 4947 GetPlayer(mctx, i)->SetNullVideo(true); 4948 } 4831 4949 } 4832 4950 4833 Restart PIPWindows(mctx, pos, mctx_mute);4951 RestartAllNVPs(mctx, pos, mctx_mute); 4834 4952 4835 4953 VERBOSE(VB_PLAYBACK, LOC + 4836 QString(" TogglePIPState() converting from %1 to %2 -- end")4954 QString("PxPToggleType() converting from %1 to %2 -- end") 4837 4955 .arg(before).arg(after)); 4838 4956 } 4839 4957 4840 void TV::ToggleActiveWindow(PlayerContext *lctx, int ctx_index) 4958 /** 4959 * \brief resize PIP Window. done when changing channels or swapping PIP 4960 */ 4961 bool TV::ResizePIPWindow(PlayerContext *ctx) 4841 4962 { 4842 if (player.size() == 1 || ctx_index < 1) 4843 return; 4844 4845 ClearOSD(lctx); 4846 4847 PlayerContext *ctx = GetPlayer(lctx, ctx_index); 4848 if (ctx->nvp) 4963 VERBOSE(VB_PLAYBACK, LOC + "ResizePIPWindow -- begin"); 4964 PlayerContext *mctx = GetPlayer(ctx, 0); 4965 if (mctx->nvp && ctx->nvp) 4849 4966 { 4850 int new_index = 0; 4851 lockTimerOn = false; 4967 QRect rect; 4852 4968 4853 if (playerActive != ctx_index) 4854 new_index = ctx_index; 4969 mctx->LockDeleteNVP(__FILE__, __LINE__); 4970 if (mctx->nvp) 4971 { 4972 PIPLocation loc = mctx->nvp->GetNextPIPLocation(); 4973 VERBOSE(VB_PLAYBACK, LOC + "ResizePIPWindow -- loc "<<loc); 4974 if (loc != kPIP_END) 4975 { 4976 rect = mctx->nvp->getVideoOutput()->GetPIPRect( 4977 loc, ctx->nvp, false); 4978 } 4979 } 4980 mctx->UnlockDeleteNVP(__FILE__, __LINE__); 4855 4981 4856 PlayerContext *mctx = GetPlayer(lctx, 0); 4857 if (mctx->nvp && 4858 mctx->nvp->getVideoOutput() && 4859 !ctx->isPBP()) 4982 if (rect.isValid()) 4860 4983 { 4861 mctx->nvp->getVideoOutput()->PadPIPImage(new_index); 4984 ctx->ResizePIPWindow(rect); 4985 VERBOSE(VB_PLAYBACK, LOC + "ResizePIPWindow -- end : ok"); 4986 return true; 4862 4987 } 4863 4864 SetActive(lctx, new_index);4865 4988 } 4866 4867 PlayerContext *actx = GetPlayer(lctx, -1); 4868 OSD *osd = GetOSDLock(actx); 4869 if (osd) 4870 osd->SetSettingsText(tr("Changed Active Window"), 3); 4871 ReturnOSDLock(actx, osd); 4989 VERBOSE(VB_PLAYBACK, LOC + "ResizePIPWindow -- end : !ok"); 4990 return false; 4872 4991 } 4873 4992 4874 /**4875 * \brief wake TV thread when pip player var is set in the main NVP4876 */4877 void TV::WakeSetPIPPlayerCond(void)4878 {4879 pipPlayerSetCondition.wakeAll();4880 }4881 4882 /**4883 * \brief resize PIP Window. done when changing channels or swapping PIP4884 */4885 void TV::ResizePIPWindow(PlayerContext *ctx)4886 {4887 PlayerContext *actx = GetPlayer(ctx, -1);4888 int loc = gContext->GetNumSetting("PIPLocation", 0);4889 if (actx->nvp && ctx->nvp)4890 {4891 QRect rect =4892 actx->nvp->getVideoOutput()->GetPIPRect(loc, ctx->nvp, false);4893 ctx->ResizePIPWindow(rect);4894 }4895 }4896 4897 4993 bool TV::IsPIPSupported(const PlayerContext *ctx) const 4898 4994 { 4899 4995 const PlayerContext *mctx = NULL; … … 4910 5006 return yes; 4911 5007 } 4912 5008 4913 /** 4914 * \brief Teardown all NVP's in preparation for PIP Swap or change from PIP <-> PBP4915 */4916 v oid TV::TeardownPIPWindows(PlayerContext *lctx)5009 /** \brief Teardown all NVP's in preparation for PxP Swap or 5010 * change from PIP -> PBP or PBP -> PIP 5011 */ 5012 vector<long long> TV::TeardownAllNVPs(PlayerContext *lctx) 4917 5013 { 4918 SetActive(lctx, 0); 5014 vector<long long> pos; 5015 for (uint i = 0; i < player.size(); i++) 5016 { 5017 const PlayerContext *ctx = GetPlayer(lctx, i); 5018 ctx->LockDeleteNVP(__FILE__, __LINE__); 5019 pos.push_back((ctx->nvp) ? ctx->nvp->GetFramesPlayed() : 0); 5020 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 5021 } 4919 5022 4920 5023 for (uint i = 0; i < player.size(); i++) 4921 5024 { 4922 5025 PlayerContext *ctx = GetPlayer(lctx, i); 4923 5026 ctx->PIPTeardown(); 4924 5027 } 5028 5029 return pos; 4925 5030 } 4926 5031 4927 5032 /** 5033 * \brief tear down remaining PBP video and restore 5034 * fullscreen display 5035 */ 5036 void TV::PBPRestartMainNVP(PlayerContext *mctx) 5037 { 5038 VERBOSE(VB_PLAYBACK, LOC + "PBPRestartMainNVP -- begin"); 5039 5040 mctx->LockDeleteNVP(__FILE__, __LINE__); 5041 if (!mctx->nvp || !mctx->nvp->IsPlaying() || 5042 mctx->GetPIPState() != kPBPLeft || exitPlayerTimerId) 5043 { 5044 mctx->UnlockDeleteNVP(__FILE__, __LINE__); 5045 VERBOSE(VB_PLAYBACK, LOC + "PBPRestartMainNVP -- end !ok !valid"); 5046 return; 5047 } 5048 5049 long long mctx_frame = mctx->nvp->GetFramesPlayed(); 5050 mctx->UnlockDeleteNVP(__FILE__, __LINE__); 5051 5052 mctx->PIPTeardown(); 5053 mctx->SetPIPState(kPIPOff); 5054 mctx->buffer->Seek(0, SEEK_SET); 5055 5056 if (mctx->CreateNVP(this, myWindow, mctx->GetState(), 5057 embedWinID, &embedBounds)) 5058 { 5059 ScheduleStateChange(mctx); 5060 mctx->StartOSD(this); 5061 mctx->nvp->JumpToFrame(mctx_frame); 5062 SetSpeedChangeTimer(25, __LINE__); 5063 VERBOSE(VB_PLAYBACK, LOC + "PBPRestartMainNVP -- end ok"); 5064 return; 5065 } 5066 5067 ForceNextStateNone(mctx, __LINE__); 5068 VERBOSE(VB_PLAYBACK, LOC + 5069 "PBPRestartMainNVP -- end !ok NVP did not restart"); 5070 } 5071 5072 /** 4928 5073 * \brief Recreate Main and PIP windows. Could be either PIP or PBP views. 4929 5074 */ 4930 void TV::Restart PIPWindows(PlayerContext *lctx,4931 4932 5075 void TV::RestartAllNVPs(PlayerContext *lctx, 5076 const vector<long long> &pos, 5077 MuteState mctx_mute) 4933 5078 { 4934 QString loc = LOC + QString("Restart PIPWindows()");5079 QString loc = LOC + QString("RestartAllNVPs(): "); 4935 5080 4936 5081 PlayerContext *mctx = GetPlayer(lctx, 0); 4937 5082 … … 4943 5088 if (StateIsLiveTV(mctx->GetState())) 4944 5089 mctx->buffer->Unpause(); 4945 5090 4946 bool ok = StartPlayer(mctx, mctx, mctx->GetState() , false);5091 bool ok = StartPlayer(mctx, mctx, mctx->GetState()); 4947 5092 4948 5093 if (ok) 4949 5094 { … … 4953 5098 { 4954 5099 VERBOSE(VB_IMPORTANT, loc + 4955 5100 "Failed to restart new main context (was pip context)"); 4956 ForceNextStateNone(mctx );5101 ForceNextStateNone(mctx, __LINE__); 4957 5102 return; 4958 5103 } 4959 5104 … … 4966 5111 if (StateIsLiveTV(pipctx->GetState())) 4967 5112 pipctx->buffer->Unpause(); 4968 5113 4969 ok = StartPlayer(mctx, pipctx, pipctx->GetState() , pipctx->isPIP());5114 ok = StartPlayer(mctx, pipctx, pipctx->GetState()); 4970 5115 4971 5116 if (ok) 4972 5117 { … … 4978 5123 { // TODO print OSD informing user of Swap failure ? 4979 5124 VERBOSE(VB_IMPORTANT, loc + 4980 5125 "Failed to restart new pip context (was main context)"); 4981 ForceNextStateNone(pipctx );5126 ForceNextStateNone(pipctx, __LINE__); 4982 5127 } 4983 5128 } 4984 5129 … … 4988 5133 mctx->nvp->SetMuteState(mctx_mute); 4989 5134 } 4990 5135 4991 void TV:: SwapPIP(PlayerContext *lctx, int ctx_index, bool ispbp)5136 void TV::PxPSwap(PlayerContext *mctx, int ctx_index) 4992 5137 { 4993 5138 lockTimerOn = false; 4994 5139 4995 PlayerContext *mctx = GetPlayer(lctx, 0); 4996 if (player.size() == 1) 5140 if (player.size() <= 1 || !mctx) 4997 5141 return; 4998 5142 4999 PlayerContext *pipctx = GetPlayer(lctx, ctx_index); 5143 PlayerContext *pipctx = GetPlayer(mctx, ctx_index); 5144 ctx_index = find_player_index(pipctx); 5145 if (ctx_index < 0 || !pipctx) 5146 return; 5000 5147 5001 5148 if (!mctx->nvp || !pipctx->nvp || !pipctx->nvp->IsPlaying()) 5002 5149 return; … … 5004 5151 VERBOSE(VB_PLAYBACK, LOC + "SwapPIP -- begin"); 5005 5152 5006 5153 MuteState mctx_mute = mctx->nvp->GetMuteState(); 5007 5008 vector<long long> pos;5009 for (uint i = 0; i < player.size(); i++)5010 {5011 const PlayerContext *ctx = GetPlayer(lctx, i);5012 ctx->LockDeleteNVP(__FILE__, __LINE__);5013 pos.push_back((ctx->nvp) ? ctx->nvp->GetFramesPlayed() : 0);5014 ctx->UnlockDeleteNVP(__FILE__, __LINE__);5015 }5016 5017 5154 bool useNullVideo = pipctx->UseNullVideo(); 5018 5155 5019 TeardownPIPWindows(lctx);5156 vector<long long> pos = TeardownAllNVPs(mctx); 5020 5157 5021 swap(player[0], player[ctx_index]); 5022 swap(pos[0], pos[ctx_index]); 5023 5024 pipctx->SetPIPState((ispbp) ? kPBPLeft: kPIPOff); 5025 5158 swap(player[0], player[ctx_index]); 5159 swap(pos[0], pos[ctx_index]); 5160 swap(player[0]->pipState, player[ctx_index]->pipState); 5161 playerActive = (ctx_index == playerActive) ? 5162 0 : ((ctx_index == 0) ? ctx_index : playerActive); 5163 5026 5164 if (useNullVideo) 5027 5165 mctx->SetNullVideo(true); 5028 5166 5029 mctx->SetPIPState((ispbp) ? kPBPRight: kPIPonTV); 5030 5031 RestartPIPWindows(mctx, pos, mctx_mute); 5167 RestartAllNVPs(mctx, pos, mctx_mute); 5032 5168 } 5033 5169 5034 5170 void TV::DoPlay(PlayerContext *ctx) … … 5387 5523 ctx->playingInfo->ApplyTranscoderProfileChange(profile); 5388 5524 QString jobHost = ""; 5389 5525 5390 if ( gContext->GetNumSetting("JobsRunOnRecordHost", 0))5526 if (db_run_jobs_on_remote) 5391 5527 jobHost = ctx->playingInfo->hostname; 5392 5528 5393 5529 OSD *osd = GetOSDLock(ctx); … … 5598 5734 5599 5735 if (testrec && testrec->IsValidRecorder()) 5600 5736 { 5601 // pause the decoder first, so we're not reading to close to the end. 5737 PlayerContext *mctx = GetPlayer(ctx, 0); 5738 if (mctx != ctx) 5739 PIPRemovePlayer(mctx, ctx); 5602 5740 5741 // pause the decoder first, so we're not reading too close to the end. 5603 5742 ctx->buffer->IgnoreLiveEOF(true); 5604 5743 ctx->buffer->StopReads(); 5605 5744 ctx->nvp->PauseDecoder(); … … 5609 5748 ctx->buffer->WaitForPause(); 5610 5749 ctx->nvp->StopPlaying(); 5611 5750 ctx->recorder->StopLiveTV(); 5612 { 5613 ctx->SetNVP(NULL); 5614 PlayerContext *mctx = GetPlayer(ctx, 0); 5615 if (ctx != mctx) 5616 SetPIPPlayer(mctx, ctx); 5617 } 5751 ctx->SetNVP(NULL); 5618 5752 5619 5753 // now restart stuff 5620 5754 ctx->lastSignalUIInfo.clear(); … … 5658 5792 ok = true; 5659 5793 ctx->StartOSD(this); 5660 5794 ctx->PushPreviousChannel(); 5661 if (ctx && (player.size() > 1)) 5662 { 5663 if (0 == playerActive) 5664 { 5665 PlayerContext *ctx1 = GetPlayer(ctx, 1); 5666 SetPIPPlayer(mctx, ctx1); 5667 } 5668 else 5669 { 5670 PlayerContext *mctx = GetPlayer(ctx, 0); 5671 SetPIPPlayer(mctx, ctx); 5672 } 5673 } 5795 for (uint i = 1; i < player.size(); i++) 5796 PIPAddPlayer(mctx, GetPlayer(ctx, i)); 5674 5797 5675 5798 SetSpeedChangeTimer(25, __LINE__); 5676 5799 } … … 6957 7080 margin = margin * 5; 6958 7081 QDomElement xmldata; 6959 7082 XMLParse *theme = new XMLParse(); 6960 if (!allowembed || 6961 !theme->LoadTheme(xmldata, str) || 6962 !gContext->GetNumSetting("ContinueEmbeddedTVPlay", 0) || 6963 ctx->nvp->IsNearEnd(margin) || 6964 ctx->paused) 7083 if (!allowembed || !theme->LoadTheme(xmldata, str) || 7084 !db_continue_embedded || ctx->nvp->IsNearEnd(margin) || ctx->paused) 6965 7085 { 6966 7086 if (!stayPaused) 6967 7087 DoPause(ctx, false); … … 6976 7096 6977 7097 void TV::DoEditSchedule(int editType) 6978 7098 { 6979 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 6980 mctx->LockPlayingInfo(__FILE__, __LINE__); 6981 if (!mctx->playingInfo) 7099 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 7100 7101 actx->LockPlayingInfo(__FILE__, __LINE__); 7102 if (!actx->playingInfo) 6982 7103 { 6983 7104 VERBOSE(VB_IMPORTANT, 6984 LOC_ERR + "doEditSchedule(): no active mctx->playingInfo.");6985 mctx->UnlockPlayingInfo(__FILE__, __LINE__);6986 ReturnPlayerLock( mctx);7105 LOC_ERR + "doEditSchedule(): no active ctx playingInfo."); 7106 actx->UnlockPlayingInfo(__FILE__, __LINE__); 7107 ReturnPlayerLock(actx); 6987 7108 return; 6988 7109 } 6989 7110 6990 7111 // Collect channel info 6991 uint chanid = mctx->playingInfo->chanid.toUInt();6992 QString channum = mctx->playingInfo->chanstr;6993 mctx->UnlockPlayingInfo(__FILE__, __LINE__);7112 uint chanid = actx->playingInfo->chanid.toUInt(); 7113 QString channum = actx->playingInfo->chanstr; channum.detach(); 7114 actx->UnlockPlayingInfo(__FILE__, __LINE__); 6994 7115 6995 ClearOSD( mctx);7116 ClearOSD(actx); 6996 7117 6997 7118 // Resize window to the MythTV GUI size 6998 7119 PlayerContext *mctx = GetPlayer(actx, 0); 6999 7120 if (mctx->nvp && mctx->nvp->getVideoOutput()) 7000 7121 mctx->nvp->getVideoOutput()->ResizeForGui(); 7001 7122 MythMainWindow *mwnd = gContext->GetMainWindow(); 7002 bool using_gui_size_for_tv = gContext->GetNumSetting("GuiSizeForTV", 0); 7003 if (! using_gui_size_for_tv)7123 7124 if (!db_use_gui_size_for_tv) 7004 7125 { 7005 7126 mwnd->setGeometry(saved_gui_bounds.left(), saved_gui_bounds.top(), 7006 7127 saved_gui_bounds.width(), saved_gui_bounds.height()); … … 7026 7147 player = this; 7027 7148 if (StateIsLiveTV(GetState(mctx))) 7028 7149 { 7029 ReturnPlayerLock( mctx);7150 ReturnPlayerLock(actx); 7030 7151 changeChannel = GuideGrid::Run(chanid, channum, false, 7031 7152 player, allowsecondary); 7032 mctx = GetPlayerReadLock(0, __FILE__, __LINE__);7153 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7033 7154 } 7034 7155 else 7035 7156 { 7036 ReturnPlayerLock( mctx);7157 ReturnPlayerLock(actx); 7037 7158 GuideGrid::Run(chanid, channum, false, player); 7038 mctx = GetPlayerReadLock(0, __FILE__, __LINE__);7159 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7039 7160 } 7040 7161 break; 7041 7162 } 7042 7163 case kScheduleProgramFinder: 7043 7164 if (!mctx->paused) 7044 7165 DoPause(mctx, false); 7166 ReturnPlayerLock(actx); 7045 7167 RunProgramFind(false, false); 7168 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7046 7169 break; 7047 7170 case kScheduledRecording: 7048 7171 { 7049 7172 if (mctx->paused) 7050 7173 DoPause(mctx, false); 7174 7051 7175 mctx->LockPlayingInfo(__FILE__, __LINE__); 7176 const ProgramInfo pginfo(*mctx->playingInfo); 7177 mctx->UnlockPlayingInfo(__FILE__, __LINE__); 7178 ReturnPlayerLock(actx); 7179 7052 7180 ScheduledRecording *record = new ScheduledRecording(); 7053 record->loadByProgram( mctx->playingInfo);7181 record->loadByProgram(&pginfo); 7054 7182 record->exec(); 7055 7183 record->deleteLater(); 7056 mctx->UnlockPlayingInfo(__FILE__, __LINE__); 7184 7185 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7057 7186 break; 7058 7187 } 7059 7188 case kViewSchedule: 7060 7189 { 7061 7190 showvideo = VideoThemeCheck(mctx, "conflict-video", stayPaused); 7191 ReturnPlayerLock(actx); 7062 7192 RunViewScheduledPtr((void *)this, showvideo); 7193 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7063 7194 break; 7064 7195 } 7065 7196 case kPlaybackBox: 7066 7197 { 7067 7198 showvideo = VideoThemeCheck(mctx, "playback-video", stayPaused); 7199 ReturnPlayerLock(actx); 7068 7200 nextProgram = RunPlaybackBoxPtr((void *)this, showvideo); 7201 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7069 7202 } 7070 7203 } 7071 7204 … … 7080 7213 embedCheckTimerId = 0; 7081 7214 } 7082 7215 7083 if (StateIsPlaying(GetState(mctx)) && 7216 VERBOSE(VB_PLAYBACK, LOC 7217 <<"state: "<<StateToString(GetState(mctx)) 7218 <<"!stayPaused: "<<stayPaused<<" mctx->paused: "<<mctx->paused); 7219 if ((StateIsPlaying(GetState(mctx)) || StateIsLiveTV(GetState(mctx))) && 7084 7220 !stayPaused && mctx->paused) 7085 7221 { 7222 VERBOSE(VB_PLAYBACK, LOC + "Unpausing video"); 7223 // this should unpause video.. 7086 7224 DoPause(mctx, true); 7087 7225 } 7088 ReturnPlayerLock( mctx);7226 ReturnPlayerLock(actx); 7089 7227 7090 7228 mctx = GetPlayerWriteLock(0, __FILE__, __LINE__); 7091 7229 if (nextProgram) 7092 7230 { 7093 if ( nextProgPIPState == kPIPonTV)7231 if (jumpToProgramPIPState == kPIPonTV) 7094 7232 CreatePIP(mctx, nextProgram); 7095 else if ( nextProgPIPState == kPBPLeft)7233 else if (jumpToProgramPIPState == kPBPLeft) 7096 7234 CreatePBP(mctx, nextProgram); 7097 7235 else 7098 7236 { 7099 setLastProgram(nextProgram);7237 SetLastProgram(nextProgram); 7100 7238 jumpToProgram = true; 7101 7239 SetExitPlayer(true, true); 7102 7240 } 7103 7241 mctx = GetPlayer(mctx, 0); // CreatePBP/PIP mess with ctx's 7104 7242 7105 nextProgPIPState = kPIPOff;7243 jumpToProgramPIPState = kPIPOff; 7106 7244 delete nextProgram; 7107 7245 nextProgram = NULL; 7108 7246 } … … 7110 7248 7111 7249 mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 7112 7250 // Resize the window back to the MythTV Player size 7113 if (! using_gui_size_for_tv)7251 if (!db_use_gui_size_for_tv) 7114 7252 { 7115 7253 mwnd->setGeometry(player_bounds.left(), player_bounds.top(), 7116 7254 player_bounds.width(), player_bounds.height()); … … 7132 7270 7133 7271 void TV::EditSchedule(const PlayerContext *ctx, int editType) 7134 7272 { 7135 if (ctx && (player.size() > 1))7136 return;7137 7138 7273 // post the request to the main UI thread 7139 7274 // it will be caught in eventFilter and processed as CustomEvent 7140 7275 // this will create the program guide window (widget) … … 7494 7629 { 7495 7630 ctx->nvp->SetWatchingRecording(false); 7496 7631 ctx->nvp->SetLength(filelen); 7497 ctx->ChangeState(kState_WatchingPreRecorded );7632 ctx->ChangeState(kState_WatchingPreRecorded, __LINE__); 7498 7633 ScheduleStateChange(ctx); 7499 7634 } 7500 7635 } … … 7644 7779 7645 7780 if (message.left(12) == "EXIT_TO_MENU") 7646 7781 { 7647 int exitprompt = gContext->GetNumSetting("PlaybackExitPrompt");7648 7649 7782 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 7650 7783 for (uint i = 0; mctx && (i < player.size()); i++) 7651 7784 { 7652 7785 PlayerContext *ctx = GetPlayer(mctx, i); 7653 7786 if (!ctx->nvp) 7654 7787 continue; 7655 if ( exitprompt == 1 || exitprompt == 2)7788 if (db_playback_exit_prompt == 1 || db_playback_exit_prompt == 2) 7656 7789 ctx->nvp->SetBookmark(); 7657 if (ctx->nvp && gContext->GetNumSetting("AutomaticSetWatched", 0))7790 if (ctx->nvp && db_auto_set_watched) 7658 7791 ctx->nvp->SetWatched(); 7659 7792 } 7660 7793 … … 7733 7866 } 7734 7867 } 7735 7868 7736 i nt player_cnt = 0;7869 if (message.left(9) == "START_EPG") 7737 7870 { 7738 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__);7739 player_cnt = player.size();7740 ReturnPlayerLock(mctx);7741 }7742 7743 if (message.left(9) == "START_EPG" && (1 == player_cnt))7744 {7745 7871 int editType = tokens[1].toInt(); 7746 7872 DoEditSchedule(editType); 7747 7873 } … … 7844 7970 browsechannum = ctx->playingInfo->chanstr; 7845 7971 browsechanid = ctx->playingInfo->chanid; 7846 7972 browsestarttime = ctx->playingInfo->startts.toString(); 7973 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 7847 7974 7848 7975 BrowseDispInfo(ctx, BROWSE_SAME); 7849 7976 … … 7852 7979 KillTimer(browseTimerId); 7853 7980 browseTimerId = StartTimer(kBrowseTimeout, __LINE__); 7854 7981 } 7855 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 7982 else 7983 { 7984 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 7985 } 7856 7986 } 7857 7987 7858 7988 /** \fn TV::BrowseEnd(PlayerContext*, bool) … … 7986 8116 QString cmdmsg(""); 7987 8117 if (ctx->playingInfo->GetAutoExpireFromRecorded() == kLiveTVAutoExpire) 7988 8118 { 7989 int autoexpiredef = gContext->GetNumSetting("AutoExpireDefault", 0); 7990 ctx->playingInfo->SetAutoExpire(autoexpiredef); 8119 ctx->playingInfo->SetAutoExpire(db_autoexpire_default); 7991 8120 ctx->playingInfo->ApplyRecordRecGroupChange("Default"); 7992 8121 cmdmsg = tr("Record"); 7993 8122 ctx->SetPseudoLiveTV(ctx->playingInfo, kPseudoRecording); … … 8155 8284 SetUpdateOSDPosition(false); 8156 8285 } 8157 8286 8158 void TV::SetActive(PlayerContext *ctx, int index) 8287 #include <cassert> 8288 void TV::SetActive(PlayerContext *lctx, int index, bool osd_msg) 8159 8289 { 8160 VERBOSE(VB_PLAYBACK, "TV::SetActive -- begin"); 8290 assert(lctx); 8291 if (!lctx) 8292 return; 8161 8293 8294 QString loc = LOC + QString("SetActive(%1,%2) was %3") 8295 .arg(index).arg((osd_msg) ? "with OSD" : "w/o OSD").arg(playerActive); 8296 8297 VERBOSE(VB_PLAYBACK, loc + " -- begin"); 8298 8162 8299 if (playerActive == index) 8163 8300 { 8164 VERBOSE(VB_PLAYBACK, "TV::SetActive -- index == active context");8301 VERBOSE(VB_PLAYBACK, loc + " -- end (index == playerActive)"); 8165 8302 return; 8166 8303 } 8167 8304 8168 VERBOSE(VB_PLAYBACK, "TV::SetActive -- lock"); 8305 index = (index < 0) ? (playerActive+1) % player.size() : index; 8306 index = (index >= (int)player.size()) ? 0 : index; 8169 8307 8170 PlayerContext *actx = NULL;8308 playerActive = index; 8171 8309 8172 if (playerActive > -1 && !ctx)8310 for (int i = 0; i < (int)player.size(); i++) 8173 8311 { 8174 actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 8175 ReturnPlayerLock(actx); 8312 PlayerContext *ctx = GetPlayer(lctx, i); 8313 ctx->LockDeleteNVP(__FILE__, __LINE__); 8314 if (ctx->nvp) 8315 ctx->nvp->SetPIPActive(i == playerActive); 8316 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 8176 8317 } 8177 8318 8178 VERBOSE(VB_PLAYBACK, 8179 QString("TV::SetActive changing playerActive " 8180 "from %1 to %2") 8181 .arg(playerActive).arg(index)); 8182 8183 playerActive = index; 8184 8185 if (!ctx) 8319 #if 0 8320 // seems reduntant, except maybe for main player? -dtk 8321 if (osd_msg) 8186 8322 { 8187 actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 8188 ReturnPlayerLock(actx); 8323 PlayerContext *actx = GetPlayer(lctx, -1); 8324 OSD *osd = GetOSDLock(actx); 8325 if (osd) 8326 osd->SetSettingsText(tr("Active").arg(playerActive), 3); 8327 ReturnOSDLock(actx, osd); 8189 8328 } 8329 #endif 8330 8331 VERBOSE(VB_PLAYBACK, loc + " -- end"); 8190 8332 } 8191 8333 8192 8334 void TV::TreeMenuEntered(OSDListTreeType *tree, OSDGenericTree *item) … … 8733 8875 EditSchedule(actx, kScheduleProgramFinder); 8734 8876 else if (action == "SCHEDULE") 8735 8877 EditSchedule(actx, kScheduledRecording); 8736 else if ((action == "JUMPPREV") ||8737 ((action == "PREVCHAN") && (!StateIsLiveTV(GetState(actx)))))8738 {8739 if (PromptRecGroupPassword(actx))8740 {8741 actx->nvp->SetBookmark();8742 jumpToProgram = true;8743 SetExitPlayer(true, true);8744 }8745 }8746 8878 else if (action == "VIEWSCHEDULED") 8747 8879 EditSchedule(actx, kViewSchedule); 8748 else if ( action == "JUMPREC")8880 else if (HandleJumpToProgramAction(actx, QStringList(action))) 8749 8881 { 8750 if (gContext->GetNumSetting("JumpToProgramOSD", 1) &&8751 StateIsPlaying(actx->GetState()))8752 {8753 if (jumpMenuTimerId)8754 KillTimer(jumpMenuTimerId);8755 jumpMenuTimerId = StartTimer(1, __LINE__);8756 }8757 else if (RunPlaybackBoxPtr)8758 EditSchedule(actx, kPlaybackBox);8759 8882 } 8760 else if ( action == "TOGGLEPIPMODE")8883 else if (PxPHandleAction(actx, QStringList(action))) 8761 8884 { 8762 ReturnPlayerLock(actx); 8885 // Hide the tree on this old active context.. 8886 tree->SetVisible(false); 8887 tree->disconnect(); 8888 OSD *osd = GetOSDLock(actx); 8889 if (osd) 8890 osd->HideTreeMenu(); 8891 ReturnOSDLock(actx, osd); 8892 ClearOSD(actx); 8763 8893 8764 actx = GetPlayerWriteLock(-1, __FILE__, __LINE__); 8765 TogglePIPView(actx); 8766 ReturnPlayerLock(actx); 8894 hidetree = true; 8767 8895 8768 actx = GetPlayer ReadLock(-1, __FILE__, __LINE__);8896 actx = GetPlayer(actx,-1); // "NEXTPIPWINDOW" changes active context.. 8769 8897 } 8770 else if (action == "TOGGLEPBPMODE")8771 {8772 needToMakePIPChange = kPBPToggle;8773 if (pipChangeTimerId)8774 KillTimer(pipChangeTimerId);8775 pipChangeTimerId = StartTimer(1, __LINE__);8776 }8777 else if (action == "TOGGLEPIPWINDOW")8778 ToggleActiveWindow(actx, 1);8779 else if (action == "TOGGLEPIPSTATE")8780 {8781 needToMakePIPChange = (actx->isPBP()) ? kPBPToPIP : kPIPToPBP;8782 if (pipChangeTimerId)8783 KillTimer(pipChangeTimerId);8784 pipChangeTimerId = StartTimer(1, __LINE__);8785 }8786 else if (action == "SWAPPIP")8787 {8788 needToMakePIPChange = (actx->isPBP()) ? kPBPSwap : kPIPSwap;8789 if (pipChangeTimerId)8790 KillTimer(pipChangeTimerId);8791 pipChangeTimerId = StartTimer(1, __LINE__);8792 }8793 8898 else if (StateIsLiveTV(GetState(actx))) 8794 8899 { 8795 8900 if (action == "TOGGLEBROWSE") … … 8833 8938 DoQueueTranscode(actx, "Medium Quality"); 8834 8939 else if (action == "QUEUETRANSCODE_LOW") 8835 8940 DoQueueTranscode(actx, "Low Quality"); 8836 else if (action.left(8) == "JUMPPROG")8837 {8838 SetJumpToProgram(action.section(" ",1,-2),8839 action.section(" ",-1,-1).toInt());8840 actx->nvp->SetBookmark();8841 jumpToProgram = true;8842 SetExitPlayer(true, true);8843 }8844 8941 else 8845 8942 { 8846 8943 VERBOSE(VB_IMPORTANT, LOC_ERR + … … 8901 8998 delete treeMenu; 8902 8999 8903 9000 treeMenu = new OSDGenericTree(NULL, "treeMenu"); 8904 OSDGenericTree *item, *subitem;8905 9001 8906 9002 bool freeRecorders = RemoteGetFreeRecorderCount(); 8907 9003 8908 if (IsPIPSupported(ctx) && ((ctx && (player.size() > 1)) || freeRecorders))8909 {8910 // Picture-in-Picture8911 item = new OSDGenericTree(treeMenu, tr("Picture-in-Picture"));8912 if (ctx && (player.size() == 1))8913 {8914 subitem = new OSDGenericTree(item, tr("Enable PIP"),8915 "TOGGLEPIPMODE");8916 subitem = new OSDGenericTree(item, tr("Enable PBP"),8917 "TOGGLEPBPMODE");8918 }8919 else8920 {8921 QString option = "Disable ";8922 QString switchTo = "Switch to ";8923 QString pipType = (ctx->isPBP()) ? "PBP" : "PIP";8924 QString changeTo = (ctx->isPBP()) ? "PIP" : "PBP";8925 option += pipType;8926 switchTo += changeTo;8927 QString toggleMode = QString("TOGGLE%1MODE").arg(pipType);8928 subitem = new OSDGenericTree(item, option, toggleMode);8929 subitem = new OSDGenericTree(item, tr("Swap Windows"),8930 "SWAPPIP");8931 subitem = new OSDGenericTree(item, tr("Change Active Window"),8932 "TOGGLEPIPWINDOW");8933 subitem = new OSDGenericTree(item, switchTo, "TOGGLEPIPSTATE");8934 }8935 }8936 8937 9004 if (freeRecorders && ctx->recorder) 8938 9005 { 8939 9006 // Input switching … … 9011 9078 } 9012 9079 } 9013 9080 9081 FillMenuPxP(ctx, treeMenu, freeRecorders); 9082 9014 9083 if ((ctx != GetPlayer(ctx, 0))) 9015 9084 return; 9016 9085 … … 9161 9230 new OSDGenericTree(s_item, "120 " + tr("minutes"), "TOGGLESLEEP120"); 9162 9231 } 9163 9232 9164 void TV::FillMenuLiveTV(OSDGenericTree *treeMenu) 9233 /// \brief Constructs Picture-X-Picture portion of menu 9234 void TV::FillMenuPxP( 9235 const PlayerContext *ctx, OSDGenericTree *treeMenu, bool freeRecorders) 9165 9236 { 9166 new OSDGenericTree(treeMenu, tr("Program Guide"), "GUIDE"); 9237 if (!ctx || !IsPIPSupported(ctx)) 9238 return; 9167 9239 9168 if (!gContext->GetNumSetting("JumpToProgramOSD", 1)) 9240 if ((player.size() <= 1) && !freeRecorders) 9241 return; 9242 9243 OSDGenericTree *item = 9244 new OSDGenericTree(treeMenu, tr("Picture-in-Picture")); 9245 9246 if (freeRecorders) 9169 9247 { 9170 OSDGenericTree *jtpo_item = 9171 new OSDGenericTree(treeMenu, tr("Jump to Program")); 9172 new OSDGenericTree(jtpo_item, tr("Recorded Program"), "JUMPREC"); 9173 if (lastProgram != NULL) 9174 new OSDGenericTree(jtpo_item, lastProgram->title, "JUMPPREV"); 9248 if (player.size() <= kMaxPIPCount) 9249 new OSDGenericTree(item, tr("Open Live TV PIP"), "CREATEPIPVIEW"); 9250 if (player.size() <= kMaxPBPCount) 9251 new OSDGenericTree(item, tr("Open Live TV PBP"), "CREATEPBPVIEW"); 9175 9252 } 9176 9253 9254 if (player.size() <= kMaxPIPCount) 9255 new OSDGenericTree(item, tr("Open Recording PIP"), "JUMPRECPIP"); 9256 if (player.size() <= kMaxPBPCount) 9257 new OSDGenericTree(item, tr("Open Recording PBP"), "JUMPRECPBP"); 9258 9259 if (player.size() <= 1) 9260 return; 9261 9262 new OSDGenericTree(item, tr("Change Active Window"), "NEXTPIPWINDOW"); 9263 9264 QString pipType = (ctx->isPBP()) ? "PBP" : "PIP"; 9265 QString toggleMode = QString("TOGGLE%1MODE").arg(pipType); 9266 9267 bool isPBP = ctx->isPBP(); 9268 const PlayerContext *mctx = GetPlayer(ctx, 0); 9269 QString pipClose = (isPBP) ? tr("Close PBP") : tr("Close PIP"); 9270 if (mctx == ctx) 9271 { 9272 if (player.size() > 2) 9273 pipClose = (isPBP) ? tr("Close PBPs") : tr("Close PIPs"); 9274 9275 new OSDGenericTree(item, pipClose, toggleMode); 9276 9277 if (player.size() == 2) 9278 new OSDGenericTree(item, tr("Swap Windows"), "SWAPPIP"); 9279 } 9280 else 9281 { 9282 new OSDGenericTree(item, pipClose, toggleMode); 9283 new OSDGenericTree(item, tr("Swap Windows"), "SWAPPIP"); 9284 } 9285 9286 uint max_cnt = min(kMaxPBPCount, kMaxPIPCount); 9287 if (player.size() <= max_cnt) 9288 { 9289 QString switchTo = (isPBP) ? tr("Switch to PIP") : tr("Switch to PBP"); 9290 new OSDGenericTree(item, switchTo, "TOGGLEPIPSTATE"); 9291 } 9292 } 9293 9294 9295 void TV::FillMenuLiveTV(OSDGenericTree *treeMenu) 9296 { 9297 new OSDGenericTree(treeMenu, tr("Program Guide"), "GUIDE"); 9298 9299 OSDGenericTree *jtpo_item = 9300 new OSDGenericTree(treeMenu, tr("Jump to Program")); 9301 new OSDGenericTree(jtpo_item, tr("Recorded Program"), "JUMPREC"); 9302 if (lastProgram != NULL) 9303 new OSDGenericTree(jtpo_item, lastProgram->title, "JUMPPREV"); 9304 9177 9305 if (!persistentbrowsemode) 9178 9306 new OSDGenericTree(treeMenu, tr("Enable Browse Mode"), "TOGGLEBROWSE"); 9179 9307 … … 9403 9531 ReturnOSDLock(ctx, osd); 9404 9532 } 9405 9533 9406 void TV::SetJumpToProgram(QString progKey, int progIndex) 9534 bool TV::HandleJumpToProgramAction( 9535 PlayerContext *ctx, const QStringList &actions) 9407 9536 { 9408 QMap<QString,ProgramList>::Iterator Iprog; 9409 Iprog = progLists.find(progKey); 9410 ProgramList plist = *Iprog; 9411 ProgramInfo *p = plist.at(progIndex); 9412 VERBOSE(VB_IMPORTANT, QString("Switching to program: %1: %2") 9413 .arg(p->title).arg(p->subtitle)); 9414 setLastProgram(p); 9537 const PlayerContext *mctx = GetPlayer(ctx, 0); 9538 TVState s = ctx->GetState(); 9539 if (has_action("JUMPPREV", actions) || 9540 (has_action("PREVCHAN", actions) && !StateIsLiveTV(s))) 9541 { 9542 if (PromptRecGroupPassword(ctx)) 9543 { 9544 if (mctx == ctx) 9545 { 9546 ctx->LockDeleteNVP(__FILE__, __LINE__); 9547 ctx->nvp->SetBookmark(); 9548 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 9549 jumpToProgram = true; 9550 SetExitPlayer(true, true); 9551 } 9552 else 9553 { 9554 // TODO 9555 } 9556 } 9557 return true; 9558 } 9559 9560 QStringList::const_iterator it = actions.begin(); 9561 for (; it != actions.end(); ++it) 9562 { 9563 if ((*it).left(8) != "JUMPPROG") 9564 continue; 9565 9566 const QString &action = *it; 9567 9568 bool ok; 9569 QString progKey = action.section(" ",1,-2); 9570 uint progIndex = action.section(" ",-1,-1).toUInt(&ok); 9571 ProgramInfo *p = NULL; 9572 9573 if (!ok) 9574 { 9575 QMutexLocker locker(&progListsLock); 9576 QMap<QString,ProgramList>::const_iterator it = 9577 progLists.find(progKey); 9578 if (it != progLists.end()) 9579 { 9580 const ProgramInfo *tmp = (*it)[progIndex]; 9581 if (tmp) 9582 p = new ProgramInfo(*tmp); 9583 } 9584 } 9585 9586 if (!p) 9587 { 9588 VERBOSE(VB_IMPORTANT, LOC_ERR + 9589 QString("Failed to locate jump to program '%1' @ %2") 9590 .arg(progKey).arg(action.section(" ",-1,-1).toUInt(&ok))); 9591 return true; 9592 } 9593 9594 PIPState state = kPIPOff; 9595 { 9596 QMutexLocker locker(&timerIdLock); 9597 state = jumpToProgramPIPState; 9598 } 9599 9600 if (kPIPOff == state) 9601 { 9602 if (mctx == ctx) 9603 { 9604 VERBOSE(VB_GENERAL, LOC + 9605 QString("Switching to program: %1: %2") 9606 .arg(p->title).arg(p->subtitle)); 9607 9608 SetLastProgram(p); 9609 ctx->LockDeleteNVP(__FILE__, __LINE__); 9610 ctx->nvp->SetBookmark(); 9611 ctx->UnlockDeleteNVP(__FILE__, __LINE__); 9612 jumpToProgram = true; 9613 SetExitPlayer(true, true); 9614 } 9615 else 9616 { 9617 // TODO 9618 } 9619 } 9620 else 9621 { 9622 QString type = (kPIPonTV == jumpToProgramPIPState) ? "PIP" : "PBP"; 9623 VERBOSE(VB_GENERAL, LOC + QString("Creating %1 with program: %2: %3") 9624 .arg(type).arg(p->title).arg(p->subtitle)); 9625 9626 if (jumpToProgramPIPState == kPIPonTV) 9627 CreatePIP(ctx, p); 9628 else if (jumpToProgramPIPState == kPBPLeft) 9629 CreatePBP(ctx, p); 9630 } 9631 9632 delete p; 9633 9634 return true; 9635 } 9636 9637 bool wants_jump = has_action("JUMPREC", actions); 9638 bool wants_pip = !wants_jump && has_action("JUMPRECPIP", actions); 9639 bool wants_pbp = !wants_jump && !wants_pip && 9640 has_action("JUMPRECPBP", actions); 9641 9642 if (!wants_jump && !wants_pip && !wants_pbp) 9643 return false; 9644 9645 { 9646 QMutexLocker locker(&timerIdLock); 9647 jumpToProgramPIPState = wants_pip ? kPIPonTV : 9648 (wants_pbp ? kPBPLeft : kPIPOff); 9649 } 9650 9651 if (db_jump_prefer_osd && (StateIsPlaying(s) || StateIsLiveTV(s))) 9652 { 9653 QMutexLocker locker(&timerIdLock); 9654 if (jumpMenuTimerId) 9655 KillTimer(jumpMenuTimerId); 9656 jumpMenuTimerId = StartTimer(1, __LINE__); 9657 } 9658 else if (RunPlaybackBoxPtr) 9659 EditSchedule(ctx, kPlaybackBox); 9660 else 9661 VERBOSE(VB_IMPORTANT, "Failed to open jump to program GUI"); 9662 9663 return true; 9415 9664 } 9416 9665 9417 9666 void TV::ToggleSleepTimer(const PlayerContext *ctx, const QString &time) … … 9769 10018 9770 10019 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 9771 10020 9772 if (isDVD && (!gContext->GetNumSetting("EnableDVDBookmark", 0) || 9773 ctx->buffer->DVD()->GetTotalTimeOfTitle() < 120)) 9774 { 9775 return false; 9776 } 9777 9778 return true; 10021 return (!isDVD || (db_use_dvd_bookmark && 10022 ctx->buffer->DVD()->GetTotalTimeOfTitle() >= 120)); 9779 10023 } 9780 10024 9781 10025 /* \fn TV::IsDeleteAllowed(const PlayerContext*) const … … 9917 10161 dialogname == "exitplayoptions"); 9918 10162 } 9919 10163 9920 void TV:: setLastProgram(ProgramInfo *rcinfo)10164 void TV::SetLastProgram(ProgramInfo *rcinfo) 9921 10165 { 10166 QMutexLocker locker(&lastProgramLock); 10167 9922 10168 if (lastProgram) 9923 10169 delete lastProgram; 9924 10170 … … 9928 10174 lastProgram = NULL; 9929 10175 } 9930 10176 10177 ProgramInfo *TV::GetLastProgram(void) const 10178 { 10179 QMutexLocker locker(&lastProgramLock); 10180 if (lastProgram) 10181 return new ProgramInfo(*lastProgram); 10182 return NULL; 10183 } 10184 9931 10185 QString TV::GetRecordingGroup(int player_idx) const 9932 10186 { 9933 10187 QString ret = QString::null; … … 10022 10276 treeMenu = new OSDGenericTree(NULL, "treeMenu"); 10023 10277 10024 10278 // Build jumpMenu of recorded program titles 10025 ProgramInfo *p;10279 QMutexLocker locker(&progListsLock); 10026 10280 progLists.clear(); 10027 vector<ProgramInfo *> *infoList; 10028 infoList = RemoteGetRecordedList(false); 10281 vector<ProgramInfo *> *infoList = RemoteGetRecordedList(false); 10029 10282 10030 10283 //bool LiveTVInAllPrograms = gContext->GetNumSetting("LiveTVInAllPrograms",0); 10031 10284 if (infoList) 10032 10285 { 10033 10286 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 10034 10287 actx->LockPlayingInfo(__FILE__, __LINE__); 10035 vector<ProgramInfo *>:: iterator i= infoList->begin();10036 for ( ; i != infoList->end(); i++)10288 vector<ProgramInfo *>::const_iterator it = infoList->begin(); 10289 for ( ; it != infoList->end(); it++) 10037 10290 { 10038 p = *i;10039 10291 //if (p->recgroup != "LiveTV" || LiveTVInAllPrograms) 10040 if ( p->recgroup == actx->playingInfo->recgroup)10041 progLists[ p->title].prepend(p);10292 if ((*it)->recgroup == actx->playingInfo->recgroup) 10293 progLists[(*it)->title].push_front(new ProgramInfo(*(*it))); 10042 10294 } 10043 10295 actx->UnlockPlayingInfo(__FILE__, __LINE__); 10044 10296 ReturnPlayerLock(actx); 10045 10297 10046 QMap<QString,ProgramList>:: Iterator Iprog;10298 QMap<QString,ProgramList>::const_iterator Iprog; 10047 10299 for (Iprog = progLists.begin(); Iprog != progLists.end(); Iprog++) 10048 10300 { 10049 ProgramListplist = *Iprog;10301 const ProgramList &plist = *Iprog; 10050 10302 int progIndex = plist.count(); 10051 10303 if (progIndex == 1) 10052 10304 { … … 10061 10313 10062 10314 for (int i = 0; i < progIndex; i++) 10063 10315 { 10064 p = plist.at(i);10065 if ( p->subtitle.size())10316 const ProgramInfo *p = plist[i]; 10317 if (!p->subtitle.isEmpty()) 10066 10318 new OSDGenericTree(j_item, p->subtitle, 10067 10319 QString("JUMPPROG %1 %2").arg(Iprog.key()).arg(i)); 10068 10320 else … … 10072 10324 } 10073 10325 } 10074 10326 } 10327 while (!infoList->empty()) 10328 { 10329 delete infoList->back(); 10330 infoList->pop_back(); 10331 } 10332 delete infoList; 10075 10333 10076 10334 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 10077 10335 OSD *osd = GetOSDLock(actx); … … 10093 10351 } 10094 10352 } 10095 10353 ReturnOSDLock(actx, osd); 10096 10354 ReturnPlayerLock(actx); 10097 10355 } 10098 10356 10099 10357 void TV::RestoreScreenSaver(const PlayerContext *ctx) … … 10104 10362 10105 10363 void TV::InitUDPNotifyEvent(void) 10106 10364 { 10107 uint udp_port = gContext->GetNumSetting("UDPNotifyPort"); 10108 if (udp_port && !udpnotify) 10365 if (db_udpnotify_port && !udpnotify) 10109 10366 { 10110 udpnotify = new UDPNotify( udp_port);10367 udpnotify = new UDPNotify(db_udpnotify_port); 10111 10368 connect(udpnotify, 10112 10369 SIGNAL(AddUDPNotifyEvent( 10113 10370 const QString&,const UDPNotifyOSDSet*)), … … 10242 10499 { 10243 10500 playerLock.lockForWrite(); 10244 10501 10502 //VERBOSE(VB_IMPORTANT, LOC_WARN + 10503 // QString("GetPlayerWriteLock(%1,%2,%3) size(%4)") 10504 // .arg(which).arg(file).arg(location).arg(player.size())); 10505 10245 10506 if ((which >= (int)player.size())) 10246 10507 { 10247 10508 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 10257 10518 { 10258 10519 playerLock.lockForRead(); 10259 10520 10521 //VERBOSE(VB_IMPORTANT, LOC_WARN + 10522 // QString("GetPlayerReadLock(%1,%2,%3) size(%4)") 10523 // .arg(which).arg(file).arg(location).arg(player.size())); 10524 10260 10525 if ((which >= (int)player.size())) 10261 10526 { 10262 10527 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 10273 10538 { 10274 10539 playerLock.lockForRead(); 10275 10540 10541 //VERBOSE(VB_IMPORTANT, LOC_WARN + 10542 // QString("GetPlayerReadLock(%1,%2,%3) const size(%4)") 10543 // .arg(which).arg(file).arg(location).arg(player.size())); 10544 10276 10545 if ((which >= (int)player.size())) 10277 10546 { 10278 10547 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 10320 10589 10321 10590 void TV::ReturnPlayerLock(PlayerContext *&ctx) 10322 10591 { 10592 //VERBOSE(VB_IMPORTANT, LOC_WARN + 10593 // QString("ReturnPlayerLock() size(%4)") 10594 // .arg(player.size())); 10595 10323 10596 playerLock.unlock(); 10324 10597 ctx = NULL; 10325 10598 } 10326 10599 10327 10600 void TV::ReturnPlayerLock(const PlayerContext *&ctx) const 10328 10601 { 10602 //VERBOSE(VB_IMPORTANT, LOC_WARN + 10603 // QString("ReturnPlayerLock() const size(%4)") 10604 // .arg(player.size())); 10605 10329 10606 playerLock.unlock(); 10330 10607 ctx = NULL; 10331 10608 } -
libs/libmythtv/videoout_null.cpp
217 217 218 218 void VideoOutputNull::ProcessFrame(VideoFrame *frame, OSD *osd, 219 219 FilterChain *filterList, 220 NuppelVideoPlayer *pipPlayer)220 const PIPMap &pipPlayers) 221 221 { 222 222 (void)frame; 223 223 (void)osd; 224 224 (void)filterList; 225 (void)pipPlayer ;225 (void)pipPlayers; 226 226 } -
libs/libmythtv/videoouttypes.h
11 11 kPIPOff = 0, 12 12 kPIPonTV, 13 13 kPIPStandAlone, 14 kPIPSwap,15 14 kPBPLeft, 16 15 kPBPRight, 17 kPBPSwap,18 kPIPToPBP,19 kPBPToPIP,20 kPBPToggle21 16 } PIPState; 22 17 23 18 typedef enum PIPLocation -
libs/libmythtv/videooutbase.cpp
267 267 pip_desired_display_size(160,128), pip_display_size(0,0), 268 268 pip_video_size(0,0), 269 269 pip_tmp_buf(NULL), pip_tmp_buf2(NULL), 270 pip_scaling_context(NULL), pad_pip_window(false),270 pip_scaling_context(NULL), 271 271 272 272 // Video resizing (for ITV) 273 273 vsz_enabled(false), … … 788 788 /* 789 789 * \brief Determines PIP Window size and Position. 790 790 */ 791 QRect VideoOutput::GetPIPRect( int location,792 791 QRect VideoOutput::GetPIPRect( 792 PIPLocation location, NuppelVideoPlayer *pipplayer, bool do_pixel_adj) const 793 793 { 794 794 return windows[0].GetPIPRect(location, pipplayer, do_pixel_adj); 795 795 } … … 799 799 * \brief Sets up Picture in Picture image resampler. 800 800 * \param pipwidth input width 801 801 * \param pipheight input height 802 * \sa ShutdownPipResize(), ShowPIP (VideoFrame*,NuppelVideoPlayer*)802 * \sa ShutdownPipResize(), ShowPIPs(VideoFrame*,const PIPMap&) 803 803 */ 804 804 void VideoOutput::DoPipResize(int pipwidth, int pipheight) 805 805 { … … 825 825 * \fn VideoOutput::ShutdownPipResize() 826 826 * \brief Shuts down Picture in Picture image resampler. 827 827 * \sa VideoOutput::DoPipResize(int,int), 828 * ShowPIP (VideoFrame*,NuppelVideoPlayer*)828 * ShowPIPs(VideoFrame*,const PIPMap&) 829 829 */ 830 830 void VideoOutput::ShutdownPipResize(void) 831 831 { … … 851 851 pip_display_size = QSize(0,0); 852 852 } 853 853 854 void VideoOutput::ShowPIPs(VideoFrame *frame, const PIPMap &pipPlayers) 855 { 856 PIPMap::const_iterator it = pipPlayers.begin(); 857 for (; it != pipPlayers.end(); ++it) 858 ShowPIP(frame, it.key(), *it); 859 } 860 854 861 /** 855 * \fn VideoOutput::ShowPIP(VideoFrame*,NuppelVideoPlayer* )862 * \fn VideoOutput::ShowPIP(VideoFrame*,NuppelVideoPlayer*,PIPLocation) 856 863 * \brief Composites PiP image onto a video frame. 857 * Note: This only works with memory backed VideoFrames, 858 * that is not XvMC. 864 * 865 * Note: This only works with memory backed VideoFrames, 866 * that is not XvMC, OpenGL, VDPAU, etc. 867 * 859 868 * \param frame Frame to composite PiP onto. 860 869 * \param pipplayer Picture-in-Picture NVP. 870 * \param loc Location of this PiP on the frame. 861 871 */ 862 void VideoOutput::ShowPIP(VideoFrame *frame, NuppelVideoPlayer *pipplayer) 872 void VideoOutput::ShowPIP(VideoFrame *frame, 873 NuppelVideoPlayer *pipplayer, 874 PIPLocation loc) 863 875 { 864 876 if (!pipplayer) 865 877 return; 866 878 867 int pipw, piph; 868 869 const float video_aspect = windows[0].GetVideoAspect(); 879 const float video_aspect = windows[0].GetVideoAspect(); 880 const QRect display_video_rect = windows[0].GetDisplayVideoRect(); 881 const QRect video_rect = windows[0].GetVideoRect(); 882 const QRect display_visible_rect = windows[0].GetDisplayVisibleRect(); 883 const float overriden_video_aspect = windows[0].GetOverridenVideoAspect(); 884 const QSize video_disp_dim = windows[0].GetVideoDispDim(); 885 const int pip_size = windows[0].GetPIPSize(); 870 886 const AspectOverrideMode aspectoverride = windows[0].GetAspectOverride(); 871 const QRect display_video_rect = windows[0].GetDisplayVideoRect();872 const QRect video_rect = windows[0].GetVideoRect();873 const QRect display_visible_rect = windows[0].GetDisplayVisibleRect();874 const float overriden_video_aspect = windows[0].GetOverridenVideoAspect();875 const QSize video_disp_dim = windows[0].GetVideoDispDim();876 887 877 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph); 878 float pipVideoAspect = pipplayer->GetVideoAspect(); 879 QSize pipVideoDim = pipplayer->GetVideoBufferSize(); 880 uint pipVideoWidth = pipVideoDim.width(); 881 uint pipVideoHeight = pipVideoDim.height(); 888 int pipw, piph; 889 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph); 890 const bool pipActive = pipplayer->IsPIPActive(); 891 const float pipVideoAspect = pipplayer->GetVideoAspect(); 892 const QSize pipVideoDim = pipplayer->GetVideoBufferSize(); 893 const uint pipVideoWidth = pipVideoDim.width(); 894 const uint pipVideoHeight = pipVideoDim.height(); 882 895 883 896 // If PiP is not initialized to values we like, silently ignore the frame. 884 897 if ((video_aspect <= 0) || (pipVideoAspect <= 0) || … … 890 903 } 891 904 892 905 // set height 893 int tmph = (int) ((frame->height * windows[0].GetPIPSize()) * 0.01f);906 int tmph = (int) ((frame->height * pip_size) * 0.01f); 894 907 pip_desired_display_size.setHeight((tmph >> 1) << 1); 895 908 896 909 // adjust for letterbox modes... … … 944 957 945 958 img_resample(pip_scaling_context, &img_out, &img_in); 946 959 947 if (p ad_pip_window)960 if (pipActive) 948 961 { 949 962 AVPicture img_padded; 950 963 avpicture_fill( … … 952 965 pip_display_size.width(), pip_display_size.height()); 953 966 954 967 int color[3] = { 20, 0, 200 }; //deep red YUV format 955 av_picture_pad(&img_padded, &img_out, pip_display_size.height(), 956 pip_display_size.width(), PIX_FMT_YUV420P, 10, 10, 957 10, 10, color); 968 av_picture_pad(&img_padded, &img_out, 969 pip_display_size.height(), 970 pip_display_size.width(), 971 PIX_FMT_YUV420P, 10, 10, 10, 10, color); 958 972 959 973 pipbuf = pip_tmp_buf2; 960 974 } 961 975 else 976 { 962 977 pipbuf = pip_tmp_buf; 978 } 963 979 964 980 pipw = pip_display_size.width(); 965 981 piph = pip_display_size.height(); 966 982 967 983 init(&pip_tmp_image, 968 969 970 971 984 FMT_YV12, 985 pipbuf, 986 pipw, piph, 987 pipimage->bpp, sizeof(pipbuf)); 972 988 } 973 989 } 974 990 975 991 // Figure out where to put the Picture-in-Picture window 976 992 int xoff = 0; 977 993 int yoff = 0; 978 switch ( windows[0].GetPIPLocation())994 switch (loc) 979 995 { 980 996 case kPIP_END: 981 997 case kPIPTopLeft: 982 983 984 998 xoff = 30 + letterXadj; 999 yoff = 40 + letterYadj; 1000 break; 985 1001 case kPIPBottomLeft: 986 987 988 1002 xoff = 30 + letterXadj; 1003 yoff = frame->height - piph - 40 - letterYadj; 1004 break; 989 1005 case kPIPTopRight: 990 991 992 1006 xoff = frame->width - pipw - 30 - letterXadj; 1007 yoff = 40 + letterYadj; 1008 break; 993 1009 case kPIPBottomRight: 994 995 996 1010 xoff = frame->width - pipw - 30 - letterXadj; 1011 yoff = frame->height - piph - 40 - letterYadj; 1012 break; 997 1013 } 998 1014 999 1015 uint xoff2[3] = { xoff, xoff>>1, xoff>>1 }; … … 1006 1022 for (uint h = 2; h < height[p]; h++) 1007 1023 { 1008 1024 memcpy((frame->buf + frame->offsets[p]) + (h + yoff2[p]) * 1009 1010 1011 1025 frame->pitches[p] + xoff2[p], 1026 (pip_tmp_image.buf + pip_tmp_image.offsets[p]) + h * 1027 pip_tmp_image.pitches[p], pip_tmp_image.pitches[p]); 1012 1028 } 1013 1029 } 1014 1030 … … 1020 1036 * \brief Sets up Picture in Picture image resampler. 1021 1037 * \param inDim input width and height 1022 1038 * \param outDim output width and height 1023 * \sa ShutdownPipResize(), ShowPIP (VideoFrame*,NuppelVideoPlayer*)1039 * \sa ShutdownPipResize(), ShowPIPs(VideoFrame*,const PIPMap&) 1024 1040 */ 1025 1041 void VideoOutput::DoVideoResize(const QSize &inDim, const QSize &outDim) 1026 1042 { -
libs/libmythtv/videooutwindow.h
70 70 float GetMzScaleV(void) const { return mz_scale_v; } 71 71 float GetMzScaleH(void) const { return mz_scale_h; } 72 72 QPoint GetMzMove(void) const { return mz_move; } 73 PIPLocation GetPIPLocation(void) const { return db_pip_location; }74 73 int GetPIPSize(void) const { return db_pip_size; } 75 74 PIPState GetPIPState(void) const { return pip_state; } 76 75 QSize GetVideoDispDim(void) const { return video_disp_dim; } … … 96 95 { return tmp_display_visible_rect; } 97 96 QRect GetVisibleOSDBounds(float&, float&, float) const; 98 97 QRect GetTotalOSDBounds(void) const; 99 QRect GetPIPRect(int location, 98 99 QRect GetPIPRect(PIPLocation location, 100 100 NuppelVideoPlayer *pipplayer = NULL, 101 101 bool do_pixel_adj = true) const; 102 102 … … 112 112 QPoint db_move; ///< Percentage move from database 113 113 float db_scale_horiz; ///< Horizontal Overscan/Underscan percentage 114 114 float db_scale_vert; ///< Vertical Overscan/Underscan percentage 115 PIPLocation db_pip_location;116 115 int db_pip_size; ///< percentage of full window to use for PiP 117 116 bool db_scaling_allowed;///< disable this to prevent overscan/underscan 118 117 -
libs/libmythtv/playercontext.h
62 62 bool StartPIPPlayer(TV *tv, TVState desiredState); 63 63 void PIPTeardown(void); 64 64 bool isPIP(void) const 65 { return ( pipState > kPIPOff && pipState < kPBPLeft); }65 { return (kPIPonTV == pipState) || (kPIPStandAlone == pipState); } 66 66 bool isPBP(void) const 67 { return ( pipState > kPIPStandAlone && pipState < kPBPSwap); }67 { return (kPBPLeft == pipState) || (kPBPRight == pipState); } 68 68 bool isMainVideo(void) const 69 { return ( pipState == kPIPOff || pipState == kPBPLeft); }69 { return (kPIPOff == pipState) || (kPBPLeft == pipState); } 70 70 void DrawARGBFrame(QPainter *p); 71 71 QRect GetStandAlonePIPRect(void); 72 QString PIPLocationToString(void);73 QString PIPStateToString(void);74 72 PIPState GetPIPState(void) const { return pipState; } 75 73 void SetNullVideo(bool setting) { useNullVideo = setting; } 76 74 bool UseNullVideo(void) const { return useNullVideo; } 75 bool IsNVPChangingBuffers(void) const { return nvpUnsafe; } 77 76 78 79 77 void PushPreviousChannel(void); 80 78 QString PopPreviousChannel(void); 81 79 QString GetPreviousChannel(void) const; … … 90 88 void LockState(void) const; 91 89 void UnlockState(void) const; 92 90 bool InStateChange(void) const; 93 void ChangeState(TVState newState );94 void ForceNextStateNone( void);91 void ChangeState(TVState newState, int line); 92 void ForceNextStateNone(int line); 95 93 TVState DequeueNextState(void); 96 94 TVState GetState(void) const; 97 95 /// This is set if the player encountered some irrecoverable error. … … 113 111 void SetPlayGroup(const QString &group); 114 112 void SetPseudoLiveTV(const ProgramInfo *pi, PseudoState new_state); 115 113 void SetPIPState(PIPState change) { pipState = change; } 114 void SetNVPChangingBuffers(bool val) { nvpUnsafe = val; } 116 115 void ResizePIPWindow(void); 117 116 118 117 119 118 public: 120 119 NuppelVideoPlayer *nvp; 120 volatile bool nvpUnsafe; 121 121 RemoteEncoder *recorder; 122 122 LiveTVChain *tvchain; 123 123 RingBuffer *buffer; -
libs/libmythtv/videoout_xv.h
72 72 73 73 void ProcessFrame(VideoFrame *frame, OSD *osd, 74 74 FilterChain *filterList, 75 NuppelVideoPlayer *pipPlayer); 75 const PIPMap &pipPlayers); 76 76 77 void PrepareFrame(VideoFrame*, FrameScanType); 77 78 void DrawSlice(VideoFrame*, int x, int y, int w, int h); 78 79 void Show(FrameScanType); … … 114 115 { return OpenGL <= VideoOutputSubType(); } 115 116 116 117 void CheckFrameStates(void); 117 QRect GetPIPRect(int location,118 NuppelVideoPlayer *pipplayer = NULL,119 bool do_pixel_adj = true) const;120 118 119 virtual QRect GetPIPRect(PIPLocation location, 120 NuppelVideoPlayer *pipplayer = NULL, 121 bool do_pixel_adj = true) const; 122 121 123 virtual void ShutdownVideoResize(void); 122 124 123 125 // OpenGL … … 162 164 void DoneDisplayingFrame(void); 163 165 164 166 void ProcessFrameVDPAU(VideoFrame *frame, OSD *osd, 165 NuppelVideoPlayer *pipPlayer);167 const PIPMap &pipPlayers); 166 168 void ProcessFrameXvMC(VideoFrame *frame, OSD *osd); 167 169 void ProcessFrameOpenGL(VideoFrame *frame, OSD *osd, 168 170 FilterChain *filterList, 169 NuppelVideoPlayer *pipPlayer);171 const PIPMap &pipPlayers); 170 172 void ProcessFrameMem(VideoFrame *frame, OSD *osd, 171 173 FilterChain *filterList, 172 NuppelVideoPlayer *pipPlayer);174 const PIPMap &pipPlayers); 173 175 174 176 void PrepareFrameVDPAU(VideoFrame *, FrameScanType); 175 177 void PrepareFrameXvMC(VideoFrame *, FrameScanType); … … 181 183 void ShowXvMC(FrameScanType scan); 182 184 void ShowXVideo(FrameScanType scan); 183 185 184 void ShowPIP(VideoFrame *frame, NuppelVideoPlayer *pipplayer); 186 virtual void ShowPIP(VideoFrame *frame, 187 NuppelVideoPlayer *pipplayer, 188 PIPLocation loc); 189 185 190 virtual int DisplayOSD(VideoFrame *frame, OSD *osd, 186 191 int stride = -1, int revision = -1); 187 192 … … 307 312 QWaitCondition gl_context_wait; 308 313 OpenGLContextGLX *gl_context; 309 314 OpenGLVideo *gl_videochain; 310 OpenGLVideo *gl_pipchain; 315 QMap<NuppelVideoPlayer*,OpenGLVideo*> gl_pipchains; 316 QMap<NuppelVideoPlayer*,bool> gl_pip_ready; 317 OpenGLVideo *gl_pipchain_active; 311 318 OpenGLVideo *gl_osdchain; 312 319 bool gl_use_osd_opengl2; 313 bool gl_pip_ready;314 320 bool gl_osd_ready; 315 321 316 322 // Chromakey OSD info -
libs/libmythtv/videoout_xv.cpp
169 169 170 170 gl_context_lock(QMutex::Recursive), 171 171 gl_context_creator(NULL), gl_context(NULL), 172 gl_videochain(NULL), gl_pipchain (NULL),172 gl_videochain(NULL), gl_pipchain_active(NULL), 173 173 gl_osdchain(NULL), 174 174 175 175 gl_use_osd_opengl2(false), 176 gl_pip_ready(false),177 176 gl_osd_ready(false), 178 177 179 178 … … 2731 2730 delete gl_videochain; 2732 2731 gl_videochain = NULL; 2733 2732 } 2734 if (gl_pipchain)2733 while (!gl_pipchains.empty()) 2735 2734 { 2736 delete gl_pipchain;2737 gl_pipchain = NULL;2735 delete *gl_pipchains.begin(); 2736 gl_pipchains.erase(gl_pipchains.begin()); 2738 2737 } 2739 2738 if (gl_osdchain) 2740 2739 { … … 2749 2748 } 2750 2749 2751 2750 gl_use_osd_opengl2 = false; 2752 gl_pip_ready = false;2751 gl_pip_ready.clear(); 2753 2752 gl_osd_ready = false; 2754 2753 2755 2754 // end OpenGL stuff … … 3162 3161 3163 3162 gl_videochain->PrepareFrame(t, m_deinterlacing, framesPlayed, false); 3164 3163 3165 if (gl_pip_ready && gl_pipchain) 3166 gl_pipchain->PrepareFrame(t, m_deinterlacing, framesPlayed, 3167 pad_pip_window); 3164 QMap<NuppelVideoPlayer*,OpenGLVideo*>::iterator it = gl_pipchains.begin(); 3165 for (; it != gl_pipchains.end(); ++it) 3166 { 3167 if (gl_pip_ready[it.key()]) 3168 { 3169 bool active = gl_pipchain_active == *it; 3170 (*it)->PrepareFrame(t, m_deinterlacing, framesPlayed, active); 3171 } 3172 } 3168 3173 3169 3174 if (gl_osd_ready && gl_osdchain) 3170 3175 gl_osdchain->PrepareFrame(t, m_deinterlacing, framesPlayed, false); … … 3582 3587 X11S(XSync(XJ_disp, False)); 3583 3588 } 3584 3589 3585 void VideoOutputXv::ShowPIP(VideoFrame *frame, NuppelVideoPlayer *pipplayer) 3590 void VideoOutputXv::ShowPIP(VideoFrame *frame, 3591 NuppelVideoPlayer *pipplayer, 3592 PIPLocation loc) 3586 3593 { 3594 if (VideoOutputSubType() >= XVideoMC && 3595 VideoOutputSubType() <= XVideoVLD) 3596 { 3597 return; 3598 } 3599 3587 3600 if (VideoOutputSubType() != OpenGL && 3588 3601 VideoOutputSubType() != XVideoVDPAU) 3589 3602 { 3590 VideoOutput::ShowPIP(frame, pipplayer );3603 VideoOutput::ShowPIP(frame, pipplayer, loc); 3591 3604 return; 3592 3605 } 3593 3606 3594 3607 (void) frame; 3595 3608 3596 gl_pip_ready = false;3597 3598 3609 if (!pipplayer) 3599 3610 return; 3600 3611 3601 3612 int pipw, piph; 3602 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph); 3603 float pipVideoAspect = pipplayer->GetVideoAspect(); 3604 QSize pipVideoDim = pipplayer->GetVideoBufferSize(); 3605 uint pipVideoWidth = pipVideoDim.width(); 3606 uint pipVideoHeight = pipVideoDim.height(); 3613 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph); 3614 const bool pipActive = pipplayer->IsPIPActive(); 3615 const float pipVideoAspect = pipplayer->GetVideoAspect(); 3616 const QSize pipVideoDim = pipplayer->GetVideoBufferSize(); 3617 const uint pipVideoWidth = pipVideoDim.width(); 3618 const uint pipVideoHeight = pipVideoDim.height(); 3607 3619 3608 3620 // If PiP is not initialized to values we like, silently ignore the frame. 3609 3621 if ((pipVideoAspect <= 0) || !pipimage || … … 3613 3625 return; 3614 3626 } 3615 3627 3616 QRect position = GetPIPRect( windows[0].GetPIPLocation(), pipplayer);3628 QRect position = GetPIPRect(loc, pipplayer); 3617 3629 QRect dvr = GetTotalVisibleRect(); 3618 3630 3619 3631 #ifdef USING_VDPAU … … 3625 3637 } 3626 3638 #endif // USING_VDPAU 3627 3639 3640 gl_pip_ready[pipplayer] = false; 3641 OpenGLVideo *gl_pipchain = gl_pipchains[pipplayer]; 3628 3642 if (!gl_pipchain) 3629 3643 { 3630 3644 VERBOSE(VB_PLAYBACK, LOC + "Initialise PiP."); 3631 gl_pipchain = new OpenGLVideo();3645 gl_pipchains[pipplayer] = gl_pipchain = new OpenGLVideo(); 3632 3646 bool success = gl_pipchain->Init(gl_context, db_use_picture_controls, 3633 3647 QSize(pipVideoWidth, pipVideoHeight), 3634 3648 dvr, position, … … 3648 3662 { 3649 3663 VERBOSE(VB_PLAYBACK, LOC + "Re-initialise PiP."); 3650 3664 delete gl_pipchain; 3651 gl_pipchain = new OpenGLVideo();3665 gl_pipchains[pipplayer] = gl_pipchain = new OpenGLVideo(); 3652 3666 bool success = gl_pipchain->Init( 3653 3667 gl_context, db_use_picture_controls, 3654 3668 QSize(pipVideoWidth, pipVideoHeight), … … 3668 3682 QRect(0, 0, pipVideoWidth, pipVideoHeight)); 3669 3683 gl_pipchain->UpdateInputFrame(pipimage); 3670 3684 3671 gl_pip_ready = true;3685 gl_pip_ready[pipplayer] = true; 3672 3686 3687 if (pipActive) 3688 gl_pipchain_active = gl_pipchain; 3689 3673 3690 pipplayer->ReleaseCurrentFrame(pipimage); 3674 3691 } 3675 3692 … … 4040 4057 } 4041 4058 4042 4059 void VideoOutputXv::ProcessFrameVDPAU(VideoFrame *frame, OSD *osd, 4043 NuppelVideoPlayer *pipPlayer)4060 const PIPMap &pipPlayers) 4044 4061 { 4045 4062 DisplayOSD(frame, osd); 4046 ShowPIP (frame, pipPlayer);4063 ShowPIPs(frame, pipPlayers); 4047 4064 } 4048 4065 4049 4066 void VideoOutputXv::ProcessFrameXvMC(VideoFrame *frame, OSD *osd) … … 4252 4269 4253 4270 void VideoOutputXv::ProcessFrameOpenGL(VideoFrame *frame, OSD *osd, 4254 4271 FilterChain *filterList, 4255 NuppelVideoPlayer *pipPlayer)4272 const PIPMap &pipPlayers) 4256 4273 { 4257 4274 (void) osd; 4258 4275 (void) filterList; 4259 (void) pipPlayer ;4276 (void) pipPlayers; 4260 4277 4261 4278 if (!gl_videochain || !gl_context) 4262 4279 return; … … 4283 4300 4284 4301 if (!windows[0].IsEmbedding()) 4285 4302 { 4286 ShowPIP(frame, pipPlayer); 4303 gl_pipchain_active = NULL; 4304 ShowPIPs(frame, pipPlayers); 4287 4305 if (osd) 4288 4306 DisplayOSD(frame, osd); 4289 4307 } … … 4296 4314 4297 4315 void VideoOutputXv::ProcessFrameMem(VideoFrame *frame, OSD *osd, 4298 4316 FilterChain *filterList, 4299 NuppelVideoPlayer *pipPlayer)4317 const PIPMap &pipPlayers) 4300 4318 { 4301 4319 bool deint_proc = m_deinterlacing && (m_deintFilter != NULL); 4302 4320 bool pauseframe = false; … … 4324 4342 m_deintFilter->ProcessFrame(frame); 4325 4343 } 4326 4344 4327 ShowPIP (frame, pipPlayer);4345 ShowPIPs(frame, pipPlayers); 4328 4346 4329 4347 if (osd && !windows[0].IsEmbedding()) 4330 4348 { … … 4350 4368 // this is documented in videooutbase.cpp 4351 4369 void VideoOutputXv::ProcessFrame(VideoFrame *frame, OSD *osd, 4352 4370 FilterChain *filterList, 4353 NuppelVideoPlayer *pipPlayer)4371 const PIPMap &pipPlayers) 4354 4372 { 4355 4373 if (IsErrored()) 4356 4374 { … … 4359 4377 } 4360 4378 4361 4379 if (VideoOutputSubType() == XVideoVDPAU) 4362 ProcessFrameVDPAU(frame, osd, pipPlayer );4380 ProcessFrameVDPAU(frame, osd, pipPlayers); 4363 4381 else if (VideoOutputSubType() == OpenGL) 4364 ProcessFrameOpenGL(frame, osd, filterList, pipPlayer );4382 ProcessFrameOpenGL(frame, osd, filterList, pipPlayers); 4365 4383 else if (VideoOutputSubType() <= XVideo) 4366 ProcessFrameMem(frame, osd, filterList, pipPlayer );4384 ProcessFrameMem(frame, osd, filterList, pipPlayers); 4367 4385 else 4368 4386 ProcessFrameXvMC(frame, osd); 4369 4387 } … … 4721 4739 #endif // USING_XVMC 4722 4740 } 4723 4741 4724 QRect VideoOutputXv::GetPIPRect(int location, NuppelVideoPlayer *pipplayer, 4725 bool do_pixel_adj) const 4742 QRect VideoOutputXv::GetPIPRect(PIPLocation location, 4743 NuppelVideoPlayer *pipplayer, 4744 bool do_pixel_adj) const 4726 4745 { 4727 4746 (void)do_pixel_adj; 4728 4747 -
libs/libmythtv/programinfo.h
1 1 #ifndef PROGRAMINFO_H_ 2 2 #define PROGRAMINFO_H_ 3 3 4 #include "recordingtypes.h" 5 #include "mythdbcon.h" 4 // C++ headers 5 #include <vector> 6 #include <deque> 7 using namespace std; 6 8 7 #include <qstring.h>8 #include <qdatetime.h>9 #include <qmap.h>10 9 #include <QStringList> 10 #include <QDateTime> 11 #include <QRegExp> 12 #include <QMap> 11 13 12 #include <qregexp.h> 14 #include "recordingtypes.h" 15 #include "mythdbcon.h" 13 16 14 #include <vector>15 #include <list>16 using namespace std;17 18 17 typedef QMap<long long, long long> frm_pos_map_t; 19 18 typedef QMap<long long, int> frm_dir_map_t; 20 19 … … 458 457 ProgramList(bool auto_delete = true) : autodelete(auto_delete) {} 459 458 ~ProgramList(); 460 459 461 typedef list<ProgramInfo*>::iterator iterator;462 typedef list<ProgramInfo*>::const_iterator const_iterator;460 typedef deque<ProgramInfo*>::iterator iterator; 461 typedef deque<ProgramInfo*>::const_iterator const_iterator; 463 462 464 463 ProgramInfo *operator[](uint index); 464 const ProgramInfo *operator[](uint index) const; 465 465 bool operator==(const ProgramList &b) const; 466 466 467 467 bool FromScheduler(bool &hasConflicts, QString altTable = "", int recordid=-1); … … 495 495 const_iterator begin(void) const { return pglist.begin(); } 496 496 const_iterator end(void) const { return pglist.end(); } 497 497 498 void sort(bool (&f)(const ProgramInfo*, const ProgramInfo*)) 499 { pglist.sort(f); } 498 void sort(bool (&f)(const ProgramInfo*, const ProgramInfo*)); 500 499 bool empty(void) const { return pglist.empty(); } 501 500 size_t size(void) const { return pglist.size(); } 502 501 void push_front(ProgramInfo *pginfo) { pglist.push_front(pginfo); } … … 511 510 void setAutoDelete(bool auto_delete) { autodelete = auto_delete; } 512 511 513 512 protected: 514 list<ProgramInfo*> pglist;513 deque<ProgramInfo*> pglist; 515 514 bool autodelete; 516 515 }; 517 516 -
libs/libmythtv/programinfo.cpp
1 #include <iostream> 1 // POSIX headers 2 2 #include <sys/types.h> 3 3 #include <unistd.h> 4 #include <stdlib.h>5 4 5 // C headers 6 #include <cstdlib> 7 8 // C++ headers 9 #include <iostream> 10 #include <algorithm> 11 using namespace std; 12 13 // Qt headers 6 14 #include <QRegExp> 7 15 #include <QMap> 8 16 #include <QLayout> … … 11 19 #include <QFile> 12 20 #include <QFileInfo> 13 21 22 // MythTV headers 14 23 #include "programinfo.h" 15 24 #include "progdetails.h" 16 25 #include "scheduledrecording.h" … … 4749 4758 4750 4759 ProgramInfo *ProgramList::operator[](uint index) 4751 4760 { 4752 iterator it = pglist.begin(); 4753 for (uint i = 0; i < index; i++, it++) 4754 { 4755 if (it == pglist.end()) 4756 return NULL; 4757 } 4758 if (it == pglist.end()) 4759 return NULL; 4760 return *it; 4761 if (index < pglist.size()) 4762 return pglist[index]; 4763 return NULL; 4761 4764 } 4762 4765 4766 const ProgramInfo *ProgramList::operator[](uint index) const 4767 { 4768 if (index < pglist.size()) 4769 return pglist[index]; 4770 return NULL; 4771 } 4772 4763 4773 bool ProgramList::operator==(const ProgramList &b) const 4764 4774 { 4765 4775 const_iterator it_a = pglist.begin(); … … 4807 4817 pglist.clear(); 4808 4818 } 4809 4819 4820 void ProgramList::sort(bool (&f)(const ProgramInfo*, const ProgramInfo*)) 4821 { 4822 stable_sort(begin(), end(), f); 4823 } 4824 4810 4825 bool ProgramList::FromScheduler(bool &hasConflicts, QString tmptable, 4811 4826 int recordid) 4812 4827 { -
libs/libmythtv/videooutbase.h
30 30 class VideoDisplayProfile; 31 31 class OpenGLContextGLX; 32 32 33 typedef QMap<NuppelVideoPlayer*,PIPLocation> PIPMap; 34 33 35 extern "C" { 34 36 struct ImgReSampleContext; 35 37 } … … 115 117 // pass in null to use the pause frame, if it exists. 116 118 virtual void ProcessFrame(VideoFrame *frame, OSD *osd, 117 119 FilterChain *filterList, 118 NuppelVideoPlayer *pipPlayer) = 0;120 const PIPMap &pipPlayers) = 0; 119 121 120 122 /// \brief Tells video output that a full repaint is needed. 121 123 void ExposeEvent(void); … … 228 230 bool IsVideoScalingAllowed(void) const; 229 231 230 232 /// \brief returns QRect of PIP based on PIPLocation 231 virtual QRect GetPIPRect( intlocation,233 virtual QRect GetPIPRect(PIPLocation location, 232 234 NuppelVideoPlayer *pipplayer = NULL, 233 235 bool do_pixel_adj = true) const; 234 236 235 237 virtual void SetPIPState(PIPState setting); 236 virtual void PadPIPImage(bool change) { pad_pip_window = change; }237 238 238 239 virtual QString GetOSDRenderer(void) const; 239 240 … … 245 246 int needprebuffer_normal, int needprebuffer_small, 246 247 int keepprebuffer); 247 248 248 virtual void ShowPIP(VideoFrame *frame, NuppelVideoPlayer *pipplayer); 249 virtual void ShowPIPs(VideoFrame *frame, const PIPMap &pipPlayers); 250 virtual void ShowPIP(VideoFrame *frame, 251 NuppelVideoPlayer *pipplayer, 252 PIPLocation loc); 253 249 254 virtual int DisplayOSD(VideoFrame *frame, OSD *osd, int stride = -1, int revision = -1); 250 255 251 256 virtual void SetPictureAttributeDBValue( … … 288 293 unsigned char *pip_tmp_buf; 289 294 unsigned char *pip_tmp_buf2; 290 295 ImgReSampleContext *pip_scaling_context; 291 bool pad_pip_window;292 296 VideoFrame pip_tmp_image; 293 297 294 298 // Video resizing (for ITV) -
libs/libmythtv/videoout_ivtv.cpp
693 693 { 694 694 } 695 695 696 void VideoOutputIvtv::ShowPIP(VideoFrame *frame, NuppelVideoPlayer *pipplayer) 696 void VideoOutputIvtv::ShowPIP(VideoFrame *frame, 697 NuppelVideoPlayer *pipplayer, 698 PIPLocation loc) 697 699 { 698 700 if (!pipplayer) 699 701 return; … … 738 740 } 739 741 } 740 742 741 switch ( windows[0].GetPIPLocation())743 switch (loc) 742 744 { 743 745 case kPIP_END: 744 746 case kPIPTopLeft: … … 782 784 783 785 void VideoOutputIvtv::ProcessFrame(VideoFrame *frame, OSD *osd, 784 786 FilterChain *filterList, 785 NuppelVideoPlayer *pipPlayer)787 const PIPMap &pipPlayers) 786 788 { 787 789 (void)filterList; 788 790 (void)frame; … … 813 815 surface = osd->Display(); 814 816 815 817 // Clear osdbuf if OSD has changed, or PiP has been toggled 816 bool clear = ( pipPlayer!=0) ^ pipon;818 bool clear = (!pipPlayers.empty()) ^ pipon; 817 819 int new_revision = osdbuf_revision; 818 820 if (surface) 819 821 { … … 828 830 drawanyway = true; 829 831 } 830 832 831 if ( pipPlayer)833 if (!pipPlayers.empty()) 832 834 { 833 ShowPIP (&tmpframe, pipPlayer);835 ShowPIPs(&tmpframe, pipPlayers); 834 836 osdbuf_revision = 0xfffffff; // make sure OSD is redrawn 835 837 lastcleared = false; 836 838 drawanyway = true; … … 849 851 { 850 852 bzero(tmpframe.buf, video_dim.height() * stride); 851 853 // redraw PiP... 852 if ( pipPlayer)853 ShowPIP (&tmpframe, pipPlayer);854 if (!pipPlayers.empty()) 855 ShowPIPs(&tmpframe, pipPlayers); 854 856 } 855 857 drawanyway |= !lastcleared || pipon; 856 858 lastcleared &= !pipon; … … 858 860 859 861 // Set these so we know if/how to clear if need be, the next time around. 860 862 osdon = (ret >= 0); 861 pipon = (bool) pipPlayer;863 pipon = (bool) !pipPlayers.empty(); 862 864 863 865 // If there is an OSD, make sure we draw OSD surface 864 866 lastcleared &= !osdon; -
libs/libmythtv/videoout_null.h
37 37 void UpdatePauseFrame(void); 38 38 void ProcessFrame(VideoFrame *frame, OSD *osd, 39 39 FilterChain *filterList, 40 NuppelVideoPlayer *pipPlayer);40 const PIPMap &pipPlayers); 41 41 42 42 static QStringList GetAllowedRenderers(MythCodecID myth_codec_id, 43 43 const QSize &video_dim);