← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~phill-ridout/openlp/ssp_import into lp:openlp

 

phill has proposed merging lp:~phill-ridout/openlp/ssp_import into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~phill-ridout/openlp/ssp_import/+merge/49548

Importer for SongShow Plus
-- 
https://code.launchpad.net/~phill-ridout/openlp/ssp_import/+merge/49548
Your team OpenLP Core is requested to review the proposed merge of lp:~phill-ridout/openlp/ssp_import into lp:openlp.
=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py	2011-02-10 19:37:02 +0000
+++ openlp/plugins/songs/forms/songimportform.py	2011-02-13 15:19:54 +0000
@@ -140,6 +140,12 @@
         QtCore.QObject.connect(self.songBeamerRemoveButton,
             QtCore.SIGNAL(u'clicked()'),
             self.onSongBeamerRemoveButtonClicked)
+        QtCore.QObject.connect(self.songShowPlusAddButton,
+            QtCore.SIGNAL(u'clicked()'),
+            self.onSongShowPlusAddButtonClicked)
+        QtCore.QObject.connect(self.songShowPlusRemoveButton,
+            QtCore.SIGNAL(u'clicked()'),
+            self.onSongShowPlusRemoveButtonClicked)
 
     def addCustomPages(self):
         """
@@ -188,6 +194,8 @@
         self.addFileSelectItem(u'ew', single_select=True)
         # Words of Worship
         self.addFileSelectItem(u'songBeamer')
+        # Song Show Plus
+        self.addFileSelectItem(u'songShowPlus')
 #        Commented out for future use.
 #        self.addFileSelectItem(u'csv', u'CSV', single_select=True)
         self.sourceLayout.addLayout(self.formatStack)
@@ -237,6 +245,8 @@
             translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
         self.formatComboBox.setItemText(10,
             translate('SongsPlugin.ImportWizardForm', 'SongBeamer'))
+        self.formatComboBox.setItemText(11,
+            translate('SongsPlugin.ImportWizardForm', 'SongShow Plus'))
 #        self.formatComboBox.setItemText(11,
 #            translate('SongsPlugin.ImportWizardForm', 'CSV'))
         self.openLP2FilenameLabel.setText(
@@ -301,6 +311,10 @@
             translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
         self.songBeamerRemoveButton.setText(
             translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
+        self.songShowPlusAddButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
+        self.songShowPlusRemoveButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
 #        self.csvFilenameLabel.setText(
 #            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
 #        self.csvBrowseButton.setText(
@@ -438,6 +452,16 @@
                         'file to import from.'))
                     self.songBeamerAddButton.setFocus()
                     return False
+            elif source_format == SongFormat.SongShowPlus:
+                if self.songShowPlusFileListWidget.count() == 0:
+                    critical_error_message_box(
+                        translate('SongsPlugin.ImportWizardForm',
+                        'No SongShow Plus Files Selected'),
+                        translate('SongsPlugin.ImportWizardForm',
+                        'You need to add at least one SongShow Plus '
+                        'file to import from.'))
+                    self.wordsOfWorshipAddButton.setFocus()
+                    return False
             return True
         elif self.currentPage() == self.progressPage:
             return True
@@ -643,6 +667,24 @@
         Remove selected SongBeamer files from the import list
         """
         self.removeSelectedItems(self.songBeamerFileListWidget)
