diff --git a/src/AudioToolbox/MusicPlayer.cs b/src/AudioToolbox/MusicPlayer.cs index 8119562b7c7f..ad32d0cf5a93 100644 --- a/src/AudioToolbox/MusicPlayer.cs +++ b/src/AudioToolbox/MusicPlayer.cs @@ -13,6 +13,7 @@ #if !WATCH using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -86,7 +87,7 @@ public enum MusicSequenceFileFlags { // MusicPlayer.h public class MusicPlayer : DisposableObject { [DllImport (Constants.AudioToolboxLibrary)] - extern static /* OSStatus */ MusicPlayerStatus NewMusicPlayer (/* MusicPlayer* */ out IntPtr outPlayer); + unsafe extern static /* OSStatus */ MusicPlayerStatus NewMusicPlayer (/* MusicPlayer* */ IntPtr* outPlayer); [DllImport (Constants.AudioToolboxLibrary)] extern static /* OSStatus */ MusicPlayerStatus DisposeMusicPlayer (/* MusicPlayer */ IntPtr inPlayer); @@ -97,7 +98,7 @@ public class MusicPlayer : DisposableObject { { } - new protected virtual void Dispose (bool disposing) + protected override void Dispose (bool disposing) { currentSequence = null; if (Owns && Handle != IntPtr.Zero) @@ -105,9 +106,10 @@ public class MusicPlayer : DisposableObject { base.Dispose (disposing); } - static IntPtr Create () + unsafe static IntPtr Create () { - var result = NewMusicPlayer (out var handle); + IntPtr handle; + var result = NewMusicPlayer (&handle); if (result == MusicPlayerStatus.Success) return handle; throw new Exception ("Unable to create MusicPlayer: " + result); @@ -120,7 +122,10 @@ public MusicPlayer () static public MusicPlayer? Create (out MusicPlayerStatus OSstatus) { - OSstatus = NewMusicPlayer (out var handle); + IntPtr handle; + unsafe { + OSstatus = NewMusicPlayer (&handle); + } if (OSstatus == 0) return new MusicPlayer (handle, true); return null; @@ -131,14 +136,17 @@ public MusicPlayer () // note: MusicTimeStamp -> Float64 [DllImport (Constants.AudioToolboxLibrary)] - extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetTime (/* MusicPlayer */ IntPtr inPlayer, /* MusicTimeStamp* */ out double outTime); + unsafe extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetTime (/* MusicPlayer */ IntPtr inPlayer, /* MusicTimeStamp* */ double* outTime); [DllImport (Constants.AudioToolboxLibrary)] extern static /* OSStatus */ MusicPlayerStatus MusicPlayerSetTime (/* MusicPlayer */ IntPtr inPlayer, /* MusicTimeStamp* */ double inTime); public double Time { get { - MusicPlayerGetTime (Handle, out var time); + double time; + unsafe { + MusicPlayerGetTime (Handle, &time); + } return time; } set { @@ -146,6 +154,19 @@ public double Time { } } + public MusicPlayerStatus GetTime (out double time) + { + time = 0; + unsafe { + return MusicPlayerGetTime (Handle, (double *) Unsafe.AsPointer (ref time)); + } + } + + public MusicPlayerStatus SetTime (double time) + { + return MusicPlayerSetTime (Handle, time); + } + [DllImport (Constants.AudioToolboxLibrary)] extern static /* OSStatus */ MusicPlayerStatus MusicPlayerPreroll (/* MusicPlayer */ IntPtr inPlayer); @@ -171,12 +192,15 @@ public MusicPlayerStatus Stop () } [DllImport (Constants.AudioToolboxLibrary)] - extern static /* OSStatus */ MusicPlayerStatus MusicPlayerIsPlaying (/* MusicPlayer */ IntPtr inPlayer, /* Boolean* */ [MarshalAs (UnmanagedType.I1)] out bool outIsPlaying); + unsafe extern static /* OSStatus */ MusicPlayerStatus MusicPlayerIsPlaying (/* MusicPlayer */ IntPtr inPlayer, /* Boolean* */ byte* outIsPlaying); public bool IsPlaying { get { - MusicPlayerIsPlaying (Handle, out var res); - return res; + byte res; + unsafe { + MusicPlayerIsPlaying (Handle, &res); + } + return res != 0; } } @@ -184,11 +208,14 @@ public bool IsPlaying { extern static /* OSStatus */ MusicPlayerStatus MusicPlayerSetPlayRateScalar (/* MusicPlayer */ IntPtr inPlayer, /* Float64 */ double inScaleRate); [DllImport (Constants.AudioToolboxLibrary)] - extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetPlayRateScalar (/* MusicPlayer */ IntPtr inPlayer, /* Float64* */ out double outScaleRate); + unsafe extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetPlayRateScalar (/* MusicPlayer */ IntPtr inPlayer, /* Float64* */ double* outScaleRate); public double PlayRateScalar { get { - MusicPlayerGetPlayRateScalar (Handle, out var rate); + double rate; + unsafe { + MusicPlayerGetPlayRateScalar (Handle, &rate); + } return rate; } set { @@ -197,34 +224,43 @@ public double PlayRateScalar { } [DllImport (Constants.AudioToolboxLibrary)] - extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetHostTimeForBeats (/* MusicPlayer */ IntPtr inPlayer, /* MusicTimeStamp */ double inBeats, /* UInt64* */ out long outHostTime); + unsafe extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetHostTimeForBeats (/* MusicPlayer */ IntPtr inPlayer, /* MusicTimeStamp */ double inBeats, /* UInt64* */ long* outHostTime); public MusicPlayerStatus GetHostTimeForBeats (double beats, out long hostTime) { - return MusicPlayerGetHostTimeForBeats (Handle, beats, out hostTime); + hostTime = 0; + unsafe { + return MusicPlayerGetHostTimeForBeats (Handle, beats, (long *) Unsafe.AsPointer (ref hostTime)); + } } [DllImport (Constants.AudioToolboxLibrary)] - extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetBeatsForHostTime (/* MusicPlayer */ IntPtr inPlayer, /* UInt64 */ long inHostTime, /* MusicTimeStamp* */ out double outBeats); + unsafe extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetBeatsForHostTime (/* MusicPlayer */ IntPtr inPlayer, /* UInt64 */ long inHostTime, /* MusicTimeStamp* */ double* outBeats); public MusicPlayerStatus GetBeatsForHostTime (long hostTime, out double beats) { - return MusicPlayerGetBeatsForHostTime (Handle, hostTime, out beats); + beats = 0; + unsafe { + return MusicPlayerGetBeatsForHostTime (Handle, hostTime, (double *) Unsafe.AsPointer (ref beats)); + } } [DllImport (Constants.AudioToolboxLibrary)] - extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetSequence (/* MusicPlayer */ IntPtr inPlayer, /* MusicSequence* */ out IntPtr outSequence); + unsafe extern static /* OSStatus */ MusicPlayerStatus MusicPlayerGetSequence (/* MusicPlayer */ IntPtr inPlayer, /* MusicSequence* */ IntPtr* outSequence); [DllImport (Constants.AudioToolboxLibrary)] extern static /* OSStatus */ MusicPlayerStatus MusicPlayerSetSequence (/* MusicPlayer */ IntPtr inPlayer, IntPtr inSequence); public MusicSequence? MusicSequence { get { - if (MusicPlayerGetSequence (Handle, out var seqHandle) == MusicPlayerStatus.Success) - return MusicSequence.Lookup (seqHandle); - else - return null; + IntPtr seqHandle; + unsafe { + if (MusicPlayerGetSequence (Handle, &seqHandle) == MusicPlayerStatus.Success) + return MusicSequence.Lookup (seqHandle); + } + + return null; } set { currentSequence = value; diff --git a/tests/cecil-tests/BlittablePInvokes.KnownFailures.cs b/tests/cecil-tests/BlittablePInvokes.KnownFailures.cs index 25cee30bd483..05551f236064 100644 --- a/tests/cecil-tests/BlittablePInvokes.KnownFailures.cs +++ b/tests/cecil-tests/BlittablePInvokes.KnownFailures.cs @@ -79,13 +79,6 @@ public partial class BlittablePInvokes { "AudioToolbox.AudioServicesError AudioToolbox.AudioServices::AudioServicesGetProperty(AudioToolbox.AudioServicesPropertyKey,System.UInt32,System.UInt32&,System.UInt32&,System.UInt32&)", "AudioToolbox.AudioServicesError AudioToolbox.AudioServices::AudioServicesSetProperty(AudioToolbox.AudioServicesPropertyKey,System.UInt32,System.UInt32&,System.UInt32,System.UInt32&)", "AudioToolbox.AudioServicesError AudioToolbox.SystemSound::AudioServicesCreateSystemSoundID(System.IntPtr,System.UInt32&)", - "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicPlayer::MusicPlayerGetBeatsForHostTime(System.IntPtr,System.Int64,System.Double&)", - "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicPlayer::MusicPlayerGetHostTimeForBeats(System.IntPtr,System.Double,System.Int64&)", - "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicPlayer::MusicPlayerGetPlayRateScalar(System.IntPtr,System.Double&)", - "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicPlayer::MusicPlayerGetSequence(System.IntPtr,System.IntPtr&)", - "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicPlayer::MusicPlayerGetTime(System.IntPtr,System.Double&)", - "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicPlayer::MusicPlayerIsPlaying(System.IntPtr,System.Boolean&)", - "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicPlayer::NewMusicPlayer(System.IntPtr&)", "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicSequence::MusicSequenceBarBeatTimeToBeats(System.IntPtr,AudioToolbox.CABarBeatTime,System.Double&)", "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicSequence::MusicSequenceBeatsToBarBeatTime(System.IntPtr,System.Double,System.Int32,AudioToolbox.CABarBeatTime&)", "AudioToolbox.MusicPlayerStatus AudioToolbox.MusicSequence::MusicSequenceFileCreateData(System.IntPtr,AudioToolbox.MusicSequenceFileTypeID,AudioToolbox.MusicSequenceFileFlags,System.UInt16,System.IntPtr&)", diff --git a/tests/monotouch-test/AudioToolbox/MusicPlayer.cs b/tests/monotouch-test/AudioToolbox/MusicPlayer.cs new file mode 100644 index 000000000000..3d0e1b2321c8 --- /dev/null +++ b/tests/monotouch-test/AudioToolbox/MusicPlayer.cs @@ -0,0 +1,103 @@ +// +// MusicPlayer unit Tests +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2023 Microsoft Corp. All rights reserved. +// + +#if !__WATCHOS__ + +using System; + +using AudioToolbox; +using Foundation; +using ObjCRuntime; + +using NUnit.Framework; + +namespace MonoTouchFixtures.AudioToolbox { + + [TestFixture] + [Preserve (AllMembers = true)] + public class MusicPlayerTest { + + [Test] + public void Defaults () + { + using (var player = new MusicPlayer ()) { + Assert.IsFalse (player.IsPlaying, "IsPlaying"); + Assert.AreEqual (0, player.Time, "Time"); + Assert.AreEqual (1, player.PlayRateScalar, "PlayRateScalar"); + Assert.AreEqual (MusicPlayerStatus.InvalidPlayerState, player.GetHostTimeForBeats (0, out var hosttime), "GetHostTimeForBeats"); + Assert.AreEqual (0, hosttime, "GetHostTimeForBeats - rv"); + Assert.AreEqual (MusicPlayerStatus.InvalidPlayerState, player.GetBeatsForHostTime (0, out var beats), "GetBeatsForHostTime"); + Assert.AreEqual (0, beats, "GetBeatsForHostTime - rv"); + Assert.IsNull (player.MusicSequence, "MusicSequence"); + } + } + + [Test] + public void MusicSequenceTest () + { + using (var player = new MusicPlayer ()) { + using (var ms = new MusicSequence ()) { + Assert.IsNull (player.MusicSequence, "MusicSequence A"); + player.MusicSequence = null; + Assert.IsNull (player.MusicSequence, "MusicSequence B"); + player.MusicSequence = ms; + Assert.AreSame (ms, player.MusicSequence, "MusicSequence C"); + player.MusicSequence = null; + Assert.IsNull (player.MusicSequence, "MusicSequence D"); + } + } + } + + [Test] + public void PlayRateScalarTest () + { + using (var player = new MusicPlayer ()) { + Assert.AreEqual (1, player.PlayRateScalar, "PlayRateScalar A"); + player.PlayRateScalar = 2; + Assert.AreEqual (2, player.PlayRateScalar, "PlayRateScalar B"); + } + } + + [Test] + public void TimeTest () + { + using (var player = new MusicPlayer ()) { + Assert.AreEqual (0, player.Time, "Time A"); + player.Time = 1; + Assert.AreEqual (0, player.Time, "Time B"); + Assert.AreEqual (MusicPlayerStatus.Success, player.GetTime (out var time), "GetTime A"); + Assert.AreEqual (0, time, "GetTime B"); + Assert.AreEqual (MusicPlayerStatus.Success, player.SetTime (1), "SetTime A"); + Assert.AreEqual (MusicPlayerStatus.Success, player.GetTime (out time), "GetTime C"); + Assert.AreEqual (0, time, "GetTime D"); + } + } + + [Test] + public void CreateTest () + { + using var player = MusicPlayer.Create (out var status); + Assert.NotNull (player, "Got a player"); + Assert.AreEqual (MusicPlayerStatus.Success, status, "Status"); + } + + [Test] + public void StartStopPreroll () + { + using var player = MusicPlayer.Create (out var status); + Assert.NotNull (player, "Got a player"); + Assert.AreEqual (MusicPlayerStatus.Success, status, "Status"); + Assert.AreEqual (MusicPlayerStatus.NoSequence, player.Preroll (), "Preroll"); + Assert.AreEqual (MusicPlayerStatus.NoSequence, player.Start (), "Start"); + Assert.AreEqual (MusicPlayerStatus.NoSequence, player.Stop (), "Stop"); + } + } +} + +#endif // !__WATCHOS__