Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 57 additions & 21 deletions src/AudioToolbox/MusicPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#if !WATCH

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;

Expand Down Expand Up @@ -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);
Expand All @@ -97,17 +98,18 @@ public class MusicPlayer : DisposableObject {
{
}

new protected virtual void Dispose (bool disposing)
protected override void Dispose (bool disposing)
{
currentSequence = null;
if (Owns && Handle != IntPtr.Zero)
DisposeMusicPlayer (Handle);
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);
Expand All @@ -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;
Expand All @@ -131,21 +136,37 @@ 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 {
MusicPlayerSetTime (Handle, value);
}
}

public MusicPlayerStatus GetTime (out double time)
{
time = 0;
unsafe {
return MusicPlayerGetTime (Handle, (double*) Unsafe.AsPointer<double> (ref time));
}
}

public MusicPlayerStatus SetTime (double time)
{
return MusicPlayerSetTime (Handle, time);
}

[DllImport (Constants.AudioToolboxLibrary)]
extern static /* OSStatus */ MusicPlayerStatus MusicPlayerPreroll (/* MusicPlayer */ IntPtr inPlayer);

Expand All @@ -171,24 +192,30 @@ 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;
}
}

[DllImport (Constants.AudioToolboxLibrary)]
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 {
Expand All @@ -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<long> (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<double> (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;
Expand Down
7 changes: 0 additions & 7 deletions tests/cecil-tests/BlittablePInvokes.KnownFailures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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&)",
Expand Down
103 changes: 103 additions & 0 deletions tests/monotouch-test/AudioToolbox/MusicPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// MusicPlayer unit Tests
//
// Authors:
// Rolf Bjarne Kvinge <rolf@xamarin.com>
//
// 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__