forked from openlp/openlp
Started on chords support
This commit is contained in:
parent
339a8e9cd6
commit
dec1aa6720
@ -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': [],
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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('&nbsp;', ' '),
|
'html': html_data.replace('&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:
|
||||||
|
@ -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;
|
||||||
|
}
|
@ -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>
|
||||||
|
@ -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 += ' ';}
|
||||||
|
}
|
||||||
|
} 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 += ' ';}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
if (!$2 && $3.charAt(0) == ' ') {for (c = 0; c < $1len; c++) {w += ' ';}}
|
||||||
|
}
|
||||||
|
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);});
|
||||||
|
});
|
||||||
|
@ -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)
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user