Files
pyramid/lib/features/voice_channel/voice_channel_service.dart
T
Bernd SteckmeisterandClaude Opus 5.5 441cc6ef54 fix(calls): Bildschirmübertragung ohne Absturz, Lautsprecher, Mikrofon im Hintergrund, zurück in den Anruf
Bernds Anruftest Handy↔PC (2026-10-07):
- Teilen am Handy: App "verkleinerte sich", Anruf danach weg. Ursache:
  Android 14+ verlangt vor MediaProjection einen Vordergrunddienst vom Typ
  mediaProjection; flutter_webrtc startet keinen, der Manifest-Eintrag
  verwies auf eine nicht mehr existierende Klasse. Neu: CallService
  (microphone|mediaProjection) + CallForeground: Zustimmung → Dienst
  (wartet auf echten startForeground) → Mitschnitt. Emulator-Test (Android
  16): mit Fix 1080x2400@30 läuft; Gegenprobe ohne Dienst wirft genau
  'Media projections require a foreground service ...'.
- Dienst läuft während jedes Anrufs: Mikrofon bleibt im Hintergrund aktiv,
  Benachrichtigung "Anruf läuft" führt zurück. Mikrofon-Typ nur mit
  Berechtigung, sonst schmalere Variante statt Dienst-Abbruch.
- Handy hörte nichts: SDK schaltet Sprachanrufe auf die Hörmuschel. Jetzt
  Lautsprecher als Standard (wie Discord) + Umschalter in der Anrufleiste.
- LiveKit-Teilen am Handy öffnete den PC-Quellen-Auswähler → System-Dialog.
- Im offenen Chat (Handy) Leiste "Anruf läuft · Zurück".
- Einstellungen → Sprache & Video: Mikrofontest mit Pegel (PC-Diagnose:
  das Standardgerät lieferte nur Stille – Voicemeeter/virtuelle Geräte).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-08 00:01:29 +02:00

81 lines
2.9 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:livekit_client/livekit_client.dart' as lk;
import 'package:matrix/matrix.dart' hide Room;
import 'package:pyramid/features/voice_channel/livekit_call_manager.dart';
/// Öffentliche Schnittstelle des Moduls `voice_channel` – LiveKit-SFU-basierte,
/// dauerhafte Voice-Channels (Discord-artig: Presence über Matrix-State-Events,
/// Screensharing, Mehrpersonen). Schnitt nach `docs/M2_MODULE_SCHNITT.md`;
/// bewusst GETRENNT vom 1:1-Modul `call_signaling`, siehe dort.
///
/// Andere Module konsumieren ausschließlich diese Schnittstelle über
/// [voiceChannelProvider] – nie `livekit_call_manager.dart` direkt.
///
/// Bewusste Abweichungen vom Entwurf im Doc (Verhaltensgleichheit vor
/// Schönheit): ChangeNotifier statt `stateStream`, Methodennamen wie im
/// Bestand (`startCall`/`hangUp` statt `join`/`leave`), und [room] bleibt
/// als LiveKit-Typ sichtbar, weil die Teilnehmer-Kacheln der UI direkt
/// LiveKit-Tracks rendern (analog zu den WebRTC-Renderern im Signaling).
abstract class VoiceChannelService extends ChangeNotifier {
bool get isActive;
bool get isConnecting;
String? get error;
bool get isMuted;
bool get isCameraOff;
bool get isScreenSharing;
bool get isDeafened;
bool get isVoiceChannel;
/// Der verbundene LiveKit-Raum (null = nicht verbunden).
lk.Room? get room;
/// Matrix-Raum-ID des aktiven Voice-Channels.
String? get currentRoomId;
String get displayName;
/// Sende-Qualität ('sd' | 'hd' | 'hd60' | 'fhd' | 'fhd60' | '4k').
/// Die *60-Presets sind für flüssiges Bildschirm-Streaming (M4).
String get currentQualityKey;
/// Empfangs-Qualität ('auto' | 'low' | 'medium' | 'high').
String get subscribeQualityKey;
Future<void> startCall({
required String roomName,
required String roomDisplayName,
required String identity,
bool audioOnly,
bool voiceChannel,
Client? matrixClient,
String? matrixRoomId,
});
Future<void> hangUp();
Future<void> toggleMute();
/// Handy: Ton über den Lautsprecher (true) oder die Hörmuschel (false).
/// Auf dem PC ohne Bedeutung.
bool get isSpeakerOn => true;
Future<void> toggleSpeaker() async {}
Future<void> toggleDeafen();
Future<void> toggleCamera();
Future<void> toggleScreenShare();
Future<void> startScreenShare(String sourceId);
Future<void> stopScreenShare();
Future<void> changeQuality(String qualityKey);
Future<void> setSubscribeQuality(String key);
/// Live-Anwendung des Lautstärke-Sliders auf alle Remote-Audio-Tracks.
Future<void> setOutputVolume(double v);
Future<void> changeAudioInput(String deviceId);
void setRemoteVolume(double volume);
}
/// Einziger Zugriffsweg der UI auf das Voice-Channel-Modul.
final voiceChannelProvider =
ChangeNotifierProvider<VoiceChannelService>((ref) {
return LiveKitCallManager.instance;
});