def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry): ''' Insert a custos. Also add a bounding box for this element. ''' # create custos custos = MeiElement("custos") if pname and oct: custos.addAttribute("pname", pname) custos.addAttribute("oct", oct) # insert the custos if before_id is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(custos) else: before = self.mei.getElementById(str(before_id)) parent = before.getParent() if parent and before: parent.addChildBefore(before, custos) # update the bounding box self.update_or_add_zone(custos, ulx, uly, lrx, lry) result = {"id": custos.getId()} return result
def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry): ''' Insert a custos. Also add a bounding box for this element. ''' # create custos custos = MeiElement("custos") if pname and oct: custos.addAttribute("pname", pname) custos.addAttribute("oct", oct) # insert the custos before = self.mei.getElementById(before_id) # get layer element parent = before.getParent() if parent and before: parent.addChildBefore(before, custos) # update the bounding box self.update_or_add_zone(custos, ulx, uly, lrx, lry) result = {"id": custos.getId()} return result
def insert_clef(self, line, shape, pitch_info, before_id, ulx, uly, lrx, lry): ''' 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. ''' clef = MeiElement("clef") clef.addAttribute("shape", shape) clef.addAttribute("line", line) # perform clef insertion if before_id is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(clef) else: before = self.mei.getElementById(str(before_id)) parent = before.getParent() if parent and before: parent.addChildBefore(before, clef) self.update_or_add_zone(clef, ulx, uly, lrx, lry) if pitch_info: self.update_pitched_elements(pitch_info) result = {"id": clef.getId()} return result
def insert_puncta(self, nid, bboxes): ''' Insert a punctum for each note in the reference neume before the reference neume in the MEI document. ''' ref_neume = self.mei.getElementById(nid) parent = ref_neume.getParent() # get underlying notes notes = ref_neume.getDescendantsByName("note") nids = [] for n, bb in zip(notes, bboxes): punctum = MeiElement("neume") punctum.addAttribute("name", "punctum") nc = MeiElement("nc") nc.addChild(n) punctum.addChild(nc) # add generated punctum id to return to client nids.append(punctum.getId()) # add facs data for the punctum zone = self.get_new_zone(bb["ulx"], bb["uly"], bb["lrx"], bb["lry"]) self.add_zone(punctum, zone) # insert the punctum before the reference neume parent.addChildBefore(ref_neume, punctum) return nids
def insert_custos(self, pname, oct, before_id, ulx, uly, lrx, lry): ''' Insert a custos. Also add a bounding box for this element. ''' # create custos custos = MeiElement("custos") custos.addAttribute("pname", pname) custos.addAttribute("oct", oct) # insert the custos before = self.mei.getElementById(before_id) # get layer element parent = before.getParent() if parent and before: parent.addChildBefore(before, custos) # update the bounding box self.update_or_add_zone(custos, ulx, uly, lrx, lry) result = {"id": custos.getId()} return result
def add_zone(self, custos, ulx, uly, lrx, lry): zone = MeiElement("zone") zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry) custos.addAttribute("facs", zone.getId()) surfaces = self.mei.getElementsByName("surface") if len(surfaces): surfaces[0].addChild(zone)
def update_or_add_zone(self, clef, ulx, uly, lrx, lry): facsid = clef.getAttribute("facs").value if facsid: zone = self.mei.getElementById(facsid) else: zone = MeiElement("zone") clef.addAttribute("facs", zone.getId()) surfaces = self.mei.getElementsByName("surface") if len(surfaces): surfaces[0].addChild(zone) zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry)
def update_zone(self, division, ulx, uly, lrx, lry): facs_id = division.getAttribute("facs").getValue() if facs_id: zone = self.mei.getElementById(facs_id) else: zone = MeiElement("zone") division.addAttribute("facs", zone.getId()) surfaces = self.mei.getElementsByName("surface") if len(surfaces): surfaces[0].addChild(zone) zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry)
def insert_punctum(self, before_id, pname, oct, dot_form, ulx, uly, lrx, lry): ''' 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. ''' # create the punctum punctum = MeiElement("neume") punctum.addAttribute("name", "punctum") nc = MeiElement("nc") note = MeiElement("note") if pname and oct: note.addAttribute("pname", pname) note.addAttribute("oct", oct) # add ornamentation if dot_form is not None: dot = MeiElement("dot") dot.addAttribute("form", str(dot_form)) note.addChild(dot) punctum.addChild(nc) nc.addChild(note) # create bounding box self.update_or_add_zone(punctum, ulx, uly, lrx, lry) # perform the insertion if before_id is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(punctum) else: before = self.mei.getElementById(before_id) # get layer element parent = before.getParent() if parent and before: parent.addChildBefore(before, punctum) # get the generated ID for the client result = {"id": punctum.getId()} return result
def insert_punctum(self, before_id, pname, oct, dot_form, ulx, uly, lrx, lry): ''' 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. ''' # create the punctum punctum = MeiElement("neume") punctum.addAttribute("name", "punctum") nc = MeiElement("nc") note = MeiElement("note") note.addAttribute("pname", pname) note.addAttribute("oct", oct) # add ornamentation if dot_form is not None: dot = MeiElement("dot") dot.addAttribute("form", str(dot_form)) note.addChild(dot) punctum.addChild(nc) nc.addChild(note) # create bounding box self.update_or_add_zone(punctum, ulx, uly, lrx, lry) # perform the insertion if before_id is None: # get last layer layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(punctum) else: before = self.mei.getElementById(before_id) # get layer element parent = before.getParent() if parent and before: parent.addChildBefore(before, punctum) # get the generated ID for the client result = {"id": punctum.getId()} return result
def insert_system(self, page_id, ulx, uly, lrx, lry): ''' Insert a system and its bounding box. ''' # create system system = MeiElement("system") # add system to page page = self.mei.getElementById(page_id) page.addChild(system) # update system bounding box self.update_or_add_zone(system, ulx, uly, lrx, lry) result = {"id": system.getId()} return result
def ungroup(self, ids, bboxes): ''' Ungroup a neume with the provided ids into puncta. Create bounding box information for each punctum. ''' newids = [] for id, bbox in zip(ids, bboxes): ref_neume = self.mei.getElementById(id) parent = ref_neume.getParent() # get underlying notes notes = ref_neume.getDescendantsByName("note") nids = [] for n, bb in zip(notes, bbox): punctum = MeiElement("neume") punctum.addAttribute("name", "punctum") nc = MeiElement("nc") nc.addChild(n) punctum.addChild(nc) # add generated punctum id to return to client nids.append(punctum.getId()) # add facs data for the punctum self.update_or_add_zone(punctum, str(bb["ulx"]), str(bb["uly"]), str(bb["lrx"]), str(bb["lry"])) # insert the punctum before the reference neume parent.addChildBefore(ref_neume, punctum) newids.append(nids) # delete the old neume neume = self.mei.getElementById(id) if neume: # remove bounding box information self.remove_zone(neume) # now remove the neume neume.getParent().removeChild(neume) result = {"nids": newids} return result
def generate_zone(surface, bb): ''' Given a bounding box, generates a zone element, adds it to the given @surface, and returns its ID. ''' el = MeiElement('zone') surface.addChild(el) # could be cleaner, but necessary so that we don't add extra attributes from @bb attribs = { 'ulx': bb['ulx'], 'uly': bb['uly'], 'lrx': bb['lrx'], 'lry': bb['lry'], } el = add_attributes_to_element(el, attribs) return el.getId()
def update_or_add_zone(self, element, ulx, uly, lrx, lry): ''' Update the bounding box information attached to an element ''' facsid = element.getAttribute("facs") if facsid: zone = self.mei.getElementById(facsid.getValue()) else: zone = MeiElement("zone") element.addAttribute("facs", zone.getId()) surfaces = self.mei.getElementsByName("surface") if len(surfaces): surfaces[0].addChild(zone) zone.addAttribute("ulx", ulx) zone.addAttribute("uly", uly) zone.addAttribute("lrx", lrx) zone.addAttribute("lry", lry)
def insert_system_break(self, system_id, order_number, next_sb_id): ''' Insert a system break before the associated system break, associate it with a system ID, and give it an order number. ''' # create system sb = MeiElement("sb") sb.addAttribute("n", str(order_number)) sb.addAttribute("systemref", str(system_id)) # Perform insertion. If we have no next reference, just add to last layer. if next_sb_id is None: layers = self.mei.getElementsByName("layer") if len(layers): layers[-1].addChild(sb) else: next_sb = self.mei.getElementById(str(next_sb_id)) parent = next_sb.getParent() if parent and next_sb: parent.addChildBefore(next_sb, sb) result = {"id": sb.getId()} return result
def insert_division(self, before_id, type, ulx, uly, lrx, lry): ''' 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 division. ''' division = MeiElement("division") division.addAttribute("form", type) self.update_or_add_zone(division, ulx, uly, lrx, lry) before = self.mei.getElementById(before_id) # get layer element layer = before.getParent() if layer and before: layer.addChildBefore(before, division) if type == "final": # if final division, close layer and staff staff = layer.getParent() section_parent = staff.getParent() # create new staff and layer new_staff = MeiElement("staff") new_layer = MeiElement("layer") new_layer.addAttribute("n", "1") # get elements after "before element" to move element_peers = before.getPeers() e_ind = list(element_peers).index(before) for e in element_peers[e_ind:]: # add element to the new staff/layer new_layer.addChild(e) # remove element from the current staff/layer layer.removeChild(e) new_staff.addChild(new_layer) # insert new staff into the document staves = section_parent.getChildrenByName("staff") s_ind = list(staves).index(staff) if s_ind + 1 < len(staves): # there are staff elements after the new staff to insert before_staff = staves[s_ind + 1] # update staff numbers staves for i, s in enumerate(staves[s_ind + 1:]): s.addAttribute("n", str(s_ind + i + 3)) section_parent.addChildBefore(before_staff, new_staff) else: section_parent.addChild(new_staff) new_staff.addAttribute("n", str(s_ind + 2)) # insert and update staff definitions staff_group = self.mei.getElementsByName("staffGrp") if len(staff_group): staff_defs = staff_group[0].getChildrenByName("staffDef") if len(staff_defs) == len(staves): staff_def = MeiElement("staffDef") staff_def.addAttribute("n", str(s_ind + 2)) if s_ind + 1 < len(staff_defs): before_staff_def = staff_defs[s_ind + 1] # update staff number for all following staff defs for i, sd in enumerate(staff_defs[s_ind + 1:]): sd.addAttribute("n", str(s_ind + i + 3)) staff_group[0].addChildBefore( before_staff_def, staff_def) else: staff_group[0].addChild(staff_def) result = {"id": division.getId()} return result
def _create_header(self, rodan_version='0.1'): ''' Create a meiHead element ''' mei_head = MeiElement('meiHead') today = datetime.date.today().isoformat() app_name = 'RODAN/barlineFinder' # file description file_desc = MeiElement('fileDesc') title_stmt = MeiElement('titleStmt') title = MeiElement('title') resp_stmt = MeiElement('respStmt') corp_name = MeiElement('corpName') corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)') title_stmt.addChild(title) title_stmt.addChild(resp_stmt) resp_stmt.addChild(corp_name) pub_stmt = MeiElement('pubStmt') resp_stmt = MeiElement('respStmt') corp_name = MeiElement('corpName') corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)') pub_stmt.addChild(resp_stmt) resp_stmt.addChild(corp_name) mei_head.addChild(file_desc) file_desc.addChild(title_stmt) file_desc.addChild(pub_stmt) # encoding description encoding_desc = MeiElement('encodingDesc') app_info = MeiElement('appInfo') application = MeiElement('application') application.addAttribute('version', rodan_version) name = MeiElement('name') name.setValue(app_name) ptr = MeiElement('ptr') ptr.addAttribute('target', 'https://github.com/DDMAL/barlineFinder') mei_head.addChild(encoding_desc) encoding_desc.addChild(app_info) app_info.addChild(application) application.addChild(name) application.addChild(ptr) # revision description revision_desc = MeiElement('revisionDesc') change = MeiElement('change') change.addAttribute('n', '1') resp_stmt = MeiElement('respStmt') corp_name = MeiElement('corpName') corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)') change_desc = MeiElement('changeDesc') ref = MeiElement('ref') ref.addAttribute('target', '#'+application.getId()) ref.setValue(app_name) ref.setTail('.') p = MeiElement('p') p.addChild(ref) p.setValue('Encoded using ') date = MeiElement('date') date.setValue(today) mei_head.addChild(revision_desc) revision_desc.addChild(change) change.addChild(resp_stmt) resp_stmt.addChild(corp_name) change.addChild(change_desc) change_desc.addChild(p) change.addChild(date) return mei_head
def neumify(self, ids, type_id, head_shapes, ulx, uly, lrx, lry): ''' Neumify a group of neumes (with provided ids) and give it the given neume name. Also update bounding box information. ''' # get neume name and variant from type id type_split = type_id.split(".") if type_split[-1].isdigit(): type_split.pop() if len(type_split) == 1: attrs = [MeiAttribute("name", type_split[0])] else: variant = " ".join(type_split[1:]) attrs = [ MeiAttribute("name", type_split[0]), MeiAttribute("variant", variant) ] new_neume = MeiElement("neume") new_neume.setAttributes(attrs) ncs = [] cur_nc = None iNote = 0 for id in ids: ref_neume = self.mei.getElementById(str(id)) if ref_neume: # get underlying notes notes = ref_neume.getDescendantsByName("note") for n in notes: head = str(head_shapes[iNote]) # check if a new nc must be opened if head == 'punctum' and cur_nc != 'punctum': ncs.append(MeiElement("nc")) cur_nc = head elif head == 'punctum_inclinatum' and cur_nc != 'punctum_inclinatum': new_nc = MeiElement("nc") new_nc.addAttribute("inclinatum", "true") ncs.append(new_nc) cur_nc = head elif head == 'punctum_inclinatum_parvum' and cur_nc != 'punctum_inclinatum_parvum': new_nc = MeiElement("nc") new_nc.addAttribute("inclinatum", "true") new_nc.addAttribute("deminutus", "true") ncs.append(new_nc) cur_nc = head elif head == 'quilisma' and cur_nc != 'quilisma': new_nc = MeiElement("nc") new_nc.addAttribute("quilisma", "true") ncs.append(new_nc) cur_nc = head elif cur_nc is None: ncs.append(MeiElement("nc")) cur_nc = 'punctum' ncs[-1].addChild(n) iNote += 1 new_neume.setChildren(ncs) # insert the new neume before = self.mei.getElementById(ids[0]) parent = before.getParent() if before and parent: parent.addChildBefore(before, new_neume) # remove the old neumes from the mei document for id in ids: neume = self.mei.getElementById(str(id)) if neume: # remove facs data facs = neume.getAttribute("facs") if facs: facsid = facs.value # Remove the zone if it exists zone = self.mei.getElementById(str(facsid)) if zone and zone.name == "zone": zone.parent.removeChild(zone) # now remove the neume neume.parent.removeChild(neume) # update bounding box data self.update_or_add_zone(new_neume, ulx, uly, lrx, lry) result = {"id": new_neume.getId()} return result
def write_mei(self, notes, audio_path, output_path=None): from pymei import MeiDocument, MeiElement, XmlExport # combine features with the same timestamps note_events = [] for n in notes: ts = n.timestamp.toSeconds() note_num = int(n.values[0]) + 1 # it looks like everything is transposed a semitone down ... transposing up # if the last timestamp is equal to this timestamp, combine into a chord if len(note_events) > 0 and note_events[-1][0] == ts: note_events[-1][1].append(note_num) else: note_events.append([ts, [note_num]]) # sort by timestamp in ascending order note_events = sorted(note_events, key=lambda n: n[0]) # begin constructing mei document meidoc = MeiDocument() mei = MeiElement('mei') meidoc.setRootElement(mei) music = MeiElement('music') timeline = MeiElement('timeline') timeline.addAttribute('avref', str(audio_path)) body = MeiElement('body') mdiv = MeiElement('mdiv') score = MeiElement('score') score_def = MeiElement('scoreDef') # assume 4/4 time signature meter_count = 4 meter_unit = 4 score_def.addAttribute('meter.count', str(meter_count)) score_def.addAttribute('meter.unit', str(meter_unit)) staff_def = MeiElement('staffDef') staff_def.addAttribute('n', '1') staff_def.addAttribute('label.full', 'Electric Guitar') staff_def.addAttribute('clef.shape', 'TAB') instr_def = MeiElement('instrDef') instr_def.addAttribute('n', 'Electric_Guitar') instr_def.addAttribute('midi.channel', '1') instr_def.addAttribute('midi.instrnum', '28') mei.addChild(music) music.addChild(timeline) music.addChild(body) body.addChild(mdiv) mdiv.addChild(score) score.addChild(score_def) score_def.addChild(staff_def) staff_def.addChild(instr_def) section = MeiElement('section') score.addChild(section) # another score def score_def = MeiElement('scoreDef') score_def.addAttribute('meter.count', str(meter_count)) score_def.addAttribute('meter.unit', str(meter_unit)) section.addChild(score_def) # start writing pitches to file note_container = None for i, note_event in enumerate(note_events): if i % meter_count == 0: measure = MeiElement('measure') measure.addAttribute('n', str(int(i/meter_count + 1))) staff = MeiElement('staff') staff.addAttribute('n', '1') layer = MeiElement('layer') layer.addAttribute('n', '1') section.addChild(measure) measure.addChild(staff) staff.addChild(layer) note_container = layer ts = note_event[0] when = MeiElement('when') if i == 0: timeline.addAttribute('origin', when.getId()) when.addAttribute('absolute', str(ts)) timeline.addChild(when) notes = note_event[1] if len(notes) > 1: chord = MeiElement('chord') chord.addAttribute('when', when.getId()) for n in notes: note = MeiElement('note') note_info = PolyTrans.midi_map[n] pname = note_info[0] oct = note_info[1] note.addAttribute('pname', pname[0]) note.addAttribute('oct', str(oct)) if len(pname) > 1 and pname[-1] == '#': # there is an accidental note.addAttribute('accid.ges', 's') note.addAttribute('dur', str(meter_unit)) chord.addChild(note) note_container.addChild(chord) else: n = notes[0] note = MeiElement('note') note.addAttribute('when', when.getId()) note_info = PolyTrans.midi_map[n] pname = note_info[0] oct = note_info[1] note.addAttribute('pname', pname[0]) note.addAttribute('oct', str(oct)) if len(pname) > 1 and pname[-1] == '#': # there is an accidental note.addAttribute('accid.ges', 's') note.addAttribute('dur', str(meter_unit)) note_container.addChild(note) if output_path is not None: XmlExport.meiDocumentToFile(meidoc, output_path) else: return XmlExport.meiDocumentToText(meidoc)
def neumify(self, ids, type_id, liquescence, head_shapes, ulx, uly, lrx, lry): ''' Neumify a group of neumes (with provided ids) and give it the given neume name. Also update bounding box information. ''' # get neume name and variant from type id type_split = type_id.split(".") if type_split[-1].isdigit(): type_split.pop() if len(type_split) == 1: attrs = [MeiAttribute("name", type_split[0])] else: variant = " ".join(type_split[1:]) attrs = [MeiAttribute("name", type_split[0]), MeiAttribute("variant", variant)] ''' # need to determine how to encode these different types of liquescence in the MEI document if liquescence: if liquescence == "alt": attrs.append(MeiAttribute("variant", "liquescence")) elif liquescence == "aug": attrs.append(MeiAttribute("variant", "liquescence_aug")) elif liquescence == "dim": attrs.append(MeiAttribute("variant", "liquescence_dim")) ''' new_neume = MeiElement("neume") new_neume.setAttributes(attrs) ncs = [] cur_nc = None iNote = 0 for id in ids: ref_neume = self.mei.getElementById(str(id)) if ref_neume: # get underlying notes notes = ref_neume.getDescendantsByName("note") for n in notes: head = str(head_shapes[iNote]) # check if a new nc must be opened if head == 'punctum' and cur_nc != 'punctum': ncs.append(MeiElement("nc")) cur_nc = head elif head == 'punctum_inclinatum' and cur_nc != 'punctum_inclinatum': new_nc = MeiElement("nc") new_nc.addAttribute("inclinatum", "true") ncs.append(new_nc) cur_nc = head elif head == 'punctum_inclinatum_parvum' and cur_nc != 'punctum_inclinatum_parvum': new_nc = MeiElement("nc") new_nc.addAttribute("inclinatum", "true") new_nc.addAttribute("deminutus", "true") ncs.append(new_nc) cur_nc = head elif head == 'quilisma' and cur_nc != 'quilisma': new_nc = MeiElement("nc") new_nc.addAttribute("quilisma", "true") ncs.append(new_nc) cur_nc = head elif cur_nc is None: ncs.append(MeiElement("nc")) cur_nc = 'punctum' ncs[-1].addChild(n) iNote += 1 new_neume.setChildren(ncs) # insert the new neume before = self.mei.getElementById(ids[0]) parent = before.getParent() if before and parent: parent.addChildBefore(before, new_neume) # remove the old neumes from the mei document for id in ids: neume = self.mei.getElementById(str(id)) if neume: # remove facs data facs = neume.getAttribute("facs") if facs: facsid = facs.value # Remove the zone if it exists zone = self.mei.getElementById(str(facsid)) if zone and zone.name == "zone": zone.parent.removeChild(zone) # now remove the neume neume.parent.removeChild(neume) # update bounding box data self.update_or_add_zone(new_neume, ulx, uly, lrx, lry) result = {"id": new_neume.getId()} return result
def _create_header(self, rodan_version='0.1'): ''' Create a meiHead element ''' mei_head = MeiElement('meiHead') today = datetime.date.today().isoformat() app_name = 'RODAN/barlineFinder' # file description file_desc = MeiElement('fileDesc') title_stmt = MeiElement('titleStmt') title = MeiElement('title') resp_stmt = MeiElement('respStmt') corp_name = MeiElement('corpName') corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)') title_stmt.addChild(title) title_stmt.addChild(resp_stmt) resp_stmt.addChild(corp_name) pub_stmt = MeiElement('pubStmt') resp_stmt = MeiElement('respStmt') corp_name = MeiElement('corpName') corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)') pub_stmt.addChild(resp_stmt) resp_stmt.addChild(corp_name) mei_head.addChild(file_desc) file_desc.addChild(title_stmt) file_desc.addChild(pub_stmt) # encoding description encoding_desc = MeiElement('encodingDesc') app_info = MeiElement('appInfo') application = MeiElement('application') application.addAttribute('version', rodan_version) name = MeiElement('name') name.setValue(app_name) ptr = MeiElement('ptr') ptr.addAttribute('target', 'https://github.com/DDMAL/barlineFinder') mei_head.addChild(encoding_desc) encoding_desc.addChild(app_info) app_info.addChild(application) application.addChild(name) application.addChild(ptr) # revision description revision_desc = MeiElement('revisionDesc') change = MeiElement('change') change.addAttribute('n', '1') resp_stmt = MeiElement('respStmt') corp_name = MeiElement('corpName') corp_name.setValue('Distributed Digital Music Archives and Libraries Lab (DDMAL)') change_desc = MeiElement('changeDesc') ref = MeiElement('ref') ref.addAttribute('target', '#' + application.getId()) ref.setValue(app_name) ref.setTail('.') p = MeiElement('p') p.addChild(ref) p.setValue('Encoded using ') date = MeiElement('date') date.setValue(today) mei_head.addChild(revision_desc) revision_desc.addChild(change) change.addChild(resp_stmt) resp_stmt.addChild(corp_name) change.addChild(change_desc) change_desc.addChild(p) change.addChild(date) return mei_head
def insert_division(self, before_id, type, ulx, uly, lrx, lry): ''' 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 division. ''' division = MeiElement("division") division.addAttribute("form", type) self.update_or_add_zone(division, ulx, uly, lrx, lry) before = self.mei.getElementById(before_id) # get layer element layer = before.getParent() if layer and before: layer.addChildBefore(before, division) if type == "final": # if final division, close layer and staff staff = layer.getParent() section_parent = staff.getParent() # create new staff and layer new_staff = MeiElement("staff") new_layer = MeiElement("layer") new_layer.addAttribute("n", "1") # get elements after "before element" to move element_peers = before.getPeers() e_ind = list(element_peers).index(before) for e in element_peers[e_ind:]: # add element to the new staff/layer new_layer.addChild(e) # remove element from the current staff/layer layer.removeChild(e) new_staff.addChild(new_layer) # insert new staff into the document staves = section_parent.getChildrenByName("staff") s_ind = list(staves).index(staff) if s_ind+1 < len(staves): # there are staff elements after the new staff to insert before_staff = staves[s_ind+1] # update staff numbers staves for i, s in enumerate(staves[s_ind+1:]): s.addAttribute("n", str(s_ind+i+3)) section_parent.addChildBefore(before_staff, new_staff) else: section_parent.addChild(new_staff) new_staff.addAttribute("n", str(s_ind+2)) # insert and update staff definitions staff_group = self.mei.getElementsByName("staffGrp") if len(staff_group): staff_defs = staff_group[0].getChildrenByName("staffDef") if len(staff_defs) == len(staves): staff_def = MeiElement("staffDef") staff_def.addAttribute("n", str(s_ind+2)) if s_ind+1 < len(staff_defs): before_staff_def = staff_defs[s_ind+1] # update staff number for all following staff defs for i, sd in enumerate(staff_defs[s_ind+1:]): sd.addAttribute("n", str(s_ind+i+3)) staff_group[0].addChildBefore(before_staff_def, staff_def) else: staff_group[0].addChild(staff_def) result = {"id": division.getId()} return result