Skip to content

Conversation

@poneciak57
Copy link
Contributor

@poneciak57 poneciak57 commented Oct 13, 2025

Under construction
Closes #

⚠️ Breaking changes ⚠️

Introduced changes

Checklist

  • Linked relevant issue
  • Updated relevant documentation
  • Added/Conducted relevant tests
  • Performed self-review of the code
  • Updated Web Audio API coverage
  • Added support for web

@poneciak57 poneciak57 self-assigned this Oct 13, 2025
@poneciak57 poneciak57 added feature New feature development Develop some feature or integrate it with sth labels Oct 13, 2025
@poneciak57 poneciak57 marked this pull request as ready for review December 1, 2025 12:46
@poneciak57 poneciak57 changed the title feat: support for midi feat: support for midi 0.1 Dec 1, 2025
} from './types';

// Web MIDI API types
interface WebMIDIPort {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated MIDIPortInfo

import type { CodegenTypes, TurboModule } from 'react-native';
import { TurboModuleRegistry } from 'react-native';

export interface MIDIPortInfoCodegen {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated MIDIPortInfo

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since midi package is not planned to be in separate repository, you can use our main .gitignore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't get it? You can nest .gitignores it is auto generated from expo project it has some expo specific things i guess

Comment on lines +279 to +285
#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeMediSpecJSI>(params);
}
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it doesn't support old arch, why this check

package = JSON.parse(File.read(File.join(__dir__, "package.json")))

Pod::Spec.new do |s|
s.name = "Medi"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
s.name = "Medi"
s.name = "RNOurAgreedName"

///
/// PS: Not actually wasted time cuz it works but brooo☠
dispatch_async(dispatch_get_main_queue(), ^{
OSStatus status = MIDIClientCreateWithBlock(CFSTR("MediClient"), &_midiClient, ^(const MIDINotification *message) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OSStatus status = MIDIClientCreateWithBlock(CFSTR("MediClient"), &_midiClient, ^(const MIDINotification *message) {
OSStatus status = MIDIClientCreateWithBlock(CFSTR("MediClient"), &self->_midiClient, ^(const MIDINotification *message) {


self.sysexEnabled = sysex;
NSLog(@"MIDIClientCreateWithBlock status: %d, sysex: %d", status, sysex);
OSStatus statusPort = MIDIInputPortCreateWithProtocol(self.midiClient, CFSTR("MediInputPort"), kMIDIProtocol_1_0, &_inputPort, ^(const MIDIEventList *eventList, void *srcConnRefCon) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OSStatus statusPort = MIDIInputPortCreateWithProtocol(self.midiClient, CFSTR("MediInputPort"), kMIDIProtocol_1_0, &_inputPort, ^(const MIDIEventList *eventList, void *srcConnRefCon) {
OSStatus statusPort = MIDIInputPortCreateWithProtocol(self.midiClient, CFSTR("MediInputPort"), kMIDIProtocol_1_0, &self->_inputPort, ^(const MIDIEventList *eventList, void *srcConnRefCon) {

reject:(RCTPromiseRejectBlock)reject)
{
if (self.midiClient != 0) {
resolve(nil);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve promises with better info

NSLog(@"MIDIInputPortCreateWithProtocol status: %d", statusPort);

// Resolve the promise after MIDI client is fully initialized
resolve(nil);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolve promises with better info

Comment on lines +198 to +232
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSNumber *, openPort:(NSString *)portId)
{
NSString *type = [portId hasPrefix:@"input_"] ? @"input" : @"output";
SInt32 uniqueID = [[portId substringFromIndex:[type length] + 1] intValue];
if ([type isEqualToString:@"output"]) {
// We do not need to open output ports so it is considered always successful
NSLog(@"Opened output port: %@", portId);
return @YES;
}
MIDIEndpointRef endpoint = 0;
ItemCount srcCount = MIDIGetNumberOfSources();
for (ItemCount i = 0; i < srcCount; ++i) {
MIDIEndpointRef src = MIDIGetSource(i);
SInt32 srcUniqueID = 0;
MIDIObjectGetIntegerProperty(src, kMIDIPropertyUniqueID, &srcUniqueID);
if (srcUniqueID == uniqueID) {
endpoint = src;
break;
}
}
if (endpoint == 0) {
NSLog(@"Port not found: %@", portId);
return @NO;
}

OSStatus status = MIDIPortConnectSource(self.inputPort, endpoint, (void *)(uintptr_t)endpoint);
if (status != noErr) {
NSLog(@"Failed to connect input port: %@, status: %d", portId, status);
return @NO;
}

self.openPorts[portId] = @(endpoint);
NSLog(@"Opened port: %@", portId);
return @YES;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSNumber *, openPort:(NSString *)portId)
{
NSString *type = [portId hasPrefix:@"input_"] ? @"input" : @"output";
SInt32 uniqueID = [[portId substringFromIndex:[type length] + 1] intValue];
if ([type isEqualToString:@"output"]) {
// We do not need to open output ports so it is considered always successful
NSLog(@"Opened output port: %@", portId);
return @YES;
}
MIDIEndpointRef endpoint = 0;
ItemCount srcCount = MIDIGetNumberOfSources();
for (ItemCount i = 0; i < srcCount; ++i) {
MIDIEndpointRef src = MIDIGetSource(i);
SInt32 srcUniqueID = 0;
MIDIObjectGetIntegerProperty(src, kMIDIPropertyUniqueID, &srcUniqueID);
if (srcUniqueID == uniqueID) {
endpoint = src;
break;
}
}
if (endpoint == 0) {
NSLog(@"Port not found: %@", portId);
return @NO;
}
OSStatus status = MIDIPortConnectSource(self.inputPort, endpoint, (void *)(uintptr_t)endpoint);
if (status != noErr) {
NSLog(@"Failed to connect input port: %@, status: %d", portId, status);
return @NO;
}
self.openPorts[portId] = @(endpoint);
NSLog(@"Opened port: %@", portId);
return @YES;
}
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(BOOL, openPort:(NSString *)portId)
{
NSString *type = [portId hasPrefix:@"input_"] ? @"input" : @"output";
SInt32 uniqueID = [[portId substringFromIndex:[type length] + 1] intValue];
if ([type isEqualToString:@"output"]) {
// We do not need to open output ports so it is considered always successful
NSLog(@"Opened output port: %@", portId);
return YES;
}
MIDIEndpointRef endpoint = 0;
ItemCount srcCount = MIDIGetNumberOfSources();
for (ItemCount i = 0; i < srcCount; ++i) {
MIDIEndpointRef src = MIDIGetSource(i);
SInt32 srcUniqueID = 0;
MIDIObjectGetIntegerProperty(src, kMIDIPropertyUniqueID, &srcUniqueID);
if (srcUniqueID == uniqueID) {
endpoint = src;
break;
}
}
if (endpoint == 0) {
NSLog(@"Port not found: %@", portId);
return NO;
}
OSStatus status = MIDIPortConnectSource(self.inputPort, endpoint, (void *)(uintptr_t)endpoint);
if (status != noErr) {
NSLog(@"Failed to connect input port: %@, status: %d", portId, status);
return NO;
}
self.openPorts[portId] = @(endpoint);
NSLog(@"Opened port: %@", portId);
return YES;
}

for me it would better map with js equivalent of this function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

development Develop some feature or integrate it with sth feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants