~ubuntu-branches/ubuntu/natty/miro/natty

« back to all changes in this revision

Viewing changes to windows/setup.py

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2011-01-22 02:46:33 UTC
  • mfrom: (1.4.10 upstream) (1.7.5 experimental)
  • Revision ID: james.westby@ubuntu.com-20110122024633-kjme8u93y2il5nmf
Tags: 3.5.1-1ubuntu1
* Merge from debian.  Remaining ubuntu changes:
  - Use python 2.7 instead of python 2.6
  - Relax dependency on python-dbus to >= 0.83.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Miro - an RSS based video player application
 
2
# Copyright (C) 2005-2010 Participatory Culture Foundation
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
17
#
 
18
# In addition, as a special exception, the copyright holders give
 
19
# permission to link the code of portions of this program with the OpenSSL
 
20
# library.
 
21
#
 
22
# You must obey the GNU General Public License in all respects for all of
 
23
# the code used other than OpenSSL. If you modify file(s) with this
 
24
# exception, you may extend this exception to your version of the file(s),
 
25
# but you are not obligated to do so. If you do not wish to do so, delete
 
26
# this exception statement from your version. If you delete this exception
 
27
# statement from all source files in the program, then also delete it here.
 
28
 
 
29
import os.path
 
30
import os
 
31
import shutil
 
32
import time
 
33
import socket
 
34
import copy
 
35
import sys
 
36
import string
 
37
import subprocess
 
38
import zipfile as zip
 
39
from glob import glob, iglob
 
40
from xml.sax.saxutils import escape
 
41
from distutils import sysconfig 
 
42
from distutils.core import Command
 
43
import distutils.command.install_data
 
44
from distutils.ccompiler import new_compiler
 
45
from distutils import file_util, dir_util
 
46
 
 
47
 
 
48
###############################################################################
 
49
## Paths and configuration                                                   ##
 
50
###############################################################################
 
51
 
 
52
# The location of the NSIS compiler
 
53
NSIS_PATH = 'C:\\Program Files\\NSIS\\makensis.exe'
 
54
 
 
55
# This is the version of the binary kit to use
 
56
BINARY_KIT_VERSION = open("binary_kit_version").read().strip()
 
57
 
 
58
# If you're using the prebuilt DTV Dependencies Binary Kit, just set
 
59
# the path to it here, and ignore everything after this point. In
 
60
# fact, if you unpacked or checked out the binary kit in the same
 
61
# directory as DTV itself, the default value here will work.
 
62
#
 
63
# Otherwise, if you build the dependencies yourself instead of using
 
64
# the Binary Kit, ignore this setting and change all of the settings
 
65
# below.
 
66
BINARY_KIT_ROOT = "miro-binary-kit-win-%s" % BINARY_KIT_VERSION
 
67
 
 
68
if not os.path.exists or not os.path.isdir(BINARY_KIT_ROOT):
 
69
    print "Binary kit %s is missing.  Run 'setup_binarykit.sh'." % BINARY_KIT_ROOT
 
70
    sys.exit()
 
71
 
 
72
ZLIB_INCLUDE_PATH = os.path.join(BINARY_KIT_ROOT, 'zlib', 'include')
 
73
ZLIB_LIB_PATH = os.path.join(BINARY_KIT_ROOT, 'zlib', 'lib')
 
74
ZLIB_RUNTIME_LIBRARY_PATH = os.path.join(BINARY_KIT_ROOT, 'zlib')
 
75
 
 
76
OPENSSL_INCLUDE_PATH = os.path.join(BINARY_KIT_ROOT, 'openssl', 'include')
 
77
OPENSSL_LIB_PATH = os.path.join(BINARY_KIT_ROOT, 'openssl', 'lib')
 
78
OPENSSL_LIBRARIES = ['ssleay32', 'libeay32']
 
79
 
 
80
# GTK_ROOT_PATH = os.path.join(BINARY_KIT_ROOT, 'gtk+-bundle_2.20.0-20100406_win32')
 
81
GTK_ROOT_PATH = os.path.join(BINARY_KIT_ROOT, 'gtk+-bundle_2.16.6-20091215_win32')
 
