Compare commits

...

13 Commits

Author SHA1 Message Date
ed
cd3e0afad2 v0.9.13 2021-03-23 02:13:28 +01:00
ed
d8d1f94a86 v0.9.12 2021-03-23 01:24:37 +01:00
ed
00dfd8cfd1 v0.9.11 2021-03-23 00:36:48 +01:00
ed
273de6db31 propagate d2d/d2t properly 2021-03-23 00:33:18 +01:00
ed
c6c0eeb0ff better volflags presentation 2021-03-23 00:28:11 +01:00
ed
e70c74a3b5 support nullmapping subfolders with -v :/foo/bar:cd2d 2021-03-23 00:08:23 +01:00
ed
f7d939eeab more sfx tweaks 2021-03-21 22:31:07 +01:00
ed
e815c091b9 v0.9.10 2021-03-21 22:05:46 +01:00
ed
963529b7cf readme 2021-03-21 20:38:29 +01:00
ed
638a52374d readme 2021-03-21 20:20:11 +01:00
ed
d9d42b7aa2 aaa 2021-03-21 20:11:03 +01:00
ed
ec7e5f36a2 make-sfx tweaks 2021-03-21 18:06:31 +01:00
ed
56110883ea readme 2021-03-21 17:56:05 +01:00
8 changed files with 104 additions and 21 deletions

View File

