Skip to content
This repository
Browse code

Merge pull request #1994 from nemphys/pvr-epg-startup

[pvr] make all livetv views available to the user earlier (as soon as channels are fetched from the backend and before epg is loaded from the db) by changing the pvr/epg manager startup logic
  • Loading branch information...
commit b0f94c77f0af8480488c0f10b4395102e8b611d0 2 parents dcd897b + 75c8a08
Lars Op den Kamp authored September 07, 2013
70  xbmc/epg/EpgContainer.cpp
@@ -53,6 +53,7 @@ CEpgContainer::CEpgContainer(void) :
53 53
   m_iNextEpgId = 0;
54 54
   m_bPreventUpdates = false;
55 55
   m_updateEvent.Reset();
  56
+  m_bStarted = false;
56 57
   m_bLoaded = false;
57 58
   m_bHasPendingUpdates = false;
58 59
 }
@@ -74,6 +75,12 @@ void CEpgContainer::Unload(void)
74 75
   Clear(false);
75 76
 }
76 77
 
  78
+bool CEpgContainer::IsStarted(void) const
  79
+{
  80
+  CSingleLock lock(m_critSection);
  81
+  return m_bStarted;
  82
+}
  83
+
77 84
 unsigned int CEpgContainer::NextEpgId(void)
78 85
 {
79 86
   CSingleLock lock(m_critSection);
@@ -100,6 +107,7 @@ void CEpgContainer::Clear(bool bClearDb /* = false */)
100 107
     }
101 108
     m_epgs.clear();
102 109
     m_iNextEpgUpdate  = 0;
  110
+    m_bStarted = false;
103 111
     m_bIsInitialising = true;
104 112
     m_iNextEpgId = 0;
105 113
   }
@@ -125,24 +133,34 @@ void CEpgContainer::Start(void)
125 133
 {
126 134
   Stop();
127 135
 
128  
-  CSingleLock lock(m_critSection);
  136
+  {
  137
+    CSingleLock lock(m_critSection);
129 138
 
130  
-  if (!m_database.IsOpen())
131  
-    m_database.Open();
  139
+    if (!m_database.IsOpen())
  140
+      m_database.Open();
132 141
 
133  
-  m_bIsInitialising = true;
134  
-  m_bStop = false;
135  
-  LoadSettings();
  142
+    m_bIsInitialising = true;
  143
+    m_bStop = false;
  144
+    LoadSettings();
136 145
 
137  
-  m_iNextEpgUpdate  = 0;
138  
-  m_iNextEpgActiveTagCheck = 0;
  146
+    m_iNextEpgUpdate  = 0;
  147
+    m_iNextEpgActiveTagCheck = 0;
  148
+  }
139 149
 
140 150
   LoadFromDB();
141  
-  CheckPlayingEvents();
142 151
 
143  
-  Create();
144  
-  SetPriority(-1);
145  
-  CLog::Log(LOGNOTICE, "%s - EPG thread started", __FUNCTION__);
  152
+  CSingleLock lock(m_critSection);
  153
+  if (!m_bStop)
  154
+  {
  155
+    CheckPlayingEvents();
  156
+
  157
+    Create();
  158
+    SetPriority(-1);
  159
+
  160
+    m_bStarted = true;
  161
+
  162
+    CLog::Log(LOGNOTICE, "%s - EPG thread started", __FUNCTION__);
  163
+  }
146 164
 }
147 165
 
148 166
 bool CEpgContainer::Stop(void)
@@ -152,6 +170,9 @@ bool CEpgContainer::Stop(void)
152 170
   if (m_database.IsOpen())
153 171
     m_database.Close();
154 172
 
  173
+  CSingleLock lock(m_critSection);
  174
+  m_bStarted = false;
  175
+
155 176
   return true;
156 177
 }
157 178
 
@@ -174,6 +195,8 @@ void CEpgContainer::OnSettingChanged(const CSetting *setting)
174 195
 
175 196
 void CEpgContainer::LoadFromDB(void)
176 197
 {
  198
+  CSingleLock lock(m_critSection);
  199
+
177 200
   if (m_bLoaded || m_bIgnoreDbForClient)
178 201
     return;
179 202
 
@@ -193,14 +216,17 @@ void CEpgContainer::LoadFromDB(void)
193 216
 
194 217
     for (map<unsigned int, CEpg *>::iterator it = m_epgs.begin(); it != m_epgs.end(); it++)
195 218
     {
  219
+      if (m_bStop)
  220
+        break;
196 221
       UpdateProgressDialog(++iCounter, m_epgs.size(), it->second->Name());
  222
+      lock.Leave();
197 223
       it->second->Load();
  224
+      lock.Enter();
198 225
     }
199 226
 
200 227
     CloseProgressDialog();
201 228
   }
