MythTV master
mythdisplayosx.cpp
Go to the documentation of this file.
1// MythTV
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
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
120bool 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}
bool GetBoolSetting(const QString &key, bool defaultval=false)
static int FindBestMatch(const MythDisplayModes &Modes, const MythDisplayMode &Mode, double &TargetRate)
static uint64_t CalcKey(QSize Size, double Rate)
~MythDisplayOSX() override
QMap< uint64_t, CGDisplayModeRef > m_modeMap
const MythDisplayModes & GetVideoModes(void) override
void ClearModes(void)
bool UsingVideoModes(void) override
void UpdateCurrentMode(void) override
Retrieve screen details.
bool SwitchToVideoMode(QSize Size, double DesiredRate) override
QWidget * m_widget
Definition: mythdisplay.h:95
QSize m_resolution
Definition: mythdisplay.h:92
virtual void UpdateCurrentMode()
Retrieve screen details.
QSize m_physicalSize
Definition: mythdisplay.h:93
void Initialise()
double m_refreshRate
Definition: mythdisplay.h:90
MythDisplayModes m_videoModes
Definition: mythdisplay.h:98
MythEDID m_edid
Definition: mythdisplay.h:94
bool m_modeComplete
Definition: mythdisplay.h:89
void DebugModes() const
static MythMainWindow * getMainWindow(bool UseDB=true)
Return the existing main window, or create one.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
std::map< uint64_t, MythDisplayMode > DisplayModeMap
std::vector< MythDisplayMode > MythDisplayModes
#define LOC
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
bool HasMythMainWindow(void)
CGDirectDisplayID GetOSXDisplay(WId win)
QByteArray GetOSXEDID(CGDirectDisplayID Display)