@@ -25,6 +25,7 @@ turn your phone or raspi into a portable file server with resumable uploads/down
* [search configuration](#search-configuration)
* [metadata from audio files](#metadata-from-audio-files)
* [file parser plugins](#file-parser-plugins)
* [complete examples](#complete-examples)
* [client examples](#client-examples)
* [dependencies](#dependencies)
* [optional gpl stuff](#optional-gpl-stuff)
@@ -171,8 +172,8 @@ copyparty can invoke external programs to collect additional metadata for files
## complete examples
* read-only music server with bpm and key scanning
* `python copyparty-sfx.py -v /mnt/nas/music:/music:r -e2dsa -e2ts -mtp .bpm=f,~/bin/audio-bpm.py -mtp key=f,~/bin/audio-key.py`
* read-only music server with bpm and key scanning
`python copyparty-sfx.py -v /mnt/nas/music:/music:r -e2dsa -e2ts -mtp .bpm=f,audio-bpm.py -mtp key=f,audio-key.py`
# client examples

View File

@@ -5,4 +5,30 @@ some of these rely on libraries which are not MIT-compatible
* [audio-bpm.py](./audio-bpm.py) detects the BPM of music using the BeatRoot Vamp Plugin; imports GPL2
* [audio-key.py](./audio-key.py) detects the melodic key of music using the Mixxx fork of keyfinder; imports GPL3
# dependencies
run [`install-deps.sh`](install-deps.sh) to build/install most dependencies required by these programs (supports windows/linux/macos)
*alternatively* (or preferably) use packages from your distro instead, then you'll need at least these:
* from distro: `numpy vamp-plugin-sdk beatroot-vamp mixxx-keyfinder ffmpeg`
* from pypy: `keyfinder vamp`
# usage from copyparty
`copyparty -e2dsa -e2ts -mtp key=f,audio-key.py -mtp .bpm=f,audio-bpm.py`
* `f,` makes the detected value replace any existing values
* the `.` in `.bpm` indicates numeric value
* assumes the python files are in the folder you're launching copyparty from, replace the filename with a relative/absolute path if that's not the case
* `mtp` modules will not run if a file has existing tags in the db, so clear out the tags with `-e2tsr` the first time you launch with new `mtp` options
## usage with volume-flags
instead of affecting all volumes, you can set the options for just one volume like so:
```
copyparty -v /mnt/nas/music:/music:r:cmtp=key=f,audio-key.py:cmtp=.bpm=f,audio-bpm.py:ce2dsa:ce2ts
```

View File

@@ -1,8 +1,8 @@
# coding: utf-8
VERSION = (0, 9, 9)
VERSION = (0, 9, 13)
CODENAME = "the strongest music server"
BUILD_DT = (2021, 3, 21)
BUILD_DT = (2021, 3, 23)
S_VERSION = ".".join(map(str, VERSION))
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)

View File

@@ -22,6 +22,14 @@ class VFS(object):
self.nodes = {} # child nodes
self.all_vols = {vpath: self} # flattened recursive
def __repr__(self):
return "VFS({})".format(
", ".join(
"{}={!r}".format(k, self.__dict__[k])
for k in "realpath vpath uread uwrite flags".split()
)
)
def _trk(self, vol):
self.all_vols[vol.vpath] = vol
return vol
@@ -343,6 +351,21 @@ class AuthSrv(object):
# append parsers from argv to volume-flags
self._read_volflag(vol.flags, "mtp", self.args.mtp, True)
# d2d drops all database features for a volume
for grp, rm in [["d2d", "e2d"], ["d2t", "e2t"]]:
if not vol.flags.get(grp, False):
continue
vol.flags["d2t"] = True
vol.flags = {k: v for k, v in vol.flags.items() if not k.startswith(rm)}
# mt* needs e2t so drop those too
for grp, rm in [["e2t", "mt"]]:
if vol.flags.get(grp, False):
continue
vol.flags = {k: v for k, v in vol.flags.items() if not k.startswith(rm)}
# verify tags mentioned by -mt[mp] are used by -mte
local_mtp = {}
local_only_mtp = {}

View File

@@ -1295,7 +1295,7 @@ class HttpCli(object):
tags = {}
f["tags"] = tags
if not r:
continue
@@ -1306,7 +1306,7 @@ class HttpCli(object):
tags[k] = v
if icur:
taglist = [k for k in vn.flags["mte"].split(",") if k in taglist]
taglist = [k for k in vn.flags.get("mte", "").split(",") if k in taglist]
for f in dirs:
f["tags"] = {}
@@ -1379,7 +1379,9 @@ class HttpCli(object):
ts=ts,
perms=json.dumps(perms),
taglist=taglist,
tag_order=json.dumps(vn.flags["mte"].split(",")),
tag_order=json.dumps(
vn.flags["mte"].split(",") if "mte" in vn.flags else []
),
have_up2k_idx=("e2d" in vn.flags),
have_tags_idx=("e2t" in vn.flags),
logues=logues,

View File

@@ -225,9 +225,14 @@ class Up2k(object):
_, flags = self._expr_idx_filter(flags)
a = "\033[0;36m{}:\033[1;30m{}"
a = [a.format(k, v) for k, v in sorted(flags.items())]
self.log(" ".join(a) + "\033[0m")
ft = "\033[0;32m{}{:.0}"
ff = "\033[0;35m{}{:.0}"
fv = "\033[0;36m{}:\033[1;30m{}"
a = [
(ft if v is True else ff if v is False else fv).format(k, str(v))
for k, v in flags.items()
]
self.log(" ".join(sorted(a)) + "\033[0m")
reg = {}
path = os.path.join(ptop, ".hist", "up2k.snap")
@@ -282,9 +287,12 @@ class Up2k(object):
dbw = [reg[0], 0, time.time()]
self.pp.n = next(dbw[0].execute("select count(w) from up"))[0]
# can be symlink so don't `and d.startswith(top)``
excl = set([d.realpath for d in all_vols if d != vol])
n_add = self._build_dir(dbw, top, excl, top)
excl = [
vol.realpath + "/" + d.vpath[len(vol.vpath) :].lstrip("/")
for d in all_vols
if d != vol and (d.vpath.startswith(vol.vpath + "/") or not vol.vpath)
]
n_add = self._build_dir(dbw, top, set(excl), top)
n_rm = self._drop_lost(dbw[0], top)
if dbw[1]:
self.log("commit {} new files".format(dbw[1]))

View File

@@ -58,7 +58,7 @@ function MPlayer() {
var links = document.querySelectorAll('#files>tbody>tr>td:nth-child(1)>a');
for (var a = 0, aa = links.length; a < aa; a++) {
var tid = links[a].getAttribute('id');
if (tid.indexOf('af-') !== 0)
if (!tid || tid.indexOf('af-') !== 0)
continue;
order.push(tid.slice(1));

View File

@@ -28,6 +28,13 @@ gtar=$(command -v gtar || command -v gnutar) || true
unexpand() { gunexpand "$@"; }
command -v grealpath >/dev/null &&
realpath() { grealpath "$@"; }
[ -e /opt/local/bin/bzip2 ] &&
bzip2() { /opt/local/bin/bzip2 "$@"; }
}
pybin=$(command -v python3 || command -v python) || {
echo need python
exit 1
}
[ -e copyparty/__main__.py ] || cd ..
@@ -38,11 +45,15 @@ gtar=$(command -v gtar || command -v gnutar) || true
exit 1
}
do_sh=1
do_py=1
while [ ! -z "$1" ]; do
[ "$1" = clean ] && clean=1 && shift && continue
[ "$1" = re ] && repack=1 && shift && continue
[ "$1" = no-ogv ] && no_ogv=1 && shift && continue
[ "$1" = no-cm ] && no_cm=1 && shift && continue
[ "$1" = no-sh ] && do_sh= && shift && continue
[ "$1" = no-py ] && do_py= && shift && continue
break
done
@@ -173,7 +184,7 @@ done
find | grep -E '\.py$' |
grep -vE '__version__' |
tr '\n' '\0' |
xargs -0 python ../scripts/uncomment.py
xargs -0 $pybin ../scripts/uncomment.py
f=dep-j2/jinja2/constants.py
awk '/^LOREM_IPSUM_WORDS/{o=1;print "LOREM_IPSUM_WORDS = u\"a\"";next} !o; /"""/{o=0}' <$f >t
@@ -195,24 +206,36 @@ tar -cf tar "${args[@]}" --numeric-owner copyparty dep-j2
echo compressing tar
# detect best level; bzip2 -7 is usually better than -9
for n in {2..9}; do cp tar t.$n; bzip2 -$n t.$n & done; wait; mv -v $(ls -1S t.*.bz2 | tail -n 1) tar.bz2
for n in {2..9}; do cp tar t.$n; xz -ze$n t.$n & done; wait; mv -v $(ls -1S t.*.xz | tail -n 1) tar.xz
rm t.*
[ $do_py ] && { for n in {2..9}; do cp tar t.$n; bzip2 -$n t.$n & done; wait; mv -v $(ls -1S t.*.bz2 | tail -n 1) tar.bz2; }
[ $do_sh ] && { for n in {2..9}; do cp tar t.$n; xz -ze$n t.$n & done; wait; mv -v $(ls -1S t.*.xz | tail -n 1) tar.xz; }
rm t.* || true
exts=()
[ $do_sh ] && {
exts+=(sh)
echo creating unix sfx
(
sed "s/PACK_TS/$ts/; s/PACK_HTS/$hts/; s/CPP_VER/$ver/" <../scripts/sfx.sh |
grep -E '^sfx_eof$' -B 9001;
cat tar.xz
) >$sfx_out.sh
}
[ $do_py ] && {
exts+=(py)
echo creating generic sfx
python ../scripts/sfx.py --sfx-make tar.bz2 $ver $ts
$pybin ../scripts/sfx.py --sfx-make tar.bz2 $ver $ts
mv sfx.out $sfx_out.py
chmod 755 $sfx_out.*
}
printf "done:\n"
printf " %s\n" "$(realpath $sfx_out)."{sh,py}
# rm -rf *
for ext in ${exts[@]}; do
printf " %s\n" "$(realpath $sfx_out)."$ext
done
# apk add bash python3 tar xz bzip2
# while true; do ./make-sfx.sh; for f in ..//dist/copyparty-sfx.{sh,py}; do mv $f $f.$(wc -c <$f | awk '{print$1}'); done; done