This commit is contained in:
tzim 2014-05-25 21:13:59 +00:00
parent 0610ed4150
commit 89fd0f36c6
4 changed files with 306 additions and 261 deletions

View file

@ -27,7 +27,8 @@ namespace DMX2
public const byte SND_SEQ_ADDRESS_BROADCAST = 255;
public const byte SND_SEQ_QUEUE_DIRECT = 253;
public enum snd_seq_client_type_t : int {
public enum snd_seq_client_type_t : int
{
SND_SEQ_USER_CLIENT = 1,
SND_SEQ_KERNEL_CLIENT = 2
}
@ -276,6 +277,7 @@ namespace DMX2
}
return _subscriberInfoSize;
}
static int GetQuerySubscribeInfoSize ()
{
if (_query_subscribeInfoSize == 0) {

View file

@ -97,20 +97,25 @@ namespace DMX2
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_port_subscribe_sizeof ();
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_query_subscribe_sizeof ();
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_query_subscribe_get_client (IntPtr info);
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_query_subscribe_get_port (IntPtr info);
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_query_subscribe_get_queue (IntPtr info);
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_query_subscribe_get_time_real (IntPtr info);
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_query_subscribe_get_time_update (IntPtr info);
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_query_subscribe_get_exclusive (IntPtr info);
@ -140,6 +145,7 @@ namespace DMX2
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr snd_seq_query_subscribe_get_addr (IntPtr subs);
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr snd_seq_query_subscribe_get_root (IntPtr subs);
@ -175,6 +181,7 @@ namespace DMX2
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_connect_to (IntPtr handle, int myport, int dest_client, int dest_port);
[DllImport(ASOUND_LIB_NAME, CallingConvention = CallingConvention.Cdecl)]
public static extern int snd_seq_disconnect_from (IntPtr handle, int myport, int src_client, int src_port);

View file

@ -8,7 +8,6 @@ namespace DMX2
public static partial class AlsaSeqLib
{
static SeqHandleWrapper seq_handle = null;
static int clientId;
static int inport;
static int outport;
@ -19,7 +18,6 @@ namespace DMX2
int id;
snd_seq_client_type_t type;
string name;
List<Port> ports = new List<Port> ();
public int Id {
@ -33,6 +31,7 @@ namespace DMX2
return type;
}
}
public string Name {
get {
return name;
@ -45,7 +44,8 @@ namespace DMX2
}
}
internal Client(PointerWrapper clientInfo){
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 ();
@ -79,6 +79,7 @@ namespace DMX2
return clientId;
}
}
public int PortId {
get {
return portId;
@ -103,7 +104,8 @@ namespace DMX2
}
}
internal Port(PointerWrapper portInfo){
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);
@ -115,7 +117,8 @@ namespace DMX2
public static void Init ()
{
if(seq_handle!=null) return;
if (seq_handle != null)
return;
seq_handle = new SeqHandleWrapper ();
@ -130,16 +133,19 @@ namespace DMX2
public static void Close ()
{
if(seq_handle==null) return;
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();
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;
if (Invoke.snd_seq_event_input_pending (seq_handle.Handle, 1) <= 0)
return false;
IntPtr evPtr;
@ -158,13 +164,12 @@ namespace DMX2
}
static PointerWrapper evOutPtr = new PointerWrapper (32);
public static void SendEvent (snd_seq_event_t ev)
{
if(seq_handle==null) throw new InvalidOperationException();
if (seq_handle == null)
throw new InvalidOperationException ();
ev.queue = SND_SEQ_QUEUE_DIRECT;
ev.source.client = (byte)clientId;
ev.source.port = (byte)outport;
@ -175,7 +180,8 @@ namespace DMX2
public static void SendEventToSubscribers (snd_seq_event_t ev)
{
if(seq_handle==null) throw new InvalidOperationException();
if (seq_handle == null)
throw new InvalidOperationException ();
ev.dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS;
ev.dest.port = SND_SEQ_ADDRESS_UNKNOWN;
SendEvent (ev);
@ -183,7 +189,8 @@ namespace DMX2
public static IEnumerable<Client> EnumClients ()
{
if(seq_handle==null) throw new InvalidOperationException();
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) {
@ -194,7 +201,8 @@ namespace DMX2
public static Client GetClientByID (int client)
{
if(seq_handle==null) throw new InvalidOperationException();
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);
@ -203,20 +211,22 @@ namespace DMX2
}
}
public static Port GetPortByIDs(int client,int port){
if(seq_handle==null) throw new InvalidOperationException();
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
} else
return null;
}
}
public static bool Connect (Port port)
{
if(seq_handle==null) throw new InvalidOperationException();
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;
@ -231,27 +241,31 @@ namespace DMX2
return true;
}
public static bool ConnectTo(int client, int port){
if(seq_handle==null) throw new InvalidOperationException();
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();
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();
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()))
{
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);

View file

