using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Collections.ObjectModel; namespace DMX2 { public static partial class AlsaSeqLib { static SeqHandleWrapper seq_handle = null; static int clientId; static int inport; static int outport; public class Client { int id; snd_seq_client_type_t type; string name; List ports = new List (); public int Id { get { return id; } } public snd_seq_client_type_t Type { get { return type; } } public string Name { get { return name; } } public ReadOnlyCollection Ports { get { return ports.AsReadOnly (); } } internal Client (PointerWrapper clientInfo) { id = Invoke.snd_seq_client_info_get_client (clientInfo.Pointer); IntPtr nameptr = Invoke.snd_seq_client_info_get_name (clientInfo.Pointer); name = nameptr.PtrToString (); type = (snd_seq_client_type_t)Invoke.snd_seq_client_info_get_type (clientInfo.Pointer); using (PointerWrapper portInfo = new PointerWrapper(GetPortInfoSize ())) { Invoke.snd_seq_port_info_set_client (portInfo.Pointer, id); Invoke.snd_seq_port_info_set_port (portInfo.Pointer, -1); while (Invoke.snd_seq_query_next_port(seq_handle.Handle, portInfo.Pointer) >= 0) { ports.Add (new Port (portInfo)); } } } } public static int ClientId { get { return clientId; } } public class Port { int portId; int clientId; string name; uint caps; uint type; public int ClientId { get { return clientId; } } public int PortId { get { return portId; } } public string Name { get { return name; } } public uint Caps { get { return caps; } } public uint Type { get { return type; } } internal Port (PointerWrapper portInfo) { clientId = Invoke.snd_seq_port_info_get_client (portInfo.Pointer); portId = Invoke.snd_seq_port_info_get_port (portInfo.Pointer); IntPtr namePtr = Invoke.snd_seq_port_info_get_name (portInfo.Pointer); caps = Invoke.snd_seq_port_info_get_capability (portInfo.Pointer); type = Invoke.snd_seq_port_info_get_type (portInfo.Pointer); name = namePtr.PtrToString (); } } public static void Init () { if (seq_handle != null) return; seq_handle = new SeqHandleWrapper (); clientId = Invoke.snd_seq_client_id (seq_handle.Handle); outport = inport = Invoke.snd_seq_create_simple_port (seq_handle.Handle, "dmx_ctrl", 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 ); } public static void Close () { if (seq_handle == null) return; seq_handle.Dispose (); seq_handle = null; } public static bool GetEvent (out snd_seq_event_t ev) { if (seq_handle == null) throw new InvalidOperationException (); ev = new snd_seq_event_t (); if (Invoke.snd_seq_event_input_pending (seq_handle.Handle, 1) <= 0) return false; IntPtr evPtr; // Recup du pointeur vers l'ev Invoke.snd_seq_event_input (seq_handle.Handle, out evPtr); // Copie de la zone mémoire dans une structure managee ev = (snd_seq_event_t)Marshal.PtrToStructure (evPtr, typeof(snd_seq_event_t)); // liberation du pointeur Invoke.snd_seq_free_event (evPtr); // TODO : Manage System Events here return true; } static PointerWrapper evOutPtr = new PointerWrapper (32); public static void SendEvent (snd_seq_event_t ev) { if (seq_handle == null) throw new InvalidOperationException (); ev.queue = SND_SEQ_QUEUE_DIRECT; ev.source.client = (byte)clientId; ev.source.port = (byte)outport; 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 static void SendEventToSubscribers (snd_seq_event_t ev) { if (seq_handle == null) throw new InvalidOperationException (); ev.dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS; ev.dest.port = SND_SEQ_ADDRESS_UNKNOWN; SendEvent (ev); } public static IEnumerable EnumClients () { if (seq_handle == null) throw new InvalidOperationException (); using (PointerWrapper clientInfo = new PointerWrapper(GetClientInfoSize())) { Invoke.snd_seq_client_info_set_client (clientInfo.Pointer, -1); while (Invoke.snd_seq_query_next_client(seq_handle.Handle,clientInfo.Pointer)>=0) { yield return new Client (clientInfo); } } } public static Client GetClientByID (int client) { if (seq_handle == null) throw new InvalidOperationException (); using (PointerWrapper clientInfo = new PointerWrapper(GetClientInfoSize())) { if (Invoke.snd_seq_get_any_client_info (seq_handle.Handle, client, clientInfo.Pointer) >= 0) { return new Client (clientInfo); } else return null; } } public static Port GetPortByIDs (int client, int port) { if (seq_handle == null) throw new InvalidOperationException (); using (PointerWrapper portInfo = new PointerWrapper(GetPortInfoSize ())) { if (Invoke.snd_seq_get_any_port_info (seq_handle.Handle, client, port, portInfo.Pointer) >= 0) { return new Port (portInfo); } else return null; } } public static bool Connect (Port port) { if (seq_handle == null) throw new InvalidOperationException (); bool isInput = (port.Caps & SND_SEQ_PORT_CAP_WRITE) == SND_SEQ_PORT_CAP_WRITE; bool isOutput = (port.Caps & SND_SEQ_PORT_CAP_READ) == SND_SEQ_PORT_CAP_READ; if (isInput) if (!ConnectTo (port.ClientId, port.PortId)) return false; if (isOutput) if (!ConnectFrom (port.ClientId, port.PortId)) return false; return true; } public static bool ConnectTo (int client, int port) { if (seq_handle == null) throw new InvalidOperationException (); return Invoke.snd_seq_connect_to (seq_handle.Handle, outport, client, port) == 0; } public static bool ConnectFrom (int client, int port) { if (seq_handle == null) throw new InvalidOperationException (); return Invoke.snd_seq_connect_from (seq_handle.Handle, inport, client, port) == 0; } public static void Deconnecte (int client, int port) { if (seq_handle == null) throw new InvalidOperationException (); snd_seq_addr_t local = new snd_seq_addr_t (); local.client = (byte)clientId; local.port = (byte)inport; 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) ) { //root = Invoke.snd_seq_query_subscribe_get_root(subqueryInfo.Pointer).PtrToSndSeqAddr(); addr = Invoke.snd_seq_query_subscribe_get_addr (subqueryInfo.Pointer).PtrToSndSeqAddr (); if (addr.client != client || addr.port != port) continue; Invoke.snd_seq_disconnect_from (seq_handle.Handle, inport, client, port); } 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) ) { //root = Invoke.snd_seq_query_subscribe_get_root(subqueryInfo.Pointer).PtrToSndSeqAddr(); addr = Invoke.snd_seq_query_subscribe_get_addr (subqueryInfo.Pointer).PtrToSndSeqAddr (); if (addr.client != client || addr.port != port) continue; Invoke.snd_seq_disconnect_to (seq_handle.Handle, outport, client, port); } } } /* public static void GetConnections() { using(PointerWrapper subscribeInfo = new PointerWrapper(GetQuerySubscribeInfoSize())){ int index=0; Invoke.snd_seq_query_subscribe_set_client (subscribeInfo.Pointer,clientId); Invoke.snd_seq_query_subscribe_set_port (subscribeInfo.Pointer,inport); Invoke.snd_seq_query_subscribe_set_index(subscribeInfo.Pointer,index++); Invoke.snd_seq_query_subscribe_set_type(subscribeInfo.Pointer,SND_SEQ_QUERY_SUBS_WRITE); while (Invoke.snd_seq_query_port_subscribers(seq_handle.Handle,subscribeInfo.Pointer) ==0){ //Console.WriteLine("Remote => {0}:{1}",rclient,rport); Invoke.snd_seq_query_subscribe_set_index(subscribeInfo.Pointer,index++); } } }*/ } }