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.
9 #include "WindowTranslator.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"
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
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
},
187 struct FallbackWindowMapping
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
)
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
);
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);
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
)
250 return WINDOW_HOME
+ iWindow
;
253 // Run through the window structure
254 auto it
= WindowMappingByName
.find({strWindow
.c_str(), {}});
255 if (it
!= WindowMappingByName
.end())
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
;
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())
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
;
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()
312 return WINDOW_FULLSCREEN_LIVETV_INPUT
;
313 else if (CServiceBroker::GetPVRManager()
314 .Get
<PVR::GUI::Channels
>()
315 .GetChannelNavigator()
317 return WINDOW_FULLSCREEN_LIVETV_PREVIEW
;
319 return WINDOW_FULLSCREEN_LIVETV
;
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()
343 return WINDOW_FULLSCREEN_RADIO_INPUT
;
344 else if (CServiceBroker::GetPVRManager()
345 .Get
<PVR::GUI::Channels
>()
346 .GetChannelNavigator()
348 return WINDOW_FULLSCREEN_RADIO_PREVIEW
;
350 return WINDOW_FULLSCREEN_RADIO
;
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
;