Skip to content

Commit

Permalink
[CoreMidi] Make P/Invokes have blittable signatures.
Browse files Browse the repository at this point in the history
Contributes towards xamarin#15684.
  • Loading branch information
rolfbjarne committed Dec 22, 2023
1 parent c1f25e6 commit 1d6f8f4
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 60 deletions.
98 changes: 62 additions & 36 deletions src/CoreMidi/MidiServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,12 +287,14 @@ internal MidiObject ()
}

[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIObjectGetIntegerProperty (MidiObjectRef obj, IntPtr str, out int /* SInt32 */ ret);
unsafe extern static int /* OSStatus = SInt32 */ MIDIObjectGetIntegerProperty (MidiObjectRef obj, IntPtr str, int* /* SInt32 */ ret);
internal int GetInt (IntPtr property)
{
int val, code;

code = MIDIObjectGetIntegerProperty (handle, property, out val);
unsafe {
code = MIDIObjectGetIntegerProperty (handle, property, &val);
}
if (code == 0)
return val;
throw new MidiException ((MidiError) code);
Expand All @@ -306,13 +308,15 @@ internal void SetInt (IntPtr property, int value)
}

[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIObjectGetDictionaryProperty (MidiObjectRef obj, IntPtr str, out IntPtr dict);
unsafe extern static int /* OSStatus = SInt32 */ MIDIObjectGetDictionaryProperty (MidiObjectRef obj, IntPtr str, IntPtr* dict);
internal NSDictionary? GetDictionary (IntPtr property)
{
IntPtr val;
int code;

code = MIDIObjectGetDictionaryProperty (handle, property, out val);
unsafe {
code = MIDIObjectGetDictionaryProperty (handle, property, &val);
}
if (code == 0) {
var dict = Runtime.GetNSObject (val) as NSDictionary;
if (val != IntPtr.Zero)
Expand All @@ -330,14 +334,16 @@ internal void SetDictionary (IntPtr property, NSDictionary dict)
}

[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIObjectGetDataProperty (MidiObjectRef obj, IntPtr str, out IntPtr data);
unsafe extern static int /* OSStatus = SInt32 */ MIDIObjectGetDataProperty (MidiObjectRef obj, IntPtr str, IntPtr* data);

public NSData? GetData (IntPtr property)
{
IntPtr val;
int code;

code = MIDIObjectGetDataProperty (handle, property, out val);
unsafe {
code = MIDIObjectGetDataProperty (handle, property, &val);
}
if (code == 0) {
var data = Runtime.GetNSObject (val) as NSData;
if (val != IntPtr.Zero)
Expand All @@ -358,14 +364,16 @@ public void SetData (IntPtr property, NSData data)
}

[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIObjectGetStringProperty (MidiObjectRef obj, IntPtr str, out IntPtr data);
unsafe extern static int /* OSStatus = SInt32 */ MIDIObjectGetStringProperty (MidiObjectRef obj, IntPtr str, IntPtr* data);

public string? GetString (IntPtr property)
{
IntPtr val;
int code;

code = MIDIObjectGetStringProperty (handle, property, out val);
unsafe {
code = MIDIObjectGetStringProperty (handle, property, &val);
}
if (code == 0) {
var ret = CFString.FromHandle (val);
if (val != IntPtr.Zero)
Expand Down Expand Up @@ -397,13 +405,15 @@ public MidiError RemoveProperty (string property)
}

[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIObjectGetProperties (MidiObjectRef obj, out IntPtr dict, [MarshalAs (UnmanagedType.U1)] bool deep);
unsafe extern static int /* OSStatus = SInt32 */ MIDIObjectGetProperties (MidiObjectRef obj, IntPtr* dict, byte deep);

public NSDictionary? GetDictionaryProperties (bool deep)
{
IntPtr val;
if (MIDIObjectGetProperties (handle, out val, deep) != 0 || val == IntPtr.Zero)
return null;
unsafe {
if (MIDIObjectGetProperties (handle, &val, deep ? (byte) 1 : (byte) 0) != 0 || val == IntPtr.Zero)
return null;
}
var value = Runtime.GetNSObject (val) as NSDictionary;
CFObject.CFRelease (val);
return value;
Expand Down Expand Up @@ -446,7 +456,7 @@ protected virtual void Dispose (bool disposing)
}

[DllImport (Constants.CoreMidiLibrary)]
extern static MidiError /* OSStatus = SInt32 */ MIDIObjectFindByUniqueID (int /* MIDIUniqueID = SInt32 */ uniqueId, out MidiObjectRef obj, out MidiObjectType objectType);
unsafe extern static MidiError /* OSStatus = SInt32 */ MIDIObjectFindByUniqueID (int /* MIDIUniqueID = SInt32 */ uniqueId, MidiObjectRef* obj, MidiObjectType* objectType);

static internal MidiObject? MidiObjectFromType (MidiObjectType type, MidiObjectRef handle)
{
Expand Down Expand Up @@ -478,7 +488,11 @@ static public MidiError FindByUniqueId (int uniqueId, out MidiObject? result)
{
MidiObjectRef handle;
MidiObjectType type;
var code = MIDIObjectFindByUniqueID (uniqueId, out handle, out type);
MidiError code;

unsafe {
code = MIDIObjectFindByUniqueID (uniqueId, &handle, &type);
}
result = null;
if (code != MidiError.Ok)
return code;
Expand Down Expand Up @@ -514,9 +528,9 @@ public class MidiClient : MidiObject {
#if !COREBUILD
[DllImport (Constants.CoreMidiLibrary)]
#if NET
unsafe extern static int /* OSStatus = SInt32 */ MIDIClientCreate (IntPtr str, delegate* unmanaged<IntPtr, IntPtr, void> callback, IntPtr context, out MidiObjectRef handle);
unsafe extern static int /* OSStatus = SInt32 */ MIDIClientCreate (IntPtr str, delegate* unmanaged<IntPtr, IntPtr, void> callback, IntPtr context, MidiObjectRef* handle);
#else
extern static int /* OSStatus = SInt32 */ MIDIClientCreate (IntPtr str, MidiNotifyProc callback, IntPtr context, out MidiObjectRef handle);
unsafe extern static int /* OSStatus = SInt32 */ MIDIClientCreate (IntPtr str, MidiNotifyProc callback, IntPtr context, MidiObjectRef* handle);
#endif

[DllImport (Constants.CoreMidiLibrary)]
Expand All @@ -533,7 +547,7 @@ public class MidiClient : MidiObject {
[Deprecated (PlatformName.MacOSX, 11, 0)]
#endif
[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDISourceCreate (MidiObjectRef handle, IntPtr name, out MidiObjectRef endpoint);
unsafe extern static int /* OSStatus = SInt32 */ MIDISourceCreate (MidiObjectRef handle, IntPtr name, MidiObjectRef* endpoint);

GCHandle gch;

Expand All @@ -552,14 +566,16 @@ public MidiClient (string name)
{
using (var nsstr = new NSString (name)) {
gch = GCHandle.Alloc (this);
#if NET
int code = 0;
MidiObjectRef tempHandle;
unsafe {
code = MIDIClientCreate (nsstr.Handle, &ClientCallback, GCHandle.ToIntPtr (gch), out handle);
}
#if NET
code = MIDIClientCreate (nsstr.Handle, &ClientCallback, GCHandle.ToIntPtr (gch), &tempHandle);
#else
int code = MIDIClientCreate (nsstr.Handle, static_MidiNotifyProc, GCHandle.ToIntPtr (gch), out handle);
code = MIDIClientCreate (nsstr.Handle, static_MidiNotifyProc, GCHandle.ToIntPtr (gch), &tempHandle);
#endif
}
handle = tempHandle;
if (code != 0) {
gch.Free ();
handle = MidiObject.InvalidRef;
Expand Down Expand Up @@ -589,7 +605,10 @@ public override string ToString ()
{
using (var nsstr = new NSString (name)) {
MidiObjectRef ret;
var code = MIDISourceCreate (handle, nsstr.Handle, out ret);
int code;
unsafe {
code = MIDISourceCreate (handle, nsstr.Handle, &ret);
}
if (code != 0) {
statusCode = (MidiError) code;
return null;
Expand Down Expand Up @@ -964,10 +983,10 @@ public class MidiPort : MidiObject {
extern unsafe static int /* OSStatus = SInt32 */ MIDIInputPortCreate (MidiClientRef client, IntPtr /* CFStringRef */ portName, delegate* unmanaged<IntPtr, IntPtr, IntPtr, void> readProc, IntPtr context, MidiPortRef* midiPort);
#else
[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIInputPortCreate (MidiClientRef client, IntPtr /* CFStringRef */ portName, MidiReadProc readProc, IntPtr context, out MidiPortRef midiPort);
unsafe extern static int /* OSStatus = SInt32 */ MIDIInputPortCreate (MidiClientRef client, IntPtr /* CFStringRef */ portName, MidiReadProc readProc, IntPtr context, MidiPortRef* midiPort);
#endif
[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIOutputPortCreate (MidiClientRef client, IntPtr /* CFStringRef */ portName, out MidiPortRef midiPort);
unsafe extern static int /* OSStatus = SInt32 */ MIDIOutputPortCreate (MidiClientRef client, IntPtr /* CFStringRef */ portName, MidiPortRef* midiPort);

[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIPortDispose (MidiPortRef port);
Expand All @@ -981,19 +1000,21 @@ internal MidiPort (MidiClient client, string portName, bool input)
GCHandle gch = GCHandle.Alloc (this);
int code;

MidiPortRef tempHandle;
if (input) {
#if NET
unsafe {
MidiPortRef tempHandle;
#if NET
code = MIDIInputPortCreate (client.handle, nsstr.Handle, &Read, GCHandle.ToIntPtr (gch), &tempHandle);
handle = tempHandle;
}
#else
code = MIDIInputPortCreate (client.handle, nsstr.Handle, static_MidiReadProc, GCHandle.ToIntPtr (gch), out handle);
code = MIDIInputPortCreate (client.handle, nsstr.Handle, static_MidiReadProc, GCHandle.ToIntPtr (gch), &tempHandle);
#endif
}
} else {
code = MIDIOutputPortCreate (client.handle, nsstr.Handle, out handle);
unsafe {
code = MIDIOutputPortCreate (client.handle, nsstr.Handle, &tempHandle);
}
}
handle = tempHandle;

if (code != 0) {
gch.Free ();
Expand Down Expand Up @@ -1176,13 +1197,15 @@ public nint Sources {
}

[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIEntityGetDevice (MidiEntityRef handle, out MidiDeviceRef devRef);
unsafe extern static int /* OSStatus = SInt32 */ MIDIEntityGetDevice (MidiEntityRef handle, MidiDeviceRef* devRef);

public MidiDevice? Device {
get {
MidiEntityRef res;
if (MIDIEntityGetDevice (handle, out res) == 0)
return new MidiDevice (res);
unsafe {
if (MIDIEntityGetDevice (handle, &res) == 0)
return new MidiDevice (res);
}
return null;
}
}
Expand Down Expand Up @@ -1558,7 +1581,7 @@ public class MidiDevice : MidiObject {
[Deprecated (PlatformName.MacOSX, 11, 0)]
#endif
[DllImport (Constants.CoreMidiLibrary)]
extern static int MIDIDeviceAddEntity (MidiDeviceRef device, /* CFString */ IntPtr name, [MarshalAs (UnmanagedType.U1)] bool embedded, nuint numSourceEndpoints, nuint numDestinationEndpoints, MidiEntityRef newEntity);
extern static int MIDIDeviceAddEntity (MidiDeviceRef device, /* CFString */ IntPtr name, byte embedded, nuint numSourceEndpoints, nuint numDestinationEndpoints, MidiEntityRef newEntity);

public MidiEntity? GetEntity (nint entityIndex)
{
Expand All @@ -1583,7 +1606,7 @@ public int Add (string name, bool embedded, nuint numSourceEndpoints, nuint numD
if (handle == MidiObject.InvalidRef)
throw new ObjectDisposedException ("handle");
using (NSString nsName = new NSString (name)) {
return MIDIDeviceAddEntity (handle, nsName.Handle, embedded, numSourceEndpoints, numDestinationEndpoints, newEntity.Handle);
return MIDIDeviceAddEntity (handle, nsName.Handle, embedded ? (byte) 1 : (byte) 0, numSourceEndpoints, numDestinationEndpoints, newEntity.Handle);
}
}

Expand Down Expand Up @@ -2279,12 +2302,15 @@ public MidiError Received (MidiPacket [] packets)
}

[DllImport (Constants.CoreMidiLibrary)]
extern static int /* OSStatus = SInt32 */ MIDIEndpointGetEntity (MidiEndpointRef endpoint, out MidiEntityRef entity);
unsafe extern static int /* OSStatus = SInt32 */ MIDIEndpointGetEntity (MidiEndpointRef endpoint, MidiEntityRef* entity);

public MidiEntity? Entity {
get {
MidiEntityRef entity;
var code = MIDIEndpointGetEntity (handle, out entity);
int code;
unsafe {
code = MIDIEndpointGetEntity (handle, &entity);
}
if (code == 0)
return new MidiEntity (entity);
return null;
Expand Down
24 changes: 15 additions & 9 deletions src/CoreMidi/MidiThruConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ protected virtual void Dispose (bool disposing)
}

[DllImport (Constants.CoreMidiLibrary)]
static extern /* OSStatus */ MidiError MIDIThruConnectionCreate (
unsafe static extern /* OSStatus */ MidiError MIDIThruConnectionCreate (
/* CFStringRef */ IntPtr inPersistentOwnerID, /* can be null */
/* CFDataRef */ IntPtr inConnectionParams,
/* MIDIThruConnectionRef* */ out MidiThruConnectionRef outConnection);
/* MIDIThruConnectionRef* */ MidiThruConnectionRef* outConnection);

public static MidiThruConnection? Create (string persistentOwnerID, MidiThruConnectionParams connectionParams, out MidiError error)
{
Expand All @@ -75,7 +75,9 @@ protected virtual void Dispose (bool disposing)
using (var data = connectionParams.WriteStruct ()) {
var retStr = CFString.CreateNative (persistentOwnerID);
try {
error = MIDIThruConnectionCreate (retStr, data.Handle, out ret);
unsafe {
error = MIDIThruConnectionCreate (retStr, data.Handle, &ret);
}
} finally {
CFString.ReleaseNative (retStr);
}
Expand All @@ -94,17 +96,19 @@ protected virtual void Dispose (bool disposing)
}

[DllImport (Constants.CoreMidiLibrary)]
static extern /* OSStatus */ MidiError MIDIThruConnectionGetParams (
unsafe static extern /* OSStatus */ MidiError MIDIThruConnectionGetParams (
/* MIDIThruConnectionRef* */ MidiThruConnectionRef connection,
/* CFDataRef */ out IntPtr outConnectionParams);
/* CFDataRef */ IntPtr* outConnectionParams);

public MidiThruConnectionParams? GetParams (out MidiError error)
{
if (Handle == InvalidRef)
throw new ObjectDisposedException ("MidiThruConnection");

IntPtr ret;
error = MIDIThruConnectionGetParams (Handle, out ret);
unsafe {
error = MIDIThruConnectionGetParams (Handle, &ret);
}
if (error != MidiError.Ok || ret == IntPtr.Zero)
return null;
using (var data = Runtime.GetNSObject<NSData> (ret, true)) {
Expand Down Expand Up @@ -141,9 +145,9 @@ public MidiError SetParams (MidiThruConnectionParams connectionParams)
}

[DllImport (Constants.CoreMidiLibrary)]
static extern /* OSStatus */ MidiError MIDIThruConnectionFind (
unsafe static extern /* OSStatus */ MidiError MIDIThruConnectionFind (
/* CFStringRef* */ IntPtr inPersistentOwnerID,
/* CFDataRef */ out IntPtr outConnectionList);
/* CFDataRef */ IntPtr* outConnectionList);

public static MidiThruConnection []? Find (string persistentOwnerID, out MidiError error)
{
Expand All @@ -153,7 +157,9 @@ public MidiError SetParams (MidiThruConnectionParams connectionParams)
IntPtr ret;
var persistentOwnerIDHandle = CFString.CreateNative (persistentOwnerID);
try {
error = MIDIThruConnectionFind (persistentOwnerIDHandle, out ret);
unsafe {
error = MIDIThruConnectionFind (persistentOwnerIDHandle, &ret);
}
} finally {
CFString.ReleaseNative (persistentOwnerIDHandle);
}
Expand Down
15 changes: 0 additions & 15 deletions tests/cecil-tests/BlittablePInvokes.KnownFailures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,6 @@ public partial class BlittablePInvokes {
"CoreMedia.CMTimebaseError CoreMedia.CMTimebase::CMTimebaseCreateWithSourceClock(System.IntPtr,System.IntPtr,System.IntPtr&)",
"CoreMedia.CMTimebaseError CoreMedia.CMTimebase::CMTimebaseCreateWithSourceTimebase(System.IntPtr,System.IntPtr,System.IntPtr&)",
"CoreMedia.CMTimebaseError CoreMedia.CMTimebase::CMTimebaseGetTimeAndRate(System.IntPtr,CoreMedia.CMTime&,System.Double&)",
"CoreMidi.MidiError CoreMidi.MidiObject::MIDIObjectFindByUniqueID(System.Int32,System.Int32&,CoreMidi.MidiObjectType&)",
"CoreMidi.MidiError CoreMidi.MidiThruConnection::MIDIThruConnectionCreate(System.IntPtr,System.IntPtr,System.UInt32&)",
"CoreMidi.MidiError CoreMidi.MidiThruConnection::MIDIThruConnectionFind(System.IntPtr,System.IntPtr&)",
"CoreMidi.MidiError CoreMidi.MidiThruConnection::MIDIThruConnectionGetParams(System.UInt32,System.IntPtr&)",
"CoreServices.LSResult CoreServices.LaunchServices::LSCanURLAcceptURL(System.IntPtr,System.IntPtr,CoreServices.LSRoles,CoreServices.LSAcceptanceFlags,System.Byte&)",
"CoreVideo.CVReturn CoreVideo.CVDisplayLink::CVDisplayLinkCreateWithActiveCGDisplays(System.IntPtr&)",
"CoreVideo.CVReturn CoreVideo.CVDisplayLink::CVDisplayLinkCreateWithCGDisplay(System.UInt32,System.IntPtr&)",
Expand Down Expand Up @@ -618,17 +614,6 @@ public partial class BlittablePInvokes {
"System.Int32 CoreGraphics.CGEvent::CGGetEventTapList(System.UInt32,CoreGraphics.CGEventTapInformation*,System.UInt32&)",
"System.Int32 CoreMedia.CMBufferQueue::CMBufferQueueCreate(System.IntPtr,System.IntPtr,CoreMedia.CMBufferQueue/CMBufferCallbacks,System.IntPtr&)",
"System.Int32 CoreMedia.CMBufferQueue::CMBufferQueueCreate(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr&)",
"System.Int32 CoreMidi.MidiClient::MIDIClientCreate(System.IntPtr,method System.Void *(System.IntPtr,System.IntPtr),System.IntPtr,System.Int32&)",
"System.Int32 CoreMidi.MidiClient::MIDISourceCreate(System.Int32,System.IntPtr,System.Int32&)",
"System.Int32 CoreMidi.MidiDevice::MIDIDeviceAddEntity(System.Int32,System.IntPtr,System.Boolean,System.UIntPtr,System.UIntPtr,System.Int32)",
"System.Int32 CoreMidi.MidiEndpoint::MIDIEndpointGetEntity(System.Int32,System.Int32&)",
"System.Int32 CoreMidi.MidiEntity::MIDIEntityGetDevice(System.Int32,System.Int32&)",
"System.Int32 CoreMidi.MidiObject::MIDIObjectGetDataProperty(System.Int32,System.IntPtr,System.IntPtr&)",
"System.Int32 CoreMidi.MidiObject::MIDIObjectGetDictionaryProperty(System.Int32,System.IntPtr,System.IntPtr&)",
"System.Int32 CoreMidi.MidiObject::MIDIObjectGetIntegerProperty(System.Int32,System.IntPtr,System.Int32&)",
"System.Int32 CoreMidi.MidiObject::MIDIObjectGetProperties(System.Int32,System.IntPtr&,System.Boolean)",
"System.Int32 CoreMidi.MidiObject::MIDIObjectGetStringProperty(System.Int32,System.IntPtr,System.IntPtr&)",
"System.Int32 CoreMidi.MidiPort::MIDIOutputPortCreate(System.Int32,System.IntPtr,System.Int32&)",
"System.Int32 CoreVideo.CVDisplayLink::CVDisplayLinkTranslateTime(System.IntPtr,CoreVideo.CVTimeStamp,CoreVideo.CVTimeStamp&)",
"System.Int32 CoreVideo.CVMetalTextureCache::CVMetalTextureCacheCreate(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr&)",
"System.Int32 CoreWlan.CWKeychain::CWKeychainCopyWiFiEAPIdentity(System.IntPtr,System.IntPtr,System.IntPtr&)",
Expand Down

0 comments on commit 1d6f8f4

Please sign in to comment.