8 #include <xf86drmMode.h>
11 #ifndef DRM_MODE_FLAG_INTERLACE
12 #define DRM_MODE_FLAG_INTERLACE (1<<4)
16 #define LOC QString("MutterDisp: ")
46 Argument.beginStructure();
48 Argument.endStructure();
54 Argument.beginArray(qMetaTypeId<MythMutterOutputOut>());
55 for (
const auto &
output : Outputs)
63 Argument.beginStructure();
65 Argument.endStructure();
71 Argument.beginStructure();
73 Argument.endStructure();
79 Argument.beginStructure();
81 Argument.endStructure();
87 Argument.beginArray(qMetaTypeId<MythMutterCRTCOut>());
88 for (
const auto & crtc : CRTCS)
96 Argument.beginStructure();
97 Argument >> CRTC.
id >> CRTC.
sys_id >> CRTC.
x >> CRTC.
y;
100 Argument.endStructure();
106 Argument.beginArray();
109 while (!Argument.atEnd())
122 Argument.beginStructure();
126 Argument.endStructure();
128 Output.
edid = QByteArray();
133 if (property.first ==
"serial")
134 Output.
serialnumber =
property.second.variant().toString();
135 if (property.first ==
"edid")
136 Output.
edid =
property.second.variant().toByteArray();
137 if (property.first ==
"width-mm")
138 Output.
widthmm =
property.second.variant().toInt();
139 if (property.first ==
"height-mm")
140 Output.
heightmm =
property.second.variant().toInt();
147 Argument.beginArray();
150 while (!Argument.atEnd())
163 Argument.beginStructure();
165 Argument >>
Mode.frequency >>
Mode.flags;
166 Argument.endStructure();
172 Argument.beginArray();
175 while (!Argument.atEnd())
193 static bool s_checked(
false);
194 static bool s_available(
false);
199 qDBusRegisterMetaType<MythMutterCRTCOut>();
200 qDBusRegisterMetaType<MythMutterOutputOut>();
204 if (mutter.isValid())
210 QDBusMessage res = mutter.call(
"GetResources");
211 QList<QVariant>
args = res.arguments();
214 uint serial =
args[0].toUInt() + 100;
217 QDBusArgument crtcsarg;
218 QDBusArgument outarg;
219 QDBusReply<void> reply = mutter.call(QLatin1String(
"ApplyConfiguration"),
221 QVariant::fromValue(crtcsarg << crtcs),
222 QVariant::fromValue(outarg << outputs));
223 if (reply.error().type() == QDBusError::UnknownMethod)
225 LOG(VB_GENERAL, LOG_WARNING,
LOC +
226 "org.gnome.Mutter.DisplayConfig.ApplyConfiguration not implemented");
228 else if (reply.error().type() == QDBusError::AccessDenied)
247 if (result->IsValid())
288 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Monitors changed");
310 for (
auto & mode :
output.modes)
320 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Ignoring interlaced mode %1x%2 %3i")
326 QSize resolution(
static_cast<int32_t
>(mmode.
width),
327 static_cast<int32_t
>(mmode.
height));
330 if (screenmap.find(key) == screenmap.end())
333 screenmap[key].AddRefreshRate(rate);
337 for (
auto & it : screenmap)
363 QDBusMessage reply =
m_interface->call(
"GetResources");
367 QList<QVariant>
args = reply.arguments();
368 if (
args.size() == 6)
374 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to register for MonitorsChanged");
378 LOG(VB_GENERAL, LOG_ERR,
LOC +
"GetResources unexpected reply");
382 LOG(VB_GENERAL, LOG_ERR,
LOC +
"GetResources signature not recognised");
396 auto rate =
static_cast<double>(NAN);
403 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Desired resolution and frame rate not found.");
410 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to find mode");
418 if ((crtc.currentmode < 0) || (crtc.width < 1) || (crtc.height < 1))
422 crtcout.
id = crtc.id;
423 crtcout.
new_mode = crtc.currentmode;
426 crtcout.
transform = crtc.currenttransform;
427 crtcout.
outputs = QList<uint32_t>();
429 crtcs.append(crtcout);
433 QDBusArgument crtcsarg;
434 QDBusArgument outarg;
435 QDBusReply<void> reply =
m_interface->call(QLatin1String(
"ApplyConfiguration"),
437 QVariant::fromValue(crtcsarg << crtcs),
438 QVariant::fromValue(outarg << outputs));
439 if (!reply.isValid())
441 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Error applying new display configuration ('%1: %2')")
442 .arg(reply.error().type()).arg(reply.error().message()));
448 QDBusMessage resources =
m_interface->call(
"GetResources");
449 QList<QVariant>
args = resources.arguments();
452 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to get updated DisplayConfig serial"
453 " - further display changes may fail");
475 QDBusMessage reply =
m_interface->call(
"GetResources");
476 QList<QVariant>
args = reply.arguments();
485 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"CRTC %1/%2: %3x%4+%5+%6 Mode: %7")
486 .arg(crtc.id).arg(crtc.sys_id).arg(crtc.width)
487 .arg(crtc.height).arg(crtc.x).arg(crtc.y).arg(crtc.currentmode));
493 QStringList possiblecrtcs;
494 for (
auto poss : qAsConst(
output.possible_crtcs))
495 possiblecrtcs.append(QString::number(poss));
497 for (
auto mode : qAsConst(
output.modes))
498 modes.append(QString::number(mode));
500 for (
const auto& prop : qAsConst(
output.properties))
501 props.append(QString(
"%1:%2").arg(prop.first, prop.second.variant().toString()));
502 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
503 QString(
"Output %1/%2: CRTC: %3 Possible CRTCs: %4 Name: '%5'")
505 .arg(possiblecrtcs.join(
","),
output.name));
506 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
507 QString(
"Output %1/%2: Modes: %3")
508 .arg(
output.id).arg(
output.sys_id).arg(modes.join(
",")));
509 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
510 QString(
"Output %1/%2: Properties: %3")
511 .arg(
output.id).arg(
output.sys_id).arg(props.join(
",")));
517 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
518 QString(
"Mode %1/%2: %3x%4@%5 Flags: 0x%6")
519 .arg(mode.id).arg(mode.sys_id).arg(mode.width)
520 .arg(mode.height).arg(mode.frequency).arg(mode.flags, 0, 16));
525 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"No connected outputs");
538 auto serial =
m_screen->serialNumber();
539 if (serial.isEmpty())
541 LOG(VB_GENERAL, LOG_INFO,
LOC +
"No serial number to search for - using first output");
550 if (
output.serialnumber == serial)
552 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Matched serial '%1' to device '%2'")
553 .arg(serial,
output.name));
562 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to match display serial - using first device");
574 static_cast<int>(
m_modes[mode].height));