flutter desktop Codec Preference

This commit is contained in:
csf 2022-09-16 19:43:28 +08:00
parent e3a5218eb1
commit c6e1e84c72
5 changed files with 152 additions and 84 deletions

View File

@ -219,17 +219,12 @@ class _GeneralState extends State<_General> {
} }
Widget hwcodec() { Widget hwcodec() {
return _futureBuilder( return Offstage(
future: bind.mainHasHwcodec(), offstage: !bind.mainHasHwcodec(),
hasData: (data) { child: _Card(title: 'Hardware Codec', children: [
return Offstage( _OptionCheckBox(context, 'Enable hardware codec', 'enable-hwcodec'),
offstage: !(data as bool), ]),
child: _Card(title: 'Hardware Codec', children: [ );
_OptionCheckBox(
context, 'Enable hardware codec', 'enable-hwcodec'),
]),
);
});
} }
Widget audio(BuildContext context) { Widget audio(BuildContext context) {

View File

@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math' as math; import 'dart:math' as math;
@ -298,25 +299,35 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
} }
Widget _buildDisplay(BuildContext context) { Widget _buildDisplay(BuildContext context) {
return mod_menu.PopupMenuButton( return FutureBuilder(future: () async {
padding: EdgeInsets.zero, final supportedHwcodec =
icon: const Icon( await bind.sessionSupportedHwcodec(id: widget.id);
Icons.tv, return {'supportedHwcodec': supportedHwcodec};
color: _MenubarTheme.commonColor, }(), builder: (context, snapshot) {
), if (snapshot.hasData) {
tooltip: translate('Display Settings'), return mod_menu.PopupMenuButton(
position: mod_menu.PopupMenuPosition.under, padding: EdgeInsets.zero,
itemBuilder: (BuildContext context) => _getDisplayMenu() icon: const Icon(
.map((entry) => entry.build( Icons.tv,
context, color: _MenubarTheme.commonColor,
const MenuConfig( ),
commonColor: _MenubarTheme.commonColor, tooltip: translate('Display Settings'),
height: _MenubarTheme.height, position: mod_menu.PopupMenuPosition.under,
dividerHeight: _MenubarTheme.dividerHeight, itemBuilder: (BuildContext context) => _getDisplayMenu(snapshot.data!)
))) .map((entry) => entry.build(
.expand((i) => i) context,
.toList(), const MenuConfig(
); commonColor: _MenubarTheme.commonColor,
height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight,
)))
.expand((i) => i)
.toList(),
);
} else {
return const Offstage();
}
});
} }
Widget _buildKeyboard(BuildContext context) { Widget _buildKeyboard(BuildContext context) {
@ -532,7 +543,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
return displayMenu; return displayMenu;
} }
List<MenuEntryBase<String>> _getDisplayMenu() { List<MenuEntryBase<String>> _getDisplayMenu(dynamic futureData) {
final displayMenu = [ final displayMenu = [
MenuEntryRadios<String>( MenuEntryRadios<String>(
text: translate('Ratio'), text: translate('Ratio'),
@ -653,33 +664,74 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
} }
}), }),
MenuEntryDivider<String>(), MenuEntryDivider<String>(),
// {show_codec ? <div> ];
// MenuEntryDivider<String>(),
() { /// Show Codec Preference
final state = ShowRemoteCursorState.find(widget.id); if (bind.mainHasHwcodec()) {
return MenuEntrySwitch2<String>( final List<bool> codecs = [];
text: translate('Show remote cursor'), try {
getter: () { final Map codecsJson = jsonDecode(futureData['supportedHwcodec']);
return state; final h264 = codecsJson['h264'] ?? false;
final h265 = codecsJson['h265'] ?? false;
codecs.add(h264);
codecs.add(h265);
} finally {}
if (codecs.length == 2 && (codecs[0] || codecs[1])) {
displayMenu.add(MenuEntryRadios<String>(
text: translate('Codec Preference'),
optionsGetter: () {
final list = [
MenuEntryRadioOption(text: translate('Auto'), value: 'auto'),
MenuEntryRadioOption(text: 'VP9', value: 'vp9'),
];
if (codecs[0]) {
list.add(MenuEntryRadioOption(text: 'H264', value: 'h264'));
}
if (codecs[1]) {
list.add(MenuEntryRadioOption(text: 'H265', value: 'h265'));
}
return list;
}, },
setter: (bool v) async { curOptionGetter: () async {
state.value = v; return await bind.sessionGetOption(
await bind.sessionToggleOption( id: widget.id, arg: 'codec-preference') ??
id: widget.id, value: 'show-remote-cursor'); 'auto';
}); },
}(), optionSetter: (String oldValue, String newValue) async {
MenuEntrySwitch<String>( await bind.sessionPeerOption(
text: translate('Show quality monitor'), id: widget.id, name: "codec-preference", value: newValue);
getter: () async { bind.sessionChangePreferCodec(id: widget.id);
return bind.sessionGetToggleOptionSync( }));
id: widget.id, arg: 'show-quality-monitor'); }
}
/// Show remote cursor
displayMenu.add(() {
final state = ShowRemoteCursorState.find(widget.id);
return MenuEntrySwitch2<String>(
text: translate('Show remote cursor'),
getter: () {
return state;
}, },
setter: (bool v) async { setter: (bool v) async {
state.value = v;
await bind.sessionToggleOption( await bind.sessionToggleOption(
id: widget.id, value: 'show-quality-monitor'); id: widget.id, value: 'show-remote-cursor');
widget.ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id); });
}), }());
];
/// Show quality monitor
displayMenu.add(MenuEntrySwitch<String>(
text: translate('Show quality monitor'),
getter: () async {
return bind.sessionGetToggleOptionSync(
id: widget.id, arg: 'show-quality-monitor');
},
setter: (bool v) async {
await bind.sessionToggleOption(
id: widget.id, value: 'show-quality-monitor');
widget.ffi.qualityMonitorModel.checkShowQualityMonitor(widget.id);
}));
final perms = widget.ffi.ffiModel.permissions; final perms = widget.ffi.ffiModel.permissions;
final pi = widget.ffi.ffiModel.pi; final pi = widget.ffi.ffiModel.pi;

