Merge pull request #26148 from ksooo/fix-secondstotimestring-warning
[xbmc.git] / xbmc / input / WindowTranslator.cpp
blob77c33f173854110f43b11b3346370da6df8c3c00
1 /*
2 * Copyright (C) 2017-2024 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 "WindowTranslator.h"
11 #include "FileItem.h"
12 #include "ServiceBroker.h"
13 #include "application/Application.h"
14 #include "application/ApplicationComponents.h"
15 #include "application/ApplicationPlayer.h"
16 #include "guilib/WindowIDs.h"
17 #include "pvr/PVRManager.h"
18 #include "pvr/guilib/PVRGUIActionsChannels.h"
19 #include "utils/StringUtils.h"
20 #include "utils/log.h"
22 #include <algorithm>
23 #include <cstring>
24 #include <stdlib.h>
26 const CWindowTranslator::WindowMapByName CWindowTranslator::WindowMappingByName = {
27 {"home", WINDOW_HOME},
28 {"programs", WINDOW_PROGRAMS},
29 {"pictures", WINDOW_PICTURES},
30 {"filemanager", WINDOW_FILES},
31 {"settings", WINDOW_SETTINGS_MENU},
32 {"music", WINDOW_MUSIC_NAV},
33 {"videos", WINDOW_VIDEO_NAV},
34 {"tvchannels", WINDOW_TV_CHANNELS},
35 {"tvrecordings", WINDOW_TV_RECORDINGS},
36 {"tvguide", WINDOW_TV_GUIDE},
37 {"tvtimers", WINDOW_TV_TIMERS},
38 {"tvsearch", WINDOW_TV_SEARCH},
39 {"tvproviders", WINDOW_TV_PROVIDERS},
40 {"radiochannels", WINDOW_RADIO_CHANNELS},
41 {"radiorecordings", WINDOW_RADIO_RECORDINGS},
42 {"radioguide", WINDOW_RADIO_GUIDE},
43 {"radiotimers", WINDOW_RADIO_TIMERS},
44 {"radiosearch", WINDOW_RADIO_SEARCH},
45 {"radioproviders", WINDOW_RADIO_PROVIDERS},
46 {"gamecontrollers", WINDOW_DIALOG_GAME_CONTROLLERS},
47 {"gameports", WINDOW_DIALOG_GAME_PORTS},
48 {"games", WINDOW_GAMES},
49 {"pvrguidecontrols", WINDOW_DIALOG_PVR_GUIDE_CONTROLS},
50 {"pvrguideinfo", WINDOW_DIALOG_PVR_GUIDE_INFO},
51 {"pvrrecordinginfo", WINDOW_DIALOG_PVR_RECORDING_INFO},
52 {"pvrradiordsinfo", WINDOW_DIALOG_PVR_RADIO_RDS_INFO},
53 {"pvrtimersetting", WINDOW_DIALOG_PVR_TIMER_SETTING},
54 {"pvrgroupmanager", WINDOW_DIALOG_PVR_GROUP_MANAGER},
55 {"pvrchannelmanager", WINDOW_DIALOG_PVR_CHANNEL_MANAGER},
56 {"pvrguidesearch", WINDOW_DIALOG_PVR_GUIDE_SEARCH},
57 {"pvrchannelscan", WINDOW_DIALOG_PVR_CHANNEL_SCAN},
58 {"pvrupdateprogress", WINDOW_DIALOG_PVR_UPDATE_PROGRESS},
59 {"pvrosdchannels", WINDOW_DIALOG_PVR_OSD_CHANNELS},
60 {"pvrchannelguide", WINDOW_DIALOG_PVR_CHANNEL_GUIDE},
61 {"pvrosdguide", WINDOW_DIALOG_PVR_CHANNEL_GUIDE}, // backward compatibility to v17
62 {"pvrosdteletext", WINDOW_DIALOG_OSD_TELETEXT},
63 {"systeminfo", WINDOW_SYSTEM_INFORMATION},
64 {"screencalibration", WINDOW_SCREEN_CALIBRATION},
65 {"systemsettings", WINDOW_SETTINGS_SYSTEM},
66 {"servicesettings", WINDOW_SETTINGS_SERVICE},
67 {"pvrsettings", WINDOW_SETTINGS_MYPVR},
68 {"playersettings", WINDOW_SETTINGS_PLAYER},
69 {"mediasettings", WINDOW_SETTINGS_MEDIA},
70 {"interfacesettings", WINDOW_SETTINGS_INTERFACE},
71 {"appearancesettings", WINDOW_SETTINGS_INTERFACE}, // backward compatibility to v16
72 {"gamesettings", WINDOW_SETTINGS_MYGAMES},
73 {"videoplaylist", WINDOW_VIDEO_PLAYLIST},
74 {"loginscreen", WINDOW_LOGIN_SCREEN},
75 {"profiles", WINDOW_SETTINGS_PROFILES},
76 {"skinsettings", WINDOW_SKIN_SETTINGS},
77 {"addonbrowser", WINDOW_ADDON_BROWSER},
78 {"yesnodialog", WINDOW_DIALOG_YES_NO},
79 {"progressdialog", WINDOW_DIALOG_PROGRESS},
80 {"virtualkeyboard", WINDOW_DIALOG_KEYBOARD},
81 {"volumebar", WINDOW_DIALOG_VOLUME_BAR},
82 {"submenu", WINDOW_DIALOG_SUB_MENU},
83 {"contextmenu", WINDOW_DIALOG_CONTEXT_MENU},
84 {"notification", WINDOW_DIALOG_KAI_TOAST},
85 {"numericinput", WINDOW_DIALOG_NUMERIC},
86 {"gamepadinput", WINDOW_DIALOG_GAMEPAD},
87 {"shutdownmenu", WINDOW_DIALOG_BUTTON_MENU},
88 {"playercontrols", WINDOW_DIALOG_PLAYER_CONTROLS},
89 {"playerprocessinfo", WINDOW_DIALOG_PLAYER_PROCESS_INFO},
90 {"seekbar", WINDOW_DIALOG_SEEK_BAR},
91 {"musicosd", WINDOW_DIALOG_MUSIC_OSD},
92 {"addonsettings", WINDOW_DIALOG_ADDON_SETTINGS},
93 {"visualisationpresetlist", WINDOW_DIALOG_VIS_PRESET_LIST},
94 {"osdcmssettings", WINDOW_DIALOG_CMS_OSD_SETTINGS},
95 {"osdvideosettings", WINDOW_DIALOG_VIDEO_OSD_SETTINGS},
96 {"osdaudiosettings", WINDOW_DIALOG_AUDIO_OSD_SETTINGS},
97 {"osdsubtitlesettings", WINDOW_DIALOG_SUBTITLE_OSD_SETTINGS},
98 {"videobookmarks", WINDOW_DIALOG_VIDEO_BOOKMARKS},
99 {"filebrowser", WINDOW_DIALOG_FILE_BROWSER},
100 {"networksetup", WINDOW_DIALOG_NETWORK_SETUP},
101 {"mediasource", WINDOW_DIALOG_MEDIA_SOURCE},
102 {"profilesettings", WINDOW_DIALOG_PROFILE_SETTINGS},
103 {"locksettings", WINDOW_DIALOG_LOCK_SETTINGS},
104 {"contentsettings", WINDOW_DIALOG_CONTENT_SETTINGS},
105 {"libexportsettings", WINDOW_DIALOG_LIBEXPORT_SETTINGS},
106 {"songinformation", WINDOW_DIALOG_SONG_INFO},
107 {"smartplaylisteditor", WINDOW_DIALOG_SMART_PLAYLIST_EDITOR},
108 {"smartplaylistrule", WINDOW_DIALOG_SMART_PLAYLIST_RULE},
109 {"busydialog", WINDOW_DIALOG_BUSY},
110 {"busydialognocancel", WINDOW_DIALOG_BUSY_NOCANCEL},
111 {"pictureinfo", WINDOW_DIALOG_PICTURE_INFO},
112 {"fullscreeninfo", WINDOW_DIALOG_FULLSCREEN_INFO},
113 {"sliderdialog", WINDOW_DIALOG_SLIDER},
114 {"addoninformation", WINDOW_DIALOG_ADDON_INFO},
115 {"subtitlesearch", WINDOW_DIALOG_SUBTITLES},
116 {"musicplaylist", WINDOW_MUSIC_PLAYLIST},
117 {"musicplaylisteditor", WINDOW_MUSIC_PLAYLIST_EDITOR},
118 {"infoprovidersettings", WINDOW_DIALOG_INFOPROVIDER_SETTINGS},
119 {"teletext", WINDOW_DIALOG_OSD_TELETEXT},
120 {"selectdialog", WINDOW_DIALOG_SELECT},
121 {"musicinformation", WINDOW_DIALOG_MUSIC_INFO},
122 {"okdialog", WINDOW_DIALOG_OK},
123 {"movieinformation", WINDOW_DIALOG_VIDEO_INFO},
124 {"managevideoversions", WINDOW_DIALOG_MANAGE_VIDEO_VERSIONS},
125 {"managevideoextras", WINDOW_DIALOG_MANAGE_VIDEO_EXTRAS},
126 {"selectvideoversion", WINDOW_DIALOG_SELECT_VIDEO_VERSION},
127 {"selectvideoextra", WINDOW_DIALOG_SELECT_VIDEO_EXTRA},
128 {"textviewer", WINDOW_DIALOG_TEXT_VIEWER},
129 {"fullscreenvideo", WINDOW_FULLSCREEN_VIDEO},
130 {"dialogcolorpicker", WINDOW_DIALOG_COLOR_PICKER},
132 // Virtual window for fullscreen radio, uses WINDOW_FULLSCREEN_VIDEO as
133 // fallback
134 {"fullscreenlivetv", WINDOW_FULLSCREEN_LIVETV},
136 // Live TV channel preview
137 {"fullscreenlivetvpreview", WINDOW_FULLSCREEN_LIVETV_PREVIEW},
139 // Live TV direct channel number input
140 {"fullscreenlivetvinput", WINDOW_FULLSCREEN_LIVETV_INPUT},
142 // Virtual window for fullscreen radio, uses WINDOW_VISUALISATION as fallback
143 {"fullscreenradio", WINDOW_FULLSCREEN_RADIO},
145 // PVR Radio channel preview
146 {"fullscreenradiopreview", WINDOW_FULLSCREEN_RADIO_PREVIEW},
148 // PVR radio direct channel number input
149 {"fullscreenradioinput", WINDOW_FULLSCREEN_RADIO_INPUT},
151 {"fullscreengame", WINDOW_FULLSCREEN_GAME},
152 {"visualisation", WINDOW_VISUALISATION},
153 {"slideshow", WINDOW_SLIDESHOW},
154 {"weather", WINDOW_WEATHER},
155 {"screensaver", WINDOW_SCREENSAVER},
156 {"videoosd", WINDOW_DIALOG_VIDEO_OSD},
157 {"videomenu", WINDOW_VIDEO_MENU},
158 {"videotimeseek", WINDOW_VIDEO_TIME_SEEK},
159 {"splash", WINDOW_SPLASH},
160 {"startwindow", WINDOW_START},
161 {"startup", WINDOW_STARTUP_ANIM},
162 {"peripherals", WINDOW_DIALOG_PERIPHERALS},
163 {"peripheralsettings", WINDOW_DIALOG_PERIPHERAL_SETTINGS},
164 {"extendedprogressdialog", WINDOW_DIALOG_EXT_PROGRESS},
165 {"mediafilter", WINDOW_DIALOG_MEDIA_FILTER},
166 {"addon", WINDOW_ADDON_START},
167 {"eventlog", WINDOW_EVENT_LOG},
168 {"favouritesbrowser", WINDOW_FAVOURITES},
169 {"tvtimerrules", WINDOW_TV_TIMER_RULES},
170 {"radiotimerrules", WINDOW_RADIO_TIMER_RULES},
171 {"gameosd", WINDOW_DIALOG_GAME_OSD},
172 {"gamevideofilter", WINDOW_DIALOG_GAME_VIDEO_FILTER},
173 {"gamestretchmode", WINDOW_DIALOG_GAME_STRETCH_MODE},
174 {"gamevolume", WINDOW_DIALOG_GAME_VOLUME},
175 {"gameadvancedsettings", WINDOW_DIALOG_GAME_ADVANCED_SETTINGS},
176 {"gamevideorotation", WINDOW_DIALOG_GAME_VIDEO_ROTATION},
177 {"ingamesaves", WINDOW_DIALOG_IN_GAME_SAVES},
178 {"gamesaves", WINDOW_DIALOG_GAME_SAVES},
179 {"gameagents", WINDOW_DIALOG_GAME_AGENTS},
180 {"dialogselectvideo", WINDOW_DIALOG_SELECT_VIDEO_STREAM},
181 {"dialogselectaudio", WINDOW_DIALOG_SELECT_AUDIO_STREAM},
182 {"dialogselectsubtitle", WINDOW_DIALOG_SELECT_SUBTITLE_STREAM},
185 namespace
187 struct FallbackWindowMapping
189 int origin;
190 int target;
193 static const std::vector<FallbackWindowMapping> FallbackWindows = {
194 {WINDOW_FULLSCREEN_LIVETV, WINDOW_FULLSCREEN_VIDEO},
195 {WINDOW_FULLSCREEN_LIVETV_INPUT, WINDOW_FULLSCREEN_LIVETV},
196 {WINDOW_FULLSCREEN_LIVETV_PREVIEW, WINDOW_FULLSCREEN_LIVETV},
197 {WINDOW_FULLSCREEN_RADIO, WINDOW_VISUALISATION},
198 {WINDOW_FULLSCREEN_RADIO_INPUT, WINDOW_FULLSCREEN_RADIO},
199 {WINDOW_FULLSCREEN_RADIO_PREVIEW, WINDOW_FULLSCREEN_RADIO},
201 } // anonymous namespace
203 bool CWindowTranslator::WindowNameCompare::operator()(const WindowMapItem& lhs,
204 const WindowMapItem& rhs) const
206 return std::strcmp(lhs.windowName, rhs.windowName) < 0;
209 bool CWindowTranslator::WindowIDCompare::operator()(const WindowMapItem& lhs,
210 const WindowMapItem& rhs) const
212 return lhs.windowId < rhs.windowId;
215 void CWindowTranslator::GetWindows(std::vector<std::string>& windowList)
217 windowList.clear();
218 windowList.reserve(WindowMappingByName.size());
219 for (auto itMapping : WindowMappingByName)
220 windowList.emplace_back(itMapping.windowName);
223 int CWindowTranslator::TranslateWindow(const std::string& window)
225 std::string strWindow(window);
226 if (strWindow.empty())
227 return WINDOW_INVALID;
229 StringUtils::ToLower(strWindow);
231 // Eliminate .xml
232 if (StringUtils::EndsWith(strWindow, ".xml"))
233 strWindow.resize(strWindow.size() - 4);
235 // window12345, for custom window to be keymapped
236 if (strWindow.length() > 6 && StringUtils::StartsWith(strWindow, "window"))
237 strWindow = strWindow.substr(6);
239 // Drop "my" prefix
240 if (StringUtils::StartsWith(strWindow, "my"))
241 strWindow = strWindow.substr(2);
243 if (StringUtils::IsNaturalNumber(strWindow))
245 // Allow a full window ID or a delta ID
246 int iWindow = atoi(strWindow.c_str());
247 if (iWindow > WINDOW_INVALID)
248 return iWindow;
250 return WINDOW_HOME + iWindow;
253 // Run through the window structure
254 auto it = WindowMappingByName.find({strWindow.c_str(), {}});
255 if (it != WindowMappingByName.end())
256 return it->windowId;
258 CLog::Log(LOGERROR, "Window Translator: Can't find window {}", window);
260 return WINDOW_INVALID;
263 std::string CWindowTranslator::TranslateWindow(int windowId)
265 static auto reverseWindowMapping = CreateWindowMappingByID();
267 windowId = GetVirtualWindow(windowId);
269 auto it = reverseWindowMapping.find(WindowMapItem{"", windowId});
270 if (it != reverseWindowMapping.end())
271 return it->windowName;
273 return "";
276 int CWindowTranslator::GetFallbackWindow(int windowId)
278 auto it = std::find_if(FallbackWindows.begin(), FallbackWindows.end(),
279 [windowId](const FallbackWindowMapping& mapping)
280 { return mapping.origin == windowId; });
282 if (it != FallbackWindows.end())
283 return it->target;
285 // For add-on windows use WINDOW_ADDON_START because ID is dynamic
286 if (WINDOW_ADDON_START < windowId && windowId <= WINDOW_ADDON_END)
287 return WINDOW_ADDON_START;
289 return -1;
292 CWindowTranslator::WindowMapByID CWindowTranslator::CreateWindowMappingByID()
294 WindowMapByID reverseWindowMapping;
296 reverseWindowMapping.insert(WindowMappingByName.begin(), WindowMappingByName.end());
298 return reverseWindowMapping;
301 int CWindowTranslator::GetVirtualWindow(int windowId)
303 if (windowId == WINDOW_FULLSCREEN_VIDEO)
305 if (g_application.CurrentFileItem().HasPVRChannelInfoTag())
307 // special casing for Live TV
308 if (CServiceBroker::GetPVRManager()
309 .Get<PVR::GUI::Channels>()
310 .GetChannelNumberInputHandler()
311 .HasChannelNumber())
312 return WINDOW_FULLSCREEN_LIVETV_INPUT;
313 else if (CServiceBroker::GetPVRManager()
314 .Get<PVR::GUI::Channels>()
315 .GetChannelNavigator()
316 .IsPreview())
317 return WINDOW_FULLSCREEN_LIVETV_PREVIEW;
318 else
319 return WINDOW_FULLSCREEN_LIVETV;
321 else
323 const auto& components = CServiceBroker::GetAppComponents();
324 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
326 // check if we're in a DVD menu
327 if (appPlayer->IsInMenu())
328 return WINDOW_VIDEO_MENU;
329 // special casing for numeric seek
330 else if (appPlayer->GetSeekHandler().HasTimeCode())
331 return WINDOW_VIDEO_TIME_SEEK;
334 else if (windowId == WINDOW_VISUALISATION)
336 if (g_application.CurrentFileItem().HasPVRChannelInfoTag())
338 // special casing for PVR radio
339 if (CServiceBroker::GetPVRManager()
340 .Get<PVR::GUI::Channels>()
341 .GetChannelNumberInputHandler()
342 .HasChannelNumber())
343 return WINDOW_FULLSCREEN_RADIO_INPUT;
344 else if (CServiceBroker::GetPVRManager()
345 .Get<PVR::GUI::Channels>()
346 .GetChannelNavigator()
347 .IsPreview())
348 return WINDOW_FULLSCREEN_RADIO_PREVIEW;
349 else
350 return WINDOW_FULLSCREEN_RADIO;
352 else
354 const auto& components = CServiceBroker::GetAppComponents();
355 const auto appPlayer = components.GetComponent<CApplicationPlayer>();
357 // special casing for numeric seek
358 if (appPlayer->GetSeekHandler().HasTimeCode())
359 return WINDOW_VIDEO_TIME_SEEK;
363 return windowId;