202 229
 
203  
-  CSingleLock lock(m_critSection);
204 230
   m_bLoaded = bLoaded;
205 231
 }
206 232
 
@@ -233,12 +259,6 @@ void CEpgContainer::Process(void)
233 259
   bool bUpdateEpg(true);
234 260
   bool bHasPendingUpdates(false);
235 261
 
236  
-  if (!CPVRManager::Get().WaitUntilInitialised())
237  
-  {
238  
-    CLog::Log(LOGDEBUG, "EPG - %s - pvr manager failed to load - exiting", __FUNCTION__);
239  
-    return;
240  
-  }
241  
-
242 262
   while (!m_bStop && !g_application.m_bStop)
243 263
   {
244 264
     CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(iNow);
@@ -248,7 +268,7 @@ void CEpgContainer::Process(void)
248 268
     }
249 269
 
250 270
     /* update the EPG */
251  
-    if (!InterruptUpdate() && bUpdateEpg && UpdateEPG())
  271
+    if (!InterruptUpdate() && bUpdateEpg && g_PVRManager.EpgsCreated() && UpdateEPG())
252 272
       m_bIsInitialising = false;
253 273
 
254 274
     /* clean up old entries */
@@ -334,7 +354,6 @@ CEpg *CEpgContainer::CreateChannelEpg(CPVRChannelPtr channel)
334 354
     return NULL;
335 355
 
336 356
   WaitForUpdateFinish(true);
337  
-  CSingleLock lock(m_critSection);
338 357
   LoadFromDB();
339 358
 
340 359
   CEpg *epg(NULL);
@@ -345,6 +364,8 @@ CEpg *CEpgContainer::CreateChannelEpg(CPVRChannelPtr channel)
345 364
   {
346 365
     channel->SetEpgID(NextEpgId());
347 366
     epg = new CEpg(channel, false);
  367
+
  368
+    CSingleLock lock(m_critSection);
348 369
     m_epgs.insert(make_pair((unsigned int)epg->EpgID(), epg));
349 370
     SetChanged();
350 371
     epg->RegisterObserver(this);
@@ -352,8 +373,11 @@ CEpg *CEpgContainer::CreateChannelEpg(CPVRChannelPtr channel)
352 373
 
353 374
   epg->SetChannel(channel);
354 375
 
355  
-  m_bPreventUpdates = false;
356  
-  CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(m_iNextEpgUpdate);
  376
+  {
  377
+    CSingleLock lock(m_critSection);
  378
+    m_bPreventUpdates = false;
  379
+    CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(m_iNextEpgUpdate);
  380
+  }
357 381
 
358 382
   NotifyObservers(ObservableMessageEpgContainer);
359 383
 
7  xbmc/epg/EpgContainer.h
@@ -95,6 +95,12 @@ namespace EPG
95 95
     virtual void Reset(void) { Clear(true); }
96 96
 
97 97
     /*!
  98
+     * @brief Check whether the EpgContainer has fully started.
  99
+     * @return True if started, false otherwise.
  100
+     */
  101
+    bool IsStarted(void) const;
  102
+
  103
+    /*!
98 104
      * @brief Delete an EPG table from this container.
99 105
      * @param epg The table to delete.
100 106
      * @param bDeleteFromDatabase Delete this table from the database too if true.
@@ -271,6 +277,7 @@ namespace EPG
271 277
     //@{
272 278
     bool         m_bIsUpdating;            /*!< true while an update is running */
273 279
     bool         m_bIsInitialising;        /*!< true while the epg manager hasn't loaded all tables */
  280
+    bool         m_bStarted;               /*!< true if EpgContainer has fully started */
274 281
     bool         m_bLoaded;                /*!< true after epg data is initially loaded from the database */
275 282
     bool         m_bPreventUpdates;        /*!< true to prevent EPG updates */
276 283
     bool         m_bHasPendingUpdates;     /*!< true if there are manual updates pending */
49  xbmc/pvr/PVRManager.cpp
@@ -74,6 +74,7 @@ CPVRManager::CPVRManager(void) :
74 74
     m_currentFile(NULL),
75 75
     m_database(NULL),
76 76
     m_bFirstStart(true),
  77
+    m_bEpgsCreated(false),
77 78
     m_progressHandle(NULL),
78 79
     m_managerState(ManagerStateStopped),
79 80
     m_bOpenPVRWindow(false)
@@ -261,12 +262,6 @@ bool CPVRManager::UpgradeOutdatedAddons(void)
261 262
   return false;
262 263
 }
