306 lines
8.4 KiB
C#
306 lines
8.4 KiB
C#
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<Port> ports = new List<Port>();
|
|
|
|
public int Id {
|
|
get {
|
|
return id;
|
|
}
|
|
}
|
|
|
|
public snd_seq_client_type_t Type {
|
|
get {
|
|
return type;
|
|
}
|
|
}
|
|
public string Name {
|
|
get {
|
|
return name;
|
|
}
|
|
}
|
|
|
|
public ReadOnlyCollection<Port> 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 override bool Equals (object obj)
|
|
{
|
|
return ((Client)obj).id == id;
|
|
}
|
|
}
|
|
|
|
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 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<Client> EnumClients ()
|
|
{
|
|
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)
|
|
{
|
|
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){
|
|
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)
|
|
{
|
|
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){
|
|
return Invoke.snd_seq_connect_to(seq_handle.Handle,outport,client,port)==0;
|
|
}
|
|
public static bool ConnectFrom(int client, int port){
|
|
return Invoke.snd_seq_connect_from(seq_handle.Handle,inport,client,port)==0;
|
|
}
|
|
|
|
public static void Deconnecte (int client, int port)
|
|
{
|
|
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++);
|
|
}
|
|
}
|
|
}*/
|
|
}
|
|
}
|
|
|