MIDI messages are multiplying - ios

I keep running into a strange issue when running AKMIDI on IOS. I also think it may be an IOS problem and not necessarily from Audiokit. I can connect a MIDI controller to IPad and receive messages as expected using the MIDI listener protocol after I open the input. If I disconnect the MIDI controller by cycling the power or unplugging it from the IPad and then reconnect it, I then start receiving two identical messages at each event. If I cycle the power again I start getting three messages, etc. I should also mention that when I detect the device is removed I close the input and clear the listeners. When I detect the new connection I open the input and start over. Does anyone know what can cause this to happen?

I think I have found a workaround for this:
If I only open the midi in and midi out one time, when my device is first detected, it seems to work correctly. I now only close the in and out when the app is terminated. You can cycle the power on the midi controller and it will still communicate with the app when it reconnects. I am also now using the more generic calls openInput(), addListener(self), openOutput().

Related

APIs are not responding fast is APP is using Multipeer Connectivity framework

I am using Multipeer Connectivity Framework in my APP and its working absolutely fine but when APP is invoking any API or downloading any file from server then its delaying the response. Sometimes its failed and sometimes I am getting Time out error.
I have also checked "Network" status on xCode debug navigator and found that speed is going up and down instantly and never going beyond 6kb/s and sometimes its showing as 0 kb/s but when I disable Multipeer Connectivity then it works fine and speed going at 70kb/s too.
I have also noticed that if bluetooth is ON then its happening not with the Wifi.
Any suggestion would be really appreciable.
This is happening because when advertising, Multipeer always advertises on the wifi (there's no way to say bluetooth only). The way it advertises is by switching the wifi access mode into adhoc multiple times per second to find other peers, then switching back to AP mode (ie. resuming its connection to your wifi router). Doing this is highly disruptive to large transfers.
You have two options to fix this:
1) as soon as you can, after getting connected, call stopAdvertising(). This will stop the wifi mode from being constantly changed, and your throughput will resume at its normal rate. Warning: you cannot micro-manage this, because it takes up to 30 seconds after calling stopAdvertising() until it takes effect
2) switch from Multipeer to an alternative framework that allows you to specify bluetooth-only, and only use bluetooth. I wrote one called BluePeer which I use in my apps. It is unicast (not multicast) and supports roles like Client/Server (as well as role-less like Multipeer)

CoreBluetooth: detect device out of range/ connection timeout

I am designing an iOS framework to handle multiple BLE devices (all of the same kind). Everything is working very well at the moment, except one thing:
The client wants a list with available devices. But how can I detect when a device, that has been discovered in the past, is not available anymore?
Another problem occurs, when I try to connect to a device that is not available anymore. Documentation says: Connection attempts never time out and
And yes, I never get an error via didFailToConnectPeripheral.
I did some research but couldn't figure out how handle these problems via CoreBluetooth properly. So I developed my own solutions, but I am not sure if that is the right way (or at least a good way, cause there may be several ways to do it).
1. Detecting devices that are not available anymore
I scan with
[_centralManager scanForPeripheralsWithServices:services options:#{CBCentralManagerScanOptionAllowDuplicatesKey: #(TRUE)}];
so I receive advertisments all the time as long as a device is not connected. I check with a timer that the advertisement reoccured in a given time interval (large enough corresponding to the devices ad interval). If the advertisement didn't occur in the interval, I remove the device from the list.
2. Detecting connection timeout
Well, that's a pretty easy one I think. I use my own timeout function and cancel the connection request if the timer expires.
If somebody ever came across these problem, I would be very interested in your opinion and/or your solution of course.
UPDATE 2014-12-17:
In the meantime I worked on my own solution using timers and it seems to work pretty well.
Connection timeout is straight forward. Simply set a timer to 5 seconds or whatever you think is good for you. If the timer expires and the device did not connect, simply cancel the connection and tell the user that there was a problem.
Detecting devices that go out of range was a bit trickier. For every discovered device I start a timer that fires after double the time, the device sends advertisements. If the device does send another advertisement till the timer expires, it probably went out of range or was turned off or connected to another device.
I don't want to answer my own question because I hope that maybe Apple will one day take care of those problems.
The correct way to determine whether a device is available is to store the peripheral identifier value. Before you attempt to reconnect, call retrievePeripheralsWithIdentifiers. However, this still does not guarantee that the device will be in range by the time you attempt to connect!
Connection attempts do not time out at the OS level, and this is explicitly documented.
Some apps may need to use the Core Bluetooth framework to perform
long-term actions in the background. As an example, imagine you are
developing a home security app for an iOS device that communicates
with a door lock (equipped with Bluetooth low energy technology). The
app and the lock interact to automatically lock the door when the user
leaves home and unlock the door when the user returns—all while the
app is in the background. When the user leaves home, the iOS device
may eventually become out of range of the lock, causing the connection
to the lock to be lost. At this point, the app can simply call the
connectPeripheral:options: method of the CBCentralManager class, and
because connection requests do not time out, the iOS device will
reconnect when the user returns home.

Disconnect external accessory without physically disconnecting

My app communicates with an external device via EA Framework. I would like to do a "soft disconnect", i.e. a software disconnect without actually physically disconnecting the device. The only way I see for a soft disconnect is to close the EASession's inputStream and outputStream. Question: Will the external device know I have closed the streams so it doesn't attempt to communicate further? Is there another way to do soft disconnect?
i think that actually is impossible to do a real soft disconnection.
i say 'think' cause you never stop learning on EA Framework (One week ago i found the showBluetoothAccessoryPickerWithNameFilter for example, maybe is useful for you for inApp-connection).
I use a EASession(s) manager to easily switch between connections. so forgot the word 'disconnection' and replace it with 'switch' :D
If you need disconnection, implements some function on btdevice-side and execute this to disconnect as soon as you receive a command from the iPhone.

How to sync counter via sockets on iPad

I have a Application on a PC which displays time-information for a mp3 song that is played. I now need to display this time information within an iPad App. The counting timers for remaining time, player position and song length must be in sync between iPad an PC.
I thought about using a socket connection (AsyncSocket on iPad) to keep the counters in sync.
Is there a better way doing this? I don't want to run in the wrong direction...
Additional, it should be possible to have more than one iPad showing the Information in future. That's a "nice to have" feature...
I don't need ready to use code snippets, it's more a theoretical question. (if someone has a ready to use code snippet, that's also good for me :-) )
MadMaxApp
i now used the AsyncSocket to solve the requirements. It works perfectly. Don't forget the handling of closing the socket connection if the app goes in background. Depending on the server the app is talking with, not closing the socket can lead to a problem in reconnecting.

How can I generate programmatically a MIDI event on iPad

I would like to test a MIDI app and want to generate some MIDI events without attaching a physical keyboard. Any hints?
If you are using CoreMidi, setup your app to use MIDINetworkSessions. Once you advertise your iPad over the network, use any MIDI sequencer etc to connect to it and send messages over WiFi.
That way you can test without constantly unplugging/replugging things, and while still tethered to Xcode which is a huge bonus.
The other option would be to create an artificial MIDIPacketList and send it directly to your handler, but this is a lot less flexible.
If you mean sending a MIDI event to an iPad, then you could use a simple program like Rondo to play a MIDI file to it.
I suppose you need some source codes to generate MIDI events on iPad.
I found this one. It is a wrapper class of CoreMIDI, and it has source codes of sending/receiving some MIDI events.
RCTMidiLib
https://github.com/recotana/RCTMidiLib
I connect iPad and Mac wirelessly, and successfully send/receive MIDI events using the test application on iPad.

Resources