[WASAPI] fix stream types and frequencies enumeration
[xbmc.git] / xbmc / guilib / GUIControlProfiler.cpp
blobd9a6570d15dff6c16a786b17ca5cd3cd43dc3a4c
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 "GUIControlProfiler.h"
11 #include "utils/StringUtils.h"
12 #include "utils/TimeUtils.h"
13 #include "utils/XBMCTinyXML.h"
15 bool CGUIControlProfiler::m_bIsRunning = false;
17 CGUIControlProfilerItem::CGUIControlProfilerItem(CGUIControlProfiler* pProfiler,
18 CGUIControlProfilerItem* pParent,
19 CGUIControl* pControl)
20 : m_pProfiler(pProfiler), m_pParent(pParent), m_pControl(pControl)
22 if (m_pControl)
24 m_controlID = m_pControl->GetID();
25 m_ControlType = m_pControl->GetControlType();
26 m_strDescription = m_pControl->GetDescription();
28 else
30 m_controlID = 0;
31 m_ControlType = CGUIControl::GUICONTROL_UNKNOWN;
35 CGUIControlProfilerItem::~CGUIControlProfilerItem(void)
37 Reset(NULL);
40 void CGUIControlProfilerItem::Reset(CGUIControlProfiler *pProfiler)
42 m_controlID = 0;
43 m_ControlType = CGUIControl::GUICONTROL_UNKNOWN;
44 m_pControl = NULL;
46 m_visTime = 0;
47 m_renderTime = 0;
48 const unsigned int dwSize = m_vecChildren.size();
49 for (unsigned int i=0; i<dwSize; ++i)
50 delete m_vecChildren[i];
51 m_vecChildren.clear();
53 m_pProfiler = pProfiler;
56 void CGUIControlProfilerItem::BeginVisibility(void)
58 m_i64VisStart = CurrentHostCounter();
61 void CGUIControlProfilerItem::EndVisibility(void)
63 m_visTime += (unsigned int)(m_pProfiler->m_fPerfScale * (CurrentHostCounter() - m_i64VisStart));
66 void CGUIControlProfilerItem::BeginRender(void)
68 m_i64RenderStart = CurrentHostCounter();
71 void CGUIControlProfilerItem::EndRender(void)
73 m_renderTime += (unsigned int)(m_pProfiler->m_fPerfScale * (CurrentHostCounter() - m_i64RenderStart));
76 void CGUIControlProfilerItem::SaveToXML(TiXmlElement *parent)
78 TiXmlElement *xmlControl = new TiXmlElement("control");
79 parent->LinkEndChild(xmlControl);
81 const char *lpszType = NULL;
82 switch (m_ControlType)
84 case CGUIControl::GUICONTROL_BUTTON:
85 lpszType = "button"; break;
86 case CGUIControl::GUICONTROL_FADELABEL:
87 lpszType = "fadelabel"; break;
88 case CGUIControl::GUICONTROL_IMAGE:
89 case CGUIControl::GUICONTROL_BORDEREDIMAGE:
90 lpszType = "image"; break;
91 case CGUIControl::GUICONTROL_LABEL:
92 lpszType = "label"; break;
93 case CGUIControl::GUICONTROL_LISTGROUP:
94 lpszType = "group"; break;
95 case CGUIControl::GUICONTROL_PROGRESS:
96 lpszType = "progress"; break;
97 case CGUIControl::GUICONTROL_RADIO:
98 lpszType = "radiobutton"; break;
99 case CGUIControl::GUICONTROL_RSS:
100 lpszType = "rss"; break;
101 case CGUIControl::GUICONTROL_SLIDER:
102 lpszType = "slider"; break;
103 case CGUIControl::GUICONTROL_SETTINGS_SLIDER:
104 lpszType = "sliderex"; break;
105 case CGUIControl::GUICONTROL_SPIN:
106 lpszType = "spincontrol"; break;
107 case CGUIControl::GUICONTROL_SPINEX:
108 lpszType = "spincontrolex"; break;
109 case CGUIControl::GUICONTROL_TEXTBOX:
110 lpszType = "textbox"; break;
111 case CGUIControl::GUICONTROL_TOGGLEBUTTON:
112 lpszType = "togglebutton"; break;
113 case CGUIControl::GUICONTROL_VIDEO:
114 lpszType = "videowindow"; break;
115 case CGUIControl::GUICONTROL_MOVER:
116 lpszType = "mover"; break;
117 case CGUIControl::GUICONTROL_RESIZE:
118 lpszType = "resize"; break;
119 case CGUIControl::GUICONTROL_EDIT:
120 lpszType = "edit"; break;
121 case CGUIControl::GUICONTROL_VISUALISATION:
122 lpszType = "visualisation"; break;
123 case CGUIControl::GUICONTROL_MULTI_IMAGE:
124 lpszType = "multiimage"; break;
125 case CGUIControl::GUICONTROL_GROUP:
126 lpszType = "group"; break;
127 case CGUIControl::GUICONTROL_GROUPLIST:
128 lpszType = "grouplist"; break;
129 case CGUIControl::GUICONTROL_SCROLLBAR:
130 lpszType = "scrollbar"; break;
131 case CGUIControl::GUICONTROL_LISTLABEL:
132 lpszType = "label"; break;
133 case CGUIControl::GUICONTAINER_LIST:
134 lpszType = "list"; break;
135 case CGUIControl::GUICONTAINER_WRAPLIST:
136 lpszType = "wraplist"; break;
137 case CGUIControl::GUICONTAINER_FIXEDLIST:
138 lpszType = "fixedlist"; break;
139 case CGUIControl::GUICONTAINER_PANEL:
140 lpszType = "panel"; break;
141 case CGUIControl::GUICONTROL_COLORBUTTON:
142 lpszType = "colorbutton";
143 break;
144 //case CGUIControl::GUICONTROL_UNKNOWN:
145 default:
146 break;
149 if (lpszType)
150 xmlControl->SetAttribute("type", lpszType);
151 if (m_controlID != 0)
153 std::string str = std::to_string(m_controlID);
154 xmlControl->SetAttribute("id", str.c_str());
157 float pct = (float)GetTotalTime() / (float)m_pProfiler->GetTotalTime();
158 if (pct > 0.01f)
160 std::string str = StringUtils::Format("{:.0f}", pct * 100.0f);
161 xmlControl->SetAttribute("percent", str.c_str());
164 if (!m_strDescription.empty())
166 TiXmlElement *elem = new TiXmlElement("description");
167 xmlControl->LinkEndChild(elem);
168 TiXmlText *text = new TiXmlText(m_strDescription.c_str());
169 elem->LinkEndChild(text);
172 // Note time is stored in 1/100 milliseconds but reported in ms
173 unsigned int vis = m_visTime / 100;
174 unsigned int rend = m_renderTime / 100;
175 if (vis || rend)
177 std::string val;
178 TiXmlElement *elem = new TiXmlElement("rendertime");
179 xmlControl->LinkEndChild(elem);
180 val = std::to_string(rend);
181 TiXmlText *text = new TiXmlText(val.c_str());
182 elem->LinkEndChild(text);
184 elem = new TiXmlElement("visibletime");
185 xmlControl->LinkEndChild(elem);
186 val = std::to_string(vis);
187 text = new TiXmlText(val.c_str());
188 elem->LinkEndChild(text);
191 if (m_vecChildren.size())
193 TiXmlElement *xmlChilds = new TiXmlElement("children");
194 xmlControl->LinkEndChild(xmlChilds);
195 const unsigned int dwSize = m_vecChildren.size();
196 for (unsigned int i=0; i<dwSize; ++i)
197 m_vecChildren[i]->SaveToXML(xmlChilds);
201 CGUIControlProfilerItem *CGUIControlProfilerItem::AddControl(CGUIControl *pControl)
203 m_vecChildren.push_back(new CGUIControlProfilerItem(m_pProfiler, this, pControl));
204 return m_vecChildren.back();
207 CGUIControlProfilerItem *CGUIControlProfilerItem::FindOrAddControl(CGUIControl *pControl, bool recurse)
209 const unsigned int dwSize = m_vecChildren.size();
210 for (unsigned int i=0; i<dwSize; ++i)
212 CGUIControlProfilerItem *p = m_vecChildren[i];
213 if (p->m_pControl == pControl)
214 return p;
215 if (recurse && (p = p->FindOrAddControl(pControl, true)))
216 return p;
219 if (pControl->GetParentControl() == m_pControl)
220 return AddControl(pControl);
222 return NULL;
225 CGUIControlProfiler::CGUIControlProfiler(void)
226 : m_ItemHead(NULL, NULL, NULL), m_pLastItem(NULL)
227 // m_bIsRunning(false), no isRunning because it is static
229 m_fPerfScale = 100000.0f / CurrentHostFrequency();
232 CGUIControlProfiler &CGUIControlProfiler::Instance(void)
234 static CGUIControlProfiler _instance;
235 return _instance;
238 bool CGUIControlProfiler::IsRunning(void)
240 return m_bIsRunning;
243 void CGUIControlProfiler::Start(void)
245 m_iFrameCount = 0;
246 m_bIsRunning = true;
247 m_pLastItem = NULL;
248 m_ItemHead.Reset(this);
251 void CGUIControlProfiler::BeginVisibility(CGUIControl *pControl)
253 CGUIControlProfilerItem *item = FindOrAddControl(pControl);
254 item->BeginVisibility();
257 void CGUIControlProfiler::EndVisibility(CGUIControl *pControl)
259 CGUIControlProfilerItem *item = FindOrAddControl(pControl);
260 item->EndVisibility();
263 void CGUIControlProfiler::BeginRender(CGUIControl *pControl)
265 CGUIControlProfilerItem *item = FindOrAddControl(pControl);
266 item->BeginRender();
269 void CGUIControlProfiler::EndRender(CGUIControl *pControl)
271 CGUIControlProfilerItem *item = FindOrAddControl(pControl);
272 item->EndRender();
275 CGUIControlProfilerItem *CGUIControlProfiler::FindOrAddControl(CGUIControl *pControl)
277 if (m_pLastItem)
279 // Typically calls come in pairs so the last control we found is probably
280 // the one we want again next time
281 if (m_pLastItem->m_pControl == pControl)
282 return m_pLastItem;
283 // If that control is not a match, usually the one we want is the next
284 // sibling of that control, or the parent of that control so check
285 // the parent first as it is more convenient
286 m_pLastItem = m_pLastItem->m_pParent;
287 if (m_pLastItem && m_pLastItem->m_pControl == pControl)
288 return m_pLastItem;
289 // continued from above, this searches the original control's siblings
290 if (m_pLastItem)
291 m_pLastItem = m_pLastItem->FindOrAddControl(pControl, false);
292 if (m_pLastItem)
293 return m_pLastItem;
296 m_pLastItem = m_ItemHead.FindOrAddControl(pControl, true);
297 if (!m_pLastItem)
298 m_pLastItem = m_ItemHead.AddControl(pControl);
300 return m_pLastItem;
303 void CGUIControlProfiler::EndFrame(void)
305 m_iFrameCount++;
306 if (m_iFrameCount >= m_iMaxFrameCount)
308 const unsigned int dwSize = m_ItemHead.m_vecChildren.size();
309 for (unsigned int i=0; i<dwSize; ++i)
311 CGUIControlProfilerItem *p = m_ItemHead.m_vecChildren[i];
312 m_ItemHead.m_visTime += p->m_visTime;
313 m_ItemHead.m_renderTime += p->m_renderTime;
316 m_bIsRunning = false;
317 if (SaveResults())
318 m_ItemHead.Reset(this);
322 bool CGUIControlProfiler::SaveResults(void)
324 if (m_strOutputFile.empty())
325 return false;
327 CXBMCTinyXML doc;
328 TiXmlDeclaration decl("1.0", "", "yes");
329 doc.InsertEndChild(decl);
331 TiXmlElement *root = new TiXmlElement("guicontrolprofiler");
332 std::string str = std::to_string(m_iFrameCount);
333 root->SetAttribute("framecount", str.c_str());
334 root->SetAttribute("timeunit", "ms");
335 doc.LinkEndChild(root);
337 m_ItemHead.SaveToXML(root);
338 return doc.SaveFile(m_strOutputFile);