285 lines
6.7 KiB
C#
285 lines
6.7 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;
|
|
|
|
static System.Threading.Thread eventthread = null;
|
|
//static MidiPort systemPort = null;
|
|
|
|
static internal Dictionary<int, MidiPort> openports = new Dictionary<int, MidiPort>();
|
|
|
|
public static int ClientId{
|
|
get {
|
|
return clientId;
|
|
}
|
|
}
|
|
|
|
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 (Port.GetPort(portInfo));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*public static int ClientId {
|
|
get {
|
|
return clientId;
|
|
}
|
|
}*/
|
|
|
|
public class Port
|
|
{
|
|
int portId;
|
|
int clientId;
|
|
string name;
|
|
uint caps;
|
|
uint type;
|
|
int srcid;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
public int SrcId
|
|
{
|
|
get
|
|
{
|
|
return srcid;
|
|
}
|
|
}
|
|
|
|
private Port(int _clientId, int _portId)
|
|
{
|
|
clientId = _clientId;
|
|
portId = _portId;
|
|
srcid = clientId << 8 + portId;
|
|
ports.Add(srcid, this);
|
|
}
|
|
|
|
private void Updateinfo (PointerWrapper portInfo)
|
|
{
|
|
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 ();
|
|
}
|
|
|
|
internal static Port GetPort(PointerWrapper portInfo)
|
|
{
|
|
Port p;
|
|
int clientId = Invoke.snd_seq_port_info_get_client(portInfo.Pointer);
|
|
int portId = Invoke.snd_seq_port_info_get_port(portInfo.Pointer);
|
|
int srcid = clientId << 8 + portId;
|
|
|
|
if (ports.ContainsKey(srcid))
|
|
p = ports[srcid];
|
|
else
|
|
p = new Port(clientId, portId);
|
|
|
|
p.Updateinfo(portInfo);
|
|
return p;
|
|
}
|
|
internal static Port GetPort(int clientId, int portId)
|
|
{
|
|
int srcid = clientId << 8 + portId;
|
|
if (ports.ContainsKey(srcid))
|
|
return ports[srcid];
|
|
return null;
|
|
}
|
|
|
|
static Dictionary<int, Port> ports = new Dictionary<int, Port>();
|
|
}
|
|
|
|
public static void Init (string appname)
|
|
{
|
|
if (seq_handle != null)
|
|
return;
|
|
|
|
seq_handle = new SeqHandleWrapper (appname);
|
|
|
|
clientId = Invoke.snd_seq_client_id (seq_handle.Handle);
|
|
|
|
System.Threading.ThreadStart ts = new System.Threading.ThreadStart (EventLoop);
|
|
eventthread = new System.Threading.Thread (ts);
|
|
eventthread.Start();
|
|
//systemPort = new MidiPort ("system");
|
|
//systemPort.ConnectTo (SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
|
|
}
|
|
|
|
public static void Close ()
|
|
{
|
|
if (seq_handle == null)
|
|
return;
|
|
seq_handle.Dispose ();
|
|
seq_handle = null;
|
|
}
|
|
|
|
public static void EventLoop(){
|
|
snd_seq_event_t ev = new snd_seq_event_t ();;
|
|
while (seq_handle != null) {
|
|
while (seq_handle != null && Invoke.snd_seq_event_input_pending (seq_handle.Handle, 1) > 0) {
|
|
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);
|
|
|
|
/*if (ev.dest.port == systemPort.portid) {
|
|
if (ev.type == AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_PORT_START) {
|
|
|
|
}
|
|
} else {*/
|
|
// queue
|
|
if (openports.ContainsKey (ev.dest.port)) {
|
|
openports [ev.dest.port].eventqueue.Enqueue (ev);
|
|
}
|
|
//}
|
|
}
|
|
System.Threading.Thread.Sleep (1);
|
|
}
|
|
}
|
|
|
|
/*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 IEnumerable<Client> 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 clientid, int portid)
|
|
{
|
|
if (seq_handle == null)
|
|
throw new InvalidOperationException ();
|
|
using (PointerWrapper portInfo = new PointerWrapper(GetPortInfoSize ())) {
|
|
if (Invoke.snd_seq_get_any_port_info (seq_handle.Handle, clientid, portid, portInfo.Pointer) >= 0) {
|
|
return Port.GetPort (portInfo);
|
|
} else
|
|
return Port.GetPort (clientid,portid);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|