forked from openlp/openlp
Added support for import of ChordPro
This commit is contained in:
parent
825a703cd0
commit
1406224a8f
@ -48,6 +48,7 @@ from .importers.powerpraise import PowerPraiseImport
|
|||||||
from .importers.presentationmanager import PresentationManagerImport
|
from .importers.presentationmanager import PresentationManagerImport
|
||||||
from .importers.lyrix import LyrixImport
|
from .importers.lyrix import LyrixImport
|
||||||
from .importers.videopsalm import VideoPsalmImport
|
from .importers.videopsalm import VideoPsalmImport
|
||||||
|
from .importers.chordpro import ChordProImport
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -155,29 +156,30 @@ class SongFormat(object):
|
|||||||
OpenLP2 = 1
|
OpenLP2 = 1
|
||||||
Generic = 2
|
Generic = 2
|
||||||
CCLI = 3
|
CCLI = 3
|
||||||
DreamBeam = 4
|
ChordPro = 4
|
||||||
EasySlides = 5
|
DreamBeam = 5
|
||||||
EasyWorshipDB = 6
|
EasySlides = 6
|
||||||
EasyWorshipService = 7
|
EasyWorshipDB = 7
|
||||||
FoilPresenter = 8
|
EasyWorshipService = 8
|
||||||
Lyrix = 9
|
FoilPresenter = 9
|
||||||
MediaShout = 10
|
Lyrix = 10
|
||||||
OpenSong = 11
|
MediaShout = 11
|
||||||
OPSPro = 12
|
OpenSong = 12
|
||||||
PowerPraise = 13
|
OPSPro = 13
|
||||||
PowerSong = 14
|
PowerPraise = 14
|
||||||
PresentationManager = 15
|
PowerSong = 15
|
||||||
ProPresenter = 16
|
PresentationManager = 16
|
||||||
SongBeamer = 17
|
ProPresenter = 17
|
||||||
SongPro = 18
|
SongBeamer = 18
|
||||||
SongShowPlus = 19
|
SongPro = 19
|
||||||
SongsOfFellowship = 20
|
SongShowPlus = 20
|
||||||
SundayPlus = 21
|
SongsOfFellowship = 21
|
||||||
VideoPsalm = 22
|
SundayPlus = 22
|
||||||
WordsOfWorship = 23
|
VideoPsalm = 23
|
||||||
WorshipAssistant = 24
|
WordsOfWorship = 24
|
||||||
WorshipCenterPro = 25
|
WorshipAssistant = 25
|
||||||
ZionWorx = 26
|
WorshipCenterPro = 26
|
||||||
|
ZionWorx = 27
|
||||||
|
|
||||||
# Set optional attribute defaults
|
# Set optional attribute defaults
|
||||||
__defaults__ = {
|
__defaults__ = {
|
||||||
@ -224,6 +226,13 @@ class SongFormat(object):
|
|||||||
'filter': '{text} (*.usr *.txt *.bin)'.format(text=translate('SongsPlugin.ImportWizardForm',
|
'filter': '{text} (*.usr *.txt *.bin)'.format(text=translate('SongsPlugin.ImportWizardForm',
|
||||||
'CCLI SongSelect Files'))
|
'CCLI SongSelect Files'))
|
||||||
},
|
},
|
||||||
|
ChordPro: {
|
||||||
|
'class': ChordProImport,
|
||||||
|
'name': 'ChordPro',
|
||||||
|
'prefix': 'chordPro',
|
||||||
|
'filter': '{text} (*.cho *.crd *.chordpro *.chopro *.txt)'.format(text=translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'ChordPro Files'))
|
||||||
|
},
|
||||||
DreamBeam: {
|
DreamBeam: {
|
||||||
'class': DreamBeamImport,
|
'class': DreamBeamImport,
|
||||||
'name': 'DreamBeam',
|
'name': 'DreamBeam',
|
||||||
@ -427,6 +436,7 @@ class SongFormat(object):
|
|||||||
SongFormat.OpenLP2,
|
SongFormat.OpenLP2,
|
||||||
SongFormat.Generic,
|
SongFormat.Generic,
|
||||||
SongFormat.CCLI,
|
SongFormat.CCLI,
|
||||||
|
SongFormat.ChordPro,
|
||||||
SongFormat.DreamBeam,
|
SongFormat.DreamBeam,
|
||||||
SongFormat.EasySlides,
|
SongFormat.EasySlides,
|
||||||
SongFormat.EasyWorshipDB,
|
SongFormat.EasyWorshipDB,
|
||||||
|
153
openlp/plugins/songs/lib/importers/chordpro.py
Normal file
153
openlp/plugins/songs/lib/importers/chordpro.py
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# OpenLP - Open Source Lyrics Projection #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# Copyright (c) 2008-2016 OpenLP Developers #
|
||||||
|
# --------------------------------------------------------------------------- #
|
||||||
|
# This program is free software; you can redistribute it and/or modify it #
|
||||||
|
# under the terms of the GNU General Public License as published by the Free #
|
||||||
|
# Software Foundation; version 2 of the License. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||||
|
# more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License along #
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
|
###############################################################################
|
||||||
|
"""
|
||||||
|
The :mod:`chordpro` module provides the functionality for importing
|
||||||
|
ChordPro files into the current database.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
from openlp.core.common import translate
|
||||||
|
from openlp.core.ui.lib.wizard import WizardStrings
|
||||||
|
from .songimport import SongImport
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# This importer is based on the information available on these webpages:
|
||||||
|
# http://webchord.sourceforge.net/tech.html
|
||||||
|
# http://www.vromans.org/johan/projects/Chordii/chordpro/
|
||||||
|
# http://www.tenbyten.com/software/songsgen/help/HtmlHelp/files_reference.htm
|
||||||
|
# http://linkesoft.com/songbook/chordproformat.html
|
||||||
|
|
||||||
|
class ChordProImport(SongImport):
|
||||||
|
"""
|
||||||
|
The :class:`ChordProImport` class provides OpenLP with the
|
||||||
|
ability to import ChordPro files.
|
||||||
|
"""
|
||||||
|
def do_import(self):
|
||||||
|
self.import_wizard.progress_bar.setMaximum(len(self.import_source))
|
||||||
|
for filename in self.import_source:
|
||||||
|
if self.stop_import_flag:
|
||||||
|
return
|
||||||
|
song_file = open(filename, 'rt')
|
||||||
|
self.do_import_file(song_file)
|
||||||
|
song_file.close()
|
||||||
|
|
||||||
|
def do_import_file(self, song_file):
|
||||||
|
"""
|
||||||
|
Imports the songs in the given file
|
||||||
|
:param song_file: The file object to be imported from.
|
||||||
|
"""
|
||||||
|
self.set_defaults()
|
||||||
|
# Loop over the lines of the file
|
||||||
|
file_content = song_file.read()
|
||||||
|
current_verse = ''
|
||||||
|
current_verse_type = 'v'
|
||||||
|
skip_block = False
|
||||||
|
for line in file_content.splitlines():
|
||||||
|
line = line.rstrip()
|
||||||
|
# Detect tags
|
||||||
|
if line.startswith('{'):
|
||||||
|
tag_name, tag_value = self.parse_tag(line)
|
||||||
|
# Detect which tag
|
||||||
|
if tag_name in ['title', 't']:
|
||||||
|
self.title = tag_value
|
||||||
|
elif tag_name in ['subtitle', 'su', 'st']:
|
||||||
|
self.alternate_title = tag_value
|
||||||
|
elif tag_name in ['comment', 'c', 'comment_italic', 'ci', 'comment_box', 'cb']:
|
||||||
|
# Detect if the comment is used as a chorus repeat marker
|
||||||
|
if tag_value.lower().startswith('chorus'):
|
||||||
|
if current_verse.strip():
|
||||||
|
# Add collected verse to the lyrics
|
||||||
|
self.add_verse(current_verse.strip(), current_verse_type)
|
||||||
|
current_verse_type = 'v'
|
||||||
|
current_verse = ''
|
||||||
|
self.repeat_verse('c1')
|
||||||
|
else:
|
||||||
|
self.add_comment(tag_value)
|
||||||
|
elif tag_name in ['start_of_chorus', 'soc']:
|
||||||
|
current_verse_type = 'c'
|
||||||
|
elif tag_name in ['end_of_chorus', 'eoc']:
|
||||||
|
# Add collected chorus to the lyrics
|
||||||
|
self.add_verse(current_verse, current_verse_type)
|
||||||
|
current_verse_type = 'v'
|
||||||
|
current_verse = ''
|
||||||
|
elif tag_name in ['start_of_tab', 'sot']:
|
||||||
|
if current_verse.strip():
|
||||||
|
# Add collected verse to the lyrics
|
||||||
|
self.add_verse(current_verse.strip(), current_verse_type)
|
||||||
|
current_verse_type = 'v'
|
||||||
|
current_verse = ''
|
||||||
|
skip_block = True
|
||||||
|
elif tag_name in ['end_of_tab', 'eot']:
|
||||||
|
skip_block = False
|
||||||
|
elif tag_name in ['new_song', 'ns']:
|
||||||
|
# A new song starts below this tag
|
||||||
|
if self.verses and self.title:
|
||||||
|
if current_verse.strip():
|
||||||
|
self.add_verse(current_verse.strip(), current_verse_type)
|
||||||
|
if not self.finish():
|
||||||
|
self.log_error(song_file.name)
|
||||||
|
self.set_defaults()
|
||||||
|
current_verse_type = 'v'
|
||||||
|
current_verse = ''
|
||||||
|
else:
|
||||||
|
# Unsupported tag
|
||||||
|
log.debug('unsupported tag: %s' % line)
|
||||||
|
elif line.startswith('#'):
|
||||||
|
# Found a comment line, which is ignored...
|
||||||
|
continue
|
||||||
|
elif line == "['|]":
|
||||||
|
# Found a vertical bar
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if skip_block:
|
||||||
|
continue
|
||||||
|
elif line == '' and current_verse.strip() and current_verse_type != 'c':
|
||||||
|
# Add collected verse to the lyrics
|
||||||
|
self.add_verse(current_verse.strip(), current_verse_type)
|
||||||
|
current_verse_type = 'v'
|
||||||
|
current_verse = ''
|
||||||
|
else:
|
||||||
|
current_verse += line + '\n'
|
||||||
|
if current_verse.strip():
|
||||||
|
self.add_verse(current_verse.strip(), current_verse_type)
|
||||||
|
if not self.finish():
|
||||||
|
self.log_error(song_file.name)
|
||||||
|
|
||||||
|
def parse_tag(self, line):
|
||||||
|
"""
|
||||||
|
:param line: Line with the tag to be parsed
|
||||||
|
:return: A tuple with tag name and tag value (if any)
|
||||||
|
"""
|
||||||
|
# Strip the first '}'
|
||||||
|
line = line[1:].strip()
|
||||||
|
colon_idx = line.find(':')
|
||||||
|
# check if this is a tag without value
|
||||||
|
if colon_idx < 0:
|
||||||
|
# strip the final '}' and return the tag name
|
||||||
|
return line[:-1], None
|
||||||
|
tag_name = line[:colon_idx]
|
||||||
|
tag_value = line[colon_idx+1:-1].strip()
|
||||||
|
return tag_name, tag_value
|
@ -301,12 +301,23 @@ class SongImport(QtCore.QObject):
|
|||||||
if verse_def not in self.verse_order_list_generated:
|
if verse_def not in self.verse_order_list_generated:
|
||||||
self.verse_order_list_generated.append(verse_def)
|
self.verse_order_list_generated.append(verse_def)
|
||||||
|
|
||||||
def repeat_verse(self):
|
def repeat_verse(self, verse_def=None):
|
||||||
"""
|
"""
|
||||||
Repeat the previous verse in the verse order
|
Repeat the verse with the given verse_def or default to repeating the previous verse in the verse order
|
||||||
|
|
||||||
|
:param verse_def: verse_def of the verse to be repeated
|
||||||
"""
|
"""
|
||||||
if self.verse_order_list_generated:
|
if self.verse_order_list_generated:
|
||||||
self.verse_order_list_generated.append(self.verse_order_list_generated[-1])
|
if verse_def:
|
||||||
|
# If the given verse_def is only one char (like 'v' or 'c'), postfix it with '1'
|
||||||
|
if len(verse_def) == 1:
|
||||||
|
verse_def += '1'
|
||||||
|
if verse_def in self.verse_order_list_generated:
|
||||||
|
self.verse_order_list_generated.append(verse_def)
|
||||||
|
else:
|
||||||
|
log.warning('Trying to add unknown verse_def "%s"' % verse_def)
|
||||||
|
else:
|
||||||
|
self.verse_order_list_generated.append(self.verse_order_list_generated[-1])
|
||||||
self.verse_order_list_generated_useful = True
|
self.verse_order_list_generated_useful = True
|
||||||
|
|
||||||
def check_complete(self):
|
def check_complete(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user