aves_mio0.31/lib/widgets/cast/cast_controller.dart
2026-07-18 13:39:22 +02:00

147 lines
4.5 KiB
Dart

// lib/widgets/cast/cast_controller.dart
// NUOVA VERSIONE MODULARE
// - Orchestratore leggero
// - Nessuna logica Google/DLNA/FAST
// - Delega tutto ai backend specializzati
import 'package:flutter/material.dart';
import 'package:aves/model/entry/entry.dart';
import 'backends/google_cast_backend.dart';
import 'backends/fast_cast_backend.dart';
import 'backends/dlna_cast_backend.dart';
import 'google_cast_controller.dart';
import 'package:shared_preferences/shared_preferences.dart';
enum CastBackend { google, fast, dlna }
enum CastIconState { idle, connecting, connected }
class CastController {
CastController._();
static final CastController instance = CastController._();
static const _prefBackend = 'cast_backend';
// Stato UI unificato (rimane qui)
final castIconState = ValueNotifier(CastIconState.idle);
final isCastingNotifier = ValueNotifier(false);
final currentIndexNotifier = ValueNotifier(0);
final isPlayingNotifier = ValueNotifier(false);
final isBufferingNotifier = ValueNotifier(false);
final positionNotifier = ValueNotifier(Duration.zero);
final durationNotifier = ValueNotifier(Duration.zero);
final volumeNotifier = ValueNotifier(1.0);
final isMutedNotifier = ValueNotifier(false);
// Backend selezionato (persistenza opzionale)
final backendNotifier = ValueNotifier(CastBackend.google);
// Backend attivo
late CastBackendBase backend;
// ------------------------------------------------------------
// SELEZIONE BACKEND
// ------------------------------------------------------------
Future<void> setBackend(CastBackend type) async {
backendNotifier.value = type;
// Persistenza
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_prefBackend, type.name);
// Ricrea backend
switch (type) {
case CastBackend.google:
backend = GoogleCastBackend(this);
GoogleCastController.instance.activateMethodChannelHandler();
break;
case CastBackend.fast:
backend = FastCastBackend(this);
// FAST non deve toccare il MethodChannel Google
break;
case CastBackend.dlna:
backend = DlnaCastBackend(this);
// DLNA non deve toccare il MethodChannel Google
break;
}
// Reset stato icona
castIconState.value = CastIconState.idle;
isCastingNotifier.value = false;
}
Future<void> loadSavedBackend() async {
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString(_prefBackend);
CastBackend type;
switch (saved) {
case 'google':
type = CastBackend.google;
break;
case 'fast':
type = CastBackend.fast;
break;
case 'dlna':
type = CastBackend.dlna;
break;
default:
type = CastBackend.google;
}
await setBackend(type);
}
// ------------------------------------------------------------
// API UNIFICATA (DELEGA AI BACKEND)
// ------------------------------------------------------------
Future<void> startCast(List<AvesEntry> entries, int index) =>
backend.startCast(entries, index);
Future<void> startFullscreen(List<AvesEntry> entries, int index) =>
backend.startFullscreen(entries, index);
Future<void> startSlideshow(List<AvesEntry> entries, int index) =>
backend.startSlideshow(entries, index);
Future<void> startManualQueue(List<AvesEntry> entries, int index) =>
backend.startManualQueue(entries, index);
Future<void> nextManual() => backend.nextManual();
Future<void> prevManual() => backend.prevManual();
Future<void> stopCast() => backend.stopCast();
// ------------------------------------------------------------
// Accesso diretto al controller Google Cast (per dialog Android)
// ------------------------------------------------------------
GoogleCastController get google => GoogleCastController.instance;
}
// ------------------------------------------------------------
// CLASSE BASE PER TUTTI I BACKEND
// ------------------------------------------------------------
abstract class CastBackendBase {
final CastController controller;
CastBackendBase(this.controller);
Future<void> startCast(List<AvesEntry> entries, int index);
Future<void> startFullscreen(List<AvesEntry> entries, int index);
Future<void> startSlideshow(List<AvesEntry> entries, int index);
Future<void> startManualQueue(List<AvesEntry> entries, int index);
Future<void> nextManual();
Future<void> prevManual();
Future<void> stopCast();
// PATCH: ogni backend decide il delay dello slideshow
Duration? getNextDelay(AvesEntry entry);
}