← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~j-corwin/openlp/bug-1015823 into lp:openlp

 

Jonathan Corwin has proposed merging lp:~j-corwin/openlp/bug-1015823 into lp:openlp.

Requested reviews:
  Jonathan Corwin (j-corwin)
  Tim Bentley (trb143)
  Samuel Findlay (sfindlay)
  Andreas Preikschat (googol)
  Raoul Snyman (raoul-snyman)

For more details, see:
https://code.launchpad.net/~j-corwin/openlp/bug-1015823/+merge/113848

This adds imports for the SongPro text file export format and MediaShout Access Database

The SongPro one is based on Martin Barrett's example attached to http://support.openlp.org/issues/569, although somewhat rewritten.

The MediaShout import is currently Windows only (due to odbc driver complexities). It also requires an Access ODBC driver, but if MediaShout is on the same PC then they will already have this, otherwise the MDAC can be freely downloaded from Microsoft.
Windows developers will need to easy_install pyodbc once this is merged. 
-- 
https://code.launchpad.net/~j-corwin/openlp/bug-1015823/+merge/113848
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/plugins/songs/lib/__init__.py'
--- openlp/plugins/songs/lib/__init__.py	2012-07-04 09:50:31 +0000
+++ openlp/plugins/songs/lib/__init__.py	2012-07-08 08:58:23 +0000
@@ -476,7 +476,7 @@
     Dictionary of fonts and respective encodings.
 
     ``default_encoding``
-    The defaul encoding to use when font_table is empty or no font is used.
+    The default encoding to use when font_table is empty or no font is used.
 
     ``failed``
     A boolean indicating whether the previous encoding didn't work.

=== modified file 'openlp/plugins/songs/lib/importer.py'
--- openlp/plugins/songs/lib/importer.py	2012-07-04 09:50:31 +0000
+++ openlp/plugins/songs/lib/importer.py	2012-07-08 08:58:23 +0000
@@ -28,6 +28,7 @@
 """
 The :mod:`importer` modules provides the general song import functionality.
 """
+import os
 import logging
 
 from openlp.core.lib import translate
@@ -44,6 +45,7 @@
 from ewimport import EasyWorshipSongImport
 from songbeamerimport import SongBeamerImport
 from songshowplusimport import SongShowPlusImport
+from songproimport import SongProImport
 from sundayplusimport import SundayPlusImport
 from foilpresenterimport import FoilPresenterImport
 from zionworximport import ZionWorxImport
@@ -67,6 +69,13 @@
 except ImportError:
     log.exception('Error importing %s', 'OooImport')
     HAS_OOO = False
+HAS_MEDIASHOUT = False
+if os.name == u'nt':
+    try:
+        from mediashoutimport import MediaShoutImport
+        HAS_MEDIASHOUT = True
+    except ImportError:
+        log.exception('Error importing %s', 'MediaShoutImport')
 
 
 class SongFormatSelect(object):
@@ -141,15 +150,16 @@
     EasySlides = 6
     EasyWorship = 7
     FoilPresenter = 8
-    OpenSong = 9
-    PowerSong = 10
-    SongBeamer = 11
-    SongShowPlus = 12
-    SongsOfFellowship = 13
-    SundayPlus = 14
-    WordsOfWorship = 15
-    ZionWorx = 16
-    #CSV = 17
+    MediaShout = 9
+    OpenSong = 10
+    PowerSong = 11
+    SongBeamer = 12
+    SongPro = 13
+    SongShowPlus = 14
+    SongsOfFellowship = 15
+    SundayPlus = 16
+    WordsOfWorship = 17
+    ZionWorx = 18
 
     # Set optional attribute defaults
     __defaults__ = {
@@ -240,6 +250,14 @@
             u'filter': u'%s (*.foil)' % translate(
                 'SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files')
         },
+        MediaShout: {
+            u'name': u'MediaShout',
+            u'prefix': u'mediaShout',
+            u'canDisable': True,
+            u'selectMode': SongFormatSelect.SingleFile,
+            u'filter': u'%s (*.mdb)' % translate('SongsPlugin.ImportWizardForm',
+                'MediaShout Database')
+        },
         OpenSong: {
             u'class': OpenSongImport,
             u'name': WizardStrings.OS,
@@ -260,6 +278,18 @@
             u'filter': u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm',
                 'SongBeamer Files')
         },
+        SongPro: {
+            u'class': SongProImport,
+            u'name': u'SongPro',
+            u'prefix': u'songPro',
+            u'selectMode': SongFormatSelect.SingleFile,
+            u'filter': u'%s (*.txt)' % translate('SongsPlugin.ImportWizardForm',
+                'SongPro Text Files'),
+            u'comboBoxText': translate('SongsPlugin.ImportWizardForm',
+                'SongPro (Export File)'),
+            u'descriptionText': translate('SongsPlugin.ImportWizardForm',
+                'In SongPro, export your songs using the File -> Export menu')
+        },
         SongShowPlus: {
             u'class': SongShowPlusImport,
             u'name': u'SongShow Plus',
@@ -302,12 +332,6 @@
                 'First convert your ZionWorx database to a CSV text file, as '
                 'explained in the <a href="http://manual.openlp.org/songs.html'
                 '#importing-from-zionworx">User Manual</a>.')
