diff --git a/src/AVFoundation/AVAudioPlayer.cs b/src/AVFoundation/AVAudioPlayer.cs index c1111dfbea62..c24c47f09fad 100644 --- a/src/AVFoundation/AVAudioPlayer.cs +++ b/src/AVFoundation/AVAudioPlayer.cs @@ -23,8 +23,8 @@ // using Foundation; using ObjCRuntime; -using AudioToolbox; using System; +using System.Runtime.InteropServices; #nullable enable @@ -32,58 +32,48 @@ namespace AVFoundation { #if !WATCH public partial class AVAudioPlayer { + [DllImport (Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")] + unsafe static extern IntPtr objc_msgSend (IntPtr receiver, IntPtr selector, IntPtr arg1, IntPtr* arg2); + public static AVAudioPlayer? FromUrl (NSUrl url, out NSError? error) { + error = null; + IntPtr url__handle__ = url!.GetNonNullHandle (nameof (url)); + IntPtr handle = Messaging.IntPtr_objc_msgSend (class_ptr, Selector.GetHandle ("alloc")); + IntPtr errorptr = IntPtr.Zero; + if (handle == IntPtr.Zero) + return null; unsafe { - IntPtr errhandle; - IntPtr ptrtohandle = (IntPtr) (&errhandle); - - var ap = new AVAudioPlayer (url, ptrtohandle); - if (ap.Handle == IntPtr.Zero) { - error = Runtime.GetNSObject (errhandle); - return null; - } else - error = null; - return ap; + handle = objc_msgSend (handle, Selector.GetHandle ("initWithContentsOfURL:error:"), url__handle__, &errorptr); } + error = Runtime.GetNSObject (errorptr); + return Runtime.GetNSObject (handle, owns: true); } public static AVAudioPlayer? FromUrl (NSUrl url) { - unsafe { - var ap = new AVAudioPlayer (url, IntPtr.Zero); - if (ap.Handle == IntPtr.Zero) - return null; - - return ap; - } + return FromUrl (url, out _); } public static AVAudioPlayer? FromData (NSData data, out NSError? error) { - unsafe { - IntPtr errhandle; - IntPtr ptrtohandle = (IntPtr) (&errhandle); + error = null; + IntPtr data__handle__ = data!.GetNonNullHandle (nameof (data)); + IntPtr errorptr = IntPtr.Zero; + IntPtr handle = Messaging.IntPtr_objc_msgSend (class_ptr, Selector.GetHandle ("alloc")); - var ap = new AVAudioPlayer (data, ptrtohandle); - if (ap.Handle == IntPtr.Zero) { - error = Runtime.GetNSObject (errhandle); - return null; - } else - error = null; - return ap; + if (handle == IntPtr.Zero) + return null; + unsafe { + handle = objc_msgSend (handle, Selector.GetHandle ("initWithData:error:"), data__handle__, &errorptr); } + error = Runtime.GetNSObject (errorptr); + return Runtime.GetNSObject (handle, owns: true); } public static AVAudioPlayer? FromData (NSData data) { - unsafe { - var ap = new AVAudioPlayer (data, IntPtr.Zero); - if (ap.Handle == IntPtr.Zero) - return null; - - return ap; - } + return FromData (data, out _); } } #endif // !WATCH diff --git a/src/avfoundation.cs b/src/avfoundation.cs index 2091a181491d..d9679779dc92 100644 --- a/src/avfoundation.cs +++ b/src/avfoundation.cs @@ -1589,13 +1589,6 @@ interface AVAudioPcmBuffer { [BaseType (typeof (NSObject))] [DisableDefaultCtor] interface AVAudioPlayer { - [Export ("initWithContentsOfURL:error:")] - [Internal] - NativeHandle Constructor (NSUrl url, IntPtr outError); - - [Export ("initWithData:error:")] - [Internal] - NativeHandle Constructor (NSData data, IntPtr outError); [Export ("prepareToPlay")] bool PrepareToPlay (); diff --git a/tests/monotouch-test/AVFoundation/AudioPlayerTest.cs b/tests/monotouch-test/AVFoundation/AudioPlayerTest.cs index a08a5cdb2a16..e37cfd1c8f7a 100644 --- a/tests/monotouch-test/AVFoundation/AudioPlayerTest.cs +++ b/tests/monotouch-test/AVFoundation/AudioPlayerTest.cs @@ -13,6 +13,7 @@ using Foundation; using AVFoundation; using NUnit.Framework; +using System; namespace MonoTouchFixtures.AVFoundation { @@ -25,13 +26,44 @@ public void FromUrl () { string file = Path.Combine (NSBundle.MainBundle.ResourcePath, "Hand.wav"); Assert.True (File.Exists (file), file); - NSError error; - using (var url = new NSUrl (file, false)) - using (var ap = AVAudioPlayer.FromUrl (url, out error)) { + using (NSUrl url = new (file, false)) + using (AVAudioPlayer ap = AVAudioPlayer.FromUrl (url, out NSError error)) { Assert.NotNull (ap, "AVAudioPlayer"); Assert.Null (error, "NSError"); } } + + [Test] + public void FromUrlWithInvalidUrl () + { + Assert.DoesNotThrow (() => { + using (AVAudioPlayer player = AVAudioPlayer.FromUrl (NSUrl.FromString ("sdf"), out NSError error)) { + Assert.Null (player, "AVAudioPlayer"); + Assert.NotNull (error, "NSError"); + } + }); + } + + [Test] + public void FromData () + { + using (NSData data = NSData.FromFile (NSBundle.MainBundle.PathForResource ("Hand", "wav"))) + using (AVAudioPlayer player = AVAudioPlayer.FromData (data, out NSError error)) { + Assert.NotNull (player, "AVAudioPlayer"); + Assert.Null (error, "NSError"); + } + } + + [Test] + public void FromDataWithNullData () + { + Assert.Throws (() => { + using (var player = AVAudioPlayer.FromData (null, out NSError error)) { + Assert.Null (player, "AVAudioPlayer"); + Assert.NotNull (error, "NSError"); + } + }); + } } } diff --git a/tests/xtro-sharpie/api-annotations-dotnet/iOS-AVFoundation.ignore b/tests/xtro-sharpie/api-annotations-dotnet/iOS-AVFoundation.ignore index 74e15e694614..a10ca55f52f8 100644 --- a/tests/xtro-sharpie/api-annotations-dotnet/iOS-AVFoundation.ignore +++ b/tests/xtro-sharpie/api-annotations-dotnet/iOS-AVFoundation.ignore @@ -12,3 +12,8 @@ ### deprecated in iOS8 !missing-protocol-member! AVAudioPlayerDelegate::audioPlayerEndInterruption:withFlags: not found + +## https://github.com/xamarin/xamarin-macios/issues/16229 prevents crashing instead of return null +## so these selectors have been bound manually +!missing-selector! AVAudioPlayer::initWithContentsOfURL:error: not bound +!missing-selector! AVAudioPlayer::initWithData:error: not bound diff --git a/tests/xtro-sharpie/api-annotations-dotnet/macOS-AVFoundation.ignore b/tests/xtro-sharpie/api-annotations-dotnet/macOS-AVFoundation.ignore index 065f8e7d962b..6427e4c916b5 100644 --- a/tests/xtro-sharpie/api-annotations-dotnet/macOS-AVFoundation.ignore +++ b/tests/xtro-sharpie/api-annotations-dotnet/macOS-AVFoundation.ignore @@ -43,3 +43,8 @@ # not used on macOS !missing-enum! AVAudioSessionInterruptionReason not bound + +## https://github.com/xamarin/xamarin-macios/issues/16229 prevents crashing instead of return null +## so these selectors have been bound manually +!missing-selector! AVAudioPlayer::initWithContentsOfURL:error: not bound +!missing-selector! AVAudioPlayer::initWithData:error: not bound diff --git a/tests/xtro-sharpie/api-annotations-dotnet/tvOS-AVFoundation.ignore b/tests/xtro-sharpie/api-annotations-dotnet/tvOS-AVFoundation.ignore index b01b308c8f4f..66de0b4a1eb9 100644 --- a/tests/xtro-sharpie/api-annotations-dotnet/tvOS-AVFoundation.ignore +++ b/tests/xtro-sharpie/api-annotations-dotnet/tvOS-AVFoundation.ignore @@ -9,3 +9,8 @@ ### deprecated in iOS8 !missing-protocol-member! AVAudioPlayerDelegate::audioPlayerEndInterruption:withFlags: not found + +## https://github.com/xamarin/xamarin-macios/issues/16229 prevents crashing instead of return null +## so these selectors have been bound manually +!missing-selector! AVAudioPlayer::initWithContentsOfURL:error: not bound +!missing-selector! AVAudioPlayer::initWithData:error: not bound diff --git a/tests/xtro-sharpie/iOS-AVFoundation.ignore b/tests/xtro-sharpie/iOS-AVFoundation.ignore index f3bb8993b14a..bf09307248f7 100644 --- a/tests/xtro-sharpie/iOS-AVFoundation.ignore +++ b/tests/xtro-sharpie/iOS-AVFoundation.ignore @@ -29,3 +29,10 @@ !incorrect-protocol-member! AVAudio3DMixing::sourceMode is REQUIRED and should be abstract !extra-null-allowed! 'Foundation.NSNumber[] AVFoundation.AVVideoCompositionInstruction::get_RequiredSourceTrackIDs()' has a extraneous [NullAllowed] on return type !missing-field! AVPlayerItemTimeJumpedOriginatingParticipantKey not bound + +## https://github.com/xamarin/xamarin-macios/issues/16229 prevents crashing instead of return null +## so these selectors have been bound manually +!missing-selector! AVAudioPlayer::initWithContentsOfURL:error: not bound +!missing-selector! AVAudioPlayer::initWithData:error: not bound + + diff --git a/tests/xtro-sharpie/macOS-AVFoundation.ignore b/tests/xtro-sharpie/macOS-AVFoundation.ignore index 8c83f2062b0c..56e7081c3253 100644 --- a/tests/xtro-sharpie/macOS-AVFoundation.ignore +++ b/tests/xtro-sharpie/macOS-AVFoundation.ignore @@ -61,3 +61,10 @@ !incorrect-protocol-member! AVAudio3DMixing::sourceMode is REQUIRED and should be abstract !extra-null-allowed! 'Foundation.NSNumber[] AVFoundation.AVVideoCompositionInstruction::get_RequiredSourceTrackIDs()' has a extraneous [NullAllowed] on return type !missing-field! AVPlayerItemTimeJumpedOriginatingParticipantKey not bound + +## https://github.com/xamarin/xamarin-macios/issues/16229 prevents crashing instead of return null +## so these selectors have been bound manually +!missing-selector! AVAudioPlayer::initWithContentsOfURL:error: not bound +!missing-selector! AVAudioPlayer::initWithData:error: not bound + + diff --git a/tests/xtro-sharpie/tvOS-AVFoundation.ignore b/tests/xtro-sharpie/tvOS-AVFoundation.ignore index 8e0c60da5ecd..c6d83fb7ba55 100644 --- a/tests/xtro-sharpie/tvOS-AVFoundation.ignore +++ b/tests/xtro-sharpie/tvOS-AVFoundation.ignore @@ -24,3 +24,8 @@ !incorrect-protocol-member! AVAudio3DMixing::sourceMode is REQUIRED and should be abstract !extra-null-allowed! 'Foundation.NSNumber[] AVFoundation.AVVideoCompositionInstruction::get_RequiredSourceTrackIDs()' has a extraneous [NullAllowed] on return type !missing-field! AVPlayerItemTimeJumpedOriginatingParticipantKey not bound + +## https://github.com/xamarin/xamarin-macios/issues/16229 prevents crashing instead of return null +## so these selectors have been bound manually +!missing-selector! AVAudioPlayer::initWithContentsOfURL:error: not bound +!missing-selector! AVAudioPlayer::initWithData:error: not bound diff --git a/tests/xtro-sharpie/watchOS-AVFoundation.ignore b/tests/xtro-sharpie/watchOS-AVFoundation.ignore index 2583e96adedf..a4251c18bc38 100644 --- a/tests/xtro-sharpie/watchOS-AVFoundation.ignore +++ b/tests/xtro-sharpie/watchOS-AVFoundation.ignore @@ -31,3 +31,8 @@ !unknown-native-enum! AVAudioSessionFlags bound !missing-protocol-member! AVAudioPlayerDelegate::audioPlayerEndInterruption:withFlags: not found !missing-protocol-member! AVAudioRecorderDelegate::audioRecorderEndInterruption:withOptions: not found + +## https://github.com/xamarin/xamarin-macios/issues/16229 prevents crashing instead of return null +## so these selectors have been bound manually +!missing-selector! AVAudioPlayer::initWithContentsOfURL:error: not bound +!missing-selector! AVAudioPlayer::initWithData:error: not bound