casting works!

just need to add session key check and remote video controls
This commit is contained in:
bwees 2025-05-19 15:47:24 -05:00
parent 4d86773ffe
commit f5ed1360e6
No known key found for this signature in database
5 changed files with 49 additions and 16 deletions

View File

@ -119,6 +119,13 @@ class GalleryViewerPage extends HookConsumerWidget {
const [],
);
useEffect(() {
final asset = loadAsset(currentIndex.value);
ref.read(castProvider.notifier).loadMedia(asset, false);
}, [
ref.watch(castProvider).isCasting,
]);
void showInfo() {
final asset = ref.read(currentAssetProvider);
if (asset == null) {

View File

@ -14,6 +14,8 @@ class GCastRepository {
void Function(CastSessionState)? onCastStatus;
void Function(Map<String, dynamic>)? onCastMessage;
Map<String, dynamic>? _receiverStatus;
GCastRepository();
Future<void> connect(CastDevice device) async {
@ -26,6 +28,9 @@ class GCastRepository {
_castSession?.messageStream.listen((message) {
onCastMessage?.call(message);
if (message['type'] == 'RECEIVER_STATUS') {
_receiverStatus = message;
}
});
// open the default receiver
@ -38,6 +43,14 @@ class GCastRepository {
}
Future<void> disconnect() async {
final sessionID =
_receiverStatus?['status']['applications'][0]['sessionId'];
sendMessage(CastSession.kNamespaceReceiver, {
'type': "STOP",
"sessionId": sessionID,
});
await _castSession?.close();
}

View File

@ -1,5 +1,6 @@
import 'package:cast/device.dart';
import 'package:cast/session.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
@ -55,12 +56,6 @@ class GCastService implements ICastDestinationService {
void _onCastMessageCallback(Map<String, dynamic> message) {
final msgType = message['type'];
print(message);
if (msgType == 'RECEIVER_STATUS') {
print("Got receiver status");
}
}
Future<void> connect(CastDevice device) async {
@ -99,8 +94,6 @@ class GCastService implements ICastDestinationService {
@override
void loadMedia(Asset asset, bool reload) async {
print("Casting media: ${asset.remoteId}");
if (!isConnected) {
return;
} else if (asset.remoteId == null) {
@ -119,7 +112,7 @@ class GCastService implements ICastDestinationService {
);
final unauthenticatedUrl = asset.isVideo
? getOriginalUrlForRemoteId(
? getPlaybackUrlForRemoteId(
asset.remoteId!,
)
: getThumbnailUrlForRemoteId(
@ -142,14 +135,12 @@ class GCastService implements ICastDestinationService {
"type": "LOAD",
"media": {
"contentId": authenticatedURL,
"streamType": "LIVE",
"streamType": "BUFFERED",
"contentType": mimeType,
"contentUrl": authenticatedURL,
},
"autoplay": true,
});
print("Sending message: $authenticatedURL");
}
@override

View File

@ -73,6 +73,10 @@ String getThumbnailUrlForRemoteId(
return '${Store.get(StoreKey.serverEndpoint)}/assets/$id/thumbnail?size=${type.value}';
}
String getPlaybackUrlForRemoteId(final String id) {
return '${Store.get(StoreKey.serverEndpoint)}/assets/$id/video/playback?';
}
String getFaceThumbnailUrl(final String personId) {
return '${Store.get(StoreKey.serverEndpoint)}/people/$personId/thumbnail';
}

View File

@ -12,6 +12,14 @@ class CastDialog extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final castManager = ref.watch(castProvider);
bool isCurrentDevice(String deviceName) {
return castManager.receiverName == deviceName && castManager.isCasting;
}
bool isDeviceConnecting(String deviceName) {
return castManager.receiverName == deviceName && !castManager.isCasting;
}
return AlertDialog(
title: const Text(
"cast",
@ -53,7 +61,7 @@ class CastDialog extends ConsumerWidget {
title: Text(
deviceName,
style: TextStyle(
color: castManager.receiverName == deviceName
color: isCurrentDevice(deviceName)
? context.colorScheme.primary
: null,
),
@ -62,12 +70,22 @@ class CastDialog extends ConsumerWidget {
type == CastDestinationType.googleCast
? Icons.cast
: Icons.cast_connected,
color: isCurrentDevice(deviceName)
? context.colorScheme.primary
: null,
),
trailing: castManager.isCasting &&
castManager.receiverName == deviceName
trailing: isCurrentDevice(deviceName)
? Icon(Icons.check, color: context.colorScheme.primary)
: null,
: isDeviceConnecting(deviceName)
? const CircularProgressIndicator()
: null,
onTap: () {
// dont accept taps if the device is already connected or is connecting now
if (isDeviceConnecting(deviceName) ||
castManager.isCasting) {
return;
}
ref.read(castProvider.notifier).connect(type, deviceObj);
},
);