mirror of
https://github.com/darlinghq/darling-dbuskit.git
synced 2024-11-23 12:19:40 +00:00
Getting ready for GSoC: Import old and current D-Bus projects.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/dbuskit/trunk@30331 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
commit
f84a07139e
41
GNUmakefile
Normal file
41
GNUmakefile
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# GNUmakefile for DBusKit
|
||||
#
|
||||
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
|
||||
# config.make will be generated by configure (see GNUmakefile.postamble)
|
||||
-include config.make
|
||||
|
||||
DBusKit_SUBPROJECTS = Source
|
||||
|
||||
#
|
||||
# Public headers (will be installed)
|
||||
#
|
||||
DBusKit_HEADER_FILES_DIR = Headers
|
||||
DBusKit_HEADER_FILES = \
|
||||
DBusKit.h \
|
||||
DKPort.h
|
||||
|
||||
#
|
||||
# Makefiles
|
||||
#
|
||||
-include GNUmakefile.preamble
|
||||
include $(GNUSTEP_MAKEFILES)/aggregate.make
|
||||
|
||||
ifeq ($(test), yes)
|
||||
# Bundle
|
||||
BUNDLE_NAME = DBusKit
|
||||
include $(GNUSTEP_MAKEFILES)/bundle.make
|
||||
|
||||
all:: ${BUNDLE_NAME}
|
||||
ukrun ${BUNDLE_NAME}.bundle
|
||||
|
||||
else
|
||||
# Framework
|
||||
FRAMEWORK_NAME = DBusKit
|
||||
VERSION = 0.1
|
||||
include $(GNUSTEP_MAKEFILES)/framework.make
|
||||
endif
|
||||
|
||||
-include GNUmakefile.postamble
|
63
GNUmakefile.postamble
Normal file
63
GNUmakefile.postamble
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# GNUmakefile.postamble for DBusKit
|
||||
#
|
||||
|
||||
# Things to do before compiling
|
||||
# before-all::
|
||||
|
||||
# Things to do after compiling
|
||||
#after-all::
|
||||
|
||||
# Things to do before installing
|
||||
# before-install::
|
||||
|
||||
# Things to do after installing
|
||||
# after-install::
|
||||
|
||||
# Things to do before uninstalling
|
||||
# before-uninstall::
|
||||
|
||||
# Things to do after uninstalling
|
||||
# after-uninstall::
|
||||
|
||||
# Things to do before cleaning
|
||||
# before-clean::
|
||||
|
||||
# Things to do after cleaning
|
||||
after-clean::
|
||||
@-$(RM) -rf DBusKit.bundle
|
||||
@-$(RM) -rf DBusKit.framework
|
||||
@-$(RM) -rf derived_src
|
||||
@-$(RM) config.make
|
||||
@-$(RM) Headers/config.h
|
||||
|
||||
# Things to do before distcleaning
|
||||
# before-distclean::
|
||||
|
||||
# Things to do after distcleaning
|
||||
after-distclean::
|
||||
@-$(RM) configure aclocal.m4 config.log config.status
|
||||
@-$(RM) -rf autom4te.cache
|
||||
|
||||
# Things to do before checking
|
||||
# before-check::
|
||||
|
||||
# Things to do after checking
|
||||
# after-check::
|
||||
|
||||
|
||||
# Rule to generate configuration data:
|
||||
|
||||
configure: aclocal.m4 configure.ac
|
||||
autoconf
|
||||
|
||||
aclocal.m4: configure.ac
|
||||
aclocal
|
||||
|
||||
config.make: config.make.in configure
|
||||
./configure
|
||||
|
||||
Headers/config.h: Headers/config.h.in configure
|
||||
./configure
|
||||
|
||||
|
23
Headers/DBusKit.h
Normal file
23
Headers/DBusKit.h
Normal file
@ -0,0 +1,23 @@
|
||||
/** Umbrella header for DBusKit.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Niels Grewe <niels.grewe@halbordnung.de>
|
||||
Created: May 2010
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#import <DBusKit/DKPort.h>
|
57
Headers/DKPort.h
Normal file
57
Headers/DKPort.h
Normal file
@ -0,0 +1,57 @@
|
||||
/** Interface for DKPort for NSConnection integration.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Niels Grewe <niels.grewe@halbordnung.de>
|
||||
Created: May 2010
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSPort.h>
|
||||
|
||||
@class DKEndpoint;
|
||||
|
||||
/**
|
||||
* DKPort is used by the Distributed Objects system to communicate with
|
||||
* D-Bus. Unless you have special needs, don't create DKPort instances
|
||||
* yourself, but use the interfaces provided by NSConnection instead.
|
||||
*
|
||||
* This is a class cluster that will return subclass instances connected to
|
||||
* specific busses or peers, depending on the way it is initialized. The default
|
||||
* +port message will return a port connected to the session bus.
|
||||
*/
|
||||
@interface DKPort: NSPort
|
||||
{
|
||||
/** The endpoint doing the connection handling. */
|
||||
DKEndpoint *endpoint;
|
||||
|
||||
/**
|
||||
* The remote side of the port. Will not be specified for peer-to-peer
|
||||
* connections bypassing the bus and for ports used in service connections.
|
||||
*/
|
||||
NSString *remote;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface DKSessionBusPort: DKPort
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@interface DKSystemBusPort: DKPort
|
||||
{
|
||||
}
|
||||
@end
|
0
Headers/config.h.in
Normal file
0
Headers/config.h.in
Normal file
52
Source/DKEndpoint.h
Normal file
52
Source/DKEndpoint.h
Normal file
@ -0,0 +1,52 @@
|
||||
/** Declaration of DKEndpoint class for integrating DBus into NSRunLoop.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Niels Grewe <niels.grewe@halbordnung.de>
|
||||
Created: May 2010
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
/**
|
||||
* DKEndpoint is used internally to manage the low level details of a connection
|
||||
* to a D-Bus peer. This can be a well known bus as well as some special peer.
|
||||
*/
|
||||
@interface DKEndpoint: NSObject
|
||||
{
|
||||
DBusConnection *connection;
|
||||
}
|
||||
/**
|
||||
* Use this initializer to use a pre-existing DBusConnection. Please note that
|
||||
* this will increase the reference count of the connection. It will still need
|
||||
* to be unreferenced by calling code.
|
||||
*/
|
||||
- (id) initWithConnection: (DBusConnection*)conn;
|
||||
|
||||
- (id) initWithConnectionTo: (NSString*)endpoint;
|
||||
|
||||
- (id) initWithWellKnownBus: (DBusBusType)type;
|
||||
@end
|
||||
|
||||
@interface DKSystemBusEndpoint: DKEndpoint;
|
||||
- (id) init;
|
||||
@end
|
||||
|
||||
@interface DKSessionBusEndpoint: DKEndpoint;
|
||||
- (id) init;
|
||||
@end
|
752
Source/DKEndpoint.m
Normal file
752
Source/DKEndpoint.m
Normal file
@ -0,0 +1,752 @@
|
||||
/** Implementation of DKEndpoint class for integrating DBus into NSRunLoop.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Niels Grewe <niels.grewe@halbordnung.de>
|
||||
Created: May 2010
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02111 USA.
|
||||
|
||||
<title>DKEndpoint class reference</title>
|
||||
*/
|
||||
|
||||
#import "DKEndpoint.h"
|
||||
#import <Foundation/NSException.h>
|
||||
#import <Foundation/NSLock.h>
|
||||
#import <Foundation/NSMapTable.h>
|
||||
#import <Foundation/NSRunLoop.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimer.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import <GNUstepBase/NSDebug+GNUstepBase.h>
|
||||
|
||||
/*
|
||||
* Integration functions:
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The DK(Timeout|Watch)* functions do what their names imply.
|
||||
*/
|
||||
static dbus_bool_t
|
||||
DKTimeoutAdd(DBusTimeout *timeout, void *data);
|
||||
|
||||
static void
|
||||
DKTimeoutRemove(DBusTimeout *timeout, void *data);
|
||||
|
||||
static void
|
||||
DKTimeoutToggled(DBusTimeout *timeout, void *data);
|
||||
|
||||
static dbus_bool_t
|
||||
DKWatchAdd(DBusWatch *watch, void *data);
|
||||
|
||||
static void
|
||||
DKWatchRemove(DBusWatch *watch, void *data);
|
||||
|
||||
static void
|
||||
DKWatchToggled(DBusWatch *watch, void *data);
|
||||
|
||||
/*
|
||||
* Informs the run loop that DBus has work for it to do.
|
||||
*/
|
||||
static void
|
||||
DKWakeUp(void *data);
|
||||
|
||||
/*
|
||||
* Will be called to indicate that messages might be waiting.
|
||||
*/
|
||||
static void
|
||||
DKUpdateDispatchStatus(DBusConnection *conn,
|
||||
DBusDispatchStatus status,
|
||||
void *data);
|
||||
|
||||
/*
|
||||
* DBus might want to release objects we created, so we wrap -release for it.
|
||||
*/
|
||||
static void
|
||||
DKRelease(void *ptr);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Global state for referencing connections:
|
||||
*/
|
||||
static NSMapTable *activeConnections;
|
||||
static NSRecursiveLock *activeConnectionLock;
|
||||
|
||||
|
||||
@interface DKEndpoint (DBusEndpointPrivate)
|
||||
- (void)cleanup;
|
||||
@end
|
||||
|
||||
/**
|
||||
* Context object to manage runLoop interactions.
|
||||
*/
|
||||
@interface DKRunLoopContext: NSObject
|
||||
{
|
||||
DBusConnection *connection;
|
||||
NSMapTable *timers;
|
||||
NSMapTable *watchers;
|
||||
}
|
||||
|
||||
- (id)initWithConnection: (DBusConnection*)connection;
|
||||
- (NSRunLoop*)runLoop;
|
||||
- (NSString*)runLoopMode;
|
||||
@end
|
||||
|
||||
/**
|
||||
* Watcher object to monitor the file descriptors D-Bus signals on.
|
||||
*/
|
||||
@interface DKWatcher: NSObject <RunLoopEvents>
|
||||
{
|
||||
DBusWatch *watch;
|
||||
BOOL callbackInProgress;
|
||||
int fileDesc;
|
||||
DKRunLoopContext *ctx;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation DKEndpoint
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
if (self != [DKEndpoint class])
|
||||
{
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* It might be smart to put DBus into thread-safe mode by default because
|
||||
* there is a fair chance of missing NSWillBecomeMultiThreadedNotification.
|
||||
* (This code might be executed pretty late in the application lifecycle.)
|
||||
* Note: We could define our own hooks and use NSLock and friends, but that's
|
||||
* pretty pointless because DBus will use pthreads itself, just as NSLock
|
||||
* would.
|
||||
*/
|
||||
dbus_threads_init_default();
|
||||
|
||||
/*
|
||||
* Further initializations unfortunately need to be done on a per-connection
|
||||
* basis. We can only optimize by reusing existing connections (D-Bus
|
||||
* will recycle them behind our back anyways). We do this by weakly
|
||||
* referencing the connections and DKEndpoint objects in a global
|
||||
* map-table. They will be removed from there prior to deallocation. The
|
||||
* downside is that we need to protect the table with a lock. (A capacity of
|
||||
* 3 is a good guess because we will probably at most need a connection to
|
||||
* the session and one to the system bus).
|
||||
*/
|
||||
activeConnections = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSNonRetainedObjectMapValueCallBacks,
|
||||
3);
|
||||
activeConnectionLock = [NSRecursiveLock new];
|
||||
NSAssert((activeConnections && activeConnectionLock),
|
||||
@"Could not allocate map table and lock for D-Bus connection management");
|
||||
}
|
||||
|
||||
- (id) initWithConnection: (DBusConnection*)conn
|
||||
{
|
||||
DKEndpoint *oldConnection = nil;
|
||||
DKRunLoopContext *ctx = nil;
|
||||
BOOL initSuccess = NO;
|
||||
|
||||
if (nil == (self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* NULL connections are useless: */
|
||||
if (NULL == conn)
|
||||
{
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reference the connection on the dbus level so that it sticks around until
|
||||
* -cleanup is called.
|
||||
*/
|
||||
dbus_connection_ref(conn);
|
||||
connection = conn;
|
||||
[activeConnectionLock lock];
|
||||
NS_DURING
|
||||
{
|
||||
|
||||
/* Check wether we can reuse an old connection. */
|
||||
oldConnection = NSMapGet(activeConnections, (void*)connection);
|
||||
if (nil != oldConnection)
|
||||
{
|
||||
// Retain the old connection to make it stick around:
|
||||
[oldConnection retain];
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
[activeConnectionLock unlock];
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
if (nil != oldConnection)
|
||||
{
|
||||
[activeConnectionLock unlock];
|
||||
[self release];
|
||||
self = oldConnection;
|
||||
return self;
|
||||
}
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
// We keep the lock until we're done initializing.
|
||||
ctx = [[DKRunLoopContext alloc] initWithConnection: connection];
|
||||
|
||||
// Install our runLoop hooks:
|
||||
if ((initSuccess = (nil != ctx)))
|
||||
{
|
||||
initSuccess = (BOOL)dbus_connection_set_timeout_functions(connection,
|
||||
DKTimeoutAdd,
|
||||
DKTimeoutRemove,
|
||||
DKTimeoutToggled,
|
||||
(void*)ctx,
|
||||
DKRelease);
|
||||
}
|
||||
|
||||
if (initSuccess)
|
||||
{
|
||||
initSuccess = (BOOL)dbus_connection_set_watch_functions(connection,
|
||||
DKWatchAdd,
|
||||
DKWatchRemove,
|
||||
DKWatchToggled,
|
||||
(void*)ctx,
|
||||
DKRelease);
|
||||
}
|
||||
|
||||
if (initSuccess)
|
||||
{
|
||||
dbus_connection_set_wakeup_main_function(connection,
|
||||
DKWakeUp,
|
||||
(void*)ctx,
|
||||
DKRelease);
|
||||
dbus_connection_set_dispatch_status_function(connection,
|
||||
DKUpdateDispatchStatus,
|
||||
(void*)ctx,
|
||||
DKRelease);
|
||||
}
|
||||
|
||||
if (!initSuccess)
|
||||
{
|
||||
[self cleanup];
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
[activeConnectionLock unlock];
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
|
||||
if (!initSuccess)
|
||||
{
|
||||
[activeConnectionLock unlock];
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
NSMapInsert(activeConnections, connection, self);
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
[activeConnectionLock unlock];
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
|
||||
[activeConnectionLock unlock];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (DBusConnection*)connection
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* For use with non-well-known buses, not exteremly useful, but generic.
|
||||
*/
|
||||
- (id) initWithConnectionTo: (NSString*)endpoint
|
||||
{
|
||||
/* Note: dbus_connection_open_private() would be an option here, but would
|
||||
* require us to take care of the connections ourselves. Right now, this does
|
||||
* not seem to be worth the effort, so we let D-Bus do this for us (hence we
|
||||
* call dbus_connection_unref() and not dbus_connection_close() in -cleanup).
|
||||
*/
|
||||
DBusConnection *conn = dbus_connection_open([endpoint UTF8String], NULL);
|
||||
if (NULL == conn)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
self = [self initWithConnection: conn];
|
||||
// -initWithConnection did increase the refcount, we release ownership of the
|
||||
// connection:
|
||||
dbus_connection_unref(conn);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithWellKnownBus: (DBusBusType)type
|
||||
{
|
||||
DBusConnection *conn = dbus_bus_get(type, NULL);
|
||||
if (NULL == conn)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
self = [self initWithConnection: conn];
|
||||
// -initWithConnection did increase the refcount, we release ownership of the
|
||||
// connection:
|
||||
dbus_connection_unref(conn);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void) cleanup
|
||||
{
|
||||
if (connection != NULL)
|
||||
{
|
||||
// Make this endpoint unavailable to other threads:
|
||||
[activeConnectionLock lock];
|
||||
NS_DURING
|
||||
{
|
||||
if (connection != NULL)
|
||||
{
|
||||
NSMapRemove(activeConnections, connection);
|
||||
|
||||
dbus_connection_unref(connection);
|
||||
connection = NULL;
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
[activeConnectionLock unlock];
|
||||
[localException raise];
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
[activeConnectionLock unlock];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self cleanup];
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@implementation DKSystemBusEndpoint
|
||||
- (id)init
|
||||
{
|
||||
if (nil == (self = [super initWithWellKnownBus: DBUS_BUS_SYSTEM]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation DKSessionBusEndpoint
|
||||
- (id)init
|
||||
{
|
||||
if (nil == (self = [super initWithWellKnownBus: DBUS_BUS_SESSION]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation DKWatcher
|
||||
- (void)monitorForEvents: (NSUInteger)events
|
||||
{
|
||||
// Dispatch new events to the runLoop:
|
||||
if (events & DBUS_WATCH_READABLE)
|
||||
{
|
||||
[[ctx runLoop] addEvent: (void*)(intptr_t)fileDesc
|
||||
type: ET_RDESC
|
||||
watcher: self
|
||||
forMode: [ctx runLoopMode]];
|
||||
}
|
||||
if (events & DBUS_WATCH_WRITABLE)
|
||||
{
|
||||
[[ctx runLoop] addEvent: (void*)(intptr_t)fileDesc
|
||||
type: ET_WDESC
|
||||
watcher: self
|
||||
forMode: [ctx runLoopMode]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)unmonitorForEvents: (NSUInteger)events
|
||||
{
|
||||
// Remove events to the runLoop:
|
||||
if (events & DBUS_WATCH_READABLE)
|
||||
{
|
||||
[[ctx runLoop] removeEvent: (void*)(intptr_t)fileDesc
|
||||
type: ET_RDESC
|
||||
forMode: [ctx runLoopMode]
|
||||
all: NO];
|
||||
}
|
||||
if (events & DBUS_WATCH_WRITABLE)
|
||||
{
|
||||
[[ctx runLoop] removeEvent: (void*)(intptr_t)fileDesc
|
||||
type: ET_WDESC
|
||||
forMode: [ctx runLoopMode]
|
||||
all: NO];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (id)initWithWatch: (DBusWatch*)_watch
|
||||
andContext: (DKRunLoopContext*)aCtx
|
||||
forFd: (int)fd
|
||||
{
|
||||
if (nil == (self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
fileDesc = fd;
|
||||
// The context retains its watchers and timers:
|
||||
ctx = aCtx;
|
||||
watch = _watch;
|
||||
[self monitorForEvents: dbus_watch_get_flags(watch)];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)receivedEvent: (void*)data
|
||||
type: (RunLoopEventType)type
|
||||
extra: (void*)extra
|
||||
forMode: (NSString*)mode
|
||||
{
|
||||
int fd = (int)(intptr_t)data;
|
||||
if(fileDesc != fd)
|
||||
{
|
||||
//Not good
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ET_RDESC:
|
||||
NSLog(@"Handling readable on watch");
|
||||
dbus_watch_handle(watch, DBUS_WATCH_READABLE);
|
||||
break;
|
||||
case ET_WDESC:
|
||||
NSLog(@"Handling writable on watch");
|
||||
dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation DKRunLoopContext
|
||||
|
||||
- (id) initWithConnection: (DBusConnection*)conn
|
||||
{
|
||||
if (nil == (self = [super init]))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
connection = conn;
|
||||
|
||||
// TODO: Profile wether 10 is a reasonable default capacity.
|
||||
timers = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks,
|
||||
10);
|
||||
watchers = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSObjectMapValueCallBacks,
|
||||
10);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TODO: We need to handle different runLoops and runLoopModes.
|
||||
*/
|
||||
- (NSRunLoop*)runLoop
|
||||
{
|
||||
return [NSRunLoop currentRunLoop];
|
||||
}
|
||||
|
||||
- (NSString*)runLoopMode
|
||||
{
|
||||
return NSDefaultRunLoopMode;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
//TODO: Further Cleanup.
|
||||
NSFreeMapTable(watchers);
|
||||
NSFreeMapTable(timers);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)addTimeout: (DBusTimeout*)timeout
|
||||
withInterval: (int)milliSeconds
|
||||
{
|
||||
NSTimer *timer = nil;
|
||||
NSTimeInterval interval = (milliSeconds / 1000.0);
|
||||
NSAssert(timeout, @"Missing timeout data during D-Bus event handling.");
|
||||
|
||||
// Just return if we already have a timer for this timeout:
|
||||
if (NSMapGet(timers,timeout))
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
//Create the timer, saving the DBusTimeout pointer for later use.
|
||||
timer = [NSTimer timerWithTimeInterval: MAX(interval, 0.1)
|
||||
target: self
|
||||
selector: @selector(handleTimeout:)
|
||||
userInfo: [NSValue valueWithPointer: timeout]
|
||||
repeats: YES];
|
||||
if (timer == nil)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
[[self runLoop] addTimer: timer forMode: [self runLoopMode]];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeTimeout: (DBusTimeout*)timeout
|
||||
{
|
||||
NSTimer *timer = nil;
|
||||
NSAssert(timeout, @"Missing timeout data during D-Bus event handling.");
|
||||
timer = NSMapGet(timers,timeout);
|
||||
if (nil != timer)
|
||||
{
|
||||
[timer invalidate];
|
||||
NSMapRemove(timers,timeout);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleTimeout: (NSTimer*)timer
|
||||
{
|
||||
DBusTimeout *timeout = (DBusTimeout*)[(NSValue*)[timer userInfo] pointerValue];
|
||||
NSAssert(timeout, @"Missing timeout data during D-Bus event handling.");
|
||||
NSLog(@"Handling timeout");
|
||||
dbus_timeout_handle(timeout);
|
||||
/*
|
||||
* Note: dbus_timeout_handle() returns FALSE on OOM, but the documentation
|
||||
* specifies we just ignore that and retry the next time the timeout fires.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
- (void)dispatchForConnection: (NSValue*)value
|
||||
{
|
||||
DBusConnection *conn = (DBusConnection*)[value pointerValue];
|
||||
DBusDispatchStatus status;
|
||||
// If called with nil, we dispatch for the default connection:
|
||||
if ((value != nil) && (conn != connection))
|
||||
{
|
||||
// This should not happen and could be a sign of some corruption.
|
||||
NSWarnMLog(@"Called to dispatch for non-local conncetion durng D-Bus event handling.");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// We drain all messages instead of waiting for the next run loop iteration:
|
||||
status = dbus_connection_dispatch(connection);
|
||||
} while (DBUS_DISPATCH_DATA_REMAINS == status);
|
||||
}
|
||||
|
||||
- (BOOL)addWatch: (DBusWatch*)watch
|
||||
{
|
||||
NSInteger fd = -1;
|
||||
DKWatcher *watcher = nil;
|
||||
NSAssert(watch, @"Missing watch data during D-Bus event handling.");
|
||||
|
||||
# if defined(__MINGW__)
|
||||
// As per D-Bus documentation, WinSock is used on Windows platforms.
|
||||
fd = dbus_watch_get_socket(watch);
|
||||
# else
|
||||
fd = dbus_watch_get_unix_fd(watch);
|
||||
# endif
|
||||
|
||||
if (-1 == fd)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
watcher = [[DKWatcher alloc] initWithWatch: watch
|
||||
andContext: self
|
||||
forFd: fd];
|
||||
if (nil == watcher)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
NSMapInsert(watchers, watch, watcher);
|
||||
// The map table has retained the watcher, we can release it:
|
||||
[watcher release];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)removeWatch: (DBusWatch*)watch
|
||||
{
|
||||
|
||||
DKWatcher *watcher = nil;
|
||||
NSAssert(watch, @"Missing watch data during D-Bus event handling.");
|
||||
watcher = NSMapGet(watchers,watch);
|
||||
if (nil != watcher)
|
||||
{
|
||||
[watcher unmonitorForEvents: dbus_watch_get_flags(watch)];
|
||||
NSMapRemove(watchers, watch);
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#define CTX(x) DKRunLoopContext *ctx = (DKRunLoopContext*)x;\
|
||||
do { NSCAssert(x, @"Missing context data during D-Bus event handling.");} while (0)
|
||||
|
||||
|
||||
static dbus_bool_t
|
||||
DKTimeoutAdd(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
CTX(data);
|
||||
NSCAssert(timeout, @"Missing timeout data during D-Bus event handling.");
|
||||
NSLog(@"Timout added");
|
||||
if (NO == (BOOL)dbus_timeout_get_enabled(timeout))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return (dbus_bool_t)[ctx addTimeout: timeout
|
||||
withInterval: dbus_timeout_get_interval(timeout)];
|
||||
}
|
||||
|
||||
static void
|
||||
DKTimeoutRemove(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
CTX(data);
|
||||
NSCAssert(timeout, @"Missing timeout data during D-Bus event handling.");
|
||||
NSLog(@"Timeout removed");
|
||||
[ctx removeTimeout: timeout];
|
||||
}
|
||||
|
||||
static void
|
||||
DKTimeoutToggled(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
/*
|
||||
* Note: This is the easy solution, not sure whether we can be smarter about
|
||||
* this.
|
||||
*/
|
||||
NSLog(@"Timeout toggled");
|
||||
DKTimeoutRemove(timeout, data);
|
||||
DKTimeoutAdd(timeout, data);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
DKWatchAdd(DBusWatch *watch, void *data)
|
||||
{
|
||||
CTX(data);
|
||||
NSCAssert(watch, @"Missing watch data during D-Bus event handling.");
|
||||
NSLog(@"Watch added");
|
||||
if (!dbus_watch_get_enabled(watch))
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
return (dbus_bool_t)[ctx addWatch: watch];
|
||||
}
|
||||
|
||||
static void
|
||||
DKWatchRemove(DBusWatch *watch, void *data)
|
||||
{
|
||||
CTX(data);
|
||||
NSCAssert(watch, @"Missing watch data during D-Bus event handling.");
|
||||
NSLog(@"Removed watch");
|
||||
[ctx removeWatch: watch];
|
||||
}
|
||||
|
||||
static void
|
||||
DKWatchToggled(DBusWatch *watch, void *data)
|
||||
{
|
||||
/*
|
||||
* Note: This is the easy solution, not sure whether we can be smarter about
|
||||
* this.
|
||||
*/
|
||||
NSLog(@"Watch toggled");
|
||||
DKWatchRemove(watch, data);
|
||||
DKWatchAdd(watch, data);
|
||||
}
|
||||
|
||||
static void
|
||||
DKRelease(void *data)
|
||||
{
|
||||
NSLog(@"D-Bus calls release on something!");
|
||||
[(id)data release];
|
||||
}
|
||||
|
||||
static void
|
||||
DKWakeUp(void *data)
|
||||
{
|
||||
CTX(data);
|
||||
NSLog(@"Starting runLoop on D-Bus request");
|
||||
// If we are woken up, we surely need to dispatch new messages:
|
||||
[[ctx runLoop] performSelector: @selector(dispatchForConnection:)
|
||||
target: ctx
|
||||
argument: nil
|
||||
order: 0
|
||||
modes: [NSArray arrayWithObject: [ctx runLoopMode]]];
|
||||
[[ctx runLoop] runMode: [ctx runLoopMode]
|
||||
beforeDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]];
|
||||
}
|
||||
|
||||
static void
|
||||
DKUpdateDispatchStatus(DBusConnection *conn,
|
||||
DBusDispatchStatus status,
|
||||
void *data)
|
||||
{
|
||||
NSValue *connectionPointer;
|
||||
CTX(data);
|
||||
NSCAssert(conn, @"Missing connection data during D-Bus event handling");
|
||||
NSLog(@"Dispatch status changed to %d", status);
|
||||
switch (status)
|
||||
{
|
||||
case DBUS_DISPATCH_COMPLETE:
|
||||
NSLog(@"Dispatch complete");
|
||||
return;
|
||||
case DBUS_DISPATCH_NEED_MEMORY:
|
||||
NSLog(@"Insufficient memory for dispatch, will try again later");
|
||||
return;
|
||||
case DBUS_DISPATCH_DATA_REMAINS:
|
||||
NSLog(@"Will schedule handling of messages.");
|
||||
}
|
||||
connectionPointer = [NSValue valueWithPointer: conn];
|
||||
[[ctx runLoop] performSelector: @selector(dispatchForConnection:)
|
||||
target: ctx
|
||||
argument: connectionPointer
|
||||
order: 0
|
||||
modes: [NSArray arrayWithObject: [ctx runLoopMode]]];
|
||||
}
|
57
Source/DKPort.m
Normal file
57
Source/DKPort.m
Normal file
@ -0,0 +1,57 @@
|
||||
/** Implementation of the DKPort class for NSConnection integration.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Niels Grewe <niels.grewe@halbordnung.de>
|
||||
Created: May 2010
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#import "DBusKit/DKPort.h"
|
||||
#import "DKEndpoint.h"
|
||||
|
||||
|
||||
static Class DKPortAbstractClass;
|
||||
static Class DKPortConcreteClass;
|
||||
|
||||
@implementation DKPort
|
||||
+ (void)initialize
|
||||
{
|
||||
/*
|
||||
* Preload the class pointers to avoid expensive class message sends on every
|
||||
* +port call.
|
||||
*/
|
||||
Class abstractClass = [DKPort class];
|
||||
if (self == abstractClass)
|
||||
{
|
||||
DKPortAbstractClass = abstractClass;
|
||||
DKPortConcreteClass = [DKSessionBusPort class];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSPort*)port
|
||||
{
|
||||
if (self == DKPortAbstractClass)
|
||||
{
|
||||
return [[[DKPortConcreteClass alloc] init] autorelease];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [[[self alloc] init] autorelease];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
27
Source/GNUmakefile
Normal file
27
Source/GNUmakefile
Normal file
@ -0,0 +1,27 @@
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
|
||||
#
|
||||
# Main framework
|
||||
#
|
||||
SUBPROJECT_NAME = libDBusKit
|
||||
|
||||
# Include configuration
|
||||
|
||||
-include ../config.make
|
||||
|
||||
#
|
||||
# Class files
|
||||
#
|
||||
libDBusKit_OBJC_FILES = \
|
||||
DKEndpoint.m \
|
||||
DKPort.m
|
||||
|
||||
#
|
||||
# C files
|
||||
#
|
||||
libDBusKit_C_FILES =
|
||||
|
||||
-include ../GNUmakefile.preamble
|
||||
include $(GNUSTEP_MAKEFILES)/subproject.make
|
||||
|
||||
-include ../GNUmakefile.postamble
|
2
config.make.in
Normal file
2
config.make.in
Normal file
@ -0,0 +1,2 @@
|
||||
ADDITIONAL_OBJCFLAGS+=@DBUS_CFLAGS@
|
||||
ADDITIONAL_LIBRARY+=@DBUS_LIBS@
|
22
configure.ac
Normal file
22
configure.ac
Normal file
@ -0,0 +1,22 @@
|
||||
# autoconf template for the configure script
|
||||
|
||||
AC_INIT
|
||||
|
||||
PKG_PROG_PKG_CONFIG([])
|
||||
|
||||
# FIXME: We need a proper test for libobjc2 for some advanced features (e.g.
|
||||
# the declared-properties - dbus-properties bridge).
|
||||
# AC_CHECK_FUNCS(objc_setProperty)
|
||||
# if test $ac_cv_func_objc_setProperty = yes ; then
|
||||
# HAVE_OBJC2=1
|
||||
# else
|
||||
# HAVE_OBJC2=0
|
||||
# fi
|
||||
|
||||
PKG_CHECK_MODULES(DBUS, dbus-1, HAVE_DBUS=1, HAVE_DBUS=0)
|
||||
AC_SUBST(DBUS_CFLAGS)
|
||||
AC_SUBST(DBUS_LIBS)
|
||||
|
||||
AC_CONFIG_FILES([config.make Headers/config.h])
|
||||
|
||||
AC_OUTPUT
|
Loading…
Reference in New Issue
Block a user