263 264
 
264  
-bool CPVRManager::WaitUntilInitialised(void)
265  
-{
266  
-  return m_initialisedEvent.Wait() &&
267  
-      IsStarted();
268  
-}
269  
-
270 265
 void CPVRManager::Cleanup(void)
271 266
 {
272 267
   CSingleLock lock(m_critSection);
@@ -284,12 +279,12 @@ void CPVRManager::Cleanup(void)
284 279
   m_bIsSwitchingChannels  = false;
285 280
   m_outdatedAddons.clear();
286 281
   m_bOpenPVRWindow = false;
  282
+  m_bEpgsCreated = false;
287 283
 
288 284
   for (unsigned int iJobPtr = 0; iJobPtr < m_pendingUpdates.size(); iJobPtr++)
289 285
     delete m_pendingUpdates.at(iJobPtr);
290 286
   m_pendingUpdates.clear();
291 287
 
292  
-  m_initialisedEvent.Reset();
293 288
   SetState(ManagerStateStopped);
294 289
 }
295 290
 
@@ -352,8 +347,6 @@ void CPVRManager::Start(bool bAsync /* = false */, bool bOpenPVRWindow /* = fals
352 347
     m_database = new CPVRDatabase;
353 348
   m_database->Open();
354 349
 
355  
-  g_EpgContainer.Start();
356  
-
357 350
   /* create the supervisor thread to do all background activities */
358 351
   StartUpdateThreads();
359 352
 }
@@ -368,7 +361,6 @@ void CPVRManager::Stop(void)
368 361
   SetState(ManagerStateStopping);
369 362
 
370 363
   /* stop the EPG updater, since it might be using the pvr add-ons */
371  
-  m_initialisedEvent.Set();
372 364
   g_EpgContainer.Stop();
373 365
 
374 366
   CLog::Log(LOGNOTICE, "PVRManager - stopping");
@@ -408,6 +400,8 @@ void CPVRManager::SetState(ManagerState state)
408 400
 
409 401
 void CPVRManager::Process(void)
