Skip to content
This repository
Browse code

[fix] the grouping of add/remove controls wasn't correctly waiting fo…

…r all of the controls to be passed.
  • Loading branch information...
commit f7809b073dc35dbaef6a055617a9658b1f3656cc 1 parent 4f196ae
authored November 13, 2012
67  xbmc/interfaces/legacy/Window.cpp
@@ -38,6 +38,19 @@ namespace XBMCAddon
38 38
   namespace xbmcgui
39 39
   {
40 40
     /**
  41
+     * Used in add/remove control. It only locks if it's given a 
  42
+     * non-NULL CCriticalSection. It's given a NULL CCriticalSection
  43
+     * when a function higher in the call stack already has a 
  44
+     */
  45
+    class MaybeLock
  46
+    {
  47
+      CCriticalSection* lock;
  48
+    public:
  49
+      inline MaybeLock(CCriticalSection* p_lock) : lock(p_lock) { if (lock) lock->lock(); }
  50
+      inline ~MaybeLock() { if (lock) lock->unlock(); }
  51
+    };
  52
+
  53
+    /**
41 54
      * Explicit template instantiation
42 55
      */
43 56
     template class Interceptor<CGUIWindow>;
@@ -538,13 +551,22 @@ namespace XBMCAddon
538 551
     void Window::removeControl(Control* pControl) throw (WindowException)
539 552
     {
540 553
       TRACE;
  554
+      DelayedCallGuard dg(languageHook);
  555
+      doRemoveControl(pControl,&g_graphicsContext,true);
  556
+    }
  557
+
  558
+    void Window::doRemoveControl(Control* pControl, CCriticalSection* gcontext, bool wait) throw (WindowException)
  559
+    {
  560
+      TRACE;
541 561
       // type checking, object should be of type Control
542 562
       if(pControl == NULL)
543 563
         throw WindowException("Object should be of type Control");
544 564
 
545  
-      CSingleLock lock(g_graphicsContext);
546  
-      if(!ref(window)->GetControl(pControl->iControlId))
547  
-        throw WindowException("Control does not exist in window");
  565
+      {
  566
+        MaybeLock mlock(gcontext);
  567
+        if(!ref(window)->GetControl(pControl->iControlId))
  568
+          throw WindowException("Control does not exist in window");
  569
+      }
548 570
 
549 571
       // delete control from vecControls in window object
550 572
       std::vector<AddonClass::Ref<Control> >::iterator it = vecControls.begin();
@@ -559,7 +581,7 @@ namespace XBMCAddon
559 581
 
560 582
       CGUIMessage msg(GUI_MSG_REMOVE_CONTROL, 0, 0);
561 583
       msg.SetPointer(pControl->pGUIControl);
562  
-      CApplicationMessenger::Get().SendGUIMessage(msg, iWindowId, true);
  584
+      CApplicationMessenger::Get().SendGUIMessage(msg, iWindowId, wait);
563 585
 
564 586
       // initialize control to zero
565 587
       pControl->pGUIControl = NULL;
@@ -569,8 +591,11 @@ namespace XBMCAddon
569 591
 
570 592
     void Window::removeControls(std::vector<Control*> pControls) throw (WindowException)
571 593
     {
572  
-      for (std::vector<Control*>::iterator iter = pControls.begin(); iter != pControls.end(); iter++)
573  
-        removeControl(*iter);
  594
+      TRACE;
  595
+      DelayedCallGuard dg(languageHook);
  596
+      int count = 1; int size = pControls.size();
  597
+      for (std::vector<Control*>::iterator iter = pControls.begin(); iter != pControls.end(); count++, iter++)
  598
+        doRemoveControl(*iter,NULL, count == size);
574 599
     }
575 600
 
576 601
     long Window::getHeight()
@@ -690,6 +715,13 @@ namespace XBMCAddon
690 715
     void Window::addControl(Control* pControl) throw (WindowException)
691 716
     {
692 717
       TRACE;
  718
+      DelayedCallGuard dg(languageHook);
  719
+      doAddControl(pControl,&g_graphicsContext,true);
  720
+    }
  721
+
  722
+    void Window::doAddControl(Control* pControl, CCriticalSection* gcontext, bool wait) throw (WindowException)
  723
+    {
  724
+      TRACE;
693 725
       if(pControl == NULL)
694 726
         throw WindowException("NULL Control passed to WindowBase::addControl");
695 727
 
@@ -697,12 +729,14 @@ namespace XBMCAddon
697 729
         throw WindowException("Control is already used");
698 730
 
699 731
       // lock xbmc GUI before accessing data from it
700  
-      CSingleLock lock(g_graphicsContext);
701 732
       pControl->iParentId = iWindowId;
702  
-      // assign control id, if id is already in use, try next id
703  
-      // TODO: This is not thread safe
704  
-      do pControl->iControlId = ++iCurrentControlId;
705  
-      while (ref(window)->GetControl(pControl->iControlId));
  733
+
  734
+      {
  735
+        MaybeLock mlock(gcontext);
  736
+        // assign control id, if id is already in use, try next id
  737
+        do pControl->iControlId = ++iCurrentControlId;
  738
+        while (ref(window)->GetControl(pControl->iControlId));
  739
+      }
706 740
 
707 741
       pControl->Create();
708 742
 
@@ -722,13 +756,17 @@ namespace XBMCAddon
722 756
       // This calls the CGUIWindow parent class to do the final add
723 757
       CGUIMessage msg(GUI_MSG_ADD_CONTROL, 0, 0);
724 758
       msg.SetPointer(pControl->pGUIControl);
725  
-      CApplicationMessenger::Get().SendGUIMessage(msg, iWindowId, true);
  759
+      CApplicationMessenger::Get().SendGUIMessage(msg, iWindowId, wait);
726 760
     }
727 761
 
728 762
     void Window::addControls(std::vector<Control*> pControls) throw (WindowException)
729 763
     {
730  
-      for (std::vector<Control*>::iterator iter = pControls.begin(); iter != pControls.end(); iter++)
731  
-        addControl(*iter);
  764
+      TRACE;
  765
+      DelayedCallGuard dg(languageHook);
  766
+      CSingleLock lock(g_graphicsContext);
  767
+      int count = 1; int size = pControls.size();
  768
+      for (std::vector<Control*>::iterator iter = pControls.begin(); iter != pControls.end(); count++, iter++)
  769
+        doAddControl(*iter,NULL, count == size);
732 770
     }
733 771
 
734 772
     Control* Window::getControl(int iControlId) throw (WindowException)
@@ -737,7 +775,6 @@ namespace XBMCAddon
737 775
       return GetControlById(iControlId);
738 776
     }
739 777
 
740  
-
741 778
     void Action::setFromCAction(const CAction& action)
742 779
     {
743 780
       TRACE;
4  xbmc/interfaces/legacy/Window.h
@@ -78,6 +78,10 @@ namespace XBMCAddon
78 78
     {
79 79
       friend class WindowDialogMixin;
80 80
       bool isDisposed;
  81
+
  82
+      void doAddControl(Control* pControl, CCriticalSection* gcontext, bool wait) throw (WindowException);
  83
+      void doRemoveControl(Control* pControl, CCriticalSection* gcontext, bool wait) throw (WindowException);
  84
+
81 85
     protected:
82 86
 #ifndef SWIG
83 87
       InterceptorBase* window;

0 notes on commit f7809b0

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