Started on chords support

This commit is contained in:
Tomas Groth 2016-01-03 18:01:44 +01:00
parent 339a8e9cd6
commit dec1aa6720
10 changed files with 274 additions and 30 deletions

View File

@ -252,7 +252,8 @@ class Settings(QtCore.QSettings):
'shortcuts/blankScreen': [QtGui.QKeySequence(QtCore.Qt.Key_Period)], 'shortcuts/blankScreen': [QtGui.QKeySequence(QtCore.Qt.Key_Period)],
'shortcuts/collapse': [QtGui.QKeySequence(QtCore.Qt.Key_Minus)], 'shortcuts/collapse': [QtGui.QKeySequence(QtCore.Qt.Key_Minus)],
'shortcuts/desktopScreen': [QtGui.QKeySequence(QtCore.Qt.Key_D)], 'shortcuts/desktopScreen': [QtGui.QKeySequence(QtCore.Qt.Key_D)],
'shortcuts/delete': [QtGui.QKeySequence(QtGui.QKeySequence.Delete), QtGui.QKeySequence(QtCore.Qt.Key_Delete)], 'shortcuts/delete': [QtGui.QKeySequence(QtGui.QKeySequence.Delete),
QtGui.QKeySequence(QtCore.Qt.Key_Delete)],
'shortcuts/down': [QtGui.QKeySequence(QtCore.Qt.Key_Down)], 'shortcuts/down': [QtGui.QKeySequence(QtCore.Qt.Key_Down)],
'shortcuts/editSong': [], 'shortcuts/editSong': [],
'shortcuts/escapeItem': [QtGui.QKeySequence(QtCore.Qt.Key_Escape)], 'shortcuts/escapeItem': [QtGui.QKeySequence(QtCore.Qt.Key_Escape)],
@ -329,7 +330,8 @@ class Settings(QtCore.QSettings):
'shortcuts/moveBottom': [QtGui.QKeySequence(QtCore.Qt.Key_End)], 'shortcuts/moveBottom': [QtGui.QKeySequence(QtCore.Qt.Key_End)],
'shortcuts/moveDown': [QtGui.QKeySequence(QtCore.Qt.Key_PageDown)], 'shortcuts/moveDown': [QtGui.QKeySequence(QtCore.Qt.Key_PageDown)],
'shortcuts/nextTrackItem': [], 'shortcuts/nextTrackItem': [],
'shortcuts/nextItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Down), QtGui.QKeySequence(QtCore.Qt.Key_PageDown)], 'shortcuts/nextItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Down),
QtGui.QKeySequence(QtCore.Qt.Key_PageDown)],
'shortcuts/nextItem_preview': [QtGui.QKeySequence(QtCore.Qt.Key_Down), 'shortcuts/nextItem_preview': [QtGui.QKeySequence(QtCore.Qt.Key_Down),
QtGui.QKeySequence(QtCore.Qt.Key_PageDown)], QtGui.QKeySequence(QtCore.Qt.Key_PageDown)],
'shortcuts/nextService': [QtGui.QKeySequence(QtCore.Qt.Key_Right)], 'shortcuts/nextService': [QtGui.QKeySequence(QtCore.Qt.Key_Right)],
@ -339,7 +341,8 @@ class Settings(QtCore.QSettings):
QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_F1)], QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_F1)],
'shortcuts/openService': [], 'shortcuts/openService': [],
'shortcuts/saveService': [], 'shortcuts/saveService': [],
'shortcuts/previousItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Up), QtGui.QKeySequence(QtCore.Qt.Key_PageUp)], 'shortcuts/previousItem_live': [QtGui.QKeySequence(QtCore.Qt.Key_Up),
QtGui.QKeySequence(QtCore.Qt.Key_PageUp)],
'shortcuts/playbackPause': [], 'shortcuts/playbackPause': [],
'shortcuts/playbackPlay': [], 'shortcuts/playbackPlay': [],
'shortcuts/playbackStop': [], 'shortcuts/playbackStop': [],

View File

