class Task(ColorLayer, pyglet.event.EventDispatcher): d = Dispatcher() states = ["INIT", "CALIBRATE", "IGNORE_INPUT", "TASK", "DONE"] STATE_INIT = 0 STATE_CALIBRATE = 1 STATE_IGNORE_INPUT = 2 STATE_TASK = 3 STATE_DONE = 4 BG_TILE_SIZE = (1024,128) FG_TILE_SIZE = (1024,128) is_event_handler = True def __init__(self, client=None): self.screen = director.get_window_size() super(Task, self).__init__(0, 0, 0, 255, 1024, int(768*1.1)) self.client = client self.state = self.STATE_INIT self.mole_images = [resource.image('mole_1.png'), resource.image('mole_laugh1.png'), resource.image('mole_laugh2.png'), resource.image('mole_laugh3.png'), resource.image('mole_thump1.png'), resource.image('mole_thump2.png'), resource.image('mole_thump3.png'), resource.image('mole_thump4.png')] self.music = Player() self.music.queue(pyglet.resource.media('whack.mp3')) self.music.eos_action = 'loop' self.cm = CollisionManagerBruteForce() self.moles = [] for i in range(0,3): mole = Mole(self.mole_images, (112 + (i * 310)), (127-80)) self.moles.append(mole) self.add(mole, 55) self.cm.add(mole) for i in range(3,6): mole = Mole(self.mole_images, (112 + ((i-3) * 310)), (383-80)) self.moles.append(mole) self.add(mole, 35) self.cm.add(mole) for i in range(6,9): mole = Mole(self.mole_images, (112 + ((i-6) * 310)), (639-80)) self.moles.append(mole) self.add(mole, 15) self.cm.add(mole) self.text_batch = BatchNode() self.add(self.text_batch, z=100) self.score = 0 scorey = int((768 + int(768*1.1))/2) self.score_num = text.Label("%06d" % self.score, font_name="Score Board", font_size=48, x=512, y=scorey, color=(255, 255, 255, 255), anchor_x='center', anchor_y='center', batch=self.text_batch.batch) self.fix = Label('G', font_name='Cut Outs for 3D FX', font_size=48, position=(0,0), color=(255, 0, 0, 192), anchor_x='center', anchor_y='center') self.fix.visible = False self.add(self.fix, z=100000) self.add(Sprite(resource.image('bg_dirt128.png'), anchor=(0,0), position=(0,0))) self.add(Sprite(resource.image('bg_dirt128.png'), anchor=(0,0), position=(0,128))) self.add(Sprite(resource.image('bg_dirt128.png'), anchor=(0,0), position=(0,256))) self.add(Sprite(resource.image('bg_dirt128.png'), anchor=(0,0), position=(0,384))) self.add(Sprite(resource.image('bg_dirt128.png'), anchor=(0,0), position=(0,512))) self.add(Sprite(resource.image('bg_dirt128.png'), anchor=(0,0), position=(0,640))) self.add(Sprite(resource.image('grass_lower128.png'), anchor=(0,0), position=(0,0)), z=60) self.add(Sprite(resource.image('grass_upper128.png'), anchor=(0,0), position=(0,128)), z=50) self.add(Sprite(resource.image('grass_lower128.png'), anchor=(0,0), position=(0,256)), z=40) self.add(Sprite(resource.image('grass_upper128.png'), anchor=(0,0), position=(0,384)), z=30) self.add(Sprite(resource.image('grass_lower128.png'), anchor=(0,0), position=(0,512)), z=20) self.add(Sprite(resource.image('grass_upper128.png'), anchor=(0,0), position=(0,640)), z=10) def set_score(self): self.score_num.begin_update() self.score_num.text = "%06d" % self.score self.score_num.end_update() def visit(self): super(Task, self).visit() if director.settings["overlay"]: for mole in self.moles: if mole.opacity > -1: if mole.state == 1: color = (.3,0.0,0.0,.7) else: color = (.3,0.2,0.5,.7) p = Polygon([(mole.center[0]-mole.rx, mole.center[1]-mole.ry), (mole.center[0]+mole.rx, mole.center[1]-mole.ry), (mole.center[0]+mole.rx, mole.center[1]+mole.ry), (mole.center[0]-mole.rx, mole.center[1]+mole.ry)], color=color) p.render() def mole_up(self): moles = [mole for mole in self.moles if not mole.active] if moles: random.choice(moles).up() def animate(self, dt): self.mole_up() if random.randint(0, 3) == 0: self.mole_up() def game_over(self): self.state = self.STATE_GAME_OVER def clear(self): self.music.pause() self.music.seek(0) for mole in self.moles: mole.active = False mole.state = 0 mole.position = mole.position_in pyglet.clock.unschedule(self.animate) if self.client: self.client.removeDispatcher(self.d) self.client.stopDataStreaming() self.client.stopFixationProcessing() def reset(self): self.clear() if self.client: self.client.addDispatcher(self.d) #self.client.setDataFormat('%TS %ET %SX %SY %DX %DY %EX %EY %EZ') #self.client.startDataStreaming() self.client.startFixationProcessing() self.state = self.STATE_TASK self.score = 0 pyglet.clock.schedule_interval(self.animate, .5) self.music.play() def on_enter(self): if isinstance(director.scene, TransitionScene): return super(Task, self).on_enter() if director.settings['eyetracker']: self.state = self.STATE_CALIBRATE self.dispatch_event("start_calibration", self.calibration_ok, self.calibration_bad) else: self.reset() def calibration_ok(self): self.dispatch_event("stop_calibration") self.reset() def calibration_bad(self): self.dispatch_event("stop_calibration") director.scene.dispatch_event("show_intro_scene") def on_exit(self): if isinstance(director.scene, TransitionScene): return super(Task, self).on_exit() self.clear() @d.listen('ET_FIX') def iViewXEvent(self, inResponse): if inResponse[0] == 'l': x = int(float(inResponse[2])) y = int(float(inResponse[3])) if director.settings["overlay"]: self.fix.position = (x, y) self.fix.visible = True self.handle_mouse_press(x, y) @d.listen('ET_EFX') def iViewXEvent(self, inResponse): if inResponse[0] == 'l': if director.settings["overlay"]: self.fix.visible = False @d.listen('ET_SPL') def iViewXEvent(self, inResponse): pass def handle_mouse_press(self, x, y): for obj in self.cm.objs_touching_point(x, y): if obj.active: if obj.state == 0: obj.state = 1 obj.thump() self.score += 10 elif obj.state == 2: self.score -= 10 self.set_score() def on_mouse_press(self, x, y, buttons, modifiers): posx, posy = director.get_virtual_coordinates(x, y) self.handle_mouse_press(posx, posy) def on_mouse_motion(self, x, y, dx, dy): pass def on_key_press(self, symbol, modifiers): if self.state < self.STATE_IGNORE_INPUT: return if symbol == key.W and (modifiers & key.MOD_ACCEL): director.scene.dispatch_event("show_intro_scene") True if self.state == self.STATE_TASK: pass elif self.state == self.STATE_DONE: pass
class SoundPlayer(object): def __init__(self, soundDirPath): self.soundDirPath = soundDirPath self.loadSounds() self.musicPlayer = Player() self.queue = False self.queuePlayer = None self.enabled = True self.soundEffectVolume = 1.0 # between 0.0 and 1.0 self._musicVolume = 1.0 # between 0.0 and 1.0 ''' loads sounds from gui config file into dict. maps name to pyglet sound object. if ',stream' exists after filename in config file, will stream file instead of loading the whole thing in once. ''' def loadSounds(self): self.sounds = dict() soundTypes = dict(gui.config.items('sound_events')) for key in soundTypes: self._loadSoundResource(key) @staticmethod def _loadSoundEntry(key): entry = gui.config.get('sound_events', key) if ',' in entry: sp = entry.split(",") fileName = sp[0] if sp[1] == "stream": stream = True else: fileName = entry stream = False return fileName, stream def _loadSoundResource(self, key): fileName, stream = self._loadSoundEntry(key) if key in self.sounds: self.sounds[key].delete() self.sounds[key] = pyglet.resource.media(self.soundDirPath + fileName, streaming=stream) def shutdown(self): from pyglet.media import avbin if self.musicPlayer.source is not None: avbin.av.avbin_close_file( self.musicPlayer.source._file ) # hack to ensure avbin closes properly. self.musicPlayer.delete() toDel = self.sounds.keys() for snd in toDel: del self.sounds[snd] @property def musicVolume(self): return self._soundEffectVolume @musicVolume.setter def musicVolume(self, value): self.musicPlayer.volume = value self._musicVolume = self.musicPlayer.volume def setMute(self, value): self.enabled = value def getSound(self, soundName): try: snd = self.sounds[soundName.lower()] except KeyError: print "Sound requsted to be played does not exist in config file." return None return snd def playMusic(self, soundName): if not self.enabled: return soundName = soundName.lower() snd = self.getSound(soundName) assert snd if self.musicPlayer.playing and self.musicPlayer.source == snd: self.musicPlayer.seek(0) return else: # reload sound and reset Player obj # (streaming sounds needs to be reloaded every time) if isinstance(snd, pyglet.media.StreamingSource): self._loadSoundResource(soundName) self.musicPlayer.delete() self.musicPlayer = Player() self.musicPlayer.volume = self._musicVolume looper = pyglet.media.SourceGroup(snd.audio_format, None) looper.loop = True looper.queue(snd) self.musicPlayer.queue(looper) self.musicPlayer.play() def playEffect(self, soundName): if not self.enabled: return soundName = soundName.lower() snd = self.getSound(soundName) assert snd p = Player() p.volume = self.soundEffectVolume p.queue(snd) p.play() def startEffectsQueue(self): self.queue = True self.queuePlayer = Player() def queueEffect(self, soundName): if not self.enabled: return soundName = soundName.lower() snd = self.getSound(soundName) assert snd self.queuePlayer.queue(snd) ''' Plays the queue and resets queue state. ''' def playEffectsQueue(self): self.queuePlayer.volume = self.soundEffectVolume self.queuePlayer.play() self.queue = False self.queuePlayer = None
class Gui(object): def __init__(self, manager, win, debug=False): self.manager = manager self.debug = debug #self.lab=Label(win, text="Serial port:") #self.lab.place(x=30, y=20) #self.txtfld=Entry(win, text="Serial port") #self.txtfld.place(x=300, y=20) #self.btn_cnct=Button(win, text="Connect printer", command=self.connect) #self.btn_cnct.place(x=30, y=50) #self.btn_init=Button(win, text="Initialize", command=self.initialize, state=DISABLED) #self.btn_init.place(x=30, y=90) #self.tidal_vol=("300","400","500","750","900","1000") #self.lab_tv=Label(win, text='Tidal volume:') #self.lab_tv.place(x=30, y=180) #self.tv=Combobox(win, values=self.tidal_vol) #self.tv.place(x=240, y=180) #self.resp_rate=("12","16","20","32") #self.lab_rr=Label(win, text='Respiratory rate:') #self.lab_rr.place(x=30, y=210) #self.rr=Combobox(win, values=self.resp_rate) #self.rr.place(x=240, y=210) #self.insp_exp=("1:2") #self.lab_ie=Label(win, text='Inspiratory/expiratory:') #self.lab_ie.place(x=30, y=240) #self.ie=Combobox(win, values=self.insp_exp) #self.ie.place(x=240, y=240) #self.btn_run=Button(win, text="Run Ventilation", command=self.start_run,state=DISABLED) #self.btn_run.place(x=30, y=310) #self.btn_stop=Button(win, text="Stop",command=self.stop,state=DISABLED) #self.btn_stop.place(x=180, y=310) self.readings = [] self.state = None self.reading_pressure = Label(win, text="Latest pressure (cmH2O)", font=("Helvetica", 18)) self.reading_pressure.place(x=30, y=20) self.reading_ppeak = Label(win, text="Latest PPeak (cmH2O)", font=("Helvetica", 18)) self.reading_ppeak.place(x=35, y=50) self.reading_timestamp = Label(win, text="Latest reading age (seconds)") self.reading_timestamp.place(x=30, y=90) self.reading_sample_rate = Label(win, text="Sample Rate") self.reading_sample_rate.place(x=30, y=110) self.reading_pressure_inches = Label(win, text="Latest pressure (inH2O)") self.reading_pressure_inches.place(x=30, y=130) self.exit_button = Button(win, text="Close App", command=self.exit_application) self.exit_button.place(x=460, y=1) Thread(target=self.timestampDisplayThread, args=[]).start() self.pressure_options = [i for i in range(0, PRESSURE_UPPER_LIMIT + 1)] self.max_alarm_enabled = BooleanVar(False) self.min_alarm_enabled = BooleanVar(False) self.timeout_alarm_enabled = BooleanVar(False) self.timeout_alarm_enabled.set(True) self.min_alarm_enabled_checkbox = makeCheckbox( win, "Enabled Min Pressure Alarm", self.min_alarm_enabled) self.min_alarm_enabled_checkbox.place(x=30, y=160) self.min_alarm_threshold_label = Label(win, text="Minimum Pressure (cmH2O)") self.min_alarm_threshold_label.place(x=30, y=220) self.min_alarm_threshold_input = Combobox(win, values=self.pressure_options) self.min_alarm_threshold_input.current(0) self.min_alarm_threshold_input.place(x=30, y=240) self.min_alarm_interval_label = Label(win, text="Alarm Interval (seconds)") self.min_alarm_interval_label.place(x=30, y=265) self.min_alarm_interval_input = Combobox(win, values=INTERVAL_LABELS) self.min_alarm_interval_input.current(0) self.min_alarm_interval_input.place(x=30, y=285) self.max_alarm_enabled_checkbox = makeCheckbox( win, "Enabled Max Pressure Alarm", self.max_alarm_enabled) self.max_alarm_enabled_checkbox.place(x=280, y=160) self.max_alarm_threshold_label = Label(win, text="Maximum Pressure (cmH2O)") self.max_alarm_threshold_label.place(x=280, y=220) self.max_alarm_threshold_input = Combobox(win, values=self.pressure_options) self.max_alarm_threshold_input.current(len(self.pressure_options) - 31) self.max_alarm_threshold_input.place(x=280, y=240) self.max_alarm_interval_label = Label(win, text="Alarm Interval (seconds)") self.max_alarm_interval_label.place(x=280, y=265) self.max_alarm_interval_input = Combobox(win, values=INTERVAL_LABELS) self.max_alarm_interval_input.current(0) self.max_alarm_interval_input.place(x=280, y=285) self.timeout_alarm_enabled_checkbox = makeCheckbox( win, "Enabled Lost Signal Alarm", self.timeout_alarm_enabled) self.timeout_alarm_enabled_checkbox.place(x=30, y=320) self.timeout_alarm_interval_label = Label( win, text="Lost Signal Timeout (seconds)") self.timeout_alarm_interval_label.place(x=30, y=380) self.timeout_alarm_interval_input = Combobox(win, values=TIMEOUT_LABELS) self.timeout_alarm_interval_input.current(0) self.timeout_alarm_interval_input.place(x=30, y=400) self.test_alarm = Button(win, text="Test Alarm", command=self.test_alarm) self.test_alarm.place(x=285, y=365) self.clear_alarm = Button(win, text="Clear Alarm", command=self.clear_alarm) self.clear_alarm.place(x=285, y=395) self.alarm_active = False self.alarm_messages = [] self.alarms_messages_var = StringVar() self.alarms_messages_label = Label( win, textvariable=self.alarms_messages_var, font=("Helvetica", 32)) self.alarms_messages_label.place(x=30, y=440) self.alarms_messages_label['bg'] = 'lightgrey' self.alarms_messages_label['fg'] = 'red' self.player = None self.last_seek = datetime.now() Thread(target=self.pygletThread, args=[]).start() Thread(target=self.alarmThread, args=[]).start() #TODO #self.place_dropdown(win,'Tidal volume:', self.tidal_vol, 60, 180) #self.place_dropdown(win,'Respiratory rate:', self.resp_rate, 60, 210) #self.place_dropdown(win,'Inspiratory/expiratory:', self.insp_exp, 60, 240) #self.place_btn(win,"Run ventilation", self.run,60,290) #self.place_btn(win,"Stop", self.run,180,290) #3dpav control self.printer = None self.lookup = None self.started_run = False self._isOk = False self.window = win def exit_application(self): self.manager.shutdown() def shutdown(self): self.window.destroy() def boot(self): self.window.title('3DPaV Pressure Monitor') self.window.geometry("529x564+0+0") self.window.mainloop() def pygletThread(self): self.player = Player() source = pyglet.resource.media('red_alert.wav') self.player.queue(source) pyglet.app.run() def timestampDisplayThread(self): while True: self.ui_updater_func() time.sleep(0.01) def test_alarm(self): self.add_alarm("Test Alarm") def clear_alarm(self): self.alarm_active = False self.alarm_messages = [] self.alarms_messages_label['bg'] = 'lightgrey' self.window['bg'] = 'lightgrey' def add_alarm(self, alarm_message): self.alarm_active = True self.alarm_messages = list(set(self.alarm_messages + [alarm_message])) self.alarms_messages_label['bg'] = 'white' self.window['bg'] = 'red' def alarmThread(self): while True: now = datetime.now() if ((now - self.last_seek).total_seconds() > LOOP_TIMEOUT_SECONDS): self.player.seek(0) self.last_seek = now if (self.player): if (self.alarm_active): if not self.player.playing: print('START ALERT') self.player.play() else: if self.player.playing: print('STOP ALERT') self.player.pause() time.sleep(0.01) def updateReadings(self, state): self.readings.append( Reading(state['latestPressureValue'], state['timestamp'])) self.state = state def ui_updater_func(self): state = self.state if state is None: return timestamp = state['timestamp'] latestPressureValue = state['latestPressureValue'] latestPPeakValue = state['latestPPeakValue'] sampleRate = state['sampleRate'] self.reading_pressure.configure( text="Latest Pressure (cmH2O): {:10.2f}".format( latestPressureValue)) self.reading_pressure_inches.configure( text="Latest Pressure (inH2O): {:10.2f}".format( latestPressureValue / INCHES_TO_CENIMETERS)) self.reading_ppeak.configure( text="Latest PPeak (cmH2O): {:10.2f}".format(latestPPeakValue)) self.reading_sample_rate.configure( text="Sample Rate (ms): {:10.2f}".format(sampleRate * 1000)) self.alarms_messages_var.set(", \n".join(self.alarm_messages)) now = datetime.now() min_alarm_label = self.min_alarm_interval_input.get() max_alarm_label = self.max_alarm_interval_input.get() min_alarm_interval = INTERVAL_OPTIONS_MAP[min_alarm_label] max_alarm_interval = INTERVAL_OPTIONS_MAP[max_alarm_label] self.readings = [ r for r in self.readings if ((now - r.stamp).total_seconds() < (2 * MAX_INTERVAL_VALUE)) ] trigger_max_alert = False if (self.max_alarm_enabled.get()): max_samples = [ r for r in self.readings if ((now - r.stamp).total_seconds() < max_alarm_interval) ] max_threshold = int(self.max_alarm_threshold_input.get()) if max_alarm_label == IMMEDIATE_KEY_WORD: trigger_max_alert = len( [r for r in max_samples if r.value >= max_threshold]) > 0 elif (len(max_samples) < len(self.readings)): trigger_max_alert = len( [r for r in max_samples if r.value < max_threshold]) == 0 trigger_min_alert = False if (self.min_alarm_enabled.get()): min_samples = [ r for r in self.readings if ((now - r.stamp).total_seconds() < min_alarm_interval) ] min_threshold = int(self.min_alarm_threshold_input.get()) if min_alarm_label == IMMEDIATE_KEY_WORD: trigger_min_alert = len( [r for r in min_samples if r.value <= min_threshold]) > 0 elif (len(min_samples) < len(self.readings)): trigger_min_alert = len( [r for r in min_samples if r.value > min_threshold]) == 0 if trigger_min_alert: self.add_alarm("Min Pressure Alarm") if trigger_max_alert: self.add_alarm("Max Pressure Alarm") if timestamp is not None: delta_seconds = (datetime.now() - timestamp).total_seconds() self.reading_timestamp.configure( text="Latest reading: {:10.2f} seconds ago".format( delta_seconds)) if (self.timeout_alarm_enabled.get()): timeout_threshold = TIMEOUT_OPTIONS_MAP[ self.timeout_alarm_interval_input.get()] if delta_seconds > timeout_threshold: self.add_alarm("Signal Lost") @property def isOk(self): return self._isOk @isOk.setter def isOk(self, new_value): if self.debug: print('isOk being updated to ' + str(new_value)) self._isOk = new_value if self.started_run and new_value == True: if self.debug: print('adding another run with ' + str(self.lookup)) g_run(self, self.lookup, self.debug) #deprecated? keep it all on one thread for now #t = Thread(target = g_run, args =(self,self.lookup,self.debug )) #------------------------- aesthetics def place_dropdown(self, win, txt, vals, xstart=60, ystart=180): self.lab = Label(win, text=txt) self.lab.place(x=xstart, y=ystart) self.box = Combobox(win, values=vals) self.box.place(x=xstart + 160, y=ystart) def place_btn(self, win, txt, cmd, xstart=60, ystart=180): self.btn = Button(win, text=txt, command=cmd) self.btn.place(x=xstart, y=ystart) #-------------------------- ventilator methods def connect(self): if self.txtfld.get() == '': path = '/Users/juliagonski/Documents/Columbia/3DprinterAsVentilator/pronsoleWork/Printator/sim' else: path = self.txtfld.get() ser_printer = serial.Serial(path, baudRate) print("Connecting to printer...") time.sleep(1) # Allow time for response if self.debug: print("Connection response from printer:", ser_printer.read(ser_printer.inWaiting())) #ser_printer.write(str.encode('M400\n')) #ser_printer.write(str.encode('M400\n')) answer = ser_printer.readline() if 'ok' in answer.decode("utf-8", "ignore"): print("------ Done connecting!") print("") self.printer = ser_printer self.btn_init["state"] = "normal" def initialize(self): g_init(self, self.debug) self.btn_run["state"] = "normal" #def check_run(self, win): # if self.started_run == 1: # answer = self.waitForOk(self.printer) # if self.debug: print("waiting response from printer?", answer) # if 'ok' in answer.decode("utf-8", "ignore"): g_run(self,self.debug) # #else: print('not ventilating, not adding more runs') # win.after(2000,self.check_run,win) def start_run(self): self.printer.flush() self.started_run = True sel_tv = self.tv.get() sel_rr = self.rr.get() sel_ie = self.ie.get() self.lookup = sel_tv + "mL_" + sel_rr + "BPM_" + sel_ie print('Started new protocol: ' + str(self.lookup)) self.btn_stop["state"] = "normal" #Start first thread, join subsequent ones t_orig = Thread(target=g_run, args=(self, self.lookup, self.debug)) t_orig.start() def stop(self): self.started_run = False self.printer.flush() g_stop(self, self.debug) def waitForOk(self, ser_printer): if self.debug: print('BEGIN waitForOk') isItOk = False answer = '' quantity = ser_printer.inWaiting() while True: if quantity > 0: #answer += ser_printer.read(quantity) answer += ser_printer.read(quantity).decode("utf-8", "ignore") ##if 'ok' in answer.decode("utf-8", "ignore"): if 'ok' in answer: if self.debug: print('found ok, breaking') isItOk = True break else: time.sleep(read_timeout) quantity = ser_printer.inWaiting() #if quantity == 0: #if self.debug: print('-------> No lines to read out') #print('ERROR connecting!!!') #raise ImportError() #break if self.debug: print('resulting answer: ', answer) return isItOk def waitForDONE(self, ser_printer): if self.debug: print('----- BEGIN waitForDONE') isItOk = False answer = '' quantity = ser_printer.inWaiting() while True: if quantity > 0: if self.debug: print('----- reading what the printer has to say: ', ser_printer.read(quantity).decode("utf-8", "ignore")) answer += ser_printer.read(quantity).decode("utf-8", "ignore") #deprecated new firmware 0622 if 'ok' in answer: if 'DECOMPRESSDONE' in answer: if self.debug: print('----- found DECMOMPRESSDONE in answer') isItOk = True break else: time.sleep(read_timeout) quantity = ser_printer.inWaiting() #if quantity == 0: #if self.debug: print('-------> No lines to read out') #print('ERROR connecting!!!') #raise ImportError() #break if self.debug: print( '----- resulting answer of concatented printer output (should end in DECOMPRESSDONE): ', answer) return isItOk
class SoundPlayer(object): def __init__(self, soundDirPath): self.soundDirPath = soundDirPath self.loadSounds() self.musicPlayer = Player() self.queue = False self.queuePlayer = None self.enabled = True self.soundEffectVolume = 1.0 # between 0.0 and 1.0 self._musicVolume = 1.0 # between 0.0 and 1.0 """ loads sounds from gui config file into dict. maps name to pyglet sound object. if ',stream' exists after filename in config file, will stream file instead of loading the whole thing in once. """ def loadSounds(self): self.sounds = dict() soundTypes = dict(gui.config.items("sound_events")) for key in soundTypes: self._loadSoundResource(key) @staticmethod def _loadSoundEntry(key): entry = gui.config.get("sound_events", key) if "," in entry: sp = entry.split(",") fileName = sp[0] if sp[1] == "stream": stream = True else: fileName = entry stream = False return fileName, stream def _loadSoundResource(self, key): fileName, stream = self._loadSoundEntry(key) if key in self.sounds: self.sounds[key].delete() self.sounds[key] = pyglet.resource.media(self.soundDirPath + fileName, streaming=stream) def shutdown(self): from pyglet.media import avbin if self.musicPlayer.source is not None: avbin.av.avbin_close_file(self.musicPlayer.source._file) # hack to ensure avbin closes properly. self.musicPlayer.delete() toDel = self.sounds.keys() for snd in toDel: del self.sounds[snd] @property def musicVolume(self): return self._soundEffectVolume @musicVolume.setter def musicVolume(self, value): self.musicPlayer.volume = value self._musicVolume = self.musicPlayer.volume def setMute(self, value): self.enabled = value def getSound(self, soundName): try: snd = self.sounds[soundName.lower()] except KeyError: print "Sound requsted to be played does not exist in config file." return None return snd def playMusic(self, soundName): if not self.enabled: return soundName = soundName.lower() snd = self.getSound(soundName) assert snd if self.musicPlayer.playing and self.musicPlayer.source == snd: self.musicPlayer.seek(0) return else: # reload sound and reset Player obj # (streaming sounds needs to be reloaded every time) if isinstance(snd, pyglet.media.StreamingSource): self._loadSoundResource(soundName) self.musicPlayer.delete() self.musicPlayer = Player() self.musicPlayer.volume = self._musicVolume looper = pyglet.media.SourceGroup(snd.audio_format, None) looper.loop = True looper.queue(snd) self.musicPlayer.queue(looper) self.musicPlayer.play() def playEffect(self, soundName): if not self.enabled: return soundName = soundName.lower() snd = self.getSound(soundName) assert snd p = Player() p.volume = self.soundEffectVolume p.queue(snd) p.play() def startEffectsQueue(self): self.queue = True self.queuePlayer = Player() def queueEffect(self, soundName): if not self.enabled: return soundName = soundName.lower() snd = self.getSound(soundName) assert snd self.queuePlayer.queue(snd) """ Plays the queue and resets queue state. """ def playEffectsQueue(self): self.queuePlayer.volume = self.soundEffectVolume self.queuePlayer.play() self.queue = False self.queuePlayer = None