summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCalum Lind <calumlind+deluge@gmail.com>2013-02-14 00:29:14 +0000
committerCalum Lind <calumlind+deluge@gmail.com>2013-02-14 00:29:55 +0000
commit2cbcb35c9e68e81926389eb251c706ae7b4e831f (patch)
tree8d713af7e9941cd9b7a81bda8c10a640e7a03ab7
parent7ef7cc41b6f001220e83bcb34454e8804d2b1101 (diff)
downloaddeluge-2cbcb35c9e68e81926389eb251c706ae7b4e831f.tar.gz
deluge-2cbcb35c9e68e81926389eb251c706ae7b4e831f.tar.bz2
deluge-2cbcb35c9e68e81926389eb251c706ae7b4e831f.zip
Add OSX packaging and GTK support
-rw-r--r--.gitignore1
-rw-r--r--deluge/ui/gtkui/gtkui.py22
-rw-r--r--deluge/ui/gtkui/menubar_osx.py97
-rw-r--r--osx/Info.plist59
-rw-r--r--osx/README.md119
-rwxr-xr-xosx/deluge-console.sh69
-rwxr-xr-xosx/deluge-web.sh69
-rw-r--r--osx/deluge.bundle50
-rw-r--r--osx/deluge.icnsbin0 -> 201047 bytes
-rw-r--r--osx/deluge.modules129
-rwxr-xr-xosx/deluge.sh77
-rwxr-xr-xosx/deluged.sh69
-rw-r--r--osx/gtkrc10
-rw-r--r--osx/jhbuildrc-custom28
-rwxr-xr-xosx/make-app.sh44
-rw-r--r--osx/torrent.icnsbin0 -> 199899 bytes
-rw-r--r--setup.cfg11
17 files changed, 853 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index cf7a67e64..76d5be39c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ _trial_temp
deluge/i18n/*/
*.desktop
.build_data*
+osx/app
diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py
index 894e81903..443c76d95 100644
--- a/deluge/ui/gtkui/gtkui.py
+++ b/deluge/ui/gtkui/gtkui.py
@@ -197,6 +197,14 @@ class GtkUI(object):
return 1
SetConsoleCtrlHandler(win_handler)
+ if deluge.common.osx_check() and gtk.gdk.WINDOWING == "quartz":
+ import gtk_osxapplication
+ self.osxapp = gtk_osxapplication.OSXApplication()
+ def on_die(*args):
+ reactor.stop()
+ self.osxapp.connect("NSApplicationWillTerminate", on_die)
+
+
# Set process name again to fix gtk issue
setproctitle(getproctitle())
@@ -238,6 +246,18 @@ class GtkUI(object):
self.statusbar = StatusBar()
self.addtorrentdialog = AddTorrentDialog()
+ if deluge.common.osx_check() and gtk.gdk.WINDOWING == "quartz":
+ def nsapp_open_file(osxapp, filename):
+ # Will be raised at app launch (python opening main script)
+ if filename.endswith('Deluge-bin'):
+ return True
+ from deluge.ui.gtkui.ipcinterface import process_args
+ process_args([filename])
+ self.osxapp.connect("NSApplicationOpenFile", nsapp_open_file)
+ from menubar_osx import menubar_osx
+ menubar_osx(self, self.osxapp)
+ self.osxapp.ready()
+
# Initalize the plugins
self.plugins = PluginManager()
@@ -261,7 +281,7 @@ class GtkUI(object):
component.stop()
# Process any pending gtk events since the mainloop has been quit
- if not deluge.common.windows_check():
+ if not deluge.common.windows_check() and not deluge.common.osx_check():
while gtk.events_pending() and reactor.running:
reactor.doIteration(0)
diff --git a/deluge/ui/gtkui/menubar_osx.py b/deluge/ui/gtkui/menubar_osx.py
new file mode 100644
index 000000000..43f290c4e
--- /dev/null
+++ b/deluge/ui/gtkui/menubar_osx.py
@@ -0,0 +1,97 @@
+#
+# menubar_osx.py
+#
+# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
+#
+# 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.
+#
+# In addition, as a special exception, the copyright holders give
+# permission to link the code of portions of this program with the OpenSSL
+# library.
+# You must obey the GNU General Public License in all respects for all of
+# the code used other than OpenSSL. If you modify file(s) with this
+# exception, you may extend this exception to your version of the file(s),
+# but you are not obligated to do so. If you do not wish to do so, delete
+# this exception statement from your version. If you delete this exception
+# statement from all source files in the program, then also delete it here.
+#
+#
+import gtk, gtk.glade
+
+from deluge.configmanager import ConfigManager
+
+def accel_swap(item, group, skey, smod, dkey, dmod):
+ item.remove_accelerator(group, ord(skey), smod)
+ item.add_accelerator("activate", group, ord(dkey), dmod, gtk.ACCEL_VISIBLE)
+
+def accel_meta(item, group, key):
+ accel_swap(item, group, key, gtk.gdk.CONTROL_MASK, key, gtk.gdk.META_MASK)
+
+def menubar_osx(gtkui, osxapp):
+ window = gtkui.mainwindow
+ glade = window.main_glade
+ menubar = glade.get_widget("menubar")
+ group = gtk.accel_groups_from_object(window.window)[0]
+
+ config = ConfigManager("gtkui.conf")
+
+ # NOTE: accel maps doesn't work with glade file format
+ # because of libglade not setting MenuItem accel groups
+ # That's why we remove / set accelerators by hand... (dirty)
+ # Clean solution: migrate glades files to gtkbuilder format
+ file_menu = glade.get_widget("menu_file").get_submenu()
+ file_items = file_menu.get_children()
+ accel_meta(file_items[0], group, 'o')
+ accel_meta(file_items[1], group, 'n')
+ quit_all_item = file_items[3]
+ accel_swap(quit_all_item, group, 'q', gtk.gdk.SHIFT_MASK | gtk.gdk.CONTROL_MASK,
+ 'q', gtk.gdk.SHIFT_MASK | gtk.gdk.META_MASK)
+ for item in range(2, len(file_items)): # remove quits
+ file_menu.remove(file_items[item])
+
+ menu_widget = glade.get_widget("menu_edit")
+ edit_menu = menu_widget.get_submenu()
+ edit_items = edit_menu.get_children()
+ pref_item = edit_items[0]
+ accel_swap(pref_item, group, 'p', gtk.gdk.CONTROL_MASK, ',', gtk.gdk.META_MASK)
+ edit_menu.remove(pref_item)
+
+ conn_item = edit_items[1]
+ accel_meta(conn_item, group, 'm')
+ edit_menu.remove(conn_item)
+
+ menubar.remove(menu_widget)
+
+ help_menu = glade.get_widget("menu_help").get_submenu()
+ help_items = help_menu.get_children()
+ about_item = help_items[4]
+ help_menu.remove(about_item)
+ help_menu.remove(help_items[3]) # separator
+
+ menubar.hide()
+ osxapp.set_menu_bar(menubar)
+ # populate app menu
+ osxapp.insert_app_menu_item(about_item, 0)
+ osxapp.insert_app_menu_item(gtk.SeparatorMenuItem(), 1)
+ osxapp.insert_app_menu_item(pref_item, 2)
+ if not config["classic_mode"]:
+ osxapp.insert_app_menu_item(conn_item, 3)
+ if quit_all_item.get_visible():
+ osxapp.insert_app_menu_item(gtk.SeparatorMenuItem(), 4)
+ osxapp.insert_app_menu_item(quit_all_item, 5)
diff --git a/osx/Info.plist b/osx/Info.plist
new file mode 100644
index 000000000..52bdca08b
--- /dev/null
+++ b/osx/Info.plist
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleIdentifier</key>
+ <string>org.deluge</string>
+ <key>CFBundleName</key>
+ <string>Deluge</string>
+ <key>CFBundleIconFile</key>
+ <string>deluge.icns</string>
+ <key>CFBundleExecutable</key>
+ <string>Deluge</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.3.5</string>
+ <key>CFBundleVersion</key>
+ <string>1.3.5</string>
+ <key>CFBundleGetInfoString</key>
+ <string>1.3.5 (c) 2008-2011 Deluge Team http://deluge-torrent.org/</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>Copyright 2008-2011 Deluge Team</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>DL##</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>10.6</string>
+ <key>LSUIElement</key>
+ <string>0</string>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+ <key>CFBundleDisplayName</key>
+ <string>Deluge</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>torrent</string>
+ </array>
+ <key>CFBundleTypeIconFile</key>
+ <string>torrent</string>
+ <key>CFBundleTypeName</key>
+ <string>BitTorrent Document</string>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ <key>LSHandlerRank</key>
+ <string>Owner</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.bittorrent.torrent</string>
+ </array>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/osx/README.md b/osx/README.md
new file mode 100644
index 000000000..1f00d3898
--- /dev/null
+++ b/osx/README.md
@@ -0,0 +1,119 @@
+# Instructions for building Deluge.app
+
+## 1. Compiler
+
+- To build deluge and the gtk osx modules, you must use `gcc`
+- This has been successfully working with :
+ - gcc 4.2.1 - Xcode 4.1 - Mac OSX Lion (10.7.2)
+ - llvm-gcc 4.2.1 - Xcode 4.3.1 (With Command line utilities) - Mac OSX Lion (10.7.3)
+- Check your version of gcc using `gcc -v`
+
+## 2. GTK-OSX [jhbuild][1] environment
+
+Quick how-to *(from the full [GTK-OSX building][2] instructions)*
+
+1. Create a dedicated user account and use it for all the next steps:
+
+ *Note*: I'm using `gtk` login with `/opt/gtk` as home an jhbuild prefix
+
+ sudo su - gtk
+ cat << EOF > ~/.profile
+ export PATH=~/.local/bin:~/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/git/bin
+ EOF
+ . ~/.profile
+
+2. Download and run the [gtk-osx-build-setup][3] script to install jhbuild:
+
+ curl -O https://raw.github.com/jralls/gtk-osx-build/master/gtk-osx-build-setup.sh
+ sh gtk-osx-build-setup.sh
+
+3. Link or copy deluge osx jhbuildrc-custom:
+
+ *Note*: This setup builds only for `x86_64` arch to `/opt/gtk`
+ prefix, feel free to edit
+
+ ln -sf deluge/osx/jhbuildrc-custom ~/.jhbuildrc-custom
+
+4. Build jhbuild and its modulesets: *(takes a while...)*
+
+ jhbuild bootstrap && jhbuild
+
+
+ *Note*: If you encounter an error while building `glib` like:
+
+ gconvert.c:65:2: error: #error GNU libiconv not in use but included iconv.h is from libiconv
+
+ Start a shell from jhbuild (#4), edit the file `vim glib/gconvert.c +65`
+ to delete the section raising error, which is irrelevant. *(Lion
+ iconv.h looks like gnu one, but it is not)*
+ Then exit the shell and resume build (#1)
+
+5. Build the deluge moduleset: *(takes a while...)*
+
+ *Note*: This jhbuild moduleset *should* build and install all deluge
+ dependencies not available in gtk-osx
+
+ jhbuild -m deluge/osx/deluge.modules build deluge
+
+## 3. Build Deluge.app
+
+1. Always do your custom build operations under a jhbuild shell:
+
+ jhbuild shell
+
+2. Cleanup:
+
+ python setup.py clean -a
+
+3. Build and install:
+
+ python setup.py py2app
+ python setup.py install
+
+4. Build app to `deluge/osx/app/Deluge.app`:
+
+ cd osx
+ ./make-app.sh
+
+You *should* have now a working Deluge.app
+
+i386 Notes:
+
+- Uncomment the relevant sections of :
+ - jhbuildrc-custom
+ - deluge.modules
+ - setup.cfg
+- deluge egg has to be named without the -macosx-10.6-intel suffix
+- To build for i386 under a x64 arch libtorrent python bindings have to be
+ patched manually to set correct arch see macports package patch
+
+## Issues
+
+If Deluge.app doesn't work or crash the first thing to do is to check OSX
+Console for logs and/or crash reports. Alternatively, you can enable python
+log by uncommenting the end of script `Deluge.app/Contents/MacOS/Deluge`
+
+Recent jhbuild issues:
+
+- Some jhbuild modules fails to build, freetype and gtk-mac-integration,
+ strangely configure is not called before build/install.
+- If that happens, just force rebuild with something like:
+
+ jhbuild build -cf gtk-mac-integration-python
+
+- Interrupt while building with ctrl-C and wipe to start over if configure missing
+
+### Known issues
+
+- **i386**: libtorrent crash
+- **i18n**: English only for now
+- **Magnet URLs**: Not currently supported by GTK-OSX
+
+## Reference
+
+[1]:http://live.gnome.org/Jhbuild
+[2]:http://live.gnome.org/GTK%2B/OSX/Building
+[3]:http://github.com/jralls/gtk-osx-build
+[4]:http://winswitch.org/dev/macosx.html
+[5]:http://mail.python.org/pipermail/pythonmac-sig/
+[6]:https://github.com/jralls/gtk-mac-integration
diff --git a/osx/deluge-console.sh b/osx/deluge-console.sh
new file mode 100755
index 000000000..9c07e4c10
--- /dev/null
+++ b/osx/deluge-console.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+EXEC="exec"
+
+name="`basename $0`"
+if [[ "$0" == `pwd`* ]] || [[ "$0" == "//"* ]]; then
+ full_path="$0"
+else
+ full_path="`pwd`/$0"
+fi
+tmp=`dirname "$full_path"`
+tmp=`dirname "$tmp"`
+bundle=`dirname "$tmp"`
+bundle_contents="$bundle"/Contents
+bundle_macos="$bundle_contents"/MacOS
+bundle_res="$bundle_contents"/Resources
+bundle_lib="$bundle_res"/lib
+bundle_bin="$bundle_res"/bin
+bundle_data="$bundle_res"/share
+bundle_etc="$bundle_res"/etc
+
+export DYLD_LIBRARY_PATH="$bundle_lib"
+export XDG_CONFIG_DIRS="$bundle_etc"/xdg
+export XDG_DATA_DIRS="$bundle_data"
+
+#Set $PYTHON to point inside the bundle
+export PYTHON="$bundle_macos/Deluge-python"
+export PYTHONHOME="$bundle_res"
+#Add the bundle's python modules
+PYTHONPATH="$bundle_lib:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/python/lib-dynload/:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/python/:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/pygtk/2.0:$PYTHONPATH"
+export PYTHONPATH
+
+# We need a UTF-8 locale.
+lang=`defaults read .GlobalPreferences AppleLocale 2>/dev/null`
+if test "$?" != "0"; then
+ lang=`defaults read .GlobalPreferences AppleCollationOrder 2>/dev/null | sed 's/_.*//'`
+fi
+LANG=""
+if test "$lang" != ""; then
+ LANG="`grep \"\`echo $lang\`_\" /usr/share/locale/locale.alias | \
+ tail -n1 | sed 's/\./ /' | awk '{print $2}'`"
+fi
+if test "$LANG" == ""; then
+ export LANG="C"
+else
+ export LANG="$LANG.utf8"
+fi
+
+if test -f "$bundle_lib/charset.alias"; then
+ export CHARSETALIASDIR="$bundle_lib"
+fi
+
+# Extra arguments can be added in environment.sh.
+EXTRA_ARGS=
+if test -f "$bundle_res/environment.sh"; then
+ source "$bundle_res/environment.sh"
+fi
+
+# Strip out the argument added by the OS.
+if [ "x`echo "x$1" | sed -e "s/^x-psn_.*//"`" == "x" ]; then
+ shift 1
+fi
+
+#Note that we're calling $PYTHON here to override the version in
+#pygtk-demo's shebang.
+$EXEC "$PYTHON" "$bundle_contents/MacOS/deluge-console-bin" "$@" #-l ~/.config/deluge/console.log -L debug
diff --git a/osx/deluge-web.sh b/osx/deluge-web.sh
new file mode 100755
index 000000000..d71603098
--- /dev/null
+++ b/osx/deluge-web.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+EXEC="exec"
+
+name="`basename $0`"
+if [[ "$0" == `pwd`* ]] || [[ "$0" == "//"* ]]; then
+ full_path="$0"
+else
+ full_path="`pwd`/$0"
+fi
+tmp=`dirname "$full_path"`
+tmp=`dirname "$tmp"`
+bundle=`dirname "$tmp"`
+bundle_contents="$bundle"/Contents
+bundle_macos="$bundle_contents"/MacOS
+bundle_res="$bundle_contents"/Resources
+bundle_lib="$bundle_res"/lib
+bundle_bin="$bundle_res"/bin
+bundle_data="$bundle_res"/share
+bundle_etc="$bundle_res"/etc
+
+export DYLD_LIBRARY_PATH="$bundle_lib"
+export XDG_CONFIG_DIRS="$bundle_etc"/xdg
+export XDG_DATA_DIRS="$bundle_data"
+
+#Set $PYTHON to point inside the bundle
+export PYTHON="$bundle_macos/Deluge-python"
+export PYTHONHOME="$bundle_res"
+#Add the bundle's python modules
+PYTHONPATH="$bundle_lib:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/python/lib-dynload/:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/python/:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/pygtk/2.0:$PYTHONPATH"
+export PYTHONPATH
+
+# We need a UTF-8 locale.
+lang=`defaults read .GlobalPreferences AppleLocale 2>/dev/null`
+if test "$?" != "0"; then
+ lang=`defaults read .GlobalPreferences AppleCollationOrder 2>/dev/null | sed 's/_.*//'`
+fi
+LANG=""
+if test "$lang" != ""; then
+ LANG="`grep \"\`echo $lang\`_\" /usr/share/locale/locale.alias | \
+ tail -n1 | sed 's/\./ /' | awk '{print $2}'`"
+fi
+if test "$LANG" == ""; then
+ export LANG="C"
+else
+ export LANG="$LANG.utf8"
+fi
+
+if test -f "$bundle_lib/charset.alias"; then
+ export CHARSETALIASDIR="$bundle_lib"
+fi
+
+# Extra arguments can be added in environment.sh.
+EXTRA_ARGS=
+if test -f "$bundle_res/environment.sh"; then
+ source "$bundle_res/environment.sh"
+fi
+
+# Strip out the argument added by the OS.
+if [ "x`echo "x$1" | sed -e "s/^x-psn_.*//"`" == "x" ]; then
+ shift 1
+fi
+
+#Note that we're calling $PYTHON here to override the version in
+#pygtk-demo's shebang.
+$EXEC "$PYTHON" "$bundle_contents/MacOS/deluge-web-bin" "$@" #-l ~/.config/deluge/web.log -L debug
diff --git a/osx/deluge.bundle b/osx/deluge.bundle
new file mode 100644
index 000000000..99b5effbd
--- /dev/null
+++ b/osx/deluge.bundle
@@ -0,0 +1,50 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<app-bundle>
+ <meta>
+ <prefix name="default">${env:JHBUILD_PREFIX}</prefix>
+ <destination overwrite="yes">app</destination>
+ <run-install-name-tool/>
+ <launcher-script>${project}/deluge.sh</launcher-script>
+ </meta>
+ <plist>${project}/Info.plist</plist>
+ <main-binary>${prefix}/bin/deluge-gtk</main-binary>
+ <binary dest="${bundle}/Contents/MacOS/deluged-bin">
+ ${prefix}/bin/deluged
+ </binary>
+ <binary dest="${bundle}/Contents/MacOS/deluge-web-bin">
+ ${prefix}/bin/deluge-web
+ </binary>
+ <binary dest="${bundle}/Contents/MacOS/deluge-console-bin">
+ ${prefix}/bin/deluge-console
+ </binary>
+ <binary dest="${bundle}/Contents/MacOS/Deluge-python">
+ ${prefix}/bin/python
+ </binary>
+ <!-- not used: binary>${prefix}/lib/${gtkdir}/modules/*.so</binary-->
+ <binary>${prefix}/lib/gdk-pixbuf-2.0/2.10.0/loaders/*.so</binary>
+ <binary>${prefix}/lib/libpyglib-2.0-python.0.dylib</binary>
+ <binary>${prefix}/lib/libgtk-quartz-2.0.0.dylib</binary>
+ <binary>${prefix}/lib/libglade-2.0.0.dylib</binary>
+ <binary>${prefix}/lib/libgtkmacintegration.0.dylib</binary>
+ <binary>${prefix}/lib/librsvg-2.2.dylib</binary>
+ <binary>${prefix}/lib/pango/1.6.0/modules/pango*.so</binary>
+ <binary>${prefix}/lib/libboost_*.dylib</binary>
+ <binary>${prefix}/lib/libtorrent-rasterbar.6.dylib</binary>
+ <binary>${prefix}/lib/libssl.1.0.0.dylib</binary>
+ <data dest="${bundle}/Contents/Resources/">
+ ${project}/../dist/deluge.app/Contents/Resources/
+ </data>
+ <data>${prefix}/lib/pygtk/2.0/</data>
+ <!-- gtk theme -->
+ <binary>${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/engines/libclearlooks.so</binary>
+ <data>${prefix}/share/themes/Clearlooks</data>
+ <data>${prefix}/share/themes/Mac</data><!-- required for stock accelerators cmd-X etc... -->
+ <!-- Emacs shortcuts doesn't work: data>${prefix}/share/themes/Emacs</data-->
+ <data dest="${bundle}/Contents/Resources/etc/gtk-2.0/gtkrc">${project}/gtkrc</data>
+ <data dest="${bundle}/Contents/Resources">${project}/deluge.icns</data>
+ <data dest="${bundle}/Contents/Resources">${project}/torrent.icns</data>
+
+ <data dest="${bundle}/Contents/MacOS/deluged">${project}/deluged.sh</data>
+ <data dest="${bundle}/Contents/MacOS/deluge-web">${project}/deluge-web.sh</data>
+ <data dest="${bundle}/Contents/MacOS/deluge-console">${project}/deluge-console.sh</data>
+</app-bundle>
diff --git a/osx/deluge.icns b/osx/deluge.icns
new file mode 100644
index 000000000..125a23db3
--- /dev/null
+++ b/osx/deluge.icns
Binary files differ
diff --git a/osx/deluge.modules b/osx/deluge.modules
new file mode 100644
index 000000000..041ba55df
--- /dev/null
+++ b/osx/deluge.modules
@@ -0,0 +1,129 @@
+<?xml version="1.0"?>
+<!DOCTYPE moduleset SYSTEM "moduleset.dtd">
+<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
+<moduleset>
+ <repository type="tarball" name="sourceforge"
+ href="http://downloads.sourceforge.net/sourceforge/"/>
+ <repository type="git" name="github.com"
+ href="git://github.com/"/>
+
+ <metamodule id="deluge">
+ <dependencies>
+ <dep package="libtorrent"/>
+ <dep package="gtk-mac-bundler"/>
+ <dep package="deluge-python-deps"/>
+ </dependencies>
+ </metamodule>
+
+ <repository type="tarball" name="libtorrent"
+ href="http://libtorrent.googlecode.com/files/"/>
+ <autotools id="libtorrent" autogen-sh="configure"
+ autogen-template="%(srcdir)s/%(autogen-sh)s --prefix=%(prefix)s --with-boost-libdir=%(libdir)s --with-openssl=%(prefix)s %(autogenargs)s"
+ autogenargs="--enable-python-binding CPPFLAGS='-DBOOST_FILESYSTEM_VERSION=2' --with-boost-thread=boost_thread">
+ <branch repo="libtorrent" version="0.15.10"
+ module="libtorrent-rasterbar-0.15.10.tar.gz"
+ hash="sha1:3e461d9ede5fab3fb59be6a9f0cbc52121d536c4"/>
+ <dependencies>
+ <dep package="openssl"/>
+ <dep package="boost"/>
+ </dependencies>
+ </autotools>
+
+ <repository type="tarball" name="openssl"
+ href="http://www.openssl.org/source/"/>
+ <autotools id="openssl" autogen-sh="Configure"
+ autogen-template="%(srcdir)s/%(autogen-sh)s --prefix=%(prefix)s -L%(libdir)s --openssldir=%(prefix)s/etc/openssl %(autogenargs)s"
+ autogenargs="darwin64-x86_64-cc zlib no-asm no-krb5 shared">
+ <!--autogenargs="darwin-i386-cc zlib no-asm no-krb5 shared">-->
+ <branch repo="openssl" version="1.0.0g"
+ module="openssl-1.0.0g.tar.gz"
+ md5sum="07ecbe4324f140d157478637d6beccf1"/>
+ </autotools>
+
+ <autotools id="boost" autogen-sh="bootstrap.sh"
+ autogen-template="%(srcdir)s/%(autogen-sh)s --prefix=%(prefix)s --libdir=%(prefix)s/lib --with-python=%(prefix)s/bin/python --with-icu=%(prefix)s --without-libraries=mpi"
+ supports-non-srcdir-builds="false"
+ makeargs="|| ./b2 link=shared threading=multi variant=release"
+ makeinstallargs="|| ./b2 install link=shared threading=multi variant=release">
+ <!--makeargs="|| ./b2 architecture=x86 link=shared threading=multi variant=release"
+ makeinstallargs="|| ./b2 install architecture=x86 link=shared threading=multi variant=release"-->
+ <branch repo="sourceforge"
+ module="boost/boost_1_49_0.tar.bz2" version="1.49"
+ md5sum="0d202cb811f934282dea64856a175698"/>
+ </autotools>
+
+ <autotools id="gtk-mac-bundler" autogen-template="echo no configure">
+ <branch repo="github.com" module="jralls/gtk-mac-bundler.git"/>
+ </autotools>
+
+ <metamodule id="deluge-python-deps">
+ <dependencies>
+ <dep package="setuptools"/>
+ <dep package="chardet"/>
+ <dep package="pyopenssl"/>
+ <dep package="pyxdg"/>
+ <dep package="py2app"/>
+ <dep package="mako"/>
+ <dep package="twisted"/>
+ <dep package="twisted-web"/>
+ </dependencies>
+ </metamodule>
+ <repository type="tarball" name="pypi"
+ href="http://pypi.python.org/packages/source/"/>
+ <distutils id="setuptools">
+ <branch repo="pypi" version="0.6c11"
+ module="s/setuptools/setuptools-0.6c11.tar.gz"/>
+ </distutils>
+ <distutils id="chardet">
+ <branch repo="pypi" version="1.0.1"
+ module="c/chardet/chardet-1.0.1.tar.gz"/>
+ </distutils>
+ <distutils id="pyopenssl">
+ <branch repo="pypi" version="0.13"
+ module="p/pyOpenSSL/pyOpenSSL-0.13.tar.gz"/>
+ </distutils>
+ <distutils id="pyxdg">
+ <branch repo="pypi" version="0.19"
+ module="p/pyxdg/pyxdg-0.19.tar.gz"/>
+ </distutils>
+ <distutils id="py2app">
+ <branch repo="pypi" version="0.6.4"
+ module="p/py2app/py2app-0.6.4.tar.gz"/>
+ </distutils>
+ <distutils id="mako">
+ <branch repo="pypi" version="0.6.2"
+ module="M/Mako/Mako-0.6.2.tar.gz"/>
+ </distutils>
+
+ <repository type="tarball" name="twistedmatrix"
+ href="http://twistedmatrix.com/Releases/"/>
+ <distutils id="twisted">
+ <branch repo="twistedmatrix" version="11.0.0"
+ module="Twisted/11.0/Twisted-11.0.0.tar.bz2"
+ md5sum="d7f94a1609a1b8f3b8c8d0146d4cfe54"/>
+ </distutils>
+ <distutils id="twisted-web">
+ <branch repo="twistedmatrix" version="8.1.0"
+ module="Web2/8.1/TwistedWeb2-8.1.0.tar.bz2"
+ md5sum="e34b48edf6fef075bd41ddbd215aed32"/>
+ </distutils>
+
+ <!--Failed attempt to build universal glib-->
+ <repository type="tarball" name="ftp.gnome.org"
+ href="http://ftp.gnome.org/pub/GNOME/sources/"/>
+ <autotools id="glib2" autogen-sh="configure" autogenargs="--enable-static">
+ <branch module="glib/2.28/glib-2.28.8.tar.bz2" version="2.28.8" repo="ftp.gnome.org"
+ hash="sha256:222f3055d6c413417b50901008c654865e5a311c73f0ae918b0a9978d1f9466f">
+ <patch file="https://trac.macports.org/export/87264/trunk/dports/devel/glib2/files/patch-configure.ac.diff"/>
+ <patch file="https://trac.macports.org/export/87264/trunk/dports/devel/glib2/files/patch-glib-2.0.pc.in.diff"/>
+ <patch file="https://trac.macports.org/export/87264/trunk/dports/devel/glib2/files/patch-glib_gunicollate.c.diff"/>
+ <patch file="https://trac.macports.org/export/87264/trunk/dports/devel/glib2/files/patch-gi18n.h.diff"/>
+ <patch file="https://trac.macports.org/export/87264/trunk/dports/devel/glib2/files/patch-gio_xdgmime_xdgmime.c.diff"/>
+ </branch>
+ <after>
+ <dep package="meta-gtk-osx-bootstrap"/>
+ <dep package="gtk-doc"/>
+ </after>
+ </autotools>
+</moduleset>
+
diff --git a/osx/deluge.sh b/osx/deluge.sh
new file mode 100755
index 000000000..2605f8cbf
--- /dev/null
+++ b/osx/deluge.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+EXEC="exec"
+
+name="`basename $0`"
+if [[ "$0" == `pwd`* ]] || [[ "$0" == "//"* ]]; then
+ full_path="$0"
+else
+ full_path="`pwd`/$0"
+fi
+tmp=`dirname "$full_path"`
+tmp=`dirname "$tmp"`
+bundle=`dirname "$tmp"`
+bundle_contents="$bundle"/Contents
+bundle_macos="$bundle_contents"/MacOS
+bundle_res="$bundle_contents"/Resources
+bundle_lib="$bundle_res"/lib
+bundle_bin="$bundle_res"/bin
+bundle_data="$bundle_res"/share
+bundle_etc="$bundle_res"/etc
+
+export DYLD_LIBRARY_PATH="$bundle_lib"
+export XDG_CONFIG_DIRS="$bundle_etc"/xdg
+export XDG_DATA_DIRS="$bundle_data"
+export GTK_DATA_PREFIX="$bundle_res"
+export GTK_EXE_PREFIX="$bundle_res"
+export GTK_PATH="$bundle_res"
+
+export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc"
+export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules"
+export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders"
+export PANGO_RC_FILE="$bundle_etc/pango/pangorc"
+
+#Set $PYTHON to point inside the bundle
+export PYTHON="$bundle_macos/Deluge-python"
+export PYTHONHOME="$bundle_res"
+#Add the bundle's python modules
+PYTHONPATH="$bundle_lib:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/python/lib-dynload/:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/python/:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/pygtk/2.0:$PYTHONPATH"
+export PYTHONPATH
+
+# We need a UTF-8 locale.
+lang=`defaults read .GlobalPreferences AppleLocale 2>/dev/null`
+if test "$?" != "0"; then
+ lang=`defaults read .GlobalPreferences AppleCollationOrder 2>/dev/null | sed 's/_.*//'`
+fi
+LANG=""
+if test "$lang" != ""; then
+ LANG="`grep \"\`echo $lang\`_\" /usr/share/locale/locale.alias | \
+ tail -n1 | sed 's/\./ /' | awk '{print $2}'`"
+fi
+if test "$LANG" == ""; then
+ export LANG="C"
+else
+ export LANG="$LANG.utf8"
+fi
+
+if test -f "$bundle_lib/charset.alias"; then
+ export CHARSETALIASDIR="$bundle_lib"
+fi
+
+# Extra arguments can be added in environment.sh.
+EXTRA_ARGS=
+if test -f "$bundle_res/environment.sh"; then
+ source "$bundle_res/environment.sh"
+fi
+
+# Strip out the argument added by the OS.
+if [ "x`echo "x$1" | sed -e "s/^x-psn_.*//"`" == "x" ]; then
+ shift 1
+fi
+
+#Note that we're calling $PYTHON here to override the version in
+#pygtk-demo's shebang.
+$EXEC "$PYTHON" "$bundle_contents/MacOS/Deluge-bin" "$@" #-l ~/.config/deluge/app.log -L debug
diff --git a/osx/deluged.sh b/osx/deluged.sh
new file mode 100755
index 000000000..e916b7387
--- /dev/null
+++ b/osx/deluged.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+EXEC="exec"
+
+name="`basename $0`"
+if [[ "$0" == `pwd`* ]] || [[ "$0" == "//"* ]]; then
+ full_path="$0"
+else
+ full_path="`pwd`/$0"
+fi
+tmp=`dirname "$full_path"`
+tmp=`dirname "$tmp"`
+bundle=`dirname "$tmp"`
+bundle_contents="$bundle"/Contents
+bundle_macos="$bundle_contents"/MacOS
+bundle_res="$bundle_contents"/Resources
+bundle_lib="$bundle_res"/lib
+bundle_bin="$bundle_res"/bin
+bundle_data="$bundle_res"/share
+bundle_etc="$bundle_res"/etc
+
+export DYLD_LIBRARY_PATH="$bundle_lib"
+export XDG_CONFIG_DIRS="$bundle_etc"/xdg
+export XDG_DATA_DIRS="$bundle_data"
+
+#Set $PYTHON to point inside the bundle
+export PYTHON="$bundle_macos/Deluge-python"
+export PYTHONHOME="$bundle_res"
+#Add the bundle's python modules
+PYTHONPATH="$bundle_lib:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/python/lib-dynload/:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/python/:$PYTHONPATH"
+PYTHONPATH="$bundle_lib/pygtk/2.0:$PYTHONPATH"
+export PYTHONPATH
+
+# We need a UTF-8 locale.
+lang=`defaults read .GlobalPreferences AppleLocale 2>/dev/null`
+if test "$?" != "0"; then
+ lang=`defaults read .GlobalPreferences AppleCollationOrder 2>/dev/null | sed 's/_.*//'`
+fi
+LANG=""
+if test "$lang" != ""; then
+ LANG="`grep \"\`echo $lang\`_\" /usr/share/locale/locale.alias | \
+ tail -n1 | sed 's/\./ /' | awk '{print $2}'`"
+fi
+if test "$LANG" == ""; then
+ export LANG="C"
+else
+ export LANG="$LANG.utf8"
+fi
+
+if test -f "$bundle_lib/charset.alias"; then
+ export CHARSETALIASDIR="$bundle_lib"
+fi
+
+# Extra arguments can be added in environment.sh.
+EXTRA_ARGS=
+if test -f "$bundle_res/environment.sh"; then
+ source "$bundle_res/environment.sh"
+fi
+
+# Strip out the argument added by the OS.
+if [ "x`echo "x$1" | sed -e "s/^x-psn_.*//"`" == "x" ]; then
+ shift 1
+fi
+
+#Note that we're calling $PYTHON here to override the version in
+#pygtk-demo's shebang.
+$EXEC "$PYTHON" "$bundle_contents/MacOS/deluged-bin" "$@" #-l ~/.config/deluge/deluged.log -L debug
diff --git a/osx/gtkrc b/osx/gtkrc
new file mode 100644
index 000000000..c9b0a50b3
--- /dev/null
+++ b/osx/gtkrc
@@ -0,0 +1,10 @@
+gtk-theme-name = "Clearlooks"
+gtk-enable-mnemonics = 0
+
+# Workaround for non-ascii display issue details
+# here: http://bugs.gramps-project.org/view.php?id=5474
+style "user-font"
+{
+ font_name="Arial Unicode MS"
+}
+widget_class "*" style "user-font"
diff --git a/osx/jhbuildrc-custom b/osx/jhbuildrc-custom
new file mode 100644
index 000000000..73541f4ae
--- /dev/null
+++ b/osx/jhbuildrc-custom
@@ -0,0 +1,28 @@
+# -*- mode: python -*-
+
+prefix = "/opt/gtk"
+checkoutroot = os.path.expanduser("~/Source/gtk")
+
+#setup_sdk(target="10.6", sdk_version="10.6", architectures=["i386", "x86_64"])
+setup_sdk(target="10.6", sdk_version="10.6", architectures=["x86_64"])
+#setup_sdk(target="10.6", sdk_version="10.6", architectures=["i386"]) # fails with libtorrent...
+#setup_universal_build(target="10.6", sdk_version="10.6", architectures=["i386", "x86_64"]) # fails with glib2...
+os.environ["CC"] = "/usr/bin/gcc"
+os.environ["CXX"] = "/usr/bin/g++"
+
+_gtk_osx_use_jhbuild_python = True
+
+skip.append("libiconv") # Lion issues
+modules = [
+ "python",
+ "meta-gtk-osx-bootstrap",
+ "meta-gtk-osx-core",
+ "librsvg", "libglade",
+ "meta-gtk-osx-python",
+ "meta-gtk-osx-themes",
+ "gtk-quartz-engine",
+]
+
+# Can be usefull when tweaking modulesets to avoid jhbuild overwriting:
+#nonetwork=True
+
diff --git a/osx/make-app.sh b/osx/make-app.sh
new file mode 100755
index 000000000..297842b5c
--- /dev/null
+++ b/osx/make-app.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+APPDIR="./app/Deluge.app"
+RSCDIR="${APPDIR}/Contents/Resources"
+LIBDIR="${RSCDIR}/lib"
+
+function msg() { echo "==> $1"; }
+
+echo "*** Packaging Deluge.app to $APPDIR..."
+
+msg "Clearing app dir"
+rm -fr $APPDIR
+
+msg "Fixing permissions on file we will need to relocate"
+if [ ! -z "${JHBUILD_PREFIX}" ]; then
+ chmod 755 "${JHBUILD_PREFIX}/lib/"libpython*.dylib
+ chmod 755 "${JHBUILD_PREFIX}/lib/"libssl*.dylib
+ chmod 755 "${JHBUILD_PREFIX}/lib/"libcrypto*.dylib
+fi
+
+chmod 755 deluge*.sh
+
+msg "Calling gtk-mac-bundler"
+gtk-mac-bundler deluge.bundle
+
+msg "Unzip site-packages and make python softlink without version number"
+pushd ${LIBDIR} || exit 1
+ln -sf python* python
+cd python
+unzip -nq site-packages.zip
+rm site-packages.zip
+popd
+
+msg "Replacing deluge by its egg..."
+rm -fr ${LIBDIR}/python/deluge
+rsync -rpl $JHBUILD_PREFIX/lib/python2.7/site-packages/deluge-*.egg "${LIBDIR}/python/"
+
+msg "Clean unnecessary files"
+find $APPDIR -name "*.la" -exec rm -f {} \; # Should not be packaged
+find $APPDIR -name "*.pyo" -exec rm -f {} \; # Just duplicates
+rm -fr $LIBDIR/pygtk/2.0/*demo*
+
+echo "*** Packaging done:`du -hs $APPDIR | cut -f 1`"
+
diff --git a/osx/torrent.icns b/osx/torrent.icns
new file mode 100644
index 000000000..a6f9040f2
--- /dev/null
+++ b/osx/torrent.icns
Binary files differ
diff --git a/setup.cfg b/setup.cfg
index 2b5e37b35..92288bc77 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -6,3 +6,14 @@ tag_svn_revision = false
source-dir = docs/source
build-dir = docs/build
all_files = 1
+
+[py2app]
+app = ['deluge/main.py']
+arch = x86_64
+#arch = i386
+iconfile = osx/deluge.icns
+site-packages = false
+includes = glib,gio,cairo,pango,pangocairo,atk,gobject,gtk.keysyms,
+ twisted.internet,twisted.internet.utils,twisted.protocols,
+ zope.interface,mako.cache,email.mime,libtorrent
+frameworks = CoreFoundation,Foundation,AppKit