82
GTK_INCLUDE_PATH = os.path.join(GTK_ROOT_PATH, 'include')
 
83
GTK_LIB_PATH = os.path.join(GTK_ROOT_PATH, 'lib')
 
84
GTK_BIN_PATH = os.path.join(GTK_ROOT_PATH, 'bin')
 
85
GTK_INCLUDE_DIRS = [
 
86
    os.path.join(GTK_INCLUDE_PATH, 'atk-1.0'),
 
87
    os.path.join(GTK_INCLUDE_PATH, 'gtk-2.0'),
 
88
    os.path.join(GTK_INCLUDE_PATH, 'glib-2.0'),
 
89
    os.path.join(GTK_INCLUDE_PATH, 'pango-1.0'),
 
90
    os.path.join(GTK_INCLUDE_PATH, 'cairo'),
 
91
    os.path.join(GTK_LIB_PATH, 'glib-2.0', 'include'),
 
92
    os.path.join(GTK_LIB_PATH, 'gtk-2.0', 'include'),
 
93
]
 
94
 
 
95
PYGOBJECT_INCLUDE_DIR = os.path.join(BINARY_KIT_ROOT, 'pygobject')
 
96
 
 
97
# path to the Mozilla "xulrunner-sdk" distribution.
 
98
XULRUNNER_SDK_PATH = os.path.join(BINARY_KIT_ROOT, 'xulrunner-sdk')
 
99
XULRUNNER_SDK_BIN_PATH = os.path.join(XULRUNNER_SDK_PATH, 'bin')
 
100
 
 
101
VLC_PATH = os.path.join(BINARY_KIT_ROOT, 'libvlc')
 
102
LIBTORRENT_PATH = os.path.join(BINARY_KIT_ROOT, 'libtorrent')
 
103
 
 
104
FFMPEG_PATH = os.path.join(
 
105
    BINARY_KIT_ROOT, 'ffmpeg', 'ffmpeg-r25766-swscale-r32562-mingw32-static')
 
106
FFMPEG2THEORA_PATH = os.path.join(BINARY_KIT_ROOT, 'ffmpeg2theora')
 
107
 
 
108
VCREDIST90_PATH = os.path.join(BINARY_KIT_ROOT, 'vc90redist')
 
109
 
 
110
def find_data_files(dest_path_base, source_path):
 
111
    retval = []
 
112
    for path, dirs, files in os.walk(source_path):
 
113
        if not path.startswith(source_path):
 
114
            raise AssertionError()
 
115
        dest_path = path.replace(source_path, dest_path_base)
 
116
        source_files = [os.path.join(path, f) for f in files]
 
117
        retval.append((dest_path, source_files))
 
118
        if '.svn' in dirs:
 
119
            dirs.remove('.svn')
 
120
    return retval
 
121
 
 
122
# Name of python binary, so we can build the download daemon in
 
123
# another process. (Can we get this from Python itself?)
 
124
PYTHON_BINARY = "python"
 
125
 
 
126
###############################################################################
 
127
## End of configuration. No user-servicable parts inside                     ##
 
128
###############################################################################
 
129
 
 
130
from distutils.core import setup
 
131
from distutils.extension import Extension
 
132
from distutils.core import Command
 
133
from distutils import log
 
134
import py2exe
 
135
import py2exe.build_exe
 
136
import os
 
137
import sys
 
138
import re
 
139
from Pyrex.Distutils import build_ext
 
140
 
 
141
# The name of this platform.
 
142
platform = 'windows'
 
143
 
 
144
# Find the top of the source tree and set search path
 
145
root_dir = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), '..')
 
146
root_dir = os.path.normpath(os.path.abspath(root_dir))
 
147
platform_dir = os.path.join(root_dir, 'windows')
 
148
platform_package_dir = os.path.join(platform_dir, 'plat')
 
149
widgets_dir = os.path.join(platform_package_dir, 'frontends', 'widgets')
 
150
portable_dir = os.path.join(root_dir, 'lib')
 