@ -27,6 +27,7 @@ OpenLP work.
from distutils.version import LooseVersion from distutils.version import LooseVersion
import logging import logging
import os import os
import re
from PyQt5 import QtCore, QtGui, Qt, QtWidgets from PyQt5 import QtCore, QtGui, Qt, QtWidgets
@ -258,11 +259,12 @@ def check_item_selected(list_widget, message):
return True return True
def clean_tags(text): def clean_tags(text, chords=False):
""" """
Remove Tags from text for display Remove Tags from text for display
:param text: Text to be cleaned :param text: Text to be cleaned
:param chords: Clean ChordPro tags
""" """
text = text.replace('<br>', '\n') text = text.replace('<br>', '\n')
text = text.replace('{br}', '\n') text = text.replace('{br}', '\n')
@ -270,21 +272,47 @@ def clean_tags(text):
for tag in FormattingTags.get_html_tags(): for tag in FormattingTags.get_html_tags():
text = text.replace(tag['start tag'], '') text = text.replace(tag['start tag'], '')
text = text.replace(tag['end tag'], '') text = text.replace(tag['end tag'], '')
# Remove ChordPro tags
if chords:
text = re.sub(r'\[.+?\]', r'', text)
return text return text
def expand_tags(text): def expand_tags(text, chords=False):
""" """
Expand tags HTML for display Expand tags HTML for display
:param text: The text to be expanded. :param text: The text to be expanded.
:param chords: Convert ChordPro tags to html
""" """
if chords:
text = expand_chords(text)
for tag in FormattingTags.get_html_tags(): for tag in FormattingTags.get_html_tags():
text = text.replace(tag['start tag'], tag['start html']) text = text.replace(tag['start tag'], tag['start html'])
text = text.replace(tag['end tag'], tag['end html']) text = text.replace(tag['end tag'], tag['end html'])
return text return text
def expand_chords(text):
"""
Expand ChordPro tags
:param text:
"""
text_lines = text.split('{br}')
expanded_text_lines = []
for line in text_lines:
# If a ChordPro is detected in the line, replace it with a html-span tag and wrap the line in a span tag.
if '[' in line and ']' in line:
new_line = '<span class="chordline">'
new_line += re.sub(r'(.*?)\[(.+?)\](.*?)', r'\1<span class="chord" style="display:none">\2</span>\3', line)
new_line += '</span>'
expanded_text_lines.append(new_line)
else:
expanded_text_lines.append(line)
return '{br}'.join(expanded_text_lines)
def create_separated_list(string_list): def create_separated_list(string_list):
""" """
Returns a string that represents a join of a list of strings with a localized separator. This function corresponds Returns a string that represents a join of a list of strings with a localized separator. This function corresponds

View File

@ -254,11 +254,11 @@ class Renderer(OpenLPMixin, RegistryMixin, RegistryProperties):
# If there are (at least) two occurrences of [---] we use the first two slides (and neglect the last # If there are (at least) two occurrences of [---] we use the first two slides (and neglect the last
# for now). # for now).
if len(slides) == 3: if len(slides) == 3:
html_text = expand_tags('\n'.join(slides[:2])) html_text = expand_tags('\n'.join(slides[:2]), item.is_capable(ItemCapabilities.HasChords))
# We check both slides to determine if the optional split is needed (there is only one optional # We check both slides to determine if the optional split is needed (there is only one optional
# split). # split).
else: else:
html_text = expand_tags('\n'.join(slides)) html_text = expand_tags('\n'.join(slides), item.is_capable(ItemCapabilities.HasChords))
html_text = html_text.replace('\n', '<br>') html_text = html_text.replace('\n', '<br>')
if self._text_fits_on_slide(html_text): if self._text_fits_on_slide(html_text):
# The first two optional slides fit (as a whole) on one slide. Replace the first occurrence # The first two optional slides fit (as a whole) on one slide. Replace the first occurrence

View File

