Merge pull request #22816 from CastagnaIT/fix_tx3g
[xbmc.git] / xbmc / dialogs / GUIDialogBusy.cpp
blobe53f1fca82d15d8790f7e7eaf641e95d19ea67d8
1 /*
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.
7 */
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;
24 public:
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);
34 Create();
35 auto start = std::chrono::steady_clock::now();
36 if (!CGUIDialogBusy::WaitOnEvent(*e_done, displaytime, allowCancel))
38 m_runnable->Cancel();
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);
46 return false;
48 return true;
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);
56 CThread::Process();
57 (*e_done).Set();
62 bool CGUIDialogBusy::Wait(IRunnable *runnable, unsigned int displaytime, bool allowCancel)
64 if (!runnable)
65 return false;
66 CBusyWaiter waiter(runnable);
67 if (!waiter.Wait(displaytime, allowCancel))
69 return false;
71 return true;
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);
81 if (dialog)
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");
90 dialog->Open();
92 while (!event.Wait(1ms))
94 dialog->ProcessRenderLoop(false);
95 if (allowCancel && dialog->IsCanceled())
97 cancelled = true;
98 break;
102 dialog->Close(true);
105 return !cancelled;
108 CGUIDialogBusy::CGUIDialogBusy(void)
109 : CGUIDialog(WINDOW_DIALOG_BUSY, "DialogBusy.xml", DialogModalityType::MODAL)
111 m_loadType = LOAD_ON_GUI_INIT;
112 m_bCanceled = false;
115 CGUIDialogBusy::~CGUIDialogBusy(void) = default;
117 void CGUIDialogBusy::Open_Internal(bool bProcessRenderLoop, const std::string& param /* = "" */)
119 m_bCanceled = false;
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()
138 if(!m_bLastVisible)
139 return;
140 CGUIDialog::Render();
143 bool CGUIDialogBusy::OnBack(int actionID)
145 m_bCanceled = true;
146 return true;