151
portable_widgets_dir = os.path.join(portable_dir, 'frontends', 'widgets')
 
152
portable_xpcom_dir = os.path.join(portable_widgets_dir, 'gtk', 'xpcom')
 
153
test_dir = os.path.join(root_dir, 'resources')
 
154
resources_dir = os.path.join(root_dir, 'resources')
 
155
 
 
156
sys.path.insert(0, root_dir)
 
157
# when we install the portable modules, they will be in the miro
 
158
# package, but at this point, they are in a package named "lib",
 
159
# so let's hack it
 
160
import lib
 
161
sys.modules['miro'] = lib
 
162
 
 
163
from miro import util
 
164
 
 
165
# put the libtorrent extension on the path, so py2exe can find the
 
166
# .pyd file
 
167
sys.path.insert(0, LIBTORRENT_PATH)
 
168
 
 
169
#### Extensions ####
 
170
 
 
171
pygtkhacks_ext = Extension(
 
172
    "miro.frontends.widgets.gtk.pygtkhacks",
 
173
    sources=[
 
174
        os.path.join(portable_widgets_dir, 'gtk', 'pygtkhacks.pyx'),
 
175
        ],
 
176
    include_dirs=GTK_INCLUDE_DIRS + [PYGOBJECT_INCLUDE_DIR],
 
177
    library_dirs=[GTK_LIB_PATH],
 
178
    libraries=[
 
179
        'gtk-win32-2.0',
 
180
        ]
 
181
    )
 
182
 
 
183
xulrunnerbrowser_ext_dir = os.path.join(widgets_dir, 'XULRunnerBrowser')
 
184
xulrunnerbrowser_ext = Extension(
 
185
    "miro.plat.frontends.widgets.xulrunnerbrowser",
 
186
    include_dirs=[
 
187
        os.path.join(XULRUNNER_SDK_PATH, 'sdk', 'include'),
 
188
        os.path.join(XULRUNNER_SDK_PATH, 'include'),
 
189
        os.path.join(XULRUNNER_SDK_PATH, 'include', 'xpcom'),
 
190
        portable_xpcom_dir,
 
191
        ] + GTK_INCLUDE_DIRS,
 
192
    define_macros=[
 
193
        ("XP_WIN", 1), 
 
194
        ("XPCOM_GLUE", 1),
 
195
        ("PCF_USING_XULRUNNER19", 1),
 
196
        ],
 
197
    extra_compile_args=[
 
198
        "/Zc:wchar_t-"
 
199
        ],
 
200
    library_dirs=[
 
201
        os.path.join(XULRUNNER_SDK_PATH, 'lib'),
 
202
        GTK_LIB_PATH,
 
203
        ],
 
204
    libraries=[
 
205
        'xpcomglue',
 
206
        'xul',
 
207
        'user32',
 
208
        'gdk-win32-2.0',
 
209
        'gtk-win32-2.0',
 
210
        ],
 
211
    language="c++",
 
212
    sources=[
 
213
        os.path.join(xulrunnerbrowser_ext_dir, 'xulrunnerbrowser.pyx'),
 
214
        os.path.join(portable_xpcom_dir, 'HttpObserver.cc'),
 
215
        os.path.join(xulrunnerbrowser_ext_dir, 'MiroBrowserEmbed.cpp'),
 
216
        os.path.join(xulrunnerbrowser_ext_dir, 'MiroWindowCreator.cpp'),
 
217
        os.path.join(xulrunnerbrowser_ext_dir, 'FixFocus.cpp'),
 
218
        os.path.join(xulrunnerbrowser_ext_dir, 'Init.cpp'),
 
219
        ]
 
220
    )
 
221
 
 
222
# Setting the path here allows py2exe to find the DLLS
 
223
os.environ['PATH'] = ';'.join([
 
224
        OPENSSL_LIB_PATH, ZLIB_RUNTIME_LIBRARY_PATH, 
 
225
        LIBTORRENT_PATH, GTK_BIN_PATH, os.environ['PATH']])
 
226
 
 
227
# Private extension modules to build.
 
