129 lines
4.1 KiB
C#
129 lines
4.1 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Collections.Concurrent;
|
|
|
|
namespace DMX2
|
|
{
|
|
public static partial class AlsaSeqLib
|
|
{ public class MidiPort : IDisposable
|
|
{
|
|
internal ConcurrentQueue<snd_seq_event_t> eventqueue = new ConcurrentQueue<snd_seq_event_t> ();
|
|
|
|
internal int portid;
|
|
public MidiPort(string portname){
|
|
portid=Invoke.snd_seq_create_simple_port (seq_handle.Handle,
|
|
portname,
|
|
SND_SEQ_PORT_CAP_WRITE
|
|
+ SND_SEQ_PORT_CAP_SUBS_WRITE
|
|
+ SND_SEQ_PORT_CAP_READ
|
|
+ SND_SEQ_PORT_CAP_SUBS_READ
|
|
,
|
|
SND_SEQ_PORT_TYPE_APPLICATION
|
|
);
|
|
openports[portid]=this;
|
|
}
|
|
|
|
bool closed = false;
|
|
public void Close()
|
|
{
|
|
if (closed)
|
|
return;
|
|
closed = true;
|
|
|
|
Invoke.snd_seq_delete_simple_port (seq_handle.Handle,
|
|
portid);
|
|
|
|
if(openports.ContainsKey(portid))
|
|
if (openports [portid] == this)
|
|
openports.Remove (portid);
|
|
}
|
|
|
|
void IDisposable.Dispose(){
|
|
Close ();
|
|
}
|
|
|
|
public void SendEvent(snd_seq_event_t ev){
|
|
if (seq_handle == null)
|
|
throw new InvalidOperationException ();
|
|
|
|
ev.source.client = (byte)clientId;
|
|
ev.source.port = (byte)portid;
|
|
ev.dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS;
|
|
ev.dest.port = SND_SEQ_ADDRESS_UNKNOWN;
|
|
ev.queue = SND_SEQ_QUEUE_DIRECT;
|
|
|
|
Marshal.StructureToPtr (ev, evOutPtr.Pointer, false);
|
|
Invoke.snd_seq_event_output (seq_handle.Handle, evOutPtr.Pointer);
|
|
Invoke.snd_seq_drain_output (seq_handle.Handle);
|
|
|
|
}
|
|
|
|
public bool GetEvent(out snd_seq_event_t ev){
|
|
return eventqueue.TryDequeue (out ev);
|
|
}
|
|
|
|
public bool ConnectTo(Port p){
|
|
if (seq_handle == null)
|
|
throw new InvalidOperationException ();
|
|
return Invoke.snd_seq_connect_to (seq_handle.Handle, portid, p.ClientId, p.PortId) == 0;
|
|
}
|
|
|
|
/*internal bool ConnectTo(int client, int port){
|
|
if (seq_handle == null)
|
|
throw new InvalidOperationException ();
|
|
return Invoke.snd_seq_connect_to (seq_handle.Handle, portid, client, port) == 0;
|
|
}*/
|
|
|
|
public bool ConnectFrom(Port p){
|
|
if (seq_handle == null)
|
|
throw new InvalidOperationException ();
|
|
return Invoke.snd_seq_connect_from (seq_handle.Handle, portid, p.ClientId, p.PortId) == 0;
|
|
}
|
|
|
|
public void Deconnecte(Port p){
|
|
if (seq_handle == null)
|
|
throw new InvalidOperationException ();
|
|
snd_seq_addr_t local = new snd_seq_addr_t ();
|
|
local.client = (byte)clientId;
|
|
local.port = (byte)portid;
|
|
|
|
snd_seq_addr_t addr;
|
|
using (PointerWrapper subqueryInfo = new PointerWrapper(GetQuerySubscribeInfoSize()))
|
|
using (PointerWrapper localAddr =new PointerWrapper(local.SndSeqAddrToPtr())) {
|
|
Invoke.snd_seq_query_subscribe_set_root (subqueryInfo.Pointer, localAddr.Pointer);
|
|
Invoke.snd_seq_query_subscribe_set_type (subqueryInfo.Pointer, SND_SEQ_QUERY_SUBS_WRITE);
|
|
|
|
for (Invoke.snd_seq_query_subscribe_set_index(subqueryInfo.Pointer,0);
|
|
Invoke.snd_seq_query_port_subscribers (seq_handle.Handle,subqueryInfo.Pointer)>=0;
|
|
Invoke.snd_seq_query_subscribe_set_index(subqueryInfo.Pointer,
|
|
Invoke.snd_seq_query_subscribe_get_index(subqueryInfo.Pointer) +1)
|
|
) {
|
|
addr = Invoke.snd_seq_query_subscribe_get_addr (subqueryInfo.Pointer).PtrToSndSeqAddr ();
|
|
|
|
if (addr.client != p.ClientId || addr.port != p.PortId)
|
|
continue;
|
|
|
|
Invoke.snd_seq_disconnect_from (seq_handle.Handle, portid, p.ClientId, p.PortId);
|
|
}
|
|
|
|
Invoke.snd_seq_query_subscribe_set_type (subqueryInfo.Pointer, SND_SEQ_QUERY_SUBS_READ);
|
|
|
|
for (Invoke.snd_seq_query_subscribe_set_index(subqueryInfo.Pointer,0);
|
|
Invoke.snd_seq_query_port_subscribers (seq_handle.Handle,subqueryInfo.Pointer)>=0;
|
|
Invoke.snd_seq_query_subscribe_set_index(subqueryInfo.Pointer,
|
|
Invoke.snd_seq_query_subscribe_get_index(subqueryInfo.Pointer) +1)
|
|
) {
|
|
addr = Invoke.snd_seq_query_subscribe_get_addr (subqueryInfo.Pointer).PtrToSndSeqAddr ();
|
|
if (addr.client != p.ClientId || addr.port != p.PortId)
|
|
continue;
|
|
Invoke.snd_seq_disconnect_to (seq_handle.Handle, portid, p.ClientId, p.PortId);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|