Skip to content

Commit

Permalink
feat: Video Test
Browse files Browse the repository at this point in the history
  • Loading branch information
bdlukaa committed Sep 15, 2024
1 parent 1b2e3d9 commit dd0fd57
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 77 deletions.
5 changes: 4 additions & 1 deletion lib/screens/layouts/desktop/viewport.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,14 @@ class DesktopTileViewport extends StatefulWidget {
final UnityVideoPlayer? controller;
final Device device;
final ValueChanged<UnityVideoFit> onFitChanged;
final bool? showDebugInfo;

const DesktopTileViewport({
super.key,
required this.controller,
required this.device,
required this.onFitChanged,
this.showDebugInfo,
});

@override
Expand Down Expand Up @@ -134,6 +136,7 @@ class _DesktopTileViewportState extends State<DesktopTileViewport> {
final video = UnityVideoView.maybeOf(context);
final isSubView = AlternativeWindow.maybeOf(context) != null;
final isMuted = volume == 0.0;
final showDebugInfo = widget.showDebugInfo ?? settings.kShowDebugInfo.value;

Widget foreground = PTZController(
enabled: ptzEnabled,
Expand Down Expand Up @@ -187,7 +190,7 @@ class _DesktopTileViewportState extends State<DesktopTileViewport> {
shadows: outlinedText(),
),
),
if (states.isHovering && settings.kShowDebugInfo.value)
if (states.isHovering && showDebugInfo)
TextSpan(
text: '\nsource: ${video?.player.dataSource}'
'\nposition: ${video?.player.currentPos}'
Expand Down
74 changes: 5 additions & 69 deletions lib/screens/settings/advanced_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,16 @@

import 'dart:io';

import 'package:auto_size_text/auto_size_text.dart';
import 'package:bluecherry_client/models/device.dart';
import 'package:bluecherry_client/providers/desktop_view_provider.dart';
import 'package:bluecherry_client/providers/settings_provider.dart';
import 'package:bluecherry_client/screens/layouts/desktop/external_stream.dart';
import 'package:bluecherry_client/screens/settings/settings_desktop.dart';
import 'package:bluecherry_client/screens/settings/shared/options_chooser_tile.dart';
import 'package:bluecherry_client/utils/config.dart';
import 'package:bluecherry_client/utils/extensions.dart';
import 'package:bluecherry_client/utils/logging.dart';
import 'package:bluecherry_client/utils/video_player.dart';
import 'package:bluecherry_client/utils/window.dart';
import 'package:bluecherry_client/widgets/misc.dart';
import 'package:bluecherry_client/widgets/squared_icon_button.dart';
import 'package:bluecherry_client/widgets/video_test.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -315,70 +311,10 @@ class _AdvancedOptionsSettingsState extends State<AdvancedOptionsSettings> {
final uuid = instance.key;
final player = instance.value;

Widget buildCardProp(String title, String value) {
return Row(children: [
Text('$title:', style: theme.textTheme.labelMedium),
const SizedBox(width: 4.0),
Text(value, style: theme.textTheme.bodySmall),
]);
}

return Card(
clipBehavior: Clip.antiAlias,
child: ListenableBuilder(
listenable: player,
builder: (context, _) {
return ListView(
padding: const EdgeInsets.all(12.0),
children: [
Row(children: [
Expanded(
child: AutoSizeText(
'Player ${index + 1} - ${player.title}',
style: theme.textTheme.titleMedium,
maxLines: 1,
),
),
SquaredIconButton(
icon: Icon(
Icons.close,
color: theme.colorScheme.error,
),
tooltip: loc.removePlayer,
onPressed: () {
final view = context.read<DesktopViewProvider>();
final device = view.layouts
.map<List<Device>>((l) => l.devices)
.reduce((a, b) => a + b)
.firstWhereOrNull((d) => d.uuid == uuid);
if (device != null) view.removeDevices([device]);
},
),
]),
AutoSizeText(
uuid,
style: theme.textTheme.bodySmall,
maxLines: 1,
),
const Divider(),
buildCardProp('Position', player.currentPos.toString()),
buildCardProp('Duration', player.duration.toString()),
buildCardProp('Buffer', player.currentBuffer.toString()),
buildCardProp('FPS', player.fps.toString()),
buildCardProp('LIU', player.lastImageUpdate.toString()),
buildCardProp(
'Resolution',
'${player.resolution?.width ?? '${loc.unknown} '}'
'x'
'${player.resolution?.height ?? ' ${loc.unknown}'}',
),
buildCardProp(
'Quality', player.quality?.name ?? loc.unknown),
buildCardProp('Volume', player.volume.toString()),
],
);
},
),
return VideoInfoCard(
player: player,
uuid: uuid,
title: 'Player ${index + 1} - ${player.title}',
);
},
),
Expand Down
33 changes: 26 additions & 7 deletions lib/screens/settings/server_and_devices.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import 'package:bluecherry_client/screens/settings/settings_mobile.dart';
import 'package:bluecherry_client/screens/settings/shared/options_chooser_tile.dart';
import 'package:bluecherry_client/utils/extensions.dart';
import 'package:bluecherry_client/widgets/misc.dart';
import 'package:bluecherry_client/widgets/video_test.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand Down Expand Up @@ -309,13 +310,6 @@ class StreamingSettings extends StatelessWidget {
},
),
*/
const SizedBox(height: 8.0),
ListTile(
title: const Text('Run a video test'),
trailing: const Icon(Icons.play_arrow),
contentPadding: DesktopSettings.horizontalPadding,
onTap: () {},
),
],
]);
}
Expand Down Expand Up @@ -348,6 +342,31 @@ class DevicesSettings extends StatelessWidget {
},
),
const SizedBox(height: 8.0),
ListTile(
leading: CircleAvatar(
backgroundColor: Colors.transparent,
foregroundColor: theme.iconTheme.color,
child: const Icon(Icons.ondemand_video),
),
title: const Text('Run a video test'),
subtitle: const Text(
'Run a video test to check the state of video playback',
),
trailing: const Icon(Icons.play_arrow),
contentPadding: DesktopSettings.horizontalPadding,
onTap: () => _runVideoTest(context),
),
]);
}