228
ext_modules = [
 
229
    pygtkhacks_ext,
 
230
    xulrunnerbrowser_ext,
 
231
]
 
232
 
 
233
def fill_template(templatepath, outpath, **vars):
 
234
    s = open(templatepath, 'rt').read()
 
235
    s = string.Template(s).safe_substitute(**vars)
 
236
    f = open(outpath, "wt")
 
237
    f.write(s)
 
238
    f.close()
 
239
 
 
240
# Data files
 
241
data_files = []
 
242
data_files.extend(find_data_files('xulrunner', XULRUNNER_SDK_BIN_PATH))
 
243
 
 
244
image_loader_path = os.path.join('lib', 'gtk-2.0', '2.10.0', 'loaders')
 
245
theme_engine_path = os.path.join('lib', 'gtk-2.0', '2.10.0', 'engines')
 
246
theme_path = os.path.join('share', 'themes')
 
247
for path in (image_loader_path, theme_engine_path, theme_path):
 
248
    src_path = os.path.join(GTK_ROOT_PATH, path)
 
249
    data_files.extend(find_data_files(path, src_path))
 
250
 
 
251
data_files.append(('', iglob(os.path.join(GTK_BIN_PATH, '*.dll'))))
 
252
data_files.extend(find_data_files(
 
253
        'vlc-plugins', os.path.join(VLC_PATH, 'vlc-plugins')))
 
254
data_files.append(('', [os.path.join(VLC_PATH, 'libvlc.dll')]))
 
255
data_files.append(('', [os.path.join(VLC_PATH, 'libvlccore.dll')]))
 
256
data_files.append(('', [os.path.join(LIBTORRENT_PATH, 'libtorrent.pyd')]))
 
257
data_files.append(('', [
 
258
            os.path.join(FFMPEG_PATH, 'bin', 'ffmpeg.exe'),
 
259
            os.path.join(FFMPEG2THEORA_PATH, 'bin', 'ffmpeg2theora.exe')]))
 
260
data_files.append(('', glob(os.path.join(FFMPEG_PATH, 'presets', '*.ffpreset'))))
 
261
data_files.extend(find_data_files('Microsoft.VC90.CRT',
 
262
    os.path.join(VCREDIST90_PATH, 'Microsoft.VC90.CRT')))
 
263
 
 
264
# handle the resources subdirectories.
 
265
for dir in ('searchengines', 'images', 'conversions'):
 
266
    dest_dir = os.path.join('resources', dir)
 
267
    source_dir = os.path.join(resources_dir, dir)
 
268
    data_files.extend(find_data_files(dest_dir, source_dir))
 
269
 
 
270
data_files.append(('resources', [os.path.join(root_dir, 'ADOPTERS')]))
 
271
data_files.append(('resources', [os.path.join(root_dir, 'CREDITS')]))
 
272
 
 
273
locale_temp_dir = os.path.join(os.path.dirname(__file__), "build", "locale")
 
274
 
 
275
def copy_locale_files():
 
276
    print "*** copying locale files ***"
 
277
    # handle locale files
 
278
    locale_files = []
 
279
    for source in glob(os.path.join(resources_dir, "locale", "*.mo")):
 
280
        lang = os.path.basename(source)[:-3]
 
281
        dest = os.path.join(locale_temp_dir, lang, "LC_MESSAGES", "miro.mo")
 
282
        locale_files.append((source, dest))
 
283
 
 
284
    dir_util.create_tree(os.path.dirname(__file__),
 
285
                         [dst for src, dst in locale_files])
 
286
 
 
287
    for source, dest in locale_files:
 
288
        file_util.copy_file(source, dest, update=True, verbose=True)
 
289
 
 
290
# FIXME - this should be done inside a build command
 
291
copy_locale_files()
 
292
data_files.extend(find_data_files(os.path.join("resources", "locale"),
 
293
                                  locale_temp_dir))
 
294
 
 
295
app_config = os.path.join(resources_dir, 'app.config.template')
 
296
template_vars = util.read_simple_config_file(app_config)
 
297
 
 
298
# pixmap for the about dialog
 
