fix: hwdec toggle
This commit is contained in:
@@ -99,7 +99,7 @@ class MpvPlayerCore(private val activity: Activity) :
|
|||||||
// Video output configuration
|
// Video output configuration
|
||||||
MPVLib.setOptionString("vo", "gpu")
|
MPVLib.setOptionString("vo", "gpu")
|
||||||
MPVLib.setOptionString("gpu-context", "android")
|
MPVLib.setOptionString("gpu-context", "android")
|
||||||
MPVLib.setOptionString("hwdec", "mediacodec-copy")
|
// hwdec is set from Flutter via setProperty based on user preference
|
||||||
|
|
||||||
// Audio configuration
|
// Audio configuration
|
||||||
MPVLib.setOptionString("ao", "audiotrack")
|
MPVLib.setOptionString("ao", "audiotrack")
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ class MpvPlayerCore: NSObject {
|
|||||||
checkError(mpv_set_option_string(mpv, "vo", "gpu-next"))
|
checkError(mpv_set_option_string(mpv, "vo", "gpu-next"))
|
||||||
checkError(mpv_set_option_string(mpv, "gpu-api", "vulkan"))
|
checkError(mpv_set_option_string(mpv, "gpu-api", "vulkan"))
|
||||||
checkError(mpv_set_option_string(mpv, "gpu-context", "moltenvk"))
|
checkError(mpv_set_option_string(mpv, "gpu-context", "moltenvk"))
|
||||||
checkError(mpv_set_option_string(mpv, "hwdec", "videotoolbox"))
|
// hwdec is set from Flutter via setProperty based on user preference
|
||||||
|
|
||||||
// Initialize MPV
|
// Initialize MPV
|
||||||
let initResult = mpv_initialize(mpv)
|
let initResult = mpv_initialize(mpv)
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ class PlayerNative implements Player {
|
|||||||
StreamSubscription? _eventSubscription;
|
StreamSubscription? _eventSubscription;
|
||||||
bool _disposed = false;
|
bool _disposed = false;
|
||||||
bool _initialized = false;
|
bool _initialized = false;
|
||||||
bool _isVisible = false;
|
|
||||||
|
|
||||||
PlayerNative() {
|
PlayerNative() {
|
||||||
_streams = PlayerStreams(
|
_streams = PlayerStreams(
|
||||||
@@ -315,7 +314,6 @@ class PlayerNative implements Player {
|
|||||||
|
|
||||||
// Show the video layer
|
// Show the video layer
|
||||||
await _methodChannel.invokeMethod('setVisible', {'visible': true});
|
await _methodChannel.invokeMethod('setVisible', {'visible': true});
|
||||||
_isVisible = true;
|
|
||||||
|
|
||||||
// Set start position if provided (must be set before loading file)
|
// Set start position if provided (must be set before loading file)
|
||||||
if (media.start != null && media.start!.inSeconds > 0) {
|
if (media.start != null && media.start!.inSeconds > 0) {
|
||||||
@@ -358,7 +356,6 @@ class PlayerNative implements Player {
|
|||||||
_checkDisposed();
|
_checkDisposed();
|
||||||
await command(['stop']);
|
await command(['stop']);
|
||||||
await _methodChannel.invokeMethod('setVisible', {'visible': false});
|
await _methodChannel.invokeMethod('setVisible', {'visible': false});
|
||||||
_isVisible = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -479,7 +476,6 @@ class PlayerNative implements Player {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await _methodChannel.invokeMethod('setVisible', {'visible': visible});
|
await _methodChannel.invokeMethod('setVisible', {'visible': visible});
|
||||||
_isVisible = visible;
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_errorController.add('Failed to set visibility: $e');
|
_errorController.add('Failed to set visibility: $e');
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import '../widgets/user_avatar_widget.dart';
|
|||||||
import '../widgets/horizontal_scroll_with_arrows.dart';
|
import '../widgets/horizontal_scroll_with_arrows.dart';
|
||||||
import '../widgets/hub_section.dart';
|
import '../widgets/hub_section.dart';
|
||||||
import '../widgets/hub_navigation_controller.dart';
|
import '../widgets/hub_navigation_controller.dart';
|
||||||
import '../widgets/focus/focus_indicator.dart';
|
|
||||||
import 'profile_switch_screen.dart';
|
import 'profile_switch_screen.dart';
|
||||||
import '../providers/user_profile_provider.dart';
|
import '../providers/user_profile_provider.dart';
|
||||||
import '../providers/settings_provider.dart';
|
import '../providers/settings_provider.dart';
|
||||||
@@ -1292,66 +1291,4 @@ class _DiscoverScreenState extends State<DiscoverScreen>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHorizontalList(
|
|
||||||
List<PlexMetadata> items, {
|
|
||||||
bool isLarge = false,
|
|
||||||
bool isInContinueWatching = false,
|
|
||||||
}) {
|
|
||||||
return SliverToBoxAdapter(
|
|
||||||
child: LayoutBuilder(
|
|
||||||
builder: (context, constraints) {
|
|
||||||
// Responsive card width based on screen size
|
|
||||||
// Match Libraries screen sizing (190px baseline)
|
|
||||||
final screenWidth = constraints.maxWidth;
|
|
||||||
final cardWidth = screenWidth > 1600
|
|
||||||
? 220.0
|
|
||||||
: screenWidth > 1200
|
|
||||||
? 200.0
|
|
||||||
: screenWidth > 800
|
|
||||||
? 190.0
|
|
||||||
: 160.0;
|
|
||||||
|
|
||||||
// MediaCard has 8px padding on all sides (16px total horizontally)
|
|
||||||
// So actual poster width is cardWidth - 16
|
|
||||||
final posterWidth = cardWidth - 16;
|
|
||||||
// 2:3 poster aspect ratio (height is 1.5x width)
|
|
||||||
final posterHeight = posterWidth * 1.5;
|
|
||||||
// Container height = poster + padding + spacing + text
|
|
||||||
// 8px top padding + posterHeight + 4px spacing + ~26px text + 8px bottom padding
|
|
||||||
final containerHeight = posterHeight + 46;
|
|
||||||
|
|
||||||
return SizedBox(
|
|
||||||
height: containerHeight,
|
|
||||||
child: HorizontalScrollWithArrows(
|
|
||||||
builder: (scrollController) => ListView.builder(
|
|
||||||
controller: scrollController,
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
|
||||||
itemCount: items.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final item = items[index];
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
|
||||||
child: MediaCard(
|
|
||||||
key: Key(item.ratingKey),
|
|
||||||
item: item,
|
|
||||||
width: cardWidth,
|
|
||||||
height: posterHeight,
|
|
||||||
onRefresh: updateItem,
|
|
||||||
onRemoveFromContinueWatching: isInContinueWatching
|
|
||||||
? _refreshContinueWatching
|
|
||||||
: null,
|
|
||||||
forceGridMode: true,
|
|
||||||
isInContinueWatching: isInContinueWatching,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen>
|
|||||||
await player!.setProperty('sub-font', 'Go Noto Current-Regular');
|
await player!.setProperty('sub-font', 'Go Noto Current-Regular');
|
||||||
await player!.setProperty('demuxer-max-bytes', bufferSizeBytes.toString());
|
await player!.setProperty('demuxer-max-bytes', bufferSizeBytes.toString());
|
||||||
await player!.setProperty('msg-level', debugLoggingEnabled ? 'all=debug' : 'all=error');
|
await player!.setProperty('msg-level', debugLoggingEnabled ? 'all=debug' : 'all=error');
|
||||||
// await player!.setProperty('hwdec', enableHardwareDecoding ? 'auto' : 'no');
|
await player!.setProperty('hwdec', _getHwdecValue(enableHardwareDecoding));
|
||||||
|
|
||||||
// Subtitle styling
|
// Subtitle styling
|
||||||
await player!.setProperty('sub-font-size', settingsService.getSubtitleFontSize().toString());
|
await player!.setProperty('sub-font-size', settingsService.getSubtitleFontSize().toString());
|
||||||
@@ -1324,3 +1324,16 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the appropriate hwdec value based on platform and user preference.
|
||||||
|
String _getHwdecValue(bool enabled) {
|
||||||
|
if (!enabled) return 'no';
|
||||||
|
|
||||||
|
if (Platform.isMacOS || Platform.isIOS) {
|
||||||
|
return 'videotoolbox';
|
||||||
|
} else if (Platform.isAndroid) {
|
||||||
|
return 'mediacodec-copy';
|
||||||
|
} else {
|
||||||
|
return 'auto'; // Windows, Linux
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class MpvPlayerCore: NSObject {
|
|||||||
checkError(mpv_set_option_string(mpv, "vo", "gpu-next"))
|
checkError(mpv_set_option_string(mpv, "vo", "gpu-next"))
|
||||||
checkError(mpv_set_option_string(mpv, "gpu-api", "vulkan"))
|
checkError(mpv_set_option_string(mpv, "gpu-api", "vulkan"))
|
||||||
checkError(mpv_set_option_string(mpv, "gpu-context", "moltenvk"))
|
checkError(mpv_set_option_string(mpv, "gpu-context", "moltenvk"))
|
||||||
checkError(mpv_set_option_string(mpv, "hwdec", "videotoolbox"))
|
// hwdec is set from Flutter via setProperty based on user preference
|
||||||
|
|
||||||
// Initialize MPV
|
// Initialize MPV
|
||||||
let initResult = mpv_initialize(mpv)
|
let initResult = mpv_initialize(mpv)
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ bool MpvPlayer::Initialize(HWND container, HWND flutter_window) {
|
|||||||
|
|
||||||
// Configure mpv for embedded playback.
|
// Configure mpv for embedded playback.
|
||||||
LogToFile("MpvPlayer::Initialize - setting mpv options");
|
LogToFile("MpvPlayer::Initialize - setting mpv options");
|
||||||
mpv_set_option_string(mpv_, "hwdec", "auto");
|
// hwdec is set from Flutter via setProperty based on user preference
|
||||||
mpv_set_option_string(mpv_, "keep-open", "yes");
|
mpv_set_option_string(mpv_, "keep-open", "yes");
|
||||||
mpv_set_option_string(mpv_, "idle", "yes");
|
mpv_set_option_string(mpv_, "idle", "yes");
|
||||||
mpv_set_option_string(mpv_, "input-default-bindings", "no");
|
mpv_set_option_string(mpv_, "input-default-bindings", "no");
|
||||||
|
|||||||
Reference in New Issue
Block a user