parent
bef70f9fe6
commit
529029bd97
3 changed files with 115 additions and 0 deletions
34
larigira/audioform_mostrecent.py
Normal file
34
larigira/audioform_mostrecent.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
from pytimeparse.timeparse import timeparse
|
||||||
|
from flask_wtf import Form
|
||||||
|
from wtforms import StringField, validators, SubmitField, ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class AudioForm(Form):
|
||||||
|
nick = StringField('Audio nick', validators=[validators.required()],
|
||||||
|
description='A simple name to recognize this audio')
|
||||||
|
path = StringField('Path', validators=[validators.required()],
|
||||||
|
description='Directory to pick file from')
|
||||||
|
maxage = StringField('Max age',
|
||||||
|
validators=[validators.required()],
|
||||||
|
description='in seconds, or human-readable '
|
||||||
|
'(like 9w3d12h)')
|
||||||
|
submit = SubmitField('Submit')
|
||||||
|
|
||||||
|
def validate_maxage(form, field):
|
||||||
|
try:
|
||||||
|
int(field.data)
|
||||||
|
except ValueError:
|
||||||
|
if timeparse(field.data) is None:
|
||||||
|
raise ValidationError("maxage must either be a number "
|
||||||
|
"(in seconds) or a human-readable "
|
||||||
|
"string like '1h2m' or '1d12h'")
|
||||||
|
|
||||||
|
|
||||||
|
def audio_receive(form):
|
||||||
|
return {
|
||||||
|
'kind': 'mostrecent',
|
||||||
|
'nick': form.nick.data,
|
||||||
|
'path': form.path.data,
|
||||||
|
'maxage': form.maxage.data,
|
||||||
|
'howmany': 1
|
||||||
|
}
|
78
larigira/audiogen_mostrecent.py
Normal file
78
larigira/audiogen_mostrecent.py
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import shutil
|
||||||
|
import time
|
||||||
|
from tempfile import mkstemp
|
||||||
|
import fnmatch
|
||||||
|
|
||||||
|
from pytimeparse.timeparse import timeparse
|
||||||
|
|
||||||
|
|
||||||
|
def scan_dir(dirname, extension=None):
|
||||||
|
if extension is None:
|
||||||
|
extension = '*'
|
||||||
|
for root, dirnames, filenames in os.walk(dirname):
|
||||||
|
for fname in fnmatch.filter(filenames, extension):
|
||||||
|
yield os.path.join(root, fname)
|
||||||
|
|
||||||
|
|
||||||
|
def get_mtime(fname):
|
||||||
|
return int(os.path.getmtime(fname))
|
||||||
|
|
||||||
|
|
||||||
|
def recent_choose(paths, howmany, minepoch):
|
||||||
|
found_files = {}
|
||||||
|
for path in paths:
|
||||||
|
if not os.path.exists(path):
|
||||||
|
logging.warn("Can't find requested path: %s" % path)
|
||||||
|
continue
|
||||||
|
if os.path.isfile(path):
|
||||||
|
found_files[path] = get_mtime(path)
|
||||||
|
elif os.path.isdir(path):
|
||||||
|
found_files.update({fname: get_mtime(fname)
|
||||||
|
for fname in scan_dir(path)})
|
||||||
|
found_files = [(fname, mtime)
|
||||||
|
for (fname, mtime) in found_files.items()
|
||||||
|
if mtime >= minepoch]
|
||||||
|
|
||||||
|
return [fname for fname, mtime in
|
||||||
|
sorted(found_files, key=lambda x: x[1])[:howmany]]
|
||||||
|
|
||||||
|
|
||||||
|
def generate(spec):
|
||||||
|
'''
|
||||||
|
resolves audiospec-randomdir
|
||||||
|
|
||||||
|
Recognized arguments:
|
||||||
|
- path [mandatory] source dir
|
||||||
|
- maxage [default=ignored] max age of audio files to pick
|
||||||
|
'''
|
||||||
|
for attr in ('path', 'maxage'):
|
||||||
|
if attr not in spec:
|
||||||
|
raise ValueError("Malformed audiospec: missing '%s'" % attr)
|
||||||
|
|
||||||
|
if spec['maxage'].strip():
|
||||||
|
try:
|
||||||
|
maxage = int(spec['maxage'])
|
||||||
|
except ValueError:
|
||||||
|
maxage = timeparse(spec['maxage'])
|
||||||
|
if maxage is None:
|
||||||
|
raise ValueError("Unknown format for maxage: '{}'"
|
||||||
|
.format(spec['maxage']))
|
||||||
|
assert type(maxage) is int
|
||||||
|
else:
|
||||||
|
maxage = None
|
||||||
|
|
||||||
|
now = int(time.time())
|
||||||
|
minepoch = 0 if maxage is None else now - maxage
|
||||||
|
|
||||||
|
picked = recent_choose([spec['path']], 1, minepoch)
|
||||||
|
|
||||||
|
for path in picked:
|
||||||
|
tmp = mkstemp(suffix=os.path.splitext(path)[-1],
|
||||||
|
prefix='audiogen-randomdir-')
|
||||||
|
os.close(tmp[0])
|
||||||
|
shutil.copy(path, tmp[1])
|
||||||
|
yield 'file://{}'.format(tmp[1])
|
||||||
|
|
||||||
|
generate.description = 'Select most recent file inside a directory'
|
3
setup.py
3
setup.py
|
@ -60,6 +60,7 @@ setup(name='larigira',
|
||||||
'mpd = larigira.audiogen_mpdrandom:generate_by_artist',
|
'mpd = larigira.audiogen_mpdrandom:generate_by_artist',
|
||||||
'static = larigira.audiogen_static:generate',
|
'static = larigira.audiogen_static:generate',
|
||||||
'randomdir = larigira.audiogen_randomdir:generate',
|
'randomdir = larigira.audiogen_randomdir:generate',
|
||||||
|
'mostrecent = larigira.audiogen_mostrecent:generate',
|
||||||
'script = larigira.audiogen_script:generate',
|
'script = larigira.audiogen_script:generate',
|
||||||
],
|
],
|
||||||
'larigira.timegenerators': [
|
'larigira.timegenerators': [
|
||||||
|
@ -78,11 +79,13 @@ setup(name='larigira',
|
||||||
'static = larigira.audioform_static:StaticAudioForm',
|
'static = larigira.audioform_static:StaticAudioForm',
|
||||||
'script = larigira.audioform_script:ScriptAudioForm',
|
'script = larigira.audioform_script:ScriptAudioForm',
|
||||||
'randomdir = larigira.audioform_randomdir:Form',
|
'randomdir = larigira.audioform_randomdir:Form',
|
||||||
|
'mostrecent = larigira.audioform_mostrecent:AudioForm',
|
||||||
],
|
],
|
||||||
'larigira.audioform_receive': [
|
'larigira.audioform_receive': [
|
||||||
'static = larigira.audioform_static:staticaudio_receive',
|
'static = larigira.audioform_static:staticaudio_receive',
|
||||||
'script = larigira.audioform_script:scriptaudio_receive',
|
'script = larigira.audioform_script:scriptaudio_receive',
|
||||||
'randomdir = larigira.audioform_randomdir:receive',
|
'randomdir = larigira.audioform_randomdir:receive',
|
||||||
|
'mostrecent = larigira.audioform_mostrecent:audio_receive',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
|
|
Loading…
Reference in a new issue