299
icon_path = os.path.join("icons", "hicolor", "128x128", "apps")
 
300
data_files.append((os.path.join("resources", icon_path), 
 
301
                   [os.path.join(platform_dir, icon_path, "miro.png")]))
 
302
 
 
303
###########################################################################
 
304
 
 
305
#### Our specialized install_data command ####
 
306
class install_data(distutils.command.install_data.install_data):
 
307
    """install_data extends to default implementation so that it
 
308
    automatically installs app.config from app.config.template.
 
309
    """
 
310
 
 
311
    def install_app_config(self):
 
312
        template = os.path.join(resources_dir, 'app.config.template')
 
313
        dest = os.path.join(self.install_dir, 'resources', 'app.config')
 
314
        revision = util.query_revision()
 
315
        if revision is None:
 
316
            revision = "unknown"
 
317
            revisionurl = "unknown"
 
318
            revisionnum = "unknown"
 
319
        else:
 
320
            revisionurl = revision[0]
 
321
            revisionnum = revision[1]
 
322
            revision = "%s - %s" % revision
 
323
 
 
324
        print "Using %s" % revisionnum
 
325
 
 
326
        self.mkpath(os.path.dirname(dest))
 
327
        # We don't use the dist utils copy_file() because it only
 
328
        # copies the file if the timestamp is newer
 
329
        fill_template(template, dest,
 
330
            APP_REVISION=revision,
 
331
            APP_REVISION_NUM=revisionnum,
 
332
            APP_REVISION_URL=revisionurl,
 
333
            APP_PLATFORM='windows',
 
334
            BUILD_MACHINE="%s@%s" % (os.environ['username'],
 
335
                socket.gethostname()),
 
336
            BUILD_TIME=str(time.time()))
 
337
        self.outfiles.append(dest)
 
338
 
 
339
    def install_gdk_pixbuf_loaders(self):
 
340
        basename = os.path.join('etc', 'gtk-2.0', 'gdk-pixbuf.loaders')
 
341
        source = os.path.join(GTK_ROOT_PATH, basename)
 
342
        dest = os.path.join(self.install_dir, basename)
 
343
        contents = open(source).read()
 
344
        # Not sure why they have paths like this in the file, but we
 
345
        # need to change them.
 
346
        contents = contents.replace(
 
347
            "c:/devel/target/9c384abfa28a3e070eb60fc2972f823b/", "")
 
348
        self.mkpath(os.path.dirname(dest))
 
349
        open(dest, 'wt').write(contents)
 
350
        self.outfiles.append(dest)
 
351
 
 
352
    def run(self):
 
353
        distutils.command.install_data.install_data.run(self)
 
354
        self.install_app_config()
 
355
        self.install_gdk_pixbuf_loaders()
 
356
 
 
357
# We want to make sure we include msvcp90.dll in the dist directory.
 
358
# Recipe taken from
 
359
# http://www.py2exe.org/index.cgi/OverridingCriteraForIncludingDlls
 
360
DLLS_TO_INCLUDE = [
 
361
    'msvcp90.dll',
 
362
]
 
363
origIsSystemDLL = py2exe.build_exe.isSystemDLL
 
364
def isSystemDLL(pathname):
 
365
    if os.path.basename(pathname).lower() in DLLS_TO_INCLUDE:
 
366
        return True
 
367
    else:
 
368
        return origIsSystemDLL(pathname)
 
369
py2exe.build_exe.isSystemDLL = isSystemDLL
 
370
 
 
371
class bdist_miro(Command):
 
372
    description = "Build Miro"
 
373
 
 
374
    user_options = []
 
375
 
 
376
    def initialize_options(self):
 
377
        pass
 
378
 
 
379
    def finalize_options(self):
 
380
        pass
 
381
 
 
382
    def run(self):
 
383
        self.run_command('py2exe')
 
384
        self.copy_ico()
 
385
 
 
386
    def copy_ico(self):
 
387
        dist_dir = self.get_finalized_command('py2exe').dist_dir
 
388
        shortappname = template_vars["shortAppName"]
 
