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 eventqueue = new ConcurrentQueue (); 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); } } } } } }