Blacken the code base.
This commit is contained in:
parent
d585c1529d
commit
07d079f204
19 changed files with 138 additions and 168 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import sys
|
import sys
|
||||||
from dcc.main import main
|
from dcc.main import main
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
sys.exit(main(sys.argv[1:]))
|
sys.exit(main(sys.argv[1:]))
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,10 @@ class Concat(dcc.doom_base.Wad):
|
||||||
+ f"to{parsed_args.end_map}"
|
+ f"to{parsed_args.end_map}"
|
||||||
)
|
)
|
||||||
output = av.open(
|
output = av.open(
|
||||||
self.fabricate.joinpath(parsed_args.wad).joinpath(
|
self.fabricate.joinpath(parsed_args.wad).joinpath(f"{fn_base}.mp4"), "w"
|
||||||
f"{fn_base}.mp4"), "w"
|
|
||||||
)
|
)
|
||||||
summary_file = open(
|
summary_file = open(
|
||||||
self.fabricate.joinpath(parsed_args.wad).joinpath(
|
self.fabricate.joinpath(parsed_args.wad).joinpath(f"{fn_base}.txt"), "w"
|
||||||
f"{fn_base}.txt"), "w"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self._offset = 0
|
self._offset = 0
|
||||||
|
|
@ -66,11 +64,13 @@ class Concat(dcc.doom_base.Wad):
|
||||||
start_time = self._offset / 1000000
|
start_time = self._offset / 1000000
|
||||||
text = self._add_chunk(
|
text = self._add_chunk(
|
||||||
videodir.joinpath(f"{parsed_args.wad}_map{idx}.mp4"),
|
videodir.joinpath(f"{parsed_args.wad}_map{idx}.mp4"),
|
||||||
output, not parsed_args.nooverlay
|
output,
|
||||||
|
not parsed_args.nooverlay,
|
||||||
)
|
)
|
||||||
list.append(
|
list.append(
|
||||||
summary, f"{text} {math.floor(start_time / 60):02}:"
|
summary,
|
||||||
+ f"{math.floor(start_time % 60):02}"
|
f"{text} {math.floor(start_time / 60):02}:"
|
||||||
|
+ f"{math.floor(start_time % 60):02}",
|
||||||
)
|
)
|
||||||
if state == State.DONE:
|
if state == State.DONE:
|
||||||
break
|
break
|
||||||
|
|
@ -82,8 +82,7 @@ class Concat(dcc.doom_base.Wad):
|
||||||
|
|
||||||
def _add_chunk(self, v, output, overlay):
|
def _add_chunk(self, v, output, overlay):
|
||||||
chunk = av.open(v)
|
chunk = av.open(v)
|
||||||
if not (len(chunk.streams.video) == 1
|
if not (len(chunk.streams.video) == 1 and len(chunk.streams.audio) == 1):
|
||||||
and len(chunk.streams.audio) == 1):
|
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f"irregular chunk {v}: streams {chunk.streams} "
|
f"irregular chunk {v}: streams {chunk.streams} "
|
||||||
+ f"(expected 1 video & 1 audio)"
|
+ f"(expected 1 video & 1 audio)"
|
||||||
|
|
@ -96,16 +95,11 @@ class Concat(dcc.doom_base.Wad):
|
||||||
text = ""
|
text = ""
|
||||||
if overlay:
|
if overlay:
|
||||||
img = wand.image.Image(
|
img = wand.image.Image(
|
||||||
height=chunk.streams[0].height,
|
height=chunk.streams[0].height, width=chunk.streams[0].width
|
||||||
width=chunk.streams[0].width
|
|
||||||
)
|
)
|
||||||
mapstring = v.name[-6:-4]
|
mapstring = v.name[-6:-4]
|
||||||
text = self._config["map_names"][f"map{mapstring}"]
|
text = self._config["map_names"][f"map{mapstring}"]
|
||||||
self.draw_text(
|
self.draw_text(img, f"MAP{mapstring}: {text}", font_size=120)
|
||||||
img,
|
|
||||||
f"MAP{mapstring}: {text}",
|
|
||||||
font_size=120
|
|
||||||
)
|
|
||||||
img.trim(reset_coords=True)
|
img.trim(reset_coords=True)
|
||||||
img.border("graya(25%, 25%)", 10, 10)
|
img.border("graya(25%, 25%)", 10, 10)
|
||||||
img.border(self.thumbnail_text_stroke, 16, 16)
|
img.border(self.thumbnail_text_stroke, 16, 16)
|
||||||
|
|
@ -113,17 +107,14 @@ class Concat(dcc.doom_base.Wad):
|
||||||
# multiple of 8. dude whyyyyyyy
|
# multiple of 8. dude whyyyyyyy
|
||||||
padfactor = 8
|
padfactor = 8
|
||||||
img.border("transparent", padfactor, 0)
|
img.border("transparent", padfactor, 0)
|
||||||
img.crop(
|
img.crop(width=img.width - img.width % padfactor, height=img.height)
|
||||||
width=img.width - img.width % padfactor,
|
|
||||||
height=img.height
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(output.streams.get()) == 0:
|
if len(output.streams.get()) == 0:
|
||||||
# We can't use the input stream as a template here; it doesn't
|
# We can't use the input stream as a template here; it doesn't
|
||||||
# have everything needed to do encoding and will fail
|
# have everything needed to do encoding and will fail
|
||||||
# mysteriously later.
|
# mysteriously later.
|
||||||
vs = chunk.streams.video[0]
|
vs = chunk.streams.video[0]
|
||||||
vr = int(vs.time_base.denominator/vs.time_base.numerator)
|
vr = int(vs.time_base.denominator / vs.time_base.numerator)
|
||||||
ovs = output.add_stream("h264", rate=vr)
|
ovs = output.add_stream("h264", rate=vr)
|
||||||
ovs.extradata = copy.deepcopy(vs.extradata)
|
ovs.extradata = copy.deepcopy(vs.extradata)
|
||||||
ovs.height = vs.height
|
ovs.height = vs.height
|
||||||
|
|
@ -145,12 +136,10 @@ class Concat(dcc.doom_base.Wad):
|
||||||
oas.bit_rate = astr.bit_rate
|
oas.bit_rate = astr.bit_rate
|
||||||
|
|
||||||
src = ograph.add_buffer(
|
src = ograph.add_buffer(
|
||||||
template=chunk.streams.video[0],
|
template=chunk.streams.video[0], time_base=chunk.streams.video[0].time_base
|
||||||
time_base=chunk.streams.video[0].time_base
|
|
||||||
)
|
)
|
||||||
asrc = ograph.add_abuffer(
|
asrc = ograph.add_abuffer(
|
||||||
template=chunk.streams.audio[0],
|
template=chunk.streams.audio[0], time_base=chunk.streams.audio[0].time_base
|
||||||
time_base=chunk.streams.audio[0].time_base
|
|
||||||
)
|
)
|
||||||
# TODO: video fades are absolute relative to the input video; audio
|
# TODO: video fades are absolute relative to the input video; audio
|
||||||
# fades need to have their timestamps offset by the position in the
|
# fades need to have their timestamps offset by the position in the
|
||||||
|
|
@ -163,19 +152,18 @@ class Concat(dcc.doom_base.Wad):
|
||||||
iafade_start = self._offset * sample_rate / 1000000
|
iafade_start = self._offset * sample_rate / 1000000
|
||||||
iafade = ograph.add("afade", args=f"in:{iafade_start}:{sample_rate}")
|
iafade = ograph.add("afade", args=f"in:{iafade_start}:{sample_rate}")
|
||||||
oafade_start = (
|
oafade_start = (
|
||||||
(self._offset + chunk.duration) * sample_rate / 1000000
|
self._offset + chunk.duration
|
||||||
- sample_rate
|
) * sample_rate / 1000000 - sample_rate
|
||||||
)
|
|
||||||
oafade = ograph.add("afade", args=f"out:{oafade_start}:{sample_rate}")
|
oafade = ograph.add("afade", args=f"out:{oafade_start}:{sample_rate}")
|
||||||
|
|
||||||
if overlay:
|
if overlay:
|
||||||
overlay = ograph.add_buffer(
|
overlay = ograph.add_buffer(
|
||||||
width=img.width, height=img.height,
|
width=img.width,
|
||||||
format="rgba", time_base=chunk.streams.video[0].time_base
|
height=img.height,
|
||||||
)
|
format="rgba",
|
||||||
overlay_fo = ograph.add(
|
time_base=chunk.streams.video[0].time_base,
|
||||||
"fade", args=f"out:{4 * frame_rate}:{frame_rate}"
|
|
||||||
)
|
)
|
||||||
|
overlay_fo = ograph.add("fade", args=f"out:{4 * frame_rate}:{frame_rate}")
|
||||||
overlay.link_to(overlay_fo, 0, 0)
|
overlay.link_to(overlay_fo, 0, 0)
|
||||||
composite = ograph.add("overlay", args="x=4:y=4")
|
composite = ograph.add("overlay", args="x=4:y=4")
|
||||||
src.link_to(composite, 0, 0)
|
src.link_to(composite, 0, 0)
|
||||||
|
|
@ -194,9 +182,8 @@ class Concat(dcc.doom_base.Wad):
|
||||||
for packet in chunk.demux():
|
for packet in chunk.demux():
|
||||||
if packet.dts is None:
|
if packet.dts is None:
|
||||||
continue
|
continue
|
||||||
pof = (
|
pof = (self._offset * packet.time_base.denominator) / (
|
||||||
(self._offset * packet.time_base.denominator)
|
packet.time_base.numerator * 1000000
|
||||||
/ (packet.time_base.numerator * 1000000)
|
|
||||||
)
|
)
|
||||||
packet.dts += pof
|
packet.dts += pof
|
||||||
packet.pts += pof
|
packet.pts += pof
|
||||||
|
|
@ -221,9 +208,7 @@ class Concat(dcc.doom_base.Wad):
|
||||||
|
|
||||||
def _make_text_frame(self, img, ifr):
|
def _make_text_frame(self, img, ifr):
|
||||||
# We need to give each frame its own memory it can own.
|
# We need to give each frame its own memory it can own.
|
||||||
text_frame = av.video.frame.VideoFrame(
|
text_frame = av.video.frame.VideoFrame(img.width, img.height, format="rgba")
|
||||||
img.width, img.height, format="rgba"
|
|
||||||
)
|
|
||||||
text_frame.planes[0].update(img.make_blob(format="rgba"))
|
text_frame.planes[0].update(img.make_blob(format="rgba"))
|
||||||
text_frame.pts = ifr.pts
|
text_frame.pts = ifr.pts
|
||||||
text_frame.dts = ifr.dts
|
text_frame.dts = ifr.dts
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,15 @@ class ConfigBase(object):
|
||||||
self._doom = pathlib.Path(parsed_args.doom)
|
self._doom = pathlib.Path(parsed_args.doom)
|
||||||
self._config_name = parsed_args.config_name
|
self._config_name = parsed_args.config_name
|
||||||
self._config = tomlkit.toml_file.TOMLFile(
|
self._config = tomlkit.toml_file.TOMLFile(
|
||||||
self.doom.joinpath(self.config_name)).read()
|
self.doom.joinpath(self.config_name)
|
||||||
|
).read()
|
||||||
|
|
||||||
self._dsda = self._config.get("dsda")
|
self._dsda = self._config.get("dsda")
|
||||||
if self._dsda is None:
|
if self._dsda is None:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"required key 'dsda' not set in config "
|
"required key 'dsda' not set in config "
|
||||||
+ f"{self.doom.joinpath(self.config_name)}.")
|
+ f"{self.doom.joinpath(self.config_name)}."
|
||||||
|
)
|
||||||
for d in ("iwads", "pwads", "demos", "fabricate"):
|
for d in ("iwads", "pwads", "demos", "fabricate"):
|
||||||
self._init_attr([d], d, fn=self.doom.joinpath)
|
self._init_attr([d], d, fn=self.doom.joinpath)
|
||||||
|
|
||||||
|
|
@ -29,10 +31,7 @@ class ConfigBase(object):
|
||||||
self._init_attr(["thumbnail", "text_fill"], "white")
|
self._init_attr(["thumbnail", "text_fill"], "white")
|
||||||
self._init_attr(["thumbnail", "text_stroke"], "red")
|
self._init_attr(["thumbnail", "text_stroke"], "red")
|
||||||
self._init_attr(["thumbnail", "overlay_name"], "M_DOOM_scaled.png")
|
self._init_attr(["thumbnail", "overlay_name"], "M_DOOM_scaled.png")
|
||||||
self._init_attr(
|
self._init_attr(["fetch", "mirror"], "https://youfailit.net/pub/idgames")
|
||||||
["fetch", "mirror"],
|
|
||||||
"https://youfailit.net/pub/idgames"
|
|
||||||
)
|
|
||||||
|
|
||||||
def _init_attr(self, what, default, fn=lambda x: x):
|
def _init_attr(self, what, default, fn=lambda x: x):
|
||||||
propname = "_".join(what)
|
propname = "_".join(what)
|
||||||
|
|
@ -45,8 +44,7 @@ class ConfigBase(object):
|
||||||
|
|
||||||
setattr(self, f"_{propname}", fn(val))
|
setattr(self, f"_{propname}", fn(val))
|
||||||
setattr(
|
setattr(
|
||||||
type(self), propname,
|
type(self), propname, property(lambda self: getattr(self, f"_{propname}"))
|
||||||
property(lambda self: getattr(self, f"_{propname}"))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -65,10 +63,10 @@ class ConfigBase(object):
|
||||||
def get_parser_func(toc):
|
def get_parser_func(toc):
|
||||||
def add_common_args(self, prog_name):
|
def add_common_args(self, prog_name):
|
||||||
parser = super(toc, self).get_parser(prog_name)
|
parser = super(toc, self).get_parser(prog_name)
|
||||||
parser.add_argument(
|
parser.add_argument("--doom", default=pathlib.Path.home().joinpath("doom"))
|
||||||
"--doom", default=pathlib.Path.home().joinpath("doom"))
|
|
||||||
parser.add_argument("--config-name", default="config.toml")
|
parser.add_argument("--config-name", default="config.toml")
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
return add_common_args
|
return add_common_args
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,10 @@ class Configure(dcc.doom_base.Wad):
|
||||||
wad = omg.WadIO(w)
|
wad = omg.WadIO(w)
|
||||||
complevel = wad.read("COMPLVL").decode("ascii").strip()
|
complevel = wad.read("COMPLVL").decode("ascii").strip()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(f"Wad {w} likely has no lump COMPLVL (exception {e})")
|
||||||
f"Wad {w} likely has no lump COMPLVL (exception {e})")
|
|
||||||
if complevel is None:
|
if complevel is None:
|
||||||
complevel = input("Complevel? ")
|
complevel = input("Complevel? ")
|
||||||
|
|
||||||
|
|
||||||
doc = tomlkit.document()
|
doc = tomlkit.document()
|
||||||
doc.add("complevel", complevel)
|
doc.add("complevel", complevel)
|
||||||
if parsed_args.iwad is not None:
|
if parsed_args.iwad is not None:
|
||||||
|
|
|
||||||
|
|
@ -70,9 +70,8 @@ class Wad(dcc.config.Base):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def thumb_overlay_path(self):
|
def thumb_overlay_path(self):
|
||||||
return (
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(
|
||||||
self._ensure(self.fabricate.joinpath(self.wad))
|
self.thumbnail_overlay_name
|
||||||
.joinpath(self.thumbnail_overlay_name)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -129,55 +128,49 @@ class WadMap(Wad):
|
||||||
|
|
||||||
def demo_in_path(self):
|
def demo_in_path(self):
|
||||||
candidates = [
|
candidates = [
|
||||||
x for x in self.demos.joinpath(self.wad)
|
x for x in self.demos.joinpath(self.wad).glob(self._file_base("*.lmp"))
|
||||||
.glob(self._file_base("*.lmp"))
|
|
||||||
]
|
]
|
||||||
if len(candidates) == 0:
|
if len(candidates) == 0:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"no suitable demo candidates for WAD {} MAP {} name {}."
|
"no suitable demo candidates for WAD {} MAP {} name {}.".format(
|
||||||
.format(self.wad, self.map, self.name_string)
|
self.wad, self.map, self.name_string
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if len(candidates) == 1:
|
if len(candidates) == 1:
|
||||||
return candidates[0]
|
return candidates[0]
|
||||||
return sorted(filter(lambda s: re.search("-", str(s)), candidates))[-1]
|
return sorted(filter(lambda s: re.search("-", str(s)), candidates))[-1]
|
||||||
|
|
||||||
def dsda_text_path(self):
|
def dsda_text_path(self):
|
||||||
return (
|
return self._ensure(self.demos.joinpath(self.wad)).joinpath(
|
||||||
self._ensure(self.demos.joinpath(self.wad))
|
self._file_base(".txt")
|
||||||
.joinpath(self._file_base(".txt"))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def video_path(self):
|
def video_path(self):
|
||||||
return (
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(
|
||||||
self._ensure(self.fabricate.joinpath(self.wad))
|
self._file_base(".mp4")
|
||||||
.joinpath(self._file_base(".mp4"))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def demo_out_path(self):
|
def demo_out_path(self):
|
||||||
return (
|
return self._ensure(self.demos.joinpath(self.wad)).joinpath(
|
||||||
self._ensure(self.demos.joinpath(self.wad))
|
self._file_base(".lmp")
|
||||||
.joinpath(self._file_base(".lmp"))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def target_bucket(self):
|
def target_bucket(self):
|
||||||
return "doom/" + self._file_base(".lmp")
|
return "doom/" + self._file_base(".lmp")
|
||||||
|
|
||||||
def base_thumb_path(self):
|
def base_thumb_path(self):
|
||||||
return (
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(
|
||||||
self._ensure(self.fabricate.joinpath(self.wad))
|
self._file_base("_base.png")
|
||||||
.joinpath(self._file_base("_base.png"))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def text_thumb_path(self):
|
def text_thumb_path(self):
|
||||||
return (
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(
|
||||||
self._ensure(self.fabricate.joinpath(self.wad))
|
self._file_base("_text.png")
|
||||||
.joinpath(self._file_base("_text.png"))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def thumb_path(self):
|
def thumb_path(self):
|
||||||
return (
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(
|
||||||
self._ensure(self.fabricate.joinpath(self.wad))
|
self._file_base("_thumb.png")
|
||||||
.joinpath(self._file_base("_thumb.png"))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def _file_base(self, ext):
|
def _file_base(self, ext):
|
||||||
|
|
|
||||||
11
dcc/dsda.py
11
dcc/dsda.py
|
|
@ -22,10 +22,9 @@ class DSDA(dcc.doom_base.WadMap):
|
||||||
if shutil.which("xvfb-run") is not None:
|
if shutil.which("xvfb-run") is not None:
|
||||||
command = ["xvfb-run"] + command
|
command = ["xvfb-run"] + command
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
command + self.dsda_preamble(warp=False) + [
|
command
|
||||||
"-fastdemo", dip, "-nosound",
|
+ self.dsda_preamble(warp=False)
|
||||||
"-skiptic", "-1", "-export_text_file"
|
+ ["-fastdemo", dip, "-nosound", "-skiptic", "-1", "-export_text_file"]
|
||||||
]
|
|
||||||
)
|
)
|
||||||
editor = "nano"
|
editor = "nano"
|
||||||
if "EDITOR" in os.environ:
|
if "EDITOR" in os.environ:
|
||||||
|
|
@ -38,7 +37,7 @@ class DSDA(dcc.doom_base.WadMap):
|
||||||
else:
|
else:
|
||||||
fh1 = self.wad[0:2] + self.map
|
fh1 = self.wad[0:2] + self.map
|
||||||
if parsed_args.single:
|
if parsed_args.single:
|
||||||
fh1 = self.wad[0:min(len(self.wad), 4)]
|
fh1 = self.wad[0 : min(len(self.wad), 4)]
|
||||||
fh2 = ""
|
fh2 = ""
|
||||||
with open(dtp, mode="r") as f:
|
with open(dtp, mode="r") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
|
|
@ -46,7 +45,7 @@ class DSDA(dcc.doom_base.WadMap):
|
||||||
m = re.search("[^0-9]*([0-9]*):([0-9]*).[0-9]*", line)
|
m = re.search("[^0-9]*([0-9]*):([0-9]*).[0-9]*", line)
|
||||||
if m is None:
|
if m is None:
|
||||||
continue
|
continue
|
||||||
fh2 = m[1]+m[2]
|
fh2 = m[1] + m[2]
|
||||||
if len(fh2) % 2 == 1:
|
if len(fh2) % 2 == 1:
|
||||||
fh2 = "0" + fh2
|
fh2 = "0" + fh2
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,11 @@ class Eureka(dcc.doom_base.WadMap):
|
||||||
if complevel == "11" or complevel == "21":
|
if complevel == "11" or complevel == "21":
|
||||||
port = "mbf"
|
port = "mbf"
|
||||||
|
|
||||||
os.execvp("eureka",
|
os.execvp(
|
||||||
["eureka"] + ["-iwad", iwad] + ["-w", parsed_args.map]
|
"eureka",
|
||||||
+ ["-p", port] + [mw]
|
["eureka"]
|
||||||
|
+ ["-iwad", iwad]
|
||||||
|
+ ["-w", parsed_args.map]
|
||||||
|
+ ["-p", port]
|
||||||
|
+ [mw],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import wand.image
|
||||||
class Extract(dcc.doom_base.Wad):
|
class Extract(dcc.doom_base.Wad):
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super().get_parser(prog_name)
|
parser = super().get_parser(prog_name)
|
||||||
parser.add_argument('lump')
|
parser.add_argument("lump")
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
|
|
@ -24,8 +24,9 @@ class Extract(dcc.doom_base.Wad):
|
||||||
) as img:
|
) as img:
|
||||||
img.transparent_color(wand.color.Color("#ff00ff"), 0.0)
|
img.transparent_color(wand.color.Color("#ff00ff"), 0.0)
|
||||||
img.save(
|
img.save(
|
||||||
filename=self.fabricate.joinpath(parsed_args.wad)
|
filename=self.fabricate.joinpath(parsed_args.wad).joinpath(
|
||||||
.joinpath(parsed_args.lump + ".png")
|
parsed_args.lump + ".png"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -35,6 +36,5 @@ class Extract(dcc.doom_base.Wad):
|
||||||
)
|
)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f"Lump {parsed_args.lump} not found in any wad in "
|
f"Lump {parsed_args.lump} not found in any wad in " + f"{parsed_args.wad}"
|
||||||
+ f"{parsed_args.wad}"
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,12 @@ class Fabricate(dcc.doom_base.WadMap):
|
||||||
command = [self.dsda]
|
command = [self.dsda]
|
||||||
if not parsed_args.fg and shutil.which("xvfb-run") is not None:
|
if not parsed_args.fg and shutil.which("xvfb-run") is not None:
|
||||||
command = ["xvfb-run"] + command
|
command = ["xvfb-run"] + command
|
||||||
os.execvp(command[0],
|
os.execvp(
|
||||||
command + self.dsda_preamble()
|
command[0],
|
||||||
|
command
|
||||||
|
+ self.dsda_preamble()
|
||||||
+ ["-timedemo", self.demo_in_path()]
|
+ ["-timedemo", self.demo_in_path()]
|
||||||
+ ["-viddump", self.video_path()]
|
+ ["-viddump", self.video_path()],
|
||||||
)
|
)
|
||||||
|
|
||||||
def options_dict(self):
|
def options_dict(self):
|
||||||
|
|
|
||||||
21
dcc/fetch.py
21
dcc/fetch.py
|
|
@ -21,14 +21,12 @@ class Fetch(dcc.config.Base):
|
||||||
idgames_id = self.search_idgames(parsed_args.id_or_name)
|
idgames_id = self.search_idgames(parsed_args.id_or_name)
|
||||||
|
|
||||||
reply = self.fetch_url(
|
reply = self.fetch_url(
|
||||||
"https://www.doomworld.com/idgames/api/" +
|
"https://www.doomworld.com/idgames/api/"
|
||||||
"api.php?action=get&id={}&out=json".format(idgames_id)
|
+ "api.php?action=get&id={}&out=json".format(idgames_id)
|
||||||
|
)
|
||||||
|
rpath = "/".join(
|
||||||
|
[self.fetch_mirror, reply["content"]["dir"], reply["content"]["filename"]]
|
||||||
)
|
)
|
||||||
rpath = "/".join([
|
|
||||||
self.fetch_mirror,
|
|
||||||
reply["content"]["dir"],
|
|
||||||
reply["content"]["filename"]
|
|
||||||
])
|
|
||||||
wad = reply["content"]["filename"][0:-4]
|
wad = reply["content"]["filename"][0:-4]
|
||||||
|
|
||||||
with urllib.request.urlopen(rpath) as response:
|
with urllib.request.urlopen(rpath) as response:
|
||||||
|
|
@ -38,8 +36,8 @@ class Fetch(dcc.config.Base):
|
||||||
# TODO: explicit error handling. Let users choose when >1 result.
|
# TODO: explicit error handling. Let users choose when >1 result.
|
||||||
def search_idgames(self, wad):
|
def search_idgames(self, wad):
|
||||||
reply = self.fetch_url(
|
reply = self.fetch_url(
|
||||||
"https://www.doomworld.com/idgames/api/" +
|
"https://www.doomworld.com/idgames/api/"
|
||||||
"api.php?action=search&query={}&out=json".format(wad)
|
+ "api.php?action=search&query={}&out=json".format(wad)
|
||||||
)
|
)
|
||||||
if "content" not in reply:
|
if "content" not in reply:
|
||||||
sys.exit(f"No WAD named {wad} found on idgames.")
|
sys.exit(f"No WAD named {wad} found on idgames.")
|
||||||
|
|
@ -62,8 +60,5 @@ class Fetch(dcc.config.Base):
|
||||||
if fetcher_path is None:
|
if fetcher_path is None:
|
||||||
raise Exception(f"Fetch util {fetcher} not found on PATH.")
|
raise Exception(f"Fetch util {fetcher} not found on PATH.")
|
||||||
|
|
||||||
proc = subprocess.run(
|
proc = subprocess.run([fetcher_path, url], capture_output=True, check=True)
|
||||||
[fetcher_path, url],
|
|
||||||
capture_output=True, check=True
|
|
||||||
)
|
|
||||||
return json.loads(proc.stdout)
|
return json.loads(proc.stdout)
|
||||||
|
|
|
||||||
24
dcc/ls.py
24
dcc/ls.py
|
|
@ -12,16 +12,13 @@ class List(dcc.config.ListerBase):
|
||||||
match parsed_args.target:
|
match parsed_args.target:
|
||||||
case "pwads":
|
case "pwads":
|
||||||
return (
|
return (
|
||||||
("pwads",), sorted(
|
("pwads",),
|
||||||
(x.name,) for x in os.scandir(self.pwads) if x.is_dir()
|
sorted((x.name,) for x in os.scandir(self.pwads) if x.is_dir()),
|
||||||
)
|
|
||||||
)
|
)
|
||||||
case "iwads":
|
case "iwads":
|
||||||
return (
|
return (
|
||||||
("iwads",), sorted(
|
("iwads",),
|
||||||
(x.name,) for x in
|
sorted((x.name,) for x in os.scandir(self.iwads) if x.is_file()),
|
||||||
os.scandir(self.iwads) if x.is_file()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
case _:
|
case _:
|
||||||
raise Exception(f"unknown target {parsed_args.target}")
|
raise Exception(f"unknown target {parsed_args.target}")
|
||||||
|
|
@ -35,11 +32,12 @@ class WadList(dcc.config.ListerBase):
|
||||||
|
|
||||||
def _get_results(self, name, base, wad, ext):
|
def _get_results(self, name, base, wad, ext):
|
||||||
return (
|
return (
|
||||||
(name,), sorted(
|
(name,),
|
||||||
(x.name,) for x in
|
sorted(
|
||||||
os.scandir(base.joinpath(wad))
|
(x.name,)
|
||||||
|
for x in os.scandir(base.joinpath(wad))
|
||||||
if x.name.endswith(ext)
|
if x.name.endswith(ext)
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -50,6 +48,4 @@ class ListDemos(WadList):
|
||||||
|
|
||||||
class ListVideos(WadList):
|
class ListVideos(WadList):
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
return self._get_results(
|
return self._get_results("videos", self.fabricate, parsed_args.wad, ".mp4")
|
||||||
"videos", self.fabricate, parsed_args.wad, ".mp4"
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -68,5 +68,5 @@ def main(argv=sys.argv[1:]):
|
||||||
return dcc.run(argv)
|
return dcc.run(argv)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|
|
||||||
11
dcc/put.py
11
dcc/put.py
|
|
@ -10,14 +10,13 @@ class Put(dcc.doom_base.WadMap):
|
||||||
|
|
||||||
# TODO: accept configuration for bucket name
|
# TODO: accept configuration for bucket name
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
s3_client = boto3.client('s3')
|
s3_client = boto3.client("s3")
|
||||||
demo = self.demo_in_path()
|
demo = self.demo_in_path()
|
||||||
bucket = self.target_bucket()
|
bucket = self.target_bucket()
|
||||||
print("Uploading {} to bucket {}.".format(demo, bucket))
|
print("Uploading {} to bucket {}.".format(demo, bucket))
|
||||||
s3_client.upload_file(
|
s3_client.upload_file(
|
||||||
demo, 'yrriban', bucket,
|
demo,
|
||||||
ExtraArgs={
|
"yrriban",
|
||||||
'ContentType': 'binary/octet-stream',
|
bucket,
|
||||||
'ACL': 'public-read'
|
ExtraArgs={"ContentType": "binary/octet-stream", "ACL": "public-read"},
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import os
|
||||||
|
|
||||||
class Record(dcc.doom_base.WadMap):
|
class Record(dcc.doom_base.WadMap):
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
os.execv(self.dsda,
|
os.execv(
|
||||||
[self.dsda] + self.dsda_preamble() +
|
self.dsda,
|
||||||
["-record", self.demo_out_path()]
|
[self.dsda] + self.dsda_preamble() + ["-record", self.demo_out_path()],
|
||||||
)
|
)
|
||||||
|
|
||||||
def options_dict(self):
|
def options_dict(self):
|
||||||
|
|
|
||||||
16
dcc/rib.py
16
dcc/rib.py
|
|
@ -16,10 +16,10 @@ class RIB(dcc.doom_base.WadMap):
|
||||||
demo = ""
|
demo = ""
|
||||||
dt = 0
|
dt = 0
|
||||||
demodir = (
|
demodir = (
|
||||||
pathlib.Path.home() /
|
pathlib.Path.home()
|
||||||
".dsda-doom" /
|
/ ".dsda-doom"
|
||||||
"dsda_doom_data" /
|
/ "dsda_doom_data"
|
||||||
self.iwad_path.stem.lower()
|
/ self.iwad_path.stem.lower()
|
||||||
)
|
)
|
||||||
for w in self.load_order():
|
for w in self.load_order():
|
||||||
demodir = demodir.joinpath(w.stem.lower())
|
demodir = demodir.joinpath(w.stem.lower())
|
||||||
|
|
@ -41,8 +41,10 @@ class RIB(dcc.doom_base.WadMap):
|
||||||
+ f"and map {parsed_args.map} (tried to look in {demodir})"
|
+ f"and map {parsed_args.map} (tried to look in {demodir})"
|
||||||
)
|
)
|
||||||
|
|
||||||
os.execv(self.dsda,
|
os.execv(
|
||||||
[self.dsda] + self.dsda_preamble(warp=False)
|
self.dsda,
|
||||||
|
[self.dsda]
|
||||||
|
+ self.dsda_preamble(warp=False)
|
||||||
+ ["-playdemo", demo]
|
+ ["-playdemo", demo]
|
||||||
+ ["-skiptic", str(-35 * parsed_args.secs_before)]
|
+ ["-skiptic", str(-35 * parsed_args.secs_before)],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ class SS(dcc.doom_base.WadMap):
|
||||||
height = self.thumbnail_height
|
height = self.thumbnail_height
|
||||||
with wand.image.Image(width=width, height=height, pseudo="x:") as img:
|
with wand.image.Image(width=width, height=height, pseudo="x:") as img:
|
||||||
img.reset_coords()
|
img.reset_coords()
|
||||||
if (img.width < width or img.height < height):
|
if img.width < width or img.height < height:
|
||||||
if not messagebox.askretrycancel(
|
if not messagebox.askretrycancel(
|
||||||
title="DCC",
|
title="DCC",
|
||||||
message=f"Image too small ({img.width}x{img.height})." +
|
message=f"Image too small ({img.width}x{img.height})."
|
||||||
"Try again?"
|
+ "Try again?",
|
||||||
):
|
):
|
||||||
sys.exit("Gave up trying to select an image.")
|
sys.exit("Gave up trying to select an image.")
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
15
dcc/text.py
15
dcc/text.py
|
|
@ -30,9 +30,7 @@ def draw_text(self, img, text, font_size=64, wrap_dist=0.75):
|
||||||
columns = len(wrapped_text)
|
columns = len(wrapped_text)
|
||||||
while columns > 0:
|
while columns > 0:
|
||||||
columns -= 1
|
columns -= 1
|
||||||
wrapped_text = '\n'.join(
|
wrapped_text = "\n".join(textwrap.wrap(wrapped_text, columns))
|
||||||
textwrap.wrap(wrapped_text, columns)
|
|
||||||
)
|
|
||||||
wrapped_width, _ = eval_metrics(wrapped_text)
|
wrapped_width, _ = eval_metrics(wrapped_text)
|
||||||
if wrapped_width <= target_width:
|
if wrapped_width <= target_width:
|
||||||
break
|
break
|
||||||
|
|
@ -43,13 +41,13 @@ def draw_text(self, img, text, font_size=64, wrap_dist=0.75):
|
||||||
)
|
)
|
||||||
textlines[idx] = wrapped_text
|
textlines[idx] = wrapped_text
|
||||||
|
|
||||||
wrapped_text = '\n'.join(textlines)
|
wrapped_text = "\n".join(textlines)
|
||||||
|
|
||||||
draw.text(5, int(draw.font_size) + 5, wrapped_text)
|
draw.text(5, int(draw.font_size) + 5, wrapped_text)
|
||||||
draw(img)
|
draw(img)
|
||||||
draw.stroke_color = wand.color.Color("none")
|
draw.stroke_color = wand.color.Color("none")
|
||||||
draw.stroke_width = 0
|
draw.stroke_width = 0
|
||||||
draw.text(5, int(draw.font_size)+5, wrapped_text)
|
draw.text(5, int(draw.font_size) + 5, wrapped_text)
|
||||||
draw(img)
|
draw(img)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -74,12 +72,9 @@ class Text(dcc.doom_base.WadMap):
|
||||||
text += "\n"
|
text += "\n"
|
||||||
text = "{}{}".format(text, parsed_args.demotype)
|
text = "{}{}".format(text, parsed_args.demotype)
|
||||||
with wand.image.Image(
|
with wand.image.Image(
|
||||||
height=self.thumbnail_height,
|
height=self.thumbnail_height, width=self.thumbnail_width
|
||||||
width=self.thumbnail_width
|
|
||||||
) as img:
|
) as img:
|
||||||
self.draw_text(
|
self.draw_text(img, text, wrap_dist=0.95)
|
||||||
img, text, wrap_dist=0.95
|
|
||||||
)
|
|
||||||
img.trim()
|
img.trim()
|
||||||
img.reset_coords()
|
img.reset_coords()
|
||||||
img.save(filename=self.text_thumb_path())
|
img.save(filename=self.text_thumb_path())
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class Thumb(dcc.doom_base.WadMap):
|
||||||
overlay = self.thumb_overlay_path()
|
overlay = self.thumb_overlay_path()
|
||||||
with (
|
with (
|
||||||
wand.image.Image(filename=base) as bi,
|
wand.image.Image(filename=base) as bi,
|
||||||
wand.color.Color("transparent") as tc
|
wand.color.Color("transparent") as tc,
|
||||||
):
|
):
|
||||||
with wand.image.Image(filename=text) as ti:
|
with wand.image.Image(filename=text) as ti:
|
||||||
ti.border(tc, 5, 5)
|
ti.border(tc, 5, 5)
|
||||||
|
|
|
||||||
|
|
@ -32,20 +32,24 @@ def test_play(expect):
|
||||||
rig._hooks = []
|
rig._hooks = []
|
||||||
parser = rig.get_parser("test_play")
|
parser = rig.get_parser("test_play")
|
||||||
parsed_args = parser.parse_args(args=["--doom", td, "scythe", "01"])
|
parsed_args = parser.parse_args(args=["--doom", td, "scythe", "01"])
|
||||||
with expect(os, times=1).execv(
|
with (
|
||||||
tdp.joinpath("dsda-doom").joinpath("exe"),
|
expect(os, times=1)
|
||||||
[
|
.execv(
|
||||||
tdp.joinpath("dsda-doom").joinpath("exe"),
|
tdp.joinpath("dsda-doom").joinpath("exe"),
|
||||||
"-iwad",
|
[
|
||||||
tdp.joinpath("iwads").joinpath("DOOM2.WAD"),
|
tdp.joinpath("dsda-doom").joinpath("exe"),
|
||||||
"-file",
|
"-iwad",
|
||||||
tdp.joinpath("pwads").joinpath("scythe").joinpath("scythe.wad"),
|
tdp.joinpath("iwads").joinpath("DOOM2.WAD"),
|
||||||
"-complevel",
|
"-file",
|
||||||
"2",
|
tdp.joinpath("pwads").joinpath("scythe").joinpath("scythe.wad"),
|
||||||
"-skill",
|
"-complevel",
|
||||||
"4",
|
"2",
|
||||||
"-warp",
|
"-skill",
|
||||||
"01",
|
"4",
|
||||||
]
|
"-warp",
|
||||||
).thenReturn(None):
|
"01",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.thenReturn(None)
|
||||||
|
):
|
||||||
assert rig.run(parsed_args) is None
|
assert rig.run(parsed_args) is None
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue