flutter-pi icon indicating copy to clipboard operation
flutter-pi copied to clipboard

[WIP] Implement DPMS get/setValue (Screen Off/On for KMS)

Open DisDis opened this issue 7 months ago • 3 comments

I added kms drm property set function. The code is dirty, but it works. Any suggestions for improvement?

It allows turn off/on screen.

For my case I use HDMI-0. kmsprint -p show:

Connector 0 (33) HDMI-A-1 (connected)
    EDID (1) = blob-id 678 len 256 (immutable)
    DPMS (2) = 0 (On) [On=0|Standby=1|Suspend=2|Off=3]
    TILE (4) = blob-id 0 (immutable)
    link-status (5) = 0 (Good) [Good=0|Bad=1]

Screen ON:

if (kmsDrmService.isAvailable()) {
  // DPMS (2) = 3 (Off) [On=0|Standby=1|Suspend=2|Off=3]
  kmsDrmService.setProperty(2, 0);
}

Screen OFF:

if (kmsDrmService.isAvailable()) {
  // DPMS (2) = 0 (On) [On=0|Standby=1|Suspend=2|Off=3]
  kmsDrmService.setProperty(2, 3);
}

Service: static final KmsDrmService kmsDrmService = KmsDrmService();

/*
uint32_t KMS_DRM_isAvailable();

void KMS_DRM_setProperty(uint32_t propId, uint64_t value) ;

uint64_t KMS_DRM_getProperty(uint32_t propId);
*/

typedef KMS_DRM_setPropertyFuncType = ffi.Void Function(ffi.Uint32 propId, ffi.Uint64 value);
typedef KMS_DRM_setPropertyType = void Function(int propId, int value);

typedef KMS_DRM_isAvailableFuncType = ffi.Uint32 Function();
typedef KMS_DRM_isAvailableType = int Function();

class KmsDrmService {
  final _KmsDrmService _service = _KmsDrmService.instance;
  bool isAvailable() {
    if (_service.KMS_DRM_isAvailable == null || _service.KMS_DRM_isAvailable!() == 0) {
      return false;
    }
    return true;
  }

  void setProperty(int propId, int value) {
    if (_service.KMS_DRM_setProperty == null) {
      return;
    }
    _service.KMS_DRM_setProperty!(propId, value);
  }
}

class _KmsDrmService {
  final KMS_DRM_setPropertyType? KMS_DRM_setProperty;
  final KMS_DRM_isAvailableType? KMS_DRM_isAvailable;
  _KmsDrmService._constructor({required this.KMS_DRM_setProperty, required this.KMS_DRM_isAvailable});

  factory _KmsDrmService._() {
    final lib = ffi.DynamicLibrary.process();

    try {
      final KMS_DRM_setPropertyLFunc = lib.lookupFunction<KMS_DRM_setPropertyFuncType, KMS_DRM_setPropertyType>("KMS_DRM_setProperty");
      final KMS_DRM_isAvailableLFunc = lib.lookupFunction<KMS_DRM_isAvailableFuncType, KMS_DRM_isAvailableType>("KMS_DRM_isAvailable");

      return _KmsDrmService._constructor(
        KMS_DRM_setProperty: KMS_DRM_setPropertyLFunc,
        KMS_DRM_isAvailable: KMS_DRM_isAvailableLFunc,
      );
    } on ArgumentError {
      return _KmsDrmService._constructor(
        KMS_DRM_setProperty: null,
        KMS_DRM_isAvailable: null,
      );
    }
  }

  static _KmsDrmService? _instance;

  static _KmsDrmService get instance {
    if (_instance == null) {
      _instance = _KmsDrmService._();
    }

    return _instance!;
  }
}

DisDis avatar May 01 '25 19:05 DisDis

I used this example https://github.com/tomba/kmsxx/blob/master/utils/kmsblank.cpp#L77

DisDis avatar May 01 '25 19:05 DisDis

Thanks for the contribution @DisDis !

I think providing support for DPMS & backlight is definitely useful, but a generic way to set KMS properties might be a bit too powerful. It's very easy to shoot yourself in the foot with that and it can easily conflict with flutter-pi's modesetting.

Might be better to provide an abstraction specifically for DPMS (and/or backlight). Just a package where you can do something like:

void main() async {
  final dpms = await DPMS.getInstance(); // optionally allow passing the view id here, for multi-view

  await dpms.setMode(PowerMode.on);
  await Future.delayed(Duration(seconds: 5));
  await dpms.setMode(PowerMode.standby);

  // ...
}

For backlight, one could implement a platform interface for: https://github.com/aaassseee/screen_brightness/

Weston has its own little sub-library to help with backlight: https://gitlab.freedesktop.org/wayland/weston/-/blob/main/libweston/backend-drm/libbacklight.c, that could just be added to the flutter-pi source tree under third_party/libbacklight.

ardera avatar May 02 '25 13:05 ardera

Hi @ardera. I implemented get/setDPMSValue. When this MR merge, I will start implement DPMS package in "flutter_packages"

DisDis avatar May 03 '25 07:05 DisDis