def draw(self, gml): """ DRAW: Execute a Graphics Macro Language string. """ # don't convert to uppercase as VARPTR$ elements are case sensitive gmls = StringIO(gml) plot, goback = True, False while True: c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == '': break elif c == ';': continue elif c == 'B': # do not draw plot = False elif c == 'N': # return to postiton after move goback = True elif c == 'X': # execute substring sub = draw_and_play.ml_parse_string(gmls) self.draw(str(sub)) elif c == 'C': # set foreground colour # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.last_attr = 0 else: self.last_attr = draw_and_play.ml_parse_number(gmls) elif c == 'S': # set scale self.draw_scale = draw_and_play.ml_parse_number(gmls) elif c == 'A': # set angle # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.draw_angle = 0 else: self.draw_angle = 90 * draw_and_play.ml_parse_number(gmls) elif c == 'T': # 'turn angle' - set (don't turn) the angle to any value if gmls.read(1).upper() != 'A': raise error.RunError(error.IFC) # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.draw_angle = 0 else: self.draw_angle = draw_and_play.ml_parse_number(gmls) # one-variable movement commands: elif c in ('U', 'D', 'L', 'R', 'E', 'F', 'G', 'H'): step = draw_and_play.ml_parse_number(gmls, default=vartypes.int_to_integer_signed(1)) x0, y0 = self.last_point x1, y1 = 0, 0 if c in ('U', 'E', 'H'): y1 -= step elif c in ('D', 'F', 'G'): y1 += step if c in ('L', 'G', 'H'): x1 -= step elif c in ('R', 'E', 'F'): x1 += step self.draw_step(x0, y0, x1, y1, plot, goback) plot = True goback = False # two-variable movement command elif c == 'M': relative = util.skip(gmls, draw_and_play.ml_whitepace) in ('+','-') x = draw_and_play.ml_parse_number(gmls) if util.skip(gmls, draw_and_play.ml_whitepace) != ',': raise error.RunError(error.IFC) else: gmls.read(1) y = draw_and_play.ml_parse_number(gmls) x0, y0 = self.last_point if relative: self.draw_step(x0, y0, x, y, plot, goback) else: if plot: self.draw_line(x0, y0, x, y, self.last_attr) self.last_point = x, y if goback: self.last_point = x0, y0 plot = True goback = False elif c =='P': # paint - flood fill colour = draw_and_play.ml_parse_number(gmls) if util.skip_read(gmls, draw_and_play.ml_whitepace) != ',': raise error.RunError(error.IFC) bound = draw_and_play.ml_parse_number(gmls) x, y = self.get_window_logical(*self.last_point) self.paint((x, y, False), None, colour, bound, None)
def play(self, mml_list): """ Parse a list of Music Macro Language strings. """ gmls_list = [] for mml in mml_list: gmls = StringIO() # don't convert to uppercase as VARPTR$ elements are case sensitive gmls.write(str(mml)) gmls.seek(0) gmls_list.append(gmls) next_oct = 0 total_time = [0, 0, 0, 0] voices = range(3) while True: if not voices: break for voice in voices: vstate = self.play_state[voice] gmls = gmls_list[voice] c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == '': voices.remove(voice) continue elif c == ';': continue elif c == 'X': # execute substring sub = draw_and_play.ml_parse_string(gmls) pos = gmls.tell() rest = gmls.read() gmls.truncate(pos) gmls.write(str(sub)) gmls.write(rest) gmls.seek(pos) elif c == 'N': note = draw_and_play.ml_parse_number(gmls) dur = vstate.length c = util.skip(gmls, draw_and_play.ml_whitepace).upper() if c == '.': gmls.read(1) dur *= 1.5 if note > 0 and note <= 84: self.play_sound(note_freq[note - 1], dur * vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice) total_time[voice] += dur * vstate.tempo elif note == 0: self.play_sound(0, dur * vstate.tempo, vstate.speed, volume=0, voice=voice) total_time[voice] += dur * vstate.tempo elif c == 'L': vstate.length = 1. / draw_and_play.ml_parse_number(gmls) elif c == 'T': vstate.tempo = 240. / draw_and_play.ml_parse_number(gmls) elif c == 'O': vstate.octave = min( 6, max(0, draw_and_play.ml_parse_number(gmls))) elif c == '>': vstate.octave += 1 if vstate.octave > 6: vstate.octave = 6 elif c == '<': vstate.octave -= 1 if vstate.octave < 0: vstate.octave = 0 elif c in ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'P'): note = c dur = vstate.length while True: c = util.skip(gmls, draw_and_play.ml_whitepace).upper() if not c: break elif c == '.': gmls.read(1) dur *= 1.5 elif c in string.digits: numstr = '' while c and c in string.digits: gmls.read(1) numstr += c c = util.skip(gmls, draw_and_play.ml_whitepace) # NOT ml_parse_number, only literals allowed here! length = int(numstr) dur = 1. / float(length) elif c in ('#', '+'): gmls.read(1) note += '#' elif c == '-': gmls.read(1) note += '-' else: break if note == 'P': self.play_sound(0, dur * vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice) total_time[voice] += dur * vstate.tempo else: try: self.play_sound( note_freq[(vstate.octave + next_oct) * 12 + notes[note]], dur * vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice) total_time[voice] += dur * vstate.tempo except KeyError: raise error.RunError(error.IFC) next_oct = 0 elif c == 'M': c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == 'N': vstate.speed = 7. / 8. elif c == 'L': vstate.speed = 1. elif c == 'S': vstate.speed = 3. / 4. elif c == 'F': self.foreground = True elif c == 'B': self.foreground = False else: raise error.RunError(error.IFC) elif c == 'V' and (pcjr_sound == 'tandy' or (pcjr_sound == 'pcjr' and self.sound_on)): vstate.volume = min( 15, max(0, draw_and_play.ml_parse_number(gmls))) else: raise error.RunError(error.IFC) max_time = max(total_time) for voice in range(3): if total_time[voice] < max_time: self.play_sound(0, max_time - total_time[voice], 1, 0, voice) if self.foreground: self.wait_all_music()
def play(self, mml_list): """ Parse a list of Music Macro Language strings. """ gmls_list = [] for mml in mml_list: gmls = StringIO() # don't convert to uppercase as VARPTR$ elements are case sensitive gmls.write(str(mml)) gmls.seek(0) gmls_list.append(gmls) next_oct = 0 total_time = [0, 0, 0, 0] voices = range(3) while True: if not voices: break for voice in voices: vstate = self.play_state[voice] gmls = gmls_list[voice] c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == "": voices.remove(voice) continue elif c == ";": continue elif c == "X": # execute substring sub = draw_and_play.ml_parse_string(gmls) pos = gmls.tell() rest = gmls.read() gmls.truncate(pos) gmls.write(str(sub)) gmls.write(rest) gmls.seek(pos) elif c == "N": note = draw_and_play.ml_parse_number(gmls) dur = vstate.length c = util.skip(gmls, draw_and_play.ml_whitepace).upper() if c == ".": gmls.read(1) dur *= 1.5 if note > 0 and note <= 84: self.play_sound( note_freq[note - 1], dur * vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice ) total_time[voice] += dur * vstate.tempo elif note == 0: self.play_sound(0, dur * vstate.tempo, vstate.speed, volume=0, voice=voice) total_time[voice] += dur * vstate.tempo elif c == "L": vstate.length = 1.0 / draw_and_play.ml_parse_number(gmls) elif c == "T": vstate.tempo = 240.0 / draw_and_play.ml_parse_number(gmls) elif c == "O": vstate.octave = min(6, max(0, draw_and_play.ml_parse_number(gmls))) elif c == ">": vstate.octave += 1 if vstate.octave > 6: vstate.octave = 6 elif c == "<": vstate.octave -= 1 if vstate.octave < 0: vstate.octave = 0 elif c in ("A", "B", "C", "D", "E", "F", "G", "P"): note = c dur = vstate.length while True: c = util.skip(gmls, draw_and_play.ml_whitepace).upper() if not c: break elif c == ".": gmls.read(1) dur *= 1.5 elif c in representation.ascii_digits: numstr = "" while c and c in representation.ascii_digits: gmls.read(1) numstr += c c = util.skip(gmls, draw_and_play.ml_whitepace) length = vartypes.pass_int_unpack(representation.str_to_value_keep(("$", numstr))) dur = 1.0 / float(length) elif c in ("#", "+"): gmls.read(1) note += "#" elif c == "-": gmls.read(1) note += "-" else: break if note == "P": self.play_sound(0, dur * vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice) total_time[voice] += dur * vstate.tempo else: try: self.play_sound( note_freq[(vstate.octave + next_oct) * 12 + notes[note]], dur * vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice, ) total_time[voice] += dur * vstate.tempo except KeyError: raise error.RunError(error.IFC) next_oct = 0 elif c == "M": c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == "N": vstate.speed = 7.0 / 8.0 elif c == "L": vstate.speed = 1.0 elif c == "S": vstate.speed = 3.0 / 4.0 elif c == "F": self.foreground = True elif c == "B": self.foreground = False else: raise error.RunError(error.IFC) elif c == "V" and (pcjr_sound == "tandy" or (pcjr_sound == "pcjr" and self.sound_on)): vstate.volume = min(15, max(0, draw_and_play.ml_parse_number(gmls))) else: raise error.RunError(error.IFC) max_time = max(total_time) for voice in range(3): if total_time[voice] < max_time: self.play_sound(0, max_time - total_time[voice], 1, 0, voice) if self.foreground: self.wait_all_music()
def draw(self, gml): """ DRAW: Execute a Graphics Macro Language string. """ # don't convert to uppercase as VARPTR$ elements are case sensitive gmls = StringIO(gml) plot, goback = True, False while True: c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == "": break elif c == ";": continue elif c == "B": # do not draw plot = False elif c == "N": # return to postiton after move goback = True elif c == "X": # execute substring sub = draw_and_play.ml_parse_string(gmls) self.draw(str(sub)) elif c == "C": # set foreground colour # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ";": self.last_attr = 0 else: self.last_attr = draw_and_play.ml_parse_number(gmls) elif c == "S": # set scale self.draw_scale = draw_and_play.ml_parse_number(gmls) elif c == "A": # set angle # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ";": self.draw_angle = 0 else: self.draw_angle = 90 * draw_and_play.ml_parse_number(gmls) elif c == "T": # 'turn angle' - set (don't turn) the angle to any value if gmls.read(1).upper() != "A": raise error.RunError(5) # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ";": self.draw_angle = 0 else: self.draw_angle = draw_and_play.ml_parse_number(gmls) # one-variable movement commands: elif c in ("U", "D", "L", "R", "E", "F", "G", "H"): step = draw_and_play.ml_parse_number(gmls, default=vartypes.pack_int(1)) x0, y0 = self.last_point x1, y1 = 0, 0 if c in ("U", "E", "H"): y1 -= step elif c in ("D", "F", "G"): y1 += step if c in ("L", "G", "H"): x1 -= step elif c in ("R", "E", "F"): x1 += step self.draw_step(x0, y0, x1, y1, plot, goback) plot = True goback = False # two-variable movement command elif c == "M": relative = util.skip(gmls, draw_and_play.ml_whitepace) in ("+", "-") x = draw_and_play.ml_parse_number(gmls) if util.skip(gmls, draw_and_play.ml_whitepace) != ",": raise error.RunError(5) else: gmls.read(1) y = draw_and_play.ml_parse_number(gmls) x0, y0 = self.last_point if relative: self.draw_step(x0, y0, x, y, plot, goback) else: if plot: self.draw_line(x0, y0, x, y, self.last_attr) self.last_point = x, y if goback: self.last_point = x0, y0 plot = True goback = False elif c == "P": # paint - flood fill colour = draw_and_play.ml_parse_number(gmls) if util.skip_read(gmls, draw_and_play.ml_whitepace) != ",": raise error.RunError(5) bound = draw_and_play.ml_parse_number(gmls) x, y = self.get_window_logical(*self.last_point) self.paint((x, y, False), None, colour, bound, None)
def draw(self, gml): """ DRAW: Execute a Graphics Macro Language string. """ # don't convert to uppercase as VARPTR$ elements are case sensitive gmls = StringIO(gml) plot, goback = True, False while True: c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == '': break elif c == ';': continue elif c == 'B': # do not draw plot = False elif c == 'N': # return to postiton after move goback = True elif c == 'X': # execute substring sub = draw_and_play.ml_parse_string(gmls) self.draw(str(sub)) elif c == 'C': # set foreground colour # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.last_attr = 0 else: self.last_attr = draw_and_play.ml_parse_number(gmls) elif c == 'S': # set scale self.draw_scale = draw_and_play.ml_parse_number(gmls) elif c == 'A': # set angle # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.draw_angle = 0 else: self.draw_angle = 90 * draw_and_play.ml_parse_number(gmls) elif c == 'T': # 'turn angle' - set (don't turn) the angle to any value if gmls.read(1).upper() != 'A': raise error.RunError(error.IFC) # allow empty spec (default 0), but only if followed by a semicolon if util.skip(gmls, draw_and_play.ml_whitepace) == ';': self.draw_angle = 0 else: self.draw_angle = draw_and_play.ml_parse_number(gmls) # one-variable movement commands: elif c in ('U', 'D', 'L', 'R', 'E', 'F', 'G', 'H'): step = draw_and_play.ml_parse_number( gmls, default=vartypes.pack_int(1)) x0, y0 = self.last_point x1, y1 = 0, 0 if c in ('U', 'E', 'H'): y1 -= step elif c in ('D', 'F', 'G'): y1 += step if c in ('L', 'G', 'H'): x1 -= step elif c in ('R', 'E', 'F'): x1 += step self.draw_step(x0, y0, x1, y1, plot, goback) plot = True goback = False # two-variable movement command elif c == 'M': relative = util.skip(gmls, draw_and_play.ml_whitepace) in ('+', '-') x = draw_and_play.ml_parse_number(gmls) if util.skip(gmls, draw_and_play.ml_whitepace) != ',': raise error.RunError(error.IFC) else: gmls.read(1) y = draw_and_play.ml_parse_number(gmls) x0, y0 = self.last_point if relative: self.draw_step(x0, y0, x, y, plot, goback) else: if plot: self.draw_line(x0, y0, x, y, self.last_attr) self.last_point = x, y if goback: self.last_point = x0, y0 plot = True goback = False elif c == 'P': # paint - flood fill colour = draw_and_play.ml_parse_number(gmls) if util.skip_read(gmls, draw_and_play.ml_whitepace) != ',': raise error.RunError(error.IFC) bound = draw_and_play.ml_parse_number(gmls) x, y = self.get_window_logical(*self.last_point) self.paint((x, y, False), None, colour, bound, None)
def play(self, mml_list): """ Parse a list of Music Macro Language strings. """ gmls_list = [] for mml in mml_list: gmls = StringIO() # don't convert to uppercase as VARPTR$ elements are case sensitive gmls.write(str(mml)) gmls.seek(0) gmls_list.append(gmls) next_oct = 0 total_time = [0, 0, 0, 0] voices = range(3) while True: if not voices: break for voice in voices: vstate = self.play_state[voice] gmls = gmls_list[voice] c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == '': voices.remove(voice) continue elif c == ';': continue elif c == 'X': # execute substring sub = draw_and_play.ml_parse_string(gmls) pos = gmls.tell() rest = gmls.read() gmls.truncate(pos) gmls.write(str(sub)) gmls.write(rest) gmls.seek(pos) elif c == 'N': note = draw_and_play.ml_parse_number(gmls) dur = vstate.length c = util.skip(gmls, draw_and_play.ml_whitepace).upper() if c == '.': gmls.read(1) dur *= 1.5 if note > 0 and note <= 84: self.play_sound(note_freq[note-1], dur*vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice) total_time[voice] += dur*vstate.tempo elif note == 0: self.play_sound(0, dur*vstate.tempo, vstate.speed, volume=0, voice=voice) total_time[voice] += dur*vstate.tempo elif c == 'L': vstate.length = 1./draw_and_play.ml_parse_number(gmls) elif c == 'T': vstate.tempo = 240./draw_and_play.ml_parse_number(gmls) elif c == 'O': vstate.octave = min(6, max(0, draw_and_play.ml_parse_number(gmls))) elif c == '>': vstate.octave += 1 if vstate.octave > 6: vstate.octave = 6 elif c == '<': vstate.octave -= 1 if vstate.octave < 0: vstate.octave = 0 elif c in ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'P'): note = c dur = vstate.length while True: c = util.skip(gmls, draw_and_play.ml_whitepace).upper() if not c: break elif c == '.': gmls.read(1) dur *= 1.5 elif c in string.digits: numstr = '' while c and c in string.digits: gmls.read(1) numstr += c c = util.skip(gmls, draw_and_play.ml_whitepace) # NOT ml_parse_number, only literals allowed here! length = int(numstr) dur = 1. / float(length) elif c in ('#', '+'): gmls.read(1) note += '#' elif c == '-': gmls.read(1) note += '-' else: break if note == 'P': self.play_sound(0, dur * vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice) total_time[voice] += dur*vstate.tempo else: try: self.play_sound( note_freq[(vstate.octave+next_oct)*12 + notes[note]], dur * vstate.tempo, vstate.speed, volume=vstate.volume, voice=voice) total_time[voice] += dur*vstate.tempo except KeyError: raise error.RunError(error.IFC) next_oct = 0 elif c == 'M': c = util.skip_read(gmls, draw_and_play.ml_whitepace).upper() if c == 'N': vstate.speed = 7./8. elif c == 'L': vstate.speed = 1. elif c == 'S': vstate.speed = 3./4. elif c == 'F': self.foreground = True elif c == 'B': self.foreground = False else: raise error.RunError(error.IFC) elif c == 'V' and (self.capabilities == 'tandy' or (self.capabilities == 'pcjr' and self.sound_on)): vstate.volume = min(15, max(0, draw_and_play.ml_parse_number(gmls))) else: raise error.RunError(error.IFC) max_time = max(total_time) for voice in range(3): if total_time[voice] < max_time: self.play_sound(0, max_time - total_time[voice], 1, 0, voice) if self.foreground: self.wait_all_music()