410 402
 {
  403
+  g_EpgContainer.Stop();
  404
+
411 405
   /* load the pvr data from the db and clients if it's not already loaded */
412 406
   while (!Load() && GetState() == ManagerStateStarting)
413 407
   {
@@ -425,7 +419,7 @@ void CPVRManager::Process(void)
425 419
 
426 420
   /* main loop */
427 421
   CLog::Log(LOGDEBUG, "PVRManager - %s - entering main loop", __FUNCTION__);
428  
-  m_initialisedEvent.Set();
  422
+  g_EpgContainer.Start();
429 423
 
430 424
   if (m_bOpenPVRWindow)
431 425
   {
@@ -914,6 +908,11 @@ CPVRChannelGroupPtr CPVRManager::GetPlayingGroup(bool bRadio /* = false */)
914 908
   return CPVRChannelGroupPtr();
915 909
 }
916 910
 
  911
+bool CPVREpgsCreateJob::DoWork(void)
  912
+{
  913
+  return g_PVRManager.CreateChannelEpgs();
  914
+}
  915
+
917 916
 bool CPVRRecordingsUpdateJob::DoWork(void)
918 917
 {
919 918
   g_PVRRecordings->Update();
@@ -1349,6 +1348,12 @@ bool CPVRManager::IsStarted(void) const
1349 1348
   return GetState() == ManagerStateStarted;
1350 1349
 }
1351 1350
 
  1351
+bool CPVRManager::EpgsCreated(void) const
  1352
+{
  1353
+  CSingleLock lock(m_critSection);
  1354
+  return m_bEpgsCreated;
  1355
+}
  1356
+
1352 1357
 bool CPVRManager::IsPlayingTV(void) const
1353 1358
 {
1354 1359
   return IsStarted() && m_addons && m_addons->IsPlayingTV();
@@ -1397,6 +1402,18 @@ bool CPVRManager::IsJobPending(const char *strJobName) const
1397 1402
   return bReturn;
1398 1403
 }
1399 1404
 
  1405
+void CPVRManager::TriggerEpgsCreate(void)
  1406
+{
  1407
+  CSingleLock lock(m_critSectionTriggers);
  1408
+  if (IsJobPending("pvr-create-epgs"))
  1409
+    return;
  1410
+
  1411
+  m_pendingUpdates.push_back(new CPVREpgsCreateJob());
  1412
+
  1413
+  lock.Leave();
  1414
+  m_triggerEvent.Set();
  1415
+}
  1416
+
1400 1417
 void CPVRManager::TriggerRecordingsUpdate(void)
1401 1418
 {
1402 1419
   CSingleLock lock(m_critSectionTriggers);
@@ -1540,3 +1557,13 @@ bool CPVRChannelSwitchJob::DoWork(void)
1540 1557
 
1541 1558
   return true;
1542 1559
 }
  1560
+
  1561
+bool CPVRManager::CreateChannelEpgs(void)
  1562
+{
  1563
+  if (EpgsCreated())
  1564
+    return true;
  1565
+
  1566
+  CSingleLock lock(m_critSection);
  1567
+  m_bEpgsCreated = m_channelGroups->CreateChannelEpgs();
  1568
+  return m_bEpgsCreated;
  1569
+}
29  xbmc/pvr/PVRManager.h
@@ -250,6 +250,12 @@ namespace PVR
250 250
     bool IsStarted(void) const;
251 251
 
252 252
     /*!
  253
+     * @brief Check whether EPG tags for channels have been created.
  254
+     * @return True if EPG tags have been created, false otherwise.
  255
+     */
  256
+    bool EpgsCreated(void) const;
  257
+
  258
+    /*!
253 259
      * @brief Reset the playing EPG tag.
254 260
      */
255 261
     void ResetPlayingTag(void);
@@ -333,6 +339,11 @@ namespace PVR
333 339
     CPVRChannelGroupPtr GetPlayingGroup(bool bRadio = false);
334 340
 
335 341
     /*!
  342
+     * @brief Let the background thread create epg tags for all channels.
  343
+     */
  344
+    void TriggerEpgsCreate(void);
  345
+
  346
+    /*!
336 347
      * @brief Let the background thread update the recordings list.
337 348
      */
338 349
     void TriggerRecordingsUpdate(void);
@@ -510,6 +521,12 @@ namespace PVR
510 521
 
511 522
     static void SettingOptionsPvrStartLastChannelFiller(const CSetting *setting, std::vector< std::pair<std::string, int> > &list, int &current);
512 523
 
  524
+    /*!
  525
+     * @brief Create EPG tags for all channels in internal channel groups
  526
+     * @return True if EPG tags where created successfully, false otherwise
  527
+     */
  528
+    bool CreateChannelEpgs(void);
  529
+
513 530
   protected:
514 531
     /*!
515 532
      * @brief PVR update and control thread.
@@ -611,6 +628,7 @@ namespace PVR
611 628
     CCriticalSection                m_critSection;                 /*!< critical section for all changes to this class, except for changes to triggers */
612 629
     bool                            m_bFirstStart;                 /*!< true when the PVR manager was started first, false otherwise */
613 630
     bool                            m_bIsSwitchingChannels;        /*!< true while switching channels */
  631
+    bool                            m_bEpgsCreated;                /*!< true if epg data for channels has been created */
614 632
     CGUIDialogProgressBarHandle *   m_progressHandle;              /*!< progress dialog that is displayed while the pvrmanager is loading */
615 633
 
616 634
     CCriticalSection                m_managerStateMutex;
@@ -618,7 +636,16 @@ namespace PVR
618 636
     CStopWatch                     *m_parentalTimer;
619 637
     bool                            m_bOpenPVRWindow;
620 638
     std::map<std::string, std::string> m_outdatedAddons;
621  
-    CEvent                             m_initialisedEvent;         /*!< triggered when the pvr manager initialised */
  639
+  };
  640
+
  641
+  class CPVREpgsCreateJob : public CJob
  642
+  {
  643
+  public:
  644
+    CPVREpgsCreateJob(void) {}
  645
+    virtual ~CPVREpgsCreateJob() {}
  646
+    virtual const char *GetType() const { return "pvr-create-epgs"; }
  647
+
  648
+    virtual bool DoWork();
622 649
   };
623 650
 
624 651
   class CPVRRecordingsUpdateJob : public CJob
6  xbmc/pvr/channels/PVRChannelGroup.cpp
@@ -1226,3 +1226,9 @@ bool CPVRChannelGroup::IsSelectedGroup(void) const
1226 1226
   CSingleLock lock(m_critSection);
1227 1227
   return m_bSelectedGroup;
1228 1228
 }
  1229
+
  1230
+bool CPVRChannelGroup::CreateChannelEpgs(bool bForce /* = false */)
  1231
+{
  1232
+  /* used only by internal channel groups */
  1233
+  return true;
  1234
+}
7  xbmc/pvr/channels/PVRChannelGroup.h
@@ -415,6 +415,13 @@ namespace PVR
415 415
     bool RemoveDeletedChannels(const CPVRChannelGroup &channels);
