vtskit 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vtskit-0.2.0/vtskit.egg-info → vtskit-0.3.0}/PKG-INFO +11 -7
- {vtskit-0.2.0 → vtskit-0.3.0}/README.md +10 -6
- {vtskit-0.2.0 → vtskit-0.3.0}/pyproject.toml +1 -1
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_lang.py +12 -1
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_title_buttons.py +44 -7
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/__init__.py +1 -1
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/lang.py +9 -7
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/titleset.py +39 -17
- {vtskit-0.2.0 → vtskit-0.3.0/vtskit.egg-info}/PKG-INFO +11 -7
- {vtskit-0.2.0 → vtskit-0.3.0}/COPYING +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/COPYING.LESSER +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/setup.cfg +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_angles.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_ifo.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_menu.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_nav.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_subtitles.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_titleset.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_vm.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/tests/test_vmg.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/errors.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/ifo.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/menu.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/nav.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/ps.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/spu.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/subtitles.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/vm.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit/vmg.py +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit.egg-info/SOURCES.txt +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit.egg-info/dependency_links.txt +0 -0
- {vtskit-0.2.0 → vtskit-0.3.0}/vtskit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vtskit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: DVD-Video titlesets in pure Python: VOBs, navigation packs and IFO files
|
|
5
5
|
Author: kajisho5
|
|
6
6
|
License-Expression: LGPL-3.0-or-later
|
|
@@ -146,10 +146,13 @@ oncemore writing its discs with vtskit.
|
|
|
146
146
|
to an end, the buttons, the palette entries that draw them): their
|
|
147
147
|
overlay is a forced subpicture added with `vtskit.subtitles`, and the
|
|
148
148
|
highlight information goes only into the VOBUs that play during the
|
|
149
|
-
stretch
|
|
149
|
+
stretch (where two stretches meet inside a VOBU, the one covering more
|
|
150
|
+
of it), with the stretch's start and end as its start time, end time
|
|
150
151
|
and the end of the selection (dvdinfo's hli_s_ptm, hli_e_ptm,
|
|
151
152
|
btn_sl_e_ptm). dvdauthor gives a title's buttons the whole title (every
|
|
152
|
-
VOBU, never ending), which is what buttons without an end write.
|
|
153
|
+
VOBU, never ending), which is what buttons without an end write. As
|
|
154
|
+
dvdauthor does, a title with buttons starts with its first button
|
|
155
|
+
highlighted (SetHL_BTNN 1 before its own pre commands).
|
|
153
156
|
* `vtskit.subtitles` adds subtitles to a title's program stream, as spumux
|
|
154
157
|
does: each cue a picture of up to four colours placed on the screen and
|
|
155
158
|
shown for a while, as subpicture packs a little before their time.
|
|
@@ -157,8 +160,8 @@ oncemore writing its discs with vtskit.
|
|
|
157
160
|
`if (g5 != 0) { button = g5; }`, `call menu entry root;`) for the domain
|
|
158
161
|
a text runs in, to the same commands dvdauthor writes for it: a tool
|
|
159
162
|
that already speaks the language, as oncemore does, keeps its text. A
|
|
160
|
-
button of several commands
|
|
161
|
-
dispatcher, and a jump to a chapter of another titleset goes through pad
|
|
163
|
+
button of several commands, a menu's or a title's, runs them from the
|
|
164
|
+
program chain's post through a dispatcher, and a jump to a chapter of another titleset goes through pad
|
|
162
165
|
program chains, as dvdauthor's "jumppads" do.
|
|
163
166
|
* `vtskit.vmg` writes the video manager: VIDEO_TS.IFO and its BUP, with
|
|
164
167
|
the first-play commands, the table of titles and the titlesets'
|
|
@@ -190,8 +193,9 @@ dvdauthor's (its buttons made with spumux), and a menu's overlay in a
|
|
|
190
193
|
normal colour is spumux's unit byte for byte; subtitles muxed by vtskit are
|
|
191
194
|
spumux's units, placed where spumux places them, and the title written
|
|
192
195
|
from that stream (4:3, and 16:9 with and without pan-scan or letterbox) is
|
|
193
|
-
dvdauthor's; a title with buttons over the whole of it
|
|
194
|
-
VOB byte for byte
|
|
196
|
+
dvdauthor's; a title with buttons over the whole of it (one of them of
|
|
197
|
+
several commands) is dvdauthor's VOB and IFO byte for byte, but for the
|
|
198
|
+
palette. A VIDEO_TS written by vtskit alone plays
|
|
195
199
|
its titles and chapters in order under libdvdnav, its commands jumping
|
|
196
200
|
between titles, its menus' buttons lead where they say, and its jumps into
|
|
197
201
|
another titleset's chapters land; a title with an angle block plays and
|
|
@@ -129,10 +129,13 @@ oncemore writing its discs with vtskit.
|
|
|
129
129
|
to an end, the buttons, the palette entries that draw them): their
|
|
130
130
|
overlay is a forced subpicture added with `vtskit.subtitles`, and the
|
|
131
131
|
highlight information goes only into the VOBUs that play during the
|
|
132
|
-
stretch
|
|
132
|
+
stretch (where two stretches meet inside a VOBU, the one covering more
|
|
133
|
+
of it), with the stretch's start and end as its start time, end time
|
|
133
134
|
and the end of the selection (dvdinfo's hli_s_ptm, hli_e_ptm,
|
|
134
135
|
btn_sl_e_ptm). dvdauthor gives a title's buttons the whole title (every
|
|
135
|
-
VOBU, never ending), which is what buttons without an end write.
|
|
136
|
+
VOBU, never ending), which is what buttons without an end write. As
|
|
137
|
+
dvdauthor does, a title with buttons starts with its first button
|
|
138
|
+
highlighted (SetHL_BTNN 1 before its own pre commands).
|
|
136
139
|
* `vtskit.subtitles` adds subtitles to a title's program stream, as spumux
|
|
137
140
|
does: each cue a picture of up to four colours placed on the screen and
|
|
138
141
|
shown for a while, as subpicture packs a little before their time.
|
|
@@ -140,8 +143,8 @@ oncemore writing its discs with vtskit.
|
|
|
140
143
|
`if (g5 != 0) { button = g5; }`, `call menu entry root;`) for the domain
|
|
141
144
|
a text runs in, to the same commands dvdauthor writes for it: a tool
|
|
142
145
|
that already speaks the language, as oncemore does, keeps its text. A
|
|
143
|
-
button of several commands
|
|
144
|
-
dispatcher, and a jump to a chapter of another titleset goes through pad
|
|
146
|
+
button of several commands, a menu's or a title's, runs them from the
|
|
147
|
+
program chain's post through a dispatcher, and a jump to a chapter of another titleset goes through pad
|
|
145
148
|
program chains, as dvdauthor's "jumppads" do.
|
|
146
149
|
* `vtskit.vmg` writes the video manager: VIDEO_TS.IFO and its BUP, with
|
|
147
150
|
the first-play commands, the table of titles and the titlesets'
|
|
@@ -173,8 +176,9 @@ dvdauthor's (its buttons made with spumux), and a menu's overlay in a
|
|
|
173
176
|
normal colour is spumux's unit byte for byte; subtitles muxed by vtskit are
|
|
174
177
|
spumux's units, placed where spumux places them, and the title written
|
|
175
178
|
from that stream (4:3, and 16:9 with and without pan-scan or letterbox) is
|
|
176
|
-
dvdauthor's; a title with buttons over the whole of it
|
|
177
|
-
VOB byte for byte
|
|
179
|
+
dvdauthor's; a title with buttons over the whole of it (one of them of
|
|
180
|
+
several commands) is dvdauthor's VOB and IFO byte for byte, but for the
|
|
181
|
+
palette. A VIDEO_TS written by vtskit alone plays
|
|
178
182
|
its titles and chapters in order under libdvdnav, its commands jumping
|
|
179
183
|
between titles, its menus' buttons lead where they say, and its jumps into
|
|
180
184
|
another titleset's chapters land; a title with an angle block plays and
|
|
@@ -138,6 +138,17 @@ class TestForms(unittest.TestCase):
|
|
|
138
138
|
self.assertEqual(hexes(self.d.compile("g1 = 0; exit;", "vts", 1)), ["7100000100000000", "3001000000000000"])
|
|
139
139
|
self.assertEqual(hexes(self.d.compile("call menu entry root resume 3;", "vts", 1)), ["3008000003830000"])
|
|
140
140
|
|
|
141
|
+
def test_title_buttons(self):
|
|
142
|
+
# dvdauthor's bytes for the same buttons in a title's <pgc>, with
|
|
143
|
+
# <post>jump title 2;</post>: the same dispatcher as a menu's
|
|
144
|
+
buttons, post = self.d.menu(["g1 = 2; g2 = 3; jump title 2 chapter 1;", "g3 = 4; g4 = 5; jump title 2;"],
|
|
145
|
+
"jump title 2;", "vts", 1)
|
|
146
|
+
self.assertEqual(hexes(buttons), ["7101000f0001000d", "7101000f0002000d"])
|
|
147
|
+
self.assertEqual(hexes(post), ["6100000e000f0000", "7100000f00000000", "00a1000e00010006",
|
|
148
|
+
"00a1000e00020009", "3003000000020000", "7100000100020000",
|
|
149
|
+
"7100000200030000", "3005000100020000", "7100000300040000",
|
|
150
|
+
"7100000400050000", "3003000000020000"])
|
|
151
|
+
|
|
141
152
|
def test_dead_code_after_a_jump(self):
|
|
142
153
|
self.assertEqual(hexes(self.d.compile("g1 = 0; resume; g1 = 0; jump title 1 chapter 2; "
|
|
143
154
|
"subtitle = 65; audio = 1;", "vtsm", 1)),
|
|
@@ -191,7 +202,7 @@ class TestForms(unittest.TestCase):
|
|
|
191
202
|
with self.assertRaises(VtsError):
|
|
192
203
|
self.d.menu(["g1 = 1; g2 = 2;"], "g3 = 3;", "vtsm", 1) # post that does not leave
|
|
193
204
|
with self.assertRaises(VtsError):
|
|
194
|
-
self.d.menu(["exit;"], "exit;", "
|
|
205
|
+
self.d.menu(["exit;"], "exit;", "fp") # no buttons in the first play
|
|
195
206
|
|
|
196
207
|
|
|
197
208
|
def author(folder, menu_n, menu_h, a, b):
|
|
@@ -13,7 +13,7 @@ import sys
|
|
|
13
13
|
import tempfile
|
|
14
14
|
import unittest
|
|
15
15
|
|
|
16
|
-
from vtskit import VtsError, menu, ps, spu, subtitles, titleset, vm, vmg
|
|
16
|
+
from vtskit import VtsError, lang, menu, ps, spu, subtitles, titleset, vm, vmg
|
|
17
17
|
from vtskit.menu import Button, TitleButtons
|
|
18
18
|
from vtskit.titleset import Audio, Title
|
|
19
19
|
|
|
@@ -104,7 +104,7 @@ class TestTitleButtons(unittest.TestCase):
|
|
|
104
104
|
def test_whole_title_as_dvdauthor(self):
|
|
105
105
|
# spumux's buttons over the whole title, then dvdauthor; vtskit
|
|
106
106
|
# given the same stream and buttons without an end writes the same
|
|
107
|
-
# VOB (dvdauthor writes the HLI in every VOBU, never ending)
|
|
107
|
+
# VOB (dvdauthor writes the HLI in every VOBU, never ending) and IFO
|
|
108
108
|
t = self.tmp
|
|
109
109
|
png(f"{t}/hl.png", 720, 480, RECTS, (255, 255, 0))
|
|
110
110
|
png(f"{t}/sel.png", 720, 480, RECTS, (255, 0, 0))
|
|
@@ -118,17 +118,35 @@ class TestTitleButtons(unittest.TestCase):
|
|
|
118
118
|
with open(self.plain, "rb") as src, open(sp, "wb") as dst:
|
|
119
119
|
subprocess.run(["spumux", "-s", "0", f"{t}/spu.xml"], stdin=src, stdout=dst, check=True,
|
|
120
120
|
stderr=subprocess.DEVNULL, env=ENV)
|
|
121
|
+
texts = ["g1 = 2; g2 = 3; jump title 2 chapter 1;", "exit;"]
|
|
121
122
|
with open(f"{t}/dvd.xml", "w") as f:
|
|
122
123
|
f.write(f'<dvdauthor dest="{t}/dvd"><vmgm/><titleset><titles>'
|
|
123
124
|
'<video format="ntsc" aspect="4:3"/><audio format="ac3" channels="2" lang="en"/>'
|
|
124
|
-
f'<pgc><vob file="{sp}"/><button name="b1">
|
|
125
|
-
'<button name="b2">
|
|
125
|
+
f'<pgc><vob file="{sp}"/><button name="b1">{texts[0]}</button>'
|
|
126
|
+
f'<button name="b2">{texts[1]}</button><post>jump title 2;</post></pgc>'
|
|
127
|
+
f'<pgc><vob file="{self.short}"/></pgc></titles></titleset></dvdauthor>')
|
|
126
128
|
subprocess.run(["dvdauthor", "-x", f"{t}/dvd.xml"], check=True, capture_output=True, env=ENV)
|
|
129
|
+
# vtskit: the same buttons compiled with vtskit.lang (a button of
|
|
130
|
+
# several commands runs them from the post, through a dispatcher)
|
|
131
|
+
disc = lang.Disc({(1, 1): 1, (1, 2): 2}, titlesets={1: lang.Menus()})
|
|
132
|
+
commands, post = disc.menu(texts, "jump title 2;", "vts", 1)
|
|
133
|
+
tb = buttons(0, None)
|
|
134
|
+
for b, c in zip(tb.buttons, commands):
|
|
135
|
+
b.command = c
|
|
127
136
|
mine = f"{t}/mine-whole"
|
|
128
|
-
titleset.write(mine, 1, [Title(sp, audio=(Audio("en", 2),),
|
|
129
|
-
|
|
137
|
+
titleset.write(mine, 1, [Title(sp, audio=(Audio("en", 2),), post=tuple(post), buttons=(tb,)),
|
|
138
|
+
Title(self.short, audio=(Audio("en", 2),))])
|
|
139
|
+
theirs = f"{t}/dvd/VIDEO_TS"
|
|
140
|
+
a, b = read(f"{mine}/VTS_01_1.VOB"), read(f"{theirs}/VTS_01_1.VOB")
|
|
130
141
|
self.assertEqual([n[2] for n in navs(a)], [n[2] for n in navs(b)])
|
|
131
142
|
self.assertEqual(a, b)
|
|
143
|
+
# the IFO: the same, the title's pre (SetHL_BTNN 1) and post
|
|
144
|
+
# included, but for the palette (spumux's colours)
|
|
145
|
+
a, b = read(f"{mine}/VTS_01_0.IFO"), read(f"{theirs}/VTS_01_0.IFO")
|
|
146
|
+
self.assertEqual(len(a), len(b))
|
|
147
|
+
pgc = struct.unpack_from(">I", a, 0xCC)[0] * 2048 + 16
|
|
148
|
+
self.assertEqual(a[:pgc + 0xA4], b[:pgc + 0xA4])
|
|
149
|
+
self.assertEqual(a[pgc + 0xE4:], b[pgc + 0xE4:])
|
|
132
150
|
|
|
133
151
|
def stretch_disc(self, start, end):
|
|
134
152
|
"""Title 1 (10 s) with buttons from `start` to `end` (button 1:
|
|
@@ -173,10 +191,29 @@ class TestTitleButtons(unittest.TestCase):
|
|
|
173
191
|
with self.assertRaisesRegex(VtsError, "overlap"):
|
|
174
192
|
write(buttons(1, None), buttons(3, 5))
|
|
175
193
|
with self.assertRaisesRegex(VtsError, "one set of buttons"):
|
|
176
|
-
write(buttons(1,
|
|
194
|
+
write(buttons(1, 3.0), buttons(3.05, 3.2), buttons(3.25, 5)) # in the VOBU from 3.0 s
|
|
177
195
|
with self.assertRaisesRegex(VtsError, "after the title ends"):
|
|
178
196
|
write(buttons(30, 40))
|
|
179
197
|
|
|
198
|
+
def test_stretches_meeting_in_a_vobu(self):
|
|
199
|
+
# the VOBUs start every 0.6006 s; where two stretches meet inside a
|
|
200
|
+
# VOBU, it carries the one covering more of it
|
|
201
|
+
def starts(*tbs):
|
|
202
|
+
"""{VOBU start (s, rounded): its HLI's start from the title's start}"""
|
|
203
|
+
out = os.path.join(self.tmp, "meeting")
|
|
204
|
+
titleset.write(out, 1, [Title(self.plain, audio=(Audio("en", 2),), buttons=tbs)])
|
|
205
|
+
packs = navs(read(f"{out}/VTS_01_1.VOB"))
|
|
206
|
+
s0 = packs[0][1]
|
|
207
|
+
return {round((s - s0) / 90000, 1): struct.unpack_from(">I", h, 2)[0] - s0 if h[1] else None
|
|
208
|
+
for _, s, h in packs}
|
|
209
|
+
got = starts(buttons(1, 2.8), buttons(2.9, 5))
|
|
210
|
+
self.assertEqual((got[1.8], got[2.4], got[3.0]), (90000, 90000, 261000))
|
|
211
|
+
# buttons that change a frame before or after a VOBU's start (as a
|
|
212
|
+
# film title's frames fall): each VOBU still carries its own
|
|
213
|
+
for edge in (3.003 - 3003 / 90000, 3.003 + 3003 / 90000):
|
|
214
|
+
got = starts(buttons(1, edge), buttons(edge, 5))
|
|
215
|
+
self.assertEqual((got[2.4], got[3.0]), (90000, int(round(edge * 90000))), edge)
|
|
216
|
+
|
|
180
217
|
@unittest.skipUnless(LIBDVDNAV, "needs libdvdnav")
|
|
181
218
|
def test_under_libdvdnav(self):
|
|
182
219
|
out = self.stretch_disc(3.0, 6.0)
|
|
@@ -25,10 +25,10 @@ authored):
|
|
|
25
25
|
* `audio = 1; subtitle = 65;` next to each other are one SetSTN; `g1 = 0;
|
|
26
26
|
jump menu 2;` is one command (vtskit.vm folds a Set and a Link), and
|
|
27
27
|
what follows an unconditional jump in a block is left out;
|
|
28
|
-
* a menu's button runs one command: a button whose text
|
|
29
|
-
sets GPRM 15 to its number and links to the end of the
|
|
30
|
-
whose post commands start with a dispatcher (`g14 = g15;
|
|
31
|
-
Goto per such button) and end with each button's code;
|
|
28
|
+
* a menu's or a title's button runs one command: a button whose text
|
|
29
|
+
compiles to more sets GPRM 15 to its number and links to the end of the
|
|
30
|
+
program chain, whose post commands start with a dispatcher (`g14 = g15;
|
|
31
|
+
g15 = 0;` and a Goto per such button) and end with each button's code;
|
|
32
32
|
* a jump into another titleset (dvdauthor's "jumppad") cannot be one
|
|
33
33
|
command: from the video manager a jump to a chapter sets GPRM 15 to a
|
|
34
34
|
code naming the title and chapter and jumps to the titleset's chapter
|
|
@@ -572,10 +572,12 @@ class Disc:
|
|
|
572
572
|
def menu(self, buttons, post, domain="vtsm", vts=0):
|
|
573
573
|
"""A menu's buttons and post commands: ([one command a button],
|
|
574
574
|
post commands). A button whose text takes several commands runs
|
|
575
|
-
them from the post, through a dispatcher, as dvdauthor arranges.
|
|
575
|
+
them from the post, through a dispatcher, as dvdauthor arranges.
|
|
576
|
+
A title's buttons (domain "vts") are compiled the same way, as
|
|
577
|
+
dvdauthor compiles them."""
|
|
576
578
|
self._check_domain(domain)
|
|
577
|
-
if domain not in ("vtsm", "vmgm"):
|
|
578
|
-
raise VtsError("buttons belong to menus")
|
|
579
|
+
if domain not in ("vtsm", "vmgm", "vts"):
|
|
580
|
+
raise VtsError("buttons belong to menus and titles")
|
|
579
581
|
commands, deferred = [], []
|
|
580
582
|
for n, text in enumerate(buttons, 1):
|
|
581
583
|
items = self.instructions(text, domain, vts)
|
|
@@ -63,7 +63,7 @@ import os
|
|
|
63
63
|
import struct
|
|
64
64
|
from dataclasses import dataclass, field
|
|
65
65
|
|
|
66
|
-
from . import menu as menus_, nav, ps, spu
|
|
66
|
+
from . import menu as menus_, nav, ps, spu, vm
|
|
67
67
|
from .errors import VtsError
|
|
68
68
|
|
|
69
69
|
SECTOR = ps.SECTOR
|
|
@@ -748,12 +748,25 @@ def _lay_title(number, title, offset, vob_id, loaded):
|
|
|
748
748
|
return w, sector, vob_id
|
|
749
749
|
|
|
750
750
|
|
|
751
|
+
def _pre(title):
|
|
752
|
+
"""A title's pre commands: with buttons, first the first button
|
|
753
|
+
highlighted (SetHL_BTNN 1), as dvdauthor writes it for a title with
|
|
754
|
+
buttons (tests/test_title_buttons.py)."""
|
|
755
|
+
if not title.buttons:
|
|
756
|
+
return tuple(title.pre)
|
|
757
|
+
return (vm.set_hl_btnn(1 << 10).encode(),) + tuple(title.pre)
|
|
758
|
+
|
|
759
|
+
|
|
751
760
|
def _title_buttons(number, title, loaded, part_start):
|
|
752
761
|
"""The HLI of the title's buttons: {(part, angle): {VOBU: HLI}}, in the
|
|
753
762
|
VOBUs that play during each stretch (every angle's), shown from the
|
|
754
763
|
stretch's start to its end in the VOB's time (a stretch that began in
|
|
755
764
|
an earlier part from the VOB's start; one that goes on into a later
|
|
756
|
-
part to the VOB's end; one without an end never ending).
|
|
765
|
+
part to the VOB's end; one without an end never ending). Where two
|
|
766
|
+
stretches meet inside a VOBU, it carries the one that covers more of
|
|
767
|
+
it: buttons that change between VOBUs (oncemore starts a VOBU there)
|
|
768
|
+
are not lost to a picture's difference between a time and the VOBU's
|
|
769
|
+
start, as in a film title with pulldown."""
|
|
757
770
|
if not title.buttons:
|
|
758
771
|
return {}
|
|
759
772
|
width, height = loaded[0][0][0].sequence[:2]
|
|
@@ -768,26 +781,35 @@ def _title_buttons(number, title, loaded, part_start):
|
|
|
768
781
|
if e1 is None or e1 > s2:
|
|
769
782
|
raise VtsError(f"{w1} and {w2} overlap in time")
|
|
770
783
|
out = {}
|
|
771
|
-
used = set()
|
|
784
|
+
touched, used = set(), set()
|
|
772
785
|
for k, part in enumerate(loaded):
|
|
773
786
|
for a, (_, vs, _) in enumerate(part):
|
|
774
787
|
base, vob_end = vs[0].s_ptm, vs[-1].e_ptm
|
|
775
788
|
table = out[(k, a)] = {}
|
|
776
|
-
for
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
789
|
+
for i, v in enumerate(vs):
|
|
790
|
+
t0 = part_start[k] + v.s_ptm - base
|
|
791
|
+
t1 = part_start[k] + v.e_ptm - base
|
|
792
|
+
# (two stretches in a VOBU: the one covering more of it, the
|
|
793
|
+
# later on a tie; a VOBU carries one set of buttons)
|
|
794
|
+
best = None
|
|
795
|
+
for s, e, tb, what in stretches:
|
|
796
|
+
cover = min(t1, e if e is not None else t1) - max(t0, s)
|
|
797
|
+
if cover > 0:
|
|
798
|
+
touched.add(what)
|
|
799
|
+
if best is None or cover >= best[0]:
|
|
800
|
+
best = (cover, s, e, tb, what)
|
|
801
|
+
if best is None:
|
|
802
|
+
continue
|
|
803
|
+
_, s, e, tb, what = best
|
|
804
|
+
he = 0xFFFFFFFF if e is None else min(base + e - part_start[k], vob_end)
|
|
805
|
+
table[i] = tb.hli(base + max(s - part_start[k], 0), he)
|
|
806
|
+
used.add(what)
|
|
788
807
|
for _, _, _, what in stretches:
|
|
789
|
-
if what not in
|
|
808
|
+
if what not in touched:
|
|
790
809
|
raise VtsError(f"{what} start after the title ends")
|
|
810
|
+
if what not in used:
|
|
811
|
+
raise VtsError(f"{what} are shown for less of each VOBU they fall in than the buttons "
|
|
812
|
+
"beside them: a VOBU carries one set of buttons")
|
|
791
813
|
return out
|
|
792
814
|
|
|
793
815
|
|
|
@@ -955,7 +977,7 @@ def _write(folder, vts, titles, written, menus, language, pan_scan, letterbox, c
|
|
|
955
977
|
for name in ("next_pgc", "prev_pgc", "up_pgc"):
|
|
956
978
|
if not 0 <= getattr(t, name) <= len(titles):
|
|
957
979
|
raise VtsError(f"title {n}: {name} {getattr(t, name)}: the titleset has {len(titles)} program chains")
|
|
958
|
-
pgcs = [_pgc((t
|
|
980
|
+
pgcs = [_pgc((_pre(t), t.post, t.cell_commands), w, frame, sorted(w.stream.subpictures), t.palette,
|
|
959
981
|
stills=t.stills, uops=t.uops, video=video, links=(t.next_pgc, t.prev_pgc, t.up_pgc))
|
|
960
982
|
for t, w in zip(titles, written)]
|
|
961
983
|
pgci = struct.pack(">HHI", len(pgcs), 0, 0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vtskit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: DVD-Video titlesets in pure Python: VOBs, navigation packs and IFO files
|
|
5
5
|
Author: kajisho5
|
|
6
6
|
License-Expression: LGPL-3.0-or-later
|
|
@@ -146,10 +146,13 @@ oncemore writing its discs with vtskit.
|
|
|
146
146
|
to an end, the buttons, the palette entries that draw them): their
|
|
147
147
|
overlay is a forced subpicture added with `vtskit.subtitles`, and the
|
|
148
148
|
highlight information goes only into the VOBUs that play during the
|
|
149
|
-
stretch
|
|
149
|
+
stretch (where two stretches meet inside a VOBU, the one covering more
|
|
150
|
+
of it), with the stretch's start and end as its start time, end time
|
|
150
151
|
and the end of the selection (dvdinfo's hli_s_ptm, hli_e_ptm,
|
|
151
152
|
btn_sl_e_ptm). dvdauthor gives a title's buttons the whole title (every
|
|
152
|
-
VOBU, never ending), which is what buttons without an end write.
|
|
153
|
+
VOBU, never ending), which is what buttons without an end write. As
|
|
154
|
+
dvdauthor does, a title with buttons starts with its first button
|
|
155
|
+
highlighted (SetHL_BTNN 1 before its own pre commands).
|
|
153
156
|
* `vtskit.subtitles` adds subtitles to a title's program stream, as spumux
|
|
154
157
|
does: each cue a picture of up to four colours placed on the screen and
|
|
155
158
|
shown for a while, as subpicture packs a little before their time.
|
|
@@ -157,8 +160,8 @@ oncemore writing its discs with vtskit.
|
|
|
157
160
|
`if (g5 != 0) { button = g5; }`, `call menu entry root;`) for the domain
|
|
158
161
|
a text runs in, to the same commands dvdauthor writes for it: a tool
|
|
159
162
|
that already speaks the language, as oncemore does, keeps its text. A
|
|
160
|
-
button of several commands
|
|
161
|
-
dispatcher, and a jump to a chapter of another titleset goes through pad
|
|
163
|
+
button of several commands, a menu's or a title's, runs them from the
|
|
164
|
+
program chain's post through a dispatcher, and a jump to a chapter of another titleset goes through pad
|
|
162
165
|
program chains, as dvdauthor's "jumppads" do.
|
|
163
166
|
* `vtskit.vmg` writes the video manager: VIDEO_TS.IFO and its BUP, with
|
|
164
167
|
the first-play commands, the table of titles and the titlesets'
|
|
@@ -190,8 +193,9 @@ dvdauthor's (its buttons made with spumux), and a menu's overlay in a
|
|
|
190
193
|
normal colour is spumux's unit byte for byte; subtitles muxed by vtskit are
|
|
191
194
|
spumux's units, placed where spumux places them, and the title written
|
|
192
195
|
from that stream (4:3, and 16:9 with and without pan-scan or letterbox) is
|
|
193
|
-
dvdauthor's; a title with buttons over the whole of it
|
|
194
|
-
VOB byte for byte
|
|
196
|
+
dvdauthor's; a title with buttons over the whole of it (one of them of
|
|
197
|
+
several commands) is dvdauthor's VOB and IFO byte for byte, but for the
|
|
198
|
+
palette. A VIDEO_TS written by vtskit alone plays
|
|
195
199
|
its titles and chapters in order under libdvdnav, its commands jumping
|
|
196
200
|
between titles, its menus' buttons lead where they say, and its jumps into
|
|
197
201
|
another titleset's chapters land; a title with an angle block plays and
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|