389
        self.copy_file("Miro.ico", 
 
390
                       os.path.join(dist_dir, "%s.ico" % shortappname))
 
391
 
 
392
class bdist_test(Command):
 
393
    description = "Builds Miro with unit tests"
 
394
 
 
395
    user_options = []
 
396
 
 
397
    def initialize_options(self):
 
398
        pass
 
399
 
 
400
    def finalize_options(self):
 
401
        pass
 
402
 
 
403
    def run(self):
 
404
        self.run_command('bdist_miro')
 
405
        self.copy_test_data()
 
406
 
 
407
    def copy_test_data(self):
 
408
        # copy test data over
 
409
        dist_dir = self.get_finalized_command('py2exe').dist_dir
 
410
 
 
411
        self.copy_tree(os.path.join(resources_dir, 'testdata'),
 
412
                       os.path.join(dist_dir, 'resources', 'testdata'))
 
413
 
 
414
class runmiro(Command):
 
415
    description = "build Miro and start it up"
 
416
 
 
417
    user_options = []
 
418
 
 
419
    def initialize_options(self):
 
420
        pass
 
421
 
 
422
    def finalize_options(self):
 
423
        pass
 
424
 
 
425
    def run(self):
 
426
        self.run_command('bdist_miro')
 
427
        olddir = os.getcwd()
 
428
        os.chdir(self.get_finalized_command('py2exe').dist_dir)
 
429
        os.system("%s" % template_vars['shortAppName'])
 
430
        os.chdir(olddir)
 
431
 
 
432
class bdist_nsis(Command):
 
433
    description = "create Miro installer using NSIS"
 
434
 
 
435
    user_options = [
 
436
        ('generic', None, 'Build a generic installer instead of the Miro-branded installer.'),
 
437
        ('nozugo', None, 'Do not include the silent Zugo toolbar installer.'),
 
438
        ('mozilla', None, 'Do not show the toolbar option to international users.'),
 
439
        ('install-icon=', None, 'ICO file to use for the installer.'),
 
440
        ('install-image=', None, 'BMP file to use for the welcome/finish pages.')
 
441
        ]
 
442
 
 
443
    def initialize_options(self):
 
444
        self.generic = False
 
445
        self.nozugo = False
 
446
        self.mozilla = False
 
447
        self.install_icon = None
 
448
        self.install_image = None
 
449
 
 
450
    def finalize_options(self):
 
451
        if self.generic and (self.install_icon or self.install_icon):
 
452
            raise AssertionError("cannot specify install images with "
 
453
                                 "generic installer")
 
454
        if self.generic:
 
455
            self.install_icon = 'miro-installer-generic.ico'
 
456
            self.install_image = 'miro-install-generic.bmp'
 
457
        if self.install_icon is None:
 
458
            self.install_icon = 'miro-installer.ico'
 
459
        if self.install_image is None:
 
460
            self.install_image = 'miro-install-image.bmp'
 
461
 
 
462
    def run(self):
 
463
        self.run_command('bdist_miro')
 
464
        self.dist_dir = self.get_finalized_command('py2exe').dist_dir
 
465
 
 
466
        log.info("building installer")
 
467
 
 
468
        self.copy_file(os.path.join(platform_dir, 'Miro.nsi'), self.dist_dir)
 
469
        if not self.nozugo:
 
470
            self.copy_file(os.path.join(platform_dir, 'zugo-silent.exe'), self.dist_dir)
 
471
        self.copy_file(self.install_icon, self.dist_dir)
 
472
        self.copy_file(self.install_image, self.dist_dir)
 
473
 
 
474
        nsis_vars = {}
 
475
        for our_name, nsis_name in [('appVersion', 'CONFIG_VERSION'),
 
476
                                    ('projectURL', 'CONFIG_PROJECT_URL'),
 
477
                                    ('shortAppName', 'CONFIG_SHORT_APP_NAME'),
 
478
                                    ('longAppName', 'CONFIG_LONG_APP_NAME'),
 
479
                                    ('publisher', 'CONFIG_PUBLISHER')]:
 
480
            nsis_vars[nsis_name] = template_vars[our_name]
 
