Skip to content

Commit

Permalink
[src] Added manual binding to prevent issue of AVAudioPlayer FromData…
Browse files Browse the repository at this point in the history
…() and FromUrl() throwing exceptions. (#17073)

Provided manual binding of AVAudioPlayer::initWithContentsOfURL:error: and AVAudioPlayer::initWithData:error: to prevent an issue where AVAudioPlayer::FromData() and FromUrl() do not throw exceptions when returning null.

Fixes #16229

Co-authored-by: GitHub Actions Autoformatter <[email protected]>
  • Loading branch information
2 people authored and rolfbjarne committed Jan 24, 2023
1 parent bd158d9 commit 9c0bfd4
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 45 deletions.
60 changes: 25 additions & 35 deletions src/AVFoundation/AVAudioPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,67 +23,57 @@
//
using Foundation;
using ObjCRuntime;
using AudioToolbox;
using System;
using System.Runtime.InteropServices;

#nullable enable

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<NSError> (errhandle);
return null;
} else
error = null;
return ap;
handle = objc_msgSend (handle, Selector.GetHandle ("initWithContentsOfURL:error:"), url__handle__, &errorptr);
}
error = Runtime.GetNSObject<NSError> (errorptr);
return Runtime.GetNSObject<AVAudioPlayer> (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<NSError> (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<NSError> (errorptr);
return Runtime.GetNSObject<AVAudioPlayer> (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
Expand Down
7 changes: 0 additions & 7 deletions src/avfoundation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
Expand Down
38 changes: 35 additions & 3 deletions tests/monotouch-test/AVFoundation/AudioPlayerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Foundation;
using AVFoundation;
using NUnit.Framework;
using System;

namespace MonoTouchFixtures.AVFoundation {

Expand All @@ -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<ArgumentNullException> (() => {
using (var player = AVAudioPlayer.FromData (null, out NSError error)) {
Assert.Null (player, "AVAudioPlayer");
Assert.NotNull (error, "NSError");
}
});
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 7 additions & 0 deletions tests/xtro-sharpie/iOS-AVFoundation.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -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


7 changes: 7 additions & 0 deletions tests/xtro-sharpie/macOS-AVFoundation.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -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


5 changes: 5 additions & 0 deletions tests/xtro-sharpie/tvOS-AVFoundation.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 5 additions & 0 deletions tests/xtro-sharpie/watchOS-AVFoundation.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 9c0bfd4

Please sign in to comment.