update wine to wine-1.1.19
[sugaredwine.git] / wineactivity.py
blob4b64d2815f3f4ff9ddfa1480e8f46dc6dd47d460
1 # Copyright (C) 2008, Vincent Povirk for CodeWeavers
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2 of the License, or (at your option) any later version.
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the
15 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 # Boston, MA 02111-1307, USA.
18 from sugar.activity import activity
19 import sys
20 import os
21 import gobject
22 import gtk
23 import shutil
24 import tempfile
25 import logging
26 import atexit
28 class WineActivity(activity.Activity):
29 def __init__(self, handle):
30 activity.Activity.__init__(self, handle)
32 self.bundle_path = activity.get_bundle_path()
34 try:
35 activity_root = activity.get_activity_root()
36 wine_prefix = os.path.join(activity_root, 'data', 'wine')
37 except AttributeError:
38 try:
39 activity_root = os.environ['SUGAR_ACTIVITY_ROOT']
40 wine_prefix = os.path.join(activity_root, 'data', 'wine')
41 except KeyError:
42 activity_root = None
43 wine_prefix = os.path.expanduser('~/.wine')
45 self.settings = {}
46 f = open(os.path.join(self.bundle_path, 'activity', 'wine.info'), 'U')
47 for line in f.readlines():
48 if '=' in line:
49 key, value = line.rstrip('\n').split('=')
50 self.settings[key] = value
51 f.close()
53 try:
54 self.desktop_parent = gtk.EventBox()
55 self.desktop_parent.show()
56 self.set_canvas(self.desktop_parent)
57 except AttributeError:
58 # remove any children of the window that Sugar may have added
59 for widget in self.get_children():
60 self.remove(widget)
62 self.desktop_parent = self
64 os.environ['LD_LIBRARY_PATH'] = "%s:%s" % (os.path.join(self.bundle_path, 'lib'), os.environ.get('LD_LIBRARY_PATH', ''))
65 os.environ['PATH'] = "%s:%s" % (os.path.join(self.bundle_path, 'bin'), os.environ.get('PATH', ''))
66 os.environ['WINEPREFIX'] = wine_prefix
67 os.environ['WINELOADER'] = os.path.join(self.bundle_path, 'bin/wine')
68 os.environ['WINESERVER'] = os.path.join(self.bundle_path, 'bin/wineserver')
69 os.environ['WINEDLLPATH'] = os.path.join(self.bundle_path, 'lib/wine')
71 self.desktop_name = str(os.getpid())
72 os.environ['WINE_DESKTOP_NAME'] = self.desktop_name
74 firstrun = not os.path.exists(wine_prefix)
76 self.setup_prefix(firstrun)
78 self.desktop_parent.connect('map', self.on_parent_map)
80 self.wine_pid = None
82 self.to_run = []
83 self.tempfiles = []
85 self.set_title("Wine")
87 def on_parent_map(self, widget):
88 os.environ['WINE_DESKTOP_PARENT'] = str(self.desktop_parent.window.xid)
89 os.environ['SUGARED_WINE_TOPLEVEL'] = str(self.window.xid)
91 gtk.gdk.flush()
93 os.chdir(self.get_unix_path('c:\\'))
95 width = gtk.gdk.screen_width()
96 height = gtk.gdk.screen_height()
98 cmdline = ('wine', 'explorer', '/desktop=%s,%sx%s' % (self.desktop_name, width, height))
99 try:
100 args = self.settings['exec'].split(' ')
101 except KeyError:
102 pass
103 else:
104 cmdline += ('start', '/unix')
105 cmdline += (os.path.join(self.bundle_path, args[0]),)
106 cmdline += tuple(args[1:])
108 self.wine_pid, stdin, stdout, stderr = gobject.spawn_async(cmdline,
109 flags=gobject.SPAWN_SEARCH_PATH|gobject.SPAWN_DO_NOT_REAP_CHILD)
110 gobject.child_watch_add(self.wine_pid, self.on_wine_quit, None)
112 for cmdline in self.to_run:
113 self.start_wine(*cmdline)
115 def start_wine(self, *args):
116 if self.wine_pid:
117 logging.info("running command line: %s" % ' '.join(str(x) for x in args))
118 gobject.spawn_async(
119 ['wine', 'explorer', '/desktop=%s' % self.desktop_name] + [str(x) for x in args],
120 flags=gobject.SPAWN_SEARCH_PATH)
121 else:
122 self.to_run.append(args)
124 def run_cmd(self, *args):
125 pid, stdin, stdout, stderr = gobject.spawn_async(
126 args,
127 flags=gobject.SPAWN_SEARCH_PATH,
128 standard_output=True)
130 result = []
131 s = os.read(stdout, 4096)
132 while s:
133 result.append(s)
134 s = os.read(stdout, 4096)
136 result = ''.join(result)
138 return result
140 def get_unix_path(self, windowspath):
141 return self.run_cmd('winepath', '--unix', windowspath).rstrip('\n')
143 def setup_prefix(self, firstrun):
144 try:
145 f = open(os.path.join(os.environ['WINEPREFIX'], '.update-timestamp'), 'r')
146 try:
147 timestamp = int(f.read().strip())
148 finally:
149 f.close()
151 expected_timestamp = os.stat(os.path.join(self.bundle_path, 'share/wine/wine.inf')).st_mtime
152 if timestamp == expected_timestamp:
153 #no update needed
154 return
155 except IOError:
156 pass
158 try:
159 self.run_cmd('wine', 'start', '/unix', os.path.join(self.bundle_path, self.settings['init']))
160 except KeyError:
161 self.run_cmd('wineboot', '--update')
163 self.run_cmd('wineserver', '-w')
165 if firstrun:
166 try:
167 background_file = os.path.join(self.bundle_path, self.settings['background'])
168 except KeyError:
169 pass
170 else:
171 #set up desktop background
172 winini = self.get_unix_path(r'c:\windows\win.ini')
174 f = open(winini, 'w')
175 f.write("\r\n\r\n[desktop]\r\nWallPaper=c:\\windows\\background.bmp")
176 f.close()
178 landscapebmp = self.get_unix_path(r'c:\windows\background.bmp')
179 os.symlink(background_file, landscapebmp)
181 def on_wine_quit(self, pid, condition, data):
182 sys.exit()
184 def read_file(self, file_path):
185 #the file is read-only and will be deleted so make a copy
186 import filenames
187 fd, filename = filenames.create_dsobject_file(self.metadata)
188 os.chmod(filename, int('0770', 8))
189 shutil.copyfile(file_path, filename)
190 os.close(fd)
191 atexit.register(os.unlink, filename)
192 self.start_wine('start', '/unix', filename)