initial commit

Esse commit está contido em:
timo
2012-11-26 12:54:39 +01:00
commit 50214e6df3
3 arquivos alterados com 548 adições e 0 exclusões
+130
Ver Arquivo
@@ -0,0 +1,130 @@
[Plugin]
Loader=python
Module=ArtDisplay
IAge=2
Depends=rb;artsearch
Name=Cover art
Name[af]=Omslagkuns
Name[ar]=صورة الغلاف
Name[as]=ক'ভাৰ আৰ্ট
Name[be]=Аздоба вокладкі
Name[be@latin]=Azdoba vokładki
Name[bg]=Обложка
Name[br]=Godellig
Name[ca]=Art de la coberta
Name[ca@valencia]=Art de la coberta
Name[cs]=Přebal
Name[da]=Omslag
Name[de]=Cover-Anzeige
Name[dz]=ཁེབས་ཀྱི་རི་མོ།
Name[el]=Εξώφυλλο
Name[en_CA]=Cover art
Name[en_GB]=Cover art
Name[eo]=Kovrilo
Name[es]=Arte de portada
Name[et]=Plaadiümbrised
Name[eu]=Azaleko diseinua
Name[fi]=Kansikuvat
Name[fr]=Pochette
Name[gl]=Portada
Name[gu]=કલાને આવરો
Name[hi]=कवर आर्ट
Name[hu]=Lemezborító
Name[it]=Copertina
Name[ja]=ジャケットのアート
Name[kn]=ಹೊದಿಕೆ ವಿನ್ಯಾಸ
Name[ko]=앨범 표지
Name[lt]=Albumų viršeliai
Name[lv]=Vāciņa attēls
Name[mk]=Слика на омот
Name[mr]=कवर कला
Name[nb]=Omslag
Name[ne]=आवरण कला
Name[nl]=Albumhoezen
Name[nn]=Plateomslag
Name[pa]=ਕਵਰ ਕਲਾਕਾਰ
Name[pl]=Okładki
Name[pt]=Imagem da capa
Name[pt_BR]=Arte de capa
Name[ro]=Copertă
Name[ru]=Обложки альбомов
Name[sk]=Obal
Name[sl]=Ovitki
Name[sr]=Омот албума
Name[sr@latin]=Omot albuma
Name[sv]=Omslagsgrafik
Name[ta]=கவர் ஆர்ட்
Name[te]=ముఖచిత్రం
Name[th]=ภาพปก
Name[tr]=Albüm kapağı
Name[uk]=Обкладинки альбомів
Name[vi]=Ảnh bìa
Name[zh_CN]=封面艺人
Name[zh_HK]=專輯封面
Name[zh_TW]=專輯封面
Description=Fetch album covers from the Internet
Description[af]=Kry albumomslae van die Internet af
Description[ar]=لجلب أغلفة الألبومات من الإنترنت
Description[as]=ইন্টাৰ্নে'টৰ পৰা এল্বামৰ ক'ভাৰ পাওক
Description[be]=Сцягваць вокладкі альбомаў з Інтэрнэту
Description[be@latin]=Zahružaj vokładki albomaŭ z Internetu
Description[bg]=Изтегляне на обложки на албуми от Интернет
Description[bn_IN]=ইন্টারনেট থেকে সংকলনের প্রচ্ছদের ছবি আহরণ করা হবে
Description[br]=Pellgargañ godelligoù albom adalek ar Genrouedad
Description[ca]=Aconsegueix les cobertes dels àlbums d'Internet
Description[ca@valencia]=Aconsegueix les cobertes dels àlbums d'Internet
Description[cs]=Načítat přebaly alb z Internetu
Description[da]=Hent albumomslag fra internettet
Description[de]=Album-Cover aus dem Internet nachladen
Description[dz]=ཨིན་ཊར་ནེཊི་ལས་གླུ་མཛོད་ཁེབས་ཚུ་ལེན།
Description[el]=Εύρεση εξώφυλλων άλμπουμ από Διαδίκτυο
Description[en_CA]=Fetch album covers from the Internet
Description[en_GB]=Fetch album covers from the Internet
Description[eo]=Obteni kovrilon el interreto
Description[es]=Buscar portadas de álbum de Internet
Description[et]=Plaadiümbriste tõmbamine internetist
Description[eu]=Eskuratu albumen azalak Internetetik
Description[fi]=Hae levyjen kansikuvia Internetistä
Description[fr]=Télécharge les pochettes d'album depuis Internet
Description[gl]=Busque as portadas do álbum na Internet
Description[gu]=ઇન્ટરનેટ માંથી આલ્બમ કવરોને પ્રાપ્ત કરો
Description[hi]=इंटरनेट से एल्बम कवर लाएँ
Description[hu]=Lemezborítók letöltése az internetről
Description[it]=Recupera le copertine degli album da Internet
Description[ja]=アルバムのジャケットをインターネットから取得します
Description[kn]=ಅಂತರಜಾಲದಿಂದ ಆಲ್ಬಮ್‌ನ ಹೊದಿಕೆಗಳನ್ನು ಪಡೆದುಕೊಳ್ಳಿ
Description[ko]=인터넷에서 앨범 표지를 가져옵니다
Description[lt]=Atsiųsti albumų viršelius iš interneto
Description[lv]=Ielādē albuma vāciņus no interneta
Description[mk]=Собирај ги омотите за албумите од интернет
Description[mr]=आंतरजाल पासून अल्बम कवर प्राप्त करा
Description[nb]=Hent omslag fra internett
Description[ne]=इन्टरनेटबाट एल्बम आवरणहरू तान्नुहोस्
Description[nl]=Albumhoezen van het internet halen
Description[nn]=Hent plateomslag frå Internett
Description[pa]=ਇੰਟਰਨੈੱਟ ਤੋਂ ਐਲਬਮ ਢੱਕਣ ਲਵੋ
Description[pl]=Pobiera okładki albumów z Internetu
Description[pt]=Obter capa de álbuns da Internet
Description[pt_BR]=Buscar capas dos álbuns na internet
Description[ro]=Preia coperțile albumelor de pe Internet
Description[ru]=Загрузка обложек альбомов из Интернета
Description[sk]=Získať obaly albumov z Internetu
Description[sl]=Pridobi naslovnice albumov z medmrežja
Description[sr]=Преузмите омоте албума са Интернета
Description[sr@latin]=Preuzmite omote albuma sa Interneta
Description[sv]=Hämta omslagsgrafik från Internet
Description[ta]=இணையத்திலிருந்து ஆல்பம் கவர்களை எடு
Description[te]=ఆల్బమ్ కవర్లను అంతర్జాలం నుండి తీసుకొనిరమ్ము
Description[th]=ดึงภาพปกอัลบั้มจากอินเทอร์เน็ต
Description[tr]=Albüm kapaklarını internetten al
Description[uk]=Звантаження обкладинок альбомів з інтернету
Description[vi]=Lấy ảnh bìa tập nhạc từ Internet
Description[zh_CN]=从互联网上获取专辑封面
Description[zh_HK]=從網絡擷取專輯封面
Description[zh_TW]=從網路擷取專輯封面
Authors=James Livingston <doclivingston@gmail.com>
Copyright=Copyright © 2006 James Livingston
Website=http://www.rhythmbox.org/
[RB]
InitiallyEnabled=true
+411
Ver Arquivo
@@ -0,0 +1,411 @@
# -*- Mode: python; coding: utf-8; tab-width: 8; indent-tabs-mode: t; -*-
#
# Copyright (C) 2006 - James Livingston
#
# 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; either version 2, or (at your option)
# any later version.
#
# The Rhythmbox authors hereby grant permission for non-GPL compatible
# GStreamer plugins to be used and distributed together with GStreamer
# and Rhythmbox. This permission is above and beyond the permissions granted
# by the GPL license by which Rhythmbox is covered. If you modify this code
# you may extend this exception to your version of the code, but you are not
# obligated to do so. If you do not wish to do so, delete this exception
# statement from your version.
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
import gi
from warnings import warn
import rb
from gi.repository import GObject, Gtk, Gdk, GdkPixbuf, Gio, Peas
from gi.repository import RB
import gettext
gettext.install('rhythmbox', RB.locale_dir())
import urllib
FADE_STEPS = 10
FADE_TOTAL_TIME = 1000
ART_MISSING_ICON = 'rhythmbox-missing-artwork'
WORKING_DELAY = 500
THROBBER_RATE = 10
THROBBER = 'process-working'
ASPECT_RATIO_MIN = 0.9
ASPECT_RATIO_MAX = 1.1
def merge_pixbufs (old_pb, new_pb, reserve_pb, step, width, height, mode=GdkPixbuf.InterpType.BILINEAR):
if width <= 1 and height <= 1:
return None
if old_pb is None:
if new_pb is None:
return reserve_pb
else:
return new_pb.scale_simple (width, height, mode)
elif step == 0.0:
return old_pb.scale_simple (width, height, mode)
elif new_pb is None:
if reserve_pb is None:
return None
new_pb = reserve_pb
sw, sh = (float (width)) / new_pb.props.width, (float (height)) / new_pb.props.height
alpha = int (step * 255)
ret = old_pb.scale_simple (width, height, mode)
new_pb.composite (ret, 0, 0, width, height, 0, 0, sw, sh, mode, alpha)
return ret
def merge_with_background (pixbuf, bgcolor, pad_if_not_near_square):
if pixbuf is None:
return pixbuf
has_alpha = pixbuf.get_has_alpha ()
width, height = pixbuf.props.width, pixbuf.props.height
if pad_if_not_near_square and (height < width * ASPECT_RATIO_MIN or
height > width * ASPECT_RATIO_MAX):
rw, rh = max (width, height), max (width, height)
left, top = (rw - width) // 2, (rh - height) // 2
else:
if not has_alpha:
return pixbuf
rw, rh, left, top = width, height, 0, 0
ret = GdkPixbuf.Pixbuf.new (GdkPixbuf.Colorspace.RGB, False, 8, rw, rh)
ret.fill ((int(bgcolor.red * 255) << 24) | (int(bgcolor.green * 255) << 16) | (int(bgcolor.blue * 255) << 8) | int(bgcolor.alpha * 255))
if has_alpha:
pixbuf.composite (ret, left, top, width, height, left, top, 1.0, 1.0, GdkPixbuf.InterpType.NEAREST, 255)
else:
pixbuf.copy_area (0, 0, width, height, ret, left, top)
return ret
class FadingImage (Gtk.Misc):
__gsignals__ = {
'get-max-size' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_INT, ())
}
def __init__ (self, missing_image):
Gtk.Misc.__init__(self)
self.sc_id = self.connect('screen-changed', self.screen_changed)
self.sa_id = self.connect('size-allocate', self.size_allocate_cb)
self.resize_id, self.fade_id, self.anim_id = 0, 0, 0
self.missing_image = missing_image
self.size = 100
self.screen_changed (self, None)
self.old_pixbuf, self.new_pixbuf = None, None
self.merged_pixbuf, self.missing_pixbuf = None, None
self.fade_step = 0.0
self.anim, self.anim_frames, self.anim_size = None, None, 0
def disconnect_handlers (self):
self.disconnect(self.sc_id)
self.disconnect(self.sa_id)
self.icon_theme.disconnect(self.tc_id)
for id in self.resize_id, self.fade_id, self.anim_id:
if id != 0:
GObject.source_remove (id)
def screen_changed (self, widget, old_screen):
if old_screen:
self.icon_theme.disconnect (self.tc_id)
self.icon_theme = Gtk.IconTheme.get_for_screen (self.get_screen ())
self.tc_id = self.icon_theme.connect ('changed', self.theme_changed)
self.theme_changed (self.icon_theme)
def reload_anim_frames (self):
icon_info = self.icon_theme.lookup_icon (THROBBER, -1, 0)
size = icon_info.get_base_size ()
icon = GdkPixbuf.Pixbuf.new_from_file (icon_info.get_filename ())
self.anim_frames = [ # along, then down
icon.new_subpixbuf (x * size, y * size, size, size)
for y in range (int (icon.props.height / size))
for x in range (int (icon.props.width / size))]
self.anim_size = size
def theme_changed (self, icon_theme):
try:
self.reload_anim_frames ()
except Exception, e:
warn ("Throbber animation not loaded: %s" % e, Warning)
self.reload_util_pixbufs ()
def reload_util_pixbufs (self):
if self.size <= 1:
return
try:
missing_pixbuf = self.icon_theme.load_icon (ART_MISSING_ICON, self.size, 0)
except:
try:
missing_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size (self.missing_image, self.size, self.size)
except Exception, e:
warn ("Missing artwork icon not found: %s" % e, Warning)
return
bgcolor = self.get_style_context().get_background_color(Gtk.StateType.NORMAL)
self.missing_pixbuf = merge_with_background (missing_pixbuf, bgcolor, False)
def size_allocate_cb (self, widget, allocation):
if self.resize_id == 0:
self.resize_id = GObject.idle_add (self.after_resize)
max_size = self.emit ('get-max-size')
self.size = min (self.get_allocated_width (), max_size)
def after_resize (self):
self.reload_util_pixbufs ()
self.merged_pixbuf = None
self.resize_id = 0
self.queue_draw ()
return False
def do_get_request_mode(self):
return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH
def do_get_preferred_width(self):
# maybe set minimum width here?
return (0, 0)
def do_get_preferred_height_for_width(self, width):
max_size = self.emit ('get-max-size')
size = min(self.get_allocated_width(), max_size)
return (size, size)
def do_draw (self, cr):
if not self.ensure_merged_pixbuf ():
return False
if self.merged_pixbuf.props.width != self.size:
draw_pb = self.merged_pixbuf.scale_simple (self.size, self.size, GdkPixbuf.InterpType.NEAREST)
else:
draw_pb = self.merged_pixbuf
# center the image if we're wider than we are tall
pad = (self.get_allocation().width - self.size) / 2
left = pad
right = pad + self.size
top = 0
bottom = self.size
if right > left and bottom > top:
Gdk.cairo_set_source_pixbuf(cr, draw_pb, pad, 0)
cr.rectangle(left, top, right - left, bottom - top)
cr.fill()
if self.anim:
x, y, w, h = self.anim_rect ()
Gdk.cairo_set_source_pixbuf(cr, self.anim, max(0, x), max(0, y))
cr.rectangle(max(0, x), max(0, y), w, h)
cr.fill()
return False
def anim_rect (self):
alloc_width = self.get_allocated_width()
alloc_height = self.get_allocated_height()
return ((alloc_width - self.anim_size) / 2,
(alloc_height - self.anim_size) / 2,
min (self.anim_size, alloc_width),
min (self.anim_size, alloc_height))
def ensure_merged_pixbuf (self):
if self.merged_pixbuf is None:
alloc_width = self.get_allocated_width()
alloc_height = self.get_allocated_height()
self.merged_pixbuf = merge_pixbufs (self.old_pixbuf, self.new_pixbuf, self.missing_pixbuf, self.fade_step, alloc_width, alloc_height)
return self.merged_pixbuf
def render_overlay (self):
ret = self.ensure_merged_pixbuf ()
if ret and self.anim:
if ret is self.missing_pixbuf: ret = ret.copy ()
x, y, w, h = self.anim_rect ()
self.anim.composite (ret, max (x, 0), max (y, 0), w, h, x, y, 1, 1, GdkPixbuf.InterpType.BILINEAR, 255)
return ret
def fade_art (self, first_time):
self.fade_step += 1.0 / FADE_STEPS
if self.fade_step > 0.999:
self.old_pixbuf = None
self.fade_id = 0
self.merged_pixbuf = None
if first_time:
self.fade_id = GObject.timeout_add ((FADE_TOTAL_TIME / FADE_STEPS), self.fade_art, False)
return False
self.queue_resize ()
return (self.fade_step <= 0.999)
def animation_advance (self, counter, first_time):
self.anim = self.anim_frames[counter[0]]
counter[0] = (counter[0] + 1) % len(self.anim_frames)
x, y, w, h = self.anim_rect ()
self.queue_draw_area (max (x, 0), max (y, 0), w, h)
if first_time:
self.anim_id = GObject.timeout_add (int (1000 / THROBBER_RATE), self.animation_advance, counter, False)
return False
return True
def set_current_art (self, pixbuf, working):
if self.props.visible and self.get_allocated_width() > 1:
self.old_pixbuf = self.render_overlay ()
else:
self.old_pixbuf = None # don't fade
bgcolor = self.get_style_context().get_background_color(Gtk.StateType.NORMAL)
self.new_pixbuf = merge_with_background (pixbuf, bgcolor, True)
self.merged_pixbuf = None
self.fade_step = 0.0
self.anim = None
if self.fade_id != 0:
GObject.source_remove (self.fade_id)
self.fade_id = 0
if self.old_pixbuf is not None:
self.fade_id = GObject.timeout_add (working and WORKING_DELAY or (FADE_TOTAL_TIME / FADE_STEPS), self.fade_art, working)
if working and self.anim_id == 0 and self.anim_frames:
self.anim_id = GObject.timeout_add (WORKING_DELAY, self.animation_advance, [0], True)
if not working and self.anim_id != 0:
GObject.source_remove (self.anim_id)
self.anim_id = 0
self.queue_resize ()
GObject.type_register (FadingImage)
class ArtDisplayWidget (FadingImage):
def __init__ (self, missing_image):
super (ArtDisplayWidget, self).__init__ (missing_image)
self.set_padding (0, 5)
self.qt_id = self.connect ('query-tooltip', self.query_tooltip)
self.props.has_tooltip = True
self.current_entry, self.working = None, False
self.current_pixbuf, self.current_uri = None, None
def disconnect_handlers (self):
super (ArtDisplayWidget, self).disconnect_handlers ()
def query_tooltip (self, widget, x, y, keyboard_mode, tooltip):
if (self.tooltip_image, self.tooltip_text) != (None, None):
tooltip.set_text(self.tooltip_text)
tooltip.set_icon(self.tooltip_image)
return True
else:
return False
def set (self, entry, pixbuf, uri, tooltip_image, tooltip_text, working):
self.current_entry = entry
self.current_pixbuf = pixbuf
self.current_uri = uri
self.set_current_art (pixbuf, working)
self.tooltip_image = None
if not self.current_entry:
self.tooltip_text = None
elif working:
self.tooltip_text = _("Searching...")
elif (tooltip_image, tooltip_text) != (None, None):
self.tooltip_image = tooltip_image
self.tooltip_text = tooltip_text
else:
self.tooltip_text = None
GObject.type_register (ArtDisplayWidget)
class ArtDisplayPlugin (GObject.GObject, Peas.Activatable):
__gtype_name__ = 'ArtDisplayPlugin'
object = GObject.property(type=GObject.GObject)
def __init__ (self):
GObject.GObject.__init__ (self)
def do_activate (self):
shell = self.object
sp = shell.props.shell_player
self.player_cb_ids = (
sp.connect ('playing-song-changed', self.playing_entry_changed),
sp.connect ('playing-changed', self.playing_changed)
)
self.art_store = RB.ExtDB(name="album-art")
self.art_widget = ArtDisplayWidget (rb.find_plugin_file (self, ART_MISSING_ICON + ".svg"))
self.art_widget.connect ('get-max-size', self.get_max_art_size)
self.art_widget.connect ('button-press-event', self.on_button_press)
self.art_container = Gtk.VBox ()
self.art_container.pack_start (self.art_widget, True, True, 6)
shell.add_widget (self.art_container, RB.ShellUILocation.SIDEBAR, False, True)
self.current_entry, self.current_pixbuf = None, None
self.playing_entry_changed (sp, sp.get_playing_entry ())
def do_deactivate (self):
shell = self.object
sp = shell.props.shell_player
for id in self.player_cb_ids:
sp.disconnect (id)
self.player_cb_ids = ()
shell.remove_widget (self.art_container, RB.ShellUILocation.SIDEBAR)
self.art_widget.disconnect_handlers ()
self.art_widget = None
self.art_container = None
def playing_changed (self, sp, playing):
self.set_entry(sp.get_playing_entry ())
def playing_entry_changed (self, sp, entry):
self.set_entry(entry)
def set_entry (self, entry):
if rb.entry_equal(entry, self.current_entry):
return
self.art_widget.set (entry, None, None, None, None, True)
self.art_container.show_all ()
self.current_entry = entry
self.current_pixbuf = None
if entry is not None:
key = entry.create_ext_db_key (RB.RhythmDBPropType.ALBUM)
self.art_store.request(key, self.art_store_request_cb, entry)
def art_store_request_cb(self, key, filename, data, entry):
if rb.entry_equal(entry, self.current_entry) is False:
# track changed while we were searching
return
if isinstance(data, GdkPixbuf.Pixbuf):
self.current_pixbuf = data
uri = "file://" + urllib.pathname2url(filename)
self.art_widget.set (entry, self.current_pixbuf, uri, None, None, False)
else:
self.art_widget.set (entry, None, None, None, None, False)
def get_max_art_size (self, widget):
# limit the art image to a third of the window height to prevent it from
# forcing the window to resize, obscuring everything else, and so on.
shell = self.object
(width, height) = shell.props.window.get_size()
return height / 3
def on_button_press (self, widget, event):
# on double clicks, open the cover image (if there is one) in the default
# image viewer
doubleclick = Gdk.EventType._2BUTTON_PRESS
if event.type != doubleclick or event.button != 1:
return
if self.art_widget.current_uri is None:
return
f = Gio.file_new_for_uri(self.art_widget.current_uri)
shell = self.object
Gtk.show_uri(shell.props.window.get_screen(), f.get_uri(), event.time)
+7
Ver Arquivo
@@ -0,0 +1,7 @@
This is simply the old artdisplay plugin from Rhythmbox <2.96.
It was removed from newer Rhythmbox versions in favor of the small cover display in the song title bar, but it still works. So if you prefer the old style, just get it.
Installation:
1.) Copy the folder 'ArtDisplay' to '~/.local/share/Rhythmbox/plugins'.
2.) Activate the plugin in Rhythmbox.