@ -34,7 +34,7 @@ import ntpath
from PyQt5 import QtGui from PyQt5 import QtGui
from openlp.core.common import RegistryProperties, Settings, translate, AppLocation, md5_hash from openlp.core.common import RegistryProperties, Settings, translate, AppLocation, md5_hash
from openlp.core.lib import ImageSource, build_icon, clean_tags, expand_tags, create_thumb from openlp.core.lib import ImageSource, build_icon, clean_tags, expand_tags, expand_chords
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -118,6 +118,8 @@ class ItemCapabilities(object):
``HasThumbnails`` ``HasThumbnails``
The item has related thumbnails available The item has related thumbnails available
``HasChords``
The item has chords - only for songs
""" """
CanPreview = 1 CanPreview = 1
CanEdit = 2 CanEdit = 2
@ -140,6 +142,7 @@ class ItemCapabilities(object):
HasDisplayTitle = 19 HasDisplayTitle = 19
HasNotes = 20 HasNotes = 20
HasThumbnails = 21 HasThumbnails = 21
HasChords = 22
class ServiceItem(RegistryProperties): class ServiceItem(RegistryProperties):
@ -260,13 +263,16 @@ class ServiceItem(RegistryProperties):
previous_pages[verse_tag] = (slide['raw_slide'], pages) previous_pages[verse_tag] = (slide['raw_slide'], pages)
for page in pages: for page in pages:
page = page.replace('<br>', '{br}') page = page.replace('<br>', '{br}')
html_data = expand_tags(html.escape(page.rstrip())) html_data = expand_tags(html.escape(page.rstrip()), self.is_capable(ItemCapabilities.HasChords))
self._display_frames.append({ new_frame = {
'title': clean_tags(page), 'title': clean_tags(page),
'text': clean_tags(page.rstrip()), 'text': clean_tags(page.rstrip(), self.is_capable(ItemCapabilities.HasChords)),
'html': html_data.replace('&amp;nbsp;', '&nbsp;'), 'html': html_data.replace('&amp;nbsp;', '&nbsp;'),
'verseTag': verse_tag 'verseTag': verse_tag
}) }
if self.is_capable(ItemCapabilities.HasChords):
new_frame['chords_text'] = expand_chords(clean_tags(page.rstrip()))
self._display_frames.append(new_frame)
elif self.service_item_type == ServiceItemType.Image or self.service_item_type == ServiceItemType.Command: elif self.service_item_type == ServiceItemType.Image or self.service_item_type == ServiceItemType.Command:
pass pass
else: else:

View File

@ -16,22 +16,22 @@
* with this program; if not, write to the Free Software Foundation, Inc., 59 * * with this program; if not, write to the Free Software Foundation, Inc., 59 *
* Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Temple Place, Suite 330, Boston, MA 02111-1307 USA *
******************************************************************************/ ******************************************************************************/
body { body {
background-color: black; background-color: black;
font-family: sans-serif; font-family: 'Arial Narrow', 'Avenir Next Condensed', sans-serif-condensed, Arial, sans-serif;
font-size: 4.4vw;
overflow: hidden; overflow: hidden;
} }
#currentslide { #currentslide {
font-size: 40pt; font-size: 100%;
color: white; color: lightgray;
padding-bottom: 0px; padding-bottom: 0px;
} }
#nextslide { #nextslide {
font-size: 40pt; font-size: 100%;
color: grey; color: gray;
padding-top: 0px; padding-top: 0px;
padding-bottom: 0px; padding-bottom: 0px;
} }
@ -41,24 +41,90 @@ body {
} }
#clock { #clock {
font-size: 30pt; font-size: 75%;
color: yellow; color: yellow;
text-align: right; text-align: right;
} }
#notes { #notes {
font-size: 36pt; font-size: 90%;
color: salmon; color: salmon;
text-align: right; text-align: right;
} }
#controls {
display: none;
}
#chords {
font-size: 50%;
color: gray;
background-color: gray;
color: white;
cursor: pointer;
}
#header {
height: 1.4em;
}
#transpose,
#transposevalue,
#capodisplay {
display: inline-block;
font-size: 75%;
color: gray;
vertical-align: middle;
}
#header .button,
#plus,
#minus {
display: inline-block;
width: 3vw;
line-height: 3vw;
vertical-align: middle;
color: white;
background-color: gray;
font-size: 75%;
text-align: center;
cursor: pointer;
}
#verseorder { #verseorder {
font-size: 30pt; font-size: 75%;
color: green; color: green;
text-align: left; text-align: left;
line-height: 1.5;
display: inline-block;
vertical-align: middle;
} }
.currenttag { .currenttag {
color: lightgreen; color: lightgreen;
font-weight: bold; font-weight: bold;
} }
.chordline {
line-height: 2.0;
}
.chordline1 {
line-height: 1.0
}
.chordline span.chord span {
position: relative;
}
.chordline span.chord span strong {
position: absolute;
top: -1em;
left: 0;
font: 500 75% 'Arial Narrow', 'Avenir Next Condensed', sans-serif-condensed, Arial, sans-serif;
color: yellow;
}
.nextslide .chordline span.chord span strong {
color: gray;
}