@ -15,7 +15,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
@ -26,7 +25,8 @@ namespace DMX2
public class MidiEventProvider : IEventProvider, IDisposable
{
class internalEvent {
class internalEvent
{
readonly string internalName;
bool bound = false;
@ -60,7 +60,6 @@ namespace DMX2
}
}
public internalEvent (string _id, uint _page, int _evHCode)
{
internalName = _id;
@ -80,6 +79,7 @@ namespace DMX2
}
AlsaSeqLib.snd_seq_event_t storedevent;
public AlsaSeqLib.snd_seq_event_t StoredEvent {
get {
return storedevent;
@ -89,13 +89,15 @@ namespace DMX2
}
}
}
abstract class feedbackinfo : IFeedbackInfo {
abstract class feedbackinfo : IFeedbackInfo
{
MidiEventProvider prov;
readonly internalEvent iev;
protected AlsaSeqLib.snd_seq_event_t ev;
public feedbackinfo(MidiEventProvider _prov, internalEvent _iev){
public feedbackinfo (MidiEventProvider _prov, internalEvent _iev)
{
prov = _prov;
iev = _iev;
}
@ -108,7 +110,8 @@ namespace DMX2
bool update = UpdateEvent (data);
iev.StoredEvent = ev;
if (!update) return true;
if (!update)
return true;
iev.LastKnownValue = data;
@ -123,7 +126,9 @@ namespace DMX2
}
#endregion
}
class ctrlfeedbackinfo : feedbackinfo {
class ctrlfeedbackinfo : feedbackinfo
{
public ctrlfeedbackinfo (MidiEventProvider _prov, internalEvent _iev, byte channel, uint param)
:base(_prov,_iev)
{
@ -136,12 +141,15 @@ namespace DMX2
protected override bool UpdateEvent (byte data)
{
int newvalue = (int)data * 127 / 255;
if(newvalue==ev.data_ev_ctrl.value) return false;
if (newvalue == ev.data_ev_ctrl.value)
return false;
ev.data_ev_ctrl.value = newvalue;
return true;
}
}
class pitchbendfeedbackinfo : feedbackinfo {
class pitchbendfeedbackinfo : feedbackinfo
{
public pitchbendfeedbackinfo (MidiEventProvider _prov, internalEvent _iev, byte channel)
:base(_prov,_iev)
{
@ -152,19 +160,24 @@ namespace DMX2
protected override bool UpdateEvent (byte data)
{
int newvalue = (int)data * 16000 / 255-8000;
if(newvalue==ev.data_ev_ctrl.value) return false;
int newvalue = (int)data * 14000 / 255 - 7000;
if (newvalue == ev.data_ev_ctrl.value)
return false;
ev.data_ev_ctrl.value = newvalue;
return true;
}
}
public class MidiDev{
public class MidiDev
{
string name;
public string Name { get { return name; } }
public bool HasFeedback { get; set; }
readonly List<int> connected = new List<int> ();
public List<int> ConnectedPorts {
get{ return connected;}
}
@ -199,14 +212,10 @@ namespace DMX2
/// Soit recue, soit envoyée (feedback / changement de page)
/// </summary>
readonly Dictionary<int,byte> lastValueOfSrc = new Dictionary<int, byte> ();
EventData last;
internalEvent levent = null;
bool connected = false;
bool guirefreshflag = false;
uint page = 1;
uint maxpage = 8;
@ -215,7 +224,8 @@ namespace DMX2
return page;
}
set {
if(value<1 || value > maxpage) return;
if (value < 1 || value > maxpage)
return;
page = value;
Refresh ();
}
@ -229,6 +239,7 @@ namespace DMX2
maxpage = value;
}
}
public List<byte> UnpaginatedChannels {
get {
return unpaginatedchannels;
@ -245,7 +256,6 @@ namespace DMX2
}
}
public void ConnectDevice (string name)
{
knowndevices.Add (name, new MidiDev (name));
@ -279,7 +289,8 @@ namespace DMX2
}
}
public bool IsKnownDevice(string name){
public bool IsKnownDevice (string name)
{
return knowndevices.ContainsKey (name);
}
@ -289,7 +300,6 @@ namespace DMX2
}
}
public MidiEventProvider (EventManager manager)
{
/*MidiDev dev = new MidiDev("VMPK Input:VMPK Input");
@ -348,7 +358,8 @@ namespace DMX2
int srcid = clientId << 8 + portId;
if (connect) {
string fpname = AlsaSeqLib.GetClientByID (clientId).Name + ":" + AlsaSeqLib.GetPortByIDs (clientId, portId).Name;
if (!knowndevices.ContainsKey(fpname)) return;
if (!knowndevices.ContainsKey (fpname))
return;
if (knowndevices [fpname].ConnectedPorts.Contains (srcid))
return;
knowndevices [fpname].ConnectedPorts.Add (srcid);
@ -362,8 +373,7 @@ namespace DMX2
}
foreach (var dev in knowndevices.Values) {
if(dev.ConnectedPorts.Contains (srcid))
{
if (dev.ConnectedPorts.Contains (srcid)) {
/*if(srcidToDev.ContainsKey(srcid))
srcidToDev.Remove(srcid);*/
dev.ConnectedPorts.Remove (srcid);
@ -420,7 +430,8 @@ namespace DMX2
if (! eventlist.ContainsKey (eventId)) {
var res = regexEventID.Match (eventId);
if (!res.Success) return false;
if (!res.Success)
return false;
uint _page = uint.Parse (res.Groups ["page"].Value);
int _evHC = res.Groups ["id"].Value.GetHashCode ();
eventlist.Add (eventId, new internalEvent (eventId, _page, _evHC));
@ -432,14 +443,16 @@ namespace DMX2
void IEventProvider.Unbind (string eventId)
{
if(! eventlist.ContainsKey(eventId)) return;
if (! eventlist.ContainsKey (eventId))
return;
eventlist [eventId].Bound = false;
return;
}
Gtk.Menu IEventProvider.GetProviderSubMenu (EventManager.EventMenuData state, Gtk.ButtonPressEventHandler handler)
{
if(!connected) return null; // Si pas encore recu d'evenements => pas de menu
if (!connected)
return null; // Si pas encore recu d'evenements => pas de menu
Gtk.Menu retmenu = new Gtk.Menu ();
if (levent != null) { // Creation du sous menu "Dernier"
@ -497,11 +510,13 @@ namespace DMX2
continue;
case AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_CONTROLLER:
if (evS.data_ev_ctrl.param == 127 && evS.data_ev_ctrl.value > 0) {
CurrentPage++; continue;
CurrentPage++;
continue;
}
if (evS.data_ev_ctrl.param == 126 && evS.data_ev_ctrl.value > 0) {
CurrentPage--; continue;
CurrentPage--;
continue;
}
id = string.Format ("CTRL-C{0}P{1}", evS.data_ev_ctrl.channel, evS.data_ev_ctrl.param);
@ -521,8 +536,11 @@ namespace DMX2
case AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_PITCHBEND:
id = string.Format ("PB-C{0}", evS.data_ev_ctrl.channel);
channel = evS.data_ev_ctrl.channel;
value = ((evS.data_ev_ctrl.value + 8000) *255 / 16000);
if(value<0) value =0; if(value>255) value = 255;
value = ((evS.data_ev_ctrl.value + 7000) * 255 / 14000);
if (value < 0)
value = 0;
if (value > 255)
value = 255;
break;
case AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_CLOCK:
case AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_SENSING:
@ -552,8 +570,7 @@ namespace DMX2
if(id!=null)
{
if (id != null) {
// Hashcode de l'ev Midi, non pagine
int evHC = id.GetHashCode ();
int srcid = evS.source.client << 8 + evS.source.port;
@ -580,7 +597,8 @@ namespace DMX2
evData.id = id;
evData.value = (byte)value;
evData.prev_value = lastValueOfSrc [lnvk];
if(evData.Equals(last)) continue;
if (evData.Equals (last))
continue;
last = evData;
if (eventlist [id].Bound) {
@ -607,18 +625,17 @@ namespace DMX2
static System.Text.RegularExpressions.Regex regexCtrlEventID = new System.Text.RegularExpressions.Regex (
@"MIDI-PAGE(?<page>\d+)-CTRL-C(?<chan>\d+)P(?<param>\d+)",
System.Text.RegularExpressions.RegexOptions.Compiled);
static System.Text.RegularExpressions.Regex regexPbEventID = new System.Text.RegularExpressions.Regex (
@"MIDI-PAGE(?<page>\d+)-PB-C(?<chan>\d+)",
System.Text.RegularExpressions.RegexOptions.Compiled);
static System.Text.RegularExpressions.Regex regexNoteEventID = new System.Text.RegularExpressions.Regex (
@"MIDI-PAGE(?<page>\d+)-NOTE-C(?<chan>\d+)N(?<note>\d+)",
System.Text.RegularExpressions.RegexOptions.Compiled);
string GetDescription (string eventId)
{
if(!eventlist.ContainsKey(eventId)) return null;
if (!eventlist.ContainsKey (eventId))
return null;
var res = regexCtrlEventID.Match (eventId);
if (res.Success) {
@ -645,7 +662,8 @@ namespace DMX2
IFeedbackInfo IEventProvider.GetFeedbackInfo (string eventId)
{
if(!eventlist.ContainsKey(eventId)) return null;
if (!eventlist.ContainsKey (eventId))
return null;
var res = regexCtrlEventID.Match (eventId);
if (res.Success) {
@ -669,12 +687,15 @@ namespace DMX2
bool disposed = false;
~MidiEventProvider(){
~MidiEventProvider ()
{
Dispose ();
}
public void Dispose ()
{
if(disposed)return;
if (disposed)
return;
disposed = true;
AlsaSeqLib.Close ();
}
@ -702,7 +723,8 @@ namespace DMX2
public void Load (System.Xml.XmlElement el)
{
if(el==null) return;
if (el == null)
return;
maxpage = uint.Parse (el.TryGetAttribute ("maxpage", "8"));
foreach (var xd in el.GetElementsByTagName("MidiDev")) {