-#        },
-#        CSV: {
-#            u'class': CSVImport,
-#            u'name': WizardStrings.CSV,
-#            u'prefix': u'csv',
-#            u'selectMode': SongFormatSelect.SingleFile
         }
     }
 
@@ -326,9 +350,11 @@
             SongFormat.EasySlides,
             SongFormat.EasyWorship,
             SongFormat.FoilPresenter,
+            SongFormat.MediaShout,
             SongFormat.OpenSong,
             SongFormat.PowerSong,
             SongFormat.SongBeamer,
+            SongFormat.SongPro,
             SongFormat.SongShowPlus,
             SongFormat.SongsOfFellowship,
             SongFormat.SundayPlus,
@@ -383,5 +409,8 @@
 SongFormat.set(SongFormat.Generic, u'availability', HAS_OOO)
 if HAS_OOO:
     SongFormat.set(SongFormat.Generic, u'class', OooImport)
+SongFormat.set(SongFormat.MediaShout, u'availability', HAS_MEDIASHOUT)
+if HAS_MEDIASHOUT:
+    SongFormat.set(SongFormat.MediaShout, u'class', MediaShoutImport)
 
 __all__ = [u'SongFormat', u'SongFormatSelect']

=== added file 'openlp/plugins/songs/lib/mediashoutimport.py'
--- openlp/plugins/songs/lib/mediashoutimport.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/lib/mediashoutimport.py	2012-07-08 08:58:23 +0000
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2012 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Edwin Lunando, Joshua Miller, Stevan Pettit,  #
+# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      #
+# Simon Scudder, Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon      #
+# Tibble, Dave Warnock, 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:`mediashoutimport` module provides the functionality for importing
+a MediaShout database into the OpenLP database.
+"""
+import re
+import os
+import pyodbc
+
+from openlp.core.lib import translate
+from openlp.plugins.songs.lib.songimport import SongImport
+
+VERSE_TAGS = [u'V', u'C', u'B', u'O', u'P', u'I', u'E']
+
+class MediaShoutImport(SongImport):
+    """
+    The :class:`MediaShoutImport` class provides the ability to import the
+    MediaShout Access Database
+    """
+    def __init__(self, manager, **kwargs):
+        """
+        Initialise the MediaShout importer.
+        """
+        SongImport.__init__(self, manager, **kwargs)
+
+    def doImport(self):
+        """
+        Receive a single file to import.
+        """
+        try:
+           conn = pyodbc.connect(u'DRIVER={Microsoft Access Driver (*.mdb)};'
+            u'DBQ=%s;PWD=6NOZ4eHK7k' % self.importSource)
+        except:
+            # Unfortunately no specific exception type
+            self.logError(self.importSource,
+                translate('SongsPlugin.MediaShoutImport',
+                    'Unable to open the MediaShout database.'))
+            return
+        cursor = conn.cursor()
+        cursor.execute(u'SELECT Record, Title, Author, Copyright, '
+                       u'SongID, CCLI, Notes FROM Songs ORDER BY Title')
+        songs = cursor.fetchall()
+        self.importWizard.progressBar.setMaximum(len(songs))
+        for song in songs:
+            if self.stopImportFlag:
+                break
+            cursor.execute(u'SELECT Type, Number, Text FROM Verses '
+                u'WHERE Record = %s ORDER BY Type, Number' % song.Record)
+            verses = cursor.fetchall()
+            cursor.execute(u'SELECT Type, Number, POrder FROM PlayOrder '
+                u'WHERE Record = %s ORDER BY POrder' % song.Record)
+            verse_order = cursor.fetchall()
+            cursor.execute(u'SELECT Name FROM Themes INNER JOIN SongThemes '
+                u'ON SongThemes.ThemeId = Themes.ThemeId '
+                u'WHERE SongThemes.Record = %s' % song.Record)
+            topics = cursor.fetchall()
+            cursor.execute(u'SELECT Name FROM Groups INNER JOIN SongGroups '
+                           u'ON SongGroups.GroupId = Groups.GroupId '
+                           u'WHERE SongGroups.Record = %s' % song.Record)
+            topics += cursor.fetchall()
+            self.processSong(song, verses, verse_order, topics)
+
+    def processSong(self, song, verses, verse_order, topics):
+        """
+        Create the song, i.e. title, verse etc.
+        """
+        self.setDefaults()
+        self.title = song.Title
+        self.parseAuthor(song.Author)
+        self.addCopyright(song.Copyright)
+        self.comments = song.Notes
+        for topic in topics:
+            self.topics.append(topic.Name)
+        if u'-' in song.SongID:
+            self.songBookName, self.songNumber = song.SongID.split(u'-', 1)
+        else:
+            self.songBookName = song.SongID
+        for verse in verses:
+            tag = VERSE_TAGS[verse.Type] + unicode(verse.Number) \
+                if verse.Type < len(VERSE_TAGS) else u'O'
+            self.addVerse(verse.Text, tag)
+        for order in verse_order:
+            if order.Type < len(VERSE_TAGS):
+                self.verseOrderList.append(VERSE_TAGS[order.Type]
+                    + unicode(order.Number))
+        self.finish()

=== added file 'openlp/plugins/songs/lib/songproimport.py'
--- openlp/plugins/songs/lib/songproimport.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/lib/songproimport.py	2012-07-08 08:58:23 +0000
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2012 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub,      #
+# Meinert Jordan, Armin Köhler, Edwin Lunando, Joshua Miller, Stevan Pettit,  #
+# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout,      #
+# Simon Scudder, Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon      #
+# Tibble, Dave Warnock, 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:`songproimport` module provides the functionality for importing SongPro
+songs into the OpenLP database.
+"""
+import re
+import os
+
+from openlp.core.lib import translate
+from openlp.plugins.songs.lib import strip_rtf
+from openlp.plugins.songs.lib.songimport import SongImport
+
+class SongProImport(SongImport):
+    """
+    The :class:`SongProImport` class provides the ability to import song files
+    from SongPro export files.
+
+    **SongPro Song File Format:**
+
+    SongPro has the option to export under its File menu
+    This produces files containing single or multiple songs
+    The file is text with lines tagged with # followed by an identifier.
+    This is documented here: http://creationsoftware.com/ImportIdentifiers.php
+    An example here: http://creationsoftware.com/ExampleImportingManySongs.txt
+
+    #A - next line is the Song Author
+    #B - the lines following until next tagged line are the "Bridge" words
+        (can be in rtf or plain text) which we map as B1
+    #C - the lines following until next tagged line are the chorus words
+        (can be in rtf or plain text)
+        which we map as C1
+    #D - the lines following until next tagged line are the "Ending" words
+        (can be in rtf or plain text) which we map as E1
+    #E - this song ends here, so we process the song -
+        and start again at the next line
+    #G - next line is the Group
+    #M - next line is the Song Number
+    #N - next line are Notes
+    #R - next line is the SongCopyright
+    #O - next line is the Verse Sequence
+    #T - next line is the Song Title
+    #1 - #7 the lines following until next tagged line are the verse x words
+        (can be in rtf or plain text)
+    """
+    def __init__(self, manager, **kwargs):
+        """
+        Initialise the SongPro importer.
+        """
+        SongImport.__init__(self, manager, **kwargs)
+
+    def doImport(self):
+        """
+        Receive a single file or a list of files to import.
+        """
+        self.encoding = None
+        with open(self.importSource, 'r') as songs_file:
+            self.importWizard.progressBar.setMaximum(0)
+            tag = u''
+            text = u''
+            for file_line in songs_file:
+                if self.stopImportFlag:
+                    break
+                file_line = unicode(file_line, u'cp1252')
+                file_text = file_line.rstrip()
+                if file_text and file_text[0] == u'#':
+                    self.processSection(tag, text.rstrip())
+                    tag = file_text[1:]
+                    text = u''
+                else:
+                    text += file_line
+
+    def processSection(self, tag, text):
+        """
+        Process a section of the song, i.e. title, verse etc.
+        """
+        if tag == u'T':
+            self.setDefaults()
+            if text:
+                self.title = text
+            return
+        elif tag == u'E':
+            self.finish()
+            return
+        if u'rtf1' in text:
+            text, self.encoding = strip_rtf(text, self.encoding)
+            text = text.rstrip()
+        if not text:
+            return
+        if tag == u'A':
+            self.parseAuthor(text)
+        elif tag in [u'B', u'C']:
+            self.addVerse(text, tag)
+        elif tag == u'D':
+            self.addVerse(text, u'E')
+        elif tag == u'G':
+            self.topics.append(text)
+        elif tag == u'M':
+            matches = re.findall(r'\d+', text)
+            if matches:
+                self.songNumber = matches[-1]
+                self.songBookName = text[:text.rfind(self.songNumber)]
+        elif tag == u'N':
+            self.comments = text
+        elif tag == u'O':
+            for char in text:
+                if char == u'C':
+                    self.verseOrderList.append(u'C1')
+                elif char == u'B':
+                    self.verseOrderList.append(u'B1')
+                elif char == u'D':
+                    self.verseOrderList.append(u'E1')
+                elif u'1' <= char <= u'7':
+                    self.verseOrderList.append(u'V' + char)
+        elif tag == u'R':
+            self.addCopyright(text)
+        elif u'1' <= tag <= u'7':
+            self.addVerse(text, u'V' + tag[1:])


Follow ups