416 416
 
417 417
     /*!
  418
+     * @brief Create an EPG table for each channel.
  419
+     * @brief bForce Create the tables, even if they already have been created before.
  420
+     * @return True if all tables were created successfully, false otherwise.
  421
+     */
  422
+    virtual bool CreateChannelEpgs(bool bForce = false);
  423
+
  424
+    /*!
418 425
      * @brief Remove invalid channels from this container.
419 426
      */
420 427
     void RemoveInvalidChannels(void);
4  xbmc/pvr/channels/PVRChannelGroupInternal.cpp
@@ -60,7 +60,7 @@ bool CPVRChannelGroupInternal::Load(void)
60 60
   if (CPVRChannelGroup::Load())
61 61
   {
62 62
     UpdateChannelPaths();
63  
-    CreateChannelEpgs();
  63
+    g_PVRManager.TriggerEpgsCreate();
64 64
     return true;
65 65
   }
66 66
 
@@ -369,6 +369,8 @@ void CPVRChannelGroupInternal::CreateChannelEpg(CPVRChannelPtr channel, bool bFo
369 369
 
370 370
 bool CPVRChannelGroupInternal::CreateChannelEpgs(bool bForce /* = false */)
371 371
 {
  372
+  if (!g_EpgContainer.IsStarted())
  373
+    return false;
372 374
   {
373 375
     CSingleLock lock(m_critSection);
374 376
     for (unsigned int iChannelPtr = 0; iChannelPtr < m_members.size(); iChannelPtr++)
13  xbmc/pvr/channels/PVRChannelGroups.cpp
@@ -519,3 +519,16 @@ void CPVRChannelGroups::FillGroupsGUI(int iWindowId, int iControlId) const
519 519
   CGUIMessage msgSel(GUI_MSG_ITEM_SELECT, iWindowId, iControlId, iSelectedGroupPtr);
520 520
   g_windowManager.SendMessage(msgSel);
521 521
 }
  522
+
  523
+bool CPVRChannelGroups::CreateChannelEpgs(void)
  524
+{
  525
+  bool bReturn(false);
  526
+  CSingleLock lock(m_critSection);
  527
+  for (std::vector<CPVRChannelGroupPtr>::iterator it = m_groups.begin(); it != m_groups.end(); it++)
  528
+  {
  529
+    /* Only create EPGs for the internatl groups */
  530
+    if ((*it)->IsInternalGroup())
  531
+      bReturn = (*it)->CreateChannelEpgs();
  532
+  }
  533
+  return bReturn;
  534
+}
6  xbmc/pvr/channels/PVRChannelGroups.h
@@ -163,6 +163,12 @@ namespace PVR
163 163
     bool DeleteGroup(const CPVRChannelGroup &group);
164 164
 
165 165
     /*!
  166
+     * @brief Create EPG tags for all channels of the internal group.
  167
+     * @return True if EPG tags where created successfully, false if not.
  168
+     */
  169
+    bool CreateChannelEpgs(void);
  170
+
  171
+    /*!
166 172
      * @brief Remove a channel from all non-system groups.
167 173
      * @param channel The channel to remove.
168 174
      */
7  xbmc/pvr/channels/PVRChannelGroupsContainer.cpp
@@ -282,3 +282,10 @@ bool CPVRChannelGroupsContainer::CreateChannel(const CPVRChannel &channel)
282 282
 {
283 283
   return GetGroupAll(channel.IsRadio())->AddNewChannel(channel);
284 284
 }
  285
+
  286
+
  287
+bool CPVRChannelGroupsContainer::CreateChannelEpgs(void)
  288
+{
  289
+  return m_groupsRadio->CreateChannelEpgs() &&
  290
+         m_groupsTV->CreateChannelEpgs();
  291
+}
6  xbmc/pvr/channels/PVRChannelGroupsContainer.h
@@ -182,6 +182,12 @@ namespace PVR
182 182
 
183 183
     bool CreateChannel(const CPVRChannel &channel);
184 184
 
  185
+    /*!
  186
+     * @brief Create EPG tags for channels in all internal channel groups.
  187
+     * @return True if EPG tags were created succesfully.
  188
+     */
  189
+    bool CreateChannelEpgs(void);
  190
+
185 191
   protected:
186 192
     /*!
187 193
      * @brief Update the contents of all the groups in this container.

0 notes on commit b0f94c7

Please sign in to comment.
Something went wrong with that request. Please try again.