1 // Copyright 2006 Alp Toker <alp@atoker.com> 2 // This software is made available under the MIT License 3 // See COPYING for details 4 5 using System; 6 using System.Collections; 7 using System.Runtime.InteropServices; 8 9 namespace DBus.GLib 10 { 11 /* 12 Specifies the type of function which is called when a data element is destroyed. It is passed the pointer to the data element and should free any memory and resources allocated for it. 13 14 @data: the data element. 15 */ 16 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] DestroyNotify(IntPtr data)17 delegate void DestroyNotify (IntPtr data); 18 19 /* 20 Specifies the type of function passed to g_io_add_watch() or g_io_add_watch_full(), which is called when the requested condition on a GIOChannel is satisfied. 21 22 @source: the GIOChannel event source. 23 @condition: the condition which has been satisfied. 24 @data: user data set in g_io_add_watch() or g_io_add_watch_full(). 25 26 Returns: the function should return FALSE if the event source should be removed. 27 */ 28 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] IOFunc(IntPtr source, IOCondition condition, IntPtr data)29 delegate bool IOFunc (IntPtr source, IOCondition condition, IntPtr data); 30 31 struct IOChannel 32 { 33 const string GLIB = "libglib-2.0-0.dll"; 34 35 public IntPtr Handle; 36 37 [DllImport(GLIB)] g_io_channel_unix_newDBus.GLib.IOChannel38 static extern IntPtr g_io_channel_unix_new (int fd); 39 IOChannelDBus.GLib.IOChannel40 public IOChannel (int fd) 41 { 42 try { 43 Handle = g_io_channel_win32_new_socket (fd); 44 } catch { 45 Handle = IntPtr.Zero; 46 } 47 48 if (Handle == IntPtr.Zero) 49 Handle = g_io_channel_unix_new (fd); 50 51 if (Handle == IntPtr.Zero) 52 throw new Exception ("Failed to create GLib IO channel for fd " + fd); 53 54 //Buffered = false; 55 } 56 57 [DllImport(GLIB)] g_io_channel_unix_get_fdDBus.GLib.IOChannel58 static extern int g_io_channel_unix_get_fd (IntPtr channel); 59 60 public int UnixFd 61 { 62 get { 63 return g_io_channel_unix_get_fd (Handle); 64 } 65 } 66 67 [DllImport(GLIB)] g_io_channel_win32_new_fdDBus.GLib.IOChannel68 public static extern IntPtr g_io_channel_win32_new_fd (int fd); 69 70 [DllImport(GLIB)] g_io_channel_win32_new_socketDBus.GLib.IOChannel71 public static extern IntPtr g_io_channel_win32_new_socket (int socket); 72 73 [DllImport(GLIB)] g_io_channel_win32_new_messagesDBus.GLib.IOChannel74 public static extern IntPtr g_io_channel_win32_new_messages (uint hwnd); 75 76 77 [DllImport(GLIB)] g_io_channel_get_buffer_sizeDBus.GLib.IOChannel78 public static extern uint g_io_channel_get_buffer_size (IntPtr channel); 79 80 [DllImport(GLIB)] g_io_channel_set_buffer_sizeDBus.GLib.IOChannel81 public static extern void g_io_channel_set_buffer_size (IntPtr channel, uint size); 82 83 public uint BufferSize 84 { 85 get { 86 return g_io_channel_get_buffer_size (Handle); 87 } set { 88 g_io_channel_set_buffer_size (Handle, value); 89 } 90 } 91 92 [DllImport(GLIB)] g_io_channel_get_bufferedDBus.GLib.IOChannel93 public static extern bool g_io_channel_get_buffered (IntPtr channel); 94 95 [DllImport(GLIB)] g_io_channel_set_bufferedDBus.GLib.IOChannel96 public static extern void g_io_channel_set_buffered (IntPtr channel, bool value); 97 98 public bool Buffered 99 { 100 get 101 { 102 return g_io_channel_get_buffered (Handle); 103 } 104 set 105 { 106 g_io_channel_set_buffered (Handle, value); 107 } 108 } 109 110 [DllImport(GLIB)] g_io_channel_get_buffer_conditionDBus.GLib.IOChannel111 public static extern IOCondition g_io_channel_get_buffer_condition (IntPtr channel); 112 113 public IOCondition BufferCondition 114 { 115 get { 116 return g_io_channel_get_buffer_condition (Handle); 117 } 118 } 119 120 [DllImport(GLIB)] g_io_channel_get_flagsDBus.GLib.IOChannel121 public static extern IOFlags g_io_channel_get_flags (IntPtr channel); 122 123 [DllImport(GLIB)] g_io_channel_set_flagsDBus.GLib.IOChannel124 static extern short g_io_channel_set_flags (IntPtr channel, IOFlags flags, IntPtr error); 125 126 public IOFlags Flags 127 { 128 get { 129 return g_io_channel_get_flags (Handle); 130 } set { 131 //TODO: fix return and error 132 g_io_channel_set_flags (Handle, value, IntPtr.Zero); 133 } 134 } 135 } 136 137 class IO 138 { 139 const string GLIB = "libglib-2.0-0.dll"; 140 141 //TODO: better memory management 142 public static ArrayList objs = new ArrayList (); 143 144 /* 145 Adds the GIOChannel into the main event loop with the default priority. 146 147 @channel: a GIOChannel. 148 @condition: the condition to watch for. 149 @func: the function to call when the condition is satisfied. 150 @user_data: user data to pass to func. 151 152 Returns: the event source id. 153 */ 154 [DllImport(GLIB)] g_io_add_watch(IntPtr channel, IOCondition condition, IOFunc func, IntPtr user_data)155 protected static extern uint g_io_add_watch (IntPtr channel, IOCondition condition, IOFunc func, IntPtr user_data); 156 AddWatch(IOChannel channel, IOCondition condition, IOFunc func)157 public static uint AddWatch (IOChannel channel, IOCondition condition, IOFunc func) 158 { 159 objs.Add (func); 160 161 return g_io_add_watch (channel.Handle, condition, func, IntPtr.Zero); 162 } 163 164 /* 165 Adds the GIOChannel into the main event loop with the given priority. 166 167 @channel: a GIOChannel. 168 @priority: the priority of the GIOChannel source. 169 @condition: the condition to watch for. 170 @func: the function to call when the condition is satisfied. 171 @user_data: user data to pass to func. 172 @notify: the function to call when the source is removed. 173 174 Returns: the event source id. 175 */ 176 [DllImport(GLIB)] g_io_add_watch_full(IntPtr channel, int priority, IOCondition condition, IOFunc func, IntPtr user_data, DestroyNotify notify)177 protected static extern uint g_io_add_watch_full (IntPtr channel, int priority, IOCondition condition, IOFunc func, IntPtr user_data, DestroyNotify notify); 178 AddWatch(IOChannel channel, int priority, IOCondition condition, IOFunc func, DestroyNotify notify)179 public static uint AddWatch (IOChannel channel, int priority, IOCondition condition, IOFunc func, DestroyNotify notify) 180 { 181 objs.Add (func); 182 objs.Add (notify); 183 184 return g_io_add_watch_full (channel.Handle, priority, condition, func, IntPtr.Zero, notify); 185 } 186 187 [DllImport(GLIB)] g_main_context_default()188 protected static extern IntPtr g_main_context_default (); 189 MainContextDefault()190 public static IntPtr MainContextDefault () 191 { 192 return g_main_context_default (); 193 } 194 195 [DllImport(GLIB)] g_main_context_wakeup(IntPtr context)196 protected static extern void g_main_context_wakeup (IntPtr context); 197 MainContextWakeup(IntPtr context)198 public static void MainContextWakeup (IntPtr context) 199 { 200 g_main_context_wakeup (context); 201 } 202 } 203 204 //From Mono.Unix and poll(2) 205 [Flags] 206 enum PollEvents : short { 207 POLLIN = 0x0001, // There is data to read 208 POLLPRI = 0x0002, // There is urgent data to read 209 POLLOUT = 0x0004, // Writing now will not block 210 POLLERR = 0x0008, // Error condition 211 POLLHUP = 0x0010, // Hung up 212 POLLNVAL = 0x0020, // Invalid request; fd not open 213 // XPG4.2 definitions (via _XOPEN_SOURCE) 214 POLLRDNORM = 0x0040, // Normal data may be read 215 POLLRDBAND = 0x0080, // Priority data may be read 216 POLLWRNORM = 0x0100, // Writing now will not block 217 POLLWRBAND = 0x0200, // Priority data may be written 218 } 219 220 //A bitwise combination representing a condition to watch for on an event source. 221 [Flags] 222 enum IOCondition : short 223 { 224 //There is data to read. 225 In = PollEvents.POLLIN, 226 //Data can be written (without blocking). 227 Out = PollEvents.POLLOUT, 228 //There is urgent data to read. 229 Pri = PollEvents.POLLPRI, 230 //Error condition. 231 Err = PollEvents.POLLERR, 232 //Hung up (the connection has been broken, usually for pipes and sockets). 233 Hup = PollEvents.POLLHUP, 234 //Invalid request. The file descriptor is not open. 235 Nval = PollEvents.POLLNVAL, 236 } 237 238 [Flags] 239 enum IOFlags : short 240 { 241 Append = 1 << 0, 242 Nonblock = 1 << 1, 243 //Read only flag 244 IsReadable = 1 << 2, 245 //Read only flag 246 isWriteable = 1 << 3, 247 //Read only flag 248 IsSeekable = 1 << 4, 249 //? 250 Mask = (1 << 5) - 1, 251 GetMask = Mask, 252 SetMask = Append | Nonblock, 253 } 254 } 255