Ticket #2287: multi-pip-v7.patch
File multi-pip-v7.patch, 108.2 KB (added by , 15 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 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)), … … 1152 1152 SetDecoder(dec); 1153 1153 } 1154 1154 1155 extern "C" { 1156 #include "libavutil/crc.h" 1157 } 1155 1158 int NuppelVideoPlayer::OpenFile(bool skipDsp, uint retries, 1156 1159 bool allow_libmpeg2) 1157 1160 { … … 1189 1192 return -1; 1190 1193 } 1191 1194 1195 long long pos = player_ctx->buffer->Seek(0, SEEK_CUR); 1196 uint checksum = av_crc(av_crc_get_table(AV_CRC_32_IEEE), 1197 (uint32_t) -1, 1198 (uint8_t*)testbuf, testreadsize - 1); 1199 VERBOSE(VB_PLAYBACK, LOC + 1200 QString("Looking for decoder for '%1'@%2 " 1201 "probe size %3 crc 0x%4") 1202 .arg(player_ctx->buffer->GetFilename()) 1203 .arg(pos).arg(testreadsize).arg(checksum,0,16)); 1204 1192 1205 player_ctx->LockPlayingInfo(__FILE__, __LINE__); 1193 1206 if (NuppelDecoder::CanHandle(testbuf, testreadsize)) 1194 1207 SetDecoder(new NuppelDecoder(this, *player_ctx->playingInfo)); … … 2956 2969 2957 2970 while (!killvideo) 2958 2971 { 2959 if (needsetpipplayer) 2960 { 2961 pip_players.clear(); 2962 if (setpipplayer) 2963 { 2964 pip_players[setpipplayer] = 2965 (PIPLocation) gContext->GetNumSetting("PIPLocation", 0); 2966 } 2967 needsetpipplayer = false; 2968 PIPState state = player_ctx->GetPIPState(); 2969 if (m_tv && (state == kPIPOff || state == kPBPLeft)) 2970 m_tv->WakeSetPIPPlayerCond(); 2971 } 2972 HandlePIPPlayerLists(4); 2972 2973 2973 2974 if (player_ctx->buffer->isDVD()) 2974 2975 { … … 3051 3052 3052 3053 while (!killvideo) 3053 3054 { 3054 if (needsetpipplayer) 3055 { 3056 pip_players.clear(); 3057 if (setpipplayer) 3058 { 3059 pip_players[setpipplayer] = 3060 (PIPLocation) gContext->GetNumSetting("PIPLocation", 0); 3061 } 3062 needsetpipplayer = false; 3063 } 3055 HandlePIPPlayerLists(1); 3064 3056 3065 3057 resetvideo = false; 3066 3058 SetVideoActuallyPaused(pausevideo); … … 3260 3252 } 3261 3253 else 3262 3254 { 3255 if (player_ctx) 3256 player_ctx->SetNVPChangingBuffers(true); 3263 3257 GetDecoder()->SetReadAdjust(player_ctx->buffer->SetAdjustFilesize()); 3264 3258 GetDecoder()->SetWaitForChange(); 3265 if (m_tv && player_ctx && !player_ctx->isPIP())3266 m_tv->SetIgnoreKeys(true);3267 3259 } 3268 3260 3269 3261 delete pginfo; … … 3303 3295 3304 3296 player_ctx->buffer->Unpause(); 3305 3297 3306 if (m_tv && player_ctx && !player_ctx->isPIP()) 3307 m_tv->SetIgnoreKeys(false); 3298 player_ctx->SetNVPChangingBuffers(false); 3308 3299 3309 3300 player_ctx->LockPlayingInfo(__FILE__, __LINE__); 3310 3301 player_ctx->tvchain->SetProgram(*player_ctx->playingInfo); … … 3877 3868 GetDecoder()->setTranscoding(value); 3878 3869 }; 3879 3870 3871 bool NuppelVideoPlayer::AddPIPPlayer( 3872 NuppelVideoPlayer *pip, PIPLocation loc, uint timeout) 3873 { 3874 QMutexLocker locker(&pip_players_lock); 3875 pip_players_add[pip] = loc; 3876 3877 pip_players_wait.wait(&pip_players_lock, timeout); 3878 3879 if (pip_players.find(pip) != pip_players.end()) 3880 return true; 3881 3882 PIPMap::iterator it = pip_players_add.find(pip); 3883 if (it != pip_players_add.end()) 3884 pip_players_add.erase(it); 3885 3886 return false; 3887 } 3888 3889 bool NuppelVideoPlayer::RemovePIPPlayer(NuppelVideoPlayer *pip, uint timeout) 3890 { 3891 QMutexLocker locker(&pip_players_lock); 3892 3893 pip_players_rm[pip] = kPIP_END; 3894 3895 pip_players_wait.wait(&pip_players_lock, timeout); 3896 3897 if (pip_players.find(pip) == pip_players.end()) 3898 return true; 3899 3900 PIPMap::iterator it = pip_players_rm.find(pip); 3901 if (it != pip_players_rm.end()) 3902 pip_players_rm.erase(it); 3903 3904 return false; 3905 } 3906 3907 void NuppelVideoPlayer::HandlePIPPlayerLists(uint max_cnt) 3908 { 3909 QMutexLocker locker(&pip_players_lock); 3910 PIPMap::const_iterator it = pip_players_rm.begin(); 3911 for (; it != pip_players_rm.end(); ++it) 3912 { 3913 PIPMap::iterator it2 = pip_players.find(it.key()); 3914 if (it2 != pip_players.end()) 3915 pip_players.erase(it2); 3916 } 3917 3918 for (it = pip_players_add.begin(); 3919 (it != pip_players_add.end()) && 3920 ((uint)pip_players.size() <= max_cnt); ++it) 3921 { 3922 if (pip_players.find(it.key()) == pip_players.end() && 3923 pip_players_rm.find(it.key()) == pip_players_rm.end()) 3924 { 3925 pip_players[it.key()] = *it; 3926 } 3927 } 3928 pip_players_add.clear(); 3929 pip_players_rm.clear(); 3930 pip_players_wait.wakeAll(); 3931 } 3932 3933 PIPLocation NuppelVideoPlayer::GetNextPIPLocation(void) const 3934 { 3935 QMutexLocker locker(&pip_players_lock); 3936 PIPMap sim_pip_players = pip_players; 3937 3938 PIPMap::const_iterator it = pip_players_rm.begin(); 3939 for (; it != pip_players_rm.end(); ++it) 3940 { 3941 PIPMap::iterator it2 = sim_pip_players.find(it.key()); 3942 if (it2 != sim_pip_players.end()) 3943 sim_pip_players.erase(it2); 3944 } 3945 3946 for (it = pip_players_add.begin(); it != pip_players_add.end(); ++it) 3947 { 3948 if (sim_pip_players.find(it.key()) == sim_pip_players.end() && 3949 pip_players_rm.find(it.key()) == pip_players_rm.end()) 3950 { 3951 sim_pip_players[it.key()] = *it; 3952 } 3953 } 3954 3955 // order of preference, could be stored in db if we want it configurable 3956 PIPLocation ols[] = 3957 { kPIPTopLeft, kPIPTopRight, kPIPBottomLeft, kPIPBottomRight }; 3958 3959 for (uint i = 0; i < sizeof(ols)/sizeof(PIPLocation); i++) 3960 { 3961 PIPMap::const_iterator it = sim_pip_players.begin(); 3962 for (; it != sim_pip_players.end() && (*it != ols[i]); ++it); 3963 3964 if (it == sim_pip_players.end()) 3965 return ols[i]; 3966 } 3967 3968 return kPIP_END; 3969 } 3970 3880 3971 void NuppelVideoPlayer::WrapTimecode(long long &timecode, TCTypes tc_type) 3881 3972 { 3882 3973 if ((tc_type == TC_AUDIO) && (tc_wrap[TC_AUDIO] == LONG_LONG_MIN)) -
libs/libmythtv/avformatdecoder.cpp
873 873 * \param novideo if true then no video is sought in ScanSreams. 874 874 * \param testbuf this parameter is not used by AvFormatDecoder. 875 875 */ 876 extern "C" { 877 #include "libavutil/crc.h" 878 } 876 879 int AvFormatDecoder::OpenFile(RingBuffer *rbuffer, bool novideo, 877 880 char testbuf[kDecoderProbeBufferSize], 878 881 int testbufsize) … … 899 902 probe.buf_size = kDecoderProbeBufferSize - AVPROBE_PADDING_SIZE; 900 903 901 904 fmt = av_probe_input_format(&probe, true); 905 uint checksum = av_crc(av_crc_get_table(AV_CRC_32_IEEE), 906 (uint32_t) -1, 907 (uint8_t*)testbuf, probe.buf_size - 1); 902 908 if (!fmt) 903 909 { 904 910 VERBOSE(VB_IMPORTANT, LOC_ERR + 905 QString("Probe failed for file: \"%1\".").arg(filename)); 911 QString("Probe failed for file: '%1' probe size %2 crc 0x%3") 912 .arg(filename).arg(probe.buf_size).arg(checksum,0,16)); 906 913 return -1; 907 914 } 915 VERBOSE(VB_IMPORTANT, LOC + 916 QString("Probe suceeded for file: '%1' probe size %2 crc 0x%3") 917 .arg(filename).arg(probe.buf_size).arg(checksum,0,16)); 908 918 909 919 fmt->flags |= AVFMT_NOFILE; 910 920 -
libs/libmythtv/tv_play.h
150 150 151 151 // LiveTV commands 152 152 bool LiveTV(bool showDialogs = true, bool startInGuide = false); 153 /// This command is used to exit the player in order to record using154 /// the recording being used by LiveTV.155 void StopLiveTV(void) { SetExitPlayer(true, true); }156 153 157 154 // Embedding commands for the guidegrid to use in LiveTV 158 155 void EmbedOutput(PlayerContext*, WId wid, int x, int y, int w, int h); … … 184 181 bool IsBookmarkAllowed(const PlayerContext*) const; 185 182 bool IsDeleteAllowed(const PlayerContext*) const; 186 183 187 bool CreatePBP(PlayerContext *, const ProgramInfo *info);188 bool CreatePIP(PlayerContext *, const ProgramInfo *info);189 voidResizePIPWindow(PlayerContext*);184 bool CreatePBP(PlayerContext *lctx, const ProgramInfo *info); 185 bool CreatePIP(PlayerContext *lctx, const ProgramInfo *info); 186 bool ResizePIPWindow(PlayerContext*); 190 187 bool IsPIPSupported(const PlayerContext *ctx = NULL) const; 191 188 192 189 // Boolean queries … … 238 235 bool inPlaylist = false, bool initByNetworkCommand = false); 239 236 static void SetFuncPtr(const char *, void *); 240 237 241 void SetIgnoreKeys(bool ignore) { ignoreKeys = ignore; }242 243 238 // Used by EPG 244 239 void ChangeVolume(PlayerContext*, bool up); 245 240 void ToggleMute(PlayerContext*); 246 241 247 void WakeSetPIPPlayerCond(void); 248 void SetNextProgPIPState(PIPState state) { nextProgPIPState = state; } 242 void SetNextProgPIPState(PIPState state) { jumpToProgramPIPState = state; } 249 243 250 244 // Used for UDPNotify 251 245 bool HasUDPNotifyEvent(void) const; … … 276 270 static EMBEDRETURNVOID RunViewScheduledPtr; 277 271 278 272 private: 279 void SetActive(PlayerContext * , int index);273 void SetActive(PlayerContext *lctx, int index, bool osd_msg); 280 274 281 275 PlayerContext *GetPlayerWriteLock( 282 276 int which, const char *file, int location); … … 297 291 298 292 int StartTimer(int interval, int line); 299 293 void KillTimer(int id); 300 void ForceNextStateNone(PlayerContext* );294 void ForceNextStateNone(PlayerContext*, int line); 301 295 void ScheduleStateChange(PlayerContext*); 302 296 void SetErrored(PlayerContext*); 303 void SetExitPlayer (bool set_it, bool wants_to) const;297 void SetExitPlayerReal(bool set_it, bool wants_to, int line) const; 304 298 void SetUpdateOSDPosition(bool set_it); 305 299 306 bool P IPHandleAction(PlayerContext*,const QStringList &actions);300 bool PxPHandleAction(PlayerContext*,const QStringList &actions); 307 301 bool ToggleHandleAction(PlayerContext*, 308 302 const QStringList &actions, bool isDVD); 309 303 bool FFRewHandleAction(PlayerContext*, const QStringList &actions); 310 304 bool ActivePostQHandleAction(PlayerContext*, 311 305 const QStringList &actions, bool isDVD); 306 bool HandleJumpToProgramAction(PlayerContext *ctx, 307 const QStringList &actions); 312 308 313 309 bool RequestNextRecorder(PlayerContext *, bool); 314 310 void DeleteRecorder(); … … 422 418 const QStringList &actions); 423 419 424 420 void DoDisplayJumpMenu(void); 425 void SetJumpToProgram(QString progKey = "", int progIndex = 0);426 421 427 422 bool ClearOSD(const PlayerContext*); 428 423 void ToggleOSD(const PlayerContext*, bool includeStatusOSD); … … 442 437 int editType = kScheduleProgramGuide); 443 438 444 439 void TeardownPlayer(PlayerContext *mctx, PlayerContext *ctx); 445 void TeardownPBP(PlayerContext*);446 440 447 441 void HandleStateChange(PlayerContext *mctx, PlayerContext *ctx); 448 442 449 443 bool StartPlayer(PlayerContext *mctx, PlayerContext *ctx, 450 TVState desiredState, bool ispip = false); 451 bool StartPIPPlayer(PlayerContext *mctx, PlayerContext *pipctx, 452 TVState desiredState); 453 void SetPIPPlayer(PlayerContext *mctx, PlayerContext *pipctx); 454 void TogglePIPView(PlayerContext*, bool ispbp = false); 455 void ToggleActiveWindow(PlayerContext*, int ctx_index); 456 void SwapPIP(PlayerContext *lctx, int ctx_index, bool ispbp); 457 void TogglePIPState(PlayerContext*, PIPState changeTo); 458 void RestartPIPWindows(PlayerContext *lctx, const vector<long long> &pos, 459 MuteState mctx_mute); 460 void TeardownPIPWindows(PlayerContext*); 444 TVState desiredState); 461 445 446 vector<long long> TeardownAllNVPs(PlayerContext*); 447 void RestartAllNVPs(PlayerContext *lctx, 448 const vector<long long> &pos, 449 MuteState mctx_mute); 450 451 void PxPToggleView( PlayerContext *actx, bool wantPBP); 452 void PxPCreateView( PlayerContext *actx, bool wantPBP); 453 void PxPTeardownView(PlayerContext *actx); 454 void PxPToggleType( PlayerContext *mctx, bool wantPBP); 455 void PxPSwap( PlayerContext *mctx, int ctx_index = -1); 456 bool HandlePxPTimerEvent(void); 457 458 bool PIPAddPlayer( PlayerContext *mctx, PlayerContext *ctx); 459 bool PIPRemovePlayer(PlayerContext *mctx, PlayerContext *ctx); 460 void PBPRestartMainNVP(PlayerContext *mctx); 461 462 462 void ToggleAutoExpire(PlayerContext*); 463 463 464 464 void BrowseStart(PlayerContext*); … … 479 479 480 480 void BuildOSDTreeMenu(const PlayerContext*); 481 481 void ShowOSDTreeMenu(const PlayerContext*); 482 void FillMenuPxP(const PlayerContext*, OSDGenericTree *treeMenu, 483 bool freeRecorders); 482 484 void FillMenuLiveTV(OSDGenericTree *treeMenu); 483 485 void FillMenuPlaying(const PlayerContext*, OSDGenericTree *treeMenu); 484 486 … … 509 511 void IdleDialogTimeout(void); 510 512 511 513 // Program jumping stuff 512 void setLastProgram(ProgramInfo *rcinfo);513 ProgramInfo * getLastProgram(void) { return lastProgram; }514 void SetLastProgram(ProgramInfo *rcinfo); 515 ProgramInfo *GetLastProgram(void) const; 514 516 515 517 static bool LoadExternalSubtitles(NuppelVideoPlayer *nvp, 516 518 const QString &videoFile); … … 537 539 QString db_time_format; 538 540 QString db_short_date_format; 539 541 uint db_idle_timeout; 542 uint db_udpnotify_port; 543 int db_playback_exit_prompt; 544 int db_autoexpire_default; 540 545 bool db_auto_set_watched; 541 546 bool db_end_of_rec_exit_prompt; 547 bool db_jump_prefer_osd; 548 bool db_use_gui_size_for_tv; 549 bool db_start_in_guide; 550 bool db_toggle_bookmark; 551 bool db_run_jobs_on_remote; 552 bool db_use_dvd_bookmark; 553 bool db_continue_embedded; 554 bool db_use_fixed_size; 555 542 556 bool smartChannelChange; 543 557 bool MuteIndividualChannels; 544 558 bool arrowAccel; … … 582 596 QMap<QString,AskProgramInfo> askAllowPrograms; 583 597 QMutex askAllowLock; 584 598 585 bool ignoreKeys; 586 PIPState needToMakePIPChange; 587 PIPState nextProgPIPState; 599 MythDeque<QString> changePxP; 600 QMutex progListsLock; 588 601 QMap<QString,ProgramList> progLists; 589 602 590 603 mutable QMutex chanEditMapLock; ///< Lock for chanEditMap and ddMap … … 639 652 640 653 // Program Info for currently playing video 641 654 // (or next video if InChangeState() is true) 655 mutable QMutex lastProgramLock; 642 656 ProgramInfo *lastProgram; ///< last program played with this player 643 bool jumpToProgram;644 645 657 bool inPlaylist; ///< show is part of a playlist 646 658 bool underNetworkControl; ///< initial show started via by the network control interface 647 659 bool isnearend; 648 660 661 // Program Jumping 662 PIPState jumpToProgramPIPState; 663 bool jumpToProgram; 664 649 665 // Video Players 650 666 vector<PlayerContext*> player; 651 667 /// Video Player to which events are sent to 652 668 int playerActive; 653 669 /// lock on player and playerActive changes 654 670 mutable QReadWriteLock playerLock; 655 QWaitCondition pipPlayerSetCondition;656 671 657 672 // Remote Encoders 658 673 /// Main recorder to use after a successful SwitchCards() call. … … 741 756 static const uint kInputKeysMax; ///< When to start discarding early keys 742 757 static const uint kNextSource; 743 758 static const uint kPreviousSource; 759 static const uint kMaxPIPCount; 760 static const uint kMaxPBPCount; 744 761 745 762 ///< Timeout for entry modes in msec 746 763 static const uint kInputModeTimeout; -
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 710 mutable QMutex pip_players_lock; 711 QWaitCondition pip_players_wait; 705 712 PIPMap pip_players; 706 NuppelVideoPlayer *setpipplayer; 707 bool needsetpipplayer; 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 PIPLocation 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 = (PIPLocation)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)4841 {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)4849 {4850 int new_index = 0;4851 lockTimerOn = false;4852 4853 if (playerActive != ctx_index)4854 new_index = ctx_index;4855 4856 SetActive(lctx, new_index);4857 }4858 4859 PlayerContext *actx = GetPlayer(lctx, -1);4860 OSD *osd = GetOSDLock(actx);4861 if (osd)4862 osd->SetSettingsText(tr("Changed Active Window"), 3);4863 ReturnOSDLock(actx, osd);4864 }4865 4866 4958 /** 4867 * \brief wake TV thread when pip player var is set in the main NVP4868 */4869 void TV::WakeSetPIPPlayerCond(void)4870 {4871 pipPlayerSetCondition.wakeAll();4872 }4873 4874 /**4875 4959 * \brief resize PIP Window. done when changing channels or swapping PIP 4876 4960 */ 4877 voidTV::ResizePIPWindow(PlayerContext *ctx)4961 bool TV::ResizePIPWindow(PlayerContext *ctx) 4878 4962 { 4879 PlayerContext *actx = GetPlayer(ctx, -1);4880 P IPLocation loc = (PIPLocation) gContext->GetNumSetting("PIPLocation", 0);4881 if ( actx->nvp && ctx->nvp)4963 VERBOSE(VB_PLAYBACK, LOC + "ResizePIPWindow -- begin"); 4964 PlayerContext *mctx = GetPlayer(ctx, 0); 4965 if (mctx->nvp && ctx->nvp) 4882 4966 { 4883 QRect rect = 4884 actx->nvp->getVideoOutput()->GetPIPRect(loc, ctx->nvp, false); 4885 ctx->ResizePIPWindow(rect); 4967 QRect rect; 4968 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__); 4981 4982 if (rect.isValid()) 4983 { 4984 ctx->ResizePIPWindow(rect); 4985 VERBOSE(VB_PLAYBACK, LOC + "ResizePIPWindow -- end : ok"); 4986 return true; 4987 } 4886 4988 } 4989 VERBOSE(VB_PLAYBACK, LOC + "ResizePIPWindow -- end : !ok"); 4990 return false; 4887 4991 } 4888 4992 4889 4993 bool TV::IsPIPSupported(const PlayerContext *ctx) const … … 4902 5006 return yes; 4903 5007 } 4904 5008 4905 /** 4906 * \brief Teardown all NVP's in preparation for PIP Swap or change from PIP <-> PBP4907 */4908 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) 4909 5013 { 4910 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 } 4911 5022 4912 5023 for (uint i = 0; i < player.size(); i++) 4913 5024 { 4914 5025 PlayerContext *ctx = GetPlayer(lctx, i); 4915 5026 ctx->PIPTeardown(); 4916 5027 } 5028 5029 return pos; 4917 5030 } 4918 5031 4919 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 /** 4920 5073 * \brief Recreate Main and PIP windows. Could be either PIP or PBP views. 4921 5074 */ 4922 void TV::Restart PIPWindows(PlayerContext *lctx,4923 4924 5075 void TV::RestartAllNVPs(PlayerContext *lctx, 5076 const vector<long long> &pos, 5077 MuteState mctx_mute) 4925 5078 { 4926 QString loc = LOC + QString("Restart PIPWindows()");5079 QString loc = LOC + QString("RestartAllNVPs(): "); 4927 5080 4928 5081 PlayerContext *mctx = GetPlayer(lctx, 0); 4929 5082 … … 4935 5088 if (StateIsLiveTV(mctx->GetState())) 4936 5089 mctx->buffer->Unpause(); 4937 5090 4938 bool ok = StartPlayer(mctx, mctx, mctx->GetState() , false);5091 bool ok = StartPlayer(mctx, mctx, mctx->GetState()); 4939 5092 4940 5093 if (ok) 4941 5094 { … … 4945 5098 { 4946 5099 VERBOSE(VB_IMPORTANT, loc + 4947 5100 "Failed to restart new main context (was pip context)"); 4948 ForceNextStateNone(mctx );5101 ForceNextStateNone(mctx, __LINE__); 4949 5102 return; 4950 5103 } 4951 5104 … … 4958 5111 if (StateIsLiveTV(pipctx->GetState())) 4959 5112 pipctx->buffer->Unpause(); 4960 5113 4961 ok = StartPlayer(mctx, pipctx, pipctx->GetState() , pipctx->isPIP());5114 ok = StartPlayer(mctx, pipctx, pipctx->GetState()); 4962 5115 4963 5116 if (ok) 4964 5117 { … … 4970 5123 { // TODO print OSD informing user of Swap failure ? 4971 5124 VERBOSE(VB_IMPORTANT, loc + 4972 5125 "Failed to restart new pip context (was main context)"); 4973 ForceNextStateNone(pipctx );5126 ForceNextStateNone(pipctx, __LINE__); 4974 5127 } 4975 5128 } 4976 5129 … … 4980 5133 mctx->nvp->SetMuteState(mctx_mute); 4981 5134 } 4982 5135 4983 void TV:: SwapPIP(PlayerContext *lctx, int ctx_index, bool ispbp)5136 void TV::PxPSwap(PlayerContext *mctx, int ctx_index) 4984 5137 { 4985 5138 lockTimerOn = false; 4986 5139 4987 PlayerContext *mctx = GetPlayer(lctx, 0); 4988 if (player.size() == 1) 5140 if (player.size() <= 1 || !mctx) 4989 5141 return; 4990 5142 4991 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; 4992 5147 4993 5148 if (!mctx->nvp || !pipctx->nvp || !pipctx->nvp->IsPlaying()) 4994 5149 return; … … 4996 5151 VERBOSE(VB_PLAYBACK, LOC + "SwapPIP -- begin"); 4997 5152 4998 5153 MuteState mctx_mute = mctx->nvp->GetMuteState(); 4999 5000 vector<long long> pos;5001 for (uint i = 0; i < player.size(); i++)5002 {5003 const PlayerContext *ctx = GetPlayer(lctx, i);5004 ctx->LockDeleteNVP(__FILE__, __LINE__);5005 pos.push_back((ctx->nvp) ? ctx->nvp->GetFramesPlayed() : 0);5006 ctx->UnlockDeleteNVP(__FILE__, __LINE__);5007 }5008 5009 5154 bool useNullVideo = pipctx->UseNullVideo(); 5010 5155 5011 TeardownPIPWindows(lctx);5156 vector<long long> pos = TeardownAllNVPs(mctx); 5012 5157 5013 swap(player[0], player[ctx_index]); 5014 swap(pos[0], pos[ctx_index]); 5015 5016 pipctx->SetPIPState((ispbp) ? kPBPLeft: kPIPOff); 5017 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 5018 5164 if (useNullVideo) 5019 5165 mctx->SetNullVideo(true); 5020 5166 5021 mctx->SetPIPState((ispbp) ? kPBPRight: kPIPonTV); 5022 5023 RestartPIPWindows(mctx, pos, mctx_mute); 5167 RestartAllNVPs(mctx, pos, mctx_mute); 5024 5168 } 5025 5169 5026 5170 void TV::DoPlay(PlayerContext *ctx) … … 5379 5523 ctx->playingInfo->ApplyTranscoderProfileChange(profile); 5380 5524 QString jobHost = ""; 5381 5525 5382 if ( gContext->GetNumSetting("JobsRunOnRecordHost", 0))5526 if (db_run_jobs_on_remote) 5383 5527 jobHost = ctx->playingInfo->hostname; 5384 5528 5385 5529 OSD *osd = GetOSDLock(ctx); … … 5590 5734 5591 5735 if (testrec && testrec->IsValidRecorder()) 5592 5736 { 5593 // 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); 5594 5740 5741 // pause the decoder first, so we're not reading too close to the end. 5595 5742 ctx->buffer->IgnoreLiveEOF(true); 5596 5743 ctx->buffer->StopReads(); 5597 5744 ctx->nvp->PauseDecoder(); … … 5601 5748 ctx->buffer->WaitForPause(); 5602 5749 ctx->nvp->StopPlaying(); 5603 5750 ctx->recorder->StopLiveTV(); 5604 { 5605 ctx->SetNVP(NULL); 5606 PlayerContext *mctx = GetPlayer(ctx, 0); 5607 if (ctx != mctx) 5608 SetPIPPlayer(mctx, ctx); 5609 } 5751 ctx->SetNVP(NULL); 5610 5752 5611 5753 // now restart stuff 5612 5754 ctx->lastSignalUIInfo.clear(); … … 5650 5792 ok = true; 5651 5793 ctx->StartOSD(this); 5652 5794 ctx->PushPreviousChannel(); 5653 if (ctx && (player.size() > 1)) 5654 { 5655 if (0 == playerActive) 5656 { 5657 PlayerContext *ctx1 = GetPlayer(ctx, 1); 5658 SetPIPPlayer(mctx, ctx1); 5659 } 5660 else 5661 { 5662 PlayerContext *mctx = GetPlayer(ctx, 0); 5663 SetPIPPlayer(mctx, ctx); 5664 } 5665 } 5795 for (uint i = 1; i < player.size(); i++) 5796 PIPAddPlayer(mctx, GetPlayer(ctx, i)); 5666 5797 5667 5798 SetSpeedChangeTimer(25, __LINE__); 5668 5799 } … … 6949 7080 margin = margin * 5; 6950 7081 QDomElement xmldata; 6951 7082 XMLParse *theme = new XMLParse(); 6952 if (!allowembed || 6953 !theme->LoadTheme(xmldata, str) || 6954 !gContext->GetNumSetting("ContinueEmbeddedTVPlay", 0) || 6955 ctx->nvp->IsNearEnd(margin) || 6956 ctx->paused) 7083 if (!allowembed || !theme->LoadTheme(xmldata, str) || 7084 !db_continue_embedded || ctx->nvp->IsNearEnd(margin) || ctx->paused) 6957 7085 { 6958 7086 if (!stayPaused) 6959 7087 DoPause(ctx, false); … … 6968 7096 6969 7097 void TV::DoEditSchedule(int editType) 6970 7098 { 6971 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 6972 mctx->LockPlayingInfo(__FILE__, __LINE__); 6973 if (!mctx->playingInfo) 7099 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 7100 7101 actx->LockPlayingInfo(__FILE__, __LINE__); 7102 if (!actx->playingInfo) 6974 7103 { 6975 7104 VERBOSE(VB_IMPORTANT, 6976 LOC_ERR + "doEditSchedule(): no active mctx->playingInfo.");6977 mctx->UnlockPlayingInfo(__FILE__, __LINE__);6978 ReturnPlayerLock( mctx);7105 LOC_ERR + "doEditSchedule(): no active ctx playingInfo."); 7106 actx->UnlockPlayingInfo(__FILE__, __LINE__); 7107 ReturnPlayerLock(actx); 6979 7108 return; 6980 7109 } 6981 7110 6982 7111 // Collect channel info 6983 uint chanid = mctx->playingInfo->chanid.toUInt();6984 QString channum = mctx->playingInfo->chanstr;6985 mctx->UnlockPlayingInfo(__FILE__, __LINE__);7112 uint chanid = actx->playingInfo->chanid.toUInt(); 7113 QString channum = actx->playingInfo->chanstr; channum.detach(); 7114 actx->UnlockPlayingInfo(__FILE__, __LINE__); 6986 7115 6987 ClearOSD( mctx);7116 ClearOSD(actx); 6988 7117 6989 7118 // Resize window to the MythTV GUI size 6990 7119 PlayerContext *mctx = GetPlayer(actx, 0); 6991 7120 if (mctx->nvp && mctx->nvp->getVideoOutput()) 6992 7121 mctx->nvp->getVideoOutput()->ResizeForGui(); 6993 7122 MythMainWindow *mwnd = gContext->GetMainWindow(); 6994 bool using_gui_size_for_tv = gContext->GetNumSetting("GuiSizeForTV", 0); 6995 if (! using_gui_size_for_tv)7123 7124 if (!db_use_gui_size_for_tv) 6996 7125 { 6997 7126 mwnd->setGeometry(saved_gui_bounds.left(), saved_gui_bounds.top(), 6998 7127 saved_gui_bounds.width(), saved_gui_bounds.height()); … … 7018 7147 player = this; 7019 7148 if (StateIsLiveTV(GetState(mctx))) 7020 7149 { 7021 ReturnPlayerLock( mctx);7150 ReturnPlayerLock(actx); 7022 7151 changeChannel = GuideGrid::Run(chanid, channum, false, 7023 7152 player, allowsecondary); 7024 mctx = GetPlayerReadLock(0, __FILE__, __LINE__);7153 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7025 7154 } 7026 7155 else 7027 7156 { 7028 ReturnPlayerLock( mctx);7157 ReturnPlayerLock(actx); 7029 7158 GuideGrid::Run(chanid, channum, false, player); 7030 mctx = GetPlayerReadLock(0, __FILE__, __LINE__);7159 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7031 7160 } 7032 7161 break; 7033 7162 } 7034 7163 case kScheduleProgramFinder: 7035 7164 if (!mctx->paused) 7036 7165 DoPause(mctx, false); 7166 ReturnPlayerLock(actx); 7037 7167 RunProgramFind(false, false); 7168 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7038 7169 break; 7039 7170 case kScheduledRecording: 7040 7171 { 7041 7172 if (mctx->paused) 7042 7173 DoPause(mctx, false); 7174 7043 7175 mctx->LockPlayingInfo(__FILE__, __LINE__); 7176 const ProgramInfo pginfo(*mctx->playingInfo); 7177 mctx->UnlockPlayingInfo(__FILE__, __LINE__); 7178 ReturnPlayerLock(actx); 7179 7044 7180 ScheduledRecording *record = new ScheduledRecording(); 7045 record->loadByProgram( mctx->playingInfo);7181 record->loadByProgram(&pginfo); 7046 7182 record->exec(); 7047 7183 record->deleteLater(); 7048 mctx->UnlockPlayingInfo(__FILE__, __LINE__); 7184 7185 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7049 7186 break; 7050 7187 } 7051 7188 case kViewSchedule: 7052 7189 { 7053 7190 showvideo = VideoThemeCheck(mctx, "conflict-video", stayPaused); 7191 ReturnPlayerLock(actx); 7054 7192 RunViewScheduledPtr((void *)this, showvideo); 7193 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7055 7194 break; 7056 7195 } 7057 7196 case kPlaybackBox: 7058 7197 { 7059 7198 showvideo = VideoThemeCheck(mctx, "playback-video", stayPaused); 7199 ReturnPlayerLock(actx); 7060 7200 nextProgram = RunPlaybackBoxPtr((void *)this, showvideo); 7201 actx = GetPlayerReadLock(0, __FILE__, __LINE__); 7061 7202 } 7062 7203 } 7063 7204 … … 7072 7213 embedCheckTimerId = 0; 7073 7214 } 7074 7215 7075 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))) && 7076 7220 !stayPaused && mctx->paused) 7077 7221 { 7222 VERBOSE(VB_PLAYBACK, LOC + "Unpausing video"); 7223 // this should unpause video.. 7078 7224 DoPause(mctx, true); 7079 7225 } 7080 ReturnPlayerLock( mctx);7226 ReturnPlayerLock(actx); 7081 7227 7082 7228 mctx = GetPlayerWriteLock(0, __FILE__, __LINE__); 7083 7229 if (nextProgram) 7084 7230 { 7085 if ( nextProgPIPState == kPIPonTV)7231 if (jumpToProgramPIPState == kPIPonTV) 7086 7232 CreatePIP(mctx, nextProgram); 7087 else if ( nextProgPIPState == kPBPLeft)7233 else if (jumpToProgramPIPState == kPBPLeft) 7088 7234 CreatePBP(mctx, nextProgram); 7089 7235 else 7090 7236 { 7091 setLastProgram(nextProgram);7237 SetLastProgram(nextProgram); 7092 7238 jumpToProgram = true; 7093 7239 SetExitPlayer(true, true); 7094 7240 } 7095 7241 mctx = GetPlayer(mctx, 0); // CreatePBP/PIP mess with ctx's 7096 7242 7097 nextProgPIPState = kPIPOff;7243 jumpToProgramPIPState = kPIPOff; 7098 7244 delete nextProgram; 7099 7245 nextProgram = NULL; 7100 7246 } … … 7102 7248 7103 7249 mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 7104 7250 // Resize the window back to the MythTV Player size 7105 if (! using_gui_size_for_tv)7251 if (!db_use_gui_size_for_tv) 7106 7252 { 7107 7253 mwnd->setGeometry(player_bounds.left(), player_bounds.top(), 7108 7254 player_bounds.width(), player_bounds.height()); … … 7124 7270 7125 7271 void TV::EditSchedule(const PlayerContext *ctx, int editType) 7126 7272 { 7127 if (ctx && (player.size() > 1))7128 return;7129 7130 7273 // post the request to the main UI thread 7131 7274 // it will be caught in eventFilter and processed as CustomEvent 7132 7275 // this will create the program guide window (widget) … … 7486 7629 { 7487 7630 ctx->nvp->SetWatchingRecording(false); 7488 7631 ctx->nvp->SetLength(filelen); 7489 ctx->ChangeState(kState_WatchingPreRecorded );7632 ctx->ChangeState(kState_WatchingPreRecorded, __LINE__); 7490 7633 ScheduleStateChange(ctx); 7491 7634 } 7492 7635 } … … 7636 7779 7637 7780 if (message.left(12) == "EXIT_TO_MENU") 7638 7781 { 7639 int exitprompt = gContext->GetNumSetting("PlaybackExitPrompt");7640 7641 7782 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 7642 7783 for (uint i = 0; mctx && (i < player.size()); i++) 7643 7784 { 7644 7785 PlayerContext *ctx = GetPlayer(mctx, i); 7645 7786 if (!ctx->nvp) 7646 7787 continue; 7647 if ( exitprompt == 1 || exitprompt == 2)7788 if (db_playback_exit_prompt == 1 || db_playback_exit_prompt == 2) 7648 7789 ctx->nvp->SetBookmark(); 7649 if (ctx->nvp && gContext->GetNumSetting("AutomaticSetWatched", 0))7790 if (ctx->nvp && db_auto_set_watched) 7650 7791 ctx->nvp->SetWatched(); 7651 7792 } 7652 7793 … … 7725 7866 } 7726 7867 } 7727 7868 7728 i nt player_cnt = 0;7869 if (message.left(9) == "START_EPG") 7729 7870 { 7730 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__);7731 player_cnt = player.size();7732 ReturnPlayerLock(mctx);7733 }7734 7735 if (message.left(9) == "START_EPG" && (1 == player_cnt))7736 {7737 7871 int editType = tokens[1].toInt(); 7738 7872 DoEditSchedule(editType); 7739 7873 } … … 7836 7970 browsechannum = ctx->playingInfo->chanstr; 7837 7971 browsechanid = ctx->playingInfo->chanid; 7838 7972 browsestarttime = ctx->playingInfo->startts.toString(); 7973 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 7839 7974 7840 7975 BrowseDispInfo(ctx, BROWSE_SAME); 7841 7976 … … 7844 7979 KillTimer(browseTimerId); 7845 7980 browseTimerId = StartTimer(kBrowseTimeout, __LINE__); 7846 7981 } 7847 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 7982 else 7983 { 7984 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 7985 } 7848 7986 } 7849 7987 7850 7988 /** \fn TV::BrowseEnd(PlayerContext*, bool) … … 7978 8116 QString cmdmsg(""); 7979 8117 if (ctx->playingInfo->GetAutoExpireFromRecorded() == kLiveTVAutoExpire) 7980 8118 { 7981 int autoexpiredef = gContext->GetNumSetting("AutoExpireDefault", 0); 7982 ctx->playingInfo->SetAutoExpire(autoexpiredef); 8119 ctx->playingInfo->SetAutoExpire(db_autoexpire_default); 7983 8120 ctx->playingInfo->ApplyRecordRecGroupChange("Default"); 7984 8121 cmdmsg = tr("Record"); 7985 8122 ctx->SetPseudoLiveTV(ctx->playingInfo, kPseudoRecording); … … 8147 8284 SetUpdateOSDPosition(false); 8148 8285 } 8149 8286 8150 void TV::SetActive(PlayerContext *ctx, int index) 8287 #include <cassert> 8288 void TV::SetActive(PlayerContext *lctx, int index, bool osd_msg) 8151 8289 { 8152 VERBOSE(VB_PLAYBACK, "TV::SetActive -- begin"); 8290 assert(lctx); 8291 if (!lctx) 8292 return; 8153 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 8154 8299 if (playerActive == index) 8155 8300 { 8156 VERBOSE(VB_PLAYBACK, "TV::SetActive -- index == active context");8301 VERBOSE(VB_PLAYBACK, loc + " -- end (index == playerActive)"); 8157 8302 return; 8158 8303 } 8159 8304 8160 VERBOSE(VB_PLAYBACK, "TV::SetActive -- lock"); 8305 index = (index < 0) ? (playerActive+1) % player.size() : index; 8306 index = (index >= (int)player.size()) ? 0 : index; 8161 8307 8162 PlayerContext *actx = NULL;8308 playerActive = index; 8163 8309 8164 if (playerActive > -1 && !ctx)8310 for (int i = 0; i < (int)player.size(); i++) 8165 8311 { 8166 actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 8167 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__); 8168 8317 } 8169 8318 8170 VERBOSE(VB_PLAYBACK, 8171 QString("TV::SetActive changing playerActive " 8172 "from %1 to %2") 8173 .arg(playerActive).arg(index)); 8174 8175 playerActive = index; 8176 8177 if (!ctx) 8319 #if 0 8320 // seems reduntant, except maybe for main player? -dtk 8321 if (osd_msg) 8178 8322 { 8179 actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 8180 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); 8181 8328 } 8329 #endif 8330 8331 VERBOSE(VB_PLAYBACK, loc + " -- end"); 8182 8332 } 8183 8333 8184 8334 void TV::TreeMenuEntered(OSDListTreeType *tree, OSDGenericTree *item) … … 8725 8875 EditSchedule(actx, kScheduleProgramFinder); 8726 8876 else if (action == "SCHEDULE") 8727 8877 EditSchedule(actx, kScheduledRecording); 8728 else if ((action == "JUMPPREV") ||8729 ((action == "PREVCHAN") && (!StateIsLiveTV(GetState(actx)))))8730 {8731 if (PromptRecGroupPassword(actx))8732 {8733 actx->nvp->SetBookmark();8734 jumpToProgram = true;8735 SetExitPlayer(true, true);8736 }8737 }8738 8878 else if (action == "VIEWSCHEDULED") 8739 8879 EditSchedule(actx, kViewSchedule); 8740 else if ( action == "JUMPREC")8880 else if (HandleJumpToProgramAction(actx, QStringList(action))) 8741 8881 { 8742 if (gContext->GetNumSetting("JumpToProgramOSD", 1) &&8743 StateIsPlaying(actx->GetState()))8744 {8745 if (jumpMenuTimerId)8746 KillTimer(jumpMenuTimerId);8747 jumpMenuTimerId = StartTimer(1, __LINE__);8748 }8749 else if (RunPlaybackBoxPtr)8750 EditSchedule(actx, kPlaybackBox);8751 8882 } 8752 else if ( action == "TOGGLEPIPMODE")8883 else if (PxPHandleAction(actx, QStringList(action))) 8753 8884 { 8754 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); 8755 8893 8756 actx = GetPlayerWriteLock(-1, __FILE__, __LINE__); 8757 TogglePIPView(actx); 8758 ReturnPlayerLock(actx); 8894 hidetree = true; 8759 8895 8760 actx = GetPlayer ReadLock(-1, __FILE__, __LINE__);8896 actx = GetPlayer(actx,-1); // "NEXTPIPWINDOW" changes active context.. 8761 8897 } 8762 else if (action == "TOGGLEPBPMODE")8763 {8764 needToMakePIPChange = kPBPToggle;8765 if (pipChangeTimerId)8766 KillTimer(pipChangeTimerId);8767 pipChangeTimerId = StartTimer(1, __LINE__);8768 }8769 else if (action == "TOGGLEPIPWINDOW")8770 ToggleActiveWindow(actx, 1);8771 else if (action == "TOGGLEPIPSTATE")8772 {8773 needToMakePIPChange = (actx->isPBP()) ? kPBPToPIP : kPIPToPBP;8774 if (pipChangeTimerId)8775 KillTimer(pipChangeTimerId);8776 pipChangeTimerId = StartTimer(1, __LINE__);8777 }8778 else if (action == "SWAPPIP")8779 {8780 needToMakePIPChange = (actx->isPBP()) ? kPBPSwap : kPIPSwap;8781 if (pipChangeTimerId)8782 KillTimer(pipChangeTimerId);8783 pipChangeTimerId = StartTimer(1, __LINE__);8784 }8785 8898 else if (StateIsLiveTV(GetState(actx))) 8786 8899 { 8787 8900 if (action == "TOGGLEBROWSE") … … 8825 8938 DoQueueTranscode(actx, "Medium Quality"); 8826 8939 else if (action == "QUEUETRANSCODE_LOW") 8827 8940 DoQueueTranscode(actx, "Low Quality"); 8828 else if (action.left(8) == "JUMPPROG")8829 {8830 SetJumpToProgram(action.section(" ",1,-2),8831 action.section(" ",-1,-1).toInt());8832 actx->nvp->SetBookmark();8833 jumpToProgram = true;8834 SetExitPlayer(true, true);8835 }8836 8941 else 8837 8942 { 8838 8943 VERBOSE(VB_IMPORTANT, LOC_ERR + … … 8893 8998 delete treeMenu; 8894 8999 8895 9000 treeMenu = new OSDGenericTree(NULL, "treeMenu"); 8896 OSDGenericTree *item, *subitem;8897 9001 8898 9002 bool freeRecorders = RemoteGetFreeRecorderCount(); 8899 9003 8900 if (IsPIPSupported(ctx) && ((ctx && (player.size() > 1)) || freeRecorders))8901 {8902 // Picture-in-Picture8903 item = new OSDGenericTree(treeMenu, tr("Picture-in-Picture"));8904 if (ctx && (player.size() == 1))8905 {8906 subitem = new OSDGenericTree(item, tr("Enable PIP"),8907 "TOGGLEPIPMODE");8908 subitem = new OSDGenericTree(item, tr("Enable PBP"),8909 "TOGGLEPBPMODE");8910 }8911 else8912 {8913 QString option = "Disable ";8914 QString switchTo = "Switch to ";8915 QString pipType = (ctx->isPBP()) ? "PBP" : "PIP";8916 QString changeTo = (ctx->isPBP()) ? "PIP" : "PBP";8917 option += pipType;8918 switchTo += changeTo;8919 QString toggleMode = QString("TOGGLE%1MODE").arg(pipType);8920 subitem = new OSDGenericTree(item, option, toggleMode);8921 subitem = new OSDGenericTree(item, tr("Swap Windows"),8922 "SWAPPIP");8923 subitem = new OSDGenericTree(item, tr("Change Active Window"),8924 "TOGGLEPIPWINDOW");8925 subitem = new OSDGenericTree(item, switchTo, "TOGGLEPIPSTATE");8926 }8927 }8928 8929 9004 if (freeRecorders && ctx->recorder) 8930 9005 { 8931 9006 // Input switching … … 9003 9078 } 9004 9079 } 9005 9080 9081 FillMenuPxP(ctx, treeMenu, freeRecorders); 9082 9006 9083 if ((ctx != GetPlayer(ctx, 0))) 9007 9084 return; 9008 9085 … … 9153 9230 new OSDGenericTree(s_item, "120 " + tr("minutes"), "TOGGLESLEEP120"); 9154 9231 } 9155 9232 9156 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) 9157 9236 { 9158 new OSDGenericTree(treeMenu, tr("Program Guide"), "GUIDE"); 9237 if (!ctx || !IsPIPSupported(ctx)) 9238 return; 9159 9239 9160 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) 9161 9247 { 9162 OSDGenericTree *jtpo_item = 9163 new OSDGenericTree(treeMenu, tr("Jump to Program")); 9164 new OSDGenericTree(jtpo_item, tr("Recorded Program"), "JUMPREC"); 9165 if (lastProgram != NULL) 9166 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"); 9167 9252 } 9168 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 9169 9305 if (!persistentbrowsemode) 9170 9306 new OSDGenericTree(treeMenu, tr("Enable Browse Mode"), "TOGGLEBROWSE"); 9171 9307 … … 9395 9531 ReturnOSDLock(ctx, osd); 9396 9532 } 9397 9533 9398 void TV::SetJumpToProgram(QString progKey, int progIndex) 9534 bool TV::HandleJumpToProgramAction( 9535 PlayerContext *ctx, const QStringList &actions) 9399 9536 { 9400 QMap<QString,ProgramList>::Iterator Iprog; 9401 Iprog = progLists.find(progKey); 9402 ProgramList plist = *Iprog; 9403 ProgramInfo *p = plist.at(progIndex); 9404 VERBOSE(VB_IMPORTANT, QString("Switching to program: %1: %2") 9405 .arg(p->title).arg(p->subtitle)); 9406 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; 9407 9664 } 9408 9665 9409 9666 void TV::ToggleSleepTimer(const PlayerContext *ctx, const QString &time) … … 9761 10018 9762 10019 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 9763 10020 9764 if (isDVD && (!gContext->GetNumSetting("EnableDVDBookmark", 0) || 9765 ctx->buffer->DVD()->GetTotalTimeOfTitle() < 120)) 9766 { 9767 return false; 9768 } 9769 9770 return true; 10021 return (!isDVD || (db_use_dvd_bookmark && 10022 ctx->buffer->DVD()->GetTotalTimeOfTitle() >= 120)); 9771 10023 } 9772 10024 9773 10025 /* \fn TV::IsDeleteAllowed(const PlayerContext*) const … … 9909 10161 dialogname == "exitplayoptions"); 9910 10162 } 9911 10163 9912 void TV:: setLastProgram(ProgramInfo *rcinfo)10164 void TV::SetLastProgram(ProgramInfo *rcinfo) 9913 10165 { 10166 QMutexLocker locker(&lastProgramLock); 10167 9914 10168 if (lastProgram) 9915 10169 delete lastProgram; 9916 10170 … … 9920 10174 lastProgram = NULL; 9921 10175 } 9922 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 9923 10185 QString TV::GetRecordingGroup(int player_idx) const 9924 10186 { 9925 10187 QString ret = QString::null; … … 10014 10276 treeMenu = new OSDGenericTree(NULL, "treeMenu"); 10015 10277 10016 10278 // Build jumpMenu of recorded program titles 10017 ProgramInfo *p;10279 QMutexLocker locker(&progListsLock); 10018 10280 progLists.clear(); 10019 vector<ProgramInfo *> *infoList; 10020 infoList = RemoteGetRecordedList(false); 10281 vector<ProgramInfo *> *infoList = RemoteGetRecordedList(false); 10021 10282 10022 10283 //bool LiveTVInAllPrograms = gContext->GetNumSetting("LiveTVInAllPrograms",0); 10023 10284 if (infoList) 10024 10285 { 10025 10286 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 10026 10287 actx->LockPlayingInfo(__FILE__, __LINE__); 10027 vector<ProgramInfo *>:: iterator i= infoList->begin();10028 for ( ; i != infoList->end(); i++)10288 vector<ProgramInfo *>::const_iterator it = infoList->begin(); 10289 for ( ; it != infoList->end(); it++) 10029 10290 { 10030 p = *i;10031 10291 //if (p->recgroup != "LiveTV" || LiveTVInAllPrograms) 10032 if ( p->recgroup == actx->playingInfo->recgroup)10033 progLists[ p->title].prepend(p);10292 if ((*it)->recgroup == actx->playingInfo->recgroup) 10293 progLists[(*it)->title].push_front(new ProgramInfo(*(*it))); 10034 10294 } 10035 10295 actx->UnlockPlayingInfo(__FILE__, __LINE__); 10036 10296 ReturnPlayerLock(actx); 10037 10297 10038 QMap<QString,ProgramList>:: Iterator Iprog;10298 QMap<QString,ProgramList>::const_iterator Iprog; 10039 10299 for (Iprog = progLists.begin(); Iprog != progLists.end(); Iprog++) 10040 10300 { 10041 ProgramListplist = *Iprog;10301 const ProgramList &plist = *Iprog; 10042 10302 int progIndex = plist.count(); 10043 10303 if (progIndex == 1) 10044 10304 { … … 10053 10313 10054 10314 for (int i = 0; i < progIndex; i++) 10055 10315 { 10056 p = plist.at(i);10057 if ( p->subtitle.size())10316 const ProgramInfo *p = plist[i]; 10317 if (!p->subtitle.isEmpty()) 10058 10318 new OSDGenericTree(j_item, p->subtitle, 10059 10319 QString("JUMPPROG %1 %2").arg(Iprog.key()).arg(i)); 10060 10320 else … … 10064 10324 } 10065 10325 } 10066 10326 } 10327 while (!infoList->empty()) 10328 { 10329 delete infoList->back(); 10330 infoList->pop_back(); 10331 } 10332 delete infoList; 10067 10333 10068 10334 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 10069 10335 OSD *osd = GetOSDLock(actx); … … 10085 10351 } 10086 10352 } 10087 10353 ReturnOSDLock(actx, osd); 10088 10354 ReturnPlayerLock(actx); 10089 10355 } 10090 10356 10091 10357 void TV::RestoreScreenSaver(const PlayerContext *ctx) … … 10096 10362 10097 10363 void TV::InitUDPNotifyEvent(void) 10098 10364 { 10099 uint udp_port = gContext->GetNumSetting("UDPNotifyPort"); 10100 if (udp_port && !udpnotify) 10365 if (db_udpnotify_port && !udpnotify) 10101 10366 { 10102 udpnotify = new UDPNotify( udp_port);10367 udpnotify = new UDPNotify(db_udpnotify_port); 10103 10368 connect(udpnotify, 10104 10369 SIGNAL(AddUDPNotifyEvent( 10105 10370 const QString&,const UDPNotifyOSDSet*)), … … 10234 10499 { 10235 10500 playerLock.lockForWrite(); 10236 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 10237 10506 if ((which >= (int)player.size())) 10238 10507 { 10239 10508 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 10249 10518 { 10250 10519 playerLock.lockForRead(); 10251 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 10252 10525 if ((which >= (int)player.size())) 10253 10526 { 10254 10527 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 10265 10538 { 10266 10539 playerLock.lockForRead(); 10267 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 10268 10545 if ((which >= (int)player.size())) 10269 10546 { 10270 10547 VERBOSE(VB_IMPORTANT, LOC_WARN + … … 10312 10589 10313 10590 void TV::ReturnPlayerLock(PlayerContext *&ctx) 10314 10591 { 10592 //VERBOSE(VB_IMPORTANT, LOC_WARN + 10593 // QString("ReturnPlayerLock() size(%4)") 10594 // .arg(player.size())); 10595 10315 10596 playerLock.unlock(); 10316 10597 ctx = NULL; 10317 10598 } 10318 10599 10319 10600 void TV::ReturnPlayerLock(const PlayerContext *&ctx) const 10320 10601 { 10602 //VERBOSE(VB_IMPORTANT, LOC_WARN + 10603 // QString("ReturnPlayerLock() const size(%4)") 10604 // .arg(player.size())); 10605 10321 10606 playerLock.unlock(); 10322 10607 ctx = NULL; 10323 10608 } -
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
887 887 888 888 int pipw, piph; 889 889 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph); 890 const bool pipActive = false;890 const bool pipActive = pipplayer->IsPIPActive(); 891 891 const float pipVideoAspect = pipplayer->GetVideoAspect(); 892 892 const QSize pipVideoDim = pipplayer->GetVideoBufferSize(); 893 893 const uint pipVideoWidth = pipVideoDim.width(); -
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.cpp
3606 3606 3607 3607 int pipw, piph; 3608 3608 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph); 3609 const bool pipActive = false;3609 const bool pipActive = pipplayer->IsPIPActive(); 3610 3610 const float pipVideoAspect = pipplayer->GetVideoAspect(); 3611 3611 const QSize pipVideoDim = pipplayer->GetVideoBufferSize(); 3612 3612 const uint pipVideoWidth = pipVideoDim.width();