[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / windowing / tvos / WinSystemTVOS.mm
blob18546f3cd66e7efb3c7c9bd123e4fcc9efaf7b5f
1 /*
2  *  Copyright (C) 2010-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
9 #include "WinSystemTVOS.h"
11 #include "ServiceBroker.h"
12 #import "cores/AudioEngine/Sinks/AESinkDARWINTVOS.h"
13 #include "cores/RetroPlayer/process/ios/RPProcessInfoIOS.h"
14 #include "cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h"
15 #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
16 #include "cores/VideoPlayer/DVDCodecs/Video/VTB.h"
17 #include "cores/VideoPlayer/Process/ios/ProcessInfoIOS.h"
18 #include "cores/VideoPlayer/VideoRenderers/HwDecRender/RendererVTBGLES.h"
19 #include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h"
20 #include "cores/VideoPlayer/VideoRenderers/RenderFactory.h"
21 #include "filesystem/SpecialProtocol.h"
22 #include "guilib/DispResource.h"
23 #include "guilib/Texture.h"
24 #include "messaging/ApplicationMessenger.h"
25 #include "settings/DisplaySettings.h"
26 #include "settings/Settings.h"
27 #include "settings/SettingsComponent.h"
28 #include "utils/StringUtils.h"
29 #include "utils/log.h"
30 #include "windowing/GraphicContext.h"
31 #include "windowing/OSScreenSaver.h"
32 #include "windowing/WindowSystemFactory.h"
33 #import "windowing/tvos/OSScreenSaverTVOS.h"
34 #import "windowing/tvos/VideoSyncTVos.h"
35 #import "windowing/tvos/WinEventsTVOS.h"
37 #import "platform/darwin/DarwinUtils.h"
38 #import "platform/darwin/tvos/TVOSDisplayManager.h"
39 #import "platform/darwin/tvos/XBMCController.h"
41 #include <memory>
42 #include <mutex>
43 #include <vector>
45 #import <Foundation/Foundation.h>
46 #import <OpenGLES/ES2/gl.h>
47 #import <OpenGLES/ES2/glext.h>
48 #import <QuartzCore/CADisplayLink.h>
50 using namespace std::chrono_literals;
52 #define CONST_HDMI "HDMI"
54 // if there was a devicelost callback
55 // but no device reset for 3 secs
56 // a timeout fires the reset callback
57 // (for ensuring that e.x. AE isn't stuck)
58 constexpr auto LOST_DEVICE_TIMEOUT_MS{3000ms};
60 // TVOSDisplayLinkCallback is defined in the lower part of the file
61 @interface TVOSDisplayLinkCallback : NSObject
63 @private
64   CVideoSyncTVos* videoSyncImpl;
66 @property(nonatomic, setter=SetVideoSyncImpl:) CVideoSyncTVos* videoSyncImpl;
67 - (void)runDisplayLink;
68 @end
70 using namespace KODI;
71 using namespace MESSAGING;
73 struct CADisplayLinkWrapper
75   CADisplayLink* impl;
76   TVOSDisplayLinkCallback* callbackClass;
79 void CWinSystemTVOS::Register()
81   KODI::WINDOWING::CWindowSystemFactory::RegisterWindowSystem(CreateWinSystem);
84 std::unique_ptr<CWinSystemBase> CWinSystemTVOS::CreateWinSystem()
86   return std::make_unique<CWinSystemTVOS>();
89 void CWinSystemTVOS::MessagePush(XBMC_Event* newEvent)
91   dynamic_cast<CWinEventsTVOS&>(*m_winEvents).MessagePush(newEvent);
94 size_t CWinSystemTVOS::GetQueueSize()
96   return dynamic_cast<CWinEventsTVOS&>(*m_winEvents).GetQueueSize();
99 void CWinSystemTVOS::AnnounceOnLostDevice()
101   std::unique_lock<CCriticalSection> lock(m_resourceSection);
102   // tell any shared resources
103   CLog::Log(LOGDEBUG, "CWinSystemTVOS::AnnounceOnLostDevice");
104   for (auto dispResource : m_resources)
105     dispResource->OnLostDisplay();
108 void CWinSystemTVOS::AnnounceOnResetDevice()
110   std::unique_lock<CCriticalSection> lock(m_resourceSection);
111   // tell any shared resources
112   CLog::Log(LOGDEBUG, "CWinSystemTVOS::AnnounceOnResetDevice");
113   for (auto dispResource : m_resources)
114     dispResource->OnResetDisplay();
117 void CWinSystemTVOS::StartLostDeviceTimer()
119   if (m_lostDeviceTimer.IsRunning())
120     m_lostDeviceTimer.Restart();
121   else
122     m_lostDeviceTimer.Start(LOST_DEVICE_TIMEOUT_MS, false);
125 void CWinSystemTVOS::StopLostDeviceTimer()
127   m_lostDeviceTimer.Stop();
131 int CWinSystemTVOS::GetDisplayIndexFromSettings()
133   // ATV only supports 1 screen with id = 0
134   return 0;
137 CWinSystemTVOS::CWinSystemTVOS() : CWinSystemBase(), m_lostDeviceTimer(this)
139   m_bIsBackgrounded = false;
140   m_pDisplayLink = new CADisplayLinkWrapper;
141   m_pDisplayLink->callbackClass = [[TVOSDisplayLinkCallback alloc] init];
143   m_winEvents = std::make_unique<CWinEventsTVOS>();
145   CAESinkDARWINTVOS::Register();
148 CWinSystemTVOS::~CWinSystemTVOS()
150   m_pDisplayLink->callbackClass = nil;
151   delete m_pDisplayLink;
154 bool CWinSystemTVOS::InitWindowSystem()
156   return CWinSystemBase::InitWindowSystem();
159 bool CWinSystemTVOS::DestroyWindowSystem()
161   return true;
164 std::unique_ptr<KODI::WINDOWING::IOSScreenSaver> CWinSystemTVOS::GetOSScreenSaverImpl()
166   std::unique_ptr<KODI::WINDOWING::IOSScreenSaver> screensaver =
167       std::make_unique<COSScreenSaverTVOS>();
168   return screensaver;
171 bool CWinSystemTVOS::CreateNewWindow(const std::string& name, bool fullScreen, RESOLUTION_INFO& res)
173   if (!SetFullScreen(fullScreen, res, false))
174     return false;
176   [g_xbmcController setFramebuffer];
178   m_bWindowCreated = true;
180   m_eglext = " ";
182   const char* tmpExtensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
183   if (tmpExtensions != nullptr)
184   {
185     m_eglext += tmpExtensions;
186     m_eglext += " ";
187   }
189   CLog::Log(LOGDEBUG, "EGL_EXTENSIONS: {}", m_eglext);
191   // register platform dependent objects
192   CDVDFactoryCodec::ClearHWAccels();
193   VTB::CDecoder::Register();
194   VIDEOPLAYER::CRendererFactory::ClearRenderer();
195   CLinuxRendererGLES::Register();
196   CRendererVTB::Register();
197   VIDEOPLAYER::CProcessInfoIOS::Register();
198   RETRO::CRPProcessInfoIOS::Register();
199   RETRO::CRPProcessInfoIOS::RegisterRendererFactory(new RETRO::CRendererFactoryOpenGLES);
201   return true;
204 bool CWinSystemTVOS::DestroyWindow()
206   return true;
209 bool CWinSystemTVOS::ResizeWindow(int newWidth, int newHeight, int newLeft, int newTop)
211   if (m_nWidth != newWidth || m_nHeight != newHeight)
212   {
213     m_nWidth = newWidth;
214     m_nHeight = newHeight;
215   }
217   CRenderSystemGLES::ResetRenderSystem(newWidth, newHeight);
219   return true;
222 bool CWinSystemTVOS::SetFullScreen(bool fullScreen, RESOLUTION_INFO& res, bool blankOtherDisplays)
224   m_nWidth = res.iWidth;
225   m_nHeight = res.iHeight;
226   m_bFullScreen = fullScreen;
228   CLog::Log(LOGDEBUG, "About to switch to {} x {} @ {}", m_nWidth, m_nHeight, res.fRefreshRate);
229   SwitchToVideoMode(res.iWidth, res.iHeight, static_cast<double>(res.fRefreshRate));
230   CRenderSystemGLES::ResetRenderSystem(res.iWidth, res.iHeight);
232   return true;
235 bool CWinSystemTVOS::SwitchToVideoMode(int width, int height, double refreshrate)
237   /*! @todo Currently support SDR dynamic range only. HDR shouldn't be done during
238    *  a modeswitch. Look to create supplemental method to handle sdr/hdr enable
239    */
240   [g_xbmcController.displayManager displayRateSwitch:refreshrate
241                                     withDynamicRange:0 /*dynamicRange*/];
242   return true;
245 bool CWinSystemTVOS::GetScreenResolution(int* w, int* h, double* fps, int screenIdx)
247   *w = [g_xbmcController.displayManager getScreenSize].width;
248   *h = [g_xbmcController.displayManager getScreenSize].height;
249   *fps = static_cast<double>([g_xbmcController.displayManager getDisplayRate]);
251   CLog::Log(LOGDEBUG, "Current resolution Screen: {} with {} x {} @ {}", screenIdx, *w, *h, *fps);
252   return true;
255 void CWinSystemTVOS::UpdateResolutions()
257   // Add display resolution
258   int w, h;
259   double fps;
260   CWinSystemBase::UpdateResolutions();
262   int screenIdx = GetDisplayIndexFromSettings();
264   //first screen goes into the current desktop mode
265   if (GetScreenResolution(&w, &h, &fps, screenIdx))
266     UpdateDesktopResolution(CDisplaySettings::GetInstance().GetResolutionInfo(RES_DESKTOP),
267                             CONST_HDMI, w, h, fps, 0);
269   CDisplaySettings::GetInstance().ClearCustomResolutions();
271   //now just fill in the possible resolutions for the attached screens
272   //and push to the resolution info vector
273   FillInVideoModes(screenIdx);
276 void CWinSystemTVOS::FillInVideoModes(int screenIdx)
278   // Potential refresh rates
279   std::vector<float> supportedDispRefreshRates = {23.976f, 24.000f, 25.000f, 29.970f,
280                                                   30.000f, 50.000f, 59.940f, 60.000f};
282   UIScreen* aScreen = UIScreen.screens[screenIdx];
283   UIScreenMode* mode = aScreen.currentMode;
284   int w = mode.size.width;
285   int h = mode.size.height;
287   //! @Todo handle different resolutions than native (ie 720p/1080p on a 4k display)
289   for (float refreshrate : supportedDispRefreshRates)
290   {
291     RESOLUTION_INFO res;
292     UpdateDesktopResolution(res, CONST_HDMI, w, h, refreshrate, 0);
293     CLog::Log(LOGINFO, "Found possible resolution for display {} with {} x {} RefreshRate:{} ",
294               screenIdx, w, h, refreshrate);
296     CServiceBroker::GetWinSystem()->GetGfxContext().ResetOverscan(res);
297     CDisplaySettings::GetInstance().AddResolutionInfo(res);
298   }
301 bool CWinSystemTVOS::IsExtSupported(const char* extension) const
303   if (strncmp(extension, "EGL_", 4) != 0)
304     return CRenderSystemGLES::IsExtSupported(extension);
306   std::string name = ' ' + std::string(extension) + ' ';
308   return m_eglext.find(name) != std::string::npos;
312 bool CWinSystemTVOS::BeginRender()
314   bool rtn;
316   [g_xbmcController setFramebuffer];
318   rtn = CRenderSystemGLES::BeginRender();
319   return rtn;
322 bool CWinSystemTVOS::EndRender()
324   bool rtn;
326   rtn = CRenderSystemGLES::EndRender();
327   return rtn;
330 void CWinSystemTVOS::Register(IDispResource* resource)
332   std::unique_lock<CCriticalSection> lock(m_resourceSection);
333   m_resources.push_back(resource);
336 void CWinSystemTVOS::Unregister(IDispResource* resource)
338   std::unique_lock<CCriticalSection> lock(m_resourceSection);
339   std::vector<IDispResource*>::iterator i = find(m_resources.begin(), m_resources.end(), resource);
340   if (i != m_resources.end())
341     m_resources.erase(i);
344 void CWinSystemTVOS::OnAppFocusChange(bool focus)
346   std::unique_lock<CCriticalSection> lock(m_resourceSection);
347   m_bIsBackgrounded = !focus;
348   CLog::Log(LOGDEBUG, "CWinSystemTVOS::OnAppFocusChange: {}", focus ? 1 : 0);
349   for (auto dispResource : m_resources)
350     dispResource->OnAppFocusChange(focus);
353 //--------------------------------------------------------------
354 //-------------------DisplayLink stuff
355 @implementation TVOSDisplayLinkCallback
356 @synthesize videoSyncImpl;
357 //--------------------------------------------------------------
358 - (void)runDisplayLink
360   @autoreleasepool
361   {
362     if (videoSyncImpl != nullptr)
363       videoSyncImpl->TVosVblankHandler();
364   }
366 @end
368 bool CWinSystemTVOS::InitDisplayLink(CVideoSyncTVos* syncImpl)
370   unsigned int currentScreenIdx = GetDisplayIndexFromSettings();
371   UIScreen* currentScreen = UIScreen.screens[currentScreenIdx];
372   m_pDisplayLink->callbackClass.videoSyncImpl = syncImpl;
373   m_pDisplayLink->impl = [currentScreen displayLinkWithTarget:m_pDisplayLink->callbackClass
374                                                      selector:@selector(runDisplayLink)];
376   [m_pDisplayLink->impl addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
377   return m_pDisplayLink->impl != nil;
380 void CWinSystemTVOS::DeinitDisplayLink(void)
382   if (m_pDisplayLink->impl)
383   {
384     [m_pDisplayLink->impl invalidate];
385     m_pDisplayLink->impl = nil;
386     [m_pDisplayLink->callbackClass SetVideoSyncImpl:nil];
387   }
389 //------------DisplayLink stuff end
390 //--------------------------------------------------------------
392 void CWinSystemTVOS::PresentRenderImpl(bool rendered)
394   //glFlush;
395   if (rendered)
396     [g_xbmcController presentFramebuffer];
399 bool CWinSystemTVOS::HasCursor()
401   return false;
404 void CWinSystemTVOS::NotifyAppActiveChange(bool bActivated)
406   if (bActivated && m_bWasFullScreenBeforeMinimize &&
407       !CServiceBroker::GetWinSystem()->GetGfxContext().IsFullScreenRoot())
408     CServiceBroker::GetAppMessenger()->PostMsg(TMSG_TOGGLEFULLSCREEN);
411 bool CWinSystemTVOS::Minimize()
413   m_bWasFullScreenBeforeMinimize =
414       CServiceBroker::GetWinSystem()->GetGfxContext().IsFullScreenRoot();
415   if (m_bWasFullScreenBeforeMinimize)
416     CServiceBroker::GetAppMessenger()->PostMsg(TMSG_TOGGLEFULLSCREEN);
418   return true;
421 bool CWinSystemTVOS::Restore()
423   return false;
426 bool CWinSystemTVOS::Hide()
428   return true;
431 bool CWinSystemTVOS::Show(bool raise)
433   return true;
436 CVEAGLContext CWinSystemTVOS::GetEAGLContextObj()
438   return [g_xbmcController getEAGLContextObj];
441 std::vector<std::string> CWinSystemTVOS::GetConnectedOutputs()
443   std::vector<std::string> outputs;
444   outputs.emplace_back("Default");
445   outputs.emplace_back(CONST_HDMI);
447   return outputs;
450 bool CWinSystemTVOS::MessagePump()
452   return m_winEvents->MessagePump();