from Tkinter import * import tempfile import os import urllib import urlparse import audiodev DEF_SOUND = "violence.au" class AudioButton: def __init__(self, master, sound=DEF_SOUND, text="Audio"): self.viewer = master.grail_viewer self.context = master.grail_context url = self.context.get_baseurl() self.url = urlparse.urljoin(url, sound) self.text = text self.tfile = None self.player = None self.button = Button(master, text=text, command=self.play) self.button.pack() def __del__(self): if self.tfile: os.unlink(self.tfile) def stop(self): if self.player: player = self.player self.player = None player.stop() self.button.config(command=self.play, text=self.text, fg='black', activeforeground='black') def play(self): # XXX This is synchronous. # XXX It should be possible to do this using a filehandler. # XXX (See how ImageLoopItem does it?) self.button.config(command=self.stop, text="Cancel", fg='red', activeforeground='red') self.player = p = audiodev.AudioDev() p.setoutrate(8000) p.setsampwidth(0) # Special: U-LAW p.setnchannels(1) if not self.tfile: self.context.message("Loading sound file %s" % self.url) try: try: f = urllib.urlopen(self.url) except IOError, msg: p.close() print "*** Error loading sound file", self.url, ":", msg return pos = 0 self.tfile = tempfile.mktemp() print self.tfile g = open(self.tfile, 'w') BS = 8*1024 while 1: self.button.update() if not self.player: break data = f.read(BS) if not data: break g.write(data) if pos < 24: head, data = data[:24-pos], data pos = pos + len(head) if data: p.writeframes(data) pos = pos + len(data) f.close() g.close() finally: self.context.message("") else: f = open(self.tfile) f.seek(24) while 1: self.button.update() if not self.player: break buf = f.read(8000) if not buf: break p.writeframes(buf) f.close() while self.player and p.getfilled(): self.button.update() self.stop()