MythTV  master
mythdisplayosx.cpp
Go to the documentation of this file.
1 // MythTV
2 #include "config.h"
3 #include "mythcorecontext.h"
4 #include "mythmainwindow.h"
5 #include "mythdisplayosx.h"
6 #import "mythosxutils.h"
7 #import "mythutilscocoa.h"
8 
9 #define LOC QString("DisplayOSX: ")
10 
12  : MythDisplay()
13 {
14  Initialise();
15 }
16 
18 {
19  ClearModes();
20 }
21 
23 {
24  QWidget* widget = m_widget;
25 
26  if (!widget)
27  {
28  if (!HasMythMainWindow())
29  {
31  return;
32  }
33  widget = qobject_cast<QWidget*>(MythMainWindow::getMainWindow());
34  }
35 
36  CGDirectDisplayID disp = GetOSXDisplay(widget->winId());
37  if (!disp)
38  {
40  return;
41  }
42  CGDisplayModeRef mode = CGDisplayCopyDisplayMode(disp);
43  if (!mode)
44  {
46  return;
47  }
48 
49  m_modeComplete = true;
50  m_refreshRate = CGDisplayModeGetRefreshRate(mode);
51  m_resolution = QSize(static_cast<int>(CGDisplayModeGetWidth(mode)),
52  static_cast<int>(CGDisplayModeGetHeight(mode)));
53  QByteArray edid = GetOSXEDID(disp);
54  m_edid = MythEDID(edid);
55  //bool interlaced = CGDisplayModeGetIOFlags(mode) & kDisplayModeInterlacedFlag;
56  CGDisplayModeRelease(mode);
57  CGSize sizemm = CGDisplayScreenSize(disp);
58  m_physicalSize = QSize(static_cast<int>(sizemm.width), static_cast<int>(sizemm.height));
59 }
60 
62 {
63  if (gCoreContext)
64  return gCoreContext->GetBoolSetting("UseVideoModes", false);
65  return false;
66 }
67 
68 const std::vector<MythDisplayMode>& MythDisplayOSX::GetVideoModes(void)
69 {
70  if (!m_videoModes.empty() || !HasMythMainWindow())
71  return m_videoModes;
72 
73  ClearModes();
74 
75  WId win = (qobject_cast<QWidget*>(MythMainWindow::getMainWindow()))->winId();
76  CGDirectDisplayID disp = GetOSXDisplay(win);
77  if (!disp)
78  return m_videoModes;
79  CFArrayRef modes = CGDisplayCopyAllDisplayModes(disp, nullptr);
80  if (!modes)
81  return m_videoModes;
82 
83  DisplayModeMap screen_map;
84  CGSize sizemm = CGDisplayScreenSize(disp);
85 
86  for (int i = 0; i < CFArrayGetCount(modes); ++i)
87  {
88  CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
89  double rate = CGDisplayModeGetRefreshRate(mode);
90  bool interlaced = CGDisplayModeGetIOFlags(mode) & kDisplayModeInterlacedFlag;
91  int width = static_cast<int>(CGDisplayModeGetWidth(mode));
92  int height = static_cast<int>(CGDisplayModeGetHeight(mode));
93 
94  // See note in MythDisplayX11
95  if (interlaced)
96  {
97  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Ignoring interlaced mode %1x%2 %3i")
98  .arg(width).arg(height).arg(rate, 2, 'f', 2, '0'));
99  continue;
100  }
101 
102  QSize resolution(width, height);
103  uint64_t key = MythDisplayMode::CalcKey(resolution, 0.0);
104  if (screen_map.find(key) == screen_map.end())
105  screen_map[key] = MythDisplayMode(resolution, QSize(sizemm.width, sizemm.height),
106  -1.0, rate);
107  else
108  screen_map[key].AddRefreshRate(rate);
109  m_modeMap.insert(MythDisplayMode::CalcKey(resolution, rate), CGDisplayModeRetain(mode));
110  }
111 
112  CFRelease(modes);
113 
114  for (auto it = screen_map.begin(); screen_map.end() != it; ++it)
115  m_videoModes.push_back(it->second);
116  DebugModes();
117  return m_videoModes;
118 }
119 
120 bool MythDisplayOSX::SwitchToVideoMode(QSize Size, double DesiredRate)
121 {
122  if (!HasMythMainWindow())
123  return false;
124  WId win = (qobject_cast<QWidget*>(MythMainWindow::getMainWindow()))->winId();
125  CGDirectDisplayID disp = GetOSXDisplay(win);
126  if (!disp)
127  return false;
128 
129  auto rate = static_cast<double>(NAN);
130  MythDisplayMode desired(Size, QSize(0, 0), -1.0, DesiredRate);
131  int idx = MythDisplayMode::FindBestMatch(m_videoModes, desired, rate);
132  if (idx < 0)
133  {
134  LOG(VB_GENERAL, LOG_ERR, LOC + "Desired resolution and frame rate not found.");
135  return false;
136  }
137 
138  auto mode = MythDisplayMode::CalcKey(Size, rate);
139  if (!m_modeMap.contains(mode))
140  {
141  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find mode");
142  return false;
143  }
144 
145  // switch mode and return success
146  CGDisplayCapture(disp);
147  CGDisplayConfigRef cfg;
148  CGBeginDisplayConfiguration(&cfg);
149  CGConfigureDisplayFadeEffect(cfg, 0.3f, 0.5f, 0, 0, 0);
150  CGDisplaySetDisplayMode(disp, m_modeMap.value(mode), nullptr);
151  CGError err = CGCompleteDisplayConfiguration(cfg, kCGConfigureForAppOnly);
152  CGDisplayRelease(disp);
153  return err == kCGErrorSuccess;
154 }
155 
157 {
158  for (auto it = m_modeMap.cbegin(); it != m_modeMap.cend(); ++it)
159  CGDisplayModeRelease(it.value());
160  m_modeMap.clear();
161  m_videoModes.clear();
162 }
static MythMainWindow * getMainWindow(bool useDB=true)
Return the existing main window, or create one.
virtual void UpdateCurrentMode(void)
Retrieve screen details.
map< uint64_t, MythDisplayMode > DisplayModeMap
vector< MythDisplayMode > m_videoModes
Definition: mythdisplay.h:92
static uint64_t CalcKey(QSize Size, double Rate)
MythEDID m_edid
Definition: mythdisplay.h:88
void ClearModes(void)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QSize m_resolution
Definition: mythdisplay.h:86
void Initialise(void)
#define LOC
bool m_modeComplete
Definition: mythdisplay.h:83
~MythDisplayOSX() override
void AddRefreshRate(double Rate)
CGDirectDisplayID GetOSXDisplay(WId win)
bool HasMythMainWindow(void)
bool UsingVideoModes(void) override
static int FindBestMatch(const vector< MythDisplayMode > &Modes, const MythDisplayMode &Mode, double &TargetRate)
void UpdateCurrentMode(void) override
Retrieve screen details.
bool SwitchToVideoMode(QSize Size, double DesiredRate) override
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
bool GetBoolSetting(const QString &key, bool defaultval=false)
void DebugModes(void) const
const std::vector< MythDisplayMode > & GetVideoModes(void) override
QSize m_physicalSize
Definition: mythdisplay.h:87
QMap< uint64_t, CGDisplayModeRef > m_modeMap
QWidget * m_widget
Definition: mythdisplay.h:89
QByteArray GetOSXEDID(CGDirectDisplayID Display)
double m_refreshRate
Definition: mythdisplay.h:84