def post(self, file): ''' Insert a custos. Also add a bounding box for this element. ''' pname = str(self.get_argument("pname", "")) oct = str(self.get_argument("oct", "")) before_id = str(self.get_argument("beforeid", None)) # bounding box ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) custos = self.create_custos(pname, oct) self.insert_custos(custos, before_id) self.add_zone(custos, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) result = {"id": custos.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Move a division before the given element. There is no element to insert before when there is no subsequent staff. In this case, the element is inserted at the end of the last system. Also sets the bounding box information of the new division placement. ''' division_id = str(self.get_argument("id", "")) before_id = str(self.get_argument("beforeid", None)) # bounding box ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) division = self.mei.getElementById(division_id) self.update_zone(division, ulx, uly, lrx, lry) self.reposition_division(division, before_id) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Move the given custos element. Also update the bounding box information. ''' custos_id = str(self.get_argument("id", "")) pname = self.get_argument("pname", None) oct = self.get_argument("oct", None) # bounding box ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) custos = self.mei.getElementById(custos_id) if pname is not None and oct is not None: custos.addAttribute("pname", str(pname)) custos.addAttribute("oct", str(oct)) self.update_or_add_zone(custos, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Insert a doh or fah clef, with a given bounding box. Must also update pitched elements on the staff that affected by this clef being inserted. ''' data = json.loads(self.get_argument("data", "")) shape = str(data["shape"]).upper() line = str(data["line"]) before_id = str(data["beforeid"]) # bounding box ulx = str(data["ulx"]) uly = str(data["uly"]) lrx = str(data["lrx"]) lry = str(data["lry"]) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) clef = self.create_clef(shape, line) self.insert_clef(clef, before_id) self.create_zone(ulx, uly, lrx, lry, clef) self.update_pitched_elements(data["pitchInfo"]) XmlExport.write(self.mei, fname) result = {"id": clef.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Insert a division before the given element. There is one case where there is no element to insert before, when there is no subsequent staff. In this case, the element is inserted at the end of the last system. Also sets the bounding box information of the new punctum. ''' div_type = str(self.get_argument("type", "")) beforeid = str(self.get_argument("beforeid", None)) # bounding box lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) zone = self.create_zone(ulx, uly, lrx, lry) division = self.create_new_division(div_type) self.add_zone(division, zone) self.insert_division(division, beforeid) XmlExport.write(self.mei, fname) result = {"id": division.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Ungroup a neume with the provided ID into puncta. Create bounding box information for each punctum. ''' data = json.loads(self.get_argument("data", "")) nids = str(data["nids"]).split(",") bboxes = data["bbs"] mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) newids = [] for nid, bb in zip(nids, bboxes): newids.append(self.insert_puncta(nid, bb)) self.delete_old_neume(nid) XmlExport.write(self.mei, fname) result = {"nids": newids} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Neumify a group of neumes (with provided ids) and give it the given neume name. Also update bounding box information. ''' nids = str(self.get_argument("nids", "")).split(",") neume_name = str(self.get_argument("name", "")) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) neume = self.create_new_neume(nids, neume_name) self.insert_neume(neume, nids[0]) self.delete_old_neumes(nids) # Bounding box lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) if lrx and lry and ulx and uly: zone = self.get_new_zone(ulx, uly, lrx, lry) self.add_zone(neume, zone) XmlExport.write(self.mei, fname) result = {"nid": neume.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Move a clef on a staff (must not change staff). Updates the bounding box information of the clef and updates the pitch information (pitch name and octave) of all pitched elements on the affected staff. ''' data = json.loads(self.get_argument("data", "")) clef_id = str(data["id"]) # bounding box ulx = str(data["ulx"]) uly = str(data["uly"]) lrx = str(data["lrx"]) lry = str(data["lry"]) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) clef = self.mei.getElementById(clef_id) # update staff line the clef is on clef.addAttribute("line", str(data["line"])) self.update_or_add_zone(clef, ulx, uly, lrx, lry) self.update_pitched_elements(data["pitchInfo"]) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): data = json.loads(self.get_argument("data", "")) nid = str(data["id"]) beforeid = str(data["beforeid"]) # Bounding box ulx = str(data["ulx"]) uly = str(data["uly"]) lrx = str(data["lrx"]) lry = str(data["lry"]) pitch_info = data["pitchInfo"] mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) neume = self.mei.getElementById(nid) if pitch_info is not None: self.neume_pitch_shift(neume, pitch_info) self.reposition_neume(neume, beforeid) self.update_or_add_zone(neume, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def test_readmethod_unicode(self): fn = unicode(os.path.join("test", "testdocs", "beethoven.mei")) doc = XmlImport.read(fn) self.assertNotEqual(None, doc) el = doc.getElementById("d1e41") self.assertEqual("c", el.getAttribute("pname").value) self.assertEqual("4", el.getAttribute("oct").value)
def post(self, file): ''' Change the shape of a given clef. Must also update bounding box data since the glyphs for c and f clefs are different. Must also update pitched elements on the affected staff to correspond with the new clef shape. ''' data = json.loads(self.get_argument("data", "")) clef_id = str(data["id"]) # bounding box ulx = str(data["ulx"]) uly = str(data["uly"]) lrx = str(data["lrx"]) lry = str(data["lry"]) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) clef = self.mei.getElementById(clef_id) # update clef shape clef.addAttribute("shape", str(data["shape"]).upper()) self.update_or_add_zone(clef, ulx, uly, lrx, lry) self.update_pitched_elements(data["pitchInfo"]) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Remove a dot ornament to a given element. ''' neumeid = str(self.get_argument("id", "")) # Bounding box ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) punctum = self.mei.getElementById(neumeid) # check that a punctum element was provided if punctum.getName() == "neume" and punctum.getAttribute("name").getValue() == "punctum": note = punctum.getDescendantsByName("note") if len(note): dot = note[0].getChildrenByName("dot") # if a dot exists if len(dot) == 1: note[0].removeChild(dot[0]) self.update_or_add_zone(punctum, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Remove a dot ornament to a given element. ''' neumeid = str(self.get_argument("id", "")) # Bounding box ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) punctum = self.mei.getElementById(neumeid) # check that a punctum element was provided if punctum.getName() == "neume" and punctum.getAttribute( "name").getValue() == "punctum": note = punctum.getDescendantsByName("note") if len(note): dot = note[0].getChildrenByName("dot") # if a dot exists if len(dot) == 1: note[0].removeChild(dot[0]) self.update_or_add_zone(punctum, ulx, uly, lrx, lry) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Delete a given custos from the document. Also remove the element's bounding box information. ''' custos_id = str(self.get_argument("id", "")) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) self.delete_custos(custos_id) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Delete a division from the MEI document. Special consideration is taken when deleting divisions of form "final" ''' division_ids = str(self.get_argument("ids", "")) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) for id in division_ids.split(","): division = self.mei.getElementById(id) self.delete_division(division) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): ''' Insert a punctum before the given element. There is one case where there is no element to insert before, when there is no subsequent staff. In this case, the element is inserted at the end of the last system. Also sets the bounding box information of the new punctum. ''' beforeid = str(self.get_argument("beforeid", None)) pname = str(self.get_argument("pname", "")) oct = str(self.get_argument("oct", "")) dot_form = self.get_argument("dotform", None) # Bounding box lrx = str(self.get_argument("lrx", None)) lry = str(self.get_argument("lry", None)) ulx = str(self.get_argument("ulx", None)) uly = str(self.get_argument("uly", None)) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) punctum = self.create_new_punctum(pname, oct, dot_form) zone = self.get_new_zone(ulx, uly, lrx, lry) self.add_zone(punctum, zone) if beforeid is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(punctum) else: self.insert_punctum(punctum, beforeid) XmlExport.write(self.mei, fname) result = {"nid": punctum.getId()} self.write(json.dumps(result)) self.set_status(200)
def post(self, file): ''' Delete a doh or fah clef. Must also update pitched elements on the staff that are affected by the deletion of this clef element. ''' clefs_to_delete = json.loads(self.get_argument("data", "")) mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) for c in clefs_to_delete: clef = self.mei.getElementById(str(c["id"])) self.delete_clef(clef) self.update_pitched_elements(c["pitchInfo"]) XmlExport.write(self.mei, fname) self.set_status(200)
def post(self, file): """ Delete one or more <note> or <neume> elements. Pass in an argument called 'id' with a comma separated list of ids of note elements to delete. If the note's surrounding <nc> element is empty after this, remove it. If the nc's surrounding <neume> element is empty, remove it. Remove any <zone> elements whose ids are referenced by removed <neume>s. Does not reduce the size of the bounding box on a <zone> or change the neume type if it now has a different number of <note> elements. """ todelete = self.get_argument("ids", "") mei_directory = os.path.abspath(conf.MEI_DIRECTORY) fname = os.path.join(mei_directory, file) self.mei = XmlImport.read(fname) self.do_delete(todelete) XmlExport.write(self.mei, fname) self.set_status(200)
def __init__(self, filename): self.mei = XmlImport.read(filename) self.filename = filename
def meitoalphatex(mei_path): alphatex = "" # read in the mei document meidoc = XmlImport.read(mei_path) mei = meidoc.getRootElement() ########################### # MetaData # ########################### title = mei.getDescendantsByName("title") if len(title): tex_title = '\\title "%s"\n' % title[0].getValue() alphatex += tex_title pers_name = mei.getDescendantsByName("persName") if len(pers_name): for p in pers_name: role = p.getAttribute("role").value if role == "artist": tex_artist = '\\artist "%s"\n' % p.getValue() alphatex += tex_artist elif role == "tabber": tex_copywrite = '\\copyright "%s"\n' % p.getValue() alphatex += tex_copywrite elif role == "lyricist": tex_words = '\\words "%s"\n' % p.getValue() alphatex += tex_words staff_def = mei.getDescendantsByName("staffDef") if len(staff_def): # capo position if staff_def[0].hasAttribute("tab.capo"): capo = staff_def[0].getAttribute("tab.capo").value if int(capo) > 0: alphatex += "\\capo %s\n" % capo # this doesn't display alphatex += "\\words %s\n" % capo # hack this to display # guitar tuning pnames = ["C", "D", "E", "F", "G", "A", "B"] if staff_def[0].hasAttribute("tab.strings"): strings = staff_def[0].getAttribute("tab.strings").value.split(" ") if len(strings) != 6: raise ValueError("Invalid number of strings: should be 6") # convert pitch names to those used in alphatab (flats vs. sharps) for i in range(len(strings)): pattern = re.compile("^([a-zA-z][#s])") match = pattern.match(strings[i]) if match: mei_pname = match.group() alpha_pname = pnames[pnames.index(mei_pname[0]) + 1 % len(pnames)] + "b" oct = strings[i][-1] # replace string strings[i] = alpha_pname + oct alphatex += "\\tuning %s\n" % " ".join(strings) # set midi instrument to play the tab with # 27 is Electric Guitar Clean alphatex += "\\instrument 27\n" # in alphatex the metadata and body are separated by a period character alphatex += ".\n" ########################### # Body # ########################### measures = mei.getDescendantsByName("measure") alpha_measures = [] for m in measures: measure_events = [] # only parse first staff (instrument), the instrument display staff = m.getChildrenByName("staff")[0] # only parse first layer (assume only one voice) layer = staff.getChildrenByName("layer")[0] score_events = layer.getChildren() for e in score_events: if e.getName() == "chord": # get notes in this chord notes = e.getChildrenByName("note") alpha_notes = [ n.getAttribute("tab.fret").value + "." + n.getAttribute("tab.string").value for n in notes ] alpha_chord = "(" + " ".join(alpha_notes) + ")" measure_events.append(alpha_chord) elif e.getName() == "note": alpha_note = e.getAttribute("tab.fret").value + "." + e.getAttribute("tab.string").value measure_events.append(alpha_note) alpha_measures.append(" ".join(measure_events)) alphatex += " |\n".join(alpha_measures) return alphatex
def meitoalphatex(mei_path): alphatex = '' # read in the mei document meidoc = XmlImport.read(mei_path) mei = meidoc.getRootElement() ########################### # MetaData # ########################### title = mei.getDescendantsByName('title') if len(title): tex_title = "\\title \"%s\"\n" % title[0].getValue() alphatex += tex_title pers_name = mei.getDescendantsByName('persName') if len(pers_name): for p in pers_name: role = p.getAttribute('role').value if role == 'artist': tex_artist = "\\artist \"%s\"\n" % p.getValue() alphatex += tex_artist elif role == 'tabber': tex_copywrite = "\\copyright \"%s\"\n" % p.getValue() alphatex += tex_copywrite elif role == 'lyricist': tex_words = "\\words \"%s\"\n" % p.getValue() alphatex += tex_words staff_def = mei.getDescendantsByName('staffDef') if len(staff_def): # capo position if staff_def[0].hasAttribute('tab.capo'): capo = staff_def[0].getAttribute('tab.capo').value if int(capo) > 0: alphatex += '\\capo %s\n' % capo # this doesn't display alphatex += '\\words %s\n' % capo # hack this to display # guitar tuning pnames = ['C', 'D', 'E', 'F', 'G', 'A', 'B'] if staff_def[0].hasAttribute('tab.strings'): strings = staff_def[0].getAttribute('tab.strings').value.split(' ') if len(strings) != 6: raise ValueError('Invalid number of strings: should be 6') # convert pitch names to those used in alphatab (flats vs. sharps) for i in range(len(strings)): pattern = re.compile('^([a-zA-z][#s])') match = pattern.match(strings[i]) if match: mei_pname = match.group() alpha_pname = pnames[pnames.index(mei_pname[0]) + 1 % len(pnames)] + 'b' oct = strings[i][-1] # replace string strings[i] = alpha_pname + oct alphatex += '\\tuning %s\n' % ' '.join(strings) # set midi instrument to play the tab with # 27 is Electric Guitar Clean alphatex += '\\instrument 27\n' # in alphatex the metadata and body are separated by a period character alphatex += '.\n' ########################### # Body # ########################### measures = mei.getDescendantsByName('measure') alpha_measures = [] for m in measures: measure_events = [] # only parse first staff (instrument), the instrument display staff = m.getChildrenByName('staff')[0] # only parse first layer (assume only one voice) layer = staff.getChildrenByName('layer')[0] score_events = layer.getChildren() for e in score_events: if e.getName() == 'chord': # get notes in this chord notes = e.getChildrenByName('note') alpha_notes = [ n.getAttribute('tab.fret').value + '.' + n.getAttribute('tab.string').value for n in notes ] alpha_chord = '(' + ' '.join(alpha_notes) + ')' measure_events.append(alpha_chord) elif e.getName() == 'note': alpha_note = e.getAttribute( 'tab.fret').value + '.' + e.getAttribute( 'tab.string').value measure_events.append(alpha_note) alpha_measures.append(' '.join(measure_events)) alphatex += ' |\n'.join(alpha_measures) return alphatex