openlp/openlp/plugins/songs/lib/mediaitem.py

537 lines
26 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2013-01-06 17:25:49 +00:00
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
2012-12-29 20:56:56 +00:00
# Copyright (c) 2008-2013 Raoul Snyman #
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
2012-11-11 21:16:14 +00:00
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
2012-10-21 13:16:22 +00:00
# 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, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
import logging
import re
import os
import shutil
from PyQt4 import QtCore, QtGui
2010-12-28 21:12:20 +00:00
from sqlalchemy.sql import or_
2013-01-27 09:57:03 +00:00
from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, translate, check_item_selected, \
PluginStatus, create_separated_list, check_directory_exists, ServiceItemContext, Settings, UiStrings
from openlp.core.lib.ui import create_widget_action
2012-12-08 21:18:45 +00:00
from openlp.core.utils import AppLocation
2013-01-27 09:57:03 +00:00
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, SongImportForm, SongExportForm
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, clean_string, natcmp
from openlp.plugins.songs.lib.db import Author, Song, Book, MediaFile
2011-02-11 21:17:56 +00:00
from openlp.plugins.songs.lib.ui import SongStrings
2010-02-27 15:31:23 +00:00
log = logging.getLogger(__name__)
2012-11-08 21:28:42 +00:00
2011-02-12 22:01:18 +00:00
class SongSearch(object):
"""
An enumeration for song search methods.
"""
Entire = 1
Titles = 2
Lyrics = 3
Authors = 4
Books = 5
Themes = 6
2011-02-12 22:01:18 +00:00
2011-02-25 17:27:06 +00:00
class SongMediaItem(MediaManagerItem):
"""
This is the custom media manager item for Songs.
"""
log.info(u'Song Media Item loaded')
2010-09-15 17:55:27 +00:00
def __init__(self, parent, plugin, icon):
2009-09-26 07:13:59 +00:00
self.IconPath = u'songs/song'
2011-05-28 09:53:37 +00:00
MediaManagerItem.__init__(self, parent, plugin, icon)
self.editSongForm = EditSongForm(self, self.main_window, self.plugin.manager)
2011-05-28 09:53:37 +00:00
self.openLyrics = OpenLyrics(self.plugin.manager)
2010-04-06 19:16:14 +00:00
self.singleServiceItem = False
2013-01-06 17:25:49 +00:00
self.songMaintenanceForm = SongMaintenanceForm(self.plugin.manager, self)
# Holds information about whether the edit is remotely triggered and
2009-11-03 19:21:58 +00:00
# which Song is required.
2009-11-03 06:15:35 +00:00
self.remoteSong = -1
self.editItem = None
self.quickPreviewAllowed = True
self.hasSearch = True
def _updateBackgroundAudio(self, song, item):
song.media_files = []
for i, bga in enumerate(item.background_audio):
dest_file = os.path.join(
2013-01-06 17:25:49 +00:00
AppLocation.get_section_data_path(self.plugin.name), u'audio', str(song.id), os.path.split(bga)[1])
2012-07-07 14:54:14 +00:00
check_directory_exists(os.path.split(dest_file)[0])
2013-01-06 17:25:49 +00:00
shutil.copyfile(os.path.join(AppLocation.get_section_data_path(u'servicemanager'), bga),
dest_file)
song.media_files.append(MediaFile.populate(
weight=i, file_name=dest_file))
self.plugin.manager.save_object(song, True)
2009-09-26 07:13:59 +00:00
def addEndHeaderBar(self):
self.toolbar.addSeparator()
## Song Maintenance Button ##
2013-01-06 17:25:49 +00:00
self.maintenanceAction = self.toolbar.addToolbarAction('maintenanceAction',
icon=':/songs/song_maintenance.png',
triggers=self.onSongMaintenanceClick)
2011-12-30 21:40:13 +00:00
self.addSearchToToolBar()
# Signals and slots
2013-01-06 17:25:49 +00:00
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'songs_load_list'), self.onSongListLoad)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configUpdated)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'songs_preview'), self.onPreviewClick)
QtCore.QObject.connect(self.searchTextEdit, QtCore.SIGNAL(u'cleared()'), self.onClearTextButtonClick)
QtCore.QObject.connect(self.searchTextEdit, QtCore.SIGNAL(u'searchTypeChanged(int)'),
self.onSearchTextButtonClicked)
2009-10-17 05:47:17 +00:00
2011-07-01 16:59:56 +00:00
def addCustomContextActions(self):
create_widget_action(self.listView, separator=True)
create_widget_action(self.listView,
2013-01-06 17:25:49 +00:00
text=translate('OpenLP.MediaManagerItem', '&Clone'), icon=u':/general/general_clone.png',
triggers=self.onCloneClick)
def onFocus(self):
self.searchTextEdit.setFocus()
2009-10-17 05:47:17 +00:00
def configUpdated(self):
self.searchAsYouType = Settings().value(self.settingsSection + u'/search as type')
self.updateServiceOnEdit = Settings().value(self.settingsSection + u'/update service on edit')
self.addSongFromService = Settings().value(self.settingsSection + u'/add song from service',)
2009-08-26 05:00:19 +00:00
def retranslateUi(self):
self.searchTextLabel.setText(u'%s:' % UiStrings().Search)
self.searchTextButton.setText(UiStrings().Search)
self.maintenanceAction.setText(SongStrings.SongMaintenance)
self.maintenanceAction.setToolTip(translate('SongsPlugin.MediaItem',
2011-05-06 05:17:13 +00:00
'Maintain the lists of authors, topics and books.'))
def initialise(self):
self.searchTextEdit.setSearchTypes([
2011-02-12 22:01:18 +00:00
(SongSearch.Entire, u':/songs/song_search_all.png',
translate('SongsPlugin.MediaItem', 'Entire Song'),
translate('SongsPlugin.MediaItem', 'Search Entire Song...')),
2011-02-12 22:01:18 +00:00
(SongSearch.Titles, u':/songs/song_search_title.png',
translate('SongsPlugin.MediaItem', 'Titles'),
translate('SongsPlugin.MediaItem', 'Search Titles...')),
2011-02-12 22:01:18 +00:00
(SongSearch.Lyrics, u':/songs/song_search_lyrics.png',
translate('SongsPlugin.MediaItem', 'Lyrics'),
translate('SongsPlugin.MediaItem', 'Search Lyrics...')),
2013-01-06 17:25:49 +00:00
(SongSearch.Authors, u':/songs/song_search_author.png', SongStrings.Authors,
translate('SongsPlugin.MediaItem', 'Search Authors...')),
2013-01-06 17:25:49 +00:00
(SongSearch.Books, u':/songs/song_book_edit.png', SongStrings.SongBooks,
translate('SongsPlugin.MediaItem', 'Search Song Books...')),
(SongSearch.Themes, u':/slides/slide_theme.png',
2012-03-26 09:41:59 +00:00
UiStrings().Themes, UiStrings().SearchThemes)
2010-12-28 21:12:20 +00:00
])
self.searchTextEdit.setCurrentSearchType(Settings().value(u'%s/last search type' % self.settingsSection))
2009-10-17 05:47:17 +00:00
self.configUpdated()
def onSearchTextButtonClicked(self):
# Save the current search type to the configuration.
2013-01-06 17:25:49 +00:00
Settings().setValue(u'%s/last search type' % self.settingsSection, self.searchTextEdit.currentSearchType())
# Reload the list considering the new search type.
search_keywords = unicode(self.searchTextEdit.displayText())
2009-09-21 23:11:50 +00:00
search_results = []
search_type = self.searchTextEdit.currentSearchType()
2011-02-12 22:01:18 +00:00
if search_type == SongSearch.Entire:
2010-12-28 21:12:20 +00:00
log.debug(u'Entire Song Search')
search_results = self.searchEntire(search_keywords)
2010-12-28 21:12:20 +00:00
self.displayResultsSong(search_results)
2011-02-12 22:01:18 +00:00
elif search_type == SongSearch.Titles:
2009-06-21 17:45:59 +00:00
log.debug(u'Titles Search')
2011-05-28 09:53:37 +00:00
search_results = self.plugin.manager.get_all_objects(Song,
2013-01-06 17:25:49 +00:00
Song.search_title.like(u'%' + clean_string(search_keywords) + u'%'))
2009-06-21 17:45:59 +00:00
self.displayResultsSong(search_results)
2011-02-12 22:01:18 +00:00
elif search_type == SongSearch.Lyrics:
2009-06-21 17:45:59 +00:00
log.debug(u'Lyrics Search')
2011-05-28 09:53:37 +00:00
search_results = self.plugin.manager.get_all_objects(Song,
2013-01-06 17:25:49 +00:00
Song.search_lyrics.like(u'%' + clean_string(search_keywords) + u'%'))
2009-06-21 17:45:59 +00:00
self.displayResultsSong(search_results)
2011-02-12 22:01:18 +00:00
elif search_type == SongSearch.Authors:
2009-06-21 17:45:59 +00:00
log.debug(u'Authors Search')
2011-05-28 09:53:37 +00:00
search_results = self.plugin.manager.get_all_objects(Author,
2013-01-06 17:25:49 +00:00
Author.display_name.like(u'%' + search_keywords + u'%'), Author.display_name.asc())
2009-06-21 17:45:59 +00:00
self.displayResultsAuthor(search_results)
elif search_type == SongSearch.Books:
log.debug(u'Books Search')
search_results = self.plugin.manager.get_all_objects(Book,
2013-01-06 17:25:49 +00:00
Book.name.like(u'%' + search_keywords + u'%'), Book.name.asc())
song_number = False
if not search_results:
search_keywords = search_keywords.rpartition(' ')
search_results = self.plugin.manager.get_all_objects(Book,
2013-01-06 17:25:49 +00:00
Book.name.like(u'%' + search_keywords[0] + u'%'), Book.name.asc())
song_number = re.sub(r'[^0-9]', u'', search_keywords[2])
self.displayResultsBook(search_results, song_number)
2011-02-12 22:01:18 +00:00
elif search_type == SongSearch.Themes:
2010-12-23 17:51:32 +00:00
log.debug(u'Theme Search')
2011-05-28 09:53:37 +00:00
search_results = self.plugin.manager.get_all_objects(Song,
2011-06-01 22:47:42 +00:00
Song.theme_name.like(u'%' + search_keywords + u'%'))
2010-12-23 17:51:32 +00:00
self.displayResultsSong(search_results)
2011-09-02 19:04:07 +00:00
self.checkSearchResult()
def searchEntire(self, search_keywords):
2011-05-28 09:53:37 +00:00
return self.plugin.manager.get_all_objects(Song,
2013-01-06 17:25:49 +00:00
or_(Song.search_title.like(u'%' + clean_string(search_keywords) + u'%'),
Song.search_lyrics.like(u'%' + clean_string(search_keywords) + u'%'),
Song.comments.like(u'%' + search_keywords.lower() + u'%')))
def onSongListLoad(self):
"""
Handle the exit from the edit dialog and trigger remote updates
of songs
"""
2011-03-08 16:46:53 +00:00
log.debug(u'onSongListLoad - start')
# Called to redisplay the song list screen edit from a search
2011-02-25 17:05:01 +00:00
# or from the exit of the Song edit dialog. If remote editing is active
# Trigger it and clean up so it will not update again.
# Push edits to the service manager to update items
2013-01-06 17:25:49 +00:00
if self.editItem and self.updateServiceOnEdit and not self.remoteTriggered:
item = self.buildServiceItem(self.editItem)
2013-01-27 20:36:18 +00:00
self.service_manager.replace_service_item(item)
self.onSearchTextButtonClicked()
2011-03-08 16:46:53 +00:00
log.debug(u'onSongListLoad - finished')
2009-06-21 17:45:59 +00:00
def displayResultsSong(self, searchresults):
log.debug(u'display results Song')
self.saveAutoSelectId()
2010-07-07 16:03:30 +00:00
self.listView.clear()
2012-11-08 21:28:42 +00:00
searchresults.sort(cmp=natcmp, key=lambda song: song.sort_key)
for song in searchresults:
2011-12-03 09:05:01 +00:00
# Do not display temporary songs
2011-12-03 19:08:02 +00:00
if song.temporary:
2011-12-03 17:01:57 +00:00
continue
2011-02-25 16:29:03 +00:00
author_list = [author.display_name for author in song.authors]
2010-06-05 23:05:53 +00:00
song_title = unicode(song.title)
2013-01-06 17:25:49 +00:00
song_detail = u'%s (%s)' % (song_title, create_separated_list(author_list))
song_name = QtGui.QListWidgetItem(song_detail)
2012-05-17 15:13:09 +00:00
song_name.setData(QtCore.Qt.UserRole, song.id)
2010-07-07 16:03:30 +00:00
self.listView.addItem(song_name)
# Auto-select the item if name has been set
if song.id == self.autoSelectId:
self.listView.setCurrentItem(song_name)
self.autoSelectId = -1
2009-06-21 17:45:59 +00:00
def displayResultsAuthor(self, searchresults):
log.debug(u'display results Author')
2010-07-07 16:03:30 +00:00
self.listView.clear()
2009-06-21 17:45:59 +00:00
for author in searchresults:
for song in author.songs:
2011-12-03 09:05:01 +00:00
# Do not display temporary songs
2011-12-03 19:08:02 +00:00
if song.temporary:
2011-12-03 17:01:57 +00:00
continue
song_detail = u'%s (%s)' % (author.display_name, song.title)
2009-06-21 17:45:59 +00:00
song_name = QtGui.QListWidgetItem(song_detail)
2012-05-17 15:13:09 +00:00
song_name.setData(QtCore.Qt.UserRole, song.id)
self.listView.addItem(song_name)
def displayResultsBook(self, searchresults, song_number=False):
log.debug(u'display results Book')
self.listView.clear()
for book in searchresults:
songs = sorted(book.songs, key=lambda song:
int(re.match(r'[0-9]+', u'0' + song.song_number).group()))
for song in songs:
# Do not display temporary songs
if song.temporary:
continue
if song_number and not song_number in song.song_number:
continue
2013-01-06 17:25:49 +00:00
song_detail = u'%s - %s (%s)' % (book.name, song.song_number, song.title)
song_name = QtGui.QListWidgetItem(song_detail)
2012-05-17 15:13:09 +00:00
song_name.setData(QtCore.Qt.UserRole, song.id)
2010-07-07 16:03:30 +00:00
self.listView.addItem(song_name)
2009-06-21 17:45:59 +00:00
def onClearTextButtonClick(self):
"""
Clear the search text.
"""
self.searchTextEdit.clear()
self.onSearchTextButtonClicked()
def onSearchTextEditChanged(self, text):
2009-11-03 06:15:35 +00:00
"""
If search as type enabled invoke the search on each key press.
If the Lyrics are being searched do not start till 7 characters
have been entered.
"""
2009-10-17 05:47:17 +00:00
if self.searchAsYouType:
search_length = 1
2011-02-20 17:52:22 +00:00
if self.searchTextEdit.currentSearchType() == SongSearch.Entire:
2011-03-11 18:03:16 +00:00
search_length = 4
2011-03-09 18:14:50 +00:00
elif self.searchTextEdit.currentSearchType() == SongSearch.Lyrics:
2011-03-11 18:03:16 +00:00
search_length = 3
2009-10-17 05:47:17 +00:00
if len(text) > search_length:
self.onSearchTextButtonClicked()
elif not text:
2011-03-09 18:14:50 +00:00
self.onClearTextButtonClick()
2010-04-02 12:23:40 +00:00
def onImportClick(self):
2011-09-05 12:51:16 +00:00
if not hasattr(self, u'importWizard'):
self.importWizard = SongImportForm(self, self.plugin)
self.importWizard.exec_()
# Run song load as list may have been cancelled but some songs loaded
Receiver.send_message(u'songs_load_list')
2010-04-02 12:23:40 +00:00
2011-01-23 16:05:46 +00:00
def onExportClick(self):
2011-09-05 12:51:16 +00:00
if not hasattr(self, u'exportWizard'):
self.exportWizard = SongExportForm(self, self.plugin)
self.exportWizard.exec_()
2011-01-23 16:05:46 +00:00
2009-09-26 07:13:59 +00:00
def onNewClick(self):
log.debug(u'onNewClick')
2011-09-05 12:51:16 +00:00
self.editSongForm.newSong()
self.editSongForm.exec_()
2011-06-03 03:39:28 +00:00
self.onClearTextButtonClick()
self.onSelectionChange()
self.autoSelectId = -1
def onSongMaintenanceClick(self):
2011-09-05 12:51:16 +00:00
self.songMaintenanceForm.exec_()
2013-01-27 09:57:03 +00:00
def onRemoteEdit(self, song_id, preview=False):
2009-11-03 06:15:35 +00:00
"""
Called by ServiceManager or SlideController by event passing
the Song Id in the payload along with an indicator to say which
type of display is required.
"""
2013-01-27 09:57:03 +00:00
log.debug(u'onRemoteEdit for song %s' % song_id)
2011-04-10 18:44:27 +00:00
song_id = int(song_id)
2011-05-28 09:53:37 +00:00
valid = self.plugin.manager.get_object(Song, song_id)
2009-11-03 19:01:53 +00:00
if valid:
2013-01-27 09:57:03 +00:00
self.editSongForm.loadSong(song_id, preview)
if self.editSongForm.exec_() == QtGui.QDialog.Accepted:
self.autoSelectId = -1
self.onSongListLoad()
self.remoteSong = song_id
self.remoteTriggered = True
item = self.buildServiceItem(remote=True)
self.remoteSong = -1
self.remoteTriggered = None
if item:
return item
return None
2009-10-29 09:18:26 +00:00
def onEditClick(self):
"""
Edit a song
"""
log.debug(u'onEditClick')
if check_item_selected(self.listView, UiStrings().SelectEdit):
self.editItem = self.listView.currentItem()
2012-05-19 09:13:32 +00:00
item_id = self.editItem.data(QtCore.Qt.UserRole)
2011-09-05 12:51:16 +00:00
self.editSongForm.loadSong(item_id, False)
self.editSongForm.exec_()
self.autoSelectId = -1
self.onSongListLoad()
2011-03-11 15:53:26 +00:00
self.editItem = None
2009-09-26 07:13:59 +00:00
def onDeleteClick(self):
"""
Remove a song from the list and database
"""
if check_item_selected(self.listView, UiStrings().SelectDelete):
2010-07-07 16:03:30 +00:00
items = self.listView.selectedIndexes()
2011-01-02 17:24:47 +00:00
if QtGui.QMessageBox.question(self,
UiStrings().ConfirmDelete,
2013-01-06 17:25:49 +00:00
translate('SongsPlugin.MediaItem', 'Are you sure you want to delete the %n selected song(s)?', '',
QtCore.QCoreApplication.CodecForTr, len(items)),
2013-01-06 17:25:49 +00:00
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:
2010-04-04 13:53:39 +00:00
return
2013-02-03 09:07:31 +00:00
self.openlp_core.set_busy_cursor()
self.main_window.displayProgressBar(len(items))
2010-04-03 19:17:37 +00:00
for item in items:
2012-05-19 09:13:32 +00:00
item_id = item.data(QtCore.Qt.UserRole)
2013-01-06 17:25:49 +00:00
media_files = self.plugin.manager.get_all_objects(MediaFile, MediaFile.song_id == item_id)
for media_file in media_files:
try:
os.remove(media_file.file_name)
except:
2013-01-06 17:25:49 +00:00
log.exception('Could not remove file: %s', media_file.file_name)
try:
2013-01-06 17:25:49 +00:00
save_path = os.path.join(AppLocation.get_section_data_path(self.plugin.name), 'audio', str(item_id))
if os.path.exists(save_path):
os.rmdir(save_path)
except OSError:
log.exception(u'Could not remove directory: %s', save_path)
2011-05-28 09:53:37 +00:00
self.plugin.manager.delete_object(Song, item_id)
self.main_window.incrementProgressBar()
self.main_window.finishedProgressBar()
2013-02-03 09:07:31 +00:00
self.openlp_core.set_normal_cursor()
self.onSearchTextButtonClicked()
def onCloneClick(self):
"""
Clone a Song
"""
log.debug(u'onCloneClick')
if check_item_selected(self.listView, UiStrings().SelectEdit):
self.editItem = self.listView.currentItem()
2012-05-19 09:13:32 +00:00
item_id = self.editItem.data(QtCore.Qt.UserRole)
old_song = self.plugin.manager.get_object(Song, item_id)
song_xml = self.openLyrics.song_to_xml(old_song)
new_song = self.openLyrics.xml_to_song(song_xml)
new_song.title = u'%s <%s>' % (new_song.title,
2013-01-06 17:25:49 +00:00
translate('SongsPlugin.MediaItem', 'copy', 'For song cloning'))
self.plugin.manager.save_object(new_song)
self.onSongListLoad()
def generateSlideData(self, service_item, item=None, xmlVersion=False,
2013-01-27 09:57:03 +00:00
remote=False, context=ServiceItemContext.Service):
2013-01-06 17:25:49 +00:00
log.debug(u'generateSlideData: %s, %s, %s' % (service_item, item, self.remoteSong))
2011-09-24 15:18:48 +00:00
item_id = self._getIdOfItemToGenerate(item, self.remoteSong)
2011-08-28 17:45:13 +00:00
service_item.add_capability(ItemCapabilities.CanEdit)
service_item.add_capability(ItemCapabilities.CanPreview)
service_item.add_capability(ItemCapabilities.CanLoop)
2010-09-30 05:12:06 +00:00
service_item.add_capability(ItemCapabilities.OnLoadUpdate)
service_item.add_capability(ItemCapabilities.AddIfNewItem)
service_item.add_capability(ItemCapabilities.CanSoftBreak)
2011-05-28 09:53:37 +00:00
song = self.plugin.manager.get_object(Song, item_id)
service_item.theme = song.theme_name
service_item.edit_id = item_id
if song.lyrics.startswith(u'<?xml version='):
verse_list = SongXML().get_verses(song.lyrics)
# no verse list or only 1 space (in error)
verse_tags_translated = False
2013-01-27 09:57:03 +00:00
if VerseType.from_translated_string(unicode(verse_list[0][0][u'type'])) is not None:
verse_tags_translated = True
if not song.verse_order.strip():
for verse in verse_list:
2011-02-17 19:46:01 +00:00
# We cannot use from_loose_input() here, because database
# is supposed to contain English lowercase singlechar tags.
verse_tag = verse[0][u'type']
verse_index = None
if len(verse_tag) > 1:
2013-01-06 17:25:49 +00:00
verse_index = VerseType.from_translated_string(verse_tag)
if verse_index is None:
verse_index = VerseType.from_string(verse_tag, None)
if verse_index is None:
verse_index = VerseType.from_tag(verse_tag)
verse_tag = VerseType.TranslatedTags[verse_index].upper()
verse_def = u'%s%s' % (verse_tag, verse[0][u'label'])
2012-06-10 13:39:45 +00:00
service_item.add_from_text(unicode(verse[1]), verse_def)
else:
# Loop through the verse list and expand the song accordingly.
for order in song.verse_order.lower().split():
if not order:
break
for verse in verse_list:
2013-01-06 17:25:49 +00:00
if verse[0][u'type'][0].lower() == order[0] and (verse[0][u'label'].lower() == order[1:] or \
not order[1:]):
if verse_tags_translated:
2013-01-06 17:25:49 +00:00
verse_index = VerseType.from_translated_tag(verse[0][u'type'])
else:
2013-01-06 17:25:49 +00:00
verse_index = VerseType.from_tag(verse[0][u'type'])
verse_tag = VerseType.TranslatedTags[verse_index]
2013-01-06 17:25:49 +00:00
verse_def = u'%s%s' % (verse_tag, verse[0][u'label'])
2012-06-10 13:39:45 +00:00
service_item.add_from_text(verse[1], verse_def)
else:
verses = song.lyrics.split(u'\n\n')
for slide in verses:
2012-06-10 13:39:45 +00:00
service_item.add_from_text(unicode(slide))
service_item.title = song.title
2011-02-25 16:29:03 +00:00
author_list = [unicode(author.display_name) for author in song.authors]
2011-03-04 17:31:23 +00:00
service_item.raw_footer.append(song.title)
2012-02-16 20:36:35 +00:00
service_item.raw_footer.append(create_separated_list(author_list))
2011-03-04 17:31:23 +00:00
service_item.raw_footer.append(song.copyright)
if Settings().value(u'general/ccli number'):
2013-01-06 17:25:49 +00:00
service_item.raw_footer.append(translate('SongsPlugin.MediaItem', 'CCLI License: ') +
Settings().value(u'general/ccli number'))
2009-10-30 17:44:16 +00:00
service_item.audit = [
2011-02-25 16:29:03 +00:00
song.title, author_list, song.copyright, unicode(song.ccli_number)
2009-10-30 17:44:16 +00:00
]
2013-01-06 17:25:49 +00:00
service_item.data_string = {u'title': song.search_title, u'authors': u', '.join(author_list)}
2010-11-28 13:39:51 +00:00
service_item.xml_version = self.openLyrics.song_to_xml(song)
2011-08-28 17:45:13 +00:00
# Add the audio file to the service item.
if song.media_files:
2011-08-28 17:45:13 +00:00
service_item.add_capability(ItemCapabilities.HasBackgroundAudio)
2013-01-06 17:25:49 +00:00
service_item.background_audio = [m.file_name for m in song.media_files]
2010-07-27 09:32:52 +00:00
return True
2010-09-30 05:12:06 +00:00
def serviceLoad(self, item):
"""
2011-03-14 18:59:59 +00:00
Triggered by a song being loaded by the service manager.
2010-09-30 05:12:06 +00:00
"""
log.debug(u'serviceLoad')
2011-02-05 23:52:05 +00:00
if self.plugin.status != PluginStatus.Active or not item.data_string:
return
if item.data_string[u'title'].find(u'@') == -1:
# This file seems to be an old one (prior to 1.9.5), which means,
# that the search title (data_string[u'title']) is probably wrong.
# We add "@" to search title and hope that we do not add any
# duplicate. This should work for songs without alternate title.
2011-05-28 09:53:37 +00:00
search_results = self.plugin.manager.get_all_objects(Song,
Song.search_title == (re.compile(r'\W+', re.UNICODE).sub(u' ',
2013-01-06 17:25:49 +00:00
item.data_string[u'title'].strip()) + u'@').strip().lower(), Song.search_title.asc())
else:
2011-05-28 09:53:37 +00:00
search_results = self.plugin.manager.get_all_objects(Song,
2013-01-06 17:25:49 +00:00
Song.search_title == item.data_string[u'title'], Song.search_title.asc())
2011-02-05 23:52:05 +00:00
editId = 0
add_song = True
2011-12-10 08:45:17 +00:00
temporary = False
2011-02-05 23:52:05 +00:00
if search_results:
for song in search_results:
author_list = item.data_string[u'authors']
2011-02-05 23:52:05 +00:00
same_authors = True
for author in song.authors:
if author.display_name in author_list:
2013-01-06 17:25:49 +00:00
author_list = author_list.replace(author.display_name, u'', 1)
else:
same_authors = False
break
if same_authors and author_list.strip(u', ') == u'':
2011-02-05 23:52:05 +00:00
add_song = False
editId = song.id
break
# If there's any backing tracks, copy them over.
if item.background_audio:
self._updateBackgroundAudio(song, item)
2011-12-08 19:42:31 +00:00
if add_song and self.addSongFromService:
song = self.openLyrics.xml_to_song(item.xml_version)
# If there's any backing tracks, copy them over.
if item.background_audio:
self._updateBackgroundAudio(song, item)
editId = song.id
self.onSearchTextButtonClicked()
2011-12-10 08:45:17 +00:00
elif add_song and not self.addSongFromService:
# Make sure we temporary import formatting tags.
2011-12-03 09:05:01 +00:00
song = self.openLyrics.xml_to_song(item.xml_version, True)
2011-12-05 19:47:50 +00:00
# If there's any backing tracks, copy them over.
if item.background_audio:
2011-12-05 19:47:50 +00:00
self._updateBackgroundAudio(song, item)
2011-12-03 17:01:57 +00:00
editId = song.id
2011-12-10 08:45:17 +00:00
temporary = True
2011-02-05 23:52:05 +00:00
# Update service with correct song id.
if editId:
2013-02-03 09:07:31 +00:00
self.service_manager.service_item_update(editId, item.unique_identifier, temporary)
2010-12-09 15:08:04 +00:00
def search(self, string, showError):
"""
Search for some songs
"""
search_results = self.searchEntire(string)
return [[song.id, song.title] for song in search_results]