Skip to content

Commit

Permalink
[trtc][flutter] Add Windows screen sharing functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
iveshzf authored and MinTate committed May 24, 2024
1 parent f15f004 commit 29edcfe
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 2 deletions.
70 changes: 70 additions & 0 deletions TRTC-Simple-Demo/lib/ui/bgra_image.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';

class BgraImage extends StatefulWidget {
final Uint8List? bgraData;
final int width;
final int height;

BgraImage({
Key? key,
required this.bgraData,
required this.width,
required this.height,
}) : super(key: key);

@override
_BgraImageState createState() => _BgraImageState();
}

class _BgraImageState extends State<BgraImage> {
late Future<ui.Image?> _imageFuture;

@override
void initState() {
super.initState();
if (widget.bgraData != null) {
_imageFuture = _bgraToImage(widget.bgraData!, widget.width, widget.height);
} else {
_imageFuture = Future.value(null);
}
}

Future<ui.Image?> _bgraToImage(Uint8List bgraData, int width, int height) async {
final completer = Completer<ui.Image>();

ui.decodeImageFromPixels(
bgraData,
width,
height,
ui.PixelFormat.bgra8888,
(ui.Image image) {
completer.complete(image);
},
);

return completer.future;
}

@override
Widget build(BuildContext context) {
return FutureBuilder<ui.Image?>(
future: _imageFuture,
builder: (BuildContext context, AsyncSnapshot<ui.Image?> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data != null) {
return RawImage(
image: snapshot.data!,
);
} else {
return Container(color: Colors.black);
}
} else {
return CircularProgressIndicator();
}
},
);
}
}
38 changes: 36 additions & 2 deletions TRTC-Simple-Demo/lib/ui/meeting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import 'package:trtc_demo/ui/login.dart';
import 'package:trtc_demo/models/meeting_model.dart';
import 'package:trtc_demo/debug/GenerateTestUserSig.dart';
import 'package:provider/provider.dart';
import 'package:trtc_demo/ui/window_dialog.dart';
import 'package:replay_kit_launcher/replay_kit_launcher.dart';

const iosAppGroup = 'group.com.tencent.comm.trtc.demo';
Expand Down Expand Up @@ -349,20 +350,53 @@ class MeetingPageState extends State<MeetingPage> with WidgetsBindingObserver {
_meetModel.getUserInfo().isOpenCamera = true;
});
}
} else if (!kIsWeb && (Platform.isWindows || Platform.isMacOS)) {
} else if (!kIsWeb && Platform.isMacOS) {
MeetingTool.toast(
'The current platform does not support screen sharing.', context);
return;
} else if (!kIsWeb && Platform.isWindows) {
if (!_meetModel.getUserInfo().isShowingWindow) {
TRTCScreenCaptureSourceList list = await _trtcCloud.getScreenCaptureSources(thumbnailWidth: 100, thumbnailHeight: 100, iconWidth: 100, iconHeight: 100);
showWindowSelector(context, list);
} else {
await _trtcCloud.stopScreenCapture();
_userList[0].isOpenCamera = true;
_trtcCloud.startLocalPreview(
_meetModel.getUserInfo().isFrontCamera, _meetModel.getUserInfo().localViewId);
this.setState(() {
_meetModel.getUserInfo().isShowingWindow = false;
_meetModel.getUserInfo().isOpenCamera = true;
});
}
} else {
await _startShare();
//The screen sharing function can only be tested on the real machine
// The screen sharing function can only be tested on the real machine
ReplayKitLauncher.launchReplayKitBroadcast(iosExtensionName);
this.setState(() {
_meetModel.getUserInfo().isOpenCamera = false;
});
}
}

void showWindowSelector(BuildContext context, TRTCScreenCaptureSourceList windows) async {
final result = await showDialog<int>(
context: context,
builder: (BuildContext context) {
return WindowSelectorDialog(windows: windows);
},
);

if (result != null) {
print('Selected window index: $result');
await _trtcCloud.selectScreenCaptureTarget(windows.sourceInfo[result], TRTCScreenCaptureProperty());
await _startShare();
this.setState(() {
_meetModel.getUserInfo().isShowingWindow = true;
_meetModel.getUserInfo().isOpenCamera = false;
});
}
}

Widget _renderView(UserModel item, valueKey, width, height) {
if (item.isOpenCamera) {
return GestureDetector(
Expand Down
58 changes: 58 additions & 0 deletions TRTC-Simple-Demo/lib/ui/window_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

import 'package:tencent_trtc_cloud/trtc_cloud_def.dart';
import 'package:flutter/material.dart';

import 'package:trtc_demo/ui/bgra_image.dart';

class WindowSelectorDialog extends StatelessWidget {
final TRTCScreenCaptureSourceList windows;

WindowSelectorDialog({required this.windows});

@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Select a window to share'),
content: Container(
width: double.maxFinite,
child: GridView.builder(
itemCount: windows.count,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 5,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
childAspectRatio: 1,
),
itemBuilder: (context, index) {
final window = windows.sourceInfo[index];
final imageBuffer = (window.type == TRTCScreenCaptureSourceType.window)
? window.iconBGRA
: window.thumbBGRA;
return InkWell(
onTap: () {
Navigator.of(context).pop(index);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
window.sourceName!,
style: TextStyle(fontSize: 12),
),
SizedBox(height: 8),
imageBuffer != null
? BgraImage(
bgraData: imageBuffer.buffer!,
width: imageBuffer.width!,
height: imageBuffer.height!,
)
: Placeholder(fallbackWidth: 50, fallbackHeight: 50),
],
),
);
},
),
),
);
}
}

0 comments on commit 29edcfe

Please sign in to comment.