Commit 45277e93 authored by Owen Fraser-Green's avatar Owen Fraser-Green

Added signal support.

parent 7dd57040
......@@ -42,6 +42,11 @@ namespace DBus
SetupWithMain();
}
public void Flush()
{
dbus_connection_flush(RawConnection);
}
public void SetupWithMain()
{
dbus_connection_setup_with_g_main(RawConnection, IntPtr.Zero);
......
namespace DBus
{
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
public class ErrorMessage : Message
{
public ErrorMessage() : base(MessageType.Error)
{
}
internal ErrorMessage(IntPtr rawMessage, Service service) : base(rawMessage, service)
{
}
public ErrorMessage(Service service) : base(MessageType.Error, service)
{
}
public new string Name
{
get {
if (this.name == null) {
this.name = Marshal.PtrToStringAnsi(dbus_message_get_error_name(RawMessage));
}
return this.name;
}
set {
if (value != this.name) {
dbus_message_set_error_name(RawMessage, value);
this.name = value;
}
}
}
[DllImport("dbus-1")]
private extern static bool dbus_message_set_error_name(IntPtr rawMessage, string name);
[DllImport("dbus-1")]
private extern static IntPtr dbus_message_get_error_name(IntPtr rawMessage);
}
}
......@@ -6,6 +6,13 @@ namespace DBus
using System.Reflection;
using System.Collections;
internal enum Result
{
Handled = 0,
NotYetHandled = 1,
NeedMemory = 2
}
internal class Handler
{
private string[] path = null;
......@@ -15,7 +22,6 @@ namespace DBus
private DBusObjectPathVTable vTable;
private Connection connection;
private Service service;
private DBusHandleMessageFunction filterCalled;
internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
IntPtr userData);
......@@ -24,18 +30,6 @@ namespace DBus
IntPtr rawMessage,
IntPtr userData);
internal delegate int DBusHandleMessageFunction(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData);
private enum Result
{
Handled = 0,
NotYetHandled = 1,
NeedMemory = 2
}
[StructLayout (LayoutKind.Sequential)]
private struct DBusObjectPathVTable
{
......@@ -67,8 +61,8 @@ namespace DBus
}
public Handler(object handledObject,
string pathName,
Service service)
string pathName,
Service service)
{
Service = service;
Connection = service.Connection;
......@@ -88,14 +82,22 @@ namespace DBus
ref vTable,
IntPtr.Zero))
throw new OutOfMemoryException();
// Setup the filter function
this.filterCalled = new DBusHandleMessageFunction(Filter_Called);
if (!dbus_connection_add_filter(Connection.RawConnection,
this.filterCalled,
IntPtr.Zero,
IntPtr.Zero))
throw new OutOfMemoryException();
RegisterSignalHandlers();
}
private void RegisterSignalHandlers()
{
ProxyBuilder proxyBuilder = new ProxyBuilder(Service, HandledObject.GetType(), this.pathName);
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
EventInfo eventE = (EventInfo) signalEntry.Value;
Delegate del = Delegate.CreateDelegate(eventE.EventHandlerType, proxyBuilder.GetSignalProxy(), "Proxy_" + eventE.Name);
eventE.AddEventHandler(HandledObject, del);
}
}
}
public object HandledObject
......@@ -113,21 +115,6 @@ namespace DBus
this.introspector = Introspector.GetIntrospector(value.GetType());
}
}
public int Filter_Called(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData)
{
Message message = Message.Wrap(rawMessage, Service);
if (message.Type == Message.MessageType.Signal) {
Signal signal = (Signal) message;
} else if (message.Type == Message.MessageType.MethodCall) {
MethodCall methodCall = (MethodCall) message;
}
return (int) Result.NotYetHandled;
}
public void Unregister_Called(IntPtr rawConnection,
IntPtr userData)
......@@ -143,7 +130,8 @@ namespace DBus
switch (message.Type) {
case Message.MessageType.Signal:
System.Console.WriteLine("FIXME: Signal called.");
// We're not interested in signals here because we're the ones
// that generate them!
break;
case Message.MessageType.MethodCall:
return (int) HandleMethod((MethodCall) message);
......@@ -216,7 +204,7 @@ namespace DBus
{
this.service = value;
}
}
}
[DllImport ("dbus-1")]
private extern static bool dbus_connection_register_object_path (IntPtr rawConnection, string[] path, ref DBusObjectPathVTable vTable, IntPtr userData);
......@@ -224,11 +212,5 @@ namespace DBus
[DllImport ("dbus-1")]
private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection, string[] path);
[DllImport ("dbus-1")]
private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
DBusHandleMessageFunction filter,
IntPtr userData,
IntPtr freeData);
}
}
......@@ -8,7 +8,8 @@ namespace DBus
{
private static Hashtable interfaceProxies = new Hashtable();
private Hashtable methods = null;
private Hashtable signals = null;
private string interfaceName;
private InterfaceProxy(Type type)
......@@ -17,17 +18,34 @@ namespace DBus
InterfaceAttribute interfaceAttribute = (InterfaceAttribute) attributes[0];
this.interfaceName = interfaceAttribute.InterfaceName;
AddMethods(type);
AddSignals(type);
}
// Add all the events with Signal attributes
private void AddSignals(Type type)
{
this.signals = new Hashtable();
foreach (EventInfo signal in type.GetEvents(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly)) {
object[] attributes = signal.GetCustomAttributes(typeof(SignalAttribute), false);
if (attributes.GetLength(0) > 0) {
MethodInfo invoke = signal.EventHandlerType.GetMethod("Invoke");
signals.Add(signal.Name + " " + GetSignature(invoke), signal);
}
}
}
// Add all the methods with Method attributes
private void AddMethods(Type type)
{
this.methods = new Hashtable();
foreach (MethodInfo method in type.GetMethods(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly)) {
object[] attributes = method.GetCustomAttributes(typeof(MethodAttribute), true);
object[] attributes = method.GetCustomAttributes(typeof(MethodAttribute), false);
if (attributes.GetLength(0) > 0) {
methods.Add(GetKey(method), method);
methods.Add(method.Name + " " + GetSignature(method), method);
}
}
}
......@@ -46,16 +64,26 @@ namespace DBus
{
return this.Methods.Contains(key);
}
public bool HasSignal(string key)
{
return this.Signals.Contains(key);
}
public EventInfo GetSignal(string key)
{
return (EventInfo) this.Signals[key];
}
public MethodInfo GetMethod(string key)
{
return (MethodInfo) this.Methods[key];
}
private string GetKey(MethodInfo method)
public static string GetSignature(MethodInfo method)
{
ParameterInfo[] pars = method.GetParameters();
string key = method.Name + " ";
string key = "";
foreach (ParameterInfo par in pars) {
if (!par.IsOut) {
......@@ -73,6 +101,13 @@ namespace DBus
return this.methods;
}
}
public Hashtable Signals
{
get {
return this.signals;
}
}
public string InterfaceName
{
......
......@@ -10,6 +10,7 @@ DBUS_SHARP_FILES= \
Custom.cs \
DBusException.cs \
Error.cs \
ErrorMessage.cs \
Handler.cs \
InterfaceAttribute.cs \
InterfaceProxy.cs \
......@@ -22,6 +23,7 @@ DBUS_SHARP_FILES= \
Server.cs \
Service.cs \
Signal.cs \
SignalAttribute.cs \
DBusType/IDBusType.cs \
DBusType/Array.cs \
DBusType/Boolean.cs \
......
......@@ -80,14 +80,23 @@ namespace DBus
}
// If it doesn't exist then create a new Message around it
Message message = null;
MessageType messageType = (MessageType) dbus_message_get_type(rawMessage);
switch ((MessageType) dbus_message_get_type(rawMessage)) {
switch (messageType) {
case MessageType.Signal:
message = new Signal(rawMessage, service);
break;
case MessageType.MethodCall:
message = new MethodCall(rawMessage, service);
break;
case MessageType.MethodReturn:
message = new MethodReturn(rawMessage, service);
break;
case MessageType.Error:
message = new ErrorMessage(rawMessage, service);
break;
default:
throw new ApplicationException("Unknown message type to wrap: " + messageType);
}
return message;
......@@ -140,6 +149,8 @@ namespace DBus
{
if (!dbus_connection_send (Service.Connection.RawConnection, RawMessage, ref serial))
throw new OutOfMemoryException ();
Service.Connection.Flush();
}
public void Send()
......@@ -245,23 +256,19 @@ namespace DBus
protected virtual string Name
{
set
{
if (value != this.name)
{
dbus_message_set_member (RawMessage, value);
this.name = value;
}
set {
if (value != this.name) {
dbus_message_set_member(RawMessage, value);
this.name = value;
}
get
{
if (this.name == null) {
this.name = Marshal.PtrToStringAnsi(dbus_message_get_member(RawMessage));
}
return this.name;
}
get {
if (this.name == null) {
this.name = Marshal.PtrToStringAnsi(dbus_message_get_member(RawMessage));
}
return this.name;
}
}
public string Key
......@@ -356,7 +363,7 @@ namespace DBus
private extern static IntPtr dbus_message_get_interface(IntPtr rawMessage);
[DllImport("dbus-1")]
private extern static bool dbus_message_set_member (IntPtr rawMessage, string name);
private extern static bool dbus_message_set_member(IntPtr rawMessage, string name);
[DllImport("dbus-1")]
private extern static IntPtr dbus_message_get_member(IntPtr rawMessage);
......
This diff is collapsed.
......@@ -4,6 +4,7 @@ namespace DBus
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
......@@ -13,12 +14,20 @@ namespace DBus
private string name;
private bool local = false;
private Hashtable registeredHandlers = new Hashtable();
internal ModuleBuilder module = null;
private delegate int DBusHandleMessageFunction(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData);
private DBusHandleMessageFunction filterCalled;
public delegate void SignalCalledHandler(Signal signal);
public event SignalCalledHandler SignalCalled;
private static AssemblyBuilder proxyAssembly;
private ModuleBuilder module = null;
internal Service(string name, Connection connection)
{
this.name = name;
this.connection = connection;
AddFilter();
}
public Service(Connection connection, string name)
......@@ -67,9 +76,7 @@ namespace DBus
public void RegisterObject(object handledObject,
string pathName)
{
Handler handler = new Handler(handledObject,
pathName,
this);
Handler handler = new Handler(handledObject, pathName, this);
registeredHandlers.Add(handledObject, handler);
}
......@@ -89,6 +96,38 @@ namespace DBus
return proxy;
}
private void AddFilter()
{
// Setup the filter function
this.filterCalled = new DBusHandleMessageFunction(Service_FilterCalled);
if (!dbus_connection_add_filter(Connection.RawConnection,
this.filterCalled,
IntPtr.Zero,
IntPtr.Zero))
throw new OutOfMemoryException();
// Add a match for signals. FIXME: Can we filter the service?
string rule = "type='signal'";
dbus_bus_add_match(connection.RawConnection, rule, IntPtr.Zero);
}
private int Service_FilterCalled(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData)
{
Message message = Message.Wrap(rawMessage, this);
if (message.Type == Message.MessageType.Signal) {
// We're only interested in signals
Signal signal = (Signal) message;
if (SignalCalled != null) {
SignalCalled(signal);
}
}
return (int) Result.NotYetHandled;
}
public string Name
{
get
......@@ -110,10 +149,51 @@ namespace DBus
}
}
[DllImport ("dbus-1")]
private extern static int dbus_bus_acquire_service (IntPtr rawConnection, string serviceName, uint flags, ref Error error);
internal AssemblyBuilder ProxyAssembly
{
get {
if (proxyAssembly == null){
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "DBusProxy";
proxyAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.RunAndSave);
}
return proxyAssembly;
}
}
internal ModuleBuilder Module
{
get {
if (this.module == null) {
this.module = ProxyAssembly.DefineDynamicModule(Name, "proxy.dll", true);
}
return this.module;
}
}
[DllImport("dbus-1")]
private extern static int dbus_bus_acquire_service(IntPtr rawConnection,
string serviceName,
uint flags, ref Error error);
[DllImport("dbus-1")]
private extern static bool dbus_bus_service_exists(IntPtr rawConnection,
string serviceName,
ref Error error);
[DllImport("dbus-1")]
private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
DBusHandleMessageFunction filter,
IntPtr userData,
IntPtr freeData);
[DllImport("dbus-1")]
private extern static void dbus_bus_add_match(IntPtr rawConnection,
string rule,
IntPtr erro);
[DllImport ("dbus-1")]
private extern static bool dbus_bus_service_exists (IntPtr rawConnection, string serviceName, ref Error error);
}
}
......@@ -18,6 +18,23 @@ namespace DBus
{
}
public Signal(Service service, string pathName, string interfaceName, string name)
{
this.service = service;
RawMessage = dbus_message_new_signal(pathName, interfaceName, name);
if (RawMessage == IntPtr.Zero) {
throw new OutOfMemoryException();
}
this.pathName = pathName;
this.interfaceName = interfaceName;
this.name = name;
dbus_message_unref(RawMessage);
}
public new string PathName
{
get
......@@ -56,5 +73,7 @@ namespace DBus
base.Name = value;
}
}
[DllImport("dbus-1")]
private extern static IntPtr dbus_message_new_signal(string pathName, string interfaceName, string name);
}
}
using System;
namespace DBus
{
[AttributeUsage(AttributeTargets.Event, AllowMultiple=false, Inherited=true)] public class SignalAttribute : Attribute
{
public SignalAttribute()
{
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment