def give_up(self, _o=None): if self.m_t.q_status == self.QSTATUS_WRONG: if len(self.m_t.m_question) == 1: s = utils.int_to_intervalname(self.m_t.m_question[0], False, True) else: s = "+".join([utils.int_to_intervalname(q, True, True) for q in self.m_t.m_question]) self.g_flashbar.push(s) self.m_t.give_up() self.std_buttons_give_up() self.g_input.mark_note(int(self.m_t.m_tonika + self.m_t.m_question[0]), 2)
def export_training_set(self, export_data, export_dir, output_format, name_track_by_question): """ This function requires a program that can create WAV files from MIDI files and MP3 files from WAV. """ def delay(n, tempo): """ tempo is a dict of two integers """ track = mpd.Track() track.set_bpm(*tempo) # self.get_int('config/default_bpm')) track.note(mpd.Rat(n, 4), 80, 0) soundcard.synth.play_track(track) track_idx = 0 num = sum([x['count'] for x in export_data]) # MainWin will set this to True if the user want to cancel # the export. self.m_abort_export = False report = reportlib.Report() report.append(reportlib.Heading(1, "Exported exercises")) table = reportlib.Table() report.append(table) for lesson_info in export_data: filename = lesson_info['filename'] module = lessonfile.infocache.get(filename, 'module') if module not in self.m_teachers: self.create_teacher(module) p = self.m_teachers[module].lessonfileclass() p.parse_file(lessonfile.uri_expand(filename)) for c in range(lesson_info['count']): trackname = "track-%i" if module == 'idbyname': p.select_random_question() if p.header.lesson_heading: s = p.header.lesson_heading else: s = p.header.title table.append_row("%i" % track_idx, p.get_question().name, s) if name_track_by_question: trackname = "%s-%%i" % p.get_name() soundcard.start_export(os.path.join( export_dir, "%s.mid" % trackname % track_idx)) for n in range(lesson_info.get('repeat', 1)): p.play_question() if n != lesson_info.get('repeat', 1) - 1: if 'delay' in lesson_info: delay(lesson_info['delay'], p.get_tempo()) soundcard.end_export() elif module in ('melodicinterval', 'harmonicinterval'): t = self.m_teachers[module] t.set_lessonfile(filename) t.start_practise() t.new_question("c", "c''") t.q_status = t.QSTATUS_SOLVED try: table.append_row("%i" % track_idx, "%s" % utils.int_to_intervalname(t.m_interval)) if name_track_by_question: trackname = "%%i-%s.mid" % utils.int_to_intervalname(t.m_interval) except AttributeError: table.append_row("%i" % track_idx, "%s" % (" + ".join([utils.int_to_intervalname(q, False, True) for q in t.m_question]))) if name_track_by_question: trackname = "%%i-%s.mid" % ("+".join([utils.int_to_intervalname(q, False, True) for q in t.m_question])) soundcard.start_export(os.path.join( export_dir, "%s.mid" % trackname % track_idx)) for n in range(lesson_info.get('repeat', 1)): t.play_question() if n != lesson_info.get('repeat', 1) - 1: if 'delay' in lesson_info: delay(lesson_info['delay'], (self.get_int('config/default_bpm'), 4)) soundcard.end_export() else: logging.warning("export_training_set:ignoring exercise with module='%s'", module) ##### def do_convert(from_format, to_format): """ Return False if we think the convert failed. """ app_cfg_name = "app/%s_to_%s_cmd" % (from_format, to_format) if from_format == 'midi': from_ext = 'mid' else: from_ext = from_format to_ext = to_format if not cfg.get_string(app_cfg_name): solfege.win.display_error_message2("Config variable not defined", "The missing or empty variable was '%s'" % app_cfg_name) return False try: inout = { 'in': os.path.join(export_dir, "%s.%s" % (trackname % track_idx, from_ext)), 'out': os.path.join(export_dir, "%s.%s" % (trackname % track_idx, to_ext))} opts = cfg.get_string(app_cfg_name + '_options').split(" ") opts = [x % inout for x in opts] # For some reasong setting the executable arg does # not work for Python 2.5.2 try: subprocess.call( [cfg.get_string(app_cfg_name)] + opts) except OSError as e: raise osutils.BinaryForMediaConvertorException(app_cfg_name, cfg.get_string(app_cfg_name), e) if os.path.exists(os.path.join(export_dir, "%s.%s" % (trackname % track_idx, to_ext))): os.remove(os.path.join(export_dir, "%s.%s" % (trackname % track_idx, from_ext))) else: # This means that the program failed to generate # the WAV file. We set output_format to 'midi' # because we don't want to display this error for # every single file. output_format = 'midi' solfege.win.display_error_message2("External program must have failed", "The file in %(from)s format was not generated from the %(to)s file as expected. Please check your setup in the preferences window (CTRL-F12)." % {'to': to_format.upper(), 'from': from_format.upper()}) except (TypeError, KeyError): solfege.win.display_error_message2("%(from)s to %(to)s config error", "There was a format string error. Will not generate WAV files. Please check the app/midi_to_wav_cmd config variable." % {'from': from_format, 'to': to_format}) output_format = 'midi' return True ##### if output_format in ('mp3', 'wav', 'ogg'): do_convert('midi', 'wav') if output_format in ('mp3', 'ogg'): if not do_convert('wav', output_format): output_format = 'wav' track_idx += 1 yield 1.0 * track_idx / num if self.m_abort_export: del self.m_abort_export return reportlib.HtmlReport(report, os.path.join(export_dir, "toc.html"))
def click_on_interval(self, mouse_button, interval, midi_int): """The key bindings are also directed here. """ if mouse_button == 3 and not solfege.app.m_test_mode \ and self.get_int('number_of_intervals') == 1: if not self.m_t.m_tonika: return i = mpd.Interval() if (not midi_int # buttons interface does not set midi_int. And # since it assumes all intervals go up, we have # to check and set the direction. and self.m_t.m_question[0] < 0): i.set_from_int(-interval) else: i.set_from_int(interval) n = self.m_t.m_tonika + i track = utils.new_track() track.note(4, self.m_t.m_tonika.semitone_pitch()) track.note(4, n.semitone_pitch()) soundcard.synth.play_track(track) return if mouse_button not in (1, self.keyboard_accel): return if solfege.app.m_test_mode and self.m_t.q_status == self.QSTATUS_NO: self.g_flashbar.flash(_("Click 'Start test' to begin.")) return if solfege.app.m_test_mode: self.g_new.hide() if self.m_t.q_status == self.QSTATUS_NO: self.g_flashbar.flash(_("Click 'New interval' to begin.")) return if midi_int: # midi_int is only set when we use some of the instrument widgets, # not when we use the buttons interface. utils.play_note(4, midi_int) if self.m_t.q_status == self.QSTATUS_GIVE_UP: return if self.m_t.q_status == self.QSTATUS_SOLVED: self.g_flashbar.flash( _("You have already identified this interval")) return if not (mpd.interval.min_interval < interval <= mpd.interval.max_interval): self.g_flashbar.flash( _("Ignoring intervals greater than double octave.")) self.g_input.forget_last_tone() return self.m_answer.append(interval) d = self.m_t.m_question[len(self.m_answer) - 1] md = d / abs(d) if self.g_input.know_directions(): md = 1 if not self.msg: self.msg = utils.int_to_intervalname(interval * md, 1, 1) + "+ ..." else: self.msg = self.msg[:-4] self.msg = self.msg + utils.int_to_intervalname( interval * md, 1, 1) + "+ ..." self.g_flashbar.push(self.msg) if len(self.m_answer) == self.m_number_of_intervals_in_question: if self.m_t.guess_answer(self.m_answer, self.g_input.know_directions()): self.g_flashbar.clear() self.g_flashbar.flash(_("Correct")) self.std_buttons_answer_correct() else: self.g_flashbar.clear() self.g_flashbar.flash(_("Wrong")) if self.get_bool( "config/auto_repeat_question_if_wrong_answer"): self.m_t.play_question() self.std_buttons_answer_wrong() self.m_answer = [] self.g_input.set_first_note(self.m_t.m_tonika) self.msg = "" if solfege.app.m_test_mode and self.m_t.m_P.is_test_complete(): self.do_test_complete() return
def key_to_pretty_name(self, key): return utils.int_to_intervalname(int(key), 1, 0)
def click_on_interval(self, mouse_button, interval, midi_int): """The key bindings are also directed here. """ if mouse_button == 3 and not solfege.app.m_test_mode \ and self.get_int('number_of_intervals') == 1: if not self.m_t.m_tonika: return i = mpd.Interval() if (not midi_int # buttons interface does not set midi_int. And # since it assumes all intervals go up, we have # to check and set the direction. and self.m_t.m_question[0] < 0): i.set_from_int(-interval) else: i.set_from_int(interval) n = self.m_t.m_tonika + i track = utils.new_track() track.note(4, self.m_t.m_tonika.semitone_pitch()) track.note(4, n.semitone_pitch()) soundcard.synth.play_track(track) return if mouse_button not in (1, self.keyboard_accel): return if solfege.app.m_test_mode and self.m_t.q_status == self.QSTATUS_NO: self.g_flashbar.flash(_("Click 'Start test' to begin.")) return if solfege.app.m_test_mode: self.g_new.hide() if self.m_t.q_status == self.QSTATUS_NO: self.g_flashbar.flash(_("Click 'New interval' to begin.")) return if midi_int: # midi_int is only set when we use some of the instrument widgets, # not when we use the buttons interface. utils.play_note(4, midi_int) if self.m_t.q_status == self.QSTATUS_GIVE_UP: return if self.m_t.q_status == self.QSTATUS_SOLVED: self.g_flashbar.flash(_("You have already identified this interval")) return if not (-17 < interval < 17): self.g_flashbar.flash(_("Ignoring intervals greater than major tenth.")) self.g_input.forget_last_tone() return self.m_answer.append(interval) d = self.m_t.m_question[len(self.m_answer)-1] md = d / abs(d) if self.g_input.know_directions(): md = 1 if not self.msg: self.msg = utils.int_to_intervalname(interval * md, 1, 1) + "+ ..." else: self.msg = self.msg[:-4] self.msg = self.msg + utils.int_to_intervalname(interval * md, 1, 1) + "+ ..." self.g_flashbar.push(self.msg) if len(self.m_answer) == self.m_number_of_intervals_in_question: if self.m_t.guess_answer(self.m_answer, self.g_input.know_directions()): self.g_flashbar.clear() self.g_flashbar.flash(_("Correct")) self.std_buttons_answer_correct() else: self.g_flashbar.clear() self.g_flashbar.flash(_("Wrong")) if self.get_bool("config/auto_repeat_question_if_wrong_answer"): self.m_t.play_question() self.std_buttons_answer_wrong() self.m_answer = [] self.g_input.set_first_note(self.m_t.m_tonika) self.msg = "" if solfege.app.m_test_mode and self.m_t.m_P.is_test_complete(): self.do_test_complete() return
def export_training_set(self, export_data, export_dir, output_format, name_track_by_question): """ This function requires a program that can create WAV files from MIDI files and MP3 files from WAV. """ def delay(n, tempo): """ tempo is a dict of two integers """ track = mpd.Track() track.set_bpm(*tempo) #self.get_int('config/default_bpm')) track.note(mpd.Rat(n, 4), 80, 0) soundcard.synth.play_track(track) track_idx = 0 num = sum([x['count'] for x in export_data]) # MainWin will set this to True if the user want to cancel # the export. self.m_abort_export = False report = reportlib.Report() report.append(reportlib.Heading(1, "Exported exercises")) table = reportlib.Table() report.append(table) for lesson_info in export_data: filename = lesson_info['filename'] module = lessonfile.infocache.get(filename, 'module') if module not in self.m_teachers: self.create_teacher(module) p = self.m_teachers[module].lessonfileclass() p.parse_file(lessonfile.uri_expand(filename)) for c in range(lesson_info['count']): trackname = "track-%i" if module == 'idbyname': p.select_random_question() if p.header.lesson_heading: s = p.header.lesson_heading else: s = p.header.title table.append_row("%i" % track_idx, p.get_question().name, s) if name_track_by_question: trackname = "%s-%%i" % p.get_name() soundcard.start_export( os.path.join(export_dir, "%s.mid" % trackname % track_idx)) for n in range(lesson_info.get('repeat', 1)): p.play_question() if n != lesson_info.get('repeat', 1) - 1: if 'delay' in lesson_info: delay(lesson_info['delay'], p.get_tempo()) soundcard.end_export() elif module in ('melodicinterval', 'harmonicinterval'): t = self.m_teachers[module] t.set_lessonfile(filename) t.start_practise() t.new_question("c", "c''") t.q_status = t.QSTATUS_SOLVED try: table.append_row( "%i" % track_idx, "%s" % utils.int_to_intervalname(t.m_interval)) if name_track_by_question: trackname = "%%i-%s.mid" % utils.int_to_intervalname( t.m_interval) except AttributeError: table.append_row( "%i" % track_idx, "%s" % (" + ".join([ utils.int_to_intervalname(q, False, True) for q in t.m_question ]))) if name_track_by_question: trackname = "%%i-%s.mid" % ("+".join([ utils.int_to_intervalname(q, False, True) for q in t.m_question ])) soundcard.start_export( os.path.join(export_dir, "%s.mid" % trackname % track_idx)) for n in range(lesson_info.get('repeat', 1)): t.play_question() if n != lesson_info.get('repeat', 1) - 1: if 'delay' in lesson_info: delay(lesson_info['delay'], (self.get_int('config/default_bpm'), 4)) soundcard.end_export() else: logging.warning( "export_training_set:ignoring exercise with module='%s'", module) ##### def do_convert(from_format, to_format): """ Return False if we think the convert failed. """ app_cfg_name = "app/%s_to_%s_cmd" % (from_format, to_format) if from_format == 'midi': from_ext = 'mid' else: from_ext = from_format to_ext = to_format if not cfg.get_string(app_cfg_name): solfege.win.display_error_message2( "Config variable not defined", "The missing or empty variable was '%s'" % app_cfg_name) return False try: inout = { 'in': os.path.join( export_dir, "%s.%s" % (trackname % track_idx, from_ext)), 'out': os.path.join( export_dir, "%s.%s" % (trackname % track_idx, to_ext)) } opts = cfg.get_string(app_cfg_name + '_options').split(" ") opts = [x % inout for x in opts] # For some reasong setting the executable arg does # not work for Python 2.5.2 try: subprocess.call([cfg.get_string(app_cfg_name)] + opts) except OSError, e: raise osutils.BinaryForMediaConvertorException( app_cfg_name, cfg.get_string(app_cfg_name), e) if os.path.exists( os.path.join( export_dir, "%s.%s" % (trackname % track_idx, to_ext))): os.remove( os.path.join( export_dir, "%s.%s" % (trackname % track_idx, from_ext))) else: # This means that the program failed to generate # the WAV file. We set output_format to 'midi' # because we don't want to display this error for # every single file. output_format = 'midi' solfege.win.display_error_message2( "External program must have failed", "The file in %(from)s format was not generated from the %(to)s file as expected. Please check your setup in the preferences window (CTRL-F12)." % { 'to': to_format.upper(), 'from': from_format.upper() }) except (TypeError, KeyError): solfege.win.display_error_message2( "%(from)s to %(to)s config error", "There was a format string error. Will not generate WAV files. Please check the app/midi_to_wav_cmd config variable." % { 'from': from_format, 'to': to_format }) output_format = 'midi' return True ##### if output_format in ('mp3', 'wav', 'ogg'): do_convert('midi', 'wav') if output_format in ('mp3', 'ogg'): if not do_convert('wav', output_format): output_format = 'wav' track_idx += 1 yield 1.0 * track_idx / num if self.m_abort_export: del self.m_abort_export return