void _runVideoTest(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
showDragHandle: true,
builder: (context) {
return const VideoTest();
},
);
}
}
181 changes: 181 additions & 0 deletions lib/widgets/video_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* This file is a part of Bluecherry Client (https://github.com/bluecherrydvr/unity).
*
* Copyright 2022 Bluecherry, LLC
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import 'package:auto_size_text/auto_size_text.dart';
import 'package:bluecherry_client/models/device.dart';
import 'package:bluecherry_client/providers/desktop_view_provider.dart';
import 'package:bluecherry_client/screens/layouts/desktop/viewport.dart';
import 'package:bluecherry_client/utils/extensions.dart';
import 'package:bluecherry_client/utils/video_player.dart';
import 'package:bluecherry_client/widgets/squared_icon_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:unity_video_player/unity_video_player.dart';

class VideoTest extends StatefulWidget {
const VideoTest({super.key});

@override
State<VideoTest> createState() => _VideoTestState();
}

class _VideoTestState extends State<VideoTest> {
final Device device = Device.dump(
name: 'Big Buck Bunny',
url:
'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
);
late final testVideoPlayer = UnityPlayers.forDevice(device);

@override
void initState() {
super.initState();
device.server = device.server.copyWith(
name: 'By Blender Foundation',
);
}

@override
void dispose() {
testVideoPlayer.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return DraggableScrollableSheet(
expand: false,
initialChildSize: 0.95,
maxChildSize: 0.95,
builder: (context, controller) {
return ListView(children: [
AspectRatio(
aspectRatio: 16 / 9,
child: UnityVideoView(
player: testVideoPlayer,
paneBuilder: (context, player) {
return DesktopTileViewport(
controller: player,
device: device,
showDebugInfo: true,
onFitChanged: (_) {},
);
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: VideoInfoCard(
player: testVideoPlayer,
uuid: device.uuid,
title: '${device.name} (${device.server.name})',
),
),
]);
},
);
}
}

class VideoInfoCard extends StatelessWidget {
final UnityVideoPlayer player;
final String uuid;
final String? title;

const VideoInfoCard({
super.key,
required this.player,
required this.uuid,
this.title,
});

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final loc = AppLocalizations.of(context);

Widget buildCardProp(String title, String value) {
return Row(children: [
Text('$title:', style: theme.textTheme.labelMedium),
const SizedBox(width: 4.0),
Text(value, style: theme.textTheme.bodySmall),
]);
}

return Card(
clipBehavior: Clip.antiAlias,
child: ListenableBuilder(
listenable: player,
child: Row(children: [
Expanded(
child: AutoSizeText(
title ?? player.title,
style: theme.textTheme.titleMedium,
maxLines: 1,
),
),
SquaredIconButton(
icon: Icon(
Icons.close,
color: theme.colorScheme.error,
),
tooltip: loc.removePlayer,
onPressed: () {
final view = context.read<DesktopViewProvider>();
final device = view.layouts
.map<List<Device>>((l) => l.devices)
.reduce((a, b) => a + b)
.firstWhereOrNull((d) => d.uuid == uuid);
if (device != null) view.removeDevices([device]);
},
),
]),
builder: (context, title) {
return ListView(
padding: const EdgeInsets.all(12.0),
shrinkWrap: true,
children: [
title!,
AutoSizeText(
uuid,
style: theme.textTheme.bodySmall,
maxLines: 1,
),
const Divider(),
buildCardProp('Position', player.currentPos.toString()),
buildCardProp('Duration', player.duration.toString()),
buildCardProp('Buffer', player.currentBuffer.toString()),
buildCardProp('FPS', player.fps.toString()),
buildCardProp('LIU', player.lastImageUpdate.toString()),
buildCardProp(
'Resolution',
'${player.resolution?.width ?? '${loc.unknown} '}'
'x'
'${player.resolution?.height ?? ' ${loc.unknown}'}',
),
buildCardProp('Quality', player.quality?.name ?? loc.unknown),
buildCardProp('Volume', player.volume.toString()),
],
);
},
),
);
}
}

0 comments on commit dd0fd57

Please sign in to comment.