fix(native): harden player teardown and shelf recovery
This commit is contained in:
@@ -10,6 +10,14 @@ import QuartzCore
|
||||
import Metal
|
||||
#endif
|
||||
|
||||
struct MpvLifecycleUnavailableError: LocalizedError {
|
||||
let errorDescription: String?
|
||||
|
||||
init(_ description: String) {
|
||||
errorDescription = description
|
||||
}
|
||||
}
|
||||
|
||||
protocol MpvPlayerDelegate: AnyObject {
|
||||
func onPropertyChange(name: String, value: Any?)
|
||||
func onEvent(name: String, data: [String: Any]?)
|
||||
@@ -944,11 +952,7 @@ class MpvPlayerCoreBase: NSObject {
|
||||
pendingRequests.removeAll()
|
||||
pendingRequestsLock.unlock()
|
||||
|
||||
let error = NSError(
|
||||
domain: "mpv",
|
||||
code: -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Player disposed"]
|
||||
)
|
||||
let error = MpvLifecycleUnavailableError("Player disposed")
|
||||
for (_, request) in pending {
|
||||
DispatchQueue.main.async {
|
||||
switch request {
|
||||
@@ -977,12 +981,8 @@ class MpvPlayerCoreBase: NSObject {
|
||||
return pendingRequests.removeValue(forKey: requestId)
|
||||
}
|
||||
|
||||
private func lifecycleUnavailableError() -> NSError {
|
||||
NSError(
|
||||
domain: "mpv",
|
||||
code: -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Player is not initialized or has been disposed"]
|
||||
)
|
||||
private func lifecycleUnavailableError() -> MpvLifecycleUnavailableError {
|
||||
MpvLifecycleUnavailableError("Player is not initialized or has been disposed")
|
||||
}
|
||||
|
||||
private func mpvError(_ status: CInt) -> NSError {
|
||||
|
||||
@@ -49,11 +49,15 @@ extension MpvPluginShared {
|
||||
self?.didSetPauseProperty(value: value)
|
||||
}
|
||||
result(nil)
|
||||
case .failure:
|
||||
case .failure(let error):
|
||||
let lifecycleUnavailable = error is MpvLifecycleUnavailableError
|
||||
result(
|
||||
FlutterError(
|
||||
code: "SET_PROPERTY_FAILED",
|
||||
message: "MPV rejected or cancelled the property write",
|
||||
code: lifecycleUnavailable ? "NOT_INITIALIZED" : "SET_PROPERTY_FAILED",
|
||||
message:
|
||||
lifecycleUnavailable
|
||||
? "MPV player is not initialized"
|
||||
: "MPV rejected or cancelled the property write",
|
||||
details: nil))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,10 @@ static constexpr size_t kSetPropertyErrorDescriptionLimit = 160;
|
||||
|
||||
inline bool SetPropertyStatusSucceeded(int status) { return status >= 0; }
|
||||
|
||||
inline const char* SetPropertyErrorCode(int status) {
|
||||
return status == MPV_ERROR_UNINITIALIZED ? kSetPropertyNotInitializedCode : kSetPropertyFailedCode;
|
||||
}
|
||||
|
||||
inline std::string SetPropertyErrorDescription(int status) {
|
||||
const char* description = mpv_error_string(status);
|
||||
if (!description || description[0] == '\0') {
|
||||
|
||||
@@ -81,14 +81,27 @@ void TestSetPropertyResultContract() {
|
||||
assert(SetPropertyStatusSucceeded(MPV_ERROR_SUCCESS));
|
||||
assert(SetPropertyStatusSucceeded(1));
|
||||
|
||||
constexpr int kFailureStatuses[] = {
|
||||
assert(!SetPropertyStatusSucceeded(MPV_ERROR_UNINITIALIZED));
|
||||
|
||||
assert(std::string(SetPropertyErrorCode(MPV_ERROR_UNINITIALIZED)) == kSetPropertyNotInitializedCode);
|
||||
|
||||
constexpr int kRejectedStatuses[] = {
|
||||
MPV_ERROR_INVALID_PARAMETER,
|
||||
MPV_ERROR_PROPERTY_ERROR,
|
||||
-1,
|
||||
};
|
||||
for (const int status : kRejectedStatuses) {
|
||||
assert(!SetPropertyStatusSucceeded(status));
|
||||
assert(std::string(SetPropertyErrorCode(status)) == kSetPropertyFailedCode);
|
||||
}
|
||||
|
||||
constexpr int kDescribedStatuses[] = {
|
||||
MPV_ERROR_INVALID_PARAMETER,
|
||||
MPV_ERROR_PROPERTY_ERROR,
|
||||
-1,
|
||||
MPV_ERROR_UNINITIALIZED,
|
||||
};
|
||||
for (const int status : kFailureStatuses) {
|
||||
assert(!SetPropertyStatusSucceeded(status));
|
||||
for (const int status : kDescribedStatuses) {
|
||||
const std::string description = SetPropertyErrorDescription(status);
|
||||
assert(!description.empty());
|
||||
assert(description.size() <= kSetPropertyErrorDescriptionLimit);
|
||||
|
||||
Reference in New Issue
Block a user