JJ_MKVMaker/lib/services/system_usage.dart

94 lines
2.6 KiB
Dart

import 'dart:async';
import 'package:flutter/foundation.dart';
/// PC 전체의 CPU · 메모리 사용량 (한 번 잰 값)
class UsageSample {
/// 0.0 ~ 1.0
final double cpu;
final int memUsed, memTotal;
/// 다운로드 대상 디스크의 남은 용량 · 전체 용량 (바이트, 알 수 없으면 null) 과 그 드라이브 (예: "M:")
final int? diskFree, diskTotal;
final String disk;
const UsageSample({
required this.cpu,
required this.memUsed,
required this.memTotal,
this.diskFree,
this.diskTotal,
this.disk = '',
});
double get mem => memTotal <= 0 ? 0 : memUsed / memTotal;
/// 디스크가 거의 찼는지: 남은 용량이 5% 미만이거나 10GB 미만
bool get diskLow =>
diskFree != null &&
(diskFree! < 10 * 1024 * 1024 * 1024 || (diskTotal != null && diskTotal! > 0 && diskFree! / diskTotal! < 0.05));
}
/// 사용량을 읽는 경계.
/// Windows: platform/windows/windows_usage.dart · 그 밖: 없음 (표시 숨김)
abstract class SystemUsage {
/// 지난번 호출 이후의 CPU 사용률과 지금 메모리. 아직 알 수 없으면 (첫 호출) null.
UsageSample? read();
/// [path] 가 있는 디스크의 (남은 용량, 전체 용량). 알 수 없으면 null.
(int, int)? disk(String path);
}
/// 일정 간격으로 사용량을 읽어 알려 준다 (위쪽 막대의 CPU · MEM 표시)
class UsageMonitor extends ValueNotifier<UsageSample?> {
final SystemUsage source;
final Duration interval;
/// 용량을 볼 디스크의 경로 (다운로드 폴더가 있는 드라이브, 예: "M:\\")
final String Function()? diskPath;
Timer? _timer;
UsageMonitor(this.source, {this.interval = const Duration(seconds: 2), this.diskPath}) : super(null);
// 보는 화면이 있을 때만 잰다
@override
void addListener(VoidCallback listener) {
super.addListener(listener);
if (_timer == null) {
_tick();
_timer = Timer.periodic(interval, (_) => _tick());
}
}
@override
void removeListener(VoidCallback listener) {
super.removeListener(listener);
if (!hasListeners) {
_timer?.cancel();
_timer = null;
}
}
void _tick() {
try {
final s = source.read();
if (s == null) return;
final path = diskPath?.call() ?? '';
final d = path.isEmpty ? null : source.disk(path);
value = UsageSample(
cpu: s.cpu,
memUsed: s.memUsed,
memTotal: s.memTotal,
diskFree: d?.$1,
diskTotal: d?.$2,
disk: path.replaceAll(RegExp(r'[\\/]+$'), ''),
);
} catch (_) {}
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
}