From 7b682f4f608677de7006b22ac3f411bb8331bc99 Mon Sep 17 00:00:00 2001 From: Andrew Resch Date: Thu, 26 Feb 2009 01:47:40 +0000 Subject: [PATCH] Implement new IPC system. There is no longer a dependency on DBUS and this system should work on all platforms. --- README | 1 - deluge/ui/gtkui/dbusinterface.py | 86 -------------------------------- deluge/ui/gtkui/ipcinterface.py | 72 +++++++++++++------------- 3 files changed, 38 insertions(+), 121 deletions(-) delete mode 100644 deluge/ui/gtkui/dbusinterface.py diff --git a/README b/README index 3e84c5934..6b9c7ab4a 100644 --- a/README +++ b/README @@ -49,7 +49,6 @@ Dependencies: gettext Gtk: - dbus-python python-notify (libnotify python wrapper) pygame pygtk >= 2.10 diff --git a/deluge/ui/gtkui/dbusinterface.py b/deluge/ui/gtkui/dbusinterface.py deleted file mode 100644 index 52c75b758..000000000 --- a/deluge/ui/gtkui/dbusinterface.py +++ /dev/null @@ -1,86 +0,0 @@ -# -# dbusinterface.py -# -# Copyright (C) 2007 Andrew Resch -# -# Deluge is free software. -# -# You may redistribute it and/or modify it under the terms of the -# GNU General Public License, as published by the Free Software -# Foundation; either version 3 of the License, or (at your option) -# any later version. -# -# deluge 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with deluge. If not, write to: -# The Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor -# Boston, MA 02110-1301, USA. -# - - -import sys -import os - -# Import DBUS -import dbus, dbus.service - -if dbus.version >= (0,41,0) and dbus.version < (0,80,0): - import dbus.glib -elif dbus.version >= (0,80,0): - from dbus.mainloop.glib import DBusGMainLoop - DBusGMainLoop(set_as_default=True) - -import deluge.component as component -import deluge.common -from deluge.log import LOG as log - -class DbusInterface(dbus.service.Object, component.Component): - def __init__(self, args, path="/org/deluge_torrent/Deluge"): - component.Component.__init__(self, "DbusInterface") - # Check to see if the daemon is already running and if not, start it - bus = dbus.SessionBus() - obj = bus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus") - iface = dbus.Interface(obj, "org.freedesktop.DBus") - if iface.NameHasOwner("org.deluge_torrent.Deluge"): - # Deluge client already running.. Lets exit. - log.info("Deluge already running..") - log.debug("args: %s", args) - # Convert the paths to absolutes - new_args = [] - for arg in args: - if not deluge.common.is_url(arg) and not deluge.common.is_magnet(arg): - new_args.append(os.path.abspath(arg)) - else: - new_args.append(arg) - args = new_args - - # Send the args to the running session - if args != [] and args != None: - bus = dbus.SessionBus() - proxy = bus.get_object("org.deluge_torrent.Deluge", - "/org/deluge_torrent/Deluge") - ui = dbus.Interface(proxy, "org.deluge_torrent.Deluge") - ui.process_args(args) - # Exit - log.debug("Exiting..") - sys.exit(0) - - # Process the args if any - self.process_args(args) - # Register Deluge with Dbus - log.info("Registering with DBUS..") - bus_name = dbus.service.BusName("org.deluge_torrent.Deluge", - bus=dbus.SessionBus()) - dbus.service.Object.__init__(self, bus_name, path) - - @dbus.service.method("org.deluge_torrent.Deluge", in_signature="as") - def process_args(self, args): - """Process arguments sent to already running Deluge""" - from ipcinterface import process_args - process_args(args) - diff --git a/deluge/ui/gtkui/ipcinterface.py b/deluge/ui/gtkui/ipcinterface.py index 6ea148afb..3df013975 100644 --- a/deluge/ui/gtkui/ipcinterface.py +++ b/deluge/ui/gtkui/ipcinterface.py @@ -1,7 +1,7 @@ # # ipcinterface.py # -# Copyright (C) 2008 Andrew Resch +# Copyright (C) 2008-2009 Andrew Resch # # Deluge is free software. # @@ -27,53 +27,57 @@ import sys import os.path import base64 +import deluge.rencode import deluge.component as component from deluge.ui.client import client import deluge.common from deluge.configmanager import ConfigManager from deluge.log import LOG as log +from twisted.internet.protocol import Factory, Protocol, ClientFactory +from twisted.internet import reactor +import twisted.internet.error + +class IPCProtocolServer(Protocol): + def dataReceived(self, data): + data = deluge.rencode.loads(data) + log.debug("Data received: %s", data) + process_args(data) + +class IPCProtocolClient(Protocol): + def connectionMade(self): + log.debug("Connection made!") + self.transport.write(deluge.rencode.dumps(self.factory.args)) + self.transport.loseConnection() + def connectionLost(self, reason): + reactor.stop() + class IPCInterface(component.Component): def __init__(self, args): component.Component.__init__(self, "IPCInterface") + log.debug("args: %s", args) + if not os.path.exists(deluge.configmanager.get_config_dir("ipc")): + os.makedirs(deluge.configmanager.get_config_dir("ipc")) - if deluge.common.windows_check(): - # If we're on windows we need to check the global mutex to see if deluge is - # already running. - import win32event - import win32api - import winerror - self.mutex = win32event.CreateMutex(None, False, "deluge") - if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS: - # We already have a running session, send a XMLRPC to the existing session - config = ConfigManager("gtkui.conf") - # XXX: Need new IPC method - # uri = "http://localhost:" + str(config["signal_port"]) - # import deluge.xmlrpclib as xmlrpclib - # rpc = xmlrpclib.ServerProxy(uri, allow_none=True) - # rpc.emit_signal("args_from_external", args) - sys.exit(0) - else: - process_args(args) - else: - try: - import dbusinterface - self.dbusinterface = dbusinterface.DbusInterface(args) - except Exception, e: - log.warning("Unable to start DBUS component: %s", e) + socket = os.path.join(deluge.configmanager.get_config_dir("ipc"), "deluge-gtk") - def shutdown(self): - if deluge.common.windows_check(): - import win32api - win32api.CloseHandle(self.mutex) + try: + self.factory = Factory() + self.factory.protocol = IPCProtocolServer + reactor.listenUNIX(socket, self.factory, wantPID=True) + except twisted.internet.error.CannotListenError, e: + log.info("Deluge is already running! Sending arguments to running instance..") + self.factory = ClientFactory() + self.factory.args = args + self.factory.protocol = IPCProtocolClient + reactor.connectUNIX(socket, self.factory, checkPID=True) + reactor.run() + sys.exit(0) def process_args(args): """Process arguments sent to already running Deluge""" - # Pythonize the values from Dbus - dbus_args = args - args = [] - for arg in dbus_args: - args.append(str(arg)) + # Make sure args is a list + args = list(args) log.debug("Processing args from other process: %s", args) if not client.connected(): # We're not connected so add these to the queue