Files
open-vinyl/lib/services/media_service.dart
T
2026-05-18 09:41:39 +01:00

99 lines
3.3 KiB
Dart

// lib/services/media_service.dart
import 'dart:typed_data';
import 'package:flutter/services.dart';
import '../models/media_info.dart';
// Uncomment when adding widgets:
// import 'package:home_widget/home_widget.dart';
class MediaService {
static const _methodChannel = MethodChannel('pt.ruifpb.openvinyl/media_control');
static const _eventChannel = EventChannel('pt.ruifpb.openvinyl/media_events');
Stream<MediaInfo>? _mediaStream;
Stream<MediaInfo> get mediaStream {
_mediaStream ??= _eventChannel
.receiveBroadcastStream()
.map(_parseEvent)
.where((info) => info != null)
.cast<MediaInfo>();
return _mediaStream!;
}
Future<bool> hasPermission() async {
try {
return await _methodChannel.invokeMethod<bool>('hasPermission') ?? false;
} on PlatformException catch (e) {
print('MediaService.hasPermission error: $e');
return false;
}
}
Future<void> requestPermission() async {
try {
await _methodChannel.invokeMethod('requestPermission');
} on PlatformException catch (e) {
print('MediaService.requestPermission error: $e');
}
}
Future<MediaInfo> getCurrentMedia() async {
try {
final data = await _methodChannel.invokeMethod<Map>('getCurrentMedia');
if (data == null) return MediaInfo.empty;
return _parseMap(Map<String, dynamic>.from(data));
} on PlatformException catch (e) {
print('MediaService.getCurrentMedia error: $e');
return MediaInfo.empty;
}
}
/// Sends a play or pause command to the active MediaSession.
/// Android decides which based on the current playback state,
/// so this is a true toggle.
Future<void> playPause() async {
try {
await _methodChannel.invokeMethod('playPause');
} on PlatformException catch (e) {
print('MediaService.playPause error: $e');
}
}
// ─── Private helpers ──────────────────────────────────────────────────────
MediaInfo? _parseEvent(dynamic event) {
if (event == null) return null;
try {
final map = Map<String, dynamic>.from(event as Map);
final info = _parseMap(map);
// _pushToWidget(info); // uncomment when adding widgets
return info;
} catch (e) {
print('MediaService._parseEvent error: $e');
return null;
}
}
MediaInfo _parseMap(Map<String, dynamic> map) {
Uint8List? albumArt;
if (map['albumArt'] != null) {
albumArt = Uint8List.fromList(List<int>.from(map['albumArt']));
}
return MediaInfo(
title: map['title'] as String? ?? 'Unknown Title',
artist: map['artist'] as String? ?? 'Unknown Artist',
album: map['album'] as String? ?? '',
albumArt: albumArt,
isPlaying: map['isPlaying'] as bool? ?? false,
);
}
// ── WIDGET HOOK ────────────────────────────────────────────────────────────
// Future<void> _pushToWidget(MediaInfo info) async {
// await HomeWidget.saveWidgetData('title', info.title);
// await HomeWidget.saveWidgetData('artist', info.artist);
// await HomeWidget.updateWidget(androidName: 'VinylWidgetReceiver');
// }
}