RaspberryPi virtual MIDI cable - raspberry-pi

I need to connect two MIDI programs with a virtual MIDI cable (or port) on Raspberry Pi 3 running Raspbian, exactly like loopMIDI does on Windows. (https://www.tobias-erichsen.de/software/loopmidi.html)
I know there has to be a way to create a virtual port using alsa or another common system on the PI, I just haven't been able to find that specific information/instruction.

You can use Jack for this. After installation, start Jack in a terminal with:
jack_control start
A Python example (requires JACKClient):
import jack
midiInBuffer = []
midiOutBuffer = []
client = jack.Client('jack')
midi_in = client.midi_inports.register('midi_in)
midi_out = client.midi_outports.register('midi_out')
#client.set_process_callback
def process(frames):
midi_out.clear_buffer()
if (len(midiOutBuffer)):
for msg in midiOutBuffer:
midi_out.write_midi_event(0, msg)
print('MIDI sent = ', msg)
midiOutBuffer.clear()
for offset, data in midi_in.incoming_midi_events():
msg = struct.unpack('3B', data)
midiInBuffer.append(msg)
print('MIDI rcvd = ', msg)
client.activate()
print(client.midi_inports)
print(client.midi_outports)
# forward all incoming messages from midi_in to midi_out
while True:
for msg in midiInBuffer
midiOutBuffer.append(msg)
print('MIDI fwd = ', msg)
midiInBuffer.clear()
Now use the jack:midi_out port to send the MIDI messages from one MIDI program to another and read these MIDI messages in the other MIDI program from the jack:midi_in port.

Related

How to make tap device use socket API?

I'm using tap device.
The problem is that you just can ->read() or ->write() one packet every system call.
After read the source file tun.c, I found there is struct socket in tun device and function tun_get_socket() can return it.
struct socket *tun_get_socket(struct file *file)
{
struct tun_file *tfile;
if (file->f_op != &tun_fops)
return ERR_PTR(-EINVAL);
tfile = file->private_data;
if (!tfile)
return ERR_PTR(-EBADFD);
return &tfile->socket;
}
EXPORT_SYMBOL_GPL(tun_get_socket);
The socket.ops is set with tun_socket_ops which have ->sendmsg() and ->recvmsg().
static const struct proto_ops tun_socket_ops = {
.sendmsg = tun_sendmsg,
.recvmsg = tun_recvmsg,
.release = tun_release,
};
The questions:
How to create one file descriptor to connect with this socket? That makes me to use ->sendmsg() and ->recvmsg() in userspace. My OS is CentOS7.9 with kernel version 3.10.0-1160.el7.x86_64.
Or is there other ways I can read or write multiple packets at one time from tap device?
Writing new kernel module is acceptable.

Unable to capture MQTT log callback

I am having trouble getting the on_log callback to trigger. I have used it on other programs w/o problems but this one is being difficult. I have included the relevant code snippets (I hope!). All other call backs are working fine. This program isn't threaded (except MQTT.start) so there aren't any other actions. Any suggestions where to look would be appreciated. fwiw, the problem I'm trying to track down is that MQTT stops responding after a few hours. The MQTT server is on a separate server, is used by numerous other processes and has no known issues.
# Set up MQTT - wait until we have an ipaddr so we know the network has been started
logger.debug("Waiting for ip address to be assigned")
while True:
ipaddr = get_local_IP()
if ipaddr is not None:
logger.info('IP address is {}'.format(ipaddr))
break
sleep(2.0)
logger.debug("Waiting for MQTT broker connection")
mqttc = mqtt.Client()
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
while True:
try:
mqttc.connect("192.168.0.18", 1884, 30)
except IOError as e:
if e.errno != errno.ENETUNREACH:
raise
logger.warning('Network error - retrying')
sleep(15)
continue
logger.debug('Connect initiated without error')
break
mqttc.loop_start()
mqttc.on_log = on_log
while not MQ_link:
sleep(1)
def on_connect(mqttc, obj, flags, rc):
global MQ_link
logger.debug("Connected: rc = " + str(rc))
if rc == 0:
MQ_link = True
def on_log(mqttc, obj, level, string):
verb = string.split('(').strip()
if verb[0] not in ['Sending PINGREQ', 'Received PINGRESP']:
logger.debug('LOG: ' + string)

UWP DatagramsSocket doesn't not fire MessageReceived

I'm working on a UWP application which should communicate via TCP/UDP to a remote device. My issue is that the UWP app successfully sends UDP messages to the remote device, but does not receive the replies.
Here follows the code extracted from the app (simplified):
async Task TestUdpIP()
{
// Writer to the DatagramSocket
DataWriter writer;
using (var udpClient = new DatagramSocket())
{
try
{
// UDP Socket binding
udpClient.MessageReceived += UdpClient_MessageReceived;
var controllerName = new Windows.Networking.HostName(controllerIpAddress.ToString());
await udpClient.BindEndpointAsync(controllerName, controllerIpPort.ToString());
var remoteHostName = new Windows.Networking.HostName(hostIpAddres.ToString());
await udpClient.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Create a message to send
string message = "Some message";
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpClient.OutputStream);
writer.WriteString(message);
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(5000);
}
catch
{
}
}
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
However the UdpClient_MessageReceived handler does not fire. I'm sure that UDP messages are correctly sent from the UWP app and that the remote device replies back as shown in the following screenshot from Wireshark (the test has been taken on the same PC where the UWP app is running)
.
(IP Address, Port) details are shown in the following list to better explain the picture above
UWP application: (192.168.1.108, 19000) to send and receive.
Remote device: (192.168.1.152, 15999) to receive and (192.168.1.152, 54697) to send
Note: this is a similar question, where the answer says that for whatever reason the DatagramSocket should fire some messages before being able to receive. In my example a message is sent out however the message received handler does not fire anyway.
Note: The UWP app has been granted the internet (client) and the internet (client and server) capabilities
Note: I've tried also this (more readable) approach to bind the inbound/outbound datagram socket on the UWP app obtaining the same results:
// UDP Socket binding
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
EndpointPair endpointpar = new EndpointPair(controllerName,
controllerIpPort.ToString(),
remoteHostName,
remoteHostPort.ToString());
udpClient.MessageReceived += UdpClient_MessageReceived;
await udpClient.ConnectAsync(endpointpar);
Where is the issue? Many thanks!
Please try to also add the Private Networks (Client & Server) capability in your app's manifest.
On other hand, you can try the Official DatagramSocket sample to see whether the both devices can communicate with each other.
After some experimenting, I came out with the idea of using two different DatagramSocket instances: one to send out UDP messages, and one to listen for incoming messages. With this code, I've been able to send UDP messages to the remote device (as before) and also I've been able to receive UDP messages from the remote device.
async Task TestUdpIP_DifferentPorts()
{
// Writer to the DatagramSocket
DataWriter writer;
// Inbound and outbound DatagramSocket
DatagramSocket udpListener = new DatagramSocket();
DatagramSocket udpSender = new DatagramSocket();
try
{
// String containing the serializaed message
string serializedMessage = "Some message";
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
// Bind listener
udpListener.MessageReceived += UdpClient_MessageReceived;
await udpListener.BindEndpointAsync(controllerName, controllerIpPort.ToString());
// Connect sender
await udpSender.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpSender.OutputStream);
writer.WriteString(JsonConvert.SerializeObject(message));
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(1000);
}
catch (Exception ex)
{
// Some exception handling
}
udpSender.Dispose();
udpListener.Dispose();
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
With this approach only the IP port (or service name) of the inbound listener needs to be specified. The framework will choose the next available outbound IP port.
Note: If I understand well the DatagramSocket.ConnectAsync(EndpointPair) documentation, the same DatagramSocket instance can be used to send and listen for incoming message, so I could not figure out the need for two different instances. From the documentation:
This ConnectAsync(EndPointPair) method on a DatagramSocket is used to define the local and remote endpoint where datagrams will be sent when using the OutputStream property. This method also restricts remote IP addresses of packets that will be accepted to the remote hostname in the endpointPair parameter. Only incoming packets that match the remote endpoint in the endpointPair parameter will trigger the MessageReceived event on the DatagramSocket.

UDP port arduino increment after packet sent

I'm working on a code to communicate two arduinos, one with ethernet shield and another with an ENC28J60 ethernet module. I'm not a newbie in arduino neither an wise/expert yet. But i'm a complete -and less than a- newbie in UDP communication.
Here is the question: my code works fine, it sends and receives UDP packets from one to another and viceversa. But after every packet is sent, it increment in one the "Udp.remotePort" value (that viewing from the "udp-reader" side). It starts from 1024 up to ~32000 (and starts over after reach the highest value). I have researched about UDP and i understand that the first 0-1023 are reserved for specifics services p.e. 80 http, 21 ftp. But i think it should not be incremented after every send. Or it should?
I don't paste the code because as i said it works OK. I just would like to know what could be wrong from your experience.
The sentence i'm using to write the packets is:
udp.beginPacket(IPAddress([ip address]), [port no]);
The libraries i'm using:
UIPEthernet.h https://github.com/UIPEthernet/UIPEthernet for ENC28J60
Ethernet.h for ethernet shield
EDIT: This is the code of the UDP sender (ENC28J60). Basically is the example code of the library as i said it works correctly in terms of communication. I only changed the IPs: 192.168.1.50 which is the UDP sender and 192.168.1.51 which is the UDP destination.
#include <UIPEthernet.h>
EthernetUDP udp;
unsigned long next;
void setup() {
Serial.begin(115200);
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
Ethernet.begin(mac,IPAddress(192,168,1,51));
// Also i used: Ethernet.begin(mac,IPAddress(192,168,1,51), 5000);
// with the same result
next = millis()+2000;
}
void loop() {
int success;
int len = 0;
if (((signed long)(millis()-next))>0)
{
do
{
success = udp.beginPacket(IPAddress(192,168,1,50),5000);
Serial.print("beginPacket: ");
Serial.println(success ? "success" : "failed");
//beginPacket fails if remote ethaddr is unknown. In this case an
//arp-request is send out first and beginPacket succeeds as soon
//the arp-response is received.
}
while (!success && ((signed long)(millis()-next))<0);
if (!success )
goto stop;
success = udp.write("hello world&from&arduino");
Serial.print("bytes written: ");
Serial.println(success);
success = udp.endPacket();
Serial.print("endPacket: ");
Serial.println(success ? "success" : "failed");
do
{
//check for new udp-packet:
success = udp.parsePacket();
}
while (!success && ((signed long)(millis()-next))<0);
if (!success )
goto stop;
Serial.print("received: '");
do
{
int c = udp.read();
Serial.write(c);
len++;
}
while ((success = udp.available())>0);
Serial.print("', ");
Serial.print(len);
Serial.println(" bytes");
//finish reading this packet:
udp.flush();
stop:
udp.stop();
next = millis()+2000;
}
}
EDIT 2: This is a capture of testing with SocketTest listening on port 5000, and after a packet received, the next one arrives with the remote port incremented on 1 each time
You must be creating a new UDP socket per sent datagram. Don't do that. Use the same one for the life of the application.

Send packet with sockets from kernel module

I am writing a kernel module that should receive messages from user-space and send response back via socket.
When program and module are on the same machine and I use IP 127.0.0.1, everything works fine. But when I try it on different machines and use real network IP, something like 192.168.3.146 it works only in one way.
I receive message from user-space, but I can not receive it from kernel. I use sock_sendmsg function for sending message from kernel and it's not return any error. Also I am not get any messages from firewall that something is came up from another machine, from kernel module.
Here were similar questions and examples, but they were not useful enough for me or examples were used too old kernel version.For skeleton I used this one,from UDP sockets: http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-3.html. Any help?
Kernel module code for sending:
void send_data(unsigned char *data)
{
if(!IS_ERR_OR_NULL(data))
{
int ret;
mm_segment_t oldfs;
struct msghdr message;
struct iovec ioVector;
struct sockaddr_in sendAddr;
sendAddr.sin_family = AF_INET;
sendAddr.sin_addr.s_addr = INADDR_ANY;
//sendAddr.sin_addr.s_addr = in_aton("192.168.1.75");
//here I get port from sk_buff structure that I received.
sendAddr.sin_port = *((unsigned short*)skBuffer->data);
memset(&message, 0, sizeof(message));
message.msg_name = &sendAddr;
message.msg_namelen = sizeof(sendAddr);
/* send the message back */
ioVector.iov_base = data;
ioVector.iov_len = strlen(data);
message.msg_iov = &ioVector;
message.msg_iovlen = 1;
message.msg_control = NULL;
message.msg_controllen = 0;
oldfs = get_fs();
set_fs(KERNEL_DS);
ret = sock_sendmsg(sendSocket, &message, strlen(data));
set_fs(oldfs);
}
}
I found an alternative solution, using netpoll sockets. It is more easier than sockets, I used before and it works. The answer and proper code is here, on another StackOverflow question.