2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GUIDialogBusy.h"
11 #include "ServiceBroker.h"
12 #include "guilib/GUIComponent.h"
13 #include "guilib/GUIWindowManager.h"
14 #include "threads/IRunnable.h"
15 #include "threads/Thread.h"
16 #include "utils/log.h"
18 using namespace std::chrono_literals
;
20 class CBusyWaiter
: public CThread
22 std::shared_ptr
<CEvent
> m_done
;
23 IRunnable
*m_runnable
;
25 explicit CBusyWaiter(IRunnable
*runnable
) :
26 CThread(runnable
, "waiting"), m_done(new CEvent()), m_runnable(runnable
) { }
28 ~CBusyWaiter() override
{ StopThread(); }
30 bool Wait(unsigned int displaytime
, bool allowCancel
)
32 std::shared_ptr
<CEvent
> e_done(m_done
);
35 auto start
= std::chrono::steady_clock::now();
36 if (!CGUIDialogBusy::WaitOnEvent(*e_done
, displaytime
, allowCancel
))
40 auto end
= std::chrono::steady_clock::now();
41 auto duration
= std::chrono::duration_cast
<std::chrono::milliseconds
>(end
- start
);
43 unsigned int remaining
=
44 (duration
.count() >= displaytime
) ? 0 : displaytime
- duration
.count();
45 CGUIDialogBusy::WaitOnEvent(*e_done
, remaining
, false);
51 // 'this' is actually deleted from the thread where it's on the stack
52 void Process() override
54 std::shared_ptr
<CEvent
> e_done(m_done
);
62 bool CGUIDialogBusy::Wait(IRunnable
*runnable
, unsigned int displaytime
, bool allowCancel
)
66 CBusyWaiter
waiter(runnable
);
67 if (!waiter
.Wait(displaytime
, allowCancel
))
74 bool CGUIDialogBusy::WaitOnEvent(CEvent
&event
, unsigned int displaytime
/* = 100 */, bool allowCancel
/* = true */)
76 bool cancelled
= false;
77 if (!event
.Wait(std::chrono::milliseconds(displaytime
)))
79 // throw up the progress
80 CGUIDialogBusy
* dialog
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogBusy
>(WINDOW_DIALOG_BUSY
);
83 if (dialog
->IsDialogRunning())
85 CLog::Log(LOGFATAL
, "Logic error due to two concurrent busydialogs, this is a known issue. "
86 "The application will exit.");
87 throw std::logic_error("busy dialog already running");
92 while (!event
.Wait(1ms
))
94 dialog
->ProcessRenderLoop(false);
95 if (allowCancel
&& dialog
->IsCanceled())
108 CGUIDialogBusy::CGUIDialogBusy(void)
109 : CGUIDialog(WINDOW_DIALOG_BUSY
, "DialogBusy.xml", DialogModalityType::MODAL
)
111 m_loadType
= LOAD_ON_GUI_INIT
;
115 CGUIDialogBusy::~CGUIDialogBusy(void) = default;
117 void CGUIDialogBusy::Open_Internal(bool bProcessRenderLoop
, const std::string
& param
/* = "" */)
120 m_bLastVisible
= true;
122 CGUIDialog::Open_Internal(false, param
);
126 void CGUIDialogBusy::DoProcess(unsigned int currentTime
, CDirtyRegionList
&dirtyregions
)
128 bool visible
= CServiceBroker::GetGUI()->GetWindowManager().IsModalDialogTopmost(WINDOW_DIALOG_BUSY
);
129 if(!visible
&& m_bLastVisible
)
130 dirtyregions
.push_back(CDirtyRegion(m_renderRegion
));
131 m_bLastVisible
= visible
;
133 CGUIDialog::DoProcess(currentTime
, dirtyregions
);
136 void CGUIDialogBusy::Render()
140 CGUIDialog::Render();
143 bool CGUIDialogBusy::OnBack(int actionID
)