SHA256
1
0
forked from pool/picard

Accepting request 76928 from home:olh:branches:multimedia:apps

- Update name of dlopen libdiscid object during build

- Update additional python plugins to report compatibility for 0.15

- Run dos2unix on additional python plugins

- Update to version 0.15 - 2011-07-17
  - Added options for using standardized track, release, and artist metadata.
  - Added preferred release format support.
  - Expanded preferred release country support to allow multiple countries.
  - Added support for tagging non-album tracks (standalone recordings).
  - Plugins can now be installed via drag and drop, or a file browser.
  - Added several new tags: %%_originaldate%%, %%_recordingcomment%%, and %%_releasecomment%%
  - Changes to request queuing: added separate high and low priority queues for each host.
  - Tagger scripts now run after metadata plugins finish (#5850)
  - The "compilation" tag can now be $unset or modified via tagger script.
  - Added a shortcut (Ctrl+I) for Edit->Details.
  - Miscellaneous bug fixes.
  - Support for the NGS web service
 
 Version 0.14 - 2011-05-15
  - Fixed a problem with network operations hanging after a network error (#5794, #5884)
  - ID3v2.3 with UTF-16 is now the default ID3 version
  - Option to set preferred release types for improved album matching
  - Added support for sorting the album/file lists (#75)
  - Fixed OptimFROG tag reading (#5859)
  - Fixed colors for a white-on-black color scheme (#5846)
  - Added an option to replace non-ASCII punctuation (#5834)
  - Support for writing release group and work IDs, currently unused (#5805)
  - Fixed saving of the release event format tag (#5250)

OBS-URL: https://build.opensuse.org/request/show/76928
OBS-URL: https://build.opensuse.org/package/show/multimedia:apps/picard?expand=0&rev=14
This commit is contained in:
Stephan Kulow 2011-07-25 10:17:02 +00:00 committed by Git OBS Bridge
parent f9fb383764
commit 6beefab6df
21 changed files with 475 additions and 813 deletions

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search AMG"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search AMG"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search Amazon for Release (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search Amazon"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search CastAlbums.org for Release (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search CastAlbums.org"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search Discogs for Release (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search Discogs"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search FilmMuziek.be for Release (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search FilmMuziek.be"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search Game Music Revolution (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search Game Music Revolution"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search with Google for Release (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search Google. Thanks to Lukas Lalinsky for bug-fix!"
PLUGIN_VERSION = "0.1.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.util import webbrowser2

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search the Lortel Archives for Release (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search the Lortel Archives"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search SoundtrackCollector for Release (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search SoundtrackCollector"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = u"Search SoundtrackINFO (codebase 4.1)"
PLUGIN_AUTHOR = u"Brian Schweitzer"
PLUGIN_DESCRIPTION = "Search SoundtrackINFO"
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from PyQt4 import QtCore
from picard.cluster import Cluster

View File

@ -1,157 +0,0 @@
# -*- coding: utf-8 -*-
PLUGIN_NAME = u'Last.fm'
PLUGIN_AUTHOR = u'Lukáš Lalinský'
PLUGIN_DESCRIPTION = u'Use tags from Last.fm as genre.'
PLUGIN_VERSION = "0.2"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
from PyQt4 import QtGui, QtCore
from picard.metadata import register_album_metadata_processor, register_track_metadata_processor
from picard.ui.options import register_options_page, OptionsPage
from picard.config import BoolOption, IntOption, TextOption
from picard.plugins.lastfm.ui_options_lastfm import Ui_LastfmOptionsPage
from picard.util import partial
_cache = {}
# TODO: move this to an options page
TRANSLATE_TAGS = {
"hip hop": u"Hip-Hop",
"synth-pop": u"Synthpop",
"electronica": u"Electronic",
}
TITLE_CASE = True
def _tags_finalize(album, metadata, tags, next):
if next:
album._requests += 1
next(tags)
else:
tags = list(set(tags))
if tags:
join_tags = album.tagger.config.setting["lastfm_join_tags"]
if join_tags:
tags = join_tags.join(tags)
metadata["genre"] = tags
def _tags_downloaded(album, metadata, min_usage, ignore, next, current, data, http, error):
try:
try: intags = data.toptags[0].tag
except AttributeError: intags = []
tags = []
for tag in intags:
name = tag.name[0].text.strip()
try: count = int(tag.count[0].text.strip(), 10)
except ValueError: count = 0
if count < min_usage:
break
try: name = TRANSLATE_TAGS[name]
except KeyError: pass
if name.lower() not in ignore:
tags.append(name.title())
_cache[str(http.currentRequest().path())] = tags
_tags_finalize(album, metadata, current + tags, next)
finally:
album._requests -= 1
album._finalize_loading(None)
def get_tags(album, metadata, path, min_usage, ignore, next, current):
"""Get tags from an URL."""
try:
if path in _cache:
_tags_finalize(album, metadata, current + _cache[path], next)
else:
album._requests += 1
album.tagger.xmlws.get("ws.audioscrobbler.com", 80, path,
partial(_tags_downloaded, album, metadata, min_usage, ignore, next, current),
position=1)
finally:
album._requests -= 1
album._finalize_loading(None)
return False
def encode_str(s):
# Yes, that's right, Last.fm prefers double URL-encoding
s = QtCore.QUrl.toPercentEncoding(s)
s = QtCore.QUrl.toPercentEncoding(unicode(s))
return s
def get_track_tags(album, metadata, artist, track, min_usage, ignore, next, current):
"""Get track top tags."""
path = "/1.0/track/%s/%s/toptags.xml" % (encode_str(artist), encode_str(track))
return get_tags(album, metadata, path, min_usage, ignore, next, current)
def get_artist_tags(album, metadata, artist, min_usage, ignore, next, current):
"""Get artist top tags."""
path = "/1.0/artist/%s/toptags.xml" % (encode_str(artist),)
return get_tags(album, metadata, path, min_usage, ignore, next, current)
def process_track(album, metadata, release, track):
tagger = album.tagger
use_track_tags = tagger.config.setting["lastfm_use_track_tags"]
use_artist_tags = tagger.config.setting["lastfm_use_artist_tags"]
min_tag_usage = tagger.config.setting["lastfm_min_tag_usage"]
ignore_tags = tagger.config.setting["lastfm_ignore_tags"].lower().split(",")
if use_track_tags or use_artist_tags:
artist = metadata["artist"]
title = metadata["title"]
if artist:
if use_artist_tags:
get_artist_tags_func = partial(get_artist_tags, album, metadata, artist, min_tag_usage, ignore_tags, None)
else:
get_artist_tags_func = None
if title and use_track_tags:
func = partial(get_track_tags, album, metadata, artist, title, min_tag_usage, ignore_tags, get_artist_tags_func, [])
elif get_artist_tags_func:
func = partial(get_artist_tags_func, [])
if func:
album._requests += 1
tagger.xmlws.add_task(func, position=1)
class LastfmOptionsPage(OptionsPage):
NAME = "lastfm"
TITLE = "Last.fm"
PARENT = "plugins"
options = [
BoolOption("setting", "lastfm_use_track_tags", False),
BoolOption("setting", "lastfm_use_artist_tags", False),
#BoolOption("setting", "lastfm_use_artist_images", False),
IntOption("setting", "lastfm_min_tag_usage", 15),
TextOption("setting", "lastfm_ignore_tags", "seen live,favorites"),
TextOption("setting", "lastfm_join_tags", ""),
]
def __init__(self, parent=None):
super(LastfmOptionsPage, self).__init__(parent)
self.ui = Ui_LastfmOptionsPage()
self.ui.setupUi(self)
def load(self):
self.ui.use_track_tags.setChecked(self.config.setting["lastfm_use_track_tags"])
self.ui.use_artist_tags.setChecked(self.config.setting["lastfm_use_artist_tags"])
#self.ui.use_artist_images.setChecked(self.config.setting["lastfm_use_artist_images"])
self.ui.min_tag_usage.setValue(self.config.setting["lastfm_min_tag_usage"])
self.ui.ignore_tags.setText(self.config.setting["lastfm_ignore_tags"])
self.ui.join_tags.setEditText(self.config.setting["lastfm_join_tags"])
def save(self):
self.config.setting["lastfm_use_track_tags"] = self.ui.use_track_tags.isChecked()
self.config.setting["lastfm_use_artist_tags"] = self.ui.use_artist_tags.isChecked()
#self.config.setting["lastfm_use_artist_images"] = self.ui.use_artist_images.isChecked()
self.config.setting["lastfm_min_tag_usage"] = self.ui.min_tag_usage.value()
self.config.setting["lastfm_ignore_tags"] = unicode(self.ui.ignore_tags.text())
self.config.setting["lastfm_join_tags"] = unicode(self.ui.join_tags.currentText())
register_track_metadata_processor(process_track)
#register_album_metadata_processor(process_album)
register_options_page(LastfmOptionsPage)

View File

@ -1,17 +1,34 @@
# -*- coding: utf-8 -*-
PLUGIN_NAME = u"Add Cluster As Release"
PLUGIN_AUTHOR = u"Lukáš Lalinský"
PLUGIN_AUTHOR = u"Lukáš Lalinský, Philip Jägenstedt"
PLUGIN_DESCRIPTION = ""
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_VERSION = "0.2"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15.0"]
from PyQt4 import QtCore
from picard.cluster import Cluster
from picard.util import webbrowser2, format_time
from picard.util import webbrowser2
from picard.ui.itemviews import BaseAction, register_cluster_action
import codecs
import os
import tempfile
HTML_HEAD = """<!doctype html>
<meta charset="UTF-8">
<title>Add Cluster As Release</title>
<form action="http://musicbrainz.org/release/add" method="post">
"""
HTML_INPUT = """<input type="hidden" name="%s" value="%s">
"""
HTML_TAIL = """<input type="submit" value="Add Release">
</form>
<script>document.forms[0].submit()</script>
"""
HTML_ATTR_ESCAPE = {
"&": "&amp;",
'"': "&quot;"
}
class AddClusterAsRelease(BaseAction):
NAME = "Add Cluster As Release..."
@ -21,32 +38,41 @@ class AddClusterAsRelease(BaseAction):
return
cluster = objs[0]
artists = set()
for i, file in enumerate(cluster.files):
artists.add(file.metadata["artist"])
(fd, fp) = tempfile.mkstemp(suffix=".html")
f = codecs.getwriter("utf-8")(os.fdopen(fd, "w"))
def esc(s):
return "".join(HTML_ATTR_ESCAPE.get(c, c) for c in s)
# add a global (release-level) name-value
def nv(n, v):
f.write(HTML_INPUT % (esc(n), esc(v)))
f.write(HTML_HEAD)
nv("artist_credit.names.0.artist.name", cluster.metadata["artist"])
nv("name", cluster.metadata["album"])
url = "http://musicbrainz.org/cdi/enter.html"
if len(artists) > 1:
url += "?hasmultipletrackartists=1&artistid=1"
else:
url += "?hasmultipletrackartists=0&artistid=2"
url += "&artistedit=1&artistname=%s" % QtCore.QUrl.toPercentEncoding(cluster.metadata["artist"])
url += "&releasename=%s" % QtCore.QUrl.toPercentEncoding(cluster.metadata["album"])
tracks = 0
for i, file in enumerate(cluster.files):
try:
i = int(file.metadata["tracknumber"]) - 1
except:
pass
tracks = max(tracks, i + 1)
url += "&track%d=%s" % (i, QtCore.QUrl.toPercentEncoding(file.metadata["title"]))
url += "&tracklength%d=%s" % (i, QtCore.QUrl.toPercentEncoding(format_time(file.metadata.length)))
if len(artists) > 1:
url += "&tr%d_artistedit=1" % i
url += "&tr%d_artistname=%s" % (i, QtCore.QUrl.toPercentEncoding(file.metadata["artist"]))
url += "&tracks=%d" % tracks
webbrowser2.open(url)
try:
m = int(file.metadata["discnumber"]) - 1
except:
m = 0
# add a track-level name-value
def tnv(n, v):
nv("mediums.%d.track.%d.%s" % (m, i, n), v)
tnv("name", file.metadata["title"])
if file.metadata["artist"] != cluster.metadata["artist"]:
tnv("artist_credit.names.0.name", file.metadata["artist"])
tnv("length", str(file.metadata.length))
f.write(HTML_TAIL)
f.close()
webbrowser2.open("file://"+fp)
register_cluster_action(AddClusterAsRelease())

View File

@ -12,7 +12,7 @@ Moves bonus disc and bonus disc titles from album titles to separate tags. For e
<li>bonusdisctitle = <em>"Covers"</em></li>
</ul>'''
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from picard.metadata import register_album_metadata_processor
import re

View File

@ -1,147 +0,0 @@
# -*- coding: utf-8 -*-
"""
A small plugin to download cover art for any releseas that have a
CoverArtLink relation.
Changelog:
[2008-04-15] Refactored the code to be similar to the server code (hartzell, phw)
[2008-03-10] Added CDBaby support (phw)
[2007-09-06] Added Jamendo support (phw)
[2007-04-24] Moved parsing code into here
Swapped to QUrl
Moved to a list of urls
[2007-04-23] Moved it to use the bzr picard
Took the hack out
Added Amazon ASIN support
[2007-04-23] Initial plugin, uses a hack that relies on Python being
installed and musicbrainz2 for the query.
"""
PLUGIN_NAME = 'Cover Art Downloader'
PLUGIN_AUTHOR = 'Oliver Charles, Philipp Wolfer'
PLUGIN_DESCRIPTION = '''Downloads cover artwork for releases that have a
CoverArtLink.'''
PLUGIN_VERSION = "0.4"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
from picard.metadata import register_album_metadata_processor
from picard.util import partial
from PyQt4.QtCore import QUrl
import re
#
# data transliterated from the perl stuff used to find cover art for the
# musicbrainz server.
# See mb_server/cgi-bin/MusicBrainz/Server/CoverArt.pm
# hartzell --- Tue Apr 15 15:25:58 PDT 2008
coverArtSites = [
# CD-Baby
# tested with http://musicbrainz.org/release/1243cc17-b9f7-48bd-a536-b10d2013c938.html
{
'regexp': 'http://cdbaby.com/cd/(\w)(\w)(\w*)',
'imguri': 'http://cdbaby.name/$1/$2/$1$2$3.jpg',
},
# Jamendo
# tested with http://musicbrainz.org/release/2fe63977-bda9-45da-8184-25a4e7af8da7.html
{
'regexp': 'http:\/\/(?:www.)?jamendo.com\/(?:[a-z]+\/)?album\/([0-9]+)',
'imguri': 'http://www.jamendo.com/get/album/id/album/artworkurl/redirect/$1/?artwork_size=0',
},
]
_AMAZON_IMAGE_HOST = 'images.amazon.com'
_AMAZON_IMAGE_PATH = '/images/P/%s.01.LZZZZZZZ.jpg'
_AMAZON_IMAGE_PATH_SMALL = '/images/P/%s.01.MZZZZZZZ.jpg'
_AMAZON_IMAGE_PATH2 = '/images/P/%s.02.LZZZZZZZ.jpg'
_AMAZON_IMAGE_PATH2_SMALL = '/images/P/%s.02.MZZZZZZZ.jpg'
def _coverart_downloaded(album, metadata, release, try_list, data, http, error):
try:
if error or len(data) < 1000:
if error:
album.log.error(str(http.errorString()))
coverart(album, metadata, release, try_list)
else:
metadata.add_image("image/jpeg", data)
for track in album._new_tracks:
track.metadata.add_image("image/jpeg", data)
finally:
album._requests -= 1
album._finalize_loading(None)
def coverart(album, metadata, release, try_list=None):
""" Gets the CDBaby URL from the metadata, and the attempts to
download the album art. """
# try_list will be None for the first call
if try_list is None:
try_list = []
try:
for relation_list in release.relation_list:
if relation_list.target_type == 'Url':
for relation in relation_list.relation:
# Search for cover art on special sites
for site in coverArtSites:
#
# this loop transliterated from the perl stuff used to find cover art for the
# musicbrainz server.
# See mb_server/cgi-bin/MusicBrainz/Server/CoverArt.pm
# hartzell --- Tue Apr 15 15:25:58 PDT 2008
match = re.match(site['regexp'], relation.target)
if match != None:
imgURI = site['imguri']
for i in range(1, len(match.groups())+1 ):
if match.group(i) != None:
imgURI = imgURI.replace('$' + str(i), match.group(i))
_try_list_append_image_url(try_list, QUrl(imgURI))
# Use the URL of a cover art link directly
if relation.type == 'CoverArtLink':
_try_list_append_image_url(try_list, QUrl(relation.target))
except AttributeError:
pass
if metadata['asin']:
try_list.append({'host': _AMAZON_IMAGE_HOST, 'port': 80,
'path': _AMAZON_IMAGE_PATH % metadata['asin']
})
try_list.append({'host': _AMAZON_IMAGE_HOST, 'port': 80,
'path': _AMAZON_IMAGE_PATH_SMALL % metadata['asin']
})
try_list.append({'host': _AMAZON_IMAGE_HOST, 'port': 80,
'path': _AMAZON_IMAGE_PATH2 % metadata['asin']
})
try_list.append({'host': _AMAZON_IMAGE_HOST, 'port': 80,
'path': _AMAZON_IMAGE_PATH2_SMALL % metadata['asin']
})
if len(try_list) > 0:
# We still have some items to try!
album._requests += 1
album.tagger.xmlws.download(
try_list[0]['host'], try_list[0]['port'], try_list[0]['path'],
partial(_coverart_downloaded, album, metadata, release, try_list[1:]),
position=1)
def _try_list_append_image_url(try_list, parsedUrl):
path = parsedUrl.path()
if parsedUrl.hasQuery():
path += '?'+'&'.join(["%s=%s" % (k,v) for k,v in parsedUrl.queryItems()])
try_list.append({
'host': str(parsedUrl.host()),
'port': parsedUrl.port(80),
'path': str(path)
})
register_album_metadata_processor(coverart)

View File

@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
PLUGIN_NAME = 'Disc Numbers'
PLUGIN_AUTHOR = 'Lukas Lalinsky'
PLUGIN_DESCRIPTION = '''Moves disc numbers and subtitles from album titles to separate tags. For example:<br/>
<em>"Aerial (disc 1: A Sea of Honey)"</em>
<ul>
<li>album = <em>"Aerial"</em></li>
<li>discnumber = <em>"1"</em></li>
<li>discsubtitle = <em>"A Sea of Honey"</em></li>
</ul>'''
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
from picard.metadata import register_album_metadata_processor
import re
_discnumber_re = re.compile(r"\s+\(disc (\d+)(?::\s+([^)]+))?\)")
def remove_discnumbers(tagger, metadata, release):
matches = _discnumber_re.search(metadata["album"])
if matches:
metadata["discnumber"] = matches.group(1)
if matches.group(2):
metadata["discsubtitle"] = matches.group(2)
metadata["album"] = _discnumber_re.sub('', metadata["album"])
register_album_metadata_processor(remove_discnumbers)

View File

@ -4,7 +4,7 @@ PLUGIN_NAME = 'Feat. Artists'
PLUGIN_AUTHOR = 'Lukas Lalinsky'
PLUGIN_DESCRIPTION = 'Removes feat. artists from track titles.'
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]
PLUGIN_API_VERSIONS = ["0.9.0", "0.10", "0.15"]
from picard.metadata import register_track_metadata_processor
import re

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7b1c2f78ecdc444e8882c2ec6dc6fff4305d90a1fb89ab01076662a8bf85f6e4
size 1011008

3
picard-0.15.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:db1228191518dd750e5f6f28992c5cc6d0fc97cb367eaa3fa74c0bc66bedf717
size 1524823

View File

@ -1,3 +1,87 @@
-------------------------------------------------------------------
Mon Jul 25 11:06:16 CEST 2011 - ohering@suse.de
- Update name of dlopen libdiscid object during build
-------------------------------------------------------------------
Mon Jul 25 09:29:08 CEST 2011 - ohering@suse.de
- Update additional python plugins to report compatibility for 0.15
-------------------------------------------------------------------
Mon Jul 25 09:24:40 CEST 2011 - ohering@suse.de
- Run dos2unix on additional python plugins
-------------------------------------------------------------------
Mon Jul 25 09:19:34 CEST 2011 - ohering@suse.de
- Update to version 0.15 - 2011-07-17
- Added options for using standardized track, release, and artist metadata.
- Added preferred release format support.
- Expanded preferred release country support to allow multiple countries.
- Added support for tagging non-album tracks (standalone recordings).
- Plugins can now be installed via drag and drop, or a file browser.
- Added several new tags: %%_originaldate%%, %%_recordingcomment%%, and %%_releasecomment%%
- Changes to request queuing: added separate high and low priority queues for each host.
- Tagger scripts now run after metadata plugins finish (#5850)
- The "compilation" tag can now be $unset or modified via tagger script.
- Added a shortcut (Ctrl+I) for Edit->Details.
- Miscellaneous bug fixes.
- Support for the NGS web service
Version 0.14 - 2011-05-15
- Fixed a problem with network operations hanging after a network error (#5794, #5884)
- ID3v2.3 with UTF-16 is now the default ID3 version
- Option to set preferred release types for improved album matching
- Added support for sorting the album/file lists (#75)
- Fixed OptimFROG tag reading (#5859)
- Fixed colors for a white-on-black color scheme (#5846)
- Added an option to replace non-ASCII punctuation (#5834)
- Support for writing release group and work IDs, currently unused (#5805)
- Fixed saving of the release event format tag (#5250)
- Added support for the language and script tags (#943)
- Plugins can now use track-track relationships (#5849)
- Allowed external drives to be visible in the file browser panel on OS X (#5308)
Version 0.13 - 2011-03-06
- Changed Picard icon license to CC by-sa
- Small UI consistency changes
- Albums with tracks linked to more than one file are never marked as
"completed".
- Fixed matching of scanned files to tracks while the album is still loading.
- Support for properly embedded FLAC pictures
- Existing embedded images in APE and ASF files are removed only if there
are new images to replace them.
- More strict tagger script validation.
- Fixed the $truncate tagger script function.
- Proper rounding of track durations.
- Fixed a bug with saving images larger than 64k to WMA files.
- Added a $swapprefix tagger script function.
- Release events with a date are preferred over the ones without a date.
- Files that are being saved as marked as pending.
- Updated .desktop file to allow opening Picard with multiple files.
- Handle the "open file" event on Mac OS X.
- Added timeouts to the HTTP web service client.
- Fixed a bug with albums missing the expand/collapse icons
-------------------------------------------------------------------
Mon Jul 25 09:10:44 CEST 2011 - ohering@suse.de
- Include a dummy binary to add the correct rpm dependency to the
libdiscid SONAME in the package. The python code uses dlopen.
-------------------------------------------------------------------
Mon Jul 25 09:06:43 CEST 2011 - ohering@suse.de
- Update specfile to include URLs to plugins
-------------------------------------------------------------------
Mon Jul 25 08:58:40 CEST 2011 - ohering@suse.de
- Remove incorrect sles_version check for libdiscid-devel
The package will be required unconditionally to read Audio CDs
-------------------------------------------------------------------
Wed Feb 2 08:58:35 UTC 2011 - saschpe@suse.de

View File

@ -19,36 +19,31 @@
Name: picard
Version: 0.12.1+bzr1043
Version: 0.15
Release: 2
Summary: The Next Generation MusicBrainz Tagger
License: GPLv2+
Group: Productivity/Multimedia/Sound/Utilities
Url: http://musicbrainz.org/doc/PicardTagger
Source0: %{name}-%{version}.tar.bz2
Source1: addrelease.py
Source2: bonusdisc.py
Source3: coverart.py
Source4: discnumber.py
Source5: featartist.py
Source6: lastfm/__init__.py
Source7: lastfm/ui_options_lastfm.py
Source8: SearchAmazon3.py
Source9: SearchAMG.py
Source10: SearchCastAlbums3.py
Source11: SearchDiscogs3.py
Source12: SearchFilmMusziek3.py
Source13: SearchGMR.py
Source14: SearchGoogle3.py
Source15: SearchLortelArchives3.py
Source16: SearchSoundtrackCollector3.py
Source17: SearchSoundtrackINFO3.py
Source0: http://ftp.musicbrainz.org/pub/musicbrainz/picard/%{name}-%{version}.tar.gz
# http://wiki.musicbrainz.org/Picard_Plugins
Source1: https://gitorious.org/musicbrainz/addrelease/blobs/raw/master/addrelease.py
Source2: http://dispuutivv.nl/~jan/bonusdisc.py
Source5: http://users.musicbrainz.org/~luks/picard-plugins/featartist.py
Source8: http://users.musicbrainz.org/~brianfreud/SearchAmazon3.py
Source9: http://users.musicbrainz.org/~brianfreud/SearchAMG.py
Source10: http://users.musicbrainz.org/~brianfreud/SearchCastAlbums3.py
Source11: http://users.musicbrainz.org/~brianfreud/SearchDiscogs3.py
Source12: http://users.musicbrainz.org/~brianfreud/SearchFilmMusziek3.py
Source13: http://users.musicbrainz.org/~brianfreud/SearchGMR.py
Source14: http://users.musicbrainz.org/~brianfreud/SearchGoogle3.py
Source15: http://users.musicbrainz.org/~brianfreud/SearchLortelArchives3.py
Source16: http://users.musicbrainz.org/~brianfreud/SearchSoundtrackCollector3.py
Source17: http://users.musicbrainz.org/~brianfreud/SearchSoundtrackINFO3.py
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: desktop-file-utils gcc-c++ libofa-devel python-devel
%if 0%{!?sles_version}
BuildRequires: libdiscid-devel
%endif
%if 0%{?suse_version}
%py_requires
BuildRequires: hicolor-icon-theme python-mutagen python-qt4 update-desktop-files
@ -87,6 +82,21 @@ Authors:
%build
export CFLAGS="$RPM_OPT_FLAGS"
cat > %{name}_libdiscid_dummy.c <<-EOF
#include <stdio.h>
#include <discid/discid.h>
int main(void) {
printf("Dummy to generate correct libdiscid.so rpm dependency.\n");
discid_free(discid_new());
return 0;
}
EOF
gcc -Wall -s $CFLAGS -o %{name}_libdiscid_dummy %{name}_libdiscid_dummy.c -ldiscid
# there is some upstream confusion about what the SONAME of libdiscid is supposed to be
libdiscid_so="`readelf --wide --dynamic picard_libdiscid_dummy | sed -n '/(NEEDED).*libdiscid.so/s@^\(.*\[\)\([^]]\+\).*@\2@p'`"
sed -i~ -e "s@^\([[:blank:]]\+\)\(libName[[:blank:]]*=[[:blank:]]*'\)\(libdiscid.so.0\)\('[[:blank:]]*\)@\1\2${libdiscid_so}\4 # was '\3'@" picard/disc.py
if diff -u picard/disc.py~ picard/disc.py ; then : ; fi
#
%{__python} setup.py config
%{__python} setup.py build
@ -95,14 +105,9 @@ export CFLAGS="$RPM_OPT_FLAGS"
# install plugins
PLUGINDIR=$RPM_BUILD_ROOT%{py_sitedir}/picard/plugins/
install -d ${PLUGINDIR}/lastfm
install -m 0644 %{SOURCE1} ${PLUGINDIR}
install -m 0644 %{SOURCE2} ${PLUGINDIR}
install -m 0644 %{SOURCE3} ${PLUGINDIR}
install -m 0644 %{SOURCE4} ${PLUGINDIR}
install -m 0644 %{SOURCE5} ${PLUGINDIR}
install -m 0644 %{SOURCE6} ${PLUGINDIR}/lastfm
install -m 0644 %{SOURCE7} ${PLUGINDIR}/lastfm
install -m 0644 %{SOURCE8} ${PLUGINDIR}
install -m 0644 %{SOURCE9} ${PLUGINDIR}
install -m 0644 %{SOURCE10} ${PLUGINDIR}
@ -124,6 +129,9 @@ desktop-file-install --delete-original --remove-category="Application" \
%find_lang %{name}
mkdir -vp $RPM_BUILD_ROOT/%{_libdir}/%{name}
cp -avL %{name}_libdiscid_dummy $RPM_BUILD_ROOT/%{_libdir}/%{name}
%clean
rm -rf $RPM_BUILD_ROOT
@ -154,6 +162,7 @@ rm -rf $RPM_BUILD_ROOT
%endif
%doc AUTHORS.txt COPYING.txt NEWS.txt
%{_bindir}/picard
/%{_libdir}/%{name}
%{_datadir}/applications/%{name}.desktop
%{py_sitedir}/picard*
%{_datadir}/icons/hicolor/16x16/apps/picard.png

View File

@ -1,125 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'options_lastfm.ui'
#
# Created: Sun May 13 11:18:12 2007
# by: PyQt4 UI code generator 4.1
#
# WARNING! All changes made in this file will be lost!
import sys
from PyQt4 import QtCore, QtGui
class Ui_LastfmOptionsPage(object):
def setupUi(self, LastfmOptionsPage):
LastfmOptionsPage.setObjectName("LastfmOptionsPage")
LastfmOptionsPage.resize(QtCore.QSize(QtCore.QRect(0,0,305,317).size()).expandedTo(LastfmOptionsPage.minimumSizeHint()))
self.vboxlayout = QtGui.QVBoxLayout(LastfmOptionsPage)
self.vboxlayout.setMargin(9)
self.vboxlayout.setSpacing(6)
self.vboxlayout.setObjectName("vboxlayout")
self.rename_files = QtGui.QGroupBox(LastfmOptionsPage)
self.rename_files.setObjectName("rename_files")
self.vboxlayout1 = QtGui.QVBoxLayout(self.rename_files)
self.vboxlayout1.setMargin(9)
self.vboxlayout1.setSpacing(2)
self.vboxlayout1.setObjectName("vboxlayout1")
self.use_track_tags = QtGui.QCheckBox(self.rename_files)
self.use_track_tags.setObjectName("use_track_tags")
self.vboxlayout1.addWidget(self.use_track_tags)
self.use_artist_tags = QtGui.QCheckBox(self.rename_files)
self.use_artist_tags.setObjectName("use_artist_tags")
self.vboxlayout1.addWidget(self.use_artist_tags)
self.vboxlayout.addWidget(self.rename_files)
self.rename_files_2 = QtGui.QGroupBox(LastfmOptionsPage)
self.rename_files_2.setObjectName("rename_files_2")
self.vboxlayout2 = QtGui.QVBoxLayout(self.rename_files_2)
self.vboxlayout2.setMargin(9)
self.vboxlayout2.setSpacing(2)
self.vboxlayout2.setObjectName("vboxlayout2")
self.ignore_tags_2 = QtGui.QLabel(self.rename_files_2)
self.ignore_tags_2.setObjectName("ignore_tags_2")
self.vboxlayout2.addWidget(self.ignore_tags_2)
self.ignore_tags = QtGui.QLineEdit(self.rename_files_2)
self.ignore_tags.setObjectName("ignore_tags")
self.vboxlayout2.addWidget(self.ignore_tags)
self.hboxlayout = QtGui.QHBoxLayout()
self.hboxlayout.setMargin(0)
self.hboxlayout.setSpacing(6)
self.hboxlayout.setObjectName("hboxlayout")
self.ignore_tags_4 = QtGui.QLabel(self.rename_files_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Policy(5),QtGui.QSizePolicy.Policy(5))
sizePolicy.setHorizontalStretch(4)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.ignore_tags_4.sizePolicy().hasHeightForWidth())
self.ignore_tags_4.setSizePolicy(sizePolicy)
self.ignore_tags_4.setObjectName("ignore_tags_4")
self.hboxlayout.addWidget(self.ignore_tags_4)
self.join_tags = QtGui.QComboBox(self.rename_files_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Policy(5),QtGui.QSizePolicy.Policy(0))
sizePolicy.setHorizontalStretch(1)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.join_tags.sizePolicy().hasHeightForWidth())
self.join_tags.setSizePolicy(sizePolicy)
self.join_tags.setEditable(True)
self.join_tags.setObjectName("join_tags")
self.join_tags.addItem("")
self.hboxlayout.addWidget(self.join_tags)
self.vboxlayout2.addLayout(self.hboxlayout)
self.hboxlayout1 = QtGui.QHBoxLayout()
self.hboxlayout1.setMargin(0)
self.hboxlayout1.setSpacing(6)
self.hboxlayout1.setObjectName("hboxlayout1")
self.label_4 = QtGui.QLabel(self.rename_files_2)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Policy(7),QtGui.QSizePolicy.Policy(5))
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth())
self.label_4.setSizePolicy(sizePolicy)
self.label_4.setObjectName("label_4")
self.hboxlayout1.addWidget(self.label_4)
self.min_tag_usage = QtGui.QSpinBox(self.rename_files_2)
self.min_tag_usage.setMaximum(100)
self.min_tag_usage.setObjectName("min_tag_usage")
self.hboxlayout1.addWidget(self.min_tag_usage)
self.vboxlayout2.addLayout(self.hboxlayout1)
self.vboxlayout.addWidget(self.rename_files_2)
spacerItem = QtGui.QSpacerItem(263,21,QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Expanding)
self.vboxlayout.addItem(spacerItem)
self.label_4.setBuddy(self.min_tag_usage)
self.retranslateUi(LastfmOptionsPage)
QtCore.QMetaObject.connectSlotsByName(LastfmOptionsPage)
LastfmOptionsPage.setTabOrder(self.use_track_tags,self.ignore_tags)
def retranslateUi(self, LastfmOptionsPage):
self.rename_files.setTitle(_("Last.fm"))
self.use_track_tags.setText(_("Use track tags"))
self.use_artist_tags.setText(_("Use artist tags"))
self.rename_files_2.setTitle(_("Tags"))
self.ignore_tags_2.setText(_("Ignore tags:"))
self.ignore_tags_4.setText(_("Join multiple tags with:"))
self.join_tags.addItem(_(" / "))
self.join_tags.addItem(_(", "))
self.label_4.setText(_("Minimal tag usage:"))
self.min_tag_usage.setSuffix(_(" %"))