481
 
 
482
        nsis_vars['CONFIG_EXECUTABLE'] = "%s.exe" % template_vars['shortAppName']
 
483
        nsis_vars['CONFIG_DOWNLOADER_EXECUTABLE'] = "%s_Downloader.exe" % \
 
484
                template_vars['shortAppName']
 
485
        nsis_vars['CONFIG_MOVIE_DATA_EXECUTABLE'] = "%s_MovieData.exe" % \
 
486
                template_vars['shortAppName']
 
487
        nsis_vars['CONFIG_ICON'] = "%s.ico" % template_vars['shortAppName']
 
488
        nsis_vars['CONFIG_PROG_ID'] = template_vars['longAppName'].replace(" ", ".") + ".1"
 
489
        nsis_vars['MIRO_INSTALL_ICON'] = self.install_icon
 
490
        nsis_vars['MIRO_INSTALL_IMAGE'] = self.install_image
 
491
        nsis_vars['CONFIG_BINARY_KIT'] = BINARY_KIT_ROOT
 
492
        if not self.nozugo:
 
493
            nsis_vars['MIROBAR_EXE'] = 'zugo-silent.exe'
 
494
        if self.generic:
 
495
            nsis_vars['GENERIC_INSTALLER'] = '1'
 
496
        if self.mozilla:
 
497
            nsis_vars['MOZILLA_INSTALLER'] = '1'
 
498
 
 
499
        output_file = '%s-%s'
 
500
        # One stage installer
 
501
        if self.generic:
 
502
            output_file = "%s-generic" % output_file
 
503
        if self.nozugo:
 
504
            output_file = "%s-nozugo" % output_file
 
505
        if self.mozilla:
 
506
            output_file = '%s-mozilla' % output_file
 
507
            
 
508
        output_file = (output_file % 
 
509
                       (template_vars['shortAppName'], template_vars['appVersion']))
 
510
        nsis_vars['CONFIG_OUTPUT_FILE'] = '%s.exe' % output_file
 
511
        nsis_vars['CONFIG_TWOSTAGE'] = "No"
 
512
 
 
513
        nsis_args = ["/D%s=%s" % (k, v) for (k, v) in nsis_vars.iteritems()]
 
514
        nsis_args.append(os.path.join(self.dist_dir, "Miro.nsi"))
 
515
 
 
516
        if os.access(output_file, os.F_OK):
 
517
            os.remove(output_file)
 
518
        if subprocess.call([NSIS_PATH] + nsis_args) != 0:
 
519
            print "ERROR creating the 1 stage installer, quitting"
 
520
            return
 
521
 
 
522
        # Two stage installer
 
523
        if self.generic:
 
524
            output_file = '%s-%s-generic-twostage.exe'
 
525
        else:
 
526
            output_file = "%s-%s-twostage.exe"
 
527
        output_file = (output_file % 
 
528
                       (template_vars['shortAppName'], template_vars['appVersion']))
 
529
        nsis_vars['CONFIG_OUTPUT_FILE'] = output_file
 
530
        nsis_vars['CONFIG_TWOSTAGE'] = "Yes"
 
531
        nsis_vars.pop('MIROBAR_EXE', None)
 
532
 
 
533
        nsis_args = ["/D%s=%s" % (k, v) for (k, v) in nsis_vars.iteritems()]
 
534
        nsis_args.append(os.path.join(self.dist_dir, "Miro.nsi"))
 
535
 
 
536
        if os.access(output_file, os.F_OK):
 
537
            os.remove(output_file)
 
538
        subprocess.call([NSIS_PATH] + nsis_args)
 
539
 
 
540
        zip_path = os.path.join(self.dist_dir, "%s-Contents-%s.zip" %
 
541
            (template_vars['shortAppName'], template_vars['appVersion']))
 
542
        self.zipfile = zip.ZipFile(zip_path, 'w', zip.ZIP_DEFLATED)
 
543
        self.add_file(nsis_vars['CONFIG_EXECUTABLE'])
 
544
        self.add_file(nsis_vars['CONFIG_ICON'])
 
