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{
13 Initialise();
14}
15
17{
18 ClearModes();
19}
20
22{
23 QWidget* widget = m_widget;
24
25 if (!widget)
26 {
27 if (!HasMythMainWindow())
28 {
30 return;
31 }
32 widget = qobject_cast<QWidget*>(MythMainWindow::getMainWindow());
33 }
34
35 CGDirectDisplayID disp = GetOSXDisplay(widget->winId());
36 if (!disp)
37 {
39 return;
40 }
41 CGDisplayModeRef mode = CGDisplayCopyDisplayMode(disp);
42 if (!mode)
43 {
45 return;
46 }
47
48 m_modeComplete = true;
49 m_refreshRate = CGDisplayModeGetRefreshRate(mode);
50 m_resolution = QSize(static_cast<int>(CGDisplayModeGetWidth(mode)),
51 static_cast<int>(CGDisplayModeGetHeight(mode)));
52 QByteArray edid = GetOSXEDID(disp);
53 m_edid = MythEDID(edid);
54 //bool interlaced = CGDisplayModeGetIOFlags(mode) & kDisplayModeInterlacedFlag;
55 CGDisplayModeRelease(mode);
56 CGSize sizemm = CGDisplayScreenSize(disp);
57 m_physicalSize = QSize(static_cast<int>(sizemm.width), static_cast<int>(sizemm.height));
58}
59
61{
62 if (gCoreContext)
63 return gCoreContext->GetBoolSetting("UseVideoModes", false);
64 return false;
65}
66
68{
69 if (!m_videoModes.empty() || !HasMythMainWindow())
70 return m_videoModes;
71
72 ClearModes();
73
74 WId win = (qobject_cast<QWidget*>(MythMainWindow::getMainWindow()))->winId();
75 CGDirectDisplayID disp = GetOSXDisplay(win);
76 if (!disp)
77 return m_videoModes;
78 CFArrayRef modes = CGDisplayCopyAllDisplayModes(disp, nullptr);
79 if (!modes)
80 return m_videoModes;
81
82 DisplayModeMap screen_map;
83 CGSize sizemm = CGDisplayScreenSize(disp);
84
85 for (int i = 0; i < CFArrayGetCount(modes); ++i)
86 {
87 auto *mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
88 double rate = CGDisplayModeGetRefreshRate(mode);
89 bool interlaced = CGDisplayModeGetIOFlags(mode) & kDisplayModeInterlacedFlag;
90 int width = static_cast<int>(CGDisplayModeGetWidth(mode));
91 int height = static_cast<int>(CGDisplayModeGetHeight(mode));
92
93 // See note in MythDisplayX11
94 if (interlaced)
95 {
96 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Ignoring interlaced mode %1x%2 %3i")
97 .arg(width).arg(height).arg(rate, 2, 'f', 2, '0'));
98 continue;
99 }
100
101 QSize resolution(width, height);
102 uint64_t key = MythDisplayMode::CalcKey(resolution, 0.0);
103 if (screen_map.find(key) == screen_map.end())
104 screen_map[key] = MythDisplayMode(resolution, QSize(sizemm.width, sizemm.height),
105 -1.0, rate);
106 else
107 screen_map[key].AddRefreshRate(rate);
108 m_modeMap.insert(MythDisplayMode::CalcKey(resolution, rate), CGDisplayModeRetain(mode));
109 }
110
111 CFRelease(modes);
112
113 for (auto & screen : screen_map)
114 m_videoModes.push_back(screen.second);
115 DebugModes();
116 return m_videoModes;
117}
118
119bool MythDisplayOSX::SwitchToVideoMode(QSize Size, double DesiredRate)
120{
121 if (!HasMythMainWindow())
122 return false;
123 WId win = (qobject_cast<QWidget*>(MythMainWindow::getMainWindow()))->winId();
124 CGDirectDisplayID disp = GetOSXDisplay(win);
125 if (!disp)
126 return false;
127
128 auto rate = static_cast<double>(NAN);
129 MythDisplayMode desired(Size, QSize(0, 0), -1.0, DesiredRate);
130 int idx = MythDisplayMode::FindBestMatch(m_videoModes, desired, rate);
131 if (idx < 0)
132 {
133 LOG(VB_GENERAL, LOG_ERR, LOC + "Desired resolution and frame rate not found.");
134 return false;
135 }
136
137 auto mode = MythDisplayMode::CalcKey(Size, rate);
138 if (!m_modeMap.contains(mode))
139 {
140 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to find mode");
141 return false;
142 }
143
144 // switch mode and return success
145 CGDisplayCapture(disp);
146 CGDisplayConfigRef cfg = nullptr;
147 CGBeginDisplayConfiguration(&cfg);
148 CGConfigureDisplayFadeEffect(cfg, 0.3F, 0.5F, 0, 0, 0);
149 CGDisplaySetDisplayMode(disp, m_modeMap.value(mode), nullptr);
150 CGError err = CGCompleteDisplayConfiguration(cfg, kCGConfigureForAppOnly);
151 CGDisplayRelease(disp);
152 return err == kCGErrorSuccess;
153}
154
156{
157 for (auto it = m_modeMap.cbegin(); it != m_modeMap.cend(); ++it)
158 CGDisplayModeRelease(it.value());
159 m_modeMap.clear();
160 m_videoModes.clear();
161}
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)