Ticket #8757: 8757-v1.patch
File 8757-v1.patch, 63.8 KB (added by , 14 years ago) |
---|
-
libs/libmythtv/libmythtv.pro
255 255 HEADERS += tv_play_win.h deletemap.h 256 256 HEADERS += mythcommflagplayer.h commbreakmap.h 257 257 HEADERS += BDRingBuffer.h mythbdplayer.h 258 HEADERS += mythiowrapper.h 258 HEADERS += mythiowrapper.h tvbrowsehelper.h 259 259 SOURCES += tv_play.cpp mythplayer.cpp 260 260 SOURCES += mythdvdplayer.cpp audioplayer.cpp 261 261 SOURCES += DVDRingBuffer.cpp playercontext.cpp 262 262 SOURCES += tv_play_win.cpp deletemap.cpp 263 263 SOURCES += mythcommflagplayer.cpp commbreakmap.cpp 264 264 SOURCES += BDRingBuffer.cpp mythbdplayer.cpp 265 SOURCES += mythiowrapper.cpp 265 SOURCES += mythiowrapper.cpp tvbrowsehelper.cpp 266 266 267 267 # Text subtitle parser 268 268 HEADERS += textsubtitleparser.h xine_demux_sputext.h -
libs/libmythtv/tv_play.h
58 58 class TV; 59 59 class OSDListTreeItemEnteredEvent; 60 60 class OSDListTreeItemSelectedEvent; 61 class TVBrowseHelper; 61 62 struct osdInfo; 62 63 63 64 typedef QMap<QString,InfoMap> DDValueMap; … … 78 79 // -> timerIdLock 79 80 // -> mainLoopCondLock 80 81 // -> stateChangeCondLock 81 // -> browseLock82 // -> channelGroupLock 82 83 // 83 84 // When holding one of these locks, you may lock any lock of the locks to 84 85 // the right of the current lock, but may not lock any lock to the left of … … 169 170 friend class PlaybackBox; 170 171 friend class GuideGrid; 171 172 friend class TvPlayWindow; 173 friend class TVBrowseHelper; 172 174 173 175 Q_OBJECT 174 176 public: … … 192 194 void ProcessKeypress(PlayerContext*, QKeyEvent *e); 193 195 void ProcessNetworkControlCommand(PlayerContext *, const QString &command); 194 196 void customEvent(QEvent *e); 197 bool event(QEvent *e); 195 198 bool HandleTrackAction(PlayerContext*, const QString &action); 196 199 197 200 // LiveTV commands … … 263 266 const QStringList &actions, 264 267 bool isDVD, bool isDVDStillFrame); 265 268 266 void GetNextProgram(RemoteEncoder *enc,267 BrowseDirection direction, InfoMap &infoMap) const;268 void GetNextProgram(BrowseDirection direction, InfoMap &infoMap) const;269 270 269 // static functions 271 270 static void InitKeys(void); 272 271 static void ResetKeys(void); … … 285 284 void HandleUDPNotifyEvent(void); 286 285 287 286 // Channel Groups 288 void SaveChannelGroup(void);289 287 void UpdateChannelList(int groupID); 290 288 291 289 public slots: … … 515 513 516 514 void ToggleAutoExpire(PlayerContext*); 517 515 518 void BrowseStart(PlayerContext*);519 void BrowseEnd(PlayerContext*, bool change_channel);520 void BrowseDispInfo(PlayerContext*, BrowseDirection direction);521 void BrowseChannel(PlayerContext*, const QString &channum);522 516 bool BrowseHandleAction(PlayerContext*, const QStringList &actions); 523 uint BrowseAllGetChanId(const QString &chan) const;524 517 525 518 void ToggleRecord(PlayerContext*); 526 519 … … 652 645 // Configuration variables from database 653 646 QString baseFilters; 654 647 QString db_channel_format; 655 QString db_time_format;656 QString db_short_date_format;657 648 uint db_idle_timeout; 658 649 uint db_udpnotify_port; 659 uint db_browse_max_forward;660 650 int db_playback_exit_prompt; 661 651 uint db_autoexpire_default; 662 652 bool db_auto_set_watched; … … 670 660 bool db_use_fixed_size; 671 661 bool db_browse_always; 672 662 bool db_browse_all_tuners; 673 DBChanList db_browse_all_channels; 663 bool db_use_channel_groups; 664 bool db_remember_last_channel_group; 665 ChannelGroupList db_channel_groups; 674 666 675 667 bool arrowAccel; 676 668 … … 763 755 QDateTime lastLockSeenTime; 764 756 765 757 // Channel browsing state variables 766 bool browsemode; 767 QString browsechannum; 768 uint browsechanid; 769 QString browsestarttime; 770 mutable QMutex browseLock; // protects db_browse_all_channels 758 TVBrowseHelper *browsehelper; 771 759 772 760 // Program Info for currently playing video 773 761 // (or next video if InChangeState() is true) … … 834 822 #endif // PLAY_FROM_RECORDER 835 823 836 824 // Channel group stuff 837 int channel_group_id; 838 uint browse_changrp; 839 ChannelGroupList m_changrplist; 840 DBChanList m_channellist; 825 mutable QMutex channelGroupLock; 826 int channelGroupId; 827 DBChanList channelGroupChannelList; 841 828 842 829 // Network Control stuff 843 830 MythDeque<QString> networkControlCommands; -
libs/libmythtv/tvbrowsehelper.h
1 // -*- Mode: c++ -*- 2 3 #ifndef _TV_BROWSE_HELPER_H_ 4 #define _TV_BROWSE_HELPER_H_ 5 6 #include <QWaitCondition> 7 #include <QThread> 8 #include <QString> 9 10 #include "dbchannelinfo.h" // for DBChanList 11 #include "programtypes.h" // for InfoMap 12 #include "tv.h" // for BrowseDirection 13 14 class PlayerContext; 15 class RemoteEncoder; 16 class TV; 17 18 class BrowseInfo 19 { 20 public: 21 BrowseInfo(BrowseDirection dir) : 22 m_dir(dir), m_chanid(0) 23 { 24 } 25 BrowseInfo(BrowseDirection dir, 26 const QString &channum, 27 uint chanid, 28 const QString &starttime) : 29 m_dir(dir), m_channum(channum), 30 m_chanid(0), m_starttime(starttime) 31 { 32 } 33 34 BrowseDirection m_dir; 35 QString m_channum; 36 uint m_chanid; 37 QString m_starttime; 38 }; 39 40 41 class TVBrowseHelper : public QThread 42 { 43 public: 44 TVBrowseHelper(TV *tv, 45 QString time_format, 46 QString short_date_format, 47 uint browse_max_forward, 48 bool browse_all_tuners, 49 bool use_channel_groups, 50 QString db_channel_ordering); 51 52 virtual ~TVBrowseHelper() 53 { 54 Stop(); 55 Wait(); 56 } 57 58 virtual void deleteLater() 59 { 60 Stop(); 61 QThread::deleteLater(); 62 } 63 64 void Stop() 65 { 66 QMutexLocker locker(&m_lock); 67 m_list.clear(); 68 m_run = false; 69 m_wait.wakeAll(); 70 } 71 72 void Wait() { QThread::wait(); } 73 74 bool BrowseStart(PlayerContext *ctx, bool skip_browse = false); 75 void BrowseEnd(PlayerContext *ctx, bool change_channel); 76 void BrowseDispInfo(PlayerContext *ctx, BrowseInfo &bi); 77 78 void BrowseDispInfo(PlayerContext *ctx, BrowseDirection direction) 79 { 80 BrowseInfo bi(direction); 81 if (BROWSE_SAME != direction) 82 BrowseDispInfo(ctx, bi); 83 } 84 85 void BrowseChannel(PlayerContext *ctx, const QString &channum) 86 { 87 BrowseInfo bi(BROWSE_SAME, channum, 0, ""); 88 BrowseDispInfo(ctx, bi); 89 } 90 91 BrowseInfo GetBrowsedInfo(void) const; 92 bool IsBrowsing(void) const; 93 uint BrowseAllGetChanId(const QString &channum) const; 94 95 protected: 96 void GetNextProgram(BrowseDirection direction, InfoMap &infoMap) const; 97 void GetNextProgramDB(BrowseDirection direction, InfoMap &infoMap) const; 98 99 virtual void run(); 100 101 TV *m_tv; 102 DBChanList db_browse_all_channels; 103 QString db_time_format; 104 QString db_short_date_format; 105 uint db_browse_max_forward; 106 bool db_browse_all_tuners; 107 bool db_use_channel_groups; 108 109 mutable QMutex m_lock; // protects variables below 110 PlayerContext *m_ctx; 111 QString m_channum; 112 uint m_chanid; 113 QString m_starttime; 114 bool m_run; 115 QWaitCondition m_wait; 116 QList<BrowseInfo> m_list; 117 }; 118 119 #endif // _TV_BROWSE_HELPER_H_ -
libs/libmythtv/tvbrowsehelper.cpp
1 #include "mythcorecontext.h" 2 3 #include <QCoreApplication> 4 5 #include "tvbrowsehelper.h" 6 #include "playercontext.h" 7 #include "remoteencoder.h" 8 #include "recordinginfo.h" 9 #include "tv_play.h" 10 11 #define GetPlayer(X,Y) GetPlayerHaveLock(X, Y, __FILE__ , __LINE__) 12 #define GetOSDLock(X) GetOSDL(X, __FILE__, __LINE__) 13 14 static void format_time(int seconds, QString &tMin, QString &tHrsMin) 15 { 16 int minutes = seconds / 60; 17 int hours = minutes / 60; 18 int min = minutes % 60; 19 20 tMin = TV::tr("%n minute(s)", "", minutes); 21 tHrsMin.sprintf("%d:%02d", hours, min); 22 } 23 24 TVBrowseHelper::TVBrowseHelper( 25 TV *tv, 26 QString time_format, 27 QString short_date_format, 28 uint browse_max_forward, 29 bool browse_all_tuners, 30 bool use_channel_groups, 31 QString db_channel_ordering) : 32 m_tv(tv), 33 db_time_format(time_format), 34 db_short_date_format(short_date_format), 35 db_browse_max_forward(browse_max_forward), 36 db_browse_all_tuners(browse_all_tuners), 37 db_use_channel_groups(use_channel_groups), 38 m_ctx(NULL), 39 m_chanid(0), 40 m_run(true) 41 { 42 if (db_browse_all_tuners) 43 { 44 db_browse_all_channels = ChannelUtil::GetChannels( 45 0, true, "channum, callsign"); 46 ChannelUtil::SortChannels( 47 db_browse_all_channels, db_channel_ordering, true); 48 } 49 50 start(); 51 } 52 53 54 /// \brief Begins channel browsing. 55 /// \note This may only be called from the UI thread. 56 bool TVBrowseHelper::BrowseStart(PlayerContext *ctx, bool skip_browse) 57 { 58 VERBOSE(VB_IMPORTANT, "BrowseStart()"); 59 60 if (!gCoreContext->IsUIThread()) 61 return false; 62 63 QMutexLocker locker(&m_lock); 64 65 if (m_ctx) 66 return m_ctx == ctx; 67 68 if (ctx->paused) 69 return false; 70 71 m_tv->ClearOSD(ctx); 72 73 ctx->LockPlayingInfo(__FILE__, __LINE__); 74 if (ctx->playingInfo) 75 { 76 m_ctx = ctx; 77 BrowseInfo bi(BROWSE_SAME, 78 ctx->playingInfo->GetChanNum(), 79 ctx->playingInfo->GetChanID(), 80 ctx->playingInfo->GetScheduledStartTime(ISODate)); 81 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 82 83 if (!skip_browse) 84 { 85 locker.unlock(); 86 BrowseDispInfo(ctx, bi); 87 } 88 return true; 89 } 90 else 91 { 92 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 93 return false; 94 } 95 } 96 97 /** \brief Ends channel browsing. 98 * Changing the channel if change_channel is true. 99 * \note This may only be called from the UI thread. 100 * \param ctx PlayerContext to end browsing on 101 * \param change_channel iff true we call ChangeChannel() 102 */ 103 void TVBrowseHelper::BrowseEnd(PlayerContext *ctx, bool change_channel) 104 { 105 VERBOSE(VB_IMPORTANT, "BrowseEnd()"); 106 107 if (!gCoreContext->IsUIThread()) 108 return; 109 110 QMutexLocker locker(&m_lock); 111 112 if (ctx && m_ctx != ctx) 113 return; 114 115 if (!m_ctx) 116 return; 117 118 { 119 QMutexLocker locker(&m_tv->timerIdLock); 120 if (m_tv->browseTimerId) 121 { 122 m_tv->KillTimer(m_tv->browseTimerId); 123 m_tv->browseTimerId = 0; 124 } 125 } 126 127 { 128 QMutexLocker locker(&m_lock); 129 m_list.clear(); 130 m_wait.wakeAll(); 131 } 132 133 OSD *osd = m_tv->GetOSDLock(ctx); 134 if (osd) 135 osd->HideWindow("browse_info"); 136 m_tv->ReturnOSDLock(ctx, osd); 137 138 if (change_channel) 139 m_tv->ChangeChannel(ctx, 0, m_channum); 140 141 m_ctx = NULL; 142 } 143 144 void TVBrowseHelper::BrowseDispInfo(PlayerContext *ctx, BrowseInfo &bi) 145 { 146 VERBOSE(VB_IMPORTANT, "BrowseDispInfo()"); 147 148 if (!gCoreContext->IsUIThread()) 149 return; 150 151 if (!BrowseStart(ctx, true)) 152 return; 153 154 { 155 QMutexLocker locker(&m_tv->timerIdLock); 156 if (m_tv->browseTimerId) 157 { 158 m_tv->KillTimer(m_tv->browseTimerId); 159 m_tv->browseTimerId = 160 m_tv->StartTimer(TV::kBrowseTimeout, __LINE__); 161 } 162 } 163 164 QMutexLocker locker(&m_lock); 165 if (BROWSE_SAME == bi.m_dir) 166 m_list.clear(); 167 m_list.push_back(bi); 168 m_wait.wakeAll(); 169 } 170 171 BrowseInfo TVBrowseHelper::GetBrowsedInfo(void) const 172 { 173 QMutexLocker locker(&m_lock); 174 BrowseInfo bi(BROWSE_SAME); 175 if (m_ctx != NULL) 176 { 177 bi.m_channum = m_channum; 178 bi.m_chanid = m_chanid; 179 bi.m_starttime = m_starttime; 180 } 181 return bi; 182 } 183 184 /** 185 * \note This may only be called from the UI thread. 186 */ 187 bool TVBrowseHelper::IsBrowsing(void) const 188 { 189 if (!gCoreContext->IsUIThread()) 190 return true; 191 192 return m_ctx != NULL; 193 } 194 195 /// Returns chanid of random channel with with matching channum 196 uint TVBrowseHelper::BrowseAllGetChanId(const QString &channum) const 197 { 198 DBChanList::const_iterator it = db_browse_all_channels.begin(); 199 for (; it != db_browse_all_channels.end(); ++it) 200 { 201 if ((*it).channum == channum) 202 return (*it).chanid; 203 } 204 return 0; 205 } 206 207 /** 208 * \brief Fetches information on the desired program from the backend. 209 * \param enc RemoteEncoder to query, if null query the actx->recorder. 210 * \param direction BrowseDirection to get information on. 211 * \param infoMap InfoMap to fill in with returned data 212 */ 213 void TVBrowseHelper::GetNextProgram( 214 BrowseDirection direction, InfoMap &infoMap) const 215 { 216 if (!m_ctx->recorder) 217 return; 218 219 QString title, subtitle, desc, category, endtime, callsign, iconpath; 220 QDateTime begts, endts; 221 222 QString starttime = infoMap["dbstarttime"]; 223 QString chanid = infoMap["chanid"]; 224 QString channum = infoMap["channum"]; 225 QString seriesid = infoMap["seriesid"]; 226 QString programid = infoMap["programid"]; 227 228 m_ctx->recorder->GetNextProgram( 229 direction, 230 title, subtitle, desc, category, 231 starttime, endtime, callsign, iconpath, 232 channum, chanid, seriesid, programid); 233 234 if (!starttime.isEmpty()) 235 begts = QDateTime::fromString(starttime, Qt::ISODate); 236 else 237 begts = QDateTime::fromString(infoMap["dbstarttime"], Qt::ISODate); 238 239 infoMap["starttime"] = begts.toString(db_time_format); 240 infoMap["startdate"] = begts.toString(db_short_date_format); 241 242 infoMap["endtime"] = infoMap["enddate"] = ""; 243 if (!endtime.isEmpty()) 244 { 245 endts = QDateTime::fromString(endtime, Qt::ISODate); 246 infoMap["endtime"] = endts.toString(db_time_format); 247 infoMap["enddate"] = endts.toString(db_short_date_format); 248 } 249 250 infoMap["lenmins"] = tr("%n minute(s)", "", 0); 251 infoMap["lentime"] = "0:00"; 252 if (begts.isValid() && endts.isValid()) 253 { 254 QString lenM, lenHM; 255 format_time(begts.secsTo(endts), lenM, lenHM); 256 infoMap["lenmins"] = lenM; 257 infoMap["lentime"] = lenHM; 258 } 259 260 infoMap["dbstarttime"] = starttime; 261 infoMap["dbendtime"] = endtime; 262 infoMap["title"] = title; 263 infoMap["subtitle"] = subtitle; 264 infoMap["description"] = desc; 265 infoMap["category"] = category; 266 infoMap["callsign"] = callsign; 267 infoMap["channum"] = channum; 268 infoMap["chanid"] = chanid; 269 infoMap["iconpath"] = iconpath; 270 infoMap["seriesid"] = seriesid; 271 infoMap["programid"] = programid; 272 } 273 274 void TVBrowseHelper::GetNextProgramDB( 275 BrowseDirection direction, InfoMap &infoMap) const 276 { 277 uint chanid = infoMap["chanid"].toUInt(); 278 if (!chanid) 279 chanid = BrowseAllGetChanId(infoMap["channum"]); 280 281 int chandir = -1; 282 switch (direction) 283 { 284 case BROWSE_UP: chandir = CHANNEL_DIRECTION_UP; break; 285 case BROWSE_DOWN: chandir = CHANNEL_DIRECTION_DOWN; break; 286 case BROWSE_FAVORITE: chandir = CHANNEL_DIRECTION_FAVORITE; break; 287 } 288 if (direction != BROWSE_INVALID) 289 { 290 chanid = ChannelUtil::GetNextChannel( 291 db_browse_all_channels, chanid, 0, chandir); 292 } 293 294 infoMap["chanid"] = QString::number(chanid); 295 296 DBChanList::const_iterator it = db_browse_all_channels.begin(); 297 for (; it != db_browse_all_channels.end(); ++it) 298 { 299 if ((*it).chanid == chanid) 300 { 301 QString tmp = (*it).channum; 302 tmp.detach(); 303 infoMap["channum"] = tmp; 304 break; 305 } 306 } 307 308 QDateTime nowtime = QDateTime::currentDateTime(); 309 QDateTime latesttime = nowtime.addSecs(6*60*60); 310 QDateTime browsetime = QDateTime::fromString( 311 infoMap["dbstarttime"], Qt::ISODate); 312 313 MSqlBindings bindings; 314 bindings[":CHANID"] = chanid; 315 bindings[":NOWTS"] = nowtime.toString("yyyy-MM-ddThh:mm:ss"); 316 bindings[":LATESTTS"] = latesttime.toString("yyyy-MM-ddThh:mm:ss"); 317 bindings[":BROWSETS"] = browsetime.toString("yyyy-MM-ddThh:mm:ss"); 318 bindings[":BROWSETS2"] = browsetime.toString("yyyy-MM-ddThh:mm:ss"); 319 320 QString querystr = " WHERE program.chanid = :CHANID "; 321 switch (direction) 322 { 323 case BROWSE_LEFT: 324 querystr += " AND program.endtime <= :BROWSETS " 325 " AND program.endtime > :NOWTS "; 326 break; 327 328 case BROWSE_RIGHT: 329 querystr += " AND program.starttime > :BROWSETS " 330 " AND program.starttime < :LATESTTS "; 331 break; 332 333 default: 334 querystr += " AND program.starttime <= :BROWSETS " 335 " AND program.endtime > :BROWSETS2 "; 336 }; 337 338 ProgramList progList; 339 ProgramList dummySched; 340 LoadFromProgram(progList, querystr, bindings, dummySched, false); 341 342 if (progList.empty()) 343 { 344 infoMap["dbstarttime"] = ""; 345 return; 346 } 347 348 const ProgramInfo *prog = (direction == BROWSE_LEFT) ? 349 progList[progList.size() - 1] : progList[0]; 350 351 infoMap["dbstarttime"] = prog->GetScheduledStartTime(ISODate); 352 } 353 354 void TVBrowseHelper::run() 355 { 356 QMutexLocker locker(&m_lock); 357 while (true) 358 { 359 while (m_list.empty() && m_run) 360 m_wait.wait(&m_lock); 361 362 if (!m_run) 363 break; 364 365 BrowseInfo bi = m_list.front(); 366 m_list.pop_front(); 367 368 PlayerContext *ctx = m_ctx; 369 370 if (BROWSE_SAME == bi.m_dir) 371 { 372 m_channum = bi.m_channum; 373 m_chanid = bi.m_chanid; 374 m_starttime = bi.m_starttime; 375 } 376 377 BrowseDirection direction = bi.m_dir; 378 379 QDateTime lasttime = QDateTime::fromString( 380 m_starttime, Qt::ISODate); 381 QDateTime curtime = QDateTime::currentDateTime(); 382 if (lasttime < curtime) 383 m_starttime = curtime.toString(Qt::ISODate); 384 385 QDateTime maxtime = curtime.addSecs(db_browse_max_forward); 386 if ((lasttime > maxtime) && (direction == BROWSE_RIGHT)) 387 continue; 388 389 m_lock.unlock(); 390 391 // if browsing channel groups is enabled or 392 // direction if BROWSE_FAVORITES 393 // Then pick the next channel in the channel group list to browse 394 // If channel group is ALL CHANNELS (-1), then bypass picking from 395 // the channel group list 396 if ((db_use_channel_groups || (direction == BROWSE_FAVORITE)) && 397 (direction != BROWSE_RIGHT) && (direction != BROWSE_LEFT) && 398 (direction != BROWSE_SAME)) 399 { 400 m_tv->channelGroupLock.lock(); 401 if (m_tv->channelGroupId > -1) 402 { 403 int dir = direction; 404 if ((direction == BROWSE_UP) || (direction == BROWSE_FAVORITE)) 405 dir = CHANNEL_DIRECTION_UP; 406 else if (direction == BROWSE_DOWN) 407 dir = CHANNEL_DIRECTION_DOWN; 408 409 uint chanid = ChannelUtil::GetNextChannel( 410 m_tv->channelGroupChannelList, m_chanid, 0, dir); 411 direction = BROWSE_SAME; 412 413 m_tv->channelGroupLock.unlock(); 414 415 m_lock.lock(); 416 m_chanid = chanid; 417 m_channum = QString::null; 418 m_lock.unlock(); 419 } 420 else 421 m_tv->channelGroupLock.unlock(); 422 } 423 424 if (direction == BROWSE_FAVORITE) 425 direction = BROWSE_UP; 426 427 InfoMap infoMap; 428 infoMap["dbstarttime"] = m_starttime; 429 infoMap["channum"] = m_channum; 430 infoMap["chanid"] = QString::number(m_chanid); 431 432 m_tv->GetPlayerReadLock(0,__FILE__,__LINE__); 433 bool still_there = false; 434 for (uint i = 0; i < m_tv->player.size() && !still_there; i++) 435 still_there |= (ctx == m_tv->player[0]); 436 if (still_there) 437 { 438 if (!db_browse_all_tuners) 439 { 440 GetNextProgram(direction, infoMap); 441 } 442 else 443 { 444 GetNextProgramDB(direction, infoMap); 445 while (!m_tv->IsTunable(ctx, infoMap["chanid"].toUInt()) && 446 (infoMap["channum"] != m_channum)) 447 { 448 GetNextProgramDB(direction, infoMap); 449 } 450 } 451 } 452 m_tv->ReturnPlayerLock(ctx); 453 454 m_lock.lock(); 455 if (!m_ctx && !still_there) 456 continue; 457 458 VERBOSE(VB_IMPORTANT, QString("browsechanid: %1 -> %2") 459 .arg(m_chanid).arg(infoMap["chanid"].toUInt())); 460 461 m_channum = infoMap["channum"]; 462 m_chanid = infoMap["chanid"].toUInt(); 463 464 if (((direction == BROWSE_LEFT) || (direction == BROWSE_RIGHT)) && 465 !infoMap["dbstarttime"].isEmpty()) 466 { 467 m_starttime = infoMap["dbstarttime"]; 468 } 469 470 if (!m_list.empty()) 471 { 472 // send partial info to UI for appearance of responsiveness 473 QCoreApplication::postEvent( 474 this, new UpdateBrowseInfoEvent(infoMap)); 475 continue; 476 } 477 m_lock.unlock(); 478 479 // pull in additional data from the DB... 480 QDateTime startts = QDateTime::fromString( 481 m_starttime, Qt::ISODate); 482 RecordingInfo recinfo(m_chanid, startts, false); 483 recinfo.ToMap(infoMap); 484 infoMap["iconpath"] = ChannelUtil::GetIcon(recinfo.GetChanID()); 485 486 m_lock.lock(); 487 if (m_ctx) 488 { 489 QCoreApplication::postEvent( 490 this, new UpdateBrowseInfoEvent(infoMap)); 491 } 492 } 493 } -
libs/libmythtv/tv_play.cpp
58 58 #include "videometadatautil.h" 59 59 #include "mythdialogbox.h" 60 60 #include "mythdirs.h" 61 #include "tvbrowsehelper.h" 61 62 62 63 #if ! HAVE_ROUND 63 64 #define round(x) ((int) ((x) + 0.5)) … … 421 422 bool allowrerecord = tv->getAllowRerecord(); 422 423 bool deleterecording = tv->requestDelete; 423 424 424 tv->SaveChannelGroup();425 426 425 delete tv; 427 426 428 427 if (curProgram) … … 857 856 : // Configuration variables from database 858 857 baseFilters(""), 859 858 db_channel_format("<num> <sign>"), 860 db_time_format("h:mm AP"), db_short_date_format("M/d"),861 859 db_idle_timeout(0), db_udpnotify_port(0), 862 db_browse_max_forward(14400),863 860 db_playback_exit_prompt(0), db_autoexpire_default(0), 864 861 db_auto_set_watched(false), db_end_of_rec_exit_prompt(false), 865 862 db_jump_prefer_osd(true), db_use_gui_size_for_tv(false), … … 867 864 db_run_jobs_on_remote(false), db_continue_embedded(false), 868 865 db_use_fixed_size(true), db_browse_always(false), 869 866 db_browse_all_tuners(false), 867 db_use_channel_groups(false), db_remember_last_channel_group(false), 870 868 871 869 arrowAccel(false), 872 870 tryUnflaggedSkip(false), … … 902 900 // Channel changing state variables 903 901 queuedChanNum(""), 904 902 lockTimerOn(false), 905 // channel browsing state variables 906 browsemode(false), 907 browsechannum(""), browsechanid(0), browsestarttime(""), 903 // channel browsing 904 browsehelper(NULL), 908 905 // Program Info for currently playing video 909 906 lastProgram(NULL), 910 907 inPlaylist(false), underNetworkControl(false), … … 992 989 kv["FFRewReposTime"] = "100"; 993 990 kv["FFRewReverse"] = "1"; 994 991 995 kv["ChannelGroupDefault"] = "-1";996 992 kv["BrowseChannelGroup"] = "0"; 993 kv["ChannelGroupDefault"] = "-1"; 994 kv["ChannelGroupRememberLast"] = "0"; 995 997 996 kv["VbiFormat"] = ""; 998 997 kv["DecodeVBIFormat"] = ""; 999 998 … … 1003 1002 1004 1003 MythDB::getMythDB()->GetSettings(kv); 1005 1004 1005 QString db_time_format; 1006 QString db_short_date_format; 1007 QString db_channel_ordering; 1008 uint db_browse_max_forward; 1009 1006 1010 // convert from minutes to ms. 1007 1011 db_idle_timeout = kv["LiveTVIdleTimeout"].toInt() * 60 * 1000; 1008 1012 db_udpnotify_port = kv["UDPNotifyPort"].toInt(); … … 1020 1024 db_use_fixed_size = kv["UseFixedWindowSize"].toInt(); 1021 1025 db_browse_always = kv["PersistentBrowseMode"].toInt(); 1022 1026 db_browse_all_tuners = kv["BrowseAllTuners"].toInt(); 1023 QString channelOrdering= kv["ChannelOrdering"];1027 db_channel_ordering = kv["ChannelOrdering"]; 1024 1028 baseFilters += kv["CustomFilters"]; 1025 1029 db_channel_format = kv["ChannelFormat"]; 1026 1030 db_time_format = kv["TimeFormat"]; 1027 1031 db_short_date_format = kv["ShortDateFormat"]; 1028 1032 arrowAccel = kv["UseArrowAccels"].toInt(); 1029 1033 tryUnflaggedSkip = kv["TryUnflaggedSkip"].toInt(); 1030 channel_group_id = kv["ChannelGroupDefault"].toInt();1031 browse_changrp = kv["BrowseChannelGroup"].toInt();1032 1034 smartForward = kv["SmartForward"].toInt(); 1033 1035 ff_rew_repos = kv["FFRewReposTime"].toFloat() * 0.01f; 1034 1036 ff_rew_reverse = kv["FFRewReverse"].toInt(); 1035 channel_group_id = kv["ChannelGroupDefault"].toInt(); 1036 browse_changrp = kv["BrowseChannelGroup"].toInt(); 1037 1038 db_use_channel_groups = kv["BrowseChannelGroup"].toInt(); 1039 db_remember_last_channel_group = kv["ChannelGroupRememberLast"].toInt(); 1040 channelGroupId = kv["ChannelGroupDefault"].toInt(); 1041 1037 1042 QString beVBI = kv["VbiFormat"]; 1038 1043 QString feVBI = kv["DecodeVBIFormat"]; 1039 1044 1045 if (db_use_channel_groups) 1046 { 1047 db_channel_groups = ChannelGroup::GetChannelGroups(); 1048 if (channelGroupId > -1) 1049 { 1050 channelGroupChannelList = ChannelUtil::GetChannels( 1051 0, true, "channum, callsign", channelGroupId); 1052 ChannelUtil::SortChannels( 1053 channelGroupChannelList, "channum", true); 1054 } 1055 } 1056 1040 1057 for (uint i = 0; i < sizeof(ff_rew_def)/sizeof(ff_rew_def[0]); i++) 1041 1058 ff_rew_speeds.push_back(kv[QString("FFRewSpeed%1").arg(i)].toInt()); 1042 1059 1043 1060 // process it.. 1061 browsehelper = new TVBrowseHelper( 1062 this, 1063 db_time_format, db_short_date_format, 1064 db_browse_max_forward, db_browse_all_tuners, 1065 db_use_channel_groups, db_channel_ordering); 1044 1066 1045 if (db_browse_all_tuners)1046 {1047 QMutexLocker locker(&browseLock);1048 db_browse_all_channels = ChannelUtil::GetChannels(1049 0, true, "channum, callsign");1050 ChannelUtil::SortChannels(1051 db_browse_all_channels, channelOrdering, true);1052 }1053 1054 1067 vbimode = VBIMode::Parse(!feVBI.isEmpty() ? feVBI : beVBI); 1055 1068 1056 if (browse_changrp && (channel_group_id > -1))1057 {1058 m_channellist = ChannelUtil::GetChannels(1059 0, true, "channum, callsign", channel_group_id);1060 ChannelUtil::SortChannels(m_channellist, "channum", true);1061 }1062 1063 m_changrplist = ChannelGroup::GetChannelGroups();1064 1065 1069 gCoreContext->addListener(this); 1066 1070 1067 1071 QMutexLocker lock(&initFromDBLock); … … 1189 1193 { 1190 1194 VERBOSE(VB_PLAYBACK, "TV::~TV() -- begin"); 1191 1195 1196 if (browsehelper) 1197 browsehelper->Stop(); 1198 1192 1199 if (udpnotify) 1193 1200 { 1194 1201 udpnotify->deleteLater(); … … 1243 1250 } 1244 1251 } 1245 1252 1253 if (browsehelper) 1254 { 1255 delete browsehelper; 1256 browsehelper = NULL; 1257 } 1258 1246 1259 PlayerContext *mctx = GetPlayerWriteLock(0, __FILE__, __LINE__); 1247 1260 while (!player.empty()) 1248 1261 { … … 1257 1270 } 1258 1271 1259 1272 /** 1260 * \brief save channel group setting to database1261 */1262 void TV::SaveChannelGroup(void)1263 {1264 int remember_last_changrp = gCoreContext->GetNumSetting("ChannelGroupRememberLast", 0);1265 1266 if (remember_last_changrp)1267 gCoreContext->SaveSetting("ChannelGroupDefault", channel_group_id);1268 }1269 1270 /**1271 1273 * \brief update the channel list with channels from the selected channel group 1272 1274 */ 1273 1275 void TV::UpdateChannelList(int groupID) 1274 1276 { 1275 if ( groupID == channel_group_id)1277 if (!db_use_channel_groups) 1276 1278 return; 1277 1279 1278 channel_group_id = groupID; 1280 QMutexLocker locker(&channelGroupLock); 1281 if (groupID == channelGroupId) 1282 return; 1279 1283 1280 if (browse_changrp) 1284 DBChanList list; 1285 if (groupID != -1) 1281 1286 { 1282 m_channellist = ChannelUtil::GetChannels(0, true, "channum, callsign", channel_group_id); 1283 ChannelUtil::SortChannels(m_channellist, "channum", true); 1287 list = ChannelUtil::GetChannels( 1288 0, true, "channum, callsign", groupID); 1289 ChannelUtil::SortChannels(list, "channum", true); 1284 1290 } 1291 1292 channelGroupId = groupID; 1293 channelGroupChannelList = list; 1294 1295 if (db_remember_last_channel_group) 1296 gCoreContext->SaveSetting("ChannelGroupDefault", channelGroupId); 1285 1297 } 1286 1298 1287 1299 /** … … 1595 1607 OSD *osd = GetOSDLock(ctx); 1596 1608 if (osd) 1597 1609 { 1598 BrowseEnd(ctx, false);1610 browsehelper->BrowseEnd(ctx, false); 1599 1611 timeuntil = QDateTime::currentDateTime().secsTo((*it).expiry) * 1000; 1600 1612 osd->DialogShow(OSD_DLG_ASKALLOW, message, timeuntil); 1601 1613 osd->DialogAddButton(record_watch, "DIALOG_ASKALLOW_WATCH_0", … … 1671 1683 OSD *osd = GetOSDLock(ctx); 1672 1684 if (osd && conflict_count > 1) 1673 1685 { 1674 BrowseEnd(ctx, false);1686 browsehelper->BrowseEnd(ctx, false); 1675 1687 osd->DialogShow(OSD_DLG_ASKALLOW, message, timeuntil); 1676 1688 osd->DialogAddButton(let_recordm, "DIALOG_ASKALLOW_EXIT_0", 1677 1689 false, true); … … 1680 1692 } 1681 1693 else if (osd) 1682 1694 { 1683 BrowseEnd(ctx, false);1695 browsehelper->BrowseEnd(ctx, false); 1684 1696 osd->DialogShow(OSD_DLG_ASKALLOW, message, timeuntil); 1685 1697 osd->DialogAddButton(let_record1, "DIALOG_ASKALLOW_EXIT_0", 1686 1698 false, !has_rec); … … 2857 2869 if (timer_id == browseTimerId) 2858 2870 { 2859 2871 PlayerContext *actx = GetPlayerReadLock(-1, __FILE__, __LINE__); 2860 BrowseEnd(actx, false);2872 browsehelper->BrowseEnd(actx, false); 2861 2873 ReturnPlayerLock(actx); 2862 2874 handled = true; 2863 2875 } … … 3333 3345 ReturnPlayerLock(actx); 3334 3346 } 3335 3347 3348 /// This selectively blocks KeyPress and Resize events 3336 3349 bool TV::eventFilter(QObject *o, QEvent *e) 3337 3350 { 3338 const MythMainWindow *mainWindow = GetMythMainWindow(); 3339 if (mainWindow == o) 3351 // We want to intercept all resize events sent to the main window 3352 if ((e->type() == QEvent::Resize)) 3353 return (GetMythMainWindow()!=o)?false:event(e); 3354 3355 // We want to intercept all KeyPress events unless ignoreKeyPresses is set 3356 if (QEvent::KeyPress == e->type()) 3357 return ignoreKeyPresses?false:event(e); 3358 3359 return QThread::eventFilter(o,e); 3360 } 3361 3362 /// This handles all standard events 3363 bool TV::event(QEvent *e) 3364 { 3365 if (QEvent::Resize == e->type()) 3340 3366 { 3341 if (e->type() == QEvent::Resize) 3342 { 3343 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 3344 mctx->LockDeletePlayer(__FILE__, __LINE__); 3345 if (mctx->player) 3346 mctx->player->WindowResized(((const QResizeEvent*) e)->size()); 3347 mctx->UnlockDeletePlayer(__FILE__, __LINE__); 3348 ReturnPlayerLock(mctx); 3349 } 3367 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 3368 mctx->LockDeletePlayer(__FILE__, __LINE__); 3369 if (mctx->player) 3370 mctx->player->WindowResized(((const QResizeEvent*) e)->size()); 3371 mctx->UnlockDeletePlayer(__FILE__, __LINE__); 3372 ReturnPlayerLock(mctx); 3373 return true; 3350 3374 } 3351 3375 3352 if ( e->type() == MythEvent::MythEventMessage)3376 if (QEvent::KeyPress == e->type()) 3353 3377 { 3354 customEvent(e); 3378 QKeyEvent *k = new QKeyEvent(*(QKeyEvent *)e); 3379 QMutexLocker locker(&timerIdLock); 3380 keyList.enqueue(k); 3381 if (!keyListTimerId) 3382 keyListTimerId = StartTimer(1, __LINE__); 3355 3383 return true; 3356 3384 } 3357 3385 3358 3386 switch (e->type()) 3359 3387 { 3360 case QEvent::KeyPress:3361 {3362 // we ignore keypresses if the epg is running for example3363 if (!ignoreKeyPresses)3364 {3365 QKeyEvent *k = new QKeyEvent(*(QKeyEvent *)e);3366 QMutexLocker locker(&timerIdLock);3367 keyList.enqueue(k);3368 if (!keyListTimerId)3369 keyListTimerId = StartTimer(1, __LINE__);3370 3371 return true;3372 }3373 else3374 {3375 return false;3376 }3377 }3378 3379 3388 case QEvent::Paint: 3380 3389 case QEvent::UpdateRequest: 3381 3390 case QEvent::Enter: 3382 {3383 3391 DrawUnusedRects(); 3384 return false; 3385 } 3386 3392 return true; 3387 3393 default: 3388 return false;3394 break; 3389 3395 } 3396 3397 return QThread::event(e); 3390 3398 } 3391 3399 3392 3400 bool TV::HandleTrackAction(PlayerContext *ctx, const QString &action) … … 3405 3413 handled = true; 3406 3414 ctx->player->ToggleCaptions(kTrackTypeTextSubtitle); 3407 3415 } 3408 else if (action == "TOGGLECC" && !browse mode)3416 else if (action == "TOGGLECC" && !browsehelper->IsBrowsing()) 3409 3417 { 3410 3418 handled = true; 3411 3419 if (ccInputMode) … … 3534 3542 bool pause = has_action("PAUSE", actions); 3535 3543 bool play = has_action("PLAY", actions); 3536 3544 3537 if ((!esc || browse mode) && !pause && !play)3545 if ((!esc || browsehelper->IsBrowsing()) && !pause && !play) 3538 3546 return; 3539 3547 } 3540 3548 … … 3694 3702 3695 3703 bool TV::BrowseHandleAction(PlayerContext *ctx, const QStringList &actions) 3696 3704 { 3697 if (!browse mode)3705 if (!browsehelper->IsBrowsing()) 3698 3706 return false; 3699 3707 3700 3708 bool handled = true; 3701 3709 3702 3710 if (has_action("UP", actions) || has_action("CHANNELUP", actions)) 3703 BrowseDispInfo(ctx, BROWSE_UP);3711 browsehelper->BrowseDispInfo(ctx, BROWSE_UP); 3704 3712 else if (has_action("DOWN", actions) || has_action("CHANNELDOWN", actions)) 3705 BrowseDispInfo(ctx, BROWSE_DOWN);3713 browsehelper->BrowseDispInfo(ctx, BROWSE_DOWN); 3706 3714 else if (has_action("LEFT", actions)) 3707 BrowseDispInfo(ctx, BROWSE_LEFT);3715 browsehelper->BrowseDispInfo(ctx, BROWSE_LEFT); 3708 3716 else if (has_action("RIGHT", actions)) 3709 BrowseDispInfo(ctx, BROWSE_RIGHT);3717 browsehelper->BrowseDispInfo(ctx, BROWSE_RIGHT); 3710 3718 else if (has_action("NEXTFAV", actions)) 3711 BrowseDispInfo(ctx, BROWSE_FAVORITE);3719 browsehelper->BrowseDispInfo(ctx, BROWSE_FAVORITE); 3712 3720 else if (has_action("SELECT", actions)) 3713 3721 { 3714 BrowseEnd(ctx, true);3722 browsehelper->BrowseEnd(ctx, true); 3715 3723 } 3716 3724 else if (has_action("CLEAROSD", actions) || 3717 3725 has_action("ESCAPE", actions) || 3718 3726 has_action("BACK", actions) || 3719 3727 has_action("TOGGLEBROWSE", actions)) 3720 3728 { 3721 BrowseEnd(ctx, false);3729 browsehelper->BrowseEnd(ctx, false); 3722 3730 } 3723 3731 else if (has_action("TOGGLERECORD", actions)) 3724 3732 ToggleRecord(ctx); … … 4309 4317 else if (has_action("TOGGLEBROWSE", actions)) 4310 4318 { 4311 4319 if (islivetv) 4312 BrowseStart(ctx);4320 browsehelper->BrowseStart(ctx); 4313 4321 else if (!isDVD) 4314 4322 ShowOSDMenu(ctx); 4315 4323 else … … 4408 4416 if (islivetv) 4409 4417 { 4410 4418 if (db_browse_always) 4411 BrowseDispInfo(ctx, BROWSE_UP);4419 browsehelper->BrowseDispInfo(ctx, BROWSE_UP); 4412 4420 else 4413 4421 ChangeChannel(ctx, CHANNEL_DIRECTION_UP); 4414 4422 } … … 4424 4432 if (islivetv) 4425 4433 { 4426 4434 if (db_browse_always) 4427 BrowseDispInfo(ctx, BROWSE_DOWN);4435 browsehelper->BrowseDispInfo(ctx, BROWSE_DOWN); 4428 4436 else 4429 4437 ChangeChannel(ctx, CHANNEL_DIRECTION_DOWN); 4430 4438 } … … 4701 4709 vol = ctx->player->AdjustVolume(vol); 4702 4710 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 4703 4711 4704 if (!browse mode&& !editmode)4712 if (!browsehelper->IsBrowsing() && !editmode) 4705 4713 { 4706 4714 UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"), 4707 4715 QString::number(vol), … … 6600 6608 // in browse mode because in browse mode space/enter exit browse 6601 6609 // mode and change to the currently browsed channel. 6602 6610 if (StateIsLiveTV(GetState(ctx)) && !ccInputMode && !asInputMode && 6603 browse mode)6611 browsehelper->IsBrowsing()) 6604 6612 { 6605 6613 commitSmart = ProcessSmartChannel(ctx, inputStr); 6606 6614 } … … 6726 6734 { 6727 6735 QString channum = GetQueuedChanNum(); 6728 6736 QString chaninput = GetQueuedInput(); 6729 if (browse mode)6737 if (browsehelper->IsBrowsing()) 6730 6738 { 6731 6739 commited = true; 6732 6740 if (channum.isEmpty()) 6741 channum = browsehelper->GetBrowsedInfo().m_channum; 6742 6743 if ((ctx->recorder && ctx->recorder->CheckChannel(channum)) || 6744 (db_browse_all_tuners && 6745 browsehelper->BrowseAllGetChanId(channum))) 6733 6746 { 6734 channum = browsechannum; 6735 channum.detach(); 6747 browsehelper->BrowseChannel(ctx, channum); 6736 6748 } 6737 BrowseChannel(ctx, channum);6738 6749 HideOSDWindow(ctx, "osd_input"); 6739 6750 } 6740 6751 else if (GetQueuedChanID() || !channum.isEmpty()) … … 6750 6761 6751 6762 void TV::ChangeChannel(PlayerContext *ctx, int direction) 6752 6763 { 6753 if ((browse_changrp || (direction == CHANNEL_DIRECTION_FAVORITE)) && 6754 (channel_group_id > -1)) 6764 if (db_use_channel_groups || (direction == CHANNEL_DIRECTION_FAVORITE)) 6755 6765 { 6756 uint chanid; 6766 QMutexLocker locker(&channelGroupLock); 6767 if (channelGroupId > -1) 6768 { 6769 locker.unlock(); 6770 ctx->LockPlayingInfo(__FILE__, __LINE__); 6771 if (!ctx->playingInfo) 6772 { 6773 VERBOSE(VB_IMPORTANT, 6774 LOC_ERR + "ChangeChannel(): " 6775 "no active ctx playingInfo."); 6776 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 6777 ReturnPlayerLock(ctx); 6778 return; 6779 } 6780 // Collect channel info 6781 const ProgramInfo pginfo(*ctx->playingInfo); 6782 uint old_chanid = pginfo.GetChanID(); 6783 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 6757 6784 6758 ctx->LockPlayingInfo(__FILE__, __LINE__); 6759 if (!ctx->playingInfo) 6760 { 6761 VERBOSE(VB_IMPORTANT, 6762 LOC_ERR + "ChangeChannel(): no active ctx playingInfo."); 6763 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 6764 ReturnPlayerLock(ctx); 6765 return; 6766 } 6767 6768 // Collect channel info 6769 const ProgramInfo pginfo(*ctx->playingInfo); 6770 uint old_chanid = pginfo.GetChanID(); 6771 ctx->UnlockPlayingInfo(__FILE__, __LINE__); 6772 6773 chanid = ChannelUtil::GetNextChannel(m_channellist, old_chanid, 0, direction); 6774 6775 ChangeChannel(ctx, chanid, ""); 6776 return; 6785 locker.relock(); 6786 if (channelGroupId > -1) 6787 { 6788 uint chanid = ChannelUtil::GetNextChannel( 6789 channelGroupChannelList, old_chanid, 0, direction); 6790 if (chanid) 6791 ChangeChannel(ctx, chanid, ""); 6792 return; 6793 } 6794 } 6777 6795 } 6778 else if (direction == CHANNEL_DIRECTION_FAVORITE) 6796 6797 if (direction == CHANNEL_DIRECTION_FAVORITE) 6779 6798 direction = CHANNEL_DIRECTION_UP; 6780 6799 6781 6800 QString oldinputname = ctx->recorder->GetInput(); … … 7013 7032 } 7014 7033 ReturnOSDLock(ctx, osd); 7015 7034 7016 if (browsemode) 7017 { 7018 QMutexLocker locker(&timerIdLock); 7019 if (browseTimerId) 7020 { 7021 KillTimer(browseTimerId); 7022 browseTimerId = 0; 7023 } 7024 browsemode = false; 7025 } 7035 if (browsehelper->IsBrowsing()) 7036 browsehelper->BrowseEnd(NULL, false); 7026 7037 7027 7038 return res; 7028 7039 } … … 7189 7200 void TV::UpdateOSDSignal(const PlayerContext *ctx, const QStringList &strlist) 7190 7201 { 7191 7202 OSD *osd = GetOSDLock(ctx); 7192 if (!osd || browse mode|| !queuedChanNum.isEmpty())7203 if (!osd || browsehelper->IsBrowsing() || !queuedChanNum.isEmpty()) 7193 7204 { 7194 7205 if (&ctx->lastSignalMsg != &strlist) 7195 7206 { … … 7493 7504 } 7494 7505 7495 7506 7496 /**7497 * \brief Fetches information on the desired program from the backend.7498 * \param enc RemoteEncoder to query, if null query the actx->recorder.7499 * \param direction BrowseDirection to get information on.7500 * \param infoMap InfoMap to fill in with returned data7501 */7502 void TV::GetNextProgram(RemoteEncoder *enc, BrowseDirection direction,7503 InfoMap &infoMap) const7504 {7505 QString title, subtitle, desc, category, endtime, callsign, iconpath;7506 QDateTime begts, endts;7507 7508 QString starttime = infoMap["dbstarttime"];7509 QString chanid = infoMap["chanid"];7510 QString channum = infoMap["channum"];7511 QString seriesid = infoMap["seriesid"];7512 QString programid = infoMap["programid"];7513 7514 const PlayerContext *actx = NULL;7515 if (!enc)7516 {7517 actx = GetPlayerReadLock(-1, __FILE__, __LINE__);7518 enc = actx->recorder;7519 }7520 7521 enc->GetNextProgram(direction,7522 title, subtitle, desc, category,7523 starttime, endtime, callsign, iconpath,7524 channum, chanid, seriesid, programid);7525 7526 if (actx)7527 {7528 enc = NULL; // once we've returned the lock, using enc is unsafe7529 ReturnPlayerLock(actx);7530 }7531 7532 if (!starttime.isEmpty())7533 begts = QDateTime::fromString(starttime, Qt::ISODate);7534 else7535 begts = QDateTime::fromString(infoMap["dbstarttime"], Qt::ISODate);7536 7537 infoMap["starttime"] = begts.toString(db_time_format);7538 infoMap["startdate"] = begts.toString(db_short_date_format);7539 7540 infoMap["endtime"] = infoMap["enddate"] = "";7541 if (!endtime.isEmpty())7542 {7543 endts = QDateTime::fromString(endtime, Qt::ISODate);7544 infoMap["endtime"] = endts.toString(db_time_format);7545 infoMap["enddate"] = endts.toString(db_short_date_format);7546 }7547 7548 infoMap["lenmins"] = tr("%n minute(s)", "", 0);7549 infoMap["lentime"] = "0:00";7550 if (begts.isValid() && endts.isValid())7551 {7552 QString lenM, lenHM;7553 format_time(begts.secsTo(endts), lenM, lenHM);7554 infoMap["lenmins"] = lenM;7555 infoMap["lentime"] = lenHM;7556 }7557 7558 infoMap["dbstarttime"] = starttime;7559 infoMap["dbendtime"] = endtime;7560 infoMap["title"] = title;7561 infoMap["subtitle"] = subtitle;7562 infoMap["description"] = desc;7563 infoMap["category"] = category;7564 infoMap["callsign"] = callsign;7565 infoMap["channum"] = channum;7566 infoMap["chanid"] = chanid;7567 infoMap["iconpath"] = iconpath;7568 infoMap["seriesid"] = seriesid;7569 infoMap["programid"] = programid;7570 }7571 7572 void TV::GetNextProgram(BrowseDirection direction, InfoMap &infoMap) const7573 {7574 uint chanid = infoMap["chanid"].toUInt();7575 if (!chanid)7576 chanid = BrowseAllGetChanId(infoMap["channum"]);7577 7578 int chandir = -1;7579 switch (direction)7580 {7581 case BROWSE_UP: chandir = CHANNEL_DIRECTION_UP; break;7582 case BROWSE_DOWN: chandir = CHANNEL_DIRECTION_DOWN; break;7583 case BROWSE_FAVORITE: chandir = CHANNEL_DIRECTION_FAVORITE; break;7584 }7585 if (direction != BROWSE_INVALID)7586 {7587 QMutexLocker locker(&browseLock);7588 chanid = ChannelUtil::GetNextChannel(7589 db_browse_all_channels, chanid, 0, chandir);7590 }7591 7592 infoMap["chanid"] = QString::number(chanid);7593 7594 {7595 QMutexLocker locker(&browseLock);7596 DBChanList::const_iterator it = db_browse_all_channels.begin();7597 for (; it != db_browse_all_channels.end(); ++it)7598 {7599 if ((*it).chanid == chanid)7600 {7601 QString tmp = (*it).channum;7602 tmp.detach();7603 infoMap["channum"] = tmp;7604 break;7605 }7606 }7607 }7608 7609 QDateTime nowtime = QDateTime::currentDateTime();7610 QDateTime latesttime = nowtime.addSecs(6*60*60);7611 QDateTime browsetime = QDateTime::fromString(7612 infoMap["dbstarttime"], Qt::ISODate);7613 7614 MSqlBindings bindings;7615 bindings[":CHANID"] = chanid;7616 bindings[":NOWTS"] = nowtime.toString("yyyy-MM-ddThh:mm:ss");7617 bindings[":LATESTTS"] = latesttime.toString("yyyy-MM-ddThh:mm:ss");7618 bindings[":BROWSETS"] = browsetime.toString("yyyy-MM-ddThh:mm:ss");7619 bindings[":BROWSETS2"] = browsetime.toString("yyyy-MM-ddThh:mm:ss");7620 7621 QString querystr = " WHERE program.chanid = :CHANID ";7622 switch (direction)7623 {7624 case BROWSE_LEFT:7625 querystr += " AND program.endtime <= :BROWSETS "7626 " AND program.endtime > :NOWTS ";7627 break;7628 7629 case BROWSE_RIGHT:7630 querystr += " AND program.starttime > :BROWSETS "7631 " AND program.starttime < :LATESTTS ";7632 break;7633 7634 default:7635 querystr += " AND program.starttime <= :BROWSETS "7636 " AND program.endtime > :BROWSETS2 ";7637 };7638 7639 ProgramList progList;7640 ProgramList dummySched;7641 LoadFromProgram(progList, querystr, bindings, dummySched, false);7642 7643 if (progList.empty())7644 {7645 infoMap["dbstarttime"] = "";7646 return;7647 }7648 7649 const ProgramInfo *prog = (direction == BROWSE_LEFT) ?7650 progList[progList.size() - 1] : progList[0];7651 7652 infoMap["dbstarttime"] = prog->GetScheduledStartTime(ISODate);7653 }7654 7655 7507 bool TV::IsTunable(const PlayerContext *ctx, uint chanid, bool use_cache) 7656 7508 { 7657 7509 VERBOSE(VB_PLAYBACK, QString("IsTunable(%1)").arg(chanid)); … … 7871 7723 const ProgramInfo pginfo(*actx->playingInfo); 7872 7724 uint chanid = pginfo.GetChanID(); 7873 7725 QString channum = pginfo.GetChanNum(); 7874 int changrpid = channel_group_id;7875 7726 actx->UnlockPlayingInfo(__FILE__, __LINE__); 7876 7727 7877 7728 ClearOSD(actx); … … 7928 7779 { 7929 7780 case kScheduleProgramGuide: 7930 7781 { 7782 channelGroupLock.lock(); 7783 int changrpid = channelGroupId; 7784 channelGroupLock.unlock(); 7785 7931 7786 isEmbedded = (isLiveTV && !pause_active && allowEmbedding); 7932 RunProgramGuidePtr(chanid, channum, this, isEmbedded, true, changrpid); 7787 RunProgramGuidePtr(chanid, channum, this, 7788 isEmbedded, true, changrpid); 7933 7789 ignoreKeyPresses = true; 7934 7790 break; 7935 7791 } … … 7992 7848 uint curvol = ctx->player->AdjustVolume((up) ? +2 : -2); 7993 7849 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 7994 7850 7995 if (!browse mode)7851 if (!browsehelper->IsBrowsing()) 7996 7852 { 7997 7853 UpdateOSDStatus(ctx, tr("Adjust Volume"), tr("Volume"), 7998 7854 QString::number(curvol), … … 8050 7906 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 8051 7907 } 8052 7908 8053 if (!browse mode)7909 if (!browsehelper->IsBrowsing()) 8054 7910 { 8055 7911 if (!allowEdit) 8056 7912 { … … 8080 7936 else 8081 7937 text = tr("Upmixer Off"); 8082 7938 8083 if (!browse mode)7939 if (!browsehelper->IsBrowsing()) 8084 7940 SetOSDMessage(ctx, text); 8085 7941 } 8086 7942 … … 8120 7976 } 8121 7977 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 8122 7978 8123 if (!browse mode)7979 if (!browsehelper->IsBrowsing()) 8124 7980 { 8125 7981 QString text; 8126 7982 int val = (int)newval; … … 8199 8055 8200 8056 text = tr("Sleep ") + " " + sleep_times[sleep_index].dispString; 8201 8057 8202 if (!browse mode)8058 if (!browsehelper->IsBrowsing()) 8203 8059 SetOSDMessage(ctx, text); 8204 8060 } 8205 8061 … … 8376 8232 ctx->UnlockDeletePlayer(__FILE__, __LINE__); 8377 8233 } 8378 8234 8235 /// This handles all custom events 8379 8236 void TV::customEvent(QEvent *e) 8380 8237 { 8238 if (e->type() == MythEvent::kUpdateBrowseInfoEventType) 8239 { 8240 UpdateBrowseInfoEvent *b = (UpdateBrowseInfoEvent*)e; 8241 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 8242 OSD *osd = GetOSDLock(mctx); 8243 if (osd) 8244 { 8245 osd->SetText("browse_info", b->im, kOSDTimeout_None); 8246 osd->SetExpiry("browse_info", kOSDTimeout_None); 8247 } 8248 ReturnOSDLock(mctx, osd); 8249 ReturnPlayerLock(mctx); 8250 return; 8251 } 8252 8381 8253 if (e->type() == DialogCompletionEvent::kEventType) 8382 8254 { 8383 8255 DialogCompletionEvent *dce = (DialogCompletionEvent *)e; … … 8772 8644 } 8773 8645 } 8774 8646 8775 /** \fn TV::BrowseStart(PlayerContext*)8776 * \brief Begins channel browsing.8777 */8778 void TV::BrowseStart(PlayerContext *ctx)8779 {8780 VERBOSE(VB_IMPORTANT, "BrowseStart()");8781 8782 if (ctx->paused)8783 return;8784 8785 OSD *osd = GetOSDLock(ctx);8786 if (osd && osd->IsWindowVisible("browse_info"))8787 {8788 ReturnOSDLock(ctx, osd);8789 return;8790 }8791 ReturnOSDLock(ctx, osd);8792 8793 ClearOSD(ctx);8794 8795 ctx->LockPlayingInfo(__FILE__, __LINE__);8796 if (ctx->playingInfo)8797 {8798 browsemode = true;8799 browsechannum = ctx->playingInfo->GetChanNum();8800 browsechannum.detach();8801 browsechanid = ctx->playingInfo->GetChanID();8802 browsestarttime = ctx->playingInfo->GetScheduledStartTime(ISODate);8803 ctx->UnlockPlayingInfo(__FILE__, __LINE__);8804 8805 BrowseDispInfo(ctx, BROWSE_SAME);8806 8807 QMutexLocker locker(&timerIdLock);8808 if (browseTimerId)8809 KillTimer(browseTimerId);8810 browseTimerId = StartTimer(kBrowseTimeout, __LINE__);8811 }8812 else8813 {8814 ctx->UnlockPlayingInfo(__FILE__, __LINE__);8815 }8816 }8817 8818 /** \fn TV::BrowseEnd(PlayerContext*, bool)8819 * \brief Ends channel browsing. Changing the channel if change is true.8820 * \param change_channel iff true we call ChangeChannel()8821 */8822 void TV::BrowseEnd(PlayerContext *ctx, bool change_channel)8823 {8824 VERBOSE(VB_IMPORTANT, "BrowseEnd()");8825 {8826 QMutexLocker locker(&timerIdLock);8827 if (browseTimerId)8828 {8829 KillTimer(browseTimerId);8830 browseTimerId = 0;8831 }8832 }8833 8834 if (!browsemode)8835 return;8836 8837 HideOSDWindow(ctx, "browse_info");8838 8839 if (change_channel)8840 ChangeChannel(ctx, 0, browsechannum);8841 8842 browsemode = false;8843 }8844 8845 /** \brief Fetches browse info from backend and sends it to the OSD.8846 * \param direction BrowseDirection to get information on.8847 */8848 void TV::BrowseDispInfo(PlayerContext *ctx, BrowseDirection direction)8849 {8850 VERBOSE(VB_IMPORTANT, "BrowseDispInfo()");8851 8852 if (!browsemode)8853 BrowseStart(ctx);8854 8855 // if browsing channel groups is enabled or direction if BROWSE_FAVORITES8856 // Then pick the next channel in the channel group list to browse8857 // If channel group is ALL CHANNELS (-1), then bypass picking from8858 // the channel group list8859 if ((browse_changrp || (direction == BROWSE_FAVORITE)) &&8860 (channel_group_id > -1) && (direction != BROWSE_SAME) &&8861 (direction != BROWSE_RIGHT) && (direction != BROWSE_LEFT))8862 {8863 uint chanid;8864 int dir;8865 8866 if ( (direction == BROWSE_UP) || (direction == BROWSE_FAVORITE) )8867 dir = CHANNEL_DIRECTION_UP;8868 else if (direction == BROWSE_DOWN)8869 dir = CHANNEL_DIRECTION_DOWN;8870 else // this should never happen, but just in case8871 dir = direction;8872 8873 chanid = ChannelUtil::GetNextChannel(8874 m_channellist, browsechanid, 0, dir);8875 VERBOSE(VB_IMPORTANT, QString("Get channel: %1").arg(chanid));8876 browsechanid = chanid;8877 browsechannum = QString::null;8878 direction = BROWSE_SAME;8879 }8880 else if ((channel_group_id == -1) && (direction == BROWSE_FAVORITE))8881 direction = BROWSE_UP;8882 8883 OSD *osd = GetOSDLock(ctx);8884 if (ctx->paused || !osd)8885 {8886 ReturnOSDLock(ctx, osd);8887 return;8888 }8889 8890 {8891 QMutexLocker locker(&timerIdLock);8892 if (browseTimerId)8893 KillTimer(browseTimerId);8894 browseTimerId = StartTimer(kBrowseTimeout, __LINE__);8895 }8896 8897 QDateTime lasttime = QDateTime::fromString(browsestarttime, Qt::ISODate);8898 QDateTime curtime = QDateTime::currentDateTime();8899 if (lasttime < curtime)8900 browsestarttime = curtime.toString(Qt::ISODate);8901 8902 QDateTime maxtime = curtime.addSecs(db_browse_max_forward);8903 if ((lasttime > maxtime) && (direction == BROWSE_RIGHT))8904 {8905 ReturnOSDLock(ctx, osd);8906 return;8907 }8908 8909 InfoMap infoMap;8910 infoMap["dbstarttime"] = browsestarttime;8911 infoMap["channum"] = browsechannum;8912 infoMap["chanid"] = QString::number(browsechanid);8913 8914 if (ctx->recorder && !db_browse_all_tuners)8915 {8916 GetNextProgram(ctx->recorder, direction, infoMap);8917 }8918 else8919 {8920 GetNextProgram(direction, infoMap);8921 while (!IsTunable(ctx, infoMap["chanid"].toUInt()) &&8922 (infoMap["channum"] != browsechannum))8923 {8924 GetNextProgram(direction, infoMap);8925 }8926 }8927 8928 VERBOSE(VB_IMPORTANT, QString("browsechanid: %1 -> %2")8929 .arg(browsechanid).arg(infoMap["chanid"].toUInt()));8930 8931 browsechannum = infoMap["channum"];8932 browsechanid = infoMap["chanid"].toUInt();8933 8934 if (((direction == BROWSE_LEFT) || (direction == BROWSE_RIGHT)) &&8935 !infoMap["dbstarttime"].isEmpty())8936 {8937 browsestarttime = infoMap["dbstarttime"];8938 }8939 8940 // pull in additional data from the DB...8941 QDateTime startts = QDateTime::fromString(browsestarttime, Qt::ISODate);8942 RecordingInfo recinfo(browsechanid, startts, false);8943 recinfo.ToMap(infoMap);8944 infoMap["iconpath"] = ChannelUtil::GetIcon(recinfo.GetChanID());8945 8946 osd->SetText("browse_info", infoMap, kOSDTimeout_None);8947 osd->SetExpiry("browse_info", kOSDTimeout_None);8948 ReturnOSDLock(ctx, osd);8949 }8950 8951 uint TV::BrowseAllGetChanId(const QString &chan) const8952 {8953 QMutexLocker locker(&browseLock);8954 DBChanList::const_iterator it = db_browse_all_channels.begin();8955 for (; it != db_browse_all_channels.end(); ++it)8956 {8957 if ((*it).channum == chan)8958 return (*it).chanid;8959 }8960 return 0;8961 }8962 8963 8647 void TV::ToggleRecord(PlayerContext *ctx) 8964 8648 { 8965 if (browsemode) 8649 BrowseInfo bi = browsehelper->GetBrowsedInfo(); 8650 if (bi.m_chanid) 8966 8651 { 8967 8652 InfoMap infoMap; 8968 8653 QDateTime startts = QDateTime::fromString( 8969 b rowsestarttime, Qt::ISODate);8654 bi.m_starttime, Qt::ISODate); 8970 8655 8971 8656 RecordingInfo::LoadStatus status; 8972 RecordingInfo recinfo(b rowsechanid, startts, false, 0, &status);8657 RecordingInfo recinfo(bi.m_chanid, startts, false, 0, &status); 8973 8658 if (RecordingInfo::kFoundProgram == status) 8974 8659 recinfo.ToggleRecord(); 8975 8660 recinfo.ToMap(infoMap); … … 9040 8725 SetOSDMessage(ctx, msg); 9041 8726 } 9042 8727 9043 void TV::BrowseChannel(PlayerContext *ctx, const QString &chan)9044 {9045 if (!ctx->recorder || !ctx->recorder->CheckChannel(chan))9046 {9047 if (!db_browse_all_tuners || !BrowseAllGetChanId(chan))9048 return;9049 }9050 9051 browsechannum = chan;9052 browsechannum.detach();9053 browsechanid = 0;9054 BrowseDispInfo(ctx, BROWSE_SAME);9055 }9056 9057 8728 void TV::HandleOSDClosed(int osdType) 9058 8729 { 9059 8730 switch (osdType) … … 9988 9659 } 9989 9660 else if (action == "GUIDE") 9990 9661 EditSchedule(actx, kScheduleProgramGuide); 9991 else if (action.left(10) == "CHANGROUP_" )9662 else if (action.left(10) == "CHANGROUP_" && db_use_channel_groups) 9992 9663 { 9993 9664 if (action == "CHANGROUP_ALL_CHANNELS") 9994 channel_group_id = -1; 9665 { 9666 UpdateChannelList(-1); 9667 } 9995 9668 else 9996 9669 { 9997 9670 action.remove("CHANGROUP_"); 9998 9671 9999 channel_group_id = action.toInt();9672 UpdateChannelList(action.toInt()); 10000 9673 10001 if (browse_changrp) 9674 QMutexLocker locker(&channelGroupLock); 9675 const DBChanList &list = channelGroupChannelList; 9676 9677 // make sure the current channel is from the selected group 9678 // or tune to the first in the group 9679 if (actx->tvchain) 10002 9680 { 10003 m_channellist = ChannelUtil::GetChannels(0, true, "channum, callsign", channel_group_id);10004 ChannelUtil::SortChannels(m_channellist, "channum", true);9681 QString cur_channum = actx->tvchain->GetChannelName(-1); 9682 QString new_channum = cur_channum; 10005 9683 10006 // make sure the current channel is from the selected group 10007 // or tune to the first in the group 10008 if (actx->tvchain) 9684 DBChanList::const_iterator it = list.begin(); 9685 for (; it != list.end(); ++it) 10009 9686 { 10010 QString cur_channum = actx->tvchain->GetChannelName(-1); 10011 QString new_channum = cur_channum; 10012 10013 DBChanList::const_iterator it = m_channellist.begin(); 10014 for (; it != m_channellist.end(); ++it) 9687 if ((*it).channum == cur_channum) 10015 9688 { 10016 if ((*it).channum == cur_channum) 10017 { 10018 break; 10019 } 9689 break; 10020 9690 } 9691 } 10021 9692 10022 if (it == m_channellist.end())10023 10024 10025 10026 it = m_channellist.begin();10027 if (it != m_channellist.end())10028 10029 9693 if (it == list.end()) 9694 { 9695 // current channel not found so switch to the 9696 // first channel in the group 9697 it = list.begin(); 9698 if (it != list.end()) 9699 new_channum = (*it).channum; 9700 } 10030 9701 10031 VERBOSE(VB_IMPORTANT, LOC + QString("Channel Group: '%1'->'%2'") 10032 .arg(cur_channum).arg(new_channum)); 9702 VERBOSE(VB_IMPORTANT, LOC + 9703 QString("Channel Group: '%1'->'%2'") 9704 .arg(cur_channum).arg(new_channum)); 10033 9705 10034 // Only change channel if new channel != current channel 10035 if (cur_channum != new_channum && !new_channum.isEmpty()) 10036 { 10037 QMutexLocker locker(&timerIdLock); 10038 queuedInput = new_channum; queuedInput.detach(); 10039 queuedChanNum = new_channum; queuedChanNum.detach(); 10040 queuedChanID = 0; 10041 if (!queueInputTimerId) 10042 queueInputTimerId = StartTimer(10, __LINE__); 10043 } 10044 10045 // Turn off OSD Channel Num so the channel changes right away 10046 HideOSDWindow(actx, "osd_input"); 9706 // Only change channel if new channel != current channel 9707 if (cur_channum != new_channum && !new_channum.isEmpty()) 9708 { 9709 QMutexLocker locker(&timerIdLock); 9710 queuedInput = new_channum; queuedInput.detach(); 9711 queuedChanNum = new_channum; queuedChanNum.detach(); 9712 queuedChanID = 0; 9713 if (!queueInputTimerId) 9714 queueInputTimerId = StartTimer(10, __LINE__); 10047 9715 } 9716 9717 // Turn off OSD Channel Num so the channel 9718 // changes right away 9719 HideOSDWindow(actx, "osd_input"); 10048 9720 } 10049 9721 } 10050 9722 } … … 10066 9738 else if (StateIsLiveTV(GetState(actx))) 10067 9739 { 10068 9740 if (action == "TOGGLEBROWSE") 10069 BrowseStart(actx);9741 browsehelper->BrowseStart(actx); 10070 9742 else if (action == "PREVCHAN") 10071 9743 PopPreviousChannel(actx, true); 10072 9744 else if (action.left(14) == "SWITCHTOINPUT_") … … 10930 10602 osd->DialogAddButton(tr("Sleep"), 10931 10603 "DIALOG_MENU_SLEEP_0", true, 10932 10604 selected == "SLEEP"); 10933 if ( browse_changrp)10605 if (db_use_channel_groups) 10934 10606 { 10935 10607 osd->DialogAddButton(tr("Channel Groups"), 10936 10608 "DIALOG_MENU_CHANNELGROUP_0", … … 10972 10644 currenttext = tr("Channel Groups"); 10973 10645 osd->DialogAddButton(tr("All Channels"), "CHANGROUP_ALL_CHANNELS"); 10974 10646 ChannelGroupList::const_iterator it; 10975 for (it = m_changrplist.begin(); it != m_changrplist.end(); ++it) 10647 for (it = db_channel_groups.begin(); 10648 it != db_channel_groups.end(); ++it) 10649 { 10650 QMutexLocker locker(&channelGroupLock); 10976 10651 osd->DialogAddButton(it->name, 10977 10652 QString("CHANGROUP_%1").arg(it->grpid), 10978 false, (int)(it->grpid) == channel_group_id); 10653 false, (int)(it->grpid) == channelGroupId); 10654 } 10979 10655 } 10980 10656 else if (category == "PIP" && (allowPIP || allowPBP)) 10981 10657 { -
libs/libmyth/programinfo.cpp
3971 3971 QStringList ProgramInfo::LoadFromScheduler( 3972 3972 const QString &tmptable, int recordid) 3973 3973 { 3974 assert(!gCoreContext->IsUIThread()); 3975 3974 3976 QStringList slist; 3975 3977 if (gCoreContext->IsBackend()) 3976 3978 { -
libs/libmythdb/mythevent.h
1 1 #ifndef MYTHEVENT_H_ 2 2 #define MYTHEVENT_H_ 3 3 4 #include <QString>5 4 #include <QStringList> 6 5 #include <QEvent> 6 #include <QHash> 7 7 8 #include "mythexp.h" 8 9 9 10 /** \class MythEvent … … 58 59 static Type kPopDisableDrawingEventType; 59 60 static Type kLockInputDevicesEventType; 60 61 static Type kUnlockInputDevicesEventType; 62 static Type kUpdateBrowseInfoEventType; 61 63 62 64 private: 63 65 QString message; … … 78 80 int keycode; 79 81 }; 80 82 83 class MPUBLIC UpdateBrowseInfoEvent : public QEvent 84 { 85 public: 86 UpdateBrowseInfoEvent(const QHash<QString,QString> &infoMap) : 87 QEvent(MythEvent::kUpdateBrowseInfoEventType), im(infoMap) {} 88 QHash<QString,QString> im; 89 }; 90 81 91 #endif /* MYTHEVENT_H */ -
libs/libmythdb/mythevent.cpp
18 18 (QEvent::Type) QEvent::registerEventType(); 19 19 QEvent::Type MythEvent::kUnlockInputDevicesEventType = 20 20 (QEvent::Type) QEvent::registerEventType(); 21 QEvent::Type MythEvent::kUpdateBrowseInfoEventType = 22 (QEvent::Type) QEvent::registerEventType(); 21 23 QEvent::Type ExternalKeycodeEvent::kEventType = 22 24 (QEvent::Type) QEvent::registerEventType();