Prepare plugin-meta-data config-dir and files
[ardour.git] / tools / bug_tool / ardour_bugs
1 #! /usr/bin/python
2
3 # By Taybin Rutkin
4 #
5 # TODO
6 # look along $PATH to find binary.
7 # Use ardour binary to get version info
8 # hide file information from reporters
9
10 # standard
11 import os
12 import Queue
13 import re
14 import shutil
15 import string
16 import sys
17 import tempfile
18 import threading
19 import warnings
20
21 # probably installed
22 import pygtk
23 pygtk.require("2.0")
24 import gtk, gnome.ui
25
26 # we provide ClientForm and ClientCookie in $prefix/share/ardour/
27 sys.path.append('/usr/local/share/ardour/')
28 sys.path.append('/opt/local/share/ardour/')
29 sys.path.append('/opt/share/ardour/')
30 sys.path.append('/usr/share/ardour/')
31
32 # probably not installed
33 import ClientForm
34 import ClientCookie
35
36 warnings.filterwarnings('ignore', message="tempnam is a potential security risk to your program")
37 g_name = os.tempnam('/tmp', 'bugrp')
38 os.mkdir(g_name)
39
40 class NoBlock(threading.Thread):
41         def __init__(self, data, queue):
42                 threading.Thread.__init__(self)
43                 self.data = data
44                 self.queue = queue
45
46         def zip(self):
47                 self.queue.put('zipping')
48                 os.system('tar cvfz ' + g_name + '.tar.gz ' + g_name + ' > /dev/null')
49         
50         def login(self):
51                 self.queue.put('logging in')
52                 response = ClientCookie.urlopen('http://ardour.org/mantis/login.php?username=bug_tool&password=bug_tool')
53                 print response
54                 response.close()
55
56         def get_form(self):
57                 self.queue.put('forming data')
58                 response = ClientCookie.urlopen('http://ardour.org/mantis/bug_report_page.php')
59                 print response
60                 forms = ClientForm.ParseResponse(response)
61                 self.form = forms[2]
62                 
63         def upload(self):
64                 self.queue.put('uploading')
65                 self.form.add_file(open(g_name+'.tar.gz'), 'application/x-gzip', 'system-info.tar.gz')
66                 self.form['description'] = self.data['long']
67                 self.form['summary'] = self.data['short']
68                 self.form['custom_field_3'] = self.data['email']
69                 self.form['custom_field_4'] = self.data['name']
70                 request = self.form.click()
71                 response2 = ClientCookie.urlopen(request)
72                 response2.close()
73
74         def run(self):
75                 print "1"
76                 self.zip()
77                 print "2"
78                 self.login()
79                 print "3"
80                 self.get_form()
81                 print "4"
82                 self.upload()
83                 print "5"
84                 self.queue.put('done')
85
86 class ProgressWin(object):
87         def __init__(self, parent_window, no_block, queue):
88                 self.no_block = no_block
89                 self.queue = queue
90
91                 self.win = gtk.Window()
92                 self.win.set_type_hint('dialog')
93                 self.win.set_title('Progress')
94                 self.win.set_resizable(False)
95                 self.win.set_transient_for(parent_window)
96                 
97                 vbox = gtk.VBox()
98                 self.text = gtk.Label('')
99                 self.progress = gtk.ProgressBar()
100                 self.progress.set_pulse_step(0.25)
101                 
102                 vbox.pack_start(self.text)
103                 vbox.pack_start(self.progress)
104                 self.win.add(vbox)
105                 
106                 self.win.show_all()
107
108                 gtk.timeout_add(100, self.check)
109
110         def check(self):
111                 try:
112                         text = self.queue.get_nowait()
113                         print text
114                         if text == 'done':
115                                 gtk.main_quit()
116                         self.text.set_text(text)
117                 except Queue.Empty:
118                         pass
119                 
120                 self.progress.pulse()
121                 return True
122                 
123 class ReportWin(object):
124         def start_page(self):
125                 start = gnome.ui.DruidPageEdge(gnome.ui.EDGE_START)
126                 start.set_text(
127 """So, you want to report a bug in ardour.  Excellent.
128
129 This program will help you to submit a bug report that will be useful to the programmers.
130
131 We are collecting this information so that we don't have to ask you to research very detailed aspects of your system configuration. The information this tool collects is stored in the Ardour bug tracking system, and is not used for any other purpose. We will not intentionally sell or disclose the information to any parties besides those authorized to view it on the Ardour bug tracking system.
132 """)
133                 start.connect('cancel', lambda w, d: gtk.main_quit())
134                 self.druid.append_page(start)
135
136         def end_page_finish(self, page, data):
137                 print "page_finish"
138                 if self.first_time:
139                         self.first_time = False
140                         self.druid.set_buttons_sensitive(False, False, False, False)
141                         print "build queue"
142                         self.queue = Queue.Queue(0)
143                         print "build no_block"
144                         self.no_block = NoBlock(self.data, self.queue)
145                         print "build progress window"
146                         self.progress = ProgressWin(self.win, self.no_block, self.queue)
147                         print "start no block"
148                         self.no_block.start()
149                         print "exit end_page_finish"
150         
151         def end_page(self):
152                 end   = gnome.ui.DruidPageEdge(gnome.ui.EDGE_FINISH)
153                 end.set_text(
154 """Thank you for helping Ardour.
155
156 When you click the "Apply" button, we will connect to the web and upload the information.
157
158 Please let the Bug Tool finish.  It will exit on its own.""")
159                 end.connect('cancel', lambda w, d: gtk.main_quit())
160                 end.connect('finish', self.end_page_finish)
161                 self.druid.append_page(end)
162         
163         def build_tools_page_next(self, page, data):
164                 if self.tools_radio.get_active():
165                         os.system("g++ --version >> " +g_name+"/build-tools")
166                         os.system("pkg-config --version >> " +g_name+"/build-tools")
167                         os.system("autoconf --version >> " +g_name+"/build-tools")
168                         os.system("automake --version >> " +g_name+"/build-tools")
169                         os.system("aclocal --version >> " +g_name+"/build-tools")
170                         os.system("libtool --version >> " +g_name+"/build-tools")
171                         os.system("gettext --version >> " +g_name+"/build-tools")
172                         os.system("autopoint --version >> " +g_name+"/build-tools")
173         
174         def build_tools_page(self):
175                 tools = gnome.ui.DruidPageStandard()
176                 self.tools_radio = gtk.RadioButton(None, "Yes")
177                 radio_btn2 = gtk.RadioButton(self.tools_radio, "No")
178                 radio_btn2.set_active(True)
179                 tools.append_item("Are you using a version of Ardour that you compiled yourself?", self.tools_radio, "")
180                 tools.append_item("", radio_btn2, "")
181                 tools.connect('cancel', lambda w, d: gtk.main_quit())
182                 tools.connect('next', self.build_tools_page_next)
183                 self.druid.append_page(tools)
184         
185         def binary_page_next(self, page, data):
186                 path = self.binary_path.get_text()
187                 if len(path) > 0 and os.path.exists(path):
188                         os.system("ldd "+path+" > "+g_name+"/linker-info")
189         
190         def binary_page(self):
191                 binary = gnome.ui.DruidPageStandard()
192                 self.binary_path = gtk.Entry()
193                 binary.append_item("Where is Ardour's binary located?", self.binary_path, "")
194                 binary.connect('cancel', lambda w, d: gtk.main_quit())
195                 binary.connect('next', self.binary_page_next)
196                 self.druid.append_page(binary)
197         
198         def versions_page_next(self, page, data):
199                 os.system('echo "gtk-ardour version: '+self.gtkardour_version.get_text()+'" >>'+g_name+'/ardour-version')
200                 os.system('echo "libardour version: '+self.libardour_version.get_text()+'" >>'+g_name+'/ardour-version')
201         
202         def versions_page(self):
203                 versions = gnome.ui.DruidPageStandard()
204                 self.gtkardour_version = gtk.Entry()
205                 self.libardour_version = gtk.Entry()
206                 versions.append_item("What is gtk-ardour's version?", self.gtkardour_version, "")
207                 versions.append_item("What is libardour's version?", self.libardour_version, "")
208                 versions.connect('cancel', lambda w, d: gtk.main_quit())
209                 versions.connect('next', self.versions_page_next)
210                 self.druid.append_page(versions)
211         
212         def session_check_toggled(self, data):
213                 self.session_path.set_sensitive(self.session_check.get_active())
214         
215         def sessions_page_next(self, page, data):
216                 session = self.session_path.get_text()
217                 if self.session_check.get_active() and session > 0:
218                         if os.path.exists(session) and os.path.isfile(session):
219                                 shutil.copy(session, g_name)
220         
221         def sessions_page(self):
222                 sessions = gnome.ui.DruidPageStandard()
223                 self.session_check = gtk.CheckButton("Yes")
224                 self.session_check.set_active(True)
225                 self.session_path = gtk.Entry()
226                 sessions.append_item("Is the problem one you've noticed while trying to run Ardour?", self.session_check, "")
227                 sessions.append_item("What is the session file you've been using?", self.session_path, "")
228                 self.session_check.connect('toggled', self.session_check_toggled)
229                 sessions.connect('cancel', lambda w, d:gtk.main_quit())
230                 sessions.connect('next', self.sessions_page_next)
231                 self.druid.append_page(sessions)
232         
233         def description_page_next(self, page, data):
234                 self.data['short'] = self.short_description.get_text()
235                 buffer  = self.long_description.get_buffer()
236                 self.data['long'] = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())
237         
238         def description_page(self):
239                 description = gnome.ui.DruidPageStandard()
240                 self.long_description = gtk.TextView()
241                 self.short_description = gtk.Entry()
242                 self.long_description.set_size_request(-1, 70)
243                 description.append_item(
244 """OK, we've collected the system information. Now its time for you
245 to explain the problem.
246
247 Please note: you do not need to include any information about versions
248 of any software - that has been taken care of.
249
250 If you are reporting an operational problem, please carefully describe
251 the actions you took, any messages that you noticed, and in as much
252 detail as possible describe what went wrong.""", self.long_description, "")
253                 description.append_item("Please give a one line summary of your problem", self.short_description, "")
254                 description.connect('cancel', lambda w, d:gtk.main_quit())
255                 description.connect('next', self.description_page_next)
256                 self.druid.append_page(description)
257         
258         def info_page_next(self, page, data):
259                 self.data['name'] = self.name.get_text()
260                 self.data['email'] = self.email.get_text()
261         
262         def info_page(self):
263                 info = gnome.ui.DruidPageStandard()
264                 self.name = gtk.Entry()
265                 self.email = gtk.Entry()
266                 info.append_item("Name", self.name, "Optional")
267                 info.append_item("Email", self.email, "")
268                 info.connect('cancel', lambda w, d:gtk.main_quit())
269                 info.connect('next', self.info_page_next)
270                 self.druid.append_page(info)
271         
272         def __init__(self):
273                 self.first_time = True
274                 
275                 self.win = gtk.Window()
276                 self.win.set_title("Ardour Bug Tool")
277                 self.win.connect('destroy', lambda w: gtk.main_quit())
278                 
279                 self.druid = gnome.ui.Druid()
280                 
281                 self.start_page()
282                 self.build_tools_page()
283                 self.binary_page()
284                 self.versions_page()
285                 self.sessions_page()
286                 self.description_page()
287                 self.info_page()
288                 self.end_page()
289                 
290                 self.win.add(self.druid)
291                 self.win.show_all()
292
293                 self.data = {}
294
295 def main(*args):
296         os.mkdir(g_name+"/proc/")
297         proclist = ['asound', 'cpuinfo', 'devices', 'dma', 'filesystems', 'irq', 'isapnp', 'meminfo', 'modules', 'mounts', 'partition', 'pci', 'slabinfo', 'sysvipc/shm', 'version']
298         for item in proclist:
299                 if os.path.exists('/proc/'+item):
300                         try:
301                                 if os.path.isdir('/proc/'+item):
302                                         shutil.copytree('/proc/'+item, g_name+'/proc/'+item)
303                                 else:
304                                         shutil.copy('/proc/'+item, g_name+'/proc/')
305                         except shutil.Error:
306                                 pass #should this be reported?
307                 else:
308                         f = open(g_name+'/proc/'+item, 'w')
309                         f.write(item+' missing in /proc')
310                         f.close
311         
312         liblist = ['asound', 'c', 'gdbm', 'gdk', 'gmodule', 'gtk', 'intl', 'jack', 'm', 'pthreads', 'sndfile', 'X11', 'Xext']
313         for lib in liblist:
314                 for libdir in ['/lib/', '/usr/lib/', '/usr/X11R6/lib/', '/usr/local/lib/', '/opt/lib/']:
315                         if os.path.exists(libdir+"lib"+lib+".so"):
316                                 os.system('echo "'+lib+ ' is `ls -l '+libdir+'lib'+lib+'.so`" >> '+g_name+'/libraries')
317         
318         if os.path.exists('/proc/sys/kernel/lowlatency'):
319                 shutil.copy('/proc/sys/kernel/lowlatency', g_name+'/lowlatency-status')
320         else:
321                 f = open(g_name+'/lowlatency-status', 'w')
322                 f.write('-1')
323                 f.close()
324
325         scsi = re.compile(r'sd[a-z][0-9]')
326         if scsi.search(open('/proc/mounts').read()):
327                 shutil.copytree('/proc/scsi', g_name+'/scsi')
328
329         ide = re.compile(r'hd[a-z][0-9]')
330         if ide.search(open('/proc/mounts').read()):
331                 pass
332
333         os.system("xmodmap >" +g_name+"/xmodmap")
334         os.system("/sbin/lspci -vv >" +g_name+"/lspci.out")
335         
336         if os.path.exists(os.path.expandvars('$HOME')+'/.ardour/ardour.rc'):
337                 shutil.copy(os.path.expandvars('$HOME')+'/.ardour/ardour.rc', g_name+'/ardour.rc')
338
339         bug_win = ReportWin()
340
341         gtk.main()
342
343 if __name__ == '__main__':
344         main()
345         
346 shutil.rmtree(g_name)
347 if os.path.exists(g_name+'.tar.gz'):
348         os.remove(g_name+'.tar.gz')
349