545
        self.add_file(nsis_vars['CONFIG_MOVIE_DATA_EXECUTABLE'])
 
546
        self.add_glob("*.dll")
 
547
 
 
548
        self.add_directory("defaults")
 
549
        self.add_directory("resources")
 
550
        self.add_directory("xulrunner")
 
551
 
 
552
        self.zipfile.close()
 
553
 
 
554
    def add_glob(self, wildcard):
 
555
        wildcard = os.path.join(self.dist_dir, wildcard)
 
556
        length = len(self.dist_dir)
 
557
        for filename in iglob(wildcard):
 
558
            if filename[:length] == self.dist_dir:
 
559
                filename = filename[length:]
 
560
                while (len(filename) > 0 
 
561
                       and (filename[0] == '/' or filename[0] == '\\')):
 
562
                    filename = filename[1:]
 
563
            print "Compressing %s" % filename
 
564
            self.zipfile.write(os.path.join(self.dist_dir, filename), filename)
 
565
 
 
566
    def add_file(self, filename):
 
567
        length = len(self.dist_dir)
 
568
        if filename[:length] == self.dist_dir:
 
569
            filename = filename[length:]
 
570
            while (len(filename) > 0 
 
571
                   and (filename[0] == '/' or filename[0] == '\\')):
 
572
                filename = filename[1:]
 
573
        print "Compressing %s" % filename
 
574
        self.zipfile.write(os.path.join(self.dist_dir, filename), filename)
 
575
 
 
576
    def add_directory(self, dirname):
 
577
        for root, dirs, files in os.walk(os.path.join(self.dist_dir, dirname)):
 
578
            for name in files:
 
579
                self.add_file(os.path.join(root, name))
 
580
 
 
581
if __name__ == "__main__":
 
582
    setup(
 
583
        windows=[
 
584
            {
 
585
                'script': 'Miro.py',
 
586
                'dest_base': template_vars['shortAppName'],
 
587
                'icon_resources': [(0, "Miro.ico")],
 
588
                },
 
589
            {
 
590
                'script': 'Miro_Downloader.py',
 
591
                'dest_base': '%s_Downloader' % template_vars['shortAppName'],
 
592
                'icon_resources': [(0, "Miro.ico")],
 
593
                },
 
594
            ],
 
595
        console=[
 
596
            {
 
597
                'script': 'moviedata_util.py',
 
598
                'dest_base': '%s_MovieData' % template_vars['shortAppName'],
 
599
                'icon_resources': [(0, "Miro.ico")],
 
600
                },
 
601
            {
 
602
                'script': 'mirotest.py',
 
603
                'dest_base': 'mirotest',
 
604
                'icon_resources': [(0, "Miro.ico")],
 
605
                }
 
606
            ],
 
607
        ext_modules=ext_modules,
 
608
        packages=[
 
609
            'miro',
 
610
            'miro.dl_daemon',
 
611
            'miro.dl_daemon.private',
 
612
            'miro.frontends',
 
613
            'miro.frontends.widgets',
 
614
            'miro.frontends.widgets.gtk',
 
615
            'miro.test',
 
616
            'miro.plat',
 
617
            'miro.plat.renderers',
 
618
            'miro.plat.frontends',
 
619
            'miro.plat.frontends.widgets',
 
620
            ],
 
621
        package_dir={
 
622
            'miro': portable_dir,
 
623
            'miro.plat': platform_package_dir,
 
624
            },
 
625
        data_files=data_files,
 
626
        cmdclass={
 
627
            'build_ext': build_ext,
 
628
            'install_data': install_data,
 
629
            'bdist_miro': bdist_miro,
 
630
            'bdist_nsis': bdist_nsis,
 
631
            'bdist_test': bdist_test,
 
632
            'runmiro': runmiro,
 
633
            },
 
634
        options={
 
635
            'py2exe': {
 
636
                'packages': [
 
637
                    'encodings',
 
638
                    ],
 
639
                'includes': 'cairo, pango, pangocairo, atk, gobject, gio, libtorrent',
 
640
                },
 
641
            },
 
642
        )