+        
+    def onSongShowPlusAddButtonClicked(self):
+        """
+        Get SongShow Plus song database files
+        """
+        self.getFiles(
+            translate('SongsPlugin.ImportWizardForm',
+            'Select SongShow Plus Files'),
+            self.songShowPlusFileListWidget, u'%s (*.sbsong)'
+            % translate('SongsPlugin.ImportWizardForm',
+            'SongShow Plus Song Files')
+        )
+
+    def onSongShowPlusRemoveButtonClicked(self):
+        """
+        Remove selected SongShow Plus files from the import list
+        """
+        self.removeSelectedItems(self.songShowPlusFileListWidget)
 
     def setDefaults(self):
         """
@@ -663,6 +705,7 @@
         self.easiSlidesFilenameEdit.setText(u'')
         self.ewFilenameEdit.setText(u'')
         self.songBeamerFileListWidget.clear()
+        self.songShowPlusFileListWidget.clear()
         #self.csvFilenameEdit.setText(u'')
 
     def preWizard(self):
@@ -739,6 +782,12 @@
             importer = self.plugin.importSongs(SongFormat.SongBeamer,
                 filenames=self.getListOfFiles(self.songBeamerFileListWidget)
             )
+        elif source_format == SongFormat.SongShowPlus:
+            # Import ShongShow Plus songs
+            importer = self.plugin.importSongs(SongFormat.SongShowPlus,
+                filenames=self.getListOfFiles(
+                    self.songShowPlusFileListWidget)
+            )
         if importer.do_import():
             self.progressLabel.setText(
                 translate('SongsPlugin.SongImportForm', 'Finished import.'))

=== modified file 'openlp/plugins/songs/lib/importer.py'
--- openlp/plugins/songs/lib/importer.py	2011-01-26 02:43:16 +0000
+++ openlp/plugins/songs/lib/importer.py	2011-02-13 15:19:54 +0000
@@ -34,6 +34,7 @@
 from cclifileimport import CCLIFileImport
 from ewimport import EasyWorshipSongImport
 from songbeamerimport import SongBeamerImport
+from songshowplusimport import SongShowPlusImport
 # Imports that might fail
 try:
     from olp1import import OpenLP1SongImport
@@ -71,6 +72,7 @@
     EasiSlides = 8
     EasyWorship = 9
     SongBeamer = 10
+    SongShowPlus = 11
 
     @staticmethod
     def get_class(format):
@@ -102,6 +104,8 @@
             return EasyWorshipSongImport
         elif format == SongFormat.SongBeamer:
             return SongBeamerImport
+        elif format == SongFormat.SongShowPlus:
+            return SongShowPlusImport
         return None
 
     @staticmethod
@@ -120,7 +124,8 @@
             SongFormat.Generic,
             SongFormat.EasiSlides,
             SongFormat.EasyWorship,
-            SongFormat.SongBeamer
+            SongFormat.SongBeamer,
+            SongFormat.SongShowPlus
         ]
 
     @staticmethod

=== added file 'openlp/plugins/songs/lib/songshowplusimport.py'
--- openlp/plugins/songs/lib/songshowplusimport.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/lib/songshowplusimport.py	2011-02-13 15:19:54 +0000
@@ -0,0 +1,212 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      #
+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian      #
+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble,    #
+# Carsten Tinggaard, Frode Woldsund                                           #
+# --------------------------------------------------------------------------- #
+# 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:`wowimport` module provides the functionality for importing Words of
+Worship songs into the OpenLP database.
+"""
+import os
+import logging
+import struct
+
+from openlp.plugins.songs.lib.songimport import SongImport
+
+TITLE = 1
+AUTHOR = 2
+COPYRIGHT = 3
+CCLI_NO = 5
+VERSE = 12
+CHORUS = 20
+TOPIC = 29
+COMMENTS = 30
+VERSE_ORDER = 31
+SONG_BOOK = 35 
+SONG_NUMBER = 36
+CUSTOM_VERSE = 37
+
+log = logging.getLogger(__name__)
+
+class SongShowPlusImport(SongImport):
+    """
+    The :class:`SongShowPlusImport` class provides the ability to import song 
+    files from SongShow Plus.
+
+    **SongShow Plus Song File Format:**
+
+    The SongShow Plus song file format is as follows:
+    
+    * Each piece of data in the song file has some information that precedes 
+    it.
+    * The general format of this data is as follows:
+    4 Bytes, forming a 32 bit number, a key if you will, this describes what 
+    the data is (see blockKey below)
+    4 Bytes, forming a 32 bit number, which is the number of bytes until the 
+    next block starts
+    1 Byte, which tells how namy bytes follows
+    1 or 4 Bytes, describes how long the string is, if its 1 byte, the string 
+    is less than 255
+    The next bytes are the actuall data.
+    The next block of data follows on.
+    
+    This description does differ for verses. Which includes extra bytes 
+    stating the verse type or number. In some cases a "custom" verse is used, 
+    in that case, this block will in include 2 strings, with the associated 
+    string length descriptors. The first string is the name of the verse, the 
+    second is the verse content.
+    
+    The file is ended with four null bytes.
+
+    Valid extensions for a SongShow Plus song file are:
+
+    * .sbsong
+    """
+    otherList = {}
+    otherCount = 0
+
+    def __init__(self, master_manager, **kwargs):
+        """
+        Initialise the import.
+
+        ``master_manager``
+            The song manager for the running OpenLP installation.
+        """
+        SongImport.__init__(self, master_manager)
+        if kwargs.has_key(u'filename'):
+            self.import_source = kwargs[u'filename']
+        if kwargs.has_key(u'filenames'):
+            self.import_source = kwargs[u'filenames']
+        log.debug(self.import_source)
+        
+    def do_import(self):
+        """
+        Receive a single file or a list of files to import.
+        """
+        if isinstance(self.import_source, list):
+            self.import_wizard.progressBar.setMaximum(len(self.import_source))
+            for file in self.import_source:
+                author = u''
+                copyright = u''
+                self.sspVerseOrderList = []
+                otherCount = 0
+                otherList = {}
+                file_name = os.path.split(file)[1]
+                self.import_wizard.incrementProgressBar(
+                    u'Importing %s' % (file_name), 0)        
+                songData = open(file, 'rb')
+                while (1):
+                    blockKey, = struct.unpack("I",songData.read(4))
+                    # The file ends with 4 NUL's
+                    if blockKey == 0:
+                        break
+                    nextBlockStarts, = struct.unpack("I",songData.read(4))
+                    if blockKey == VERSE or blockKey == CHORUS:
+                        null, verseNo,  = struct.unpack("BB",songData.read(2))
+                    elif blockKey == CUSTOM_VERSE:
+                        null, verseNameLength,  = struct.unpack("BB",
+                            songData.read(2))
+                        verseName = songData.read(verseNameLength)
+                    lengthDescriptorSize, = struct.unpack("B",songData.read(1))
+                    # Detect if/how long the length descriptor is
+                    if lengthDescriptorSize == 12:
+                        lengthDescriptor, = struct.unpack("I",songData.read(4))
+                    elif lengthDescriptorSize == 2:
+                        lengthDescriptor = 1
+                    elif lengthDescriptorSize == 9:
+                        lengthDescriptor = 0
+                    else: 
+                        lengthDescriptor, = struct.unpack("B",songData.read(1))
+                    data = songData.read(lengthDescriptor)
+                    
+                    if blockKey == TITLE:
+                        self.title =  unicode(data, u'cp1252')
+                    elif blockKey == AUTHOR:
+                        authors = data.split(" / ")
+                        for author in authors:
+                            if author.find(",") !=-1:
+                                authorParts = author.split(", ")
+                                author = authorParts[1]  + " " + authorParts[0]
+                            self.parse_author(unicode(author,  u'cp1252'))
+                    elif blockKey == COPYRIGHT:
+                        self.add_copyright(unicode(data, u'cp1252'))
+                    elif blockKey == CCLI_NO:
+                        self.ccli_number = int(data)
+                    elif blockKey == VERSE:
+                        self.add_verse(unicode(data, u'cp1252'), 
+                            "V%s" % verseNo)
+                    elif blockKey == CHORUS:
+                        self.add_verse(unicode(data, u'cp1252'), 
+                            "C%s" % verseNo)
+                    elif blockKey == TOPIC:
+                        self.topics.append(unicode(data, u'cp1252'))
+                    elif blockKey == COMMENTS:
+                        self.comments = unicode(data, u'cp1252')
+                    elif blockKey == VERSE_ORDER:
+                        verseTag = self.toOpenLPVerseTag(data)
+                        self.sspVerseOrderList.append(unicode(verseTag,
+                            u'cp1252'))
+                    elif blockKey == SONG_BOOK:
+                        self.song_book_name = unicode(data, u'cp1252')
+                    elif blockKey == SONG_NUMBER:
+                        self.song_number = ord(data)
+                    elif blockKey == CUSTOM_VERSE:
+                        verseTag = self.toOpenLPVerseTag(verseName)
+                        self.add_verse(unicode(data, u'cp1252'), verseTag)
+                    else:
+                        log.debug("Unrecognised blockKey: %s, data: %s"
+                            %(blockKey, data))
+                self.verse_order_list = self.sspVerseOrderList
+                songData.close()
+                self.finish()
+                self.import_wizard.incrementProgressBar(
+                    u'Importing %s' % (file_name))
+            return True
+    
+    def toOpenLPVerseTag(self, verseName):
+        if verseName.find(" ")!=-1:
+            verseParts = verseName.split(" ")
+            verseType = verseParts[0]
+            verseNumber = verseParts[1]
+        else:
+            verseType = verseName
+            verseNumber = "1"
+        verseType = verseType.lower()
+        if verseType == "verse":
+            verseTag = "V"
+        elif verseType == "chorus":
+            verseTag = "C"
+        elif verseType == "bridge":
+            verseTag = "B"
+        elif verseType == "pre-chorus":
+            verseTag = "P"
+        elif verseType == "bridge":
+            verseTag = "B"
+        else:
+            if  not self.otherList.has_key(verseName):
+                self.otherCount = self.otherCount + 1
+                self.otherList[verseName] = str(self.otherCount)
+            verseTag = "O"
+            verseNumber = self.otherList[verseName]
+        verseTag = verseTag + verseNumber
+        return verseTag


Follow ups