00001 namespace DBus
00002 {
00003
00004 using System;
00005 using System.Runtime.InteropServices;
00006 using System.Diagnostics;
00007 using System.Reflection;
00008 using System.IO;
00009 using System.Collections;
00010
00011 public delegate int DBusHandleMessageFunction (IntPtr rawConnection,
00012 IntPtr rawMessage,
00013 IntPtr userData);
00014
00015 internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
00016 IntPtr userData);
00017
00018 internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection,
00019 IntPtr rawMessage,
00020 IntPtr userData);
00021
00022 [StructLayout (LayoutKind.Sequential)]
00023 internal struct DBusObjectPathVTable
00024 {
00025 public DBusObjectPathUnregisterFunction unregisterFunction;
00026 public DBusObjectPathMessageFunction messageFunction;
00027 public IntPtr padding1;
00028 public IntPtr padding2;
00029 public IntPtr padding3;
00030 public IntPtr padding4;
00031
00032 public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction,
00033 DBusObjectPathMessageFunction messageFunction)
00034 {
00035 this.unregisterFunction = unregisterFunction;
00036 this.messageFunction = messageFunction;
00037 this.padding1 = IntPtr.Zero;
00038 this.padding2 = IntPtr.Zero;
00039 this.padding3 = IntPtr.Zero;
00040 this.padding4 = IntPtr.Zero;
00041 }
00042 }
00043
00044 public class Connection : IDisposable
00045 {
00049 private IntPtr rawConnection;
00050
00054 private static int slot = -1;
00055
00056 private int timeout = -1;
00057
00058 private ArrayList filters = new ArrayList ();
00059 private ArrayList matches = new ArrayList ();
00060 private Hashtable object_paths = new Hashtable ();
00061
00062 internal Connection(IntPtr rawConnection)
00063 {
00064 RawConnection = rawConnection;
00065 ExitOnDisconnect = true;
00066 }
00067
00068 public Connection(string address)
00069 {
00070
00071 Error error = new Error();
00072 error.Init();
00073 RawConnection = dbus_connection_open(address, ref error);
00074 if (RawConnection != IntPtr.Zero) {
00075 dbus_connection_unref(RawConnection);
00076 } else {
00077 throw new DBusException(error);
00078 }
00079
00080 SetupWithMain();
00081 ExitOnDisconnect = true;
00082 }
00083
00084 public void Dispose()
00085 {
00086 Dispose(true);
00087 GC.SuppressFinalize(this);
00088 }
00089
00090 public void Dispose (bool disposing)
00091 {
00092 if (disposing && RawConnection != IntPtr.Zero)
00093 {
00094 dbus_connection_disconnect(rawConnection);
00095
00096 RawConnection = IntPtr.Zero;
00097 }
00098 }
00099
00100 public void Flush()
00101 {
00102 dbus_connection_flush(RawConnection);
00103 }
00104
00105 public void SetupWithMain()
00106 {
00107 dbus_connection_setup_with_g_main(RawConnection, IntPtr.Zero);
00108 }
00109
00110 ~Connection ()
00111 {
00112 Dispose (false);
00113 }
00114
00115 internal static Connection Wrap(IntPtr rawConnection)
00116 {
00117 if (slot > -1) {
00118
00119
00120 IntPtr rawThis = dbus_connection_get_data (rawConnection, slot);
00121 if (rawThis != IntPtr.Zero && ((GCHandle)rawThis).Target == typeof(DBus.Connection)) {
00122 return (DBus.Connection) ((GCHandle)rawThis).Target;
00123 }
00124 }
00125
00126
00127 return new Connection(rawConnection);
00128 }
00129
00130 public void AddFilter (DBusHandleMessageFunction func)
00131 {
00132 if (!dbus_connection_add_filter (RawConnection,
00133 func,
00134 IntPtr.Zero,
00135 IntPtr.Zero))
00136 throw new OutOfMemoryException ();
00137
00138 this.filters.Add (func);
00139 }
00140
00141 public void RemoveFilter (DBusHandleMessageFunction func)
00142 {
00143 dbus_connection_remove_filter (RawConnection, func, IntPtr.Zero);
00144
00145 this.filters.Remove (func);
00146 }
00147
00148 public void AddMatch (string match_rule)
00149 {
00150 dbus_bus_add_match (RawConnection, match_rule, IntPtr.Zero);
00151
00152 this.matches.Add (match_rule);
00153 }
00154
00155 public void RemoveMatch (string match_rule)
00156 {
00157 dbus_bus_remove_match (RawConnection, match_rule, IntPtr.Zero);
00158
00159 this.matches.Remove (match_rule);
00160 }
00161
00162 internal void RegisterObjectPath (string path, DBusObjectPathVTable vtable)
00163 {
00164 if (!dbus_connection_register_object_path (RawConnection, path, ref vtable, IntPtr.Zero))
00165 throw new OutOfMemoryException ();
00166
00167 this.object_paths[path] = vtable;
00168 }
00169
00170 internal void UnregisterObjectPath (string path)
00171 {
00172 dbus_connection_unregister_object_path (RawConnection, path);
00173
00174 this.object_paths.Remove (path);
00175 }
00176
00177
00178 public string UniqueName
00179 {
00180 get
00181 {
00182 return Marshal.PtrToStringAnsi (dbus_bus_get_unique_name (RawConnection));
00183 }
00184 }
00185
00186 public int Timeout
00187 {
00188 get
00189 {
00190 return this.timeout;
00191 }
00192 set
00193 {
00194 this.timeout = value;
00195 }
00196 }
00197
00198 public bool ExitOnDisconnect
00199 {
00200 set
00201 {
00202 dbus_connection_set_exit_on_disconnect(RawConnection, value);
00203 }
00204 }
00205
00206 private int Slot
00207 {
00208 get
00209 {
00210 if (slot == -1)
00211 {
00212
00213 if (!dbus_connection_allocate_data_slot (ref slot))
00214 throw new OutOfMemoryException ();
00215
00216 Debug.Assert (slot >= 0);
00217 }
00218
00219 return slot;
00220 }
00221 }
00222
00223 internal IntPtr RawConnection
00224 {
00225 get
00226 {
00227 return rawConnection;
00228 }
00229 set
00230 {
00231 if (value == rawConnection)
00232 return;
00233
00234 if (rawConnection != IntPtr.Zero)
00235 {
00236
00237 foreach (DBusHandleMessageFunction func in this.filters)
00238 dbus_connection_remove_filter (rawConnection, func, IntPtr.Zero);
00239
00240 foreach (string match_rule in this.matches)
00241 dbus_bus_remove_match (rawConnection, match_rule, IntPtr.Zero);
00242
00243 foreach (string path in this.object_paths.Keys)
00244 dbus_connection_unregister_object_path (rawConnection, path);
00245
00246
00247 IntPtr rawThis = dbus_connection_get_data (rawConnection, Slot);
00248 Debug.Assert (rawThis != IntPtr.Zero);
00249
00250
00251 dbus_connection_set_data (rawConnection, Slot, IntPtr.Zero, IntPtr.Zero);
00252
00253
00254 ((GCHandle) rawThis).Free();
00255
00256
00257 dbus_connection_unref(rawConnection);
00258 }
00259
00260 this.rawConnection = value;
00261
00262 if (rawConnection != IntPtr.Zero)
00263 {
00264 GCHandle rawThis;
00265
00266 dbus_connection_ref (rawConnection);
00267
00268
00269 rawThis = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
00270
00271 dbus_connection_set_data(rawConnection, Slot, (IntPtr) rawThis, IntPtr.Zero);
00272
00273
00274 foreach (DBusHandleMessageFunction func in this.filters)
00275 dbus_connection_add_filter (rawConnection, func, IntPtr.Zero, IntPtr.Zero);
00276
00277 foreach (string match_rule in this.matches)
00278 dbus_bus_add_match (rawConnection, match_rule, IntPtr.Zero);
00279
00280 foreach (string path in this.object_paths.Keys) {
00281 DBusObjectPathVTable vtable = (DBusObjectPathVTable) this.object_paths[path];
00282 dbus_connection_register_object_path (rawConnection, path, ref vtable, IntPtr.Zero);
00283 }
00284 }
00285 else
00286 {
00287 this.filters.Clear ();
00288 this.matches.Clear ();
00289 this.object_paths.Clear ();
00290 }
00291 }
00292 }
00293
00294 [DllImport("dbus-glib-1")]
00295 private extern static void dbus_connection_setup_with_g_main(IntPtr rawConnection,
00296 IntPtr rawContext);
00297
00298 [DllImport ("dbus-1")]
00299 private extern static IntPtr dbus_connection_open (string address, ref Error error);
00300
00301 [DllImport ("dbus-1")]
00302 private extern static void dbus_connection_unref (IntPtr ptr);
00303
00304 [DllImport ("dbus-1")]
00305 private extern static void dbus_connection_ref (IntPtr ptr);
00306
00307 [DllImport ("dbus-1")]
00308 private extern static bool dbus_connection_allocate_data_slot (ref int slot);
00309
00310 [DllImport ("dbus-1")]
00311 private extern static void dbus_connection_free_data_slot (ref int slot);
00312
00313 [DllImport ("dbus-1")]
00314 private extern static bool dbus_connection_set_data (IntPtr ptr,
00315 int slot,
00316 IntPtr data,
00317 IntPtr free_data_func);
00318
00319 [DllImport ("dbus-1")]
00320 private extern static void dbus_connection_flush (IntPtr ptr);
00321
00322 [DllImport ("dbus-1")]
00323 private extern static IntPtr dbus_connection_get_data (IntPtr ptr,
00324 int slot);
00325
00326 [DllImport ("dbus-1")]
00327 private extern static void dbus_connection_disconnect (IntPtr ptr);
00328
00329 [DllImport ("dbus-1")]
00330 private extern static IntPtr dbus_bus_get_unique_name (IntPtr ptr);
00331
00332 [DllImport("dbus-1")]
00333 private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
00334 DBusHandleMessageFunction filter,
00335 IntPtr userData,
00336 IntPtr freeData);
00337
00338 [DllImport("dbus-1")]
00339 private extern static void dbus_connection_remove_filter(IntPtr rawConnection,
00340 DBusHandleMessageFunction filter,
00341 IntPtr userData);
00342
00343 [DllImport("dbus-1")]
00344 private extern static void dbus_bus_add_match(IntPtr rawConnection,
00345 string rule,
00346 IntPtr erro);
00347
00348 [DllImport("dbus-1")]
00349 private extern static void dbus_bus_remove_match(IntPtr rawConnection,
00350 string rule,
00351 IntPtr erro);
00352
00353 [DllImport ("dbus-1")]
00354 private extern static bool dbus_connection_register_object_path (IntPtr rawConnection,
00355 string path,
00356 ref DBusObjectPathVTable vTable,
00357 IntPtr userData);
00358
00359 [DllImport ("dbus-1")]
00360 private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection,
00361 string path);
00362
00363 [DllImport ("dbus-1")]
00364 private extern static void dbus_connection_set_exit_on_disconnect (IntPtr rawConnection,
00365 bool exitOnDisconnect);
00366 }
00367 }