Skip to content
This repository
Browse code

Handle the possibility that a XBPython registration list is modified …

…in a callback.
  • Loading branch information...
commit 6f87d6b7a298f1cbd080c150b5904231e2b63b2c 1 parent be93a9d
authored February 08, 2013
66  xbmc/interfaces/python/XBPython.cpp
@@ -26,6 +26,8 @@
26 26
 // python.h should always be included first before any other includes
27 27
 #include <Python.h>
28 28
 
  29
+#include <algorithm>
  30
+
29 31
 #include "system.h"
30 32
 #include "cores/DllLoader/DllLoaderContainer.h"
31 33
 #include "GUIPassword.h"
@@ -82,9 +84,12 @@ XBPython::~XBPython()
82 84
 #define LOCK_AND_COPY(type, dest, src) \
83 85
   if (!m_bInitialized) return; \
84 86
   CSingleLock lock(src); \
  87
+  src.hadSomethingRemoved = false; \
85 88
   type dest; \
86 89
   dest = src
87 90
 
  91
+#define CHECK_FOR_ENTRY(l,v) \
  92
+  (l.hadSomethingRemoved ? (std::find(l.begin(),l.end(),v) != l.end()) : true)
88 93
 
89 94
 // message all registered callbacks that xbmc stopped playing
90 95
 void XBPython::OnPlayBackEnded()
@@ -92,8 +97,8 @@ void XBPython::OnPlayBackEnded()
92 97
   TRACE;
93 98
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
94 99
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
95  
-    ((IPlayerCallback*)(*it))->OnPlayBackEnded();
96  
-
  100
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  101
+      ((IPlayerCallback*)(*it))->OnPlayBackEnded();
97 102
 }
98 103
 
99 104
 void XBPython::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
@@ -127,7 +132,8 @@ void XBPython::OnPlayBackStarted()
127 132
   TRACE;
128 133
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
129 134
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
130  
-    ((IPlayerCallback*)(*it))->OnPlayBackStarted();
  135
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  136
+      ((IPlayerCallback*)(*it))->OnPlayBackStarted();
131 137
 }
132 138
 
133 139
 // message all registered callbacks that we paused playing
@@ -136,7 +142,8 @@ void XBPython::OnPlayBackPaused()
136 142
   TRACE;
137 143
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
138 144
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
139  
-    ((IPlayerCallback*)(*it))->OnPlayBackPaused();
  145
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  146
+      ((IPlayerCallback*)(*it))->OnPlayBackPaused();
140 147
 }
141 148
 
142 149
 // message all registered callbacks that we resumed playing
@@ -145,7 +152,8 @@ void XBPython::OnPlayBackResumed()
145 152
   TRACE;
146 153
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
147 154
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
148  
-    ((IPlayerCallback*)(*it))->OnPlayBackResumed();
  155
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  156
+      ((IPlayerCallback*)(*it))->OnPlayBackResumed();
149 157
 }
150 158
 
151 159
 // message all registered callbacks that user stopped playing
@@ -154,7 +162,8 @@ void XBPython::OnPlayBackStopped()
154 162
   TRACE;
155 163
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
156 164
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
157  
-    ((IPlayerCallback*)(*it))->OnPlayBackStopped();
  165
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  166
+      ((IPlayerCallback*)(*it))->OnPlayBackStopped();
158 167
 }
159 168
 
160 169
 // message all registered callbacks that playback speed changed (FF/RW)
@@ -163,7 +172,8 @@ void XBPython::OnPlayBackSpeedChanged(int iSpeed)
163 172
   TRACE;
164 173
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
165 174
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
166  
-    ((IPlayerCallback*)(*it))->OnPlayBackSpeedChanged(iSpeed);
  175
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  176
+      ((IPlayerCallback*)(*it))->OnPlayBackSpeedChanged(iSpeed);
167 177
 }
168 178
 
169 179
 // message all registered callbacks that player is seeking
@@ -172,7 +182,8 @@ void XBPython::OnPlayBackSeek(int iTime, int seekOffset)
172 182
   TRACE;
173 183
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
174 184
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
175  
-    ((IPlayerCallback*)(*it))->OnPlayBackSeek(iTime, seekOffset);
  185
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  186
+      ((IPlayerCallback*)(*it))->OnPlayBackSeek(iTime, seekOffset);
176 187
 }
177 188
 
178 189
 // message all registered callbacks that player chapter seeked
@@ -181,7 +192,8 @@ void XBPython::OnPlayBackSeekChapter(int iChapter)
181 192
   TRACE;
182 193
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
183 194
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
184  
-    ((IPlayerCallback*)(*it))->OnPlayBackSeekChapter(iChapter);
  195
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  196
+      ((IPlayerCallback*)(*it))->OnPlayBackSeekChapter(iChapter);
185 197
 }
186 198
 
187 199
 // message all registered callbacks that next item has been queued
@@ -190,7 +202,8 @@ void XBPython::OnQueueNextItem()
190 202
   TRACE;
191 203
   LOCK_AND_COPY(std::vector<PVOID>,tmp,m_vecPlayerCallbackList);
192 204
   for (PlayerCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
193  
-    ((IPlayerCallback*)(*it))->OnQueueNextItem();
  205
+    if (CHECK_FOR_ENTRY(m_vecPlayerCallbackList,(*it)))
  206
+      ((IPlayerCallback*)(*it))->OnQueueNextItem();
194 207
 }
195 208
 
196 209
 void XBPython::RegisterPythonPlayerCallBack(IPlayerCallback* pCallback)
@@ -208,7 +221,10 @@ void XBPython::UnregisterPythonPlayerCallBack(IPlayerCallback* pCallback)
208 221
   while (it != m_vecPlayerCallbackList.end())
209 222
   {
210 223
     if (*it == pCallback)
  224
+    {
211 225
       it = m_vecPlayerCallbackList.erase(it);
  226
+      m_vecPlayerCallbackList.hadSomethingRemoved = true;
  227
+    }
212 228
     else
213 229
       it++;
214 230
   }
@@ -229,7 +245,10 @@ void XBPython::UnregisterPythonMonitorCallBack(XBMCAddon::xbmc::Monitor* pCallba
229 245
   while (it != m_vecMonitorCallbackList.end())
230 246
   {
231 247
     if (*it == pCallback)
  248
+    {
232 249
       it = m_vecMonitorCallbackList.erase(it);
  250
+      m_vecMonitorCallbackList.hadSomethingRemoved = true;
  251
+    }
233 252
     else
234 253
       it++;
235 254
   }
@@ -240,7 +259,7 @@ void XBPython::OnSettingsChanged(const CStdString &ID)
240 259
   TRACE;
241 260
   LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList);
242 261
   for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
243  
-    if ((*it)->GetId() == ID)  
  262
+    if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it)) && ((*it)->GetId() == ID))
244 263
       (*it)->OnSettingsChanged();
245 264
 }  
246 265
 
@@ -249,7 +268,8 @@ void XBPython::OnScreensaverActivated()
249 268
   TRACE;
250 269
   LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList);
251 270
   for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
252  
-    (*it)->OnScreensaverActivated();
  271
+    if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it)))
  272
+      (*it)->OnScreensaverActivated();
253 273
 } 
254 274
 
255 275
 void XBPython::OnScreensaverDeactivated()
@@ -257,7 +277,8 @@ void XBPython::OnScreensaverDeactivated()
257 277
   TRACE;
258 278
   LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList);
259 279
   for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
260  
-    (*it)->OnScreensaverDeactivated();
  280
+    if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it)))
  281
+      (*it)->OnScreensaverDeactivated();
261 282
 } 
262 283
 
263 284
 void XBPython::OnDatabaseUpdated(const std::string &database)
@@ -265,7 +286,8 @@ void XBPython::OnDatabaseUpdated(const std::string &database)
265 286
   TRACE;
266 287
   LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList);
267 288
   for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
268  
-    (*it)->OnDatabaseUpdated(database);
  289
+    if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it)))
  290
+      (*it)->OnDatabaseUpdated(database);
269 291
 } 
270 292
 
271 293
 void XBPython::OnDatabaseScanStarted(const std::string &database)
@@ -273,7 +295,8 @@ void XBPython::OnDatabaseScanStarted(const std::string &database)
273 295
   TRACE;
274 296
   LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList);
275 297
   for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
276  
-    (*it)->OnDatabaseScanStarted(database);
  298
+    if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it)))
  299
+      (*it)->OnDatabaseScanStarted(database);
277 300
 }
278 301
 
279 302
 void XBPython::OnAbortRequested(const CStdString &ID)
@@ -282,10 +305,13 @@ void XBPython::OnAbortRequested(const CStdString &ID)
282 305
   LOCK_AND_COPY(std::vector<XBMCAddon::xbmc::Monitor*>,tmp,m_vecMonitorCallbackList);
283 306
   for (MonitorCallbackList::iterator it = tmp.begin(); (it != tmp.end()); it++)
284 307
   {
285  
-    if (ID.IsEmpty())
286  
-      (*it)->OnAbortRequested();
287  
-    else if ((*it)->GetId() == ID)
288  
-      (*it)->OnAbortRequested();
  308
+    if (CHECK_FOR_ENTRY(m_vecMonitorCallbackList,(*it)))
  309
+    {
  310
+      if (ID.IsEmpty())
  311
+        (*it)->OnAbortRequested();
  312
+      else if ((*it)->GetId() == ID)
  313
+        (*it)->OnAbortRequested();
  314
+    }
289 315
   }  
290 316
 } 
291 317
 
@@ -578,6 +604,7 @@ void XBPython::FreeResources()
578 604
 {
579 605
   LOCK_AND_COPY(std::vector<PyElem>,tmpvec,m_vecPyList);
580 606
   m_vecPyList.clear();
  607
+  m_vecPyList.hadSomethingRemoved = true;
581 608
 
582 609
   lock.Leave(); //unlock here because the python thread might lock when it exits
583 610
 
@@ -611,6 +638,7 @@ void XBPython::Process()
611 638
       {
612 639
         tmpvec.push_back(*it);
613 640
         it = m_vecPyList.erase(it);
  641
+        m_vecPyList.hadSomethingRemoved = true;
614 642
       }
615 643
       else
616 644
         it++;
5  xbmc/interfaces/python/XBPython.h
@@ -47,12 +47,13 @@ namespace XBMCAddon
47 47
   }
48 48
 }
49 49
 
50  
-template <class T> class LockableType : public T, public CCriticalSection { };
  50
+template <class T> struct LockableType : public T, public CCriticalSection 
  51
+{ bool hadSomethingRemoved; };
51 52
 
52 53
 typedef LockableType<std::vector<PVOID> > PlayerCallbackList;
53 54
 typedef LockableType<std::vector<XBMCAddon::xbmc::Monitor*> > MonitorCallbackList;
54 55
 typedef LockableType<std::vector<PyElem> > PyList;
55  
-typedef LockableType<std::vector<LibraryLoader*> > PythonExtensionLibraries;
  56
+typedef std::vector<LibraryLoader*> PythonExtensionLibraries;
56 57
 
57 58
 class XBPython : 
58 59
   public IPlayerCallback,

0 notes on commit 6f87d6b

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