[rhythmbox] lyrics: fetch lyrics from metadata tags
- From: Jonathan Matthew <jmatthew src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rhythmbox] lyrics: fetch lyrics from metadata tags
- Date: Sat, 15 Jul 2017 10:51:55 +0000 (UTC)
commit 1416e4cbeb751acb92d2008d9e4afe9e4967a2be
Author: Christian Weiske <cweiske cweiske de>
Date: Sat Jul 15 20:48:39 2017 +1000
lyrics: fetch lyrics from metadata tags
Only works with ogg tags for now.
https://bugzilla.gnome.org/show_bug.cgi?id=463978
plugins/lyrics/lyrics.py | 95 ++++++++++++++++++++++++++++++++++++++-------
1 files changed, 80 insertions(+), 15 deletions(-)
---
diff --git a/plugins/lyrics/lyrics.py b/plugins/lyrics/lyrics.py
index 13124b3..c0f8de1 100644
--- a/plugins/lyrics/lyrics.py
+++ b/plugins/lyrics/lyrics.py
@@ -32,6 +32,7 @@ import urllib.request
import rb
from gi.repository import Gtk, Gio, GObject, Peas
from gi.repository import RB
+from gi.repository import Gst, GstPbutils
import LyricsParse
from LyricsConfigureDialog import LyricsConfigureDialog
@@ -132,22 +133,33 @@ def build_cache_path(artist, title):
return os.path.join(artist_folder, title[:128] + '.lyric')
class LyricGrabber(object):
+ """
+ Fetch lyrics from several sources.
+
+ 1. Local cache file
+ 2. Lyric tags in file meta data
+ 3. Online services
+ """
def __init__(self, db, entry):
self.db = db
self.entry = entry
-
+
(self.artist, self.title) = parse_song_data(self.db, self.entry)
self.cache_path = build_cache_path(self.artist, self.title)
def verify_lyric(self):
return os.path.exists(self.cache_path)
-
+
def search_lyrics(self, callback, cache_only=False):
+ """
+ Fetch lyrics from cache.
+
+ If no cache file exist, tag extraction is tried next.
+ """
self.callback = callback
-
+
status = self.verify_lyric()
-
if status:
f = open(self.cache_path, 'rt')
text = f.read()
@@ -155,20 +167,73 @@ class LyricGrabber(object):
self.callback(text)
elif cache_only:
self.callback(_("No lyrics found"))
- elif self.artist == "" and self.title == "":
- self.callback(_("No lyrics found"))
else:
- def lyric_callback (text):
- if text is not None:
- f = open(self.cache_path, 'wt')
- f.write (text)
- f.close ()
- self.callback(text)
- else:
- self.callback(_("No lyrics found"))
+ self.search_tags()
+
+ def search_tags(self):
+ """
+ Initiate fetching meta tags.
+
+ Result will be handled in search_tags_result
+ """
+ location = self.entry.get_playback_uri()
+ self.discoverer = GstPbutils.Discoverer(timeout=Gst.SECOND*3)
+ self.discoverer.connect('discovered', self.search_tags_result)
+ self.discoverer.start()
+ self.discoverer.discover_uri_async(location)
+
+ def search_tags_result(self, discoverer, info, error):
+ """
+ Extract lyrics from the file meta data (tags).
+
+ If no lyrics tags are found, online services are tried next.
+
+ Supported file formats and lyrics tags:
+ - ogg/vorbis files with "LYRICS" and "SYNCLYRICS" tag
+ """
+ tags = info.get_tags()
+ if tags is None:
+ self.search_online()
+ return
+ for i in range(tags.get_tag_size("extended-comment")):
+ (exists, value) = tags.get_string_index("extended-comment", i)
+ #ogg/vorbis unsynchronized lyrics
+ if exists and value.startswith("LYRICS"):
+ text = value.replace("LYRICS=", "")
+ self.lyrics_found(text)
+ return
+ #ogg/vorbis synchronized lyrics
+ elif exists and value.startswith("SYNCLYRICS"):
+ text = value.replace("SYNCLYRICS=", "")
+ self.lyrics_found(text)
+ return
+
+ self.search_online()
+
+ def search_online(self):
+ """Initiate searching the online lyrics services"""
+ if self.artist == "" and self.title == "":
+ self.callback(_("No lyrics found"))
+ else:
parser = LyricsParse.Parser(self.artist, self.title)
- parser.get_lyrics(lyric_callback)
+ parser.get_lyrics(self.search_online_result)
+
+ def search_online_result(self, text):
+ """Handle the result of searching online lyrics services"""
+ if text is not None:
+ self.lyrics_found(text)
+ else:
+ self.callback(_("No lyrics found"))
+
+
+ def lyrics_found(self, text):
+ f = open(self.cache_path, 'wt')
+ f.write(text)
+ f.close()
+
+ self.callback(text)
+
class LyricPane(object):
def __init__(self, db, song_info):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]