View File

@ -754,8 +754,8 @@ pub fn main_remove_peer(id: String) {
PeerConfig::remove(&id); PeerConfig::remove(&id);
} }
pub fn main_has_hwcodec() -> bool { pub fn main_has_hwcodec() -> SyncReturn<bool> {
has_hwcodec() SyncReturn(has_hwcodec())
} }
pub fn session_send_mouse(id: String, msg: String) { pub fn session_send_mouse(id: String, msg: String) {
@ -816,6 +816,22 @@ pub fn session_send_note(id: String, note: String) {
} }
} }
pub fn session_supported_hwcodec(id: String) -> String {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
let (h264, h265) = session.supported_hwcodec();
let msg = HashMap::from([("h264", h264), ("h265", h265)]);
serde_json::ser::to_string(&msg).unwrap_or("".to_owned())
} else {
String::new()
}
}
pub fn session_change_prefer_codec(id: String) {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
session.change_prefer_codec();
}
}
pub fn main_set_home_dir(home: String) { pub fn main_set_home_dir(home: String) {
*config::APP_HOME_DIR.write().unwrap() = home; *config::APP_HOME_DIR.write().unwrap() = home;
} }

View File

@ -449,27 +449,11 @@ impl SciterSession {
} }
fn supported_hwcodec(&self) -> Value { fn supported_hwcodec(&self) -> Value {
#[cfg(feature = "hwcodec")] let (h264, h265) = self.0.supported_hwcodec();
{ let mut v = Value::array(0);
let mut v = Value::array(0); v.push(h264);
let decoder = scrap::codec::Decoder::video_codec_state(&self.id); v.push(h265);
let mut h264 = decoder.score_h264 > 0; v
let mut h265 = decoder.score_h265 > 0;
if let Some((encoding_264, encoding_265)) = self.lc.read().unwrap().supported_encoding {
h264 = h264 && encoding_264;
h265 = h265 && encoding_265;
}
v.push(h264);
v.push(h265);
v
}
#[cfg(not(feature = "hwcodec"))]
{
let mut v = Value::array(0);
v.push(false);
v.push(false);
v
}
} }
fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) { fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) {

View File

@ -11,9 +11,9 @@ use async_trait::async_trait;
use hbb_common::config::{Config, LocalConfig, PeerConfig}; use hbb_common::config::{Config, LocalConfig, PeerConfig};
use hbb_common::rendezvous_proto::ConnType; use hbb_common::rendezvous_proto::ConnType;
use hbb_common::tokio::{self, sync::mpsc}; use hbb_common::tokio::{self, sync::mpsc};
use rdev::{Event, EventType::*, Key as RdevKey, KeyboardState};
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
use rdev::Keyboard as RdevKeyboard; use rdev::Keyboard as RdevKeyboard;
use rdev::{Event, EventType::*, Key as RdevKey, KeyboardState};
use hbb_common::{allow_err, message_proto::*}; use hbb_common::{allow_err, message_proto::*};
use hbb_common::{fs, get_version_number, log, Stream}; use hbb_common::{fs, get_version_number, log, Stream};
@ -143,6 +143,25 @@ impl<T: InvokeUiSession> Session<T> {
return true; return true;
} }
pub fn supported_hwcodec(&self) -> (bool, bool) {
#[cfg(feature = "hwcodec")]
{
let decoder = scrap::codec::Decoder::video_codec_state(&self.id);
let mut h264 = decoder.score_h264 > 0;
let mut h265 = decoder.score_h265 > 0;
if let Some((encoding_264, encoding_265)) = self.lc.read().unwrap().supported_encoding {
h264 = h264 && encoding_264;
h265 = h265 && encoding_265;
}
return (h264, h265);
}
#[cfg(feature = "mediacodec")]
{
todo!();
}
(false, false)
}
pub fn change_prefer_codec(&self) { pub fn change_prefer_codec(&self) {
let msg = self.lc.write().unwrap().change_prefer_codec(); let msg = self.lc.write().unwrap().change_prefer_codec();
self.send(Data::Message(msg)); self.send(Data::Message(msg));
@ -658,18 +677,20 @@ impl<T: InvokeUiSession> Session<T> {
} }
self.map_keyboard_mode(down_or_up, key, Some(evt)); self.map_keyboard_mode(down_or_up, key, Some(evt));
} }
KeyboardMode::Legacy => { KeyboardMode::Legacy =>
{
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
self.legacy_keyboard_mode(down_or_up, key, evt) self.legacy_keyboard_mode(down_or_up, key, evt)
}, }
KeyboardMode::Translate => { KeyboardMode::Translate => {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
self.translate_keyboard_mode(down_or_up, key, evt); self.translate_keyboard_mode(down_or_up, key, evt);
} }
_ => { _ =>
{
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
self.legacy_keyboard_mode(down_or_up, key, evt) self.legacy_keyboard_mode(down_or_up, key, evt)
}, }
} }
} }
@ -1178,7 +1199,7 @@ impl<T: InvokeUiSession> Session<T> {
if self.is_port_forward() || self.is_file_transfer() { if self.is_port_forward() || self.is_file_transfer() {
return; return;
} }
if !KEYBOARD_HOOKED.load(Ordering::SeqCst){ if !KEYBOARD_HOOKED.load(Ordering::SeqCst) {
return; return;
} }
log::info!("keyboard hooked"); log::info!("keyboard hooked");