Picard plugin
Add two context menu options, ingest tracks, and Copy MusicBrainz ids to the clipboard. The latest root hash of the ingest set is accessed in the options menu or in the log output.master
parent
d0d264c42e
commit
cac95e2db4
|
@ -2,3 +2,4 @@
|
|||
/tests/test_set
|
||||
/tests/test_http
|
||||
/genode/bin/
|
||||
*.pyc
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
PLUGIN_NAME = 'Blobsets'
|
||||
PLUGIN_AUTHOR = 'ehmry'
|
||||
PLUGIN_DESCRIPTION = '''Ingest files into a blobset.'''
|
||||
PLUGIN_VERSION = '0.1'
|
||||
PLUGIN_API_VERSIONS = ['2.0']
|
||||
PLUGIN_LICENSE = "GPL-2.0"
|
||||
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.html"
|
||||
|
||||
from functools import partial
|
||||
|
||||
from picard.config import TextOption
|
||||
from picard.file import File
|
||||
from picard.album import Album
|
||||
from picard.track import Track
|
||||
from picard.ui.itemviews import BaseAction, register_track_action, register_album_action
|
||||
from picard.ui.options import register_options_page, OptionsPage
|
||||
from picard.util import thread
|
||||
from .ui_options_blobsets import Ui_BlobsetsOptionsPage
|
||||
|
||||
import picard.tagger as tagger
|
||||
|
||||
from PyQt5 import QtWidgets
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
import os.path
|
||||
|
||||
ROOT_HASH_KEY = "blobsets_root_hash"
|
||||
|
||||
# TODO the setttings thing cannot be trusted
|
||||
|
||||
class BlobsetsOptionsPage(OptionsPage):
|
||||
NAME = 'blobsets'
|
||||
TITLE = 'Blobsets'
|
||||
PARENT = "plugins"
|
||||
options = [
|
||||
TextOption("setting", ROOT_HASH_KEY, "d59ea2fbcbf2f3d21184f21938ed7966aa480c1dea7463b3de6cae1a18bb1308")
|
||||
]
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(BlobsetsOptionsPage, self).__init__(parent)
|
||||
self.ui = Ui_BlobsetsOptionsPage()
|
||||
self.ui.setupUi(self)
|
||||
|
||||
def load(self):
|
||||
self.ui.root_hash.setText(self.config.setting[ROOT_HASH_KEY])
|
||||
|
||||
def save(self):
|
||||
self.config.setting[ROOT_HASH_KEY] = self.ui.root_hash.text()
|
||||
|
||||
register_options_page(BlobsetsOptionsPage)
|
||||
|
||||
class IngestFile(BaseAction):
|
||||
NAME = 'Ingest file to blob set'
|
||||
|
||||
def _ingest(self, track, file):
|
||||
rootHex = tagger.config.setting[ROOT_HASH_KEY]
|
||||
print("rootHex is ", rootHex)
|
||||
mbid = track.metadata["musicbrainz_recordingid"]
|
||||
path = file.filename
|
||||
self.tagger.window.set_statusbar_message(
|
||||
N_('Ingesting %(path)s...'), {'path': path})
|
||||
_, ext = os.path.splitext(path)
|
||||
p = Popen(["blobset", "repl"], stdin=PIPE, stdout=PIPE)
|
||||
cmd = '(hex (commit (insert (load {}) (blob (path "{}")) "{}{}")))'.format(rootHex, path, mbid, ext)
|
||||
print(cmd)
|
||||
(stdout_data, stderr_data) = p.communicate(cmd.encode(encoding='UTF-8'))
|
||||
new_root = stdout_data.decode().strip().strip('"')
|
||||
print(new_root)
|
||||
tagger.config.setting[ROOT_HASH_KEY] = new_root
|
||||
self.tagger.window.set_statusbar_message(
|
||||
N_('Root hash updated to %(hash)s.'),
|
||||
{'hash': tagger.config.setting[ROOT_HASH_KEY]}
|
||||
)
|
||||
|
||||
def _ingest_callback(self, track, result=None, error=None):
|
||||
if error:
|
||||
self.tagger.window.set_statusbar_message(
|
||||
N_('%(mbid)s ingestion failed.'),
|
||||
{'mbid': track.metadata["musicbrainz_recordingid"]}
|
||||
)
|
||||
|
||||
def callback(self, objs):
|
||||
rootHex = tagger.config.setting[ROOT_HASH_KEY]
|
||||
print("current hash ", rootHex)
|
||||
for obj in objs:
|
||||
if isinstance(obj, Track):
|
||||
for file in obj.linked_files:
|
||||
thread.run_task(
|
||||
partial(self._ingest, obj, file),
|
||||
partial(self._ingest_callback, obj),
|
||||
priority=2, thread_pool=file.tagger.save_thread_pool)
|
||||
break
|
||||
|
||||
class CopyIdToClipboard(BaseAction):
|
||||
NAME = "Copy id Clipboard..."
|
||||
|
||||
# Copy an id to the clipboard so the playlist generator picks it up
|
||||
|
||||
def callback(self, objs):
|
||||
if len(objs) != 1:
|
||||
return
|
||||
if isinstance(objs[0], Track):
|
||||
track = objs[0]
|
||||
mbid = track.metadata["musicbrainz_recordingid"]
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText('musicbrainz/recording/{}'.format(mbid))
|
||||
elif isinstance(objs[0], Album):
|
||||
album = objs[0]
|
||||
mbid = album.metadata["musicbrainz_albumid"]
|
||||
clipboard = QtWidgets.QApplication.clipboard()
|
||||
clipboard.setText('musicbrainz/release/{}'.format(mbid))
|
||||
|
||||
register_track_action(IngestFile())
|
||||
register_track_action(CopyIdToClipboard())
|
||||
register_album_action(CopyIdToClipboard())
|
|
@ -0,0 +1,32 @@
|
|||
from PyQt5 import QtCore, QtWidgets
|
||||
|
||||
|
||||
class Ui_BlobsetsOptionsPage(object):
|
||||
|
||||
def setupUi(self, BlobsetsOptionsPage):
|
||||
BlobsetsOptionsPage.setObjectName("BlobsetsOptionsPage")
|
||||
self.vboxlayout = QtWidgets.QVBoxLayout(BlobsetsOptionsPage)
|
||||
self.vboxlayout.setContentsMargins(9, 9, 9, 9)
|
||||
self.vboxlayout.setSpacing(6)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
self.root_hash_group = QtWidgets.QGroupBox(BlobsetsOptionsPage)
|
||||
self.root_hash_group.setObjectName("root_hash_group")
|
||||
self.vboxlayout2 = QtWidgets.QVBoxLayout(self.root_hash_group)
|
||||
self.vboxlayout2.setContentsMargins(9, 9, 9, 9)
|
||||
self.vboxlayout2.setSpacing(2)
|
||||
self.vboxlayout2.setObjectName("vboxlayout2")
|
||||
self.root_hash_label = QtWidgets.QLabel(self.root_hash_group)
|
||||
self.root_hash_label.setObjectName("root_hash_label")
|
||||
self.vboxlayout2.addWidget(self.root_hash_label)
|
||||
self.root_hash = QtWidgets.QLineEdit(self.root_hash_group)
|
||||
self.root_hash.setObjectName("root_hash")
|
||||
self.vboxlayout2.addWidget(self.root_hash)
|
||||
self.vboxlayout.addWidget(self.root_hash_group)
|
||||
spacerItem = QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.vboxlayout.addItem(spacerItem)
|
||||
|
||||
self.retranslateUi(BlobsetsOptionsPage)
|
||||
QtCore.QMetaObject.connectSlotsByName(BlobsetsOptionsPage)
|
||||
|
||||
def retranslateUi(self, BlobsetsOptionsPage):
|
||||
self.root_hash_label.setText(_("Current Blobset root hash"))
|
Loading…
Reference in New Issue