def render(self, provides_own_theme_data=False): """ The render method is what generates the frames for the screen and obtains the display information from the renderer. At this point all slides are built for the given display size. :param provides_own_theme_data: This switch disables the usage of the item's theme. However, this is disabled by default. If this is used, it has to be taken care, that the renderer knows the correct theme data. However, this is needed for the theme manager. """ log.debug('Render called') self._display_frames = [] self.bg_image_bytes = None if not provides_own_theme_data: self.renderer.set_item_theme(self.theme) self.theme_data, self.main, self.footer = self.renderer.pre_render() if self.service_item_type == ServiceItemType.Text: log.debug('Formatting slides: %s' % self.title) # Save rendered pages to this dict. In the case that a slide is used twice we can use the pages saved to # the dict instead of rendering them again. if self.get_plugin_name() == 'songs': if not self.extra_data_dict: self.extra_data_dict = {} if not self.xml_version.startswith('<?xml') and not self.xml_version.startswith('<song'): # This is an old style song, without XML. verses = self.xml_version.split('\n\n') for count, verse in enumerate(verses): self.extra_data_dict['v' + str(count)] = str(verse).split('\n') elif self.xml_version.startswith('<?xml'): # New style song, output as XML. song_xml_split = re.split('(<verse[\w"= ]*>)', self.xml_version) current_section = '' for song_part in song_xml_split: if song_part.startswith("<verse name"): current_section = song_part.replace('<verse name="', '').replace('">', '') elif song_part.startswith("<lines"): # New line needed between <lines> sections song_part = song_part.replace('</lines><line', '</lines><br/><line') # Split out <lines>, </lines>, </verse>, </lyrics> and </song> tags song_part = ''.join(re.split('<lines[\w"= ]*>', song_part)) song_part = song_part.replace('</lines>','').replace('</verse>', '') song_part = song_part.replace('</lyrics>','').replace('</song>', '') # Convert to list self.extra_data_dict[current_section] = song_part.split('<br/>') previous_pages = {} # Get key and transpose amount, if used in this song if "<key>" in self.xml_version: current_key = self.xml_version[(self.xml_version.index('<key>') + 5):(self.xml_version.index('<key>')+7)] if current_key[1] == '<': current_key = current_key[0] else: current_key = '' if "<transposition>" in self.xml_version: current_transpose = self.xml_version[(self.xml_version.index('<transposition>') + 15):(self.xml_version.index('<transposition>')+18)] # Possible options: 1,...,9, 10, 11, -1, ... -9, -10, -11 if current_transpose[1] == '<': current_transpose = int(current_transpose[0]) elif current_transpose[2] == '<': current_transpose = int(current_transpose[0:2]) else: current_transpose = 0 # Calculate resultant key for musician oriented view if current_key != '': resultant_key = Chords.transpose_chord(current_key, current_key, current_transpose) else: resultant_key = '' for slide in self._raw_frames: verse_tag = slide['verseTag'] if verse_tag in previous_pages and previous_pages[verse_tag][0] == slide['raw_slide']: pages = previous_pages[verse_tag][1] else: pages = self.renderer.format_slide(slide['raw_slide'], self) previous_pages[verse_tag] = (slide['raw_slide'], pages) xml_lines = self.extra_data_dict[verse_tag.lower()] xml_line_lower, xml_line_upper = 0, 0 subpage_count = 0 for page in pages: subpage_count += 1 page_lines = page.split('<br>') # Given the current page_lines, calculate the corresponding xml_lines xml_segment = '' xml_line_lower = xml_line_upper for line in page_lines: while (xml_line_upper < len(xml_lines)) and not (''.join(re.split('<chord[\w\+#"=// ]* />', xml_lines[xml_line_upper])).strip() == line.strip()): xml_line_upper += 1 xml_line_upper += 1 page_xml = xml_lines[xml_line_lower: xml_line_upper] # Exclude any [br] or [---] elements from the XML list page_xml_short = [] for item in page_xml: if item != '[br]' and item != '[---]': # split item by chord tags, then transpose each chord tag if current_transpose != 0: item_sections = re.split('(<chord[\w\+#"=// ]* />)', item) transposed_item = '' for item_section in item_sections: if item_section.startswith('<chord name'): transposed_item = transposed_item + Chords.transpose_chord_tag(item_section, current_key, current_transpose) else: transposed_item = transposed_item + item_section page_xml_short.append(transposed_item) else: page_xml_short.append(item) page = page.replace('<br>', '{br}') html_data = expand_tags(html.escape(page.rstrip())) self._display_frames.append({ 'title': clean_tags(page), 'text': clean_tags(page.rstrip()), 'html': html_data.replace('&nbsp;', ' '), 'verseTag': verse_tag, 'verseSubpage': subpage_count, 'extraInfo': '<br>'.join(page_xml_short), 'playedKey': resultant_key }) # Deal with any [br] tag in XML before processing next page # TODO: Check if we need to also do this for [---] tags if xml_line_upper < len(xml_lines) and xml_lines[xml_line_upper].strip() == '[br]': xml_line_upper += 1 else: previous_pages = {} for slide in self._raw_frames: verse_tag = slide['verseTag'] if verse_tag in previous_pages and previous_pages[verse_tag][0] == slide['raw_slide']: pages = previous_pages[verse_tag][1] else: pages = self.renderer.format_slide(slide['raw_slide'], self) previous_pages[verse_tag] = (slide['raw_slide'], pages) for page in pages: page = page.replace('<br>', '{br}') html_data = expand_tags(html.escape(page.rstrip())) self._display_frames.append({ 'title': clean_tags(page), 'text': clean_tags(page.rstrip()), 'html': html_data.replace('&nbsp;', ' '), 'verseTag': verse_tag, }) elif self.service_item_type == ServiceItemType.Image or self.service_item_type == ServiceItemType.Command: pass else: log.error('Invalid value renderer: %s' % self.service_item_type) self.title = clean_tags(self.title) # The footer should never be None, but to be compatible with a few # nightly builds between 1.9.4 and 1.9.5, we have to correct this to # avoid tracebacks. if self.raw_footer is None: self.raw_footer = [] self.foot_text = '<br>'.join([_f for _f in self.raw_footer if _f])
def process_chord_view(self, args): # Pre-condition: args is of the form update=n&capo=m, either one is optional # Also capo must be an integer m, 0<=m<=11 update_id = "unset" capo = 0 for update_option in args.split("&"): option_parts = update_option.split("=") if (option_parts[0] == "update"): update_id = option_parts[1] elif (option_parts[0] == "capo"): if (option_parts[1].isdigit() and int(option_parts[1]) >=0 and int(option_parts[1]) <= 11): capo = int(option_parts[1]) current_item = self.live_controller.service_item if current_item and current_item.get_plugin_name() == 'songs': if update_id == str(self.service_manager.last_update_count): json_data = {'status': 'current'} else: if (self.service_manager.stored_update_id == self.service_manager.last_update_count) and (capo == 0): json_data = self.service_manager.stored_chord_json_data else: current_frames = current_item.get_frames() current_slide = str(current_frames[self.live_controller.selected_row]['extraInfo']) if (self.live_controller.selected_row+1) != len(current_frames): next_slide = str(current_frames[self.live_controller.selected_row+1]['extraInfo']) else: next_slide = '' if (capo > 0) and (current_frames[0]['playedKey'] != ''): # Song has a key specified and a non-zero capo musician_key = 'Capo ' + str(capo) + ' (' + Chords.transpose_chord(current_frames[0]['playedKey'], current_frames[0]['playedKey'], -capo) + ')' current_slide_sections = re.split('(<chord[\w\+#"=// ]* />)', current_slide) transposed_current_slide = '' next_slide_sections = re.split('(<chord[\w\+#"=// ]* />)', next_slide) transposed_next_slide = '' for current_slide_section in current_slide_sections: if current_slide_section.startswith('<chord name'): transposed_current_slide = transposed_current_slide + Chords.transpose_chord_tag(current_slide_section, current_frames[0]['playedKey'], -capo) else: transposed_current_slide = transposed_current_slide + current_slide_section for next_slide_section in next_slide_sections: if next_slide_section.startswith('<chord name'): transposed_next_slide = transposed_next_slide + Chords.transpose_chord_tag(next_slide_section, current_frames[0]['playedKey'], -capo) else: transposed_next_slide = transposed_next_slide + next_slide_section current_slide = transposed_current_slide next_slide = transposed_next_slide else: musician_key = current_frames[0]['playedKey'] song_order = [] for item, frame in enumerate(current_frames): if item == self.live_controller.selected_row: if frame['verseSubpage'] == 1: # First page of a verse/chorus song_order.append("(" + frame['verseTag'] + ")") else: # Not first page of verse/chorus, so verseTag already in list song_order[-1] = "(" + frame['verseTag'] + ")" else: if frame['verseSubpage'] == 1: song_order.append(frame['verseTag']) json_data = {'status': 'update', 'update_id': str(self.service_manager.last_update_count), 'current_slide': current_slide.replace("\"", "'"), 'next_slide': next_slide.replace("\"", "'"), 'song_order': ' '.join(song_order), 'played_key': musician_key} if capo == 0: self.service_manager.stored_update_id = self.service_manager.last_update_count self.service_manager.stored_chord_json_data = json_data else: json_data = {'status': 'inactive'} self.do_json_header() return json.dumps(json_data).encode()
def process_chord_view(self, args): # Pre-condition: args is of the form update=n&capo=m, either one is optional # Also capo must be an integer m, 0<=m<=11 update_id = "unset" capo = 0 for update_option in args.split("&"): option_parts = update_option.split("=") if (option_parts[0] == "update"): update_id = option_parts[1] elif (option_parts[0] == "capo"): if (option_parts[1].isdigit() and int(option_parts[1]) >= 0 and int(option_parts[1]) <= 11): capo = int(option_parts[1]) current_item = self.live_controller.service_item if current_item and current_item.get_plugin_name() == 'songs': if update_id == str(self.service_manager.last_update_count): json_data = {'status': 'current'} else: if (self.service_manager.stored_update_id == self.service_manager.last_update_count) and (capo == 0): json_data = self.service_manager.stored_chord_json_data else: current_frames = current_item.get_frames() current_slide = str(current_frames[ self.live_controller.selected_row]['extraInfo']) if (self.live_controller.selected_row + 1) != len(current_frames): next_slide = str( current_frames[self.live_controller.selected_row + 1]['extraInfo']) else: next_slide = '' if (capo > 0) and ( current_frames[0]['playedKey'] != '' ): # Song has a key specified and a non-zero capo musician_key = 'Capo ' + str( capo) + ' (' + Chords.transpose_chord( current_frames[0]['playedKey'], current_frames[0]['playedKey'], -capo) + ')' current_slide_sections = re.split( '(<chord[\w\+#"=// ]* />)', current_slide) transposed_current_slide = '' next_slide_sections = re.split( '(<chord[\w\+#"=// ]* />)', next_slide) transposed_next_slide = '' for current_slide_section in current_slide_sections: if current_slide_section.startswith('<chord name'): transposed_current_slide = transposed_current_slide + Chords.transpose_chord_tag( current_slide_section, current_frames[0]['playedKey'], -capo) else: transposed_current_slide = transposed_current_slide + current_slide_section for next_slide_section in next_slide_sections: if next_slide_section.startswith('<chord name'): transposed_next_slide = transposed_next_slide + Chords.transpose_chord_tag( next_slide_section, current_frames[0]['playedKey'], -capo) else: transposed_next_slide = transposed_next_slide + next_slide_section current_slide = transposed_current_slide next_slide = transposed_next_slide else: musician_key = current_frames[0]['playedKey'] song_order = [] for item, frame in enumerate(current_frames): if item == self.live_controller.selected_row: if frame[ 'verseSubpage'] == 1: # First page of a verse/chorus song_order.append("(" + frame['verseTag'] + ")") else: # Not first page of verse/chorus, so verseTag already in list song_order[-1] = "(" + frame['verseTag'] + ")" else: if frame['verseSubpage'] == 1: song_order.append(frame['verseTag']) subpage_list = [] subpage = 1 for item, frame in enumerate(current_frames): if frame['verseSubpage'] == 1: subpage = 1 subpage_list.append("1") else: subpage = subpage + 1 subpage_list[-1] = str(subpage) json_data = { 'status': 'update', 'update_id': str(self.service_manager.last_update_count), 'current_slide': current_slide.replace("\"", "'"), 'next_slide': next_slide.replace("\"", "'"), 'song_order': ' '.join(song_order), 'subpages': ' '.join(subpage_list), 'played_key': musician_key, 'slide_type': 'songs' } if capo == 0: self.service_manager.stored_update_id = self.service_manager.last_update_count self.service_manager.stored_chord_json_data = json_data elif current_item and current_item.get_plugin_name() == 'custom': if update_id == str(self.service_manager.last_update_count): json_data = {'status': 'current'} else: current_frames = current_item.get_frames() current_slide = str( current_frames[self.live_controller.selected_row]['html']) if (self.live_controller.selected_row + 1) != len(current_frames): next_slide = str( current_frames[self.live_controller.selected_row + 1]['html']) else: next_slide = '' json_data = { 'status': 'update', 'update_id': str(self.service_manager.last_update_count), 'current_slide': current_slide.replace("\"", "'"), 'next_slide': next_slide.replace("\"", "'"), 'song_order': '', 'subpages': '', 'played_key': '', 'slide_type': 'custom' } elif current_item and current_item.get_plugin_name() == 'bibles': if update_id == str(self.service_manager.last_update_count): json_data = {'status': 'current'} else: current_frames = current_item.get_frames() current_slide = str( current_frames[self.live_controller.selected_row]['html']) if (self.live_controller.selected_row + 1) != len(current_frames): next_slide = str( current_frames[self.live_controller.selected_row + 1]['html']) else: next_slide = '' json_data = { 'status': 'update', 'update_id': str(self.service_manager.last_update_count), 'current_slide': current_slide.replace("\"", "'"), 'next_slide': next_slide.replace("\"", "'"), 'song_order': current_frames[self.live_controller.selected_row] ['extraInfo'], 'subpages': '', 'played_key': '', 'slide_type': 'bibles' } else: json_data = {'status': 'inactive'} self.do_json_header() return json.dumps(json_data).encode()