Added support for import of ChordPro

This commit is contained in:
Tomas Groth 2016-09-25 11:30:00 +02:00
parent 825a703cd0
commit 1406224a8f
3 changed files with 200 additions and 26 deletions

View File

@ -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,

View 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

View File

@ -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):