forked from openlp/openlp
Changed 'PowerSong' to 'PowerSong 1.0 and Code tidy ups.
bzr-revno: 1967
This commit is contained in:
commit
fc8c5598aa
@ -53,6 +53,7 @@ class WizardStrings(object):
|
|||||||
OL = u'OpenLyrics'
|
OL = u'OpenLyrics'
|
||||||
OS = u'OpenSong'
|
OS = u'OpenSong'
|
||||||
OSIS = u'OSIS'
|
OSIS = u'OSIS'
|
||||||
|
PS = u'PowerSong 1.0'
|
||||||
SB = u'SongBeamer'
|
SB = u'SongBeamer'
|
||||||
SoF = u'Songs of Fellowship'
|
SoF = u'Songs of Fellowship'
|
||||||
SSP = u'SongShow Plus'
|
SSP = u'SongShow Plus'
|
||||||
|
@ -171,6 +171,12 @@ class SongImportForm(OpenLPWizard):
|
|||||||
QtCore.QObject.connect(self.foilPresenterRemoveButton,
|
QtCore.QObject.connect(self.foilPresenterRemoveButton,
|
||||||
QtCore.SIGNAL(u'clicked()'),
|
QtCore.SIGNAL(u'clicked()'),
|
||||||
self.onFoilPresenterRemoveButtonClicked)
|
self.onFoilPresenterRemoveButtonClicked)
|
||||||
|
QtCore.QObject.connect(self.powerSongAddButton,
|
||||||
|
QtCore.SIGNAL(u'clicked()'),
|
||||||
|
self.onPowerSongAddButtonClicked)
|
||||||
|
QtCore.QObject.connect(self.powerSongRemoveButton,
|
||||||
|
QtCore.SIGNAL(u'clicked()'),
|
||||||
|
self.onPowerSongRemoveButtonClicked)
|
||||||
|
|
||||||
def addCustomPages(self):
|
def addCustomPages(self):
|
||||||
"""
|
"""
|
||||||
@ -217,6 +223,8 @@ class SongImportForm(OpenLPWizard):
|
|||||||
self.addFileSelectItem(u'foilPresenter')
|
self.addFileSelectItem(u'foilPresenter')
|
||||||
# Open Song
|
# Open Song
|
||||||
self.addFileSelectItem(u'openSong', u'OpenSong')
|
self.addFileSelectItem(u'openSong', u'OpenSong')
|
||||||
|
# PowerSong
|
||||||
|
self.addFileSelectItem(u'powerSong')
|
||||||
# SongBeamer
|
# SongBeamer
|
||||||
self.addFileSelectItem(u'songBeamer')
|
self.addFileSelectItem(u'songBeamer')
|
||||||
# Song Show Plus
|
# Song Show Plus
|
||||||
@ -264,6 +272,8 @@ class SongImportForm(OpenLPWizard):
|
|||||||
self.formatComboBox.setItemText(
|
self.formatComboBox.setItemText(
|
||||||
SongFormat.FoilPresenter, WizardStrings.FP)
|
SongFormat.FoilPresenter, WizardStrings.FP)
|
||||||
self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS)
|
self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS)
|
||||||
|
self.formatComboBox.setItemText(
|
||||||
|
SongFormat.PowerSong, WizardStrings.PS)
|
||||||
self.formatComboBox.setItemText(
|
self.formatComboBox.setItemText(
|
||||||
SongFormat.SongBeamer, WizardStrings.SB)
|
SongFormat.SongBeamer, WizardStrings.SB)
|
||||||
self.formatComboBox.setItemText(
|
self.formatComboBox.setItemText(
|
||||||
@ -305,6 +315,10 @@ class SongImportForm(OpenLPWizard):
|
|||||||
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
|
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
|
||||||
self.dreamBeamRemoveButton.setText(
|
self.dreamBeamRemoveButton.setText(
|
||||||
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
|
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
|
||||||
|
self.powerSongAddButton.setText(
|
||||||
|
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
|
||||||
|
self.powerSongRemoveButton.setText(
|
||||||
|
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
|
||||||
self.songsOfFellowshipAddButton.setText(
|
self.songsOfFellowshipAddButton.setText(
|
||||||
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
|
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
|
||||||
self.songsOfFellowshipRemoveButton.setText(
|
self.songsOfFellowshipRemoveButton.setText(
|
||||||
@ -417,6 +431,12 @@ class SongImportForm(OpenLPWizard):
|
|||||||
WizardStrings.YouSpecifyFile % WizardStrings.DB)
|
WizardStrings.YouSpecifyFile % WizardStrings.DB)
|
||||||
self.dreamBeamAddButton.setFocus()
|
self.dreamBeamAddButton.setFocus()
|
||||||
return False
|
return False
|
||||||
|
elif source_format == SongFormat.PowerSong:
|
||||||
|
if self.powerSongFileListWidget.count() == 0:
|
||||||
|
critical_error_message_box(UiStrings().NFSp,
|
||||||
|
WizardStrings.YouSpecifyFile % WizardStrings.PS)
|
||||||
|
self.powerSongAddButton.setFocus()
|
||||||
|
return False
|
||||||
elif source_format == SongFormat.SongsOfFellowship:
|
elif source_format == SongFormat.SongsOfFellowship:
|
||||||
if self.songsOfFellowshipFileListWidget.count() == 0:
|
if self.songsOfFellowshipFileListWidget.count() == 0:
|
||||||
critical_error_message_box(UiStrings().NFSp,
|
critical_error_message_box(UiStrings().NFSp,
|
||||||
@ -600,6 +620,22 @@ class SongImportForm(OpenLPWizard):
|
|||||||
"""
|
"""
|
||||||
self.removeSelectedItems(self.dreamBeamFileListWidget)
|
self.removeSelectedItems(self.dreamBeamFileListWidget)
|
||||||
|
|
||||||
|
def onPowerSongAddButtonClicked(self):
|
||||||
|
"""
|
||||||
|
Get PowerSong song database files
|
||||||
|
"""
|
||||||
|
self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.PS,
|
||||||
|
self.powerSongFileListWidget, u'%s (*.song)'
|
||||||
|
% translate('SongsPlugin.ImportWizardForm',
|
||||||
|
'PowerSong 1.0 Song Files')
|
||||||
|
)
|
||||||
|
|
||||||
|
def onPowerSongRemoveButtonClicked(self):
|
||||||
|
"""
|
||||||
|
Remove selected PowerSong files from the import list
|
||||||
|
"""
|
||||||
|
self.removeSelectedItems(self.powerSongFileListWidget)
|
||||||
|
|
||||||
def onSongsOfFellowshipAddButtonClicked(self):
|
def onSongsOfFellowshipAddButtonClicked(self):
|
||||||
"""
|
"""
|
||||||
Get Songs of Fellowship song database files
|
Get Songs of Fellowship song database files
|
||||||
@ -717,6 +753,7 @@ class SongImportForm(OpenLPWizard):
|
|||||||
self.wordsOfWorshipFileListWidget.clear()
|
self.wordsOfWorshipFileListWidget.clear()
|
||||||
self.ccliFileListWidget.clear()
|
self.ccliFileListWidget.clear()
|
||||||
self.dreamBeamFileListWidget.clear()
|
self.dreamBeamFileListWidget.clear()
|
||||||
|
self.powerSongFileListWidget.clear()
|
||||||
self.songsOfFellowshipFileListWidget.clear()
|
self.songsOfFellowshipFileListWidget.clear()
|
||||||
self.genericFileListWidget.clear()
|
self.genericFileListWidget.clear()
|
||||||
self.easySlidesFilenameEdit.setText(u'')
|
self.easySlidesFilenameEdit.setText(u'')
|
||||||
@ -784,6 +821,12 @@ class SongImportForm(OpenLPWizard):
|
|||||||
filenames=self.getListOfFiles(
|
filenames=self.getListOfFiles(
|
||||||
self.dreamBeamFileListWidget)
|
self.dreamBeamFileListWidget)
|
||||||
)
|
)
|
||||||
|
elif source_format == SongFormat.PowerSong:
|
||||||
|
# Import PowerSong songs
|
||||||
|
importer = self.plugin.importSongs(SongFormat.PowerSong,
|
||||||
|
filenames=self.getListOfFiles(
|
||||||
|
self.powerSongFileListWidget)
|
||||||
|
)
|
||||||
elif source_format == SongFormat.SongsOfFellowship:
|
elif source_format == SongFormat.SongsOfFellowship:
|
||||||
# Import a Songs of Fellowship RTF file
|
# Import a Songs of Fellowship RTF file
|
||||||
importer = self.plugin.importSongs(SongFormat.SongsOfFellowship,
|
importer = self.plugin.importSongs(SongFormat.SongsOfFellowship,
|
||||||
|
@ -36,6 +36,7 @@ from openlyricsimport import OpenLyricsImport
|
|||||||
from wowimport import WowImport
|
from wowimport import WowImport
|
||||||
from cclifileimport import CCLIFileImport
|
from cclifileimport import CCLIFileImport
|
||||||
from dreambeamimport import DreamBeamImport
|
from dreambeamimport import DreamBeamImport
|
||||||
|
from powersongimport import PowerSongImport
|
||||||
from ewimport import EasyWorshipSongImport
|
from ewimport import EasyWorshipSongImport
|
||||||
from songbeamerimport import SongBeamerImport
|
from songbeamerimport import SongBeamerImport
|
||||||
from songshowplusimport import SongShowPlusImport
|
from songshowplusimport import SongShowPlusImport
|
||||||
@ -79,16 +80,17 @@ class SongFormat(object):
|
|||||||
EasyWorship = 7
|
EasyWorship = 7
|
||||||
FoilPresenter = 8
|
FoilPresenter = 8
|
||||||
OpenSong = 9
|
OpenSong = 9
|
||||||
SongBeamer = 10
|
PowerSong = 10
|
||||||
SongShowPlus = 11
|
SongBeamer = 11
|
||||||
SongsOfFellowship = 12
|
SongShowPlus = 12
|
||||||
WordsOfWorship = 13
|
SongsOfFellowship = 13
|
||||||
#CSV = 14
|
WordsOfWorship = 14
|
||||||
|
#CSV = 15
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_class(format):
|
def get_class(format):
|
||||||
"""
|
"""
|
||||||
Return the appropriate imeplementation class.
|
Return the appropriate implementation class.
|
||||||
|
|
||||||
``format``
|
``format``
|
||||||
The song format.
|
The song format.
|
||||||
@ -111,6 +113,8 @@ class SongFormat(object):
|
|||||||
return CCLIFileImport
|
return CCLIFileImport
|
||||||
elif format == SongFormat.DreamBeam:
|
elif format == SongFormat.DreamBeam:
|
||||||
return DreamBeamImport
|
return DreamBeamImport
|
||||||
|
elif format == SongFormat.PowerSong:
|
||||||
|
return PowerSongImport
|
||||||
elif format == SongFormat.EasySlides:
|
elif format == SongFormat.EasySlides:
|
||||||
return EasySlidesImport
|
return EasySlidesImport
|
||||||
elif format == SongFormat.EasyWorship:
|
elif format == SongFormat.EasyWorship:
|
||||||
@ -139,6 +143,7 @@ class SongFormat(object):
|
|||||||
SongFormat.EasyWorship,
|
SongFormat.EasyWorship,
|
||||||
SongFormat.FoilPresenter,
|
SongFormat.FoilPresenter,
|
||||||
SongFormat.OpenSong,
|
SongFormat.OpenSong,
|
||||||
|
SongFormat.PowerSong,
|
||||||
SongFormat.SongBeamer,
|
SongFormat.SongBeamer,
|
||||||
SongFormat.SongShowPlus,
|
SongFormat.SongShowPlus,
|
||||||
SongFormat.SongsOfFellowship,
|
SongFormat.SongsOfFellowship,
|
||||||
|
195
openlp/plugins/songs/lib/powersongimport.py
Normal file
195
openlp/plugins/songs/lib/powersongimport.py
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
# -*- 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, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
|
||||||
|
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
|
||||||
|
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||||
|
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, 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:`powersongimport` module provides the functionality for importing
|
||||||
|
PowerSong songs into the OpenLP database.
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from openlp.core.lib import translate
|
||||||
|
from openlp.plugins.songs.lib.songimport import SongImport
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class PowerSongImport(SongImport):
|
||||||
|
"""
|
||||||
|
The :class:`PowerSongImport` class provides the ability to import song files
|
||||||
|
from PowerSong.
|
||||||
|
|
||||||
|
**PowerSong 1.0 Song File Format:**
|
||||||
|
|
||||||
|
The file has a number of label-field (think key-value) pairs.
|
||||||
|
|
||||||
|
Label and Field strings:
|
||||||
|
|
||||||
|
* Every label and field is a variable length string preceded by an
|
||||||
|
integer specifying it's byte length.
|
||||||
|
* Integer is 32-bit but is encoded in 7-bit format to save space. Thus
|
||||||
|
if length will fit in 7 bits (ie <= 127) it takes up only one byte.
|
||||||
|
|
||||||
|
Metadata fields:
|
||||||
|
|
||||||
|
* Every PowerSong file has a TITLE field.
|
||||||
|
* There is zero or more AUTHOR fields.
|
||||||
|
* There is always a COPYRIGHTLINE label, but its field may be empty.
|
||||||
|
This field may also contain a CCLI number: e.g. "CCLI 176263".
|
||||||
|
|
||||||
|
Lyrics fields:
|
||||||
|
|
||||||
|
* Each verse is contained in a PART field.
|
||||||
|
* Lines have Windows line endings ``CRLF`` (0x0d, 0x0a).
|
||||||
|
* There is no concept of verse types.
|
||||||
|
|
||||||
|
Valid extensions for a PowerSong song file are:
|
||||||
|
|
||||||
|
* .song
|
||||||
|
"""
|
||||||
|
|
||||||
|
def doImport(self):
|
||||||
|
"""
|
||||||
|
Receive a list of files to import.
|
||||||
|
"""
|
||||||
|
if not isinstance(self.importSource, list):
|
||||||
|
self.logError(unicode(translate('SongsPlugin.PowerSongImport',
|
||||||
|
'No files to import.')))
|
||||||
|
return
|
||||||
|
self.importWizard.progressBar.setMaximum(len(self.importSource))
|
||||||
|
for file in self.importSource:
|
||||||
|
if self.stopImportFlag:
|
||||||
|
return
|
||||||
|
self.setDefaults()
|
||||||
|
parse_error = False
|
||||||
|
with open(file, 'rb') as song_data:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
label = self._readString(song_data)
|
||||||
|
if not label:
|
||||||
|
break
|
||||||
|
field = self._readString(song_data)
|
||||||
|
except ValueError:
|
||||||
|
parse_error = True
|
||||||
|
self.logError(file, unicode(
|
||||||
|
translate('SongsPlugin.PowerSongImport',
|
||||||
|
'Invalid PowerSong file. Unexpected byte value.')))
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if label == u'TITLE':
|
||||||
|
self.title = field.replace(u'\n', u' ')
|
||||||
|
elif label == u'AUTHOR':
|
||||||
|
self.parseAuthor(field)
|
||||||
|
elif label == u'COPYRIGHTLINE':
|
||||||
|
found_copyright = True
|
||||||
|
self._parseCopyrightCCLI(field)
|
||||||
|
elif label == u'PART':
|
||||||
|
self.addVerse(field)
|
||||||
|
if parse_error:
|
||||||
|
continue
|
||||||
|
# Check that file had TITLE field
|
||||||
|
if not self.title:
|
||||||
|
self.logError(file, unicode(
|
||||||
|
translate('SongsPlugin.PowerSongImport',
|
||||||
|
'Invalid PowerSong file. Missing "TITLE" header.')))
|
||||||
|
continue
|
||||||
|
# Check that file had COPYRIGHTLINE label
|
||||||
|
if not found_copyright:
|
||||||
|
self.logError(file, unicode(
|
||||||
|
translate('SongsPlugin.PowerSongImport',
|
||||||
|
'"%s" Invalid PowerSong file. Missing "COPYRIGHTLINE" '
|
||||||
|
'header.' % self.title)))
|
||||||
|
continue
|
||||||
|
# Check that file had at least one verse
|
||||||
|
if not self.verses:
|
||||||
|
self.logError(file, unicode(
|
||||||
|
translate('SongsPlugin.PowerSongImport',
|
||||||
|
'"%s" Verses not found. Missing "PART" header.'
|
||||||
|
% self.title)))
|
||||||
|
continue
|
||||||
|
if not self.finish():
|
||||||
|
self.logError(file)
|
||||||
|
|
||||||
|
def _readString(self, file_object):
|
||||||
|
"""
|
||||||
|
Reads in next variable-length string.
|
||||||
|
"""
|
||||||
|
string_len = self._read7BitEncodedInteger(file_object)
|
||||||
|
return unicode(file_object.read(string_len), u'utf-8', u'ignore')
|
||||||
|
|
||||||
|
def _read7BitEncodedInteger(self, file_object):
|
||||||
|
"""
|
||||||
|
Reads in a 32-bit integer in compressed 7-bit format.
|
||||||
|
|
||||||
|
Accomplished by reading the integer 7 bits at a time. The high bit
|
||||||
|
of the byte when set means to continue reading more bytes.
|
||||||
|
If the integer will fit in 7 bits (ie <= 127), it only takes up one
|
||||||
|
byte. Otherwise, it may take up to 5 bytes.
|
||||||
|
|
||||||
|
Reference: .NET method System.IO.BinaryReader.Read7BitEncodedInt
|
||||||
|
"""
|
||||||
|
val = 0
|
||||||
|
shift = 0
|
||||||
|
i = 0
|
||||||
|
while True:
|
||||||
|
# Check for corrupted stream (since max 5 bytes per 32-bit integer)
|
||||||
|
if i == 5:
|
||||||
|
raise ValueError
|
||||||
|
byte = self._readByte(file_object)
|
||||||
|
# Strip high bit and shift left
|
||||||
|
val += (byte & 0x7f) << shift
|
||||||
|
shift += 7
|
||||||
|
high_bit_set = byte & 0x80
|
||||||
|
if not high_bit_set:
|
||||||
|
break
|
||||||
|
i += 1
|
||||||
|
return val
|
||||||
|
|
||||||
|
def _readByte(self, file_object):
|
||||||
|
"""
|
||||||
|
Reads in next byte as an unsigned integer
|
||||||
|
|
||||||
|
Note: returns 0 at end of file.
|
||||||
|
"""
|
||||||
|
byte_str = file_object.read(1)
|
||||||
|
# If read result is empty, then reached end of file
|
||||||
|
if not byte_str:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return ord(byte_str)
|
||||||
|
|
||||||
|
def _parseCopyrightCCLI(self, field):
|
||||||
|
"""
|
||||||
|
Look for CCLI song number, and get copyright
|
||||||
|
"""
|
||||||
|
copyright, sep, ccli_no = field.rpartition(u'CCLI')
|
||||||
|
if not sep:
|
||||||
|
copyright = ccli_no
|
||||||
|
ccli_no = u''
|
||||||
|
if copyright:
|
||||||
|
self.addCopyright(copyright.rstrip(u'\n').replace(u'\n', u' '))
|
||||||
|
if ccli_no:
|
||||||
|
ccli_no = ccli_no.strip(u' :')
|
||||||
|
if ccli_no.isdigit():
|
||||||
|
self.ccliNumber = ccli_no
|
@ -107,11 +107,11 @@ class SongImport(QtCore.QObject):
|
|||||||
|
|
||||||
``filepath``
|
``filepath``
|
||||||
This should be the file path if ``self.importSource`` is a list
|
This should be the file path if ``self.importSource`` is a list
|
||||||
with different files. If it is not a list, but a single file (for
|
with different files. If it is not a list, but a single file (for
|
||||||
instance a database), then this should be the song's title.
|
instance a database), then this should be the song's title.
|
||||||
|
|
||||||
``reason``
|
``reason``
|
||||||
The reason, why the import failed. The string should be as
|
The reason why the import failed. The string should be as
|
||||||
informative as possible.
|
informative as possible.
|
||||||
"""
|
"""
|
||||||
self.setDefaults()
|
self.setDefaults()
|
||||||
|
@ -71,7 +71,7 @@ class WowImport(SongImport):
|
|||||||
* ``SOH`` (0x01) - Chorus
|
* ``SOH`` (0x01) - Chorus
|
||||||
* ``STX`` (0x02) - Bridge
|
* ``STX`` (0x02) - Bridge
|
||||||
|
|
||||||
Blocks are seperated by two bytes. The first byte is 0x01, and the
|
Blocks are separated by two bytes. The first byte is 0x01, and the
|
||||||
second byte is 0x80.
|
second byte is 0x80.
|
||||||
|
|
||||||
Lines:
|
Lines:
|
||||||
@ -126,7 +126,7 @@ class WowImport(SongImport):
|
|||||||
('Invalid Words of Worship song file. Missing '
|
('Invalid Words of Worship song file. Missing '
|
||||||
'"CSongDoc::CBlock" string.'))))
|
'"CSongDoc::CBlock" string.'))))
|
||||||
continue
|
continue
|
||||||
# Seek to the beging of the first block
|
# Seek to the beginning of the first block
|
||||||
song_data.seek(82)
|
song_data.seek(82)
|
||||||
for block in range(no_of_blocks):
|
for block in range(no_of_blocks):
|
||||||
self.linesToRead = ord(song_data.read(4)[:1])
|
self.linesToRead = ord(song_data.read(4)[:1])
|
||||||
@ -140,7 +140,7 @@ class WowImport(SongImport):
|
|||||||
block_text += self.lineText
|
block_text += self.lineText
|
||||||
self.linesToRead -= 1
|
self.linesToRead -= 1
|
||||||
block_type = BLOCK_TYPES[ord(song_data.read(4)[:1])]
|
block_type = BLOCK_TYPES[ord(song_data.read(4)[:1])]
|
||||||
# Blocks are seperated by 2 bytes, skip them, but not if
|
# Blocks are separated by 2 bytes, skip them, but not if
|
||||||
# this is the last block!
|
# this is the last block!
|
||||||
if block + 1 < no_of_blocks:
|
if block + 1 < no_of_blocks:
|
||||||
song_data.seek(2, os.SEEK_CUR)
|
song_data.seek(2, os.SEEK_CUR)
|
||||||
|
Loading…
Reference in New Issue
Block a user