View File

@ -32,9 +32,15 @@
<input type="hidden" id="next-text" value="${next}" /> <input type="hidden" id="next-text" value="${next}" />
<div id="right"> <div id="right">
<div id="clock"></div> <div id="clock"></div>
<div id="chords">chords on/off</div>
<div id="plus" class="button">+</div>
<div id="minus" class="button">-</div>
<div id="notes"></div> <div id="notes"></div>
</div> </div>
<div id="verseorder"></div> <div id="header">
<div id="verseorder"></div>
<div id="transpose">Transpose:</div> <div class="button" id="transposedown">-</div> <div id="transposevalue">0</div> <div class="button" id="transposeup">+</div> <div id="capodisplay">(Capo)</div>
</div>
<div id="currentslide"></div> <div id="currentslide"></div>
<div id="nextslide"></div> <div id="nextslide"></div>
</body> </body>

View File

@ -16,7 +16,69 @@
* with this program; if not, write to the Free Software Foundation, Inc., 59 * * with this program; if not, write to the Free Software Foundation, Inc., 59 *
* Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Temple Place, Suite 330, Boston, MA 02111-1307 USA *
******************************************************************************/ ******************************************************************************/
var lastChord;
function getTransposeValue(songId) {
if (localStorage.getItem(songId + '_transposeValue')) {return localStorage.getItem(songId + '_transposeValue');}
else {return 0;}
}
function storeTransposeValue(songId,transposeValueToSet) {
localStorage.setItem(songId + '_transposeValue', transposeValueToSet);
}
function transposeChord(chord, transposeValue) {
var chordSplit = chord.replace('♭', 'b').split(/[\/\(\)]/), transposedChord = '', note, notenumber, rest, currentChord,
notesSharp = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','H'],
notesFlat = ['C','Db','D','Eb','Fb','F','Gb','G','Ab','A','B','H'],
notesPreferred = ['b','#','#','#','#','#','#','#','#','#','#','#'];
chordNotes = Array();
for (i = 0; i <= chordSplit.length - 1; i++) {
if (i > 0) {
transposedChord += '/';
}
currentchord = chordSplit[i];
if (currentchord.charAt(0) === '(') {
transposedChord += '(';
if (currentchord.length > 1) {
currentchord = currentchord.substr(1);
} else {
currentchord = "";
}
}
if (currentchord.length > 0) {
if (currentchord.length > 1) {
if ('#b'.indexOf(currentchord.charAt(1)) === -1) {
note = currentchord.substr(0, 1);
rest = currentchord.substr(1);
} else {
note = currentchord.substr(0, 2);
rest = currentchord.substr(2);
}
} else {
note = currentchord;
rest = "";
}
notenumber = (notesSharp.indexOf(note) === -1?notesFlat.indexOf(note):notesSharp.indexOf(note));
notenumber -= parseInt(transposeValue);
while (notenumber > 11) {notenumber -= 12;}
while (notenumber < 0) {notenumber += 12;}
if (i === 0) {
currentChord = notesPreferred[notenumber] === '#' ? notesSharp[notenumber] : notesFlat[notenumber];
lastChord = currentChord;
}else {
currentChord = notesSharp.indexOf(lastChord) === -1 ? notesFlat[notenumber] : notesSharp[notenumber];
}
if(!(notesFlat.indexOf(note)===-1 && notesSharp.indexOf(note)===-1)) transposedChord += currentChord + rest; else transposedChord += note + rest; //note+rest;
//transposedChord += currentChord + rest;
}
}
return transposedChord;
}
var OpenLPChordOverflowFillCount = 0;
window.OpenLP = { window.OpenLP = {
showchords:true,
loadService: function (event) { loadService: function (event) {
$.getJSON( $.getJSON(
"/api/service/list", "/api/service/list",
@ -27,6 +89,7 @@ window.OpenLP = {
idx = parseInt(idx, 10); idx = parseInt(idx, 10);
if (data.results.items[idx]["selected"]) { if (data.results.items[idx]["selected"]) {
$("#notes").html(data.results.items[idx]["notes"].replace(/\n/g, "<br />")); $("#notes").html(data.results.items[idx]["notes"].replace(/\n/g, "<br />"));
$("#songtitle").html(data.results.items[idx]["title"].replace(/\n/g, "<br />"));
if (data.results.items.length > idx + 1) { if (data.results.items.length > idx + 1) {
OpenLP.nextSong = data.results.items[idx + 1]["title"]; OpenLP.nextSong = data.results.items[idx + 1]["title"];
} }
@ -42,6 +105,7 @@ window.OpenLP = {
"/api/controller/live/text", "/api/controller/live/text",
function (data, status) { function (data, status) {
OpenLP.currentSlides = data.results.slides; OpenLP.currentSlides = data.results.slides;
$('#transposevalue').text(getTransposeValue(OpenLP.currentSlides[0].text.split("\n")[0]));
OpenLP.currentSlide = 0; OpenLP.currentSlide = 0;
OpenLP.currentTags = Array(); OpenLP.currentTags = Array();
var div = $("#verseorder"); var div = $("#verseorder");
@ -61,7 +125,7 @@ window.OpenLP = {
} }
else { else {
if ((slide["text"] == data.results.slides[lastChange]["text"]) && if ((slide["text"] == data.results.slides[lastChange]["text"]) &&
(data.results.slides.length >= idx + (idx - lastChange))) { (data.results.slides.length > idx + (idx - lastChange))) {
// If the tag hasn't changed, check to see if the same verse // If the tag hasn't changed, check to see if the same verse
// has been repeated consecutively. Note the verse may have been // has been repeated consecutively. Note the verse may have been
// split over several slides, so search through. If so, repeat the tag. // split over several slides, so search through. If so, repeat the tag.
@ -92,6 +156,37 @@ window.OpenLP = {
// Show the current slide on top. Any trailing slides for the same verse // Show the current slide on top. Any trailing slides for the same verse
// are shown too underneath in grey. // are shown too underneath in grey.
// Then leave a blank line between following verses // Then leave a blank line between following verses
var transposeValue = getTransposeValue(OpenLP.currentSlides[0].text.split("\n")[0]),
chordclass=/class="[a-z\s]*chord[a-z\s]*"\s*style="display:\s?none"/g,
chordclassshow='class="chord" style="display:inline"',
regchord=/<span class="chord" style="display:inline">([\(\w#b♭\+\*\d/\)-]+)<\/span>([\u0080-\uFFFF,\w]*)([\u0080-\uFFFF,\w,\s,\.,\,,\!,\?,\;,\:,\|,\",\',\-,\_]*)(<br>)?/g,
replaceChords=function(mstr,$1,$2,$3,$4) {
// regchord=/<span class="chord" style="display:inline">[\[{]([\(\w#b♭\+\*\d/\)-]+)[\]}]<\/span>([\u0080-\uFFFF,\w]*)([\u0080-\uFFFF,\w,\s,\.,\,,\!,\?,\;,\:,\|,\",\',\-,\_]*)(<br>)?/g,
var v='', w='';
var $1len = 0, $2len = 0, slimchars='fiíIÍjlĺľrtť.,;/ ()|"\'!:\\';
$1 = transposeChord($1, transposeValue);
for (var i = 0; i < $1.length; i++) if (slimchars.indexOf($1.charAt(i)) === -1) {$1len += 2;} else {$1len += 1;}
for (var i = 0; i < $2.length; i++) if (slimchars.indexOf($2.charAt(i)) === -1) {$2len += 2;} else {$2len += 1;}
for (var i = 0; i < $3.length; i++) if (slimchars.indexOf($2.charAt(i)) === -1) {$2len += 2;} else {$2len += 1;}
if ($1len>=$2len && !$4) {
if ($2.length){
if (!$3.length) {
for (c = 0; c < Math.ceil(($1len - $2len) / 2) + 1; c++) {w += '_';}
} else {
for (c = 0; c < $1len - $2len + 2; c++) {w += '&nbsp;';}
}
} else {
if (!$3.length) {
for (c = 0; c < Math.floor(($1len - $2len) / 2) + 1; c++) {w += '_';}
} else {
for (c = 0; c < $1len - $2len + 1; c++) {w += '&nbsp;';}
}
};
} else {
if (!$2 && $3.charAt(0) == ' ') {for (c = 0; c < $1len; c++) {w += '&nbsp;';}}
}
return $.grep(['<span class="chord" style="display:inline"><span><strong>', $1, '</strong></span>', $2, w, $3, '</span>', $4], Boolean).join('');
};
$("#verseorder span").removeClass("currenttag"); $("#verseorder span").removeClass("currenttag");
$("#tag" + OpenLP.currentTags[OpenLP.currentSlide]).addClass("currenttag"); $("#tag" + OpenLP.currentTags[OpenLP.currentSlide]).addClass("currenttag");
var slide = OpenLP.currentSlides[OpenLP.currentSlide]; var slide = OpenLP.currentSlides[OpenLP.currentSlide];
@ -101,6 +196,10 @@ window.OpenLP = {
text = slide["title"]; text = slide["title"];
} else { } else {
text = slide["text"]; text = slide["text"];
if(OpenLP.showchords) {
text = text.replace(chordclass,chordclassshow);
text = text.replace(regchord, replaceChords);
}
} }
// use thumbnail if available // use thumbnail if available
if (slide["img"]) { if (slide["img"]) {
@ -121,19 +220,24 @@ window.OpenLP = {
text = text + OpenLP.currentSlides[idx]["title"]; text = text + OpenLP.currentSlides[idx]["title"];
} else { } else {
text = text + OpenLP.currentSlides[idx]["text"]; text = text + OpenLP.currentSlides[idx]["text"];
if(OpenLP.showchords) {
text = text.replace(chordclass,chordclassshow);
text = text.replace(regchord, replaceChords);
}
} }
if (OpenLP.currentTags[idx] != OpenLP.currentTags[idx - 1]) if (OpenLP.currentTags[idx] != OpenLP.currentTags[idx - 1])
text = text + "</p>"; text = text + "</p>";
else else
text = text + "<br />"; text = text + "<br />";
} }
text = text.replace(/\n/g, "<br />"); text = text.replace(/\n/g, "<br />");
$("#nextslide").html(text); $("#nextslide").html(text);
} }
else { else {
text = "<p class=\"nextslide\">" + $("#next-text").val() + ": " + OpenLP.nextSong + "</p>"; text = "<p class=\"nextslide\">" + $("#next-text").val() + ": " + OpenLP.nextSong + "</p>";
$("#nextslide").html(text); $("#nextslide").html(text);
} }
if(!OpenLP.showchords) $(".chordline").toggleClass('chordline1');
}, },
updateClock: function(data) { updateClock: function(data) {
var div = $("#clock"); var div = $("#clock");
@ -141,6 +245,7 @@ window.OpenLP = {
var h = t.getHours(); var h = t.getHours();
if (data.results.twelve && h > 12) if (data.results.twelve && h > 12)
h = h - 12; h = h - 12;
if (h < 10) h = '0' + h + '';
var m = t.getMinutes(); var m = t.getMinutes();
if (m < 10) if (m < 10)
m = '0' + m + ''; m = '0' + m + '';
@ -151,8 +256,7 @@ window.OpenLP = {
"/api/poll", "/api/poll",
function (data, status) { function (data, status) {
OpenLP.updateClock(data); OpenLP.updateClock(data);
if (OpenLP.currentItem != data.results.item || if (OpenLP.currentItem != data.results.item || OpenLP.currentService != data.results.service) {
OpenLP.currentService != data.results.service) {
OpenLP.currentItem = data.results.item; OpenLP.currentItem = data.results.item;
OpenLP.currentService = data.results.service; OpenLP.currentService = data.results.service;
OpenLP.loadSlides(); OpenLP.loadSlides();
@ -163,8 +267,27 @@ window.OpenLP = {
} }
} }
); );
// $('span.chord').each(function(){this.style.display="inline"});
} }
} }
$.ajaxSetup({ cache: false }); $.ajaxSetup({ cache: false });
setInterval("OpenLP.pollServer();", 500); setInterval("OpenLP.pollServer();", 500);
OpenLP.pollServer(); OpenLP.pollServer();
$(document).ready(function() {
$('#transposeup').click(function(e) {
$('#transposevalue').text(parseInt($('#transposevalue').text()) + 1);
storeTransposeValue(OpenLP.currentSlides[0].text.split("\n")[0], $('#transposevalue').text());
//alert(getTransposeValue(OpenLP.currentSlides[0].text.split("\n")[0]));
//$('body').get(0).style.'font-size' = (parseFloat($('body').css('font-size')) + 0.1) + 'vw');
OpenLP.loadSlides();
});
$('#transposedown').click(function(e) {
$('#transposevalue').text(parseInt($('#transposevalue').text()) - 1);
storeTransposeValue(OpenLP.currentSlides[0].text.split("\n")[0], $('#transposevalue').text());
OpenLP.loadSlides();
});
$("#chords").click(function(){ OpenLP.showchords=OpenLP.showchords?false:true; OpenLP.updateSlide(); });
$('#plus').click(function() { var fs=$('#currentslide').css('font-size').match(/\d+/); $('#currentslide').css("font-size",+fs+10+"px");$('#nextslide').css("font-size",+fs+10+"px"); } );
$("#minus").click(function() {var fs=$('#currentslide').css('font-size').match(/\d+/); $('#currentslide').css("font-size",+fs-10+"px");$('#nextslide').css("font-size",+fs-10+"px"); } );
$('body').hover(function(){ $('#controls').fadeIn(500);},function(){ $('#controls').fadeOut(500);});
});

View File

@ -546,8 +546,14 @@ class HttpRouter(RegistryProperties):
item['tag'] = str(frame['verseTag']) item['tag'] = str(frame['verseTag'])
else: else:
item['tag'] = str(index + 1) item['tag'] = str(index + 1)
item['text'] = str(frame['text']) # Use chords if available and enabled
if current_item.is_capable(ItemCapabilities.HasChords):
item['text'] = str(frame['chords_text'])
else:
item['text'] = str(frame['text'])
item['html'] = str(frame['html']) item['html'] = str(frame['html'])
print('text: %s' % item['text'])
print('html: %s' % item['html'])
# Handle images, unless a custom thumbnail is given or if thumbnails is disabled # Handle images, unless a custom thumbnail is given or if thumbnails is disabled
elif current_item.is_image() and not frame.get('image', '') and Settings().value('remotes/thumbnails'): elif current_item.is_image() and not frame.get('image', '') and Settings().value('remotes/thumbnails'):
item['tag'] = str(index + 1) item['tag'] = str(index + 1)

View File

@ -471,6 +471,9 @@ class SongMediaItem(MediaManagerItem):
if song.media_files: if song.media_files:
service_item.add_capability(ItemCapabilities.HasBackgroundAudio) service_item.add_capability(ItemCapabilities.HasBackgroundAudio)
service_item.background_audio = [m.file_name for m in song.media_files] service_item.background_audio = [m.file_name for m in song.media_files]
# If chords are enabled and detected, mark the item as having chords
if Settings().value(self.settings_section + '/chords') and '[' in song.lyrics:
service_item.add_capability(ItemCapabilities.HasChords)
return True return True
def generate_footer(self, item, song): def generate_footer(self, item, song):

View File

@ -65,7 +65,10 @@ __default_settings__ = {
'songs/last directory export': '', 'songs/last directory export': '',
'songs/songselect username': '', 'songs/songselect username': '',
'songs/songselect password': '', 'songs/songselect password': '',
'songs/songselect searches': '' 'songs/songselect searches': '',
'songs/chords': True,
'songs/stageview chords': False,
'songs/mainview chords': False
} }