Changes of Revision 6
tovid.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Sat Mar 14 15:34:58 UTC 2015 - aloisio@gmx.com
4
+
5
+- Update to 0.35
6
+ * full changelog at http://tovid.wikia.com/wiki/Tovid_changelog
7
+- Fixed build for 13.2 and newer
8
+
9
+-------------------------------------------------------------------
10
Fri Dec 26 15:40:08 UTC 2014 - obs@botter.cc
11
12
- Require /usr/bin/mkisofs instead of just mkisofs [PM-118]
13
tovid.spec
Changed
44
1
2
3
Summary: Video conversion and DVD authoring tools
4
Name: tovid
5
-Version: 0.34
6
+Version: 0.35
7
Release: 0.pm.1
8
Group: Productivity/Multimedia/Video/Editors and Convertors
9
-License: GNU General Public License version 2 or later (GPLv2 or later)
10
+License: GPL-2.0+
11
Url: http://tovid.sourceforge.net/
12
# http://tovid.googlecode.com/files/tovid-%{version}.tar.gz
13
-Source: tovid-%{version}.tar.bz2
14
+Source: tovid-%{version}.tar.gz
15
Source90: %{name}-rpmlintrc
16
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
17
%if %suse_version > 1110
18
19
%endif
20
Requires: python-cairo
21
Requires: python-imaging
22
-Requires: python-wxGTK
23
+%if 0%{?suse_version} >= 1320
24
+Requires: python-wxGTK >= 3.0
25
+%else
26
+Requires: python-wxGTK < 3.0
27
+%endif
28
Requires: sox
29
Requires: transcode
30
Requires: vcdimager
31
32
BuildRequires: normalize
33
BuildRequires: python-cairo
34
BuildRequires: python-imaging
35
-BuildRequires: python-wxGTK
36
+%if 0%{?suse_version} >= 1320
37
+BuildRequires: python-wxGTK >= 3.0
38
+%else
39
+BuildRequires: python-wxGTK < 3.0
40
+%endif
41
BuildRequires: sox
42
BuildRequires: transcode
43
BuildRequires: vcdimager
44
tovid-0.34.tar.bz2/libtovid/author.py
Deleted
265
1
2
-"""This module is for authoring a DVD or (S)VCD using dvdauthor or vcdimager.
3
-"""
4
-
5
-__all__ = [
6
- 'Disc',
7
- 'Menu',
8
- 'Video',
9
- 'Group',
10
- 'Titleset',
11
- 'vcdimager_xml',
12
- 'dvdauthor_xml',
13
-]
14
-
15
-from libtovid import xml
16
-
17
-
18
-###
19
-### Supporting classes
20
-###
21
-
22
-class Video:
23
- """A video title for inclusion on a video disc.
24
- """
25
- def __init__(self, filename, title=''):
26
- self.filename = filename
27
- self.title = title
28
- self.chapters = []
29
-
30
-
31
-class Group:
32
- """A group title for inclusion on a video disc.
33
- """
34
- def __init__(self, filenames, title):
35
- self.filenames = filenames
36
- self.title = title
37
-
38
-
39
-class Menu:
40
- """A menu for navigating the titles on a video disc.
41
- """
42
- def __init__(self, filename='', videos=None):
43
- """Create a menu linking to the given `Video`\s."""
44
- self.filename = filename
45
- self.videos = videos or []
46
-
47
- def add(self, video):
48
- """Add a `Video` to the Menu."""
49
- self.videos.append(video)
50
-
51
-
52
-class Titleset:
53
- """A group of `Video`\s, with an optional `Menu`.
54
- """
55
- def __init__(self, menu=None, videos=None):
56
- """Create a Titleset containing the given `Video`\s.
57
- """
58
- self.menu = menu
59
- self.videos = videos or []
60
-
61
- def add(self, video):
62
- """Add a `Video` to the Titleset."""
63
- self.videos.append(video)
64
-
65
-
66
-class Disc:
67
- """A video disc containing one or more `Titleset`\s, and an optional
68
- top `Menu` for navigating to each Titleset.
69
-
70
- """
71
- def __init__(self, name='Untitled', format='dvd', tvsys='ntsc',
72
- titlesets=None):
73
- """Create a Disc with the given properties.
74
-
75
- format
76
- 'vcd', 'svcd', or 'dvd'
77
- tvsys
78
- 'pal' or 'ntsc'
79
- title
80
- String containing the title of the disc
81
- titlesets
82
- List of `Titleset` objects
83
- """
84
- self.name = name
85
- self.format = format
86
- self.tvsys = tvsys
87
- self.topmenu = None
88
- self.titlesets = titlesets or []
89
-
90
-
91
-
92
-###
93
-### Internal functions
94
-###
95
-
96
-def _add_titleset(titleset, ts_id, segment_items, sequence_items, pbc):
97
- """Add titleset content to a vcdimager XML structure. This function is
98
- used internally, mainly to keep `vcdimager_xml` from being too long.
99
- """
100
- menu = titleset.menu
101
- videos = titleset.videos
102
- # Add menu
103
- if menu:
104
- segment_items.add('segment-item', src=menu.filename,
105
- id='seg-menu-%d' % ts_id)
106
- # Add menu to pbc
107
- selection = pbc.add('selection', id='select-menu-%d' % ts_id)
108
- selection.add('bsn', '1')
109
- # Link back to topmenu (not sure what'll happen if there isn't one...)
110
- selection.add('return', ref='select-topmenu')
111
- selection.add('loop', '0', jump_timing='immediate')
112
- selection.add('play-item', ref='seg-menu-%d' % ts_id)
113
- # Navigational links to titleset videos
114
- for video_id in range(len(videos)):
115
- selection.add('select',
116
- ref='play-title-%d-%d' % (ts_id, video_id))
117
- # Add videos
118
- for video_id, video in enumerate(videos):
119
- # Add sequence items
120
- sequence_item = sequence_items.add('sequence-item')
121
- sequence_item.set(id='seq-title-%d-%d' % (ts_id, video_id),
122
- src=video.filename)
123
- # Add chapter entries
124
- for chapterid, chapter in enumerate(video.chapters):
125
- sequence_item.add('entry', chapter, id='chapter-%d' % chapterid)
126
- # Add playlists to pbc
127
- playlist = pbc.add('playlist')
128
- playlist.set(id='play-title-%d-%d' % (ts_id, video_id))
129
- # Add prev/next links if appropriate
130
- if 0 <= video_id < len(videos):
131
- if 0 < video_id:
132
- playlist.add('prev',
133
- ref='play-title-%d-%d' % (ts_id, video_id-1))
134
- if video_id < len(videos) - 1:
135
- playlist.add('next',
136
- ref='play-title-%d-%d' % (ts_id, video_id+1))
137
- # Add a return link to the menu, if there is one
138
- if menu:
139
- playlist.add('return', ref='select-menu-%d' % ts_id)
140
- playlist.add('wait', '0')
141
- playlist.add('play-item', ref='seq-title-%d-%d' % (ts_id, video_id))
142
-
143
-
144
-###
145
-### Exported functions
146
-###
147
-
148
-def vcdimager_xml(disc):
149
- """Return the vcdimager XML string for the given `Disc`.
150
- """
151
- assert isinstance(disc, Disc)
152
- # XML header (will be added later)
153
- header = '<?xml version="1.0"?>\n'
154
- header += '<!DOCTYPE videocd PUBLIC "-//GNU/DTD VideoCD//EN"\n'
155
- header += ' "http://www.gnu.org/software/vcdimager/videocd.dtd">\n'
156
- # Root videocd element
157
- attributes = {
158
- 'xmlns': 'http://www.gnu.org/software/vcdimager/1.0/',
159
- 'class': disc.format}
160
- if disc.format == 'vcd':
161
- attributes['version'] = '2.0'
162
- else: # SVCD
163
- attributes['version'] = '1.0'
164
- root = xml.Element('videocd')
165
- root.set(**attributes)
166
- # Add info block
167
- info = root.add('info')
168
- info.add('album-id', 'VIDEO_DISC')
169
- info.add('volume-count', '1')
170
- info.add('volume-number', '1')
171
- info.add('restriction', '0')
172
- # Add pvd block
173
- pvd = root.add('pvd')
174
- pvd.add('volume-id', 'VIDEO_DISC')
175
- pvd.add('system-id', 'CD-RTOS CD-BRIDGE')
176
-
177
- # Add segment, sequence, and pbc
178
- segment_items = root.add('segment-items')
179
- sequence_items = root.add('sequence-items')
180
- pbc = root.add('pbc')
181
- # Add topmenu
182
- if disc.topmenu:
183
- segment_items.add('segment-item', src=disc.topmenu.filename,
184
- id='seg-topmenu')
185
- selection = pbc.add('selection', id='select-topmenu')
186
- selection.add('bsn', '1')
187
- selection.add('loop', '0', jump_timing='immediate')
188
- selection.add('play-item', ref='seg-topmenu')
189
- # Add titlesets
190
- for ts_id, titleset in enumerate(disc.titlesets):
191
- _add_titleset(titleset, ts_id, segment_items, sequence_items, pbc)
192
- # If we're doing a topmenu, add a link to the titleset menu
193
- if disc.topmenu:
194
- selection.add('select', ref='select-menu-%d' % ts_id)
195
-
196
- # Return XML with header prepended
197
- return header + str(root) + '\n'
198
-
199
-
200
-def dvdauthor_xml(disc):
201
- """Return the dvdauthor XML string for the given `Disc`.
202
- """
203
- assert isinstance(disc, Disc)
204
- # Root dvdauthor element
205
- root = xml.Element('dvdauthor', dest=disc.name.replace(' ', '_'))
206
- vmgm = root.add('vmgm')
207
- # Add topmenu if present
208
- if disc.topmenu:
209
- menus = vmgm.add('menus')
210
- menus.add('video')
211
- pgc = menus.add('pgc', entry='title')
212
- vob = pgc.add('vob', file=disc.topmenu.filename)
213
- for index, titleset in enumerate(disc.titlesets):
214
- if titleset.menu:
215
- pgc.add('button', 'jump titleset %d menu;' % (index + 1))
216
- else:
217
- pgc.add('button', 'jump titleset %d;' % (index + 1))
218
- # Add each titleset
219
- for titleset in disc.titlesets:
220
- menu = titleset.menu
221
- ts = root.add('titleset')
222
- # Add menu if present
223
- if menu:
224
- menus = ts.add('menus')
225
- menus.add('video')
226
- pgc = menus.add('pgc', entry='root')
227
- vob = pgc.add('vob', file=menu.filename)
228
- for index, video in enumerate(titleset.videos):
229
- pgc.add('button', 'jump title %d;' % (index + 1))
230
- if disc.topmenu:
231
- pgc.add('button', 'jump vmgm menu;')
232
- titles = ts.add('titles')
233
- # Add a pgc for each video
234
- for video in titleset.videos:
235
- pgc = titles.add('pgc')
236
- vob = pgc.add('vob', file=video.filename)
237
- if video.chapters:
238
- vob.set(chapters=','.join(video.chapters))
239
- pgc.add('post', 'call menu;')
240
- # Return XML string
241
- return str(root) + '\n'
242
-
243
-
244
-if __name__ == '__main__':
245
- menu1 = Menu('menu1.mpg')
246
- videos1 = [
247
- Video('video1.mpg'),
248
- Video('video2.mpg'),
249
- Video('video3.mpg')]
250
- menu2 = Menu('menu2.mpg')
251
- videos2 = [
252
- Video('video4.mpg'),
253
- Video('video5.mpg'),
254
- Video('video6.mpg')]
255
- titlesets = [
256
- Titleset(menu1, videos1),
257
- Titleset(menu2, videos2)]
258
- disc = Disc('dvd_test', 'dvd', 'ntsc', titlesets)
259
-
260
- print("dvdauthor XML example:")
261
- print(dvdauthor_xml(disc))
262
-
263
- print("vcdimager XML example:")
264
- print(vcdimager_xml(disc))
265
tovid-0.34.tar.bz2/libtovid/backend
Deleted
2
1
-(directory)
2
tovid-0.34.tar.bz2/libtovid/backend/__init__.py
Deleted
9
1
2
-"""Backends, which do some task using a command-line program.
3
-
4
-This module is split into submodules, each named after the command-line
5
-program they predominantly rely on. Backends which use several of these
6
-submodules may be defined here in ``__init__.py``.
7
-"""
8
-
9
tovid-0.34.tar.bz2/libtovid/backend/ffmpeg.py
Deleted
181
1
2
-"""Video encoding and identification using ``ffmpeg``.
3
-"""
4
-
5
-__all__ = [
6
- 'encode',
7
- 'encode_audio',
8
- 'identify',
9
-]
10
-
11
-import re
12
-from libtovid import log
13
-from libtovid import cli
14
-
15
-def encode(source, target, **kw):
16
- """Encode a multimedia video using ffmpeg.
17
-
18
- source
19
- Input `~libtovid.media.MediaFile`
20
- target
21
- Output `~libtovid.media.MediaFile`
22
- kw
23
- Keyword arguments to customize encoding behavior
24
-
25
- Supported keywords:
26
-
27
- quant
28
- Minimum quantization, from 1-31 (1 being fewest artifacts)
29
- vbitrate
30
- Maximum video bitrate, in kilobits per second.
31
- abitrate
32
- Audio bitrate, in kilobits per second
33
- interlace
34
- 'top' or 'bottom', to do interlaced encoding with
35
- top or bottom field first
36
-
37
- For example::
38
-
39
- ffmpeg_encode(source, target, quant=4, vbitrate=7000)
40
- """
41
- cmd = cli.Command('ffmpeg', '-y', '-i', source.filename)
42
-
43
- # Use format/tvsys that ffmpeg knows about
44
- if target.format in ['vcd', 'svcd', 'dvd']:
45
- cmd.add('-tvstd', target.tvsys,
46
- '-target', '%s-%s' % (target.tvsys, target.format))
47
-
48
- # Interpret keyword arguments
49
- if 'quant' in kw:
50
- cmd.add('-qmin', kw['quant'], '-qmax', 31)
51
- if 'vbitrate' in kw:
52
- cmd.add('-b', '%dk' % kw['vbitrate'])
53
- if 'abitrate' in kw:
54
- cmd.add('-ab', '%dk' % kw['abitrate'])
55
- if 'interlace' in kw:
56
- if kw['interlace'] == 'bottom':
57
- cmd.add('-top', 0, '-flags', '+alt+ildct+ilme')
58
- elif kw['interlace'] == 'top':
59
- cmd.add('-top', 1, '-flags', '+alt+ildct+ilme')
60
-
61
- # Frame rate and audio sampling rate
62
- cmd.add('-r', target.fps,
63
- '-ar', target.samprate)
64
-
65
- # Convert scale/expand to ffmpeg's padding system
66
- if target.scale:
67
- cmd.add('-s', '%sx%s' % target.scale)
68
- # Letterbox if necessary
69
- if target.expand != target.scale:
70
- e_width, e_height = target.expand
71
- s_width, s_height = target.scale
72
- h_pad = (e_width - s_width) / 2
73
- v_pad = (e_height - s_height) / 2
74
- if h_pad > 0:
75
- cmd.add('-padleft', h_pad, '-padright', h_pad)
76
- if v_pad > 0:
77
- cmd.add('-padtop', v_pad, '-padbottom', v_pad)
78
-
79
- # Aspect
80
- if target.widescreen:
81
- cmd.add('-aspect', '16:9')
82
- else:
83
- cmd.add('-aspect', '4:3')
84
-
85
- cmd.add(target.filename)
86
- cmd.run()
87
-
88
-
89
-def encode_audio(source, audiofile, target):
90
- """Encode the audio stream in a source file to a target format, saving
91
- to the given filename.
92
-
93
- source
94
- Input `~libtovid.media.MediaFile`
95
- audiofile
96
- Filename for encoded audio
97
- target
98
- Output `~libtovid.media.MediaFile`
99
-
100
- If no audio is present in the source file, encode silence.
101
- """
102
- cmd = cli.Command('ffmpeg')
103
-
104
- # If source has audio, encode it
105
- if source.has_audio:
106
- cmd.add('-i', source.filename)
107
- # Otherwise, encode silence (minimum 4 seconds)
108
- else:
109
- cmd.add('-f', 's16le', '-i', '/dev/zero')
110
- if source.length < 4:
111
- cmd.add('-t', '4.0')
112
- else:
113
- cmd.add('-t', '%f' % source.length)
114
-
115
- cmd.add('-vn', '-ac', '2', '-ab', '224k')
116
- cmd.add('-ar', target.samprate)
117
- cmd.add('-acodec', target.acodec)
118
- cmd.add('-y', audiofile)
119
-
120
- cmd.run()
121
-
122
-
123
-from libtovid.media import MediaFile
124
-
125
-def identify(filename):
126
- """Identify a video file using ffmpeg, and return a
127
- `~libtovid.media.MediaFile` with the video's specifications.
128
- """
129
- result = MediaFile(filename)
130
-
131
- cmd = cli.Command('ffmpeg', '-i', filename)
132
- cmd.run(capture=True)
133
-
134
- # ffmpeg puts its output on stderr
135
- output = cmd.get_errors()
136
-
137
- video_line = re.compile(''
138
- 'Stream (?P<tracknum>[^:]+): Video: ' # Track number (ex. #0.0)
139
- '(?P<vcodec>[^,]+), ' # Video codec (ex. mpeg4)
140
- '(?P<colorspace>[^,]+), ' # Color space (ex. yuv420p)
141
- '(?P<width>\d+)x(?P<height>\d+), ' # Resolution (ex. 720x480)
142
- '((?P<vbitrate>\d+) kb/s, )?' # Video bitrate (ex. 8000 kb/s)
143
- '(?P<fps>[\d.]+)') # FPS (ex. 29.97 fps(r))
144
-
145
- audio_line = re.compile(''
146
- 'Stream (?P<tracknum>[^:]+): Audio: ' # Track number (ex. #0.1)
147
- '(?P<acodec>[^,]+), ' # Audio codec (ex. mp3)
148
- '(?P<samprate>\d+) Hz, ' # Sampling rate (ex. 44100 Hz)
149
- '(?P<channels>[^,]+), ' # Channels (ex. stereo)
150
- '(?P<abitrate>\d+) kb/s') # Audio bitrate (ex. 128 kb/s)
151
-
152
- # Parse ffmpeg output and set MediaFile attributes
153
- for line in output.split('\n'):
154
- video_match = video_line.search(line)
155
- audio_match = audio_line.search(line)
156
-
157
- if video_match:
158
- m = video_match
159
- result.vcodec = m.group('vcodec')
160
- result.scale = (int(m.group('width')),
161
- int(m.group('height')))
162
- result.expand = result.scale
163
- result.fps = float(m.group('fps'))
164
- if m.group('vbitrate'):
165
- result.vbitrate = int(m.group('vbitrate'))
166
-
167
- elif audio_match:
168
- m = audio_match
169
- result.acodec = m.group('acodec')
170
- result.samprate = int(m.group('samprate'))
171
- result.abitrate = int(m.group('abitrate'))
172
- if m.group('channels') == '5.1':
173
- result.channels = 6
174
- elif m.group('channels') == 'stereo':
175
- result.channels = 2
176
- else:
177
- result.channels = 1
178
-
179
- return result
180
-
181
tovid-0.34.tar.bz2/libtovid/backend/mpeg2enc.py
Deleted
222
1
2
-"""Video and frame encoding using ``mpeg2enc``.
3
-"""
4
-
5
-__all__ = [
6
- 'encode',
7
- 'encode_video',
8
- 'encode_frames',
9
-]
10
-
11
-# TODO: Filter out some of the inter-backend dependencies
12
-
13
-import os, glob
14
-from libtovid import log
15
-from libtovid import util
16
-from libtovid import cli
17
-from libtovid.backend import mplex, mplayer, ffmpeg
18
-
19
-def encode(source, target, **kw):
20
- """Encode a multimedia video using mplayer|yuvfps|mpeg2enc.
21
-
22
- source
23
- Input `~libtovid.media.MediaFile`
24
- target
25
- Output `~libtovid.media.MediaFile`
26
- kw
27
- Keyword arguments to customize encoding behavior
28
-
29
- Supported keywords:
30
-
31
- None yet
32
-
33
- """
34
- log.warning("This encoder is very experimental, and may not work.")
35
-
36
- outname = target.filename
37
- # YUV raw video FIFO, for piping video from mplayer to mpeg2enc
38
- yuvfile = '%s.yuv' % outname
39
- if os.path.exists(yuvfile):
40
- os.remove(yuvfile)
41
-
42
- # Filenames for intermediate streams (ac3/m2v etc.)
43
- # Appropriate suffix for audio stream
44
- if target.format in ['vcd', 'svcd']:
45
- audiofile = '%s.mp2' % outname
46
- else:
47
- audiofile = '%s.ac3' % outname
48
- # Appropriate suffix for video stream
49
- if target.format == 'vcd':
50
- videofile = '%s.m1v' % outname
51
- else:
52
- videofile = '%s.m2v' % outname
53
- # Do audio
54
- ffmpeg.encode_audio(source, audiofile, target)
55
- # Do video
56
- mplayer.rip_video(source, yuvfile, target)
57
- encode_video(source, yuvfile, videofile, target)
58
- # Combine audio and video
59
- mplex.mux(videofile, audiofile, target)
60
-
61
-
62
-
63
-def encode_video(source, yuvfile, videofile, target):
64
- """Encode a yuv4mpeg stream to an MPEG video stream.
65
-
66
- source
67
- Input `~libtovid.media.MediaFile`
68
- yuvfile
69
- Filename of .yuv stream coming from mplayer
70
- videofile
71
- Filename of .m[1|2]v to write encoded video stream to
72
- target
73
- Output `~libtovid.media.MediaFile`
74
-
75
- """
76
- # TODO: Control over quality (bitrate/quantization) and disc split size,
77
- # corresp. to $VID_BITRATE, $MPEG2_QUALITY, $DISC_SIZE, etc.
78
- # Missing options (compared to tovid)
79
- # -S 700 -B 247 -b 2080 -v 0 -4 2 -2 1 -q 5 -H -o FILE
80
- pipe = cli.Pipe()
81
-
82
- # Feed the .yuv file into the pipeline
83
- cat = cli.Command('cat', yuvfile)
84
- pipe.add(cat)
85
-
86
- # Adjust framerate if necessary by piping through yuvfps
87
- if source.fps != target.fps:
88
- log.info("Adjusting framerate")
89
- yuvfps = cli.Command('yuvfps')
90
- yuvfps.add('-r', util.float_to_ratio(target.fps))
91
- pipe.add(yuvfps)
92
-
93
- # Encode the resulting .yuv stream by piping into mpeg2enc
94
- mpeg2enc = cli.Command('mpeg2enc')
95
- # TV system
96
- if target.tvsys == 'pal':
97
- mpeg2enc.add('-F', '3', '-n', 'p')
98
- elif target.tvsys == 'ntsc':
99
- mpeg2enc.add('-F', '4', '-n', 'n')
100
- # Format
101
- format = target.format
102
- if format == 'vcd':
103
- mpeg2enc.add('-f', '1')
104
- elif format == 'svcd':
105
- mpeg2enc.add('-f', '4')
106
- elif 'dvd' in format:
107
- mpeg2enc.add('-f', '8')
108
- # Aspect ratio
109
- if target.widescreen:
110
- mpeg2enc.add('-a', '3')
111
- else:
112
- mpeg2enc.add('-a', '2')
113
- mpeg2enc.add('-o', videofile)
114
- pipe.add(mpeg2enc)
115
-
116
- # Run the pipeline to encode the video stream
117
- pipe.run()
118
-
119
-
120
-# --------------------------------------------------------------------------
121
-#
122
-# Frame encoder
123
-#
124
-# --------------------------------------------------------------------------
125
-from libtovid import standard
126
-
127
-def encode_frames(imagedir, outfile, format, tvsys, aspect, interlaced=False):
128
- """Convert an image sequence in the given directory to match a target
129
- `~libtovid.media.MediaFile`, putting the output stream in outfile.
130
-
131
- imagedir
132
- Directory containing images (and only images)
133
- outfile
134
- Filename for output.
135
- tvsys
136
- TVsys desired for output (to deal with FPS)
137
- aspect
138
- Aspect ratio ('4:3', '16:9')
139
- interlaced
140
- Frames are interlaced material
141
-
142
- Currently supports JPG and PNG images; input images must already be
143
- at the desired target resolution.
144
- """
145
-
146
- # Use absolute path name
147
- imagedir = os.path.abspath(imagedir)
148
- print("Creating video stream from image sequence in %s" % imagedir)
149
- # Determine image type
150
- images = glob.glob("%s/*" % imagedir)
151
- extension = images[0][-3:]
152
- if extension not in ['jpg', 'png']:
153
- raise ValueError("Image format '%s' isn't currently supported to "
154
- "render video from still frames" % extension)
155
- # Make sure remaining image files have the same extension
156
- for img in images:
157
- if not img.endswith(extension):
158
- raise ValueError("%s does not have a .%s extension" %
159
- (img, extension))
160
-
161
- pipe = cli.Pipe()
162
-
163
- # Use jpeg2yuv/png2yuv to stream images
164
- if extension == 'jpg':
165
- jpeg2yuv = cli.Command('jpeg2yuv')
166
-
167
- jpeg2yuv.add('-Ip') # Progressive
168
-
169
- jpeg2yuv.add('-f', '%.3f' % standard.fps(tvsys),
170
- '-j', '%s/%%08d.%s' % (imagedir, extension))
171
- pipe.add(jpeg2yuv)
172
- elif extension == 'png':
173
- #ls = cli.Command('sh', '-c', 'ls %s/*.png' % imagedir)
174
- #xargs = cli.Command('xargs', '-n1', 'pngtopnm')
175
- png2yuv = cli.Command('png2yuv')
176
-
177
- png2yuv.add('-Ip') # Progressive
178
-
179
-
180
- png2yuv.add('-f', '%.3f' % standard.fps(tvsys),
181
- '-j', '%s/%%08d.png' % (imagedir))
182
-
183
- pipe.add(png2yuv)
184
-
185
- #pipe.add(ls, xargs, png2yuv)
186
- #cmd += 'pnmtoy4m -Ip -F %s %s/*.png' % standard.fps_ratio(tvsys)
187
-
188
- # TODO: Scale to correct target size using yuvscaler or similar
189
-
190
- # Pipe image stream into mpeg2enc to encode
191
- mpeg2enc = cli.Command('mpeg2enc')
192
-
193
- # Anyways.
194
- mpeg2enc.add('-I 0') # Progressive
195
-
196
- # Bottom-first, determined in render/drawing.py::interlace_drawings()
197
- if (interlaced):
198
- mpeg2enc.add('--playback-field-order', 'b') # Bottom-first field order
199
- # conforming to drawing.py::interlace_drawings()
200
-
201
- mpeg2enc.add('-v', '0',
202
- '-q' '3',
203
- '-o' '%s' % outfile)
204
- # Format
205
- if format == 'vcd':
206
- mpeg2enc.add('--format', '1')
207
- elif format == 'svcd':
208
- mpeg2enc.add('--format', '4')
209
- else:
210
- mpeg2enc.add('--format', '8')
211
- # Aspect ratio
212
- if aspect == '16:9':
213
- mpeg2enc.add('-a', '3')
214
- elif aspect == '4:3':
215
- mpeg2enc.add('-a', '2')
216
-
217
- pipe.add(mpeg2enc)
218
-
219
- pipe.run(capture=True)
220
- pipe.get_output() # and wait :)
221
-
222
tovid-0.34.tar.bz2/libtovid/backend/mplayer.py
Deleted
213
1
2
-"""Video encoding, ripping, and identification using ``mplayer``.
3
-"""
4
-
5
-__all__ = [
6
- 'encode',
7
- 'identify',
8
- 'rip_video',
9
-]
10
-
11
-from libtovid import log
12
-from libtovid import cli
13
-from libtovid.media import MediaFile
14
-from libtovid.backend import ffmpeg
15
-
16
-def encode(source, target, **kw):
17
- """Encode a multimedia video using mencoder.
18
-
19
- source
20
- Input `~libtovid.media.MediaFile`
21
- target
22
- Output `~libtovid.media.MediaFile`
23
- kw
24
- Keyword arguments to customize encoding behavior
25
-
26
- Supported keywords:
27
-
28
- None yet
29
-
30
- """
31
- cmd = cli.Command('mencoder')
32
- cmd.add(source.filename,
33
- '-o', target.filename,
34
- '-oac', 'lavc',
35
- '-ovc', 'lavc',
36
- '-of', 'mpeg')
37
- # Format
38
- cmd.add('-mpegopts')
39
- if target.format in ['vcd', 'svcd']:
40
- cmd.add('format=x%s' % target.format)
41
- else:
42
- cmd.add('format=dvd')
43
-
44
- # FIXME: This assumes we only have ONE audio track.
45
- if source.has_audio:
46
- # Adjust audio sampling rate if necessary
47
- if source.samprate != target.samprate:
48
- log.info("Resampling needed to achieve %d Hz" % target.samprate)
49
- cmd.add('-srate', target.samprate)
50
- cmd.add('-af', 'lavcresample=%s' % target.samprate)
51
- else:
52
- log.info("No resampling needed, already at %d Hz" % target.samprate)
53
-
54
- else:
55
- log.info("No audio file, generating silence of %f seconds." % \
56
- source.length)
57
- # Generate silence.
58
- if target.format in ['vcd', 'svcd']:
59
- audiofile = '%s.mpa' % target.filename
60
- else:
61
- audiofile = '%s.ac3' % target.filename
62
- ffmpeg.encode_audio(source, audiofile, target)
63
- # TODO: make this work, it's still not adding the ac3 file correctly.
64
- cmd.add('-audiofile', audiofile)
65
-
66
- # Video codec
67
- if target.format == 'vcd':
68
- lavcopts = 'vcodec=mpeg1video'
69
- else:
70
- lavcopts = 'vcodec=mpeg2video'
71
- # Audio codec
72
- lavcopts += ':acodec=%s' % target.acodec
73
- lavcopts += ':abitrate=%s:vbitrate=%s' % \
74
- (target.abitrate, target.vbitrate)
75
- # Maximum video bitrate
76
- lavcopts += ':vrc_maxrate=%s' % target.vbitrate
77
- if target.format == 'vcd':
78
- lavcopts += ':vrc_buf_size=327'
79
- elif target.format == 'svcd':
80
- lavcopts += ':vrc_buf_size=917'
81
- else:
82
- lavcopts += ':vrc_buf_size=1835'
83
- # Set appropriate target aspect
84
- if target.widescreen:
85
- lavcopts += ':aspect=16/9'
86
- else:
87
- lavcopts += ':aspect=4/3'
88
- # Pass all lavcopts together
89
- cmd.add('-lavcopts', lavcopts)
90
-
91
- # FPS
92
- if target.tvsys == 'pal':
93
- cmd.add('-ofps', '25/1')
94
- elif target.tvsys == 'ntsc':
95
- cmd.add('-ofps', '30000/1001') # ~= 29.97
96
-
97
- # Scale/expand to fit target frame
98
- if target.scale:
99
- vfilter = 'scale=%s:%s' % target.scale
100
- # Expand is not done unless also scaling
101
- if target.expand != target.scale:
102
- vfilter += ',expand=%s:%s' % target.expand
103
- cmd.add('-vf', vfilter)
104
-
105
- cmd.run()
106
-
107
-
108
-def identify(filename):
109
- """Identify a video file using mplayer, and return a
110
- `~libtovid.media.MediaFile` with the video's specifications.
111
- """
112
- # TODO: Raise an exception if the file couldn't be identified
113
- # TODO: Infer aspect ratio
114
-
115
- media = MediaFile(filename)
116
-
117
- mp_dict = {}
118
- # Use mplayer
119
- cmd = cli.Command('mplayer',
120
- '-identify',
121
- '%s' % filename,
122
- '-vo', 'null',
123
- '-ao', 'null',
124
- '-frames', '1',
125
- '-channels', '6')
126
- cmd.run(capture=True)
127
-
128
- # Look for mplayer's "ID_..." lines and include each assignment in mp_dict
129
- for line in cmd.get_output().splitlines():
130
- log.debug(line)
131
- if line.startswith("ID_"):
132
- left, right = line.split('=')
133
- mp_dict[left] = right.strip()
134
-
135
- # Check for existence of streams
136
- if 'ID_VIDEO_ID' in mp_dict:
137
- media.has_video = True
138
- else:
139
- media.has_video = False
140
- if 'ID_AUDIO_ID' in mp_dict:
141
- media.has_audio = True
142
- else:
143
- media.has_audio = False
144
-
145
- # Parse the dictionary and set appropriate values
146
- for left, right in mp_dict.iteritems():
147
- if left == "ID_VIDEO_WIDTH":
148
- media.scale = (int(right), media.scale[1])
149
- elif left == "ID_VIDEO_HEIGHT":
150
- media.scale = (media.scale[0], int(right))
151
- elif left == "ID_VIDEO_FPS":
152
- media.fps = float(right)
153
- elif left == "ID_VIDEO_FORMAT":
154
- media.vcodec = right
155
- elif left == "ID_VIDEO_BITRATE":
156
- media.vbitrate = int(right) / 1000
157
- elif left == "ID_AUDIO_CODEC":
158
- media.acodec = right
159
- elif left == "ID_AUDIO_FORMAT":
160
- pass
161
- elif left == "ID_AUDIO_BITRATE":
162
- media.abitrate = int(right) / 1000
163
- elif left == "ID_AUDIO_RATE":
164
- media.samprate = int(right)
165
- elif left == "ID_AUDIO_NCH":
166
- media.channels = right
167
- elif left == 'ID_LENGTH':
168
- media.length = float(right)
169
- media.expand = media.scale
170
-
171
- # Fix mplayer's audio codec naming for ac3 and mp2
172
- if media.acodec == "8192":
173
- media.acodec = "ac3"
174
- elif media.acodec == "80":
175
- media.acodec = "mp2"
176
- # Fix mplayer's video codec naming for mpeg1 and mpeg2
177
- if media.vcodec == "0x10000001":
178
- media.vcodec = "mpeg1"
179
- elif media.vcodec == "0x10000002":
180
- media.vcodec = "mpeg2"
181
- return media
182
-
183
-
184
-
185
-
186
-def rip_video(source, yuvfile, target):
187
- """Rip video to the given yuv4mpeg file.
188
-
189
- source
190
- Input `~libtovid.media.MediaFile`
191
- yuvfile
192
- File to put ripped video in
193
- target
194
- Output `~libtovid.media.MediaFile`
195
-
196
- """
197
- # TODO: Custom mplayer options, subtitles, interlacing,
198
- # corresp. to $MPLAYER_OPT, $SUBTITLES, $VF_PRE/POST, $YUV4MPEG_ILACE,
199
- # etc.
200
- cmd = cli.Command('mplayer')
201
- cmd.add(source.filename)
202
- cmd.add('-vo', 'yuv4mpeg:file=%s' % yuvfile)
203
- cmd.add('-nosound', '-benchmark', '-noframedrop')
204
- # TODO: Support subtitles. For now, use default tovid behavior.
205
- cmd.add('-noautosub')
206
- if target.scale:
207
- cmd.add('-vf', 'scale=%s:%s' % target.scale)
208
- if target.expand > target.scale:
209
- cmd.add('-vf-add', 'expand=%s:%s' % target.expand)
210
- # Run the command to rip the video
211
- cmd.run(background=True)
212
-
213
tovid-0.34.tar.bz2/libtovid/backend/mplex.py
Deleted
40
1
2
-"""Multiplexing using ``mplex``.
3
-"""
4
-
5
-__all__ = [
6
- 'mux',
7
-]
8
-
9
-from libtovid import cli
10
-
11
-def mux(vstream, astream, target):
12
- """Multiplex audio and video stream files to the given target.
13
-
14
- vstream
15
- Filename of MPEG video stream
16
- astream
17
- Filename of MP2/AC3 audio stream
18
- target
19
- Profile of output file
20
-
21
- """
22
- cmd = cli.Command('mplex')
23
- format = target.format
24
- if format == 'vcd':
25
- cmd.add('-f', '1')
26
- elif format == 'dvd-vcd':
27
- cmd.add('-V', '-f', '8')
28
- elif format == 'svcd':
29
- cmd.add('-V', '-f', '4', '-b', '230')
30
- elif format == 'half-dvd':
31
- cmd.add('-V', '-f', '8', '-b', '300')
32
- elif format == 'dvd':
33
- cmd.add('-V', '-f', '8', '-b', '400')
34
- # elif format == 'kvcd':
35
- # cmd += ' -V -f 5 -b 350 -r 10800 '
36
- cmd.add(vstream, astream, '-o', target.filename)
37
- # Run the command to multiplex the streams
38
- cmd.run()
39
-
40
tovid-0.34.tar.bz2/libtovid/backend/spumux.py
Deleted
182
1
2
-"""This module is for adding subtitles to MPEG video files using spumux.
3
-
4
-Defined here are two functions for adding subtitles to an MPEG file:
5
-
6
- `add_subpictures`
7
- Add image files (``.png``)
8
- `add_subtitles`
9
- Add subtitle files (``.sub``, ``.srt`` etc.)
10
-
11
-Use these if you just want to add subpictures or subtitles, and don't want
12
-to think much about the XML internals.
13
-"""
14
-
15
-__all__ = [
16
- 'add_subpictures',
17
- 'add_subtitles',
18
-]
19
-
20
-import os
21
-from libtovid import util
22
-from libtovid import xml
23
-from libtovid import cli
24
-from libtovid.backend import mplayer
25
-
26
-# spumux XML elements and valid attributes
27
-#
28
-# subpictures
29
-# stream
30
-# textsub
31
-# ['filename',
32
-# 'characterset',
33
-# 'fontsize',
34
-# 'font',
35
-# 'horizontal-alignment',
36
-# 'vertical-alignment',
37
-# 'left-margin',
38
-# 'right-margin',
39
-# 'subtitle-fps',
40
-# 'movie-fps',
41
-# 'movie-width',
42
-# 'movie-height']
43
-# button
44
-# ['name',
45
-# 'x0', 'y0', # Upper-left corner, inclusively
46
-# 'x1', 'y1', # Lower-right corner, exclusively
47
-# 'up', 'down', 'left', 'right']
48
-# action
49
-# ['name']
50
-# spu
51
-# ['start',
52
-# 'end',
53
-# 'image',
54
-# 'highlight',
55
-# 'select',
56
-# 'transparent', # color code
57
-# 'force', # 'yes' (force display, required for menus)
58
-# 'autooutline', # 'infer'
59
-# 'outlinewidth',
60
-# 'autoorder', # 'rows' or 'columns'
61
-# 'xoffset',
62
-# 'yoffset']
63
-
64
-def _get_xml(textsub_or_spu):
65
- """Return an XML string for the given Textsub or Spu element.
66
- """
67
- subpictures = xml.Element('subpictures')
68
- stream = subpictures.add('stream')
69
- stream.add_child(textsub_or_spu)
70
- return str(subpictures)
71
-
72
-
73
-def _get_xmlfile(textsub_or_spu):
74
- """Write spumux XML file for the given Textsub or Spu element, and
75
- return the written filename.
76
- """
77
- xmldata = _get_xml(textsub_or_spu)
78
- xmlfile = open(util.temp_file(suffix=".xml"), 'w')
79
- xmlfile.write(xmldata)
80
- xmlfile.close()
81
- return xmlfile.name
82
-
83
-
84
-def _mux_subs(subtitle, movie_filename, stream_id=0):
85
- """Run spumux to multiplex the given subtitle with an ``.mpg`` file.
86
-
87
- subtitle
88
- Textsub or Spu element
89
- movie_filename
90
- Name of an ``.mpg`` file to multiplex subtitle into
91
- stream_id
92
- Stream ID number to pass to spumux
93
- """
94
- # Create XML file for subtitle element
95
- xmlfile = _get_xmlfile(subtitle)
96
- # Create a temporary .mpg for the subtitled output
97
- #base_dir = os.path.dirname(movie_filename)
98
- subbed_filename = util.temp_file(suffix=".mpg")
99
- # spumux xmlfile < movie_filename > subbed_filename
100
- spumux = cli.Command('spumux', '-s%s' % stream_id, xmlfile.name)
101
- spumux.run_redir(movie_filename, subbed_filename)
102
- spumux.wait()
103
-
104
- # Remove old file
105
- os.remove(movie_filename)
106
- # Rename temporary file to new file
107
- os.rename(subbed_filename, movie_filename)
108
- # Remove the XML file
109
- os.remove(xmlfile.name)
110
-
111
-
112
-def add_subpictures(movie_filename, select, image=None, highlight=None):
113
- """Adds ``.png`` subpictures to an ``.mpg`` video file to create a DVD menu.
114
-
115
- select
116
- ``.png`` filename shown for the navigational selector or "cursor"
117
- image
118
- ``.png`` filename shown for non-selected regions
119
- highlight
120
- ``.png`` filename shown when "enter" is pressed
121
-
122
- All images must be indexed, 4-color, transparent, non-antialiased PNG.
123
- Button regions are auto-inferred.
124
- """
125
- spu = xml.Element('spu')
126
- spu.set(start='0',
127
- force='yes',
128
- select=select,
129
- image=image,
130
- highlight=highlight)
131
- # TODO Find a good default outlinewidth
132
- spu.set(autooutline='infer', outlinewidth='10')
133
- # TODO: Support explicit button regions
134
- _mux_subs(spu, movie_filename)
135
-
136
-
137
-def add_subtitles(movie_filename, sub_filenames):
138
- """Adds one or more subtitle files to an ``.mpg`` video file.
139
-
140
- movie_filename
141
- Name of ``.mpg`` file to add subtitles to
142
- sub_filenames
143
- Filename or list of filenames of subtitle
144
- files to include (``.sub``, ``.srt`` etc.)
145
-
146
- """
147
- infile = mplayer.identify(movie_filename)
148
- width, height = infile.scale
149
-
150
- # Convert sub_filenames to list if necessary
151
- if type(sub_filenames) == str:
152
- sub_filenames = [sub_filenames]
153
- # spumux each subtitle file with its own stream ID
154
- for stream_id, sub_filename in enumerate(sub_filenames):
155
- # <textsub attribute="value" .../>
156
- textsub = xml.Element('textsub')
157
- textsub.set(movie_fps=infile.fps,
158
- movie_width=width,
159
- movie_height=height,
160
- filename=sub_filename)
161
- _mux_subs(textsub, movie_filename, stream_id)
162
-
163
-
164
-
165
-if __name__ == '__main__':
166
- print("spumux XML examples")
167
-
168
- print("Subpicture example:")
169
- spu = xml.Element('spu')
170
- spu.add('button', name='but1', down='but2')
171
- spu.add('button', name='but2', up='but1')
172
- print(_get_xml(spu))
173
-
174
- print("Text subtitle example:")
175
- textsub = xml.Element('textsub')
176
- textsub.set(filename='foo.sub',
177
- fontsize=14.0,
178
- font="Luxi Mono")
179
- print(_get_xml(textsub))
180
-
181
-
182
tovid-0.34.tar.bz2/libtovid/backend/transcode.py
Deleted
121
1
2
-"""Video frame ripping and video identification using ``transcode``.
3
-"""
4
-
5
-# Sample output from tcprobe:
6
-#
7
-# [tcprobe] RIFF data, AVI video
8
-# [avilib] V: 24.000 fps, codec=DIVX, frames=15691, width=1024, height=576
9
-# [avilib] A: 48000 Hz, format=0x2000, bits=0, channels=5, bitrate=448 kbps,
10
-# [avilib] 10216 chunks, 36614144 bytes, CBR
11
-# [tcprobe] summary for Elephants_1024.avi, (*) = not default, 0 = not
12
-# detected
13
-# import frame size: -g 1024x576 [720x576] (*)
14
-# frame rate: -f 24.000 [25.000] frc=0 (*)
15
-# audio track: -a 0 [0] -e 48000,0,5 [48000,16,2] -n 0x2000 [0x2000] (*)
16
-# bitrate=448 kbps
17
-# length: 15691 frames, frame_time=41 msec, duration=0:10:53.790
18
-
19
-__all__ = [
20
- 'identify',
21
- 'rip_frames',
22
-]
23
-
24
-import os, re, glob
25
-from libtovid import log
26
-from libtovid import cli
27
-from libtovid.media import MediaFile
28
-
29
-def identify(filename):
30
- """Identify a video file using transcode (tcprobe), and return a
31
- `~libtovid.media.MediaFile` with the video's specifications.
32
- """
33
- result = MediaFile(filename)
34
-
35
- cmd = cli.Command('tcprobe', '-i', filename)
36
- cmd.run(capture=True)
37
- output = cmd.get_output()
38
-
39
- video_line = re.compile('V: '
40
- '(?P<fps>[\d.]+) fps, '
41
- 'codec=(?P<vcodec>[^,]+), '
42
- 'frames=\d+, '
43
- 'width=(?P<width>\d+), '
44
- 'height=(?P<height>\d+)')
45
-
46
- audio_line = re.compile('A: '
47
- '(?P<samprate>\d+) Hz, '
48
- 'format=(?P<acodec>[^,]+), '
49
- 'bits=\d+, '
50
- 'channels=(?P<channels>[^,]+), '
51
- 'bitrate=(?P<abitrate>\d+) kbps')
52
-
53
- for line in output.split('\n'):
54
- if 'V: ' in line:
55
- match = video_line.search(line)
56
- result.fps = float(match.group('fps'))
57
- result.vcodec = match.group('vcodec')
58
- result.scale = (int(match.group('width')),
59
- int(match.group('height')))
60
- result.expand = result.scale
61
-
62
- elif 'A: ' in line:
63
- match = audio_line.search(line)
64
- result.acodec = match.group('acodec')
65
- result.samprate = int(match.group('samprate'))
66
- result.abitrate = int(match.group('abitrate'))
67
- result.channels = int(match.group('channels'))
68
-
69
- return result
70
-
71
-
72
-def rip_frames(media, out_dir, frames='all', size=(0, 0)):
73
- """Extract frame images from a `~libtovid.media.MediaFile` and return a
74
- list of frame image files.
75
-
76
- media
77
- `~libtovid.media.MediaFile` to extract images from
78
- out_dir
79
- Directory where output images should be stored; images are saved
80
- in a subdirectory of ``out_dir`` named after the input filename
81
- frames
82
- Which frames to rip: ``'all'`` for all frames, ``15`` to rip frame
83
- 15; ``[30, 90]`` to rip frames 30 through 90, etc.
84
- size
85
- Resolution of frame images (default: original size), used
86
- for prescaling
87
-
88
- """
89
- out_dir = os.path.abspath(out_dir)
90
- if os.path.exists(out_dir):
91
- log.warning("Temp directory: %s already exists. Overwriting." % out_dir)
92
- os.system('rm -rf "%s"' % out_dir)
93
- os.mkdir(out_dir)
94
-
95
- # TODO: use tcdemux to generate a nav index, like:
96
- # tcdemux -f 29.970 -W -i "$FILE" > "$NAVFILE"
97
-
98
- # Use transcode to rip frames
99
- cmd = cli.Command('transcode',
100
- '-i', '%s' % media.filename)
101
- # Resize
102
- if size != (0, 0):
103
- cmd.add('-Z', '%sx%s' % size)
104
- # Encode selected frames
105
- if frames == 'all':
106
- # transcode does all by default
107
- pass
108
- elif isinstance(frames, int):
109
- # rip a single frame
110
- cmd.add('-c', '%s-%s' % (frames, frames))
111
- elif isinstance(frames, list):
112
- # rip a range of frames
113
- cmd.add('-c', '%s-%s' % (frames[0], frames[-1]))
114
- cmd.add('-y', 'jpg,null')
115
- cmd.add('-o', '%s/frame_' % out_dir)
116
- log.info("Creating image sequence from %s" % media.filename)
117
- cmd.run()
118
-
119
- # Return a list of ripped files
120
- return glob.glob('%s/frame_*.jpg' % out_dir)
121
tovid-0.34.tar.bz2/libtovid/deps.py
Deleted
212
1
2
-"""This module is for verifying libtovid's run-time dependencies.
3
-For example::
4
-
5
- deps.require(deps.core)
6
-
7
-will look for all of tovid's core dependencies. If any cannot be found, the
8
-missing ones are printed and an exception is raised. Run ``deps.py`` from a prompt
9
-for further examples.
10
-
11
-In practice::
12
-
13
- try:
14
- deps.require(deps.core)
15
- except deps.MissingDep:
16
- print("Exiting...")
17
- sys.exit(1)
18
-
19
-`deps.core` is an internal dictionary of tovid's core dependencies, where the
20
-keys are the names, and the values are brief descriptions with URLs.
21
-
22
-Provided dependency dictionaries:
23
-
24
- core
25
- grep/sed/md5sum, mplayer, mencoder, mpjpegtools, ffmpeg
26
- magick
27
- composite, convert
28
- dvd
29
- spumux, dvdauthor, growisofs
30
- vcd
31
- vcdxbuild, cdrdao
32
- transcode
33
- tcprobe, tcrequant
34
- plugin
35
- sox, normalize
36
- all
37
- ALL dependencies above
38
-
39
-If you don't want to use a provided dictionary, you can specify individual
40
-program names to look for::
41
-
42
- deps.require("more less cat")
43
-
44
-`require` also provides ways to print custom URLs and help when it cannot find
45
-dependencies. See ``help(deps.require)`` or keep reading.
46
-"""
47
-
48
-__all__ = [
49
- 'which',
50
- 'require',
51
- 'MissingDep',
52
-]
53
-
54
-import subprocess
55
-import textwrap
56
-
57
-from libtovid.util.output import red
58
-
59
-class MissingDep (Exception):
60
- """Missing dependency exception."""
61
- pass
62
-
63
-###
64
-### Module data
65
-###
66
-
67
-# Dictionary format: {"name": "description (url)"}
68
-all = {}
69
-
70
-core = {
71
- "grep": "a GNU utility (www.gnu.org/software/grep)",
72
- "sed": "a GNU utility (directory.fsf.org/GNU/software/sed.html)",
73
- "md5sum": "a GNU utility (www.gnu.org/software/coreutils)",
74
- "mplayer": "part of mplayer (www.mplayerhq.hu)",
75
- "mencoder": "part of mplayer (www.mplayerhq.hu)",
76
- "mplex": "part of mjpegtools (mjpeg.sf.net)",
77
- "mpeg2enc": "part of mjpegtools (mjpeg.sf.net)",
78
- "yuvfps": "part of mjpegtools (mjpeg.sf.net)",
79
- "yuvdenoise": "part of mjpegtools (mjpeg.sf.net)",
80
- "ppmtoy4m": "part of mjpegtools (mjpeg.sf.net)",
81
- "mp2enc": "part of mjpegtools (mjpeg.sf.net)",
82
- "jpeg2yuv": "part of mjpegtools (mjpeg.sf.net)",
83
- "ffmpeg": "a video encoding utility (ffmpeg.mplayerhq.hu)" }
84
-all.update(core)
85
-
86
-magick = {
87
- "composite": "part of ImageMagick (www.imagemagick.org)",
88
- "convert": "part of ImageMagick (www.imagemagick.org)" }
89
-all.update(magick)
90
-
91
-dvd = {
92
- "spumux": "part of dvdauthor (dvdauthor.sf.net)",
93
- "dvdauthor": "part of dvdauthor (dvdauthor.sf.net)",
94
- "growisofs": "part of dvd+rw-tools (fy.chalmers.se/~appro/linux/DVD+RW)"}
95
-all.update(dvd)
96
-
97
-vcd = {
98
- "vcdxbuild": "part of vcdimager (www.vcdimager.org)",
99
- "cdrdao": "a cd burning application (cdrdao.sf.net)" }
100
-all.update(vcd)
101
-
102
-transcode = {
103
- "tcprobe": "part of transcode (www.transcoding.org)",
104
- "tcrequant": "part of transcode (www.transcoding.org)" }
105
-all.update(transcode)
106
-
107
-plugin = {
108
- "sox": "swiss army knife for sound (sox.sf.net)",
109
- "normalize": "wave gain and normalization (normalize.nongnu.org)" }
110
-all.update(plugin)
111
-
112
-__missing_dependency_message = \
113
-"""Please install the above MISSING dependencies and try again. See
114
-http://tovid.wikia.com/wiki/Tovid_dependencies for more help.
115
-"""
116
-
117
-###
118
-### Exported functions
119
-###
120
-
121
-def which(executable):
122
- """Locate the given executable program name on the current path.
123
- If found, return the full pathname; otherwise, return the empty string.
124
- """
125
- proc = subprocess.Popen(['which', executable],
126
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
127
- return proc.stdout.read().rstrip('\n')
128
-
129
-def require(deps,
130
- help="You need these to finish what you were doing.",
131
- description="oops"):
132
-
133
- """Assert that one or more dependencies exist on the system. If any
134
- are missing, raise a `MissingDep` exception.
135
-
136
- deps
137
- Names of dependencies to assert. May be a single name,
138
- a python list or space-separated string list of names,
139
- or a dictionary of the form {depname: description}.
140
- help
141
- A help message about why the dependencies are needed
142
- description
143
- A short description of the dep, and its homepage URL
144
- (ignored if deps is a dictionary).
145
-
146
- If a given dependency name is found in one of the internal dictionaries,
147
- (core, magick, etc.), its description is taken from there.
148
-
149
- Examples:
150
-
151
- require(all)
152
- Look for ALL dependencies that are defined internally.
153
-
154
- require(core, "You are missing CORE dependencies!")
155
- Use the core dictionary to determine which dependencies to
156
- look for. Print the help message if any dependency is missing.
157
-
158
- require("xine", "You can't preview!", "a video player (xinehq.de)")
159
- Check for xine and print the custom help and URL messages
160
- if missing.
161
-
162
- require("mplayer mencoder", url="a video player (mplayerhq.hu)")
163
- Look for mplayer and mencoder. Use the default help message,
164
- but print a custom URL.
165
-
166
- """
167
- # Get the deps to check for: dictionary.keys(), or a list
168
- if type(deps) == dict:
169
- deps = deps.keys()
170
- elif type(deps) == str:
171
- deps = deps.split(' ')
172
- elif type(deps) != list:
173
- raise ValueError("%s is not dictionary, list, or string!" % str(deps))
174
-
175
- # Find the missing dependencies
176
- have_deps = True
177
- for dep in deps:
178
- if which(dep) == '':
179
- if type(deps) == dict:
180
- description = deps[dep]
181
- elif dep in all:
182
- description = all[dep]
183
- # Tell the user which dependencies they're missing
184
- print(red("MISSING:") + " %s, %s" % (dep, description))
185
- have_deps = False
186
-
187
- # Having reported the missing dependencies, print the help message and quit
188
- if not have_deps:
189
- print("\n", textwrap.fill(help + ' ' + __missing_dependency_message, 79))
190
- raise MissingDep("Cannot find required dependencies!")
191
-
192
-
193
-
194
-if __name__ == "__main__":
195
- trials = [
196
- (core, "You are missing CORE dependencies!", "custom url 1"),
197
- (core, "You are missing CORE dependencies!", "custom url 2"),
198
- ("grp md5sm", "You're missing some vowels!", "custom url 4"),
199
- ("foo", "heh, you don't have foo?!", "see foo.org") ]
200
-
201
- for dep, help, url in trials:
202
- try:
203
- print("================================================")
204
- print("Starting test...")
205
- require(dep, help, url)
206
- except MissingDep:
207
- print("(Would exit here.)\n")
208
- else:
209
- print("Test passed!\n")
210
-
211
-
212
tovid-0.34.tar.bz2/libtovid/encode.py
Deleted
207
1
2
-"""Encode video to standard formats, using one of several supported backends.
3
-
4
-One high-level function is provided::
5
-
6
- encode(infile, outfile, format, tvsys, method, **kwargs)
7
-
8
-For example::
9
-
10
- encode('/video/foo.avi', '/video/bar.mpg', 'dvd', 'ntsc', 'ffmpeg')
11
-
12
-This will encode ``/video/foo.avi`` to NTSC DVD format using ffmpeg, saving
13
-the result as ``/video/bar.mpg``. The ``format``, ``tvsys``, and ``method``
14
-arguments are optional; if you do::
15
-
16
- encode('/video/foo.avi', '/video/bar.mpg')
17
-
18
-then encoding will be DVD NTSC, using ffmpeg.
19
-
20
-Keyword arguments may be used to further refine encoding behavior, for example::
21
-
22
- encode('foo.avi', 'foo.mpg', 'dvd', 'pal',
23
- quality=7, interlace='bottom', ...)
24
-
25
-The supported keywords may vary by backend, but some keywords are supported
26
-by all backends. The available backends are:
27
-
28
- - `~libtovid.backend.ffmpeg`
29
- - `~libtovid.backend.mplayer`
30
- - `~libtovid.backend.mpeg2enc`
31
-
32
-"""
33
-
34
-__all__ = [
35
- 'encode',
36
- 'eval_keywords',
37
- 'fit',
38
-]
39
-
40
-from libtovid.backend import ffmpeg, mplayer, mpeg2enc
41
-from libtovid.media import MediaFile, standard_media, correct_aspect
42
-
43
-
44
-_bitrate_limits = {
45
- 'vcd': (1150, 1150),
46
- 'kvcd': (400, 4000),
47
- 'dvd-vcd': (400, 4000),
48
- 'svcd': (900, 2400),
49
- 'half-dvd': (600, 6000),
50
- 'dvd': (900, 9000)
51
- }
52
-
53
-# --------------------------------------------------------------------------
54
-#
55
-# Primary interface
56
-#
57
-# --------------------------------------------------------------------------
58
-
59
-def encode(infile, outfile, format='dvd', tvsys='ntsc', method='ffmpeg',
60
- **kwargs):
61
- """Encode a multimedia file ``infile`` according to a target profile,
62
- saving the encoded file to ``outfile``.
63
-
64
- infile
65
- Input filename
66
- outfile
67
- Desired output filename (``.mpg`` implied)
68
- format
69
- One of 'vcd', 'svcd', 'dvd' (case-insensitive)
70
- tvsys
71
- One of 'ntsc', 'pal' (case-insensitive)
72
- method
73
- Encoding backend: `~libtovid.backend.ffmpeg`,
74
- `~libtovid.backend.mplayer`, or `~libtovid.backend.mpeg2enc`
75
- kwargs
76
- Additional keyword arguments (name=value)
77
-
78
- For example::
79
-
80
- encode('/video/foo.avi', '/video/bar.mpg', 'dvd', 'ntsc', 'ffmpeg')
81
-
82
- This will encode ``/video/foo.avi`` to NTSC DVD format using ffmpeg, saving
83
- the result as '/video/bar.mpg'. The ``format``, ``tvsys``, and ``method``
84
- arguments are optional; if you do::
85
-
86
- encode('/video/foo.avi', '/video/bar.mpg')
87
-
88
- then encoding will be DVD NTSC, using ffmpeg.
89
-
90
- Keyword arguments may be used to further refine encoding behavior, for example::
91
-
92
- encode('foo.avi', 'foo.mpg', 'dvd', 'pal',
93
- quality=7, interlace='bottom', ...)
94
-
95
- The supported keywords may vary by backend, but some keywords are supported
96
- by all backends.
97
-
98
-
99
- """
100
- source = mplayer.identify(infile)
101
- # Add .mpg to outfile if not already present
102
- if not outfile.endswith('.mpg'):
103
- outfile += '.mpg'
104
- # Get an appropriate encoding target
105
- target = standard_media(format, tvsys)
106
- target.filename = outfile
107
- # Set desired aspect ratio, or auto
108
- if 'aspect' in kwargs:
109
- target = correct_aspect(source, target, kwargs['aspect'])
110
- else:
111
- target = correct_aspect(source, target, 'auto')
112
-
113
- # Some friendly output
114
- print("Source media:")
115
- print(source)
116
- print(' ')
117
- print("Target media:")
118
- print(target)
119
-
120
- # Get the appropriate encoding backend
121
- encode_method = get_encoder(method)
122
- # Evaluate high-level keywords
123
- kwargs = eval_keywords(source, target, **kwargs)
124
- # Encode!
125
- encode_method(source, target, **kwargs)
126
-
127
-
128
-# --------------------------------------------------------------------------
129
-#
130
-# Helper functions
131
-#
132
-# --------------------------------------------------------------------------
133
-
134
-def _get_encoder(backend):
135
- """Get an encoding function."""
136
- if backend == 'ffmpeg':
137
- return ffmpeg.encode
138
- elif backend in ['mplayer', 'mencoder']:
139
- return mplayer.encode
140
- elif backend == 'mpeg2enc':
141
- return mpeg2enc.encode
142
-
143
-
144
-def eval_keywords(source, target, **kwargs):
145
- """Interpret keywords that affect other keywords, and return the result.
146
- These are keywords that can be shared between multiple encoding backends.
147
-
148
- Supported keywords:
149
-
150
- quality
151
- From 1 (lowest) to 10 (highest) video quality.
152
- Overrides 'quant' and 'vbitrate' keywords.
153
- fit
154
- Size in MiB to fit output video to (overrides 'quality')
155
- Overrides 'quant' and 'vbitrate' keywords.
156
-
157
- """
158
- # Set quant and vbitrate to match desired quality
159
- if 'quality' in kwargs:
160
- kwargs['quant'] = 13-kwargs['quality']
161
- max_bitrate = _bitrate_limits[target.format][1]
162
- kwargs['vbitrate'] = kwargs['quality'] * max_bitrate / 10
163
- # Set quant and vbitrate to fit desired size
164
- if 'fit' in kwargs:
165
- kwargs['quant'], kwargs['vbitrate'] = \
166
- fit(source, target, kwargs['fit'])
167
- return kwargs
168
-
169
-
170
-def fit(source, target, fit_size):
171
- """Return video (quantization, bitrate) to fit a video into a given size.
172
-
173
- source
174
- `~libtovid.media.MediaFile` input (the video being encoded)
175
- target
176
- `~libtovid.media.MediaFile` output (desired target profile)
177
- fit_size
178
- Desired encoded file size, in MiB
179
-
180
- """
181
- assert isinstance(source, MediaFile)
182
- assert isinstance(target, MediaFile)
183
- fit_size = float(fit_size)
184
- mpeg_overhead = fit_size / 100
185
- aud_vid_size = fit_size - mpeg_overhead
186
- audio_size = float(source.length * target.abitrate) / (8*1024)
187
- video_size = aud_vid_size - audio_size
188
- vid_bitrate = int(video_size*8*1024 / source.length)
189
-
190
- print("Length: %s seconds" % source.length)
191
- print("Overhead: %s MiB" % mpeg_overhead)
192
- print("Audio: %s MiB" % audio_size)
193
- print("Video: %s MiB" % video_size)
194
- print("VBitrate: %s kbps" % vid_bitrate)
195
-
196
- # Keep bitrates sane for each disc format
197
- lower, upper = _bitrate_limits[target.format]
198
- quant = 3
199
- if vid_bitrate < lower:
200
- return (quant, lower)
201
- elif vid_bitrate > upper:
202
- return (quant, upper)
203
- else:
204
- return (quant, vid_bitrate)
205
-
206
-
207
tovid-0.34.tar.bz2/libtovid/media.py
Deleted
197
1
2
-"""This module provides a multimedia file class for storing a profile of
3
-attributes including resolution, audio and video codecs and bitrates.
4
-
5
-These can be used for getting a target `MediaFile` for encoding via
6
-one of the backends in :mod:`libtovid.backend`. For example::
7
-
8
- >>> dvd = standard_media('dvd', 'ntsc')
9
- >>> print(dvd)
10
- Filename:
11
- Format: DVD
12
- TVsys: NTSC
13
- Length: 0 seconds
14
- Video: 720x480 29.97fps 4:3 mpeg2 6000kbps
15
- Audio: ac3 224kbps 48000hz 2-channel
16
-
17
-"""
18
-
19
-__all__ = [
20
- 'MediaFile',
21
- 'standard_media',
22
- 'correct_aspect',
23
-]
24
-
25
-import copy
26
-from libtovid import log
27
-from libtovid import standard
28
-from libtovid.util import ratio_to_float
29
-
30
-# Analysis of MediaFile attributes
31
-#
32
-# acodec: ID, target
33
-# abitrate: ID, target
34
-# channels: ID
35
-# samprate: ID, source, target
36
-# vcodec: ID
37
-# vbitrate: ID, target
38
-# length: ID, source
39
-# scale: (ID), (source), target
40
-# expand: target
41
-# fps: ID, source, target
42
-# aspect: source
43
-# widescreen: target
44
-#
45
-#
46
-# Redundancies(?):
47
-# widescreen/aspect
48
-# scale/expand if aspect is known
49
-
50
-class MediaFile:
51
- """A multimedia video file, and its vital statistics.
52
- """
53
- def __init__(self, filename='', format='none', tvsys='none'):
54
- log.debug("MediaFile(%s, %s, %s)" % (filename, format, tvsys))
55
- # TODO: Set attributes to match given format and tvsys
56
- self.filename = filename
57
- self.format = format
58
- self.tvsys = tvsys
59
- self.length = 0
60
- # TODO: Support multiple audio and video tracks
61
- self.has_audio = False
62
- self.has_video = False
63
- # Audio attributes
64
- self.acodec = 'none'
65
- self.abitrate = 0
66
- self.channels = 0
67
- self.samprate = 0
68
- # Video attributes
69
- self.vcodec = 'none'
70
- # TODO: Better names for scale & expand, but not so long as
71
- # 'inner_resolution' and 'outer_resolution', or
72
- # 'picture_res' and 'frame_res'. Suggestions?
73
- self.scale = (0, 0)
74
- self.expand = (0, 0)
75
- self.vbitrate = 0
76
- self.fps = 0.0
77
- self.aspect = '0:0'
78
- self.widescreen = False
79
-
80
-
81
- def __str__(self):
82
- """Return a string representation of the MediaFile.
83
- """
84
- width, height = self.expand or self.scale
85
- # List of lines of output
86
- lines = [
87
- 'Filename: %s' % self.filename,
88
- 'Format: %s' % self.format,
89
- 'TVsys: %s' % self.tvsys,
90
- 'Length: %s seconds' % self.length,
91
- 'Video: %sx%s %sfps %s %s %skbps' % \
92
- (width, height, self.fps, self.aspect, self.vcodec, self.vbitrate),
93
- 'Audio: %s %skbps %shz %s-channel' % \
94
- (self.acodec, self.abitrate, self.samprate, self.channels)
95
- ]
96
- # Add newlines and return
97
- return '\n'.join(lines)
98
-
99
-
100
-def standard_media(format, tvsys):
101
- """Return a `MediaFile` compliant with a standard format and TV system.
102
-
103
- format
104
- Standard format ('vcd', 'svcd', or 'dvd')
105
- tvsys
106
- TV system ('pal' or 'ntsc')
107
-
108
- """
109
- log.debug("standard_media(%s, %s)" % (format, tvsys))
110
- media = MediaFile('', format, tvsys)
111
- # Set valid video attributes
112
- media.vcodec = standard.vcodec(format)
113
- media.scale = standard.resolution(format, tvsys)
114
- media.expand = media.scale
115
- media.fps = standard.fps(tvsys)
116
- # Set valid audio attributes
117
- media.acodec = standard.acodec(format)
118
- media.samprate = standard.samprate(format)
119
- # TODO: How to handle default bitrates? These functions return a range.
120
- #media.vbitrate = standard.vbitrate(format)[1]
121
- #media.abitrate = standard.abitrate(format)[1]
122
- media.abitrate = 224
123
- if format == 'vcd':
124
- media.vbitrate = 1150
125
- elif format == 'svcd':
126
- media.vbitrate = 2600
127
- else:
128
- media.vbitrate = 6000
129
- return media
130
-
131
-
132
-def correct_aspect(source, target, aspect='auto'):
133
- """Calculate the necessary scaling to fit source into target at a given
134
- aspect ratio, without distorting the picture.
135
-
136
- source
137
- Input `MediaFile`
138
- target
139
- Output `MediaFile`
140
- aspect
141
- Aspect ratio to assume for input file (e.g., '4:3', '16:9')
142
- or 'auto' to use autodetection based on source aspect
143
-
144
- Return a new target `MediaFile` with correct scaling, using letterboxing
145
- if appropriate, and anamorphic widescreen if available (DVD only).
146
- """
147
- assert isinstance(source, MediaFile)
148
- assert isinstance(target, MediaFile)
149
-
150
- # Base new target on existing one
151
- target = copy.copy(target)
152
-
153
- # Convert aspect (ratio) to a floating-point value
154
- if aspect == 'auto':
155
- src_aspect = ratio_to_float(source.aspect)
156
- else:
157
- src_aspect = ratio_to_float(aspect)
158
-
159
- # Use anamorphic widescreen for any video ~16:9 or wider
160
- # (Only DVD supports this)
161
- if src_aspect >= 1.7 and target.format == 'dvd':
162
- target_aspect = 16.0/9.0
163
- widescreen = True
164
- else:
165
- target_aspect = 4.0/3.0
166
- widescreen = False
167
-
168
- # Start by assuming direct scaling to target resolution
169
- width, height = target.scale
170
-
171
- # If aspect matches target, no letterboxing is necessary
172
- tolerance = 0.05
173
- if abs(src_aspect - target_aspect) < tolerance:
174
- scale = (width, height)
175
- # If aspect is wider than target, letterbox vertically
176
- elif src_aspect > target_aspect:
177
- scale = (width, int(height * target_aspect / src_aspect))
178
- # Otherwise (rare), letterbox horizontally
179
- else:
180
- scale = (int(width * src_aspect / target_aspect), height)
181
-
182
- # Always expand to the target resolution
183
- expand = (width, height)
184
-
185
- # If input file is already the correct size, don't scale
186
- if scale == source.scale:
187
- scale = False
188
-
189
- # Final scaling/expansion for correct aspect ratio display
190
- target.scale = scale
191
- target.expand = expand
192
- target.widescreen = widescreen
193
- return target
194
-
195
-
196
-
197
tovid-0.34.tar.bz2/libtovid/opts.py
Deleted
256
1
2
-# opts.py
3
-
4
-# WARNING: This module is a hack in progress
5
-
6
-__all__ = [
7
- 'Option',
8
- 'Usage',
9
- 'parse',
10
- 'validate',
11
-]
12
-
13
-import sys
14
-import textwrap
15
-from libtovid.odict import Odict
16
-from libtovid.util import trim
17
-
18
-class Option (object):
19
- """A command-line-style option, expected argument formatting, default value,
20
- and notes on usage and purpose.
21
-
22
- For example::
23
-
24
- debug_opt = Option(
25
- 'debug',
26
- 'none|some|all',
27
- 'some',
28
- "Amount of debugging information to display"
29
- )
30
-
31
- This defines a 'debug' option, along with a human-readable string showing
32
- expected argument formatting, a default value, and a string documenting the
33
- option's purpose and/or usage information.
34
- """
35
- def __init__(self, name, argformat='', default=None,
36
- doc='Undocumented option', alias=None,
37
- required=False):
38
- """Create a new option definition with the given attributes.
39
-
40
- name
41
- Option name
42
- argformat
43
- String describing format of expected arguments
44
- default
45
- Default value, if any
46
- doc
47
- Manual-page-style documentation of the option
48
- alias
49
- An ('option', 'value') equivalent for this option
50
-
51
- """
52
- self.name = name
53
- self.argformat = argformat
54
- self.default = default
55
- self.doc = trim(doc)
56
- self.alias = alias
57
- self.required = required
58
- # If an alias was provided, generate documentation.
59
- # i.e., alias=('tvsys', 'ntsc') means this option is the same as
60
- # giving the 'tvsys' option with 'ntsc' as the argument.
61
- if self.alias:
62
- self.doc = 'Same as -%s %s.' % alias
63
-
64
-
65
- def num_args(self):
66
- """Return the number of arguments expected by this option,
67
- or -1 if unlimited.
68
- """
69
- # Flag alias for another option
70
- if self.alias:
71
- return 0
72
- # Boolean: no argument
73
- elif isinstance(self.default, bool):
74
- return 0
75
- # List: unlimited arguments
76
- elif isinstance(self.default, list):
77
- return -1
78
- # Unary: one argument
79
- else:
80
- return 1
81
-
82
-
83
- def __str__(self):
84
- """Return a string containing "usage notes" for this option.
85
- """
86
- if self.alias:
87
- usage = "-%s: Same as '-%s %s'\n" % \
88
- (self.name, self.alias[0], self.alias[1])
89
- else:
90
- usage = "-%s %s " % (self.name, self.argformat)
91
- if self.required:
92
- usage += "(REQUIRED)\n"
93
- else:
94
- usage += "(default: %s)\n" % self.default
95
- for line in textwrap.wrap(self.doc, 60):
96
- usage += ' ' + line + '\n'
97
- return usage
98
-
99
-class Usage (object):
100
- """Command-line usage definition."""
101
- def __init__(self, usage_string='program [options]', *options):
102
- """Define usage of a command-line program.
103
-
104
- usage_string
105
- Command-line syntax and required options
106
- options
107
- List of allowed Options
108
-
109
- Examples::
110
-
111
- usage = Usage('pytovid [options] -in FILENAME -out NAME',
112
- Option('in', 'FILENAME', None,
113
- "Input video file, in any format."),
114
- Option('out', 'NAME', None,
115
- "Output prefix or name."),
116
- Option('format', 'vcd|svcd|dvd|half-dvd|dvd-vcd', 'dvd',
117
- "Make video compliant with the specified format")
118
- )
119
- print(usage)
120
- print(usage.options['format'])
121
-
122
- """
123
- self.usage_string = usage_string
124
- # Odict of options indexed by name
125
- names = [opt.name for opt in options]
126
- self.options = Odict(names, options)
127
-
128
-
129
- def __str__(self):
130
- """Return string-formatted usage notes.
131
- """
132
- result = "Usage: %s\n" % self.usage_string
133
- result += "Allowed options:\n"
134
- option_list = ['-' + opt.name for opt in self.options.values()]
135
- result += ', '.join(option_list)
136
- return result
137
-
138
-
139
-
140
-from copy import copy
141
-
142
-def parse(args):
143
- """Parse a list of arguments and return a dictionary of found options.
144
-
145
- args: List of command-line arguments (such as from sys.argv)
146
-
147
- The argument list is interpreted in this way:
148
-
149
- * If it begins with '-', it's an option
150
- * Arguments that precede the first option are ignored
151
- * Anything following an option is an argument to that option
152
- * If there is no argument to an option, it's a flag (True if present)
153
- * If there's one argument to an option, it's a single string value
154
- * If there are multiple arguments to an option, it's a list of strings
155
-
156
- """
157
- args = copy(args)
158
- options = {}
159
- current = None
160
- while len(args) > 0:
161
- arg = args.pop(0)
162
- # New option
163
- if arg.startswith('-'):
164
- current = arg.lstrip('-')
165
- # Treat it as a flag unless we see arguments later
166
- options[current] = True
167
-
168
- # Argument to current option
169
- elif current:
170
- # Was a flag, now has a single value
171
- if options[current] is True:
172
- options[current] = arg
173
- # Was a single value, now a list
174
- elif type(options[current]) != list:
175
- options[current] = [options[current], arg]
176
- # Was a list, so append new value
177
- else:
178
- options[current].append(arg)
179
- return options
180
-
181
-
182
-import re
183
-
184
-def validate(option, arg):
185
- """Check whether an argument is valid for a given option.
186
-
187
- option: An Option to validate
188
- arg: Candidate argument
189
-
190
- Expected/allowed values are inferred from the argformat string.
191
-
192
- argformat patterns to consider:
193
- opta|optb|optc # Either opta, optb, or optc
194
- [100-999] # Any integer between 100 and 999
195
- NUM:NUM # Any two integers separated by a colon
196
- VAR # A single string (VAR can be any all-caps word)
197
- VAR [, VAR] # List of strings
198
- (empty) # Boolean; no argument required
199
-
200
- All very experimental...
201
- """
202
- # TODO: Eliminate hackery; find a more robust way of doing this.
203
- # Also, pretty inefficient, since regexp matching is done every
204
- # time this function is called.
205
-
206
- # Empty argformat means boolean/no argument expected
207
- if option.argformat == '':
208
- if arg in [True, False, '']:
209
- return True
210
- else:
211
- return False
212
-
213
- # Any alphanumeric word (any string)
214
- if re.compile('^\w+$').match(option.argformat):
215
- if arg.__class__ == str:
216
- return True
217
- else:
218
- return False
219
-
220
- # Square-bracketed values are ranges, i.e. [1-99]
221
- match = re.compile('^\[\d+-\d+\]$').match(option.argformat)
222
- if match:
223
- # Get min/max by stripping and splitting argformat
224
- limits = re.split('-', match.group().strip('[]'))
225
- option.min = int(limits[0])
226
- option.max = int(limits[1])
227
- if int(arg) >= option.min and int(arg) <= option.max:
228
- return True
229
- else:
230
- return False
231
-
232
- # Values separated by | are mutually-exclusive
233
- if re.compile('[-\w]+\|[-\w]+').match(option.argformat):
234
- if arg in option.argformat.split('|'):
235
- return True
236
- else:
237
- return False
238
-
239
- # For now, accept any unknown cases
240
- return True
241
-
242
-
243
-
244
-if __name__ == '__main__':
245
- print("Option-parsing demo")
246
-
247
- print("You passed the following arguments:")
248
- print(sys.argv[1:])
249
-
250
- print("Parsing...")
251
- options = parse(sys.argv[1:])
252
-
253
- print("Found the following options:")
254
- print(options)
255
-
256
tovid-0.34.tar.bz2/libtovid/render
Deleted
2
1
-(directory)
2
tovid-0.34.tar.bz2/libtovid/render/__init__.py
Deleted
9
1
2
-__all__ = [
3
- 'animation',
4
- 'drawing',
5
- 'effect',
6
- 'flipbook',
7
- 'layer',
8
-]
9
tovid-0.34.tar.bz2/libtovid/render/animation.py
Deleted
318
1
2
-"""This module provides classes and functions for working with animation.
3
-Two classes are provided:
4
-
5
- `Keyframe`
6
- A frame with a specific data value
7
- `Tween`
8
- A data sequence interpolated from Keyframes
9
-
10
-The data being interpolated may represent color, opacity, location, or anything
11
-else that can be described numerically. Keyframe data may be scalar (single
12
-integers or decimal values) or vector (tuples such as ``(x, y)`` coordinates or
13
-``(r, g, b)`` color values).
14
-
15
-For example, let's define three keyframes::
16
-
17
- >>> keys = [Keyframe(1, 0),
18
- ... Keyframe(6, 50),
19
- ... Keyframe(12, 10)]
20
-
21
-The value increases from 0 to 50 over frames 1-6, then back down to 10
22
-over frames 6-12. The values at intermediate frames (2-5 and 7-11) can be
23
-interpolated or "tweened" automatically, using the Tween class::
24
-
25
- >>> tween = Tween(keys)
26
- >>> tween.data
27
- [0, 10, 20, 30, 40, 50, 43, 36, 30, 23, 16, 10]
28
-
29
-Another example using tweening of ``(x, y)`` coordinates::
30
-
31
- >>> keys = [Keyframe(1, (20, 20)),
32
- ... Keyframe(6, (80, 20)),
33
- ... Keyframe(12, (100, 100))]
34
-
35
-Here, a point on a two-dimensional plane starts at (20, 20), moving first
36
-to the right, to (80, 20), then diagonally to (100, 100)::
37
-
38
- >>> tween = Tween(keys)
39
- >>> for (x, y) in tween.data:
40
- ... print((x, y))
41
- ...
42
- (20, 20)
43
- (32, 20)
44
- (44, 20)
45
- (56, 20)
46
- (68, 20)
47
- (80, 20)
48
- (83, 33)
49
- (86, 46)
50
- (90, 60)
51
- (93, 73)
52
- (96, 86)
53
- (100, 100)
54
-
55
-"""
56
-
57
-__all__ = [
58
- 'Keyframe',
59
- 'Tween',
60
- 'lerp',
61
- 'cos_interp',
62
- 'interpolate',
63
-]
64
-
65
-import copy
66
-import doctest
67
-import math
68
-
69
-class Keyframe:
70
- """Associates a specific frame in an animation with a numeric value.
71
- A Keyframe is a ``(frame, data)`` pair defining a "control point" on a graph::
72
-
73
- 100 |
74
- | Keyframe(10, 50)
75
- data | *
76
- |
77
- 0 |__________________________
78
- 1 10 20 30
79
- frame
80
-
81
- The data can represent anything you like. For instance, opacity::
82
-
83
- 100 |* Keyframe(1, 100)
84
- |
85
- opacity(%) |
86
- |
87
- 0 |____________________* Keyframe(30, 0)
88
- 1 10 20 30
89
- frame
90
-
91
- See the `Tween` class below for what you can do with these Keyframes,
92
- once you have them.
93
- """
94
- def __init__(self, frame, data):
95
- """Create a keyframe, associating a given frame with some data.
96
- The data may be an integer, floating-point value, or a tuple like
97
- (x, y) or (r, g, b).
98
- """
99
- self.frame = frame
100
- self.data = data
101
-
102
-
103
-### --------------------------------------------------------------------------
104
-### Interpolation algorithms
105
-### --------------------------------------------------------------------------
106
-
107
-def lerp(x, (x0, y0), (x1, y1)):
108
- """Do linear interpolation between points ``(x0, y0)``, ``(x1, y1)``, and
109
- return the ``y`` for the given ``x``.
110
-
111
- This form of interpolation simply connects two points with a straight
112
- line. Blunt, but effective.
113
- """
114
- return y0 + (x - x0) * (y1 - y0) / (x1 - x0)
115
-
116
-
117
-def cos_interp(x, (x0, y0), (x1, y1)):
118
- """Do cosine-based interpolation between ``(x0, y0)``, ``(x1, y1)`` and
119
- return the ``y`` for the given ``x``.
120
-
121
- Essentially, a crude alternative to polynomial spline interpolation; this
122
- method transitions between two values by matching a segment of the cosine
123
- curve [0, pi] (for decreasing value) or [pi, 2*pi] (for increasing value)
124
- to the interval between the given points.
125
-
126
- It gives smoother results at inflection points than linear interpolation,
127
- but will result in "ripple" effects if keyframes are too dense or many.
128
- """
129
- # Map the interpolation area (domain of x) to [0, pi]
130
- x_norm = math.pi * (x - x0) / (x1 - x0)
131
- # For y0 < y1, use upward-sloping part of the cosine curve [pi, 2*pi]
132
- if y0 < y1:
133
- x_norm += math.pi
134
- # Calculate and return resulting y-value
135
- y_min = min(y1, y0)
136
- y_diff = abs(y1 - y0)
137
- return y_min + y_diff * (math.cos(x_norm) + 1) / 2.0
138
-
139
-
140
-def interpolate(frame, left, right, method='linear'):
141
- """Return the interpolated value at ``frame``, between two `Keyframe`
142
- endpoints, using the given interpolation method ('linear' or 'cosine').
143
-
144
- The left and right Keyframes mark the endpoints of the curve to be
145
- interpolated. For example, if a value changes from 50 to 80 over the
146
- course of frames 1 to 30::
147
-
148
- >>> left = Keyframe(1, 50)
149
- >>> right = Keyframe(30, 80)
150
-
151
- Then, the value at frame 10 can be interpolated as follows::
152
-
153
- >>> interpolate(10, left, right, 'linear')
154
- 59
155
- >>> interpolate(10, left, right, 'cosine')
156
- 56.582194019564263
157
-
158
- For frames outside the keyframe interval, the corresponding endpoint value
159
- is returned::
160
-
161
- >>> interpolate(0, left, right, 'linear')
162
- 50
163
- >>> interpolate(40, left, right, 'linear')
164
- 80
165
-
166
- """
167
- assert isinstance(left, Keyframe) and isinstance(right, Keyframe)
168
- # At or beyond endpoints, return endpoint value
169
- if frame <= left.frame:
170
- return left.data
171
- elif frame >= right.frame:
172
- return right.data
173
-
174
- # Use the appropriate interpolation function
175
- if method == 'cosine':
176
- interp_func = cos_interp
177
- else: # method == 'linear'
178
- interp_func = lerp
179
-
180
- # Interpolate integers or floats
181
- if isinstance(left.data, int) or isinstance(left.data, float):
182
- p0 = (left.frame, left.data)
183
- p1 = (right.frame, right.data)
184
- return interp_func(frame, p0, p1)
185
- # Interpolate a tuple (x, y, ...)
186
- elif isinstance(left.data, tuple):
187
- # Interpolate each dimension separately
188
- dim = 0
189
- result = []
190
- while dim < len(left.data):
191
- interp_val = interp_func(frame,
192
- (left.frame, left.data[dim]),
193
- (right.frame, right.data[dim]))
194
- result.append(interp_val)
195
- dim += 1
196
- return tuple(result)
197
-
198
-
199
-class Tween:
200
- """An "in-between" sequence, calculated by interpolating the data in a
201
- list of keyframes according to a given interpolation method.
202
-
203
- First, define some keyframes::
204
-
205
- >>> keyframes = [Keyframe(1, 1), Keyframe(10, 25)]
206
-
207
- At frame 1, the value is 1; at frame 10, the value is 25. To get an
208
- interpolation of the data between these two keyframes, use::
209
-
210
- >>> tween = Tween(keyframes)
211
-
212
- Now, retrieve the interpolated data all at once::
213
-
214
- >>> tween.data
215
- [1, 3, 6, 9, 11, 14, 17, 19, 22, 25]
216
-
217
- Or by using array notation, indexed by frame number::
218
-
219
- >>> tween[3]
220
- 6
221
- >>> tween[8]
222
- 19
223
-
224
- """
225
- def __init__(self, keyframes, method='linear'):
226
- """Create an in-between sequence from a list of keyframes. The
227
- interpolation method can be 'linear' or 'cosine'.
228
-
229
- See `libtovid.render.effect` for implementation examples.
230
- """
231
- for keyframe in keyframes:
232
- assert isinstance(keyframe, Keyframe)
233
- self.keyframes = keyframes
234
- self.start = self.keyframes[0].frame
235
- self.end = self.keyframes[-1].frame
236
- self.method = method
237
- # Do the tweening
238
- self.data = self._calculate()
239
-
240
-
241
- def _calculate(self):
242
- """Perform in-betweening calculation on the current keyframes and
243
- return a list of tweened values, indexed by frame number.
244
- """
245
- data = []
246
- # TODO: Sort keyframes in increasing order by frame number (to ensure
247
- # keyframes[0] is the first frame, and keyframes[-1] is the last frame)
248
- # Make a copy of keyframes
249
- keys = copy.copy(self.keyframes)
250
- first = self.start
251
- last = self.end
252
-
253
- # If keyframe interval is empty, use constant data from first keyframe
254
- if first == last:
255
- return keys[0].data
256
-
257
- # Pop off keyframes as each interval is calculated
258
- left = keys.pop(0)
259
- right = keys.pop(0)
260
- frame = first
261
- # Interpolate until the last frame is reached
262
- while frame <= last:
263
- value = interpolate(frame, left, right, self.method)
264
- data.append(value)
265
- # Get the next interval, if it exists
266
- if frame == right.frame and len(keys) > 0:
267
- left = right
268
- right = keys.pop(0)
269
- frame += 1
270
-
271
- return data
272
-
273
-
274
- def __getitem__(self, frame):
275
- """Return the interpolated data at the given frame. This allows
276
- accessing a tweened value with subscripting by frame number::
277
-
278
- >>> keys = [Keyframe(1, 1), Keyframe(30, 50)]
279
- >>> tween = Tween(keys)
280
- >>> tween[1]
281
- 1
282
- >>> tween[30]
283
- 50
284
- >>> tween[21]
285
- 34
286
-
287
- Frame numbers outside the keyframed region have the same values as
288
- those at the corresponding endpoints::
289
-
290
- >>> tween[0]
291
- 1
292
- >>> tween[100]
293
- 50
294
- """
295
- # If data is a single value, frame is irrelevant
296
- if not isinstance(self.data, list):
297
- return self.data
298
- # Otherwise, return the value for the given frame, extending endpoints
299
- elif frame < self.start:
300
- return self.data[0]
301
- elif frame > self.end:
302
- return self.data[-1]
303
- else:
304
- return self.data[frame - self.start]
305
-
306
-
307
-if __name__ == '__main__':
308
- doctest.testmod(verbose=True)
309
-
310
- p0 = (1, 1)
311
- p1 = (20, 20)
312
-
313
- print("Interpolation methods")
314
- print("x lerp cos_interp")
315
- for x in range(1, 21):
316
- print("%s %s %s" % \
317
- (x, lerp(x, p0, p1), cos_interp(x, p0, p1)))
318
tovid-0.34.tar.bz2/libtovid/render/drawing.py
Deleted
1458
1
2
-# -=- encoding: latin-1 -=-
3
-
4
-# Run this script standalone for a demonstration:
5
-# $ python libtovid/render/drawing.py
6
-
7
-# To use this module from your Python interpreter, run:
8
-# $ python
9
-# >>> from libtovid.render.drawing import *
10
-
11
-"""Interactive vector drawing and rendering interface.
12
-
13
-This module provides a class called Drawing, which provides a blank canvas
14
-that can be painted with vector drawing functions, and later rendered to
15
-a raster image file (.png, .jpg etc.) at any desired resolution.
16
-
17
-To create a new, blank Drawing::
18
-
19
- >>> d = Drawing(800, 600) # width, height
20
-
21
-Here, (800, 600) defines two things:
22
-
23
- - On-screen display size, in pixels (800px x 600px)
24
- - Intended viewing aspect ratio (800:600 or 4:3)
25
-
26
-Note that you are still doing vector drawing, so whatever size you pick here
27
-has no bearing on your final target resolution--it's mostly intended for a
28
-convenient "preview" size while doing interactive drawing.
29
-
30
-Back on topic: you can now add shapes to the drawing, fill and stroke them::
31
-
32
- >>> d.circle(500, 300, 150) # (x, y, radius)
33
- >>> d.fill('blue', 0.8) # color name with optional alpha
34
- >>> d.stroke('rgb(0, 128, 255)') # rgb values 0-255
35
-
36
-Then add more shapes::
37
-
38
- >>> d.rectangle(25, 25, 320, 240) # x, y, width, height
39
- >>> d.fill('rgb(40%, 80%, 10%)') # rgb percentages
40
- >>> d.stroke('#FF0080', 0.5) # rgb hex notation with an alpha
41
-
42
-To see what the drawing looks like so far, do::
43
-
44
- >>> display(d) # display at existing size
45
- >>> display(d, 720, 480) # display at different size
46
- >>> display(d, fix_aspect=True) # display in correct aspect ratio
47
-
48
-You may then decide to add more to the drawing::
49
-
50
- >>> d.set_source('white')
51
- >>> d.text("Dennis", 50, 100) # text, x, y
52
-
53
-And preview again::
54
-
55
- >>> display(d)
56
-
57
-Once you finish your beautiful painting, save it as a nice high-res PNG::
58
-
59
- >>> save_png(d, "my.png", 1600, 1200)
60
-
61
-Cairo references:
62
-
63
- [1] http://www.cairographics.org
64
- [2] http://tortall.net/mu/wiki/CairoTutorial
65
-
66
-"""
67
-
68
-__all__ = [
69
- 'Drawing',
70
- 'render',
71
- 'display',
72
- 'save_image',
73
- 'save_jpg',
74
- 'save_pdf',
75
- 'save_png',
76
- 'save_ps',
77
- 'save_svg',
78
- 'write_ppm',
79
-]
80
-
81
-import os
82
-import sys
83
-import time
84
-import commands
85
-from copy import copy
86
-from math import pi, sqrt
87
-import cairo
88
-import Image # for JPG export
89
-import ImageColor # for getrgb, getcolor
90
-import ImageFile # for write_png()
91
-from libtovid import log
92
-from libtovid.util import to_unicode
93
-
94
-def get_surface(width, height, surface_type='image', filename=''):
95
- """Get a cairo surface at the given dimensions.
96
- """
97
- if type(width) != int or type(height) != int:
98
- log.warning("Surface width and height should be integers."\
99
- " Converting to int.")
100
-
101
- if surface_type == 'image':
102
- return cairo.ImageSurface(cairo.FORMAT_ARGB32,
103
- int(width), int(height))
104
- elif surface_type == 'svg':
105
- return cairo.SVGSurface(filename, width, height)
106
- elif surface_type == 'pdf':
107
- return cairo.PDFSurface(filename, width, height)
108
- elif surface_type == 'ps':
109
- return cairo.PSSurface(filename, width, height)
110
-
111
-
112
-
113
-### --------------------------------------------------------------------
114
-### Classes
115
-### --------------------------------------------------------------------
116
-class Step:
117
- """An atomic drawing procedure, consisting of a closed function that
118
- draws on a given cairo surface, and human-readable information about
119
- what parameters were given to it.
120
- """
121
- def __init__(self, function, *args):
122
- self.function = function
123
- self.name = function.__name__.lstrip('_')
124
- self.args = args
125
- def __str__(self):
126
- return "%s%s" % (self.name, self.args)
127
-
128
-
129
-# Drawing class notes
130
-#
131
-# The Drawing class has a number of methods (circle, rectangle, fill, stroke
132
-# and many others) that need to operate on a Cairo surface. But we'd like to
133
-# delay execution of actually drawing on that surface--otherwise, we can't
134
-# easily render a given Drawing to a custom resolution.
135
-#
136
-# Closures save the day here--that is, functions without "free variables".
137
-# Anytime you "paint" on the Drawing, what's actually happening is a new
138
-# function is getting created, whose sole purpose in life is to carry out that
139
-# specific paint operation. These tiny, single-purpose functions are then
140
-# added to a list of steps (self.steps) that will actually be executed at
141
-# rendering-time (i.e., when you do display() or save_png).
142
-#
143
-# This not only lets us render a Drawing to different resolutions, but allows
144
-# the possibility of rendering to different Cairo surfaces.
145
-
146
-class Drawing:
147
-
148
- tk = None # tkinter widget to send redraws to
149
-
150
- def __init__(self, width=800, height=600, autodraw=False):
151
- """Create a blank drawing at the given size.
152
-
153
- width, height
154
- Dimensions of the drawable region, in arbitrary units
155
- autodraw
156
- Redraw a preview image after each drawing operation
157
- """
158
- self.size = (width, height)
159
- self.w = width
160
- self.h = height
161
- self.aspect = float(width) / height
162
- self.autodraw = autodraw
163
- #self.commands = []
164
- self.steps = []
165
- # "Dummy" surface/context at the original resolution;
166
- # should not be drawn on
167
- self.surface = get_surface(width, height, 'image')
168
- self.cr = cairo.Context(self.surface)
169
-
170
-
171
- def addStep(self, func, *args):
172
- """Add a Step to self.steps using the given function and args."""
173
- step = Step(func, *args)
174
- self.steps.append(step)
175
- if self.autodraw and step.name in ['fill', 'stroke']:
176
- display(self, 640, 480, True)
177
-
178
-
179
- def doStep(self, func, *args):
180
- """Add the given Step, and execute it."""
181
- self.addStep(func, *args)
182
- func(self.cr)
183
-
184
-
185
- def history(self):
186
- """Return a formatted string of all steps in this Drawing."""
187
- result = ''
188
- for number, step in enumerate(self.steps):
189
- result += '%d. %s\n' % (number, step)
190
- return result
191
-
192
-
193
- def affine(self, rot_x, rot_y, scale_x, scale_y, translate_x, translate_y):
194
- """Define a 3x3 transformation matrix::
195
-
196
- [ scale_x rot_y translate_x ]
197
- [ rot_x scale_y translate_y ]
198
- [ 0 0 1 ]
199
-
200
- This is scaling, rotation, and translation in a single matrix,
201
- so it's a compact way to represent any transformation.
202
-
203
- See [http://www.w3.org/TR/SVG11/coords.html] for more on
204
- these matrices and how to use them.
205
- """
206
- mtx = cairo.Matrix(scale_x, rot_x, rot_y, scale_y,
207
- translate_x, translate_y)
208
- def _affine(cr):
209
- cr.set_matrix(mtx)
210
- self.doStep(_affine, rot_x, rot_y, scale_x, scale_y,
211
- translate_x, translate_y)
212
-
213
-
214
- def arc(self, x, y, radius, start_deg, end_deg):
215
- """Draw an arc from (x, y), with the specified radius, starting at
216
- degree start_deg and ending at end_deg.
217
- """
218
- def _arc(cr):
219
- cr.arc(x, y, radius, start_deg * pi/180., end_deg * pi/180.)
220
- self.doStep(_arc, x, y, radius, start_deg, end_deg)
221
-
222
-
223
- def arc_rad(self, x, y, radius, start_rad, end_rad):
224
- """Draw an arc from (x, y), with the specified radius, starting at
225
- radian start_rad and ending at end_rad.
226
- """
227
- def _arc_rad(cr):
228
- cr.arc(x, y, radius, start_rad, end_rad)
229
- self.doStep(_arc_rad, x, y, radius, start_rad, end_rad)
230
-
231
-
232
- # TODO: Rewrite/cleanup bezier function
233
- def bezier(self, points, rel=False, close_path=False):
234
- """Create a Bezier curve.
235
-
236
- Points should look like::
237
-
238
- points = [[(x0, y0), (x_ctl1, y_ctl1), (x_ctl2, y_ctl2)],
239
- [(x0, y0), (x_ctl1, y_ctl1), (x_ctl2, y_ctl2)],
240
- [(x0, y0), (x_ctl1, y_ctl1), (x_ctl2, y_ctl2)],
241
- [(x0, y0)],
242
- ]
243
-
244
- where (x0, y0) are the point coordinates, and x_ctl* are the control
245
- points coordinates.
246
-
247
- - ctl1 - control from last point
248
- - ctl2 - control to next point
249
-
250
- The last line would specify that control points
251
- are at the same place (x0, y0), drawing straight lines.
252
-
253
- rel
254
- when this is True, the x_ctl and y_ctl become relatives
255
- to the (x0, y0) points
256
- close_path
257
- set this to True to call cr.close_path() before stroking.
258
-
259
- """
260
- assert len(points) > 1, "You need at least two points"
261
- for pt in points:
262
- # If only one point is specified, copy it for control points
263
- if len(pt) == 1:
264
- pt.append(pt[0]) # add the two identical
265
- pt.append(pt[0]) # control points
266
- assert len(pt) == 3, "You need to specify three tuples for each point, or one single"
267
- for y in pt:
268
- assert isinstance(y, tuple) and len(y) == 2, "You need "\
269
- "to specify two-values tuples"
270
- # Map relative stuff to absolute, when rel=True
271
- if rel:
272
- for x in range(0, len(points)):
273
- pt = points[x]
274
- assert len(pt) == 3, "In relative mode, you must "\
275
- "specify control points"
276
- # Render relative values to absolute values.
277
- npt = []
278
- # # x # y
279
- npt.append([pt[0][0], pt[0][1]]) # x0, y0
280
- npt.append([pt[0][0] + pt[1][0], pt[0][1] + pt[1][1]])
281
- npt.append([pt[0][0] + pt[2][0], pt[0][1] + pt[2][1]])
282
- points[x] = npt
283
-
284
- # Define the actual drawing function
285
- def _bezier(cr):
286
- # Move to the first x,y in the first point
287
- cr.new_path()
288
- cr.move_to(points[0][0][0], points[0][0][1])
289
- for pt in points:
290
- cr.curve_to(pt[2][0], pt[2][1],
291
- pt[0][0], pt[0][1],
292
- pt[1][0], pt[1][1])
293
- if close_path:
294
- cr.close_path()
295
- self.doStep(_bezier, points, rel, close_path)
296
-
297
-
298
- def circle(self, center_x, center_y, radius):
299
- """Draw a circle defined by center point and radius."""
300
- def _circle(cr):
301
- cr.new_path()
302
- cr.arc(center_x, center_y, radius, 0, 2*pi)
303
- self.doStep(_circle, center_x, center_y, radius)
304
-
305
-
306
- def fill(self, source=None, opacity=None):
307
- """Fill the current (closed) path with an optionally given color.
308
-
309
- If arguments are present, they are passed to set_source()
310
- before filling. Note that this source will be applied to further
311
- fill()ings or stroke()ings or text() calls.
312
- """
313
- # Optionally set fill color, and save it.
314
- if source is not None:
315
- self.set_source(source, opacity)
316
-
317
- def _fill(cr):
318
- cr.fill_preserve()
319
- self.doStep(_fill, source, opacity)
320
-
321
-
322
- def fill_rule(self, rule):
323
- """Set the fill rule to one of:
324
-
325
- evenodd, winding (nonzero)
326
-
327
- This determines which parts of an overlapping path polygon will
328
- be filled with the fill() command.
329
-
330
- http://www.w3.org/TR/SVG/painting.html#FillRuleProperty
331
- """
332
- tr = {'evenodd': cairo.FILL_RULE_EVEN_ODD,
333
- 'winding': cairo.FILL_RULE_WINDING}
334
-
335
- # Test value
336
- tr[rule]
337
-
338
- def _fill_rule(cr):
339
- cr.set_fill_rule(tr[rule])
340
- self.doStep(_fill_rule, rule)
341
-
342
-
343
- def font(self, name, slant='normal', weight='normal'):
344
- """Set the current font.
345
-
346
- name
347
- name of the Font, or family (sans-serif, serif)
348
- slant
349
- one of: italic, normal, oblique
350
- weight
351
- one of: normal, bold
352
- """
353
- sl = {'italic': cairo.FONT_SLANT_ITALIC,
354
- 'normal': cairo.FONT_SLANT_NORMAL,
355
- 'oblique': cairo.FONT_SLANT_OBLIQUE}
356
- wg = {'normal': cairo.FONT_WEIGHT_NORMAL,
357
- 'bold': cairo.FONT_WEIGHT_BOLD}
358
- def _font(cr):
359
- cr.select_font_face(name, sl[slant], wg[weight])
360
- self.doStep(_font, name, slant, weight)
361
-
362
-
363
- def font_size(self, pointsize):
364
- """Set the current font size in points.
365
- """
366
- def _font_size(cr):
367
- cr.set_font_size(pointsize)
368
- self.doStep(_font_size, pointsize)
369
-
370
-
371
- def font_stretch(self, x=1.0, y=1.0):
372
- """Set the font stretch type in both directions to one of:
373
-
374
- = 1.0 -- normal
375
- > 1.0 -- strench
376
- < 1.0 -- shrink
377
-
378
- """
379
- def _font_stretch(cr):
380
- m = cr.get_font_matrix()
381
- m.scale(x, y)
382
- cr.set_font_matrix(m)
383
- self.doStep(_font_stretch, x, y)
384
-
385
-
386
- def font_rotate(self, degrees):
387
- """Set the font rotation, in degrees.
388
- """
389
- def _font_rotate(cr):
390
- m = cr.get_font_matrix()
391
- m.rotate(degrees * pi/180.)
392
- cr.set_font_matrix(m)
393
- self.doStep(_font_rotate, degrees)
394
-
395
-
396
- def image_surface(self, x, y, width, height, surface, mask=None):
397
- """Draw a given cairo.ImageSurface centered at (x, y), at the given
398
- width and height.
399
-
400
- If you specify mask, it must be a cairo ImageSurface.
401
- """
402
- # Calculate centering and scaling
403
- add_x, add_y = (0, 0)
404
- dw = float(width) / float(surface.get_width())
405
- dh = float(height) / float(surface.get_height())
406
- if (dw > dh):
407
- scale = dh
408
- add_x = (width - dh * float(surface.get_width())) / 2
409
- else:
410
- scale = dw
411
- add_y = (height - dw * float(surface.get_height())) / 2
412
-
413
- # Save context and get the surface to right dimensions
414
- self.save()
415
- self.translate(x + add_x, y + add_y)
416
- self.scale(scale, scale)
417
-
418
- # Create and append the drawing function
419
- if (mask):
420
- def _image_surface(cr):
421
- cr.set_source_surface(surface)
422
- cr.mask_surface(mask)
423
- self.doStep(_image_surface, x, y, width, height, surface, mask)
424
- else:
425
- def _image_surface(cr):
426
- cr.set_source_surface(surface)
427
- cr.paint()
428
- self.doStep(_image_surface, x, y, width, height, surface, mask)
429
-
430
- self.restore()
431
-
432
-
433
- def image(self, x, y, width, height, source):
434
- """Draw an image centered at (x, y), scaled to the given width and
435
- height. Return the corresponding cairo.ImageSurface object.
436
-
437
- source
438
- - a .png filename (quicker and alpha present),
439
- - a cairo.ImageSurface object, which is even better,
440
- - a file object
441
- - a filename - any file supported by python-imaging,
442
- a.k.a PIL [1]
443
-
444
- Ref:
445
- [1] http://www.pythonware.com/library/pil/handbook/formats.htm
446
-
447
- You can apply some operator() to manipulation how the image is going
448
- to show up. See operator()
449
- """
450
- # Determine what type of source was given, and make it into
451
- # a cairo.ImageSurface
452
- if isinstance(source, cairo.ImageSurface):
453
- surface = source
454
- # PNG files can be added directly
455
- elif isinstance(source, str) and source.endswith('.png'):
456
- surface = cairo.ImageSurface.create_from_png(source)
457
- # Other formats must be converted to PNG
458
- else:
459
- infile = Image.open(source)
460
- outfile = open('/tmp/export.png', 'wb+')
461
- infile.save(outfile, 'PNG')
462
- outfile.seek(0)
463
- surface = cairo.ImageSurface.create_from_png(outfile)
464
- outfile.close()
465
- # Let someone else do the dirty work
466
- self.image_surface(x, y, width, height, surface)
467
-
468
- return surface
469
-
470
-
471
- def line(self, x0, y0, x1, y1):
472
- """Set new path as a line from (x0, y0) to (x1, y1).
473
-
474
- Don't forget to stroke()
475
- """
476
- def _line(cr):
477
- cr.new_path()
478
- cr.move_to(x0, y0)
479
- cr.line_to(x1, y1)
480
- self.doStep(_line, x0, y0, x1, y1)
481
-
482
-
483
- def operator(self, operator='clear'):
484
- """Set the operator mode.
485
-
486
- operator
487
- One of: clear, source, over, in, out, atop, dest,
488
- dest_over, dest_in, dest_out, dest_atop, xor, add, saturate
489
-
490
- """
491
- ops = {'clear': cairo.OPERATOR_CLEAR,
492
- 'source': cairo.OPERATOR_SOURCE,
493
- 'over': cairo.OPERATOR_OVER,
494
- 'in': cairo.OPERATOR_IN,
495
- 'out': cairo.OPERATOR_OUT,
496
- 'atop': cairo.OPERATOR_ATOP,
497
- 'dest': cairo.OPERATOR_DEST,
498
- 'dest_over': cairo.OPERATOR_DEST_OVER,
499
- 'dest_in': cairo.OPERATOR_DEST_IN,
500
- 'dest_out': cairo.OPERATOR_DEST_OUT,
501
- 'dest_atop': cairo.OPERATOR_DEST_ATOP,
502
- 'xor': cairo.OPERATOR_XOR,
503
- 'add': cairo.OPERATOR_ADD,
504
- 'saturate': cairo.OPERATOR_SATURATE,
505
- }
506
-
507
- # Test bad value
508
- ops[operator]
509
-
510
- def _operator(cr):
511
- cr.set_operator(ops[operator])
512
- self.doStep(_operator, operator)
513
-
514
-
515
- def paint(self):
516
- """Paint the current source everywhere within the current clip
517
- region.
518
- """
519
- def _paint(cr):
520
- cr.paint()
521
- self.doStep(_paint)
522
-
523
-
524
- def paint_with_alpha(self, alpha):
525
- """Paints the current source everywhere within the current clip
526
- region using a mask of constant alpha value alpha.
527
-
528
- The effect is similar to paint(), but the drawing is faded out
529
- using the alpha value.
530
- """
531
- def _paint_with_alpha(cr):
532
- cr.paint_with_alpha(alpha)
533
- self.doStep(_paint_with_alpha, alpha)
534
-
535
-
536
- def point(self, x, y):
537
- """Draw a point at (x, y).
538
- """
539
- # Circle radius 1/1000 the drawing width
540
- radius = float(self.size[0]) / 1000
541
- def _point(cr):
542
- cr.new_path()
543
- cr.arc(x, y, radius, 0, 2*pi)
544
- self.doStep(_point, x, y)
545
-
546
-
547
- def polygon(self, points, close_path=True):
548
- """Define a polygonal path defined by (x, y) points in the given
549
- list.
550
-
551
- points = [(x0, y0),
552
- (x1, y1),
553
- (x2, y2)]
554
-
555
- Draw strokes and filling yourself, with fill() and stroke().
556
- """
557
- nlist = []
558
- for tup in points:
559
- nlist.append([tup])
560
- self.bezier(nlist, False, close_path)
561
-
562
-
563
- def polyline(self, points, close_path=True):
564
- """Draw a polygon defined by (x, y) points in the given list.
565
-
566
- This is a short- (or long-) hand for polygon. In Cairo, you draw
567
- your filling (fill()), or strokes (stroke()) yourself, so
568
- having polyline and polygon is basiclly useless.
569
- """
570
- self.polygon(points, close_path)
571
-
572
-
573
- def rectangle_corners(self, x0, y0, x1, y1):
574
- """Draw a rectangle defined by opposite corners (x0, y0) and (x1, y1).
575
- """
576
- def _rectangle_corners(cr):
577
- cr.new_path()
578
- cr.rectangle(x0, y0, x1-x0, y1-y0)
579
- self.doStep(_rectangle_corners, x0, y0, x1, y1)
580
-
581
-
582
- def rectangle(self, x, y, width, height):
583
- """Draw a rectangle with top-left corner at (x, y), and (width x height)
584
- in size.
585
- """
586
- def _rectangle(cr):
587
- cr.new_path()
588
- cr.rectangle(x, y, width, height)
589
- self.doStep(_rectangle, x, y, width, height)
590
-
591
-
592
- def rotate_deg(self, degrees):
593
- """Rotate by the given number of degrees.
594
- """
595
- def _rotate_deg(cr):
596
- m = cr.get_matrix()
597
- m.rotate(degrees * pi/180.)
598
- cr.set_matrix(m)
599
- self.doStep(_rotate_deg, degrees)
600
-
601
- rotate = rotate_deg
602
- def rotate_rad(self, rad):
603
- """Rotate by the given number of radians.
604
- """
605
- def _rotate_rad(cr):
606
- m = cr.get_matrix()
607
- m.rotate(rad)
608
- cr.set_matrix(m)
609
- self.doStep(_rotate_rad, rad)
610
-
611
-
612
- def roundrectangle(self, x0, y0, x1, y1, bevel_width, bevel_height):
613
- """Draw a rounded rectangle from (x0, y0) to (x1, y1), with
614
- a bevel size of (bevel_width, bevel_height).
615
- """
616
- bw = bevel_width
617
- bh = bevel_height
618
- # Add bezier points
619
- tl1 = [(x0, y0 + bh), (0, 0), (0, 0)]
620
- tl2 = [(x0 + bw, y0), (0, 0), (-bw, 0)]
621
- tr1 = [(x1 - bw, y0), (0, 0), (-bw, 0)]
622
- tr2 = [(x1, y0 + bh), (0, 0), (0, -bw)]
623
- br1 = [(x1, y1 - bh), (0, 0), (0, -bh)]
624
- br2 = [(x1 - bw, y1), (0, 0), (+bw, 0)]
625
- bl1 = [(x0 + bw, y1), (0, 0), (+bw, 0)]
626
- bl2 = [(x0, y1 - bh), (0, 0), (0, +bh)]
627
- end = [(x0, y0 + bh), (0, 0), (0, 0)]
628
- # Call in relative mode bezier control points.
629
- mylst = [tl1, tl2, tr1, tr2, br1, br2, bl1, bl2, end]
630
- # Let bezier do the work
631
- self.bezier(mylst, True)
632
-
633
-
634
- def set_source(self, source, opacity=None):
635
- """Set the source.
636
-
637
- source
638
- One of the following color formats as a string or a tuple
639
- (see below), another Surface or Surface-derivative object,
640
- or a Pattern object (and its derivatives).
641
- opacity
642
- Opacity ranging from 0.0 to 1.0. Defaults to None. If
643
- you specify a 'string' or 'tuple' RGB-like code as
644
- source, opacity defaults to 1.0
645
-
646
- You can use the following *tuple* format to specify color:
647
-
648
- - (red, green, blue) with colors ranging from 0.0 to 1.0,
649
- like Cairo wants them
650
-
651
- You can use the following *string* formats to specify color:
652
-
653
- - Hexadecimal color specifiers, given as '#rgb' or '#rrggbb'.
654
- For example, '#ff0000' specifies pure red.
655
- - RGB functions, given as 'rgb(red, green, blue)' where the colour
656
- values are integers in the range 0 to 255. Alternatively, the color
657
- values can be given as three percentages (0% to 100%). For example,
658
- 'rgb(255,0,0)' and 'rgb(100%,0%,0%)' both specify pure red.
659
- - Hue-Saturation-Lightness (HSL) functions, given as:
660
- 'hsl(hue, saturation%, lightness%)' where hue is the colour given as
661
- an angle between 0 and 360 (red=0, green=120, blue=240), saturation
662
- is a value between 0% and 100% (gray=0%, full color=100%), and
663
- lightness is a value between 0% and 100% (black=0%, normal=50%,
664
- white=100%). For example, 'hsl(0,100%,50%)' is pure red.
665
- - Common HTML colour names. The ImageColor module provides some 140
666
- standard colour names, based on the colors supported by the X
667
- Window system and most web browsers. Colour names are case
668
- insensitive. For example, 'red' and 'Red' both specify pure red.
669
-
670
- """
671
- mysource = self.create_source(source, opacity)
672
- def _set_source(cr):
673
- cr.set_source(mysource)
674
- # Only do the step if the source could be created
675
- if mysource:
676
- self.doStep(_set_source, source, opacity)
677
-
678
-
679
- def create_source(self, source, opacity=None):
680
- """Return a source pattern (solid, gradient, image surface)
681
- with anything fed into it. Returns None if the source could not
682
- be created successfully.
683
-
684
- See the set_source() documentation for more details on inputs.
685
-
686
- You can feed anything returned by this function into set_source()
687
- """
688
- if isinstance(source, cairo.Pattern):
689
- return source
690
- # A string--color name, rgb(), hsv(), or hexadecimal
691
- elif isinstance(source, str):
692
- try:
693
- (r, g, b) = ImageColor.getrgb(source)
694
- except ValueError, err:
695
- log.error(err)
696
- return None
697
- alpha = 1.0
698
- if opacity is not None:
699
- alpha = opacity
700
- return cairo.SolidPattern(r / 255.0, g / 255.0,
701
- b / 255.0, alpha)
702
- # An (r, g, b) tuple
703
- elif isinstance(source, tuple):
704
- assert len(source) == 3
705
- (r, g, b) = source
706
- alpha = 1.0
707
- if opacity is not None:
708
- alpha = opacity
709
- return cairo.SolidPattern(r, g, b, alpha)
710
- # A cairo Gradient
711
- elif isinstance(source, cairo.Gradient):
712
- return source
713
- # A cairo Surface
714
- elif isinstance(source, cairo.Surface):
715
- return cairo.SurfacePattern(source)
716
- else:
717
- raise TypeError, "source must be one of: str, tuple, "\
718
- "cairo.Pattern, cairo.Gradient or cairo.Surface"
719
-
720
-
721
- def get_source(self):
722
- """Return the actually used source pattern
723
-
724
- This returns either of these:
725
-
726
- cairo.SolidPattern (RGB or RGBA color)
727
- cairo.SurfacePattern (some other image)
728
- cairo.LinearGradient (linear gradient :)
729
- cairo.RadialGradient (radial gradient :)
730
-
731
- You can then use this source in set_source(), to use the same
732
- pattern for fill()ing or stroke()ing.
733
- """
734
- # TODO: Fix or remove this function
735
- return self.cr.get_source()
736
-
737
-
738
- def scale(self, factor_x, factor_y):
739
- """Set scaling to (factor_x, factor_y), where 1.0 means no scaling.
740
-
741
- Note that the center point for scaling is (0,0); to scale from a
742
- different center point, use scale_centered()
743
- """
744
- def _scale(cr):
745
- m = cr.get_matrix()
746
- m.scale(factor_x, factor_y)
747
- cr.set_matrix(m)
748
- self.doStep(_scale, factor_x, factor_y)
749
-
750
-
751
- def scale_centered(self, center_x, center_y, factor_x, factor_y):
752
- """Set scaling to (dx, dy), where dx and dy are horizontal and
753
- vertical ratios (floats).
754
-
755
- scale_centered() will keep the (center_x, center_y) in the middle
756
- of the scaling, operating a translation in addition to scaling.
757
- """
758
- def _scale_centered(cr):
759
- m = cr.get_matrix()
760
- # Ouch, we want to keep the center x,y at the same place?!
761
- m.translate(-(center_x * factor_x - center_x),
762
- -(center_y * factor_y - center_y))
763
- m.scale(factor_x, factor_y)
764
- cr.set_matrix(m)
765
- self.doStep(_scale_centered, center_x, center_y, factor_x, factor_y)
766
-
767
-
768
- def stroke(self, source=None, opacity=None):
769
- """Stroke the current shape.
770
-
771
- See fill() documentation for parameter explanation. They are the
772
- same.
773
- """
774
- # Optionally set stroke color, and save it.
775
- if source is not None:
776
- self.set_source(source, opacity)
777
-
778
- def _stroke(cr):
779
- # Optionally set fill color, and save it.
780
- cr.stroke_preserve()
781
- self.doStep(_stroke, source, opacity)
782
-
783
-
784
- def stroke_antialias(self, do_antialias=True):
785
- """Enable/disable antialiasing for strokes.
786
-
787
- do_antialias: True, False, 'none', 'default', or 'gray'
788
-
789
- This does not affect text. See text_antialias() for more info
790
- on text antialiasing.
791
- """
792
- if do_antialias:
793
- aa_type = cairo.ANTIALIAS_GRAY
794
- else:
795
- aa_type = cairo.ANTIALIAS_NONE
796
-
797
- def _stroke_antialias(cr):
798
- cr.set_antialias(aa_type)
799
- self.doStep(_stroke_antialias, do_antialias)
800
-
801
-
802
- def stroke_dash(self, array, offset=0.0):
803
- """Set the dash style.
804
-
805
- array
806
- A list of floats, alternating between ON and OFF for
807
- each value
808
- offset
809
- An offset into the dash pattern at which the stroke
810
- should start
811
-
812
- For example::
813
-
814
- >>> stroke_dash([5.0, 3.0])
815
-
816
- alternates between 5 pixels on, and 3 pixels off.
817
- """
818
- def _stroke_dash(cr):
819
- cr.set_dash(array, offset)
820
- self.doStep(_stroke_dash, array, offset)
821
-
822
-
823
- def stroke_linecap(self, cap_type):
824
- """Set the type of line cap to use for stroking.
825
-
826
- cap_type
827
- 'butt', 'round', or 'square'
828
- """
829
- dic = {'butt': cairo.LINE_CAP_BUTT,
830
- 'round': cairo.LINE_CAP_ROUND,
831
- 'square': cairo.LINE_CAP_SQUARE}
832
-
833
- # Test value
834
- dic[cap_type]
835
-
836
- def _stroke_linecap(cr):
837
- cr.set_line_cap(dic[cap_type])
838
- self.doStep(_stroke_linecap, cap_type)
839
-
840
-
841
- def stroke_linejoin(self, join_type):
842
- """Set the type of line-joining to do for stroking.
843
-
844
- join_type
845
- 'bevel', 'miter', or 'round'
846
- """
847
- dic = {'bevel': cairo.LINE_JOIN_BEVEL,
848
- 'miter': cairo.LINE_JOIN_MITER,
849
- 'round': cairo.LINE_JOIN_ROUND}
850
-
851
- # Test value
852
- dic[join_type]
853
-
854
- def _stroke_linejoin(cr):
855
- cr.set_line_join(dic[join_type])
856
- self.doStep(_stroke_linejoin, join_type)
857
-
858
-
859
- def stroke_width(self, width):
860
- """Set the current stroke width in pixels."""
861
- # (Pixels or points?)
862
- def _stroke_width(cr):
863
- cr.set_line_width(width)
864
- self.doStep(_stroke_width, width)
865
-
866
-
867
- def text(self, text_string, x, y, align='left'):
868
- """Draw the given text string.
869
-
870
- text_string
871
- utf8 encoded text string
872
- x, y
873
- lower-left corner position
874
-
875
- Set the text's color with set_source() before calling text().
876
- """
877
- text_string = to_unicode(text_string)
878
-
879
- def _text(cr):
880
- (dx, dy, w, h, ax, ay) = cr.text_extents(text_string)
881
- if align == 'right':
882
- nx = x - w
883
- elif align == 'center':
884
- nx = x - w / 2
885
- else:
886
- nx = x
887
- cr.move_to(nx, y)
888
- cr.show_text(text_string)
889
- self.doStep(_text, text_string, x, y, align)
890
-
891
-
892
- def text_path(self, text_string, x, y):
893
- """Same as text(), but sets a path and doesn't draw anything.
894
- Call stroke() or fill() yourself.
895
-
896
- Has the parameters and returns the same values as text().
897
-
898
- Beware that text() calls the Cairo function show_text() which
899
- caches glyphs, so is more efficient when dealing with large
900
- texts.
901
- """
902
- if not isinstance(text_string, unicode):
903
- text_string = unicode(text_string.decode('latin-1'))
904
- def _text_path(cr):
905
- cr.move_to(x, y)
906
- cr.text_path(text_string)
907
- self.doStep(_text_path, text_string, x, y)
908
-
909
-
910
- def text_extents(self, text):
911
- """Returns the dimensions of the to-be-drawn text.
912
-
913
- Call this before calling text() if you want to place it well,
914
- according to the dimensions of the text rectangle to be drawn.
915
-
916
- See text()'s return value for details.
917
-
918
- Returns:
919
- (x_bearing, y_bearing, width, height, x_advance, y_advance)
920
- """
921
- text = to_unicode(text)
922
- return self.cr.text_extents(text)
923
-
924
-
925
- def translate(self, dx, dy):
926
- """Do a translation by (dx, dy) pixels."""
927
- def _translate(cr):
928
- m = cr.get_matrix()
929
- m.translate(dx, dy)
930
- cr.set_matrix(m)
931
- self.doStep(_translate, dx, dy)
932
-
933
-
934
- def push_group(self):
935
- """Temporarily redirects drawing to an intermediate surface
936
- known as a group.
937
-
938
- The redirection lasts until the group is completed by a call
939
- to pop_group() or pop_group_to_source(). These calls provide
940
- the result of any drawing to the group as a pattern, (either
941
- as an explicit object, or set as the source pattern).
942
- """
943
- def _push_group(cr):
944
- cr.push_group()
945
- self.doStep(_push_group)
946
-
947
-
948
- def pop_group_to_source(self):
949
- """Terminates the redirection begun by a call to push_group() and
950
- installs the resulting pattern as the source pattern in the current
951
- cairo context.
952
- """
953
- def _pop_group_to_source(cr):
954
- cr.pop_group_to_source()
955
- self.doStep(_pop_group_to_source)
956
-
957
-
958
- def save(self):
959
- """Save state for Cairo and local contexts.
960
-
961
- You can save in a nested manner, and calls to restore() will pop
962
- the latest saved context.
963
- """
964
- def _save(cr):
965
- cr.save()
966
- self.doStep(_save)
967
-
968
- BEGIN = save
969
- def restore(self):
970
- """Restore the previously saved context.
971
- """
972
- def _restore(cr):
973
- cr.restore()
974
- self.doStep(_restore)
975
-
976
- END = restore
977
- def font_family(self, family):
978
- """Set the current font, by family name."""
979
- def _font_family(cr):
980
- cr.select_font_face(family)
981
- self.doStep(_font_family, family)
982
-
983
- font_face = font_family
984
- def text_align(self, text_string, x, y, align='left'):
985
- """Draw the given text string.
986
-
987
- text_string
988
- UTF-8 encoded text string
989
- x, y
990
- Lower-left corner position
991
- align
992
- 'left', 'center', 'right'. This only changes the
993
- alignment in 'x', and 'y' stays the baseline.
994
-
995
- Set the text's color with set_source() before calling text().
996
- """
997
- (dx, dy, w, h, ax, ay) = self.cr.text_extents(text_string)
998
- w = 0
999
- if align == 'right':
1000
- x = x - w
1001
- elif align == 'center':
1002
- x = x - w / 2
1003
- else: # 'left'
1004
- x = x
1005
- # Let text() do the drawing
1006
- self.text(text_string, x, y)
1007
-
1008
-
1009
- def text_path_align(self, x, y, text_string, centered=False):
1010
- """Same as text_align(), but sets a path and doesn't draw anything.
1011
- Call stroke() or fill() yourself.
1012
- """
1013
- (dx, dy, w, h, ax, ay) = self.cr.text_extents(text_string)
1014
- if centered:
1015
- x = x - w / 2
1016
- y = y + h / 2
1017
- # Let text_path() do the drawing
1018
- self.text_path(text_string, x, y)
1019
-
1020
-
1021
-### --------------------------------------------------------------------
1022
-### Exported functions
1023
-### --------------------------------------------------------------------
1024
-# Cached masks, rendered only once.
1025
-interlace_fields = None
1026
-
1027
-
1028
-def interlace_drawings(draw1, draw2):
1029
- """Merge two drawings into one, using interlacing fields.
1030
-
1031
- This method interlaces with the BOTTOM-FIRST field order.
1032
- """
1033
- global interlace_fields
1034
-
1035
- dr = Drawing(draw1.w, draw1.h)
1036
-
1037
- # create masks (only once)
1038
- if (not interlace_fields):
1039
- fields = [0, 1]
1040
- for f in range(0, 2):
1041
- img = cairo.ImageSurface(cairo.FORMAT_ARGB32, draw1.w, draw1.h)
1042
- cr = cairo.Context(img)
1043
- cr.set_antialias(cairo.ANTIALIAS_NONE)
1044
- cr.set_source_rgba(0.5, 0.5, 0.5, 1)
1045
- cr.set_line_width(1)
1046
-
1047
- for x in range(0, draw1.h / 2):
1048
- # x*2 + f = top field first.., each two lines..
1049
- # -1 à draw1.w +1 -> pour être sur de couvrir aussi les bouts.
1050
- cr.move_to(-1, x*2 + f)
1051
- cr.line_to(draw1.w + 1, x*2 + f)
1052
- cr.stroke()
1053
-
1054
- fields[f] = img
1055
- interlace_fields = fields
1056
- else:
1057
- fields = interlace_fields
1058
-
1059
- # For bottom first, use fields[0] first, and fields[1] after.
1060
- # For top-first, use draw1 with fields[1] and draw2 with fields[0]
1061
- # paint first image
1062
- dr.image_surface(0, 0, dr.w, dr.h, draw1.surface, fields[0])
1063
- # paint second image
1064
- dr.image_surface(0, 0, dr.w, dr.h, draw2.surface, fields[1])
1065
-
1066
- return dr
1067
-
1068
-
1069
-
1070
-def render(drawing, context, width, height):
1071
- """Render a Drawing to the given cairo context at the given size.
1072
- """
1073
- # Scale from the original size
1074
- scale_x = float(width) / drawing.size[0]
1075
- scale_y = float(height) / drawing.size[1]
1076
- drawing.scale(scale_x, scale_y)
1077
- # Sneaky bit--scaling needs to happen before everything else
1078
- drawing.steps.insert(0, drawing.steps.pop(-1))
1079
-
1080
- # Execute all draw commands
1081
- for step in drawing.steps:
1082
- log.debug("Drawing step: %s" % step)
1083
- step.function(context)
1084
-
1085
- # Remove scaling function
1086
- drawing.steps.pop(0)
1087
-
1088
-
1089
-def display(drawing, width=None, height=None, fix_aspect=False):
1090
- """Render and display the given Drawing at the given size.
1091
-
1092
- drawing
1093
- A Drawing object to display
1094
- width
1095
- Pixel width of displayed image,
1096
- or 0 to use the given Drawing's size
1097
- height
1098
- Pixel height of displayed image,
1099
- or 0 to use the given Drawing's size
1100
- fix_aspect
1101
- True to adjust height to make the image
1102
- appear in the correct aspect ratio
1103
- """
1104
- if not width:
1105
- width = drawing.size[0]
1106
- if not height:
1107
- height = drawing.size[1]
1108
-
1109
- # Adjust height to fix aspect ratio if desired
1110
- if fix_aspect:
1111
- height = width / drawing.aspect
1112
- # Render and display a .png
1113
- png_file = '/tmp/drawing.png'
1114
- save_png(drawing, png_file, width, height)
1115
- print("Displaying %s at %sx%s" % (png_file, width, height))
1116
- print("(press 'q' in image window to continue)")
1117
- print(commands.getoutput('display %s' % png_file))
1118
-
1119
-
1120
-def write_ppm(drawing, pipe, width, height, workdir=None):
1121
- """Write image as a PPM file to a file-object
1122
-
1123
- workdir
1124
- Unused in this context, just to have parallel parameters
1125
- with write_png().
1126
-
1127
- Useful to pipe directly in ppmtoy4m and to pipe directly to mpeg2enc.
1128
- """
1129
- # Timing
1130
- start = time.time()
1131
- if (width, height) == drawing.size:
1132
- #print("Not re-rendering")
1133
- surface = drawing.surface
1134
- else:
1135
- surface = get_surface(width, height, 'image')
1136
- context = cairo.Context(surface)
1137
- render(drawing, context, width, height)
1138
-
1139
- buf = surface.get_data()
1140
- # Assumes surface is cairo.FORMAT_ARGB32
1141
- im = Image.frombuffer('RGBA', (surface.get_width(), surface.get_height()),
1142
- buf)
1143
- im = im.transpose(Image.FLIP_TOP_BOTTOM)
1144
- im.save(pipe, 'ppm')
1145
-
1146
- #print("write_ppm took %s seconds" % (time.time() - start))
1147
-
1148
-
1149
-def write_png(drawing, pipe, width, height, workdir):
1150
- """Write image as a PPM file to a file-object
1151
-
1152
- Useful to pipe directly in::
1153
-
1154
- pngtopnm -mix -background=rgb:00/00/00 | ppmtoy4m | mpeg2enc.
1155
- """
1156
- # Timing
1157
- start = time.time()
1158
- if (width, height) == drawing.size:
1159
- #print("Not re-rendering")
1160
- surface = drawing.surface
1161
- else:
1162
- surface = get_surface(width, height, 'image')
1163
- context = cairo.Context(surface)
1164
- render(drawing, context, width, height)
1165
-
1166
- surface.write_to_png('%s/tmp.png' % workdir)
1167
- im = Image.open('%s/tmp.png' % workdir)
1168
- im.load()
1169
- im.save(pipe, 'ppm')
1170
-
1171
- #print("write_png took %s seconds" % (time.time() - start))
1172
-
1173
-
1174
-def save_png(drawing, filename, width, height):
1175
- """Saves a drawing to PNG, keeping alpha channel intact.
1176
-
1177
- This is the quickest, since Cairo itself exports directly to .png
1178
- """
1179
- # Timing
1180
- start = time.time()
1181
- if (width, height) == drawing.size:
1182
- #print("Not re-rendering")
1183
- surface = drawing.surface
1184
- else:
1185
- surface = get_surface(width, height, 'image')
1186
- context = cairo.Context(surface)
1187
- render(drawing, context, width, height)
1188
- surface.write_to_png(filename)
1189
- #print("save_png took %s seconds" % (time.time() - start))
1190
-
1191
-
1192
-def save_jpg(drawing, filename, width, height):
1193
- """Saves a drawing to JPG, losing alpha channel information.
1194
- """
1195
- f = open('/tmp/export.png', 'wb+')
1196
- save_png(drawing, f, width, height)
1197
- f.seek(0)
1198
- im = Image.open(f)
1199
- im.save(filename)
1200
- del(im)
1201
- f.close()
1202
-
1203
-
1204
-def save_image(drawing, img_filename, width, height):
1205
- """Render drawing to a .jpg, .png or other image.
1206
- """
1207
- log.info("Saving Drawing to %s" % img_filename)
1208
- if img_filename.endswith('.png'):
1209
- save_png(drawing, img_filename, width, height)
1210
- elif img_filename.endswith('.jpg'):
1211
- save_jpg(drawing, img_filename, width, height)
1212
- else:
1213
- log.debug("Creating temporary .png")
1214
- temp_png = '/tmp/%s.png' % img_filename
1215
- save_png(drawing, temp_png, width, height)
1216
- log.debug("Converting temporary png to %s" % img_filename)
1217
- cmd = "convert -size %sx%s " % drawing.size
1218
- cmd += "%s %s" % (temp_png, img_filename)
1219
- print(commands.getoutput(cmd))
1220
-
1221
-
1222
-def save_svg(drawing, filename, width, height):
1223
- """Render drawing to an SVG file.
1224
- """
1225
- surface = get_surface(width, height, 'svg', filename)
1226
- context = cairo.Context(surface)
1227
- render(drawing, context, width, height)
1228
- context.show_page()
1229
- surface.finish()
1230
- print("Saved SVG to %s" % filename)
1231
-
1232
-
1233
-def save_pdf(drawing, filename, width, height):
1234
- """Render drawing to a PDF file.
1235
- """
1236
- surface = get_surface(width, height, 'pdf', filename)
1237
- context = cairo.Context(surface)
1238
- render(drawing, context, width, height)
1239
- context.show_page()
1240
- surface.finish()
1241
- print("Saved PDF to %s" % filename)
1242
-
1243
-
1244
-def save_ps(drawing, filename, width, height):
1245
- """Render drawing to a PostScript file.
1246
- """
1247
- surface = get_surface(width, height, 'ps', filename)
1248
- context = cairo.Context(surface)
1249
- render(drawing, context, width, height)
1250
- context.show_page()
1251
- surface.finish()
1252
- print("Saved PostScript to %s" % filename)
1253
-
1254
-
1255
-### --------------------------------------------------------------------
1256
-### Demo functions
1257
-### --------------------------------------------------------------------
1258
-def draw_fontsize_demo(drawing):
1259
- """Draw font size samples on the given drawing.
1260
- """
1261
- assert isinstance(drawing, Drawing)
1262
-
1263
- # Save context
1264
- drawing.save()
1265
- # TODO: Remove this scaling hack
1266
- drawing.scale(800.0/720, 600.0/480)
1267
-
1268
- # Draw white text in a range of sizes
1269
- drawing.set_source('white')
1270
-
1271
- for size in [12, 16, 20, 24, 28, 32]:
1272
- ypos = size * size / 5
1273
- drawing.font('Nimbus Sans')
1274
- drawing.font_size(size)
1275
- drawing.text("%s pt: The quick brown fox" % size, 700, ypos, 'right')
1276
-
1277
- # Restore context
1278
- drawing.restore()
1279
-
1280
-
1281
-def draw_font_demo(drawing):
1282
- """Draw samples of different fonts on the given drawing.
1283
- """
1284
- assert isinstance(drawing, Drawing)
1285
-
1286
- # Save context
1287
- drawing.save()
1288
- # TODO: Remove this scaling hack
1289
- drawing.scale(800.0/720, 600.0/480)
1290
-
1291
- fontsize = 24
1292
- drawing.font_size(fontsize)
1293
- fonts = [
1294
- 'Arial',
1295
- 'Baskerville',
1296
- 'Dragonwick',
1297
- 'Georgia',
1298
- 'Helvetica',
1299
- 'Linotext',
1300
- 'Luxi Mono',
1301
- 'Nimbus Sans',
1302
- 'Old-Town',
1303
- 'Sharktooth',
1304
- 'Tahoma',
1305
- 'Times']
1306
- ypos = 0
1307
- for font in fonts:
1308
- drawing.font(font)
1309
- # Transparent shadow
1310
- drawing.set_source('darkblue', 0.4)
1311
- drawing.text(font, 3, ypos+3)
1312
- # White text
1313
- drawing.set_source('white', 1.0)
1314
- drawing.text(font, 0, ypos)
1315
- ypos += fontsize
1316
-
1317
- # Restore context
1318
- drawing.restore()
1319
-
1320
-
1321
-def draw_shape_demo(drawing):
1322
- """Draw shape samples on the given drawing.
1323
- """
1324
- assert isinstance(drawing, Drawing)
1325
-
1326
- # Save context
1327
- drawing.save()
1328
- # TODO: Remove this scaling hack
1329
- drawing.scale(800.0/720, 600.0/480)
1330
-
1331
- # Large orange circle with black stroke
1332
- drawing.save()
1333
- drawing.stroke_width(12)
1334
- # Circle at (500, 200), with radius 200
1335
- drawing.circle(500, 200, 200)
1336
- drawing.stroke('black')
1337
- drawing.fill('orange')
1338
- drawing.restore()
1339
-
1340
- # Grey-stroked blue circles
1341
- drawing.save()
1342
- # TODO:
1343
- # All circles have the same stroke width and color (and, in other cases,
1344
- # might all have the same fill style as well). A simpler interface is
1345
- # called for, e.g.:
1346
- # drawing.set_style(fill='#8080FF', stroke='#777', stroke_width=2)
1347
- # drawing.circle((65, 50), 15)
1348
- # drawing.circle((65, 100), 10)
1349
- # drawing.circle((65, 150), 5)
1350
- # drawing.set_style(fill='black') # stroke stays the same as before
1351
- # drawing.rectangle((40, 30), (50, 150))
1352
-
1353
- drawing.stroke_width(2)
1354
- drawing.circle(65, 50, 15)
1355
- drawing.fill('#8080FF')
1356
- drawing.stroke('#777')
1357
-
1358
- drawing.circle(60, 100, 10)
1359
- drawing.fill('#2020F0')
1360
- drawing.stroke('#777')
1361
-
1362
- drawing.circle(55, 150, 5)
1363
- drawing.fill('#0000A0')
1364
- drawing.stroke('#777')
1365
- drawing.restore()
1366
-
1367
- # Semitransparent green rectangles
1368
- drawing.save()
1369
- drawing.translate(50, 400)
1370
- for scale in [0.2, 0.4, 0.7, 1.1, 1.6, 2.2, 2.9, 3.7]:
1371
- drawing.save()
1372
- drawing.translate(scale * 70, scale * -50)
1373
- drawing.scale(scale, scale)
1374
- drawing.stroke_width(scale)
1375
- # roundrectangle broken?
1376
- drawing.roundrectangle(-30, -30, 30, 30, 8, 8)
1377
- #drawing.rectangle(-30, -30, 30, 30)
1378
- drawing.fill('lightgreen', scale / 5.0)
1379
- drawing.stroke('black')
1380
- drawing.restore()
1381
- drawing.restore()
1382
-
1383
- # Restore context
1384
- drawing.restore()
1385
-
1386
-
1387
-def draw_stroke_demo(drawing):
1388
- """Draw a stroke/strokewidth demo on the given drawing.
1389
- """
1390
- assert isinstance(drawing, Drawing)
1391
-
1392
- # Save context
1393
- drawing.save()
1394
- # TODO: Remove this scaling hack
1395
- drawing.scale(800.0/720, 600.0/480)
1396
-
1397
- for width in [1, 2, 4, 6, 8, 10, 12, 14, 16]:
1398
- drawing.stroke_width(width)
1399
- rgb = ((255 - width * 8), (120 - width * 5), 0)
1400
- offset = width * 10
1401
- drawing.line(0, offset, -offset, offset)
1402
- drawing.stroke('rgb(%s,%s,%s)' % rgb)
1403
-
1404
- # Restore context
1405
- drawing.restore()
1406
-
1407
-
1408
-if __name__ == '__main__':
1409
- mytime = time.time() # Benchmark
1410
-
1411
- drawing = Drawing(800, 600)
1412
-
1413
- # Start a new
1414
- drawing.save()
1415
-
1416
- # Add a background fill
1417
- #->Background
1418
- drawing.set_source('darkgray')
1419
- drawing.rectangle(0, 0, 800, 600)
1420
- drawing.fill()
1421
-
1422
- # Shape demo
1423
- drawing.save()
1424
- draw_shape_demo(drawing)
1425
- drawing.restore()
1426
-
1427
- # Font size demo
1428
- drawing.save()
1429
- draw_fontsize_demo(drawing)
1430
- drawing.restore()
1431
-
1432
- # Stroke demo
1433
- drawing.save()
1434
- drawing.translate(680, 240)
1435
- draw_stroke_demo(drawing)
1436
- drawing.restore()
1437
-
1438
- # Font face demo
1439
- drawing.save()
1440
- drawing.translate(60, 160)
1441
- draw_font_demo(drawing)
1442
- drawing.restore()
1443
-
1444
- # Close out the Cairo rendering...
1445
- drawing.restore()
1446
-
1447
- print("Took %f seconds" % (time.time() - mytime))
1448
-
1449
- # Render and display the Drawing at several different sizes
1450
- resolutions = [(352, 240), (352, 480), (720, 480), (800, 600)]
1451
- #resolutions = [(720, 480)]
1452
- for w, h in resolutions:
1453
- display(drawing, w, h)
1454
-
1455
- #save_svg(drawing, "/tmp/drawing.svg", 400, 300)
1456
- #save_pdf(drawing, "/tmp/drawing.pdf", 400, 300)
1457
- #save_ps(drawing, "/tmp/drawing.ps", 400, 300)
1458
tovid-0.34.tar.bz2/libtovid/render/effect.py
Deleted
459
1
2
-"""This module defines classes for creating and drawing effects on a series
3
-of drawings (as in a Flipbook).
4
-
5
-Effect classes are arranged in a (currently) simple hierarchy::
6
-
7
- Effect (base class)
8
- Movement
9
- Translate
10
- Fade
11
- FadeInOut
12
- Colorfade
13
- Spectrum
14
- Scale
15
- Whirl
16
- PhotoZoom
17
- KeyFunction
18
-
19
-"""
20
-
21
-__all__ = [
22
- 'Effect',
23
- 'Movement',
24
- 'Translate',
25
- 'Fade',
26
- 'FadeInOut',
27
- 'Colorfade',
28
- 'Spectrum',
29
- 'Scale',
30
- 'Whirl',
31
- 'PhotoZoom',
32
- 'KeyFunction',
33
-]
34
-
35
-from libtovid.render.drawing import Drawing
36
-from libtovid.render.animation import Keyframe, Tween
37
-from random import randint
38
-
39
-class Effect:
40
- """A "special effect" created by keyframing a Cairo drawing command
41
- along the given frame interval.
42
- """
43
- def __init__(self, start, end):
44
- """Create an effect lasting from start frame to end frame.
45
- """
46
- self.start = start
47
- self.end = end
48
- # List of Keyframes
49
- self.keyframes = [Keyframe(self.start, 0), Keyframe(self.end, 0)]
50
- self.tween = Tween(self.keyframes)
51
-
52
- # Parents
53
- self._parent_flipbook = None
54
- self._parent_layer = None
55
-
56
-
57
- def init_parent_flipbook(self, fb):
58
- self._parent_flipbook = fb
59
-
60
-
61
- def init_parent_layer(self, layer):
62
- self._parent_layer = layer
63
-
64
-
65
- def pre_draw(self, drawing, frame):
66
- """Set up effect elements that must be applied before drawing a Layer.
67
-
68
- drawing
69
- The Drawing to apply effects to
70
- frame
71
- The frame for which to render the effect
72
-
73
- Extend this function in derived classes.
74
- """
75
- drawing.save()
76
-
77
-
78
- def post_draw(self, drawing, frame):
79
- """Finalize effect elements after a Layer is drawn.
80
-
81
- drawing
82
- The Drawing to apply effects to
83
- frame
84
- The frame for which to render the effect
85
-
86
- Extend this function in derived classes.
87
- """
88
- drawing.restore()
89
-
90
-
91
-# New Effect template
92
-#
93
-# Copy and paste this code to create your own Effect
94
-#
95
-# The first line defines your effect's name. (Effect) means it inherits from
96
-# the base Effect class, and shares some properties with it.
97
-
98
-class MyEffect (Effect):
99
- """Modify this documentation string to describe what your effect does.
100
- """
101
- # The __init__ function is called whenever a MyEffect is created. Make
102
- # sure your __init__ takes start and end arguments; additional arguments
103
- # (such as start_val and end_val below) allow someone using your effect
104
- # class to customize its behavior in some way. See the other effects below
105
- # for examples.
106
- def __init__(self, start, end, start_val, end_val):
107
- """Create a MyEffect lasting from start to end frame.
108
- """
109
- # Be sure to call this first-thing:
110
- Effect.__init__(self, start, end)
111
- # It initializes the base Effect class with start and end frames.
112
-
113
- # Next, define any keyframes your effect needs to use. This
114
- # effect just varies something from start_val to end_val:
115
- self.keyframes = [
116
- Keyframe(start, start_val),
117
- Keyframe(end, end_val)
118
- ]
119
-
120
- # Call this afterwards, to calculate the values at all frames
121
- self.tween = Tween(self.keyframes)
122
-
123
- def draw(self, drawing, frame):
124
- """Undocumented"""
125
- # Example function that can be called when drawing a layer.
126
- # The Layer must know that his particular effect requires the
127
- # calling of this function, or to add special parameters, or to
128
- # draw between items in the layer.
129
-
130
- # First, it's good to make sure we really have a Drawing class
131
- assert isinstance(drawing, Drawing)
132
-
133
- # This effect varies the stroke width across a sequence of frames.
134
- # Replace 'stroke_width' with your own drawing function(s)
135
- drawing.stroke_width(self.tween[frame])
136
-
137
- # Effect rendering occurs in two phases: pre_draw and post_draw.
138
- # These functions are already defined in the Effect base class; extend
139
- # them to do your effect rendering.
140
- def pre_draw(self, drawing, frame):
141
- """Do preliminary effect rendering."""
142
- # Always call the base class pre_draw first:
143
- Effect.pre_draw(self, drawing, frame)
144
-
145
- # This effect varies the stroke width across a sequence of frames.
146
- # Replace 'stroke_width' with your own drawing function(s)
147
- drawing.stroke_width(self.tween[frame])
148
-
149
- # Extend post_draw to do any post-rendering cleanup you need to do. Most
150
- # of the time, you won't need to extend this, but if you do, be sure to
151
- # call the base class post_draw at the end:
152
- def post_draw(self, drawing, frame):
153
- """Do post-drawing cleanup."""
154
- # Post-drawing cleanup here
155
- Effect.post_draw(self, drawing, frame)
156
-
157
-
158
-class Movement (Effect):
159
- """A movement effect, from one point to another."""
160
- def __init__(self, start, end, (x0, y0), (x1, y1)):
161
- """Move from start (x0, y0) to end (x1, y1).
162
- """
163
- Effect.__init__(self, start, end)
164
- self.keyframes = [
165
- Keyframe(start, (x0, y0)),
166
- Keyframe(end, (x1, y1))
167
- ]
168
- self.tween = Tween(self.keyframes)
169
-
170
- def pre_draw(self, drawing, frame):
171
- drawing.save()
172
- drawing.translate(*self.tween[frame])
173
-
174
- def post_draw(self, drawing, frame):
175
- drawing.restore()
176
-
177
-class Translate (Movement):
178
- """Translates the layer to some relative (x,y) coordinates
179
- """
180
- def __init__(self, start, end, (dx, dy)):
181
- Movement.__init__(self, start, end, (0, 0), (dx, dy))
182
-
183
-
184
-class Fade (Effect):
185
- """A generic fade effect, varying the opacity of a layer.
186
- """
187
- def __init__(self, keyframes, method='linear'):
188
- """Fade in from start, for fade_length frames; hold at full
189
- opacity, then fade out for fade_length frames before end.
190
-
191
- fade_length
192
- Number of frames to fade-in from start, and number of
193
- frames to fade-out before end. Everything in-between
194
- is at full opacity.
195
- keyframes
196
- A set of Keyframe() objects, determining the fading
197
- curve. Values of the Keyframe() must be floats ranging
198
- from 0.0 to 1.0 (setting opacity).
199
- method
200
- 'linear' or 'cosine' interpolation
201
-
202
- """
203
- # A fill-opacity curve, something like:
204
- # ______ 100%
205
- # / \
206
- # start./ \.end 0%
207
- #
208
- if isinstance(keyframes, list):
209
- if not isinstance(keyframes[0], Keyframe):
210
- raise ValueError, "Must be a list of Keyframe objects"
211
- self.keyframes = keyframes
212
- else:
213
- raise ValueError, "List of Keyframe objects required"
214
-
215
- self.tween = Tween(self.keyframes, method)
216
-
217
-
218
- def pre_draw(self, drawing, frame):
219
- """Called before drawing on a layer.
220
- """
221
- drawing.push_group()
222
-
223
-
224
- def post_draw(self, drawing, frame):
225
- """Called after drawing on a layer.
226
- """
227
- assert isinstance(drawing, Drawing)
228
- drawing.pop_group_to_source()
229
- drawing.paint_with_alpha(self.tween[frame])
230
-
231
-class FadeInOut (Fade):
232
- def __init__(self, start, end, fade_length=30):
233
- """Fade in from start, for fade_length frames; hold at full
234
- opacity, then fade out for fade_length frames before end.
235
-
236
- fade_length
237
- Number of frames to fade-in from start, and number of
238
- frames to fade-out before end. Everything in-between
239
- is at full opacity.
240
- """
241
- # A fill-opacity curve, something like:
242
- # ______ 100%
243
- # / \
244
- # start./ \.end 0%
245
- #
246
- self.keyframes = [
247
- Keyframe(start, 0.0), # Start fading in
248
- Keyframe(start + fade_length, 1.0), # Fade-in done
249
- Keyframe(end - fade_length, 1.0), # Start fading out
250
- Keyframe(end, 0.0) # Fade-out done
251
- ]
252
-
253
- self.tween = Tween(self.keyframes)
254
-
255
-class Colorfade (Effect):
256
- """A color-slide effect between an arbitrary number of RGB colors.
257
- """
258
- def __init__(self, start, end, (r0, g0, b0), (r1, g1, b1)):
259
- """Fade between the given RGB colors."""
260
- Effect.__init__(self, start, end)
261
- self.keyframes = [
262
- Keyframe(start, (r0, g0, b0)),
263
- Keyframe(end, (r1, g1, b1))
264
- ]
265
- self.tween = Tween(self.keyframes)
266
-
267
-
268
- def pre_draw(self, drawing, frame):
269
- """Set source color"""
270
- drawing.set_source(self.tween[frame])
271
-
272
-
273
- def post_draw(self, drawing, frame):
274
- pass
275
-
276
-
277
-class Spectrum (Effect):
278
- """A full-spectrum color-fade effect between start and end frames.
279
- """
280
- def __init__(self, start, end):
281
- Effect.__init__(self, start, end)
282
- step = (end - start) / 6
283
- self.keyframes = [
284
- Keyframe(start, (1.0, 0, 0)),
285
- Keyframe(start + step, (1.0, 0, 1.0)),
286
- Keyframe(start + step*2, (0, 0, 1.0)),
287
- Keyframe(start + step*3, (0, 1.0, 1.0)),
288
- Keyframe(start + step*4, (0, 1.0, 0)),
289
- Keyframe(start + step*5, (1.0, 1.0, 0)),
290
- Keyframe(end, (1.0, 0, 0))
291
- ]
292
- self.tween = Tween(self.keyframes)
293
-
294
-
295
- def pre_draw(self, drawing, frame):
296
- drawing.set_source(self.tween[frame])
297
-
298
-
299
- def post_draw(self, drawing, frame):
300
- pass
301
-
302
-class Scale (Effect):
303
- """A Scaling effect, from one size to another.
304
- """
305
- def __init__(self, start, end, (w0, h0), (w1, h1)):
306
- Effect.__init__(self, start, end)
307
- self.keyframes = [
308
- Keyframe(start, (w0, h0)),
309
- Keyframe(end, (w1, h1))
310
- ]
311
- self.tween = Tween(self.keyframes)
312
-
313
-
314
- def pre_draw(self, drawing, frame):
315
- drawing.save()
316
- drawing.scale(self.tween[frame])
317
-
318
-
319
- def post_draw(self, drawing, frame):
320
- drawing.restore()
321
-
322
-class Whirl (Effect):
323
- """Rotates an object a number of times.
324
- """
325
- def __init__(self, keyframes, center=(0, 0), method='linear', units='deg'):
326
- """Create a Whirl effect
327
-
328
- method
329
- 'linear' or 'cosine', for passing from one angle to another
330
- units
331
- 'deg' or 'rad', the unit used in the Keyframes
332
- """
333
- if units != 'deg' and units != 'rad':
334
- raise ValueError, "units must be 'rad' (radians) or 'deg' (degrees)"
335
- self.units = units
336
-
337
- if not isinstance(center, tuple):
338
- raise ValueError, "center must be a two-value tuple"
339
- self.center = center
340
-
341
- self.keyframes = keyframes
342
- self.tween = Tween(self.keyframes, method)
343
-
344
-
345
- def pre_draw(self, drawing, frame):
346
- drawing.save()
347
- # how to center the thing ? so you give a rotation point ?
348
- drawing.translate(*self.center)
349
- if self.units is 'deg':
350
- drawing.rotate_deg(self.tween[frame])
351
- elif self.units is 'rad':
352
- drawing.rotate_rad(self.tween[frame])
353
-
354
-
355
- def post_draw(self, drawing, frame):
356
- drawing.translate(- self.center[0], - self.center[1])
357
- drawing.restore()
358
-
359
-class PhotoZoom (Effect):
360
- """Zoom in and create dynamism by moving a picture.
361
-
362
- Normally applies to an Image layer, but can be used with others.
363
- """
364
- def __init__(self, keyframes, subject=(0, 0), direction=None,
365
- movement=50, method='linear'):
366
- """Create a PhotoZoom effect
367
-
368
- keyframes
369
- 0.0 for beginning of effect, and 1.0 to reach the end,
370
- intermediate values show the intermediate state of the effect.
371
- subject
372
- Position of the subject of interest. That is the point where
373
- the zoom in/out will focus it's attention.
374
- If (0, 0), the focus will be chosen randomly in the 2/3 of
375
- the center of the screen.
376
- direction
377
- 'in', 'out', None (random)
378
- movement
379
- 0 to 100, percentage of movement to create.
380
- method
381
- 'linear' or 'cosine'
382
- """
383
- if direction not in ['in', 'out', None]:
384
- raise ValueError, "'direction' must be 'in', 'out' or None"
385
- if (direction == None):
386
- self.direction = randint(0, 1) and 'in' or 'out'
387
- else:
388
- self.direction = direction
389
-
390
- print("Zoom in direction: %s" % self.direction)
391
-
392
- self.subject = subject
393
-
394
- self.movement = movement
395
-
396
- self.keyframes = keyframes
397
- self.tween = Tween(self.keyframes, method)
398
-
399
-
400
- def pre_draw(self, drawing, frame):
401
- drawing.save()
402
-
403
- fb = self._parent_flipbook
404
- # Use subject, or randomize in the center 1/3 of the image.
405
- if (self.subject == (0, 0)):
406
- self.subject = (randint(int(0.33 * fb.w),
407
- int(0.66 * fb.w)),
408
- randint(int(0.33 * fb.h),
409
- int(0.66 * fb.h)))
410
-
411
- # Max moving = 25% * pixels estimation * movement factor
412
- zoomfactor = 0.25 * (self.movement / 100.)
413
-
414
- inter = self.tween[frame]
415
-
416
- if (self.direction == 'in'):
417
- gozoom = 1.0 + (1.0 - inter) * zoomfactor
418
- else:
419
- gozoom = 1.0 + inter * zoomfactor
420
-
421
- drawing.scale_centered(self.subject[0], self.subject[1],
422
- gozoom, gozoom)
423
-
424
-
425
- def post_draw(self, drawing, frame):
426
- drawing.restore()
427
-
428
-class KeyFunction (Effect):
429
- """A keyframed effect on an arbitrary Drawing function.
430
- """
431
- def __init__(self, draw_function, keyframes, method='linear'):
432
- """Create an effect using the given Drawing function, with values
433
- determined by the given list of Keyframes. For example::
434
-
435
- KeyFunction(Drawing.stroke_width,
436
- [Keyframe(1, 1), Keyframe(30, 12)])
437
-
438
- This says to vary the stroke width from 1 (at frame 1) to 12 (at
439
- frame 30).
440
-
441
- The 'method' argument defines an interpolation method to use between
442
- keyframes, and may be either 'linear' or 'cosine'.
443
- """
444
- # Call base constructor with start and end frames
445
- Effect.__init__(self, keyframes[0].frame, keyframes[-1].frame)
446
- # TODO: Make sure a valid function name is given
447
- self.draw_function = draw_function
448
- self.keyframes = keyframes
449
- # Tween keyframes using the given interpolation method
450
- self.tween = Tween(self.keyframes, method)
451
-
452
- def pre_draw(self, drawing, frame):
453
- drawing.save()
454
- self.draw_function(drawing, self.tween[frame])
455
-
456
- def post_draw(self, drawing, frame):
457
- drawing.restore()
458
-
459
tovid-0.34.tar.bz2/libtovid/render/flipbook.py
Deleted
430
1
2
-"""This module provides the Flipbook class, a collection of drawings that, when
3
-displayed in sequence, make up an animation or video.
4
-
5
-Run this module standalone for a demonstration:
6
-
7
- $ python flipbook.py
8
-
9
-To use this module interactively, run 'python' from the command-line, and do:
10
-
11
- >>> from libtovid.render.flipbook import Flipbook
12
-
13
-To create a Flipbook 10 seconds long with 'dvd' and 'ntsc' standards, do:
14
-
15
- >>> flipbook = Flipbook(10, 'dvd', 'ntsc', '4:3')
16
-
17
-You can retrieve the canvas width and height with:
18
-
19
- >>> flipbook.canvas
20
- (640, 480)
21
- >>> flipbook.w
22
- 640
23
- >>> flipbook.h
24
- 480
25
-
26
-All drawing upon a Flipbook is achieved through the use of layers (layer.py).
27
-To use them, import the layer module:
28
-
29
- >>> from libtovid.render import layer
30
-
31
-You can add layers to a Flipbook on-the-fly:
32
-
33
- >>> flipbook.add(layer.Background('black'))
34
- >>> flipbook.add(layer.Text("Hello, world"))
35
-
36
-Or, create layers separately before adding them to the Flipbook:
37
-
38
- >>> text = Text("Elephant talk")
39
- >>> flipbook.add(text)
40
-
41
-This latter approach is useful if you plan to apply animation effects to the
42
-Layer. For this, effects classes (effect.py) may be applied. First, import:
43
-
44
- >>> from libtovid.render import effect
45
-
46
-Now, say we want the text "Elephant talk" to move across the screen, say from
47
-(100, 100) to (500, 100) over the course of the first 90 frames. The
48
-effect.Movement class does the trick:
49
-
50
- >>> text.add_effect(effect.Movement(1, 90, (100, 100), (500, 100)))
51
-
52
-You can preview a specific frame of the Flipbook by calling render():
53
-
54
- >>> flipbook.render(50)
55
-
56
-Or, you can generate all frames and create an .m2v video stream file by calling
57
-render_video():
58
-
59
- >>> filename = flipbook.render_video()
60
-
61
-See the demo below for more on what's possible with Flipbooks.
62
-"""
63
-
64
-__all__ = ['Flipbook']
65
-
66
-import os
67
-import sys
68
-import time
69
-import math
70
-import cairo
71
-import shutil
72
-import random
73
-from libtovid.render.animation import Keyframe
74
-from libtovid.render.drawing import Drawing, interlace_drawings
75
-from libtovid.render.drawing import write_ppm, write_png, save_png
76
-from libtovid.render import layer, effect
77
-from libtovid import standard
78
-from libtovid.media import MediaFile
79
-from libtovid.backend import mplex, mplayer, ffmpeg
80
-
81
-
82
-class Flipbook:
83
- """A collection of Drawings that together comprise an animation.
84
- """
85
- def __init__(self, seconds, format, tvsys, aspect='4:3', interlaced=False):
86
- """Create a flipbook of the given length in seconds, at the given
87
- resolution.
88
-
89
- seconds
90
- Length of flipbook playback in seconds
91
- format
92
- 'dvd', 'vcd', 'svcd', 'dvd-vcd', or 'half-dvd'
93
- tvsys
94
- 'ntsc' or 'pal'
95
- aspect
96
- '4:3' or '16:9' (the latter only for format='dvd')
97
- interlaced
98
- True/False. When enabled, the framerate will be doubled,
99
- but only half the frames (twice the fields) will be rendered.
100
-
101
- Once you've created the Flipbook, you can grab the dimensions
102
- in with the property:
103
-
104
- flipbook.canvas as (width, height)
105
-
106
- and with the two properties:
107
-
108
- flipbook.w (width)
109
- flipbook.h (height)
110
- """
111
- self.tmpdir = '/tmp'
112
- if 'TMPDIR' in os.environ:
113
- self.tmpdir = os.environ['TMPDIR']
114
- self.seconds = float(seconds)
115
- self.fps = standard.fps(tvsys)
116
- self.fps_ratio = standard.fps_ratio(tvsys)
117
- if (interlaced):
118
- self.fps *= 2
119
- self.interlaced = interlaced
120
- self.frames = int(seconds * self.fps)
121
- self.output_size = standard.resolution(format, tvsys)
122
- # TODO: We'll need aspect ratio here.. 4:3 or 16:9 anamorphic ?
123
- self.format = format
124
- self.tvsys = tvsys
125
- if (aspect not in ['4:3', '16:9']):
126
- raise ValueError, "aspect must be: '4:3' or '16:9'"
127
- self.aspect = aspect
128
- self.widescreen = False
129
- if (aspect == '16:9'):
130
- self.widescreen = True
131
-
132
- self.canvas = self.get_canvas_size()
133
- self.w = self.canvas[0]
134
- self.h = self.canvas[1]
135
-
136
- # Empty layers, and currently no drawings.
137
- self.layers = []
138
- self.drawings = []
139
-
140
- self.called_init_childs = False
141
-
142
-
143
- def init_childs(self):
144
- """Give access to all descendant layers and effects to their parents.
145
-
146
- In layers, you can access your parent layer (if sublayed) with:
147
- layer._parent_layer
148
- and to the top Flipbook object with:
149
- layer._parent_flipbook
150
-
151
- This function gets called just before rendering a video with
152
- render_video()
153
-
154
- It's also called in emergency if you call directly get_drawing().
155
- """
156
- for x in range(0, len(self.layers)):
157
- self.layers[x][0].init_parent_flipbook(self)
158
- self.layers[x][0].init_childs()
159
-
160
- self.called_init_childs = True
161
-
162
-
163
- def stof(self, seconds):
164
- """Return the number of frames to the specified time (in seconds).
165
- """
166
- return int(self.fps * float(seconds))
167
-
168
-
169
- def get_canvas_size(self):
170
- """Return the dimensions of the canvas.
171
- """
172
- #ow = self.output_size[0]
173
- oh = self.output_size[1]
174
- a = self.aspect.split(':')
175
-
176
- # Calculate the square pixels canvas size based on aspect ratio
177
- # and intended output size.
178
- x = float(a[0]) * float(oh) / float(a[1])
179
- # Make sure they are factor of '2'
180
- nw = int(math.ceil(x / 2.0) * 2)
181
-
182
- # We'll always change only the width, like it seems the standard,
183
- # since on TVs, the number of *lines* can't change (when interlacing
184
- # is into business)
185
- return (nw, oh)
186
-
187
-
188
- def add(self, layer, position=(0, 0)):
189
- """Add a Layer to the flipbook.
190
- """
191
- self.layers.append((layer, position))
192
-
193
-
194
- def render(self, frame=1):
195
- """Render the given frame.
196
- """
197
- print("DEPRECATED FUNCTION.")
198
- exit()
199
-
200
- filename = "/tmp/flipbook_%s.png" % frame
201
- print("Rendering Flipbook frame %s to %s" % (frame, filename))
202
- drawing = self.get_drawing(frame)
203
-
204
- save_png(drawing, filename, self.output_size[0], self.output_size[1])
205
-
206
-
207
- def get_drawing(self, frame):
208
- """Get a Drawing of the given frame
209
-
210
- TODO: 0-based or 1-based ?
211
- """
212
-
213
- # Make sure all layers and effects has been initialized with parents.
214
- if (not self.called_init_childs):
215
- self.init_childs()
216
-
217
- drawing = Drawing(self.canvas[0], self.canvas[1])
218
- # Draw each layer
219
- for layer, position in self.layers:
220
- drawing.save()
221
- drawing.translate(position[0], position[1])
222
- # Apply effects and draw
223
- layer.draw_with_effects(drawing, frame)
224
- drawing.restore()
225
- return drawing
226
-
227
-
228
- def render_video(self, out_filename=None):
229
- """Render the flipbook to an .m2v video stream file.
230
-
231
- out_filename
232
- Filename for output. If not specified, a temporary filename
233
- will be given, and returned from the function.
234
-
235
- Return the filename of the output, in both cases.
236
- """
237
- # Make sure layers and effects have been initialized with parents.
238
- self.init_childs()
239
-
240
- #
241
- # if self.tmpdir = /tmp, we get:
242
- # /tmp
243
- # /tmp/flipbook-120391232-work/
244
- # /tmp/flipbook-120391232-work/bunch-of-files..m2v, .ac3, etc.
245
- # /tmp/flipbook-120391232.mpg -> final output..
246
- #
247
-
248
- tmp_prefix = ''
249
- tmp_workdir = ''
250
- while 1:
251
- rnd = random.randint(1000000, 9999999)
252
- tmp_prefix = "%s/flipbook-%s" % (self.tmpdir, rnd)
253
- tmp_workdir = "%s-work" % (tmp_prefix)
254
-
255
- if not os.path.exists(tmp_workdir):
256
- break
257
-
258
- # In case no filename has been specified.
259
- if not out_filename:
260
- out_filename = "%s.mpg" % tmp_workdir
261
-
262
- os.mkdir(tmp_workdir)
263
-
264
- # Encode the frames to an .m2v file
265
- m2v_file = "%s/video.m2v" % tmp_workdir
266
- ac3_file = "%s/audio.ac3" % tmp_workdir
267
-
268
-
269
- try:
270
- #cairo.ImageSurface.get_data
271
- pngorpnm = 'ppmtoy4m -F %s -A %s -Ip -B -S 420mpeg2' % \
272
- (self.fps_ratio, self.aspect)
273
- _write_img = write_ppm # set write function just below
274
- except:
275
- pngorpnm = 'ppmtoy4m -F %s -A %s -Ip -S 420mpeg2' % \
276
- (self.fps_ratio, self.aspect)
277
- _write_img = write_png
278
-
279
- # Cinelerra params: -b 0 -q 5 -a 2 -F 4 -I 0 -M 2 -f 8 -R 0
280
- # TODO: move this to encode.py
281
- # -M (multi-threading, num CPUs)
282
- #
283
- # -b 0 -q 5
284
- # or
285
- # -b 7500
286
- pipe = os.popen("%s | mpeg2enc -q 5 -g 45 -G 45 -f 8 -a 2 -I 0 "
287
- "-o '%s'" % (pngorpnm, m2v_file), 'w')
288
-
289
- frame = 1
290
- while frame <= self.frames:
291
- print("Drawing frame %s of %s" % (frame, self.frames))
292
-
293
- if (self.interlaced):
294
- draw1 = self.get_drawing(frame)
295
- frame += 1
296
- draw2 = self.get_drawing(frame)
297
-
298
- drawing = interlace_drawings(draw1, draw2)
299
- else:
300
- drawing = self.get_drawing(frame)
301
-
302
- # jpeg2yuv likes frames to start at 0
303
- _write_img(drawing, pipe,
304
- self.output_size[0], self.output_size[1],
305
- tmp_workdir)
306
-
307
- frame += 1
308
-
309
- print("Closing encoder. Output to %s" % out_filename)
310
- pipe.close()
311
-
312
- print("Waiting for encoder to finish...")
313
- time.sleep(0.5)
314
-
315
- os.system("ls -al %s" % m2v_file)
316
- os.system("cp %s /tmp/go.m2v" % m2v_file)
317
- vidonly = mplayer.identify(m2v_file)
318
-
319
- # Fix length
320
- vidonly.length = float(self.seconds)
321
-
322
- outvid = MediaFile(out_filename, self.format, self.tvsys)
323
- outvid.aspect = self.aspect
324
- # Important to render 16:9 video correctly.
325
- outvid.widescreen = self.widescreen
326
-
327
- print("Running audio encoder...")
328
- ffmpeg.encode_audio(vidonly, ac3_file, outvid)
329
-
330
- print("Mplex...")
331
- mplex.mux(m2v_file, ac3_file, outvid)
332
-
333
- # Clean up
334
- print("Cleaning up %s ..." % tmp_workdir)
335
- shutil.rmtree(tmp_workdir)
336
-
337
- print("Output: %s" % out_filename)
338
- return out_filename
339
-
340
-
341
-def draw_text_demo(flipbook):
342
- """Draw a demonstration of Text layers with various effects.
343
- """
344
- assert isinstance(flipbook, Flipbook)
345
-
346
- last_frame = flipbook.frames
347
-
348
- # Background image
349
- bgd = layer.Background('black')
350
- flipbook.add(bgd)
351
-
352
- text1 = layer.Text(u"Spectrum effect demo", color=None)
353
- text1.add_effect(effect.Spectrum(1, last_frame))
354
- flipbook.add(text1, (20, 30))
355
-
356
- #text2 = layer.Text(u"FadeInOut effect demo")
357
- #text2.add_effect(effect.FadeInOut(1, last_frame, last_frame / 4))
358
- #flipbook.add(text2, (20, 60))
359
-
360
- text3 = layer.Text(u"Movement effect demo")
361
- text3.add_effect(effect.Movement(1, last_frame, (0, 0), (300, 50)))
362
- flipbook.add(text3, (20, 90))
363
-
364
- text4 = layer.Text(u"Whirl effect demo", color=None, align='center')
365
- k = [Keyframe(0, 0),
366
- Keyframe(30, 0),
367
- Keyframe(40, 15),
368
- Keyframe(45, -10),
369
- Keyframe(50, 10),
370
- Keyframe(55, -2),
371
- Keyframe(60, 0)]
372
- text4.add_effect(effect.Whirl(k, center=(25, 10), units='deg'))
373
- text4.add_effect(effect.Colorfade(1, last_frame, (1.0, 0, 0), (0, 1.0, 0)))
374
- flipbook.add(text4, (340, 350))
375
-
376
- text5 = layer.Text(u'Whirl effect demo2 ', color='white', align="center")
377
- k2 = [Keyframe(0, 0),
378
- Keyframe(last_frame, 720)]
379
- text5.add_effect(effect.Whirl(k2, center=(25, 10), units='deg'))
380
- flipbook.add(text5, (450, 400))
381
-
382
- # Keyframed opacity demos, using both linear and cosine interpolation
383
- pulse = [Keyframe(1, 0.2),
384
- Keyframe(last_frame * 2/10, 1.0),
385
- Keyframe(last_frame * 4/10, 0.2),
386
- Keyframe(last_frame * 6/10, 1.0),
387
- Keyframe(last_frame * 8/10, 0.5),
388
- Keyframe(last_frame, 1.0)]
389
- # Text Layers
390
- text_linear = layer.Text("Keyframed opacity (linear)", color='lightgreen')
391
- text_cosine = layer.Text("Keyframed opacity (cosine)", color='lightgreen')
392
- # Effects
393
- eff_linear = effect.Fade(pulse, 'linear')
394
- eff_cosine = effect.Fade(pulse, 'cosine')
395
- # Graph of the keyframe effects
396
- graph_linear = layer.InterpolationGraph(pulse, method='linear')
397
- graph_cosine = layer.InterpolationGraph(pulse, method='cosine')
398
- # Add effects to the text layers
399
- text_linear.add_effect(eff_linear)
400
- text_cosine.add_effect(eff_cosine)
401
- # Add layers to the flipbook
402
- flipbook.add(text_linear, (20, 150))
403
- flipbook.add(graph_linear, (20, 180))
404
- flipbook.add(text_cosine, (340, 150))
405
- flipbook.add(graph_cosine, (340, 180))
406
-
407
-
408
-if __name__ == '__main__':
409
- start_time = time.time() # Benchmark
410
-
411
- if len(sys.argv) > 1:
412
- seconds = int(sys.argv[1])
413
- else:
414
- seconds = 3
415
- flip = Flipbook(seconds, 'dvd', 'ntsc')
416
-
417
- draw_text_demo(flip)
418
-
419
- # Video clip
420
- #clip = layer.VideoClip(video, (320, 240))
421
- #clip.rip_frames(0, 90)
422
- #clip.effects.append(effect.Fade(1, 90, 20))
423
- #flip.add(clip, (260, 200))
424
-
425
- # Render the final video
426
- filename = flip.render_video('/tmp/flipbook.mpg')
427
-
428
- print("Took %f seconds to render: %s" % (time.time() - start_time, filename))
429
-
430
tovid-0.34.tar.bz2/libtovid/render/layer.py
Deleted
900
1
2
-"""This module provides a Layer class and several derivatives. A Layer
3
-is a graphical overlay that may be composited onto an image canvas.
4
-
5
-Run this script standalone for a demonstration:
6
-
7
- $ python libtovid/layer.py
8
-
9
-Layer subclasses may combine graphical elements, including other Layers,
10
-into a single interface for drawing and customizing those elements. Layers may
11
-exhibit animation, through the use of keyframed drawing commands, or through
12
-use of the Effect class (and its subclasses, as defined in libtovid/effect.py).
13
-
14
-Each Layer subclass provides (at least) an __init__ function, and a draw
15
-function. For more on how to use Layers, see the Layer class definition and
16
-template example below.
17
-"""
18
-
19
-__all__ = [
20
- 'Layer',
21
- 'Background',
22
- 'Text',
23
- 'ShadedText',
24
- 'Label',
25
- 'VideoClip',
26
- 'Image',
27
- 'Thumb',
28
- 'ThumbGrid',
29
- 'SafeArea',
30
- 'Scatterplot',
31
- 'InterpolationGraph',
32
- 'ColorBars',
33
-]
34
-
35
-import os
36
-import sys
37
-import math
38
-import commands
39
-from libtovid.util import get_file_type
40
-from libtovid.render.drawing import Drawing, save_image
41
-from libtovid.render.effect import Effect
42
-from libtovid.render.animation import Keyframe, Tween
43
-from libtovid.media import MediaFile
44
-from libtovid.backend import transcode
45
-from libtovid import log
46
-
47
-class Layer:
48
- """A visual element, or a composition of visual elements. Conceptually
49
- similar to a layer in the GIMP or Photoshop, with support for animation
50
- effects and sub-Layers.
51
- """
52
- def __init__(self):
53
- """Initialize the layer. Extend this in derived classes to accept
54
- configuration settings for drawing the layer; call this function
55
- from any derived __init__ functions.
56
- """
57
- self.effects = []
58
- self.sublayers = []
59
- self._parent_flipbook = None
60
- self._parent_layer = None
61
-
62
- ###
63
- ### Child-parent initialization
64
- ###
65
- def init_childs(self):
66
- """Give access to all descendant layers and effects to their parents.
67
-
68
- In layers, you can access your parent layer (if sublayed) with:
69
- layer._parent_layer
70
- and to the top Flipbook object with:
71
- layer._parent_flipbook
72
- """
73
- for x in range(0, len(self.effects)):
74
- self.effects[x].init_parent_flipbook(self._parent_flipbook)
75
- self.effects[x].init_parent_layer(self)
76
- for x in range(0, len(self.sublayers)):
77
- self.sublayers[x][0].init_parent_flipbook(self._parent_flipbook)
78
- self.sublayers[x][0].init_parent_layer(self)
79
- self.sublayers[x][0].init_childs(self)
80
-
81
- def init_parent_flipbook(self, flipbook):
82
- self._parent_flipbook = flipbook
83
-
84
- def init_parent_layer(self, layer):
85
- self._parent_layer = layer
86
-
87
-
88
- ###
89
- ### Derived-class interface
90
- ###
91
-
92
- def draw(self, drawing, frame):
93
- """Draw the layer and all sublayers onto the given Drawing. Override
94
- this function in derived layers.
95
- """
96
- assert isinstance(drawing, Drawing)
97
-
98
- ###
99
- ### Sublayer and effect interface
100
- ###
101
-
102
- def add_sublayer(self, layer, position=(0, 0)):
103
- """Add the given Layer as a sublayer of this one, at the given position.
104
- Sublayers are drawn in the order they are added; each sublayer may have
105
- its own effects, but the parent Layer's effects apply to all sublayers.
106
- """
107
- assert isinstance(layer, Layer)
108
- self.sublayers.append((layer, position))
109
-
110
- def draw_sublayers(self, drawing, frame):
111
- """Draw all sublayers onto the given Drawing for the given frame.
112
- """
113
- assert isinstance(drawing, Drawing)
114
- for sublayer, position in self.sublayers:
115
- drawing.save()
116
- drawing.translate(*position)
117
- sublayer.draw(drawing, frame)
118
- drawing.restore()
119
-
120
- def add_effect(self, effect):
121
- """Add the given Effect to this Layer. A Layer may have multiple effects
122
- applied to it; all effects apply to the current layer, and all sublayers.
123
- """
124
- assert isinstance(effect, Effect)
125
- self.effects.append(effect)
126
-
127
- def draw_with_effects(self, drawing, frame):
128
- """Render the entire layer, with all effects applied.
129
-
130
- drawing: A Drawing object to draw the Layer on
131
- frame: The frame number that is being drawn
132
-
133
- """
134
- # Do preliminary effect rendering
135
- for effect in self.effects:
136
- effect.pre_draw(drawing, frame)
137
- # Draw the layer and sublayers
138
- self.draw(drawing, frame)
139
- # Close out effect rendering, in reverse (nested) order
140
- for effect in reversed(self.effects):
141
- effect.post_draw(drawing, frame)
142
-
143
-
144
-# Layer template
145
-#
146
-# Copy and paste the following code to create your own Layer.
147
-#
148
-# Layer subclasses should define two things:
149
-#
150
-# __init__(): How to initialize the layer with parameters
151
-# draw(): How do draw the layer on a Drawing
152
-#
153
-# First, declare the layer class name. Include (Layer) to indicate that your
154
-# class is a Layer.
155
-
156
-class MyLayer (Layer):
157
- """Overlapping semitransparent rectangles.
158
- (Modify this documentation string to describe what's in your layer)"""
159
- # Here's the class initialization function, __init__. Define here any
160
- # parameters that might be used to configure your layer's behavior or
161
- # appearance in some way (along with default values, if you like). Here,
162
- # we're allowing configuration of the fill and stroke colors, with default
163
- # values of 'blue' and 'black', respectively:
164
-
165
- def __init__(self, fill_color='blue', stroke_color='black'):
166
- """Create a MyLayer with the given fill and stroke colors."""
167
- # Initialize the base Layer class. Always do this.
168
- Layer.__init__(self)
169
- # Store the given colors, for later use
170
- self.fill_color = fill_color
171
- self.stroke_color = stroke_color
172
-
173
- # The draw() function is responsible for rendering the contents of the
174
- # layer onto a Drawing. It will use the configuration given to __init__
175
- # (in this case, fill and stroke colors) to render something onto a Drawing
176
- # associated with a particular frame number:
177
-
178
- def draw(self, drawing, frame):
179
- """Draw MyLayer contents onto the given drawing, at the given frame
180
- number."""
181
-
182
- # For safety's sake, make sure you really have a Drawing object:
183
- assert isinstance(drawing, Drawing)
184
-
185
- # Save the drawing context. This prevents any upcoming effects or
186
- # style changes from messing up surrounding layers in the Drawing.
187
- drawing.save()
188
-
189
- # Get a Cairo pattern source for the fill and stroke colors
190
- # (TODO: Make this easier, or use a simpler example)
191
- fc = drawing.create_source(self.fill_color, 0.6)
192
- sc = drawing.create_source(self.stroke_color)
193
-
194
- # And a stroke width of 1, say:
195
- drawing.stroke_width(1)
196
-
197
- # Now, draw something. Here, a couple of pretty semitransparent
198
- # rectangles, using the fill and stroke color patterns created earlier:
199
- drawing.rectangle(0, 0, 50, 20)
200
- drawing.fill(fc)
201
- drawing.stroke(sc)
202
- drawing.rectangle(15, 12, 45, 28)
203
- drawing.fill(fc)
204
- drawing.stroke(sc)
205
-
206
- # Be sure to restore the drawing context afterwards:
207
- drawing.restore()
208
-
209
-
210
-class Background (Layer):
211
- """A background that fills the frame with a solid color, or an image."""
212
- def __init__(self, color='black', filename=''):
213
- Layer.__init__(self)
214
- self.color = color
215
- self.filename = filename
216
-
217
- def draw(self, drawing, frame):
218
- assert isinstance(drawing, Drawing)
219
- log.debug("Drawing Background")
220
- width, height = drawing.size
221
- drawing.save()
222
- # Fill drawing with an image
223
- if self.filename is not '':
224
- drawing.image(0, 0, width, height, self.filename)
225
- # Fill drawing with a solid color
226
- elif self.color:
227
- drawing.rectangle(0, 0, width, height)
228
- drawing.fill(self.color)
229
- drawing.restore()
230
-
231
-
232
-class Image (Layer):
233
- """A rectangular image, scaled to the given size.
234
-
235
- image_source
236
- Can be anything Drawing::image() can accept.
237
- See documentation in render/drawing.py.
238
- """
239
- def __init__(self, image_source, (x, y), (width, height)):
240
- Layer.__init__(self)
241
- self.size = (width, height)
242
- self.image_source = image_source
243
- self.position = (x, y)
244
-
245
-
246
- def draw(self, drawing, frame=1):
247
- assert isinstance(drawing, Drawing)
248
- log.debug("Drawing Image")
249
- drawing.save()
250
- # Save the source for future calls to draw, so no further
251
- # processing will be necessary. And other effects can be done
252
- # without interferring with the original source.
253
- self.image_source = drawing.image(self.position[0], self.position[1],
254
- self.size[0], self.size[1],
255
- self.image_source)
256
- drawing.restore()
257
-
258
-
259
-class VideoClip (Layer):
260
- """A rectangular video clip, scaled to the given size.
261
-
262
- TODO: num_frames should accept a range [first, end], an int (1-INT) and
263
- rip frames accordingly. For now, it only accepts an INT for the range 1-INT
264
- """
265
- def __init__(self, filename, (width, height),
266
- position=(0, 0), num_frames=120):
267
- Layer.__init__(self)
268
- self.filename = filename
269
- self.mediafile = MediaFile(filename)
270
- self.size = (width, height)
271
- # List of filenames of individual frames
272
- self.frame_files = []
273
- # TODO: be able to change hardcoded default values
274
- self.rip_frames(1, num_frames)
275
- # Set (x,y) position
276
- assert(isinstance(position, tuple))
277
- self.position = position
278
-
279
- def rip_frames(self, start, end):
280
- """Rip frames from the video file, from start to end frames."""
281
- log.info("VideoClip: Ripping frames %s to %s" % (start, end))
282
- outdir = '/tmp/%s_frames' % self.filename
283
- self.frame_files = transcode.rip_frames(self.mediafile, outdir,
284
- [start, end])
285
-
286
- def draw(self, drawing, frame=1):
287
- """Draw ripped video frames to the given drawing. For now, it's
288
- necessary to call rip_frames() before calling this function.
289
-
290
- Video is looped.
291
- """
292
- assert isinstance(drawing, Drawing)
293
- log.debug("Drawing VideoClip")
294
- if len(self.frame_files) == 0:
295
- log.error("VideoClip: need to call rip_frames() before drawing.")
296
- sys.exit(1)
297
- drawing.save()
298
- # Loop frames (modular arithmetic)
299
- if frame >= len(self.frame_files):
300
- frame = frame % len(self.frame_files)
301
- filename = self.frame_files[frame-1]
302
- drawing.image(self.position, self.size, filename)
303
- drawing.restore()
304
-
305
-
306
-class Text (Layer):
307
- """A simple text string, with size, color and font.
308
- """
309
- def __init__(self, text, position=(0, 0), color='white', fontsize=20, \
310
- font='Helvetica', align='left'):
311
- """Create a Text layer.
312
-
313
- text
314
- UTF8 encoded string.
315
- """
316
- Layer.__init__(self)
317
- self.text = text
318
- self.color = color
319
- self.fontsize = fontsize
320
- self.font = font
321
- self.align = align
322
- # Set (x,y) position
323
- self.position = position
324
-
325
- # TODO: This is gonna be pretty broken...
326
- def extents(self, drawing):
327
- """Return the extents of the text as a (x0, y0, x1, y1) tuple.
328
- """
329
- assert isinstance(drawing, Drawing)
330
- drawing.save()
331
- drawing.font(self.font)
332
- drawing.font_size(self.fontsize)
333
- x_bearing, y_bearing, width, height, x_adv, y_adv = \
334
- drawing.text_extents(self.text)
335
- drawing.restore()
336
- # Add current layer's position to the (x,y) bearing of extents
337
- x0 = int(self.position[0] + x_bearing)
338
- y0 = int(self.position[1] + y_bearing)
339
- x1 = int(x0 + width)
340
- y1 = int(y0 + height)
341
- return (x0, y0, x1, y1)
342
-
343
- def draw(self, drawing, frame=1):
344
- assert isinstance(drawing, Drawing)
345
- log.debug("Drawing Text")
346
- # Drop in debugger
347
- drawing.save()
348
- drawing.font(self.font)
349
- drawing.font_size(self.fontsize)
350
- if self.color is not None:
351
- drawing.set_source(self.color)
352
- # TODO: DO something with the align !!
353
- drawing.text(self.text, self.position[0], self.position[1], self.align)
354
- drawing.restore()
355
-
356
-
357
-class ShadedText (Layer):
358
- """A simple text string, with size, color and font.
359
- """
360
- def __init__(self, text, position=(0, 0), offset=(5, 5),
361
- color='white', shade_color='gray', fontsize=20,
362
- font='Nimbus Sans', align='left'):
363
- Layer.__init__(self)
364
- shade_position = (position[0] + offset[0],
365
- position[1] + offset[1])
366
- self.under = Text(text, shade_position, shade_color,
367
- fontsize, font, align)
368
- self.over = Text(text, position, color, fontsize, font, align)
369
-
370
- def draw(self, drawing, frame=1):
371
- assert isinstance(drawing, Drawing)
372
- log.debug("Drawing Text")
373
- drawing.save()
374
- self.under.draw(drawing, frame)
375
- self.over.draw(drawing, frame)
376
- drawing.restore()
377
-
378
-
379
-class Label (Text):
380
- """A text string with a rectangular background.
381
-
382
- You can access Text's extents() function from within here too.
383
- """
384
- def __init__(self, text, position=(0, 0), color='white', bgcolor='#555',
385
- fontsize=20, font='NimbusSans'):
386
- Text.__init__(self, text, position, color, fontsize, font)
387
- self.bgcolor = bgcolor
388
- # Set (x,y) position
389
- assert(isinstance(position, tuple))
390
- self.position = position
391
-
392
- def draw(self, drawing, frame=1):
393
- assert isinstance(drawing, Drawing)
394
- log.debug("Drawing Label")
395
- #(dx, dy, w, h, ax, ay) = self.extents(drawing)
396
- (x0, y0, x1, y1) = self.extents(drawing)
397
- # Save context
398
- drawing.save()
399
-
400
- # Calculate rectangle dimensions from text size/length
401
- width = x1 - x0
402
- height = y1 - y0
403
- # Padding to use around text
404
- pad = self.fontsize / 3
405
- # Calculate start and end points of background rectangle
406
- start = (-pad, -height - pad)
407
- end = (width + pad, pad)
408
-
409
- # Draw a stroked round rectangle
410
- drawing.save()
411
- drawing.stroke_width(1)
412
- drawing.roundrectangle(start[0], start[1], end[0], end[1], pad, pad)
413
- drawing.stroke('black')
414
- drawing.fill(self.bgcolor, 0.3)
415
- drawing.restore()
416
-
417
- # Call base Text class to draw the text
418
- Text.draw(self, drawing, frame)
419
-
420
- # Restore context
421
- drawing.restore()
422
-
423
-
424
-class Thumb (Layer):
425
- """A thumbnail image or video.
426
- """
427
- def __init__(self, filename, (width, height), position=(0, 0), title=''):
428
- Layer.__init__(self)
429
- self.filename = filename
430
- self.size = (width, height)
431
- self.title = title or os.path.basename(filename)
432
- # Set (x,y) position
433
- assert(isinstance(position, tuple))
434
- self.position = position
435
-
436
- # Determine whether file is a video or image, and create the
437
- # appropriate sublayer
438
- filetype = get_file_type(filename)
439
- if filetype == 'video':
440
- self.add_sublayer(VideoClip(filename, self.size, self.position))
441
- elif filetype == 'image':
442
- self.add_sublayer(Image(filename, self.size, self.position))
443
- self.lbl = Label(self.title, fontsize=15)
444
- self.add_sublayer(self.lbl, self.position)
445
-
446
- def draw(self, drawing, frame=1):
447
- assert isinstance(drawing, Drawing)
448
- log.debug("Drawing Thumb")
449
- drawing.save()
450
- (x0, y0, x1, y1) = self.lbl.extents(drawing)
451
- drawing.translate(0, x1-x0)
452
- self.draw_sublayers(drawing, frame)
453
- drawing.restore()
454
-
455
-
456
-class ThumbGrid (Layer):
457
- """A rectangular array of thumbnail images or videos."""
458
- def __init__(self, files, titles=None, (width, height)=(600, 400),
459
- (columns, rows)=(0, 0), aspect=(4,3)):
460
- """Create a grid of thumbnail images or videos from a list of files,
461
- fitting in a space no larger than the given size, with the given number
462
- of columns and rows. Use 0 to auto-layout columns or rows, or both
463
- (default).
464
- """
465
- assert files != []
466
- if titles:
467
- assert len(files) == len(titles)
468
- else:
469
- titles = files
470
- Layer.__init__(self)
471
- self.size = (width, height)
472
- # Auto-dimension (using desired rows/columns, if given)
473
- self.columns, self.rows = \
474
- self._fit_items(len(files), columns, rows, aspect)
475
- # Calculate thumbnail size, keeping aspect
476
- w = (width - self.columns * 16) / self.columns
477
- h = w * aspect[1] / aspect[0]
478
- thumbsize = (w, h)
479
-
480
- # Calculate thumbnail positions
481
- positions = []
482
- for row in range(self.rows):
483
- for column in range(self.columns):
484
- x = column * (width / self.columns)
485
- y = row * (height / self.rows)
486
- positions.append((x, y))
487
-
488
- # Add Thumb sublayers
489
- for file, title, position in zip(files, titles, positions):
490
- title = os.path.basename(file)
491
- self.add_sublayer(Thumb(file, thumbsize, (0, 0), title), position)
492
-
493
- def _fit_items(self, num_items, columns, rows, aspect=(4, 3)):
494
- # Both fixed, nothing to calculate
495
- if columns > 0 and rows > 0:
496
- # Make sure num_items will fit (columns, rows)
497
- if num_items < columns * rows:
498
- return (columns, rows)
499
- # Not enough room; auto-dimension both
500
- else:
501
- log.warning("ThumbGrid: Can't fit %s items" % num_items +\
502
- " in (%s, %s) grid;" % (columns, rows) +\
503
- " doing auto-dimensioning instead.")
504
- columns = rows = 0
505
- # Auto-dimension to fit num_items
506
- if columns == 0 and rows == 0:
507
- # TODO: Take aspect ratio into consideration to find an optimal fit
508
- root = int(math.floor(math.sqrt(num_items)))
509
- return ((1 + num_items / root), root)
510
- # Rows fixed; use enough columns to fit num_items
511
- if columns == 0 and rows > 0:
512
- return ((1 + num_items / rows), rows)
513
- # Columns fixed; use enough rows to fit num_items
514
- if rows == 0 and columns > 0:
515
- return (columns, (1 + num_items / columns))
516
-
517
- def draw(self, drawing, frame=1):
518
- assert isinstance(drawing, Drawing)
519
- log.debug("Drawing ThumbGrid")
520
- drawing.save()
521
- self.draw_sublayers(drawing, frame)
522
- drawing.restore()
523
-
524
-
525
-class SafeArea (Layer):
526
- """Render a safe area box at a given percentage.
527
- """
528
- def __init__(self, percent, color):
529
- self.percent = percent
530
- self.color = color
531
-
532
- def draw(self, drawing, frame=1):
533
- assert isinstance(drawing, Drawing)
534
- log.debug("Drawing SafeArea")
535
- # Calculate rectangle dimensions
536
- scale = float(self.percent) / 100.0
537
- width, height = drawing.size
538
- topleft = ((1.0 - scale) * width / 2,
539
- (1.0 - scale) * height / 2)
540
- # Save context
541
- drawing.save()
542
- drawing.translate(topleft[0], topleft[1])
543
- # Safe area box
544
- drawing.stroke_width(3)
545
- drawing.rectangle(0, 0, width * scale, height * scale)
546
- drawing.stroke(self.color)
547
- # Label
548
- drawing.font_size(18)
549
- drawing.set_source(self.color)
550
- drawing.text(u"%s%%" % self.percent, 10, 20)
551
- # Restore context
552
- drawing.restore()
553
-
554
-
555
-class Scatterplot (Layer):
556
- """A 2D scatterplot of data.
557
- """
558
- def __init__(self, xy_dict, width=240, height=80, x_label='', y_label=''):
559
- """Create a scatterplot using data in xy_dict, a dictionary of
560
- lists of y-values, indexed by x-value.
561
- """
562
- self.xy_dict = xy_dict
563
- self.width, self.height = (width, height)
564
- self.x_label = x_label
565
- self.y_label = y_label
566
-
567
- def draw(self, drawing, frame):
568
- """Draw the scatterplot."""
569
- assert isinstance(drawing, Drawing)
570
- log.debug("Drawing Scatterplot")
571
- width, height = (self.width, self.height)
572
- x_vals = self.xy_dict.keys()
573
- max_y = 0
574
- for x in x_vals:
575
- largest = max(self.xy_dict[x] or [0])
576
- if largest > max_y:
577
- max_y = largest
578
- # For numeric x, scale by maximum x-value
579
- x_is_num = isinstance(x_vals[0], int) or isinstance(x_vals[0], float)
580
- if x_is_num:
581
- x_scale = float(width) / max(x_vals)
582
- # For string x, scale by number of x-values
583
- else:
584
- x_scale = float(width) / len(x_vals)
585
- # Scale y according to maximum value
586
- y_scale = float(height) / max_y
587
-
588
- # Save context
589
- drawing.save()
590
- drawing.rectangle(0, 0, width, height)
591
- drawing.fill('white', 0.75)
592
-
593
- # Draw axes
594
- #->comment("Axes of scatterplot")
595
- drawing.save()
596
- drawing.stroke_width(2)
597
- drawing.line(0, 0, 0, height)
598
- drawing.stroke('black')
599
- drawing.line(0, height, width, height)
600
- drawing.stroke('black')
601
- drawing.restore()
602
-
603
- # Axis labels
604
- drawing.save()
605
- drawing.set_source('blue')
606
-
607
- drawing.save()
608
- for i, x in enumerate(x_vals):
609
- drawing.save()
610
- if x_is_num:
611
- drawing.translate(x * x_scale, height + 15)
612
- else:
613
- drawing.translate(i * x_scale, height + 15)
614
- drawing.rotate(30)
615
- drawing.text(x, 0, 0)
616
- drawing.restore()
617
-
618
- drawing.font_size(20)
619
- drawing.text(self.x_label, width/2, height+40)
620
- drawing.restore()
621
-
622
- drawing.save()
623
- drawing.text(max_y, -30, 0)
624
- drawing.translate(-25, height/2)
625
- drawing.rotate(90)
626
- drawing.text(self.y_label, 0, 0)
627
- drawing.restore()
628
-
629
- drawing.restore()
630
-
631
- # Plot all y-values for each x (as small circles)
632
- #->comment("Scatterplot data")
633
- drawing.save()
634
- for i, x in enumerate(x_vals):
635
- if x_is_num:
636
- x_coord = x * x_scale
637
- else:
638
- x_coord = i * x_scale
639
- # Shift x over slightly
640
- x_coord += 10
641
- # Plot all y-values for this x
642
- for y in self.xy_dict[x]:
643
- y_coord = height - y * y_scale
644
- drawing.circle(x_coord, y_coord, 3)
645
- drawing.fill('red', 0.2)
646
- drawing.restore()
647
-
648
- # Restore context
649
- drawing.restore()
650
-
651
-
652
-class InterpolationGraph (Layer):
653
- # TODO: Support graphing of tuple data
654
- """A graph of an interpolation curve, defined by a list of Keyframes and
655
- an interpolation method.
656
- """
657
- def __init__(self, keyframes, size=(240, 80), method='linear'):
658
- """Create an interpolation graph of the given keyframes, at the given
659
- size, using the given interpolation method.
660
- """
661
- Layer.__init__(self)
662
-
663
- self.keyframes = keyframes
664
- self.size = size
665
- self.method = method
666
- # Interpolate keyframes
667
- self.tween = Tween(keyframes, method)
668
-
669
- def draw(self, drawing, frame):
670
- """Draw the interpolation graph, including frame/value axes,
671
- keyframes, and the interpolation curve."""
672
- assert isinstance(drawing, Drawing)
673
- log.debug("Drawing InterpolationGraph")
674
- data = self.tween.data
675
- # Calculate maximum extents of the graph
676
- width, height = self.size
677
- x_scale = float(width) / len(data)
678
- y_scale = float(height) / max(data)
679
-
680
- #->drawing.comment("InterpolationGraph Layer")
681
-
682
- # Save context
683
- drawing.save()
684
-
685
- # Draw axes
686
- #->drawing.comment("Axes of graph")
687
- drawing.save()
688
- drawing.stroke_width(3)
689
- drawing.polyline([(0, 0), (0, height), (width, height)], False)
690
- drawing.stroke('#ccc')
691
- drawing.restore()
692
-
693
- # Create a list of (x, y) points to be graphed
694
- curve = []
695
- x = 1
696
- while x <= len(self.tween.data):
697
- # y increases downwards; subtract from height to give a standard
698
- # Cartesian-oriented graph (so y increases upwards)
699
- point = (int(x * x_scale), int(height - data[x-1] * y_scale))
700
- curve.append(point)
701
- x += 1
702
- drawing.save()
703
- # Draw the curve
704
- drawing.stroke_width(2)
705
- drawing.polyline(curve, False)
706
- drawing.stroke('blue')
707
- drawing.restore()
708
-
709
- # Draw Keyframes as dotted vertical lines
710
- drawing.save()
711
- # Vertical dotted lines
712
- drawing.set_source('red')
713
- drawing.stroke_width(2)
714
- for key in self.keyframes:
715
- x = int(key.frame * x_scale)
716
- drawing.line(x, 0, x, height)
717
- drawing.stroke('red')
718
-
719
- # Draw Keyframe labels
720
- drawing.set_source('white')
721
- for key in self.keyframes:
722
- x = int(key.frame * x_scale)
723
- y = int(height - key.data * y_scale - 3)
724
- drawing.text(u"(%s,%s)" % (key.frame, key.data), x, y)
725
-
726
- drawing.restore()
727
-
728
- # Draw a yellow dot for current frame
729
- #->drawing.comment("Current frame marker")
730
- drawing.save()
731
- pos = (frame * x_scale, height - data[frame-1] * y_scale)
732
- drawing.circle(pos[0], pos[1], 2)
733
- drawing.fill('yellow')
734
- drawing.restore()
735
-
736
- # Restore context
737
- drawing.restore()
738
-
739
-
740
-class ColorBars (Layer):
741
- """Standard SMPTE color bars
742
- (http://en.wikipedia.org/wiki/SMPTE_color_bars)
743
- """
744
- def __init__(self, size, position=(0, 0)):
745
- """Create color bars in a region of the given size and position.
746
- """
747
- Layer.__init__(self)
748
- self.size = size
749
- # Set (x,y) position
750
- assert(isinstance(position, tuple))
751
- self.position = position
752
-
753
- def draw(self, drawing, frame=1):
754
- assert isinstance(drawing, Drawing)
755
- log.debug("Drawing ColorBars")
756
- x, y = self.position
757
- width, height = self.size
758
-
759
- drawing.save()
760
- # Get to the right place and size
761
- drawing.translate(x, y)
762
- drawing.scale(width, height)
763
- # Video-black background
764
- drawing.rectangle(0, 0, 1, 1)
765
- drawing.fill('rgb(16, 16, 16)')
766
-
767
- # Top 67% of picture: Color bars at 75% amplitude
768
- top = 0
769
- bottom = 2.0 / 3
770
- seventh = 1.0 / 7
771
- size = (seventh, bottom)
772
- bars = [(0, top, seventh, bottom, 'rgb(191, 191, 191)'),
773
- (seventh, top, seventh, bottom, 'rgb(191, 191, 0)'),
774
- (2*seventh, top, seventh, bottom, 'rgb(0, 191, 191)'),
775
- (3*seventh, top, seventh, bottom, 'rgb(0, 191, 0)'),
776
- (4*seventh, top, seventh, bottom, 'rgb(191, 0, 191)'),
777
- (5*seventh, top, seventh, bottom, 'rgb(191, 0, 0)'),
778
- (6*seventh, top, seventh, bottom, 'rgb(0, 0, 191)')]
779
-
780
- # Next 8% of picture: Reverse blue bars
781
- top = bottom
782
- bottom = 0.75
783
- height = bottom - top
784
- bars.extend([(0, top, seventh, height, 'rgb(0, 0, 191)'),
785
- (seventh, top, seventh, height, 'rgb(16, 16, 16)'),
786
- (2*seventh, top, seventh, height, 'rgb(191, 0, 191)'),
787
- (3*seventh, top, seventh, height, 'rgb(16, 16, 16)'),
788
- (4*seventh, top, seventh, height, 'rgb(0, 191, 191)'),
789
- (5*seventh, top, seventh, height, 'rgb(16, 16, 16)'),
790
- (6*seventh, top, seventh, height, 'rgb(191, 191, 191)')])
791
-
792
- # Lower 25%: Pluge signal
793
- top = bottom
794
- bottom = 1.0
795
- sixth = 1.0 / 6
796
- height = bottom - top
797
- bars.extend([(0, top, 1.0, height, 'rgb(16, 16, 16)'),
798
- (0, top, sixth, height, 'rgb(0, 29, 66)'),
799
- (sixth, top, sixth, height, 'rgb(255, 255, 255)'),
800
- (2*sixth, top, sixth, height, 'rgb(44, 0, 92)'),
801
- # Sub- and super- black narrow bars
802
- (4*sixth, top, 0.33*sixth, height, 'rgb(7, 7, 7)'),
803
- (4.33*sixth, top, 0.33*sixth, height,'rgb(16, 16, 16)'),
804
- (4.66*sixth, top, 0.33*sixth, height, 'rgb(24, 24, 24)')])
805
-
806
- # Draw and fill all bars
807
- for x, y, width, height, color in bars:
808
- drawing.rectangle(x, y, width, height)
809
- drawing.fill(color)
810
-
811
- drawing.restore()
812
-
813
-
814
-
815
-
816
-if __name__ == '__main__':
817
- images = None
818
- # Get arguments, if any
819
- if len(sys.argv) > 1:
820
- # Use all args as image filenames to ThumbGrid
821
- images = sys.argv[1:]
822
-
823
- # A Drawing to render Layer demos to
824
- drawing = Drawing(800, 600)
825
-
826
- # Draw a background layer
827
- bgd = Background(color='#7080A0')
828
- bgd.draw(drawing, 1)
829
-
830
- # Draw color bars
831
- bars = ColorBars((320, 240), (400, 100))
832
- bars.draw(drawing, 1)
833
-
834
- # Draw a label
835
- drawing.save()
836
- drawing.translate(460, 200)
837
- label = Label("tovid loves Linux")
838
- label.draw(drawing, 1)
839
- drawing.restore()
840
-
841
- # Draw a text layer, with position.
842
- text = Text("Jackdaws love my big sphinx of quartz",
843
- (82, 62), '#bbb')
844
- text.draw(drawing, 1)
845
-
846
- # Draw a text layer
847
- drawing.save()
848
- drawing.translate(80, 60)
849
- text = Text("Jackdaws love my big sphinx of quartz")
850
- text.draw(drawing, 1)
851
- drawing.restore()
852
-
853
- # Draw a template layer (overlapping semitransparent rectangles)
854
- template = MyLayer('white', 'darkblue')
855
- # Scale and translate the layer before drawing it
856
- drawing.save()
857
- drawing.translate(50, 100)
858
- drawing.scale(3.0, 3.0)
859
- template.draw(drawing, 1)
860
- drawing.restore()
861
-
862
- # Draw a safe area test (experimental)
863
- safe = SafeArea(93, 'yellow')
864
- safe.draw(drawing, 1)
865
-
866
- # Draw a thumbnail grid (if images were provided)
867
- if images:
868
- drawing.save()
869
- drawing.translate(350, 300)
870
- thumbs = ThumbGrid(images, (320, 250))
871
- thumbs.draw(drawing, 1)
872
- drawing.restore()
873
-
874
- # Draw an interpolation graph
875
- drawing.save()
876
- drawing.translate(60, 400)
877
- # Some random keyframes to graph
878
- keys = [Keyframe(1, 25), Keyframe(10, 5), Keyframe(30, 35),
879
- Keyframe(40, 35), Keyframe(45, 20), Keyframe(60, 40)]
880
- interp = InterpolationGraph(keys, (400, 120), method="cosine")
881
- interp.draw(drawing, 25)
882
- drawing.restore()
883
-
884
- # Draw a scatterplot
885
- drawing.save()
886
- xy_data = {
887
- 5: [2, 4, 6, 8],
888
- 10: [3, 5, 7, 9],
889
- 15: [5, 9, 13, 17],
890
- 20: [8, 14, 20, 26]}
891
- drawing.translate(550, 350)
892
- #drawing.scale(200, 200)
893
- plot = Scatterplot(xy_data, 200, 200, "Spam", "Eggs")
894
- plot.draw(drawing, 1)
895
- drawing.restore()
896
-
897
- log.info("Output to /tmp/my.png")
898
- save_image(drawing, '/tmp/my.png', 800, 600)
899
-
900
tovid-0.34.tar.bz2/libtovid/runtest.py
Deleted
66
1
2
-# runtest.py
3
-
4
-"""libtovid test script
5
-
6
-Execute this script to run tests on the modules in libtovid. These tests
7
-consist of executing each libtovid module standalone; it is presumed that
8
-each module to be tested contains at least the following::
9
-
10
- import unittest
11
- if __name__ == '__main__':
12
- unittest.main()
13
-
14
-which runs unit tests, or::
15
-
16
- import doctest
17
- if __name__ == '__main__':
18
- doctest.testmod(verbose=True)
19
-
20
-which does an automated verification of the docstrings in each module.
21
-
22
-NB -- You're going to get lots of output, so a ``> log.txt`` is advised.
23
-"""
24
-
25
-import os
26
-import commands
27
-from glob import glob
28
-
29
-libtovid_modules = [
30
- 'author.py',
31
- 'cli.py',
32
- 'deps.py',
33
- 'encode.py',
34
- 'media.py',
35
- 'odict.py',
36
- 'opts.py',
37
- 'standard.py',
38
- 'stats.py',
39
- 'xml.py',
40
-]
41
-
42
-subdirs = [
43
- 'backend',
44
- 'metagui',
45
- 'render',
46
- 'template',
47
- 'test',
48
- 'util',
49
-]
50
-
51
-subdir_modules = []
52
-for subdir in subdirs:
53
- subdir_modules.extend(glob('%s/*.py' % subdir))
54
-
55
-all_modules = libtovid_modules + subdir_modules
56
-
57
-if __name__ == '__main__':
58
- # Execute each module
59
- for mod in all_modules:
60
- print("Testing: %s" % mod)
61
- try:
62
- print(commands.getoutput('python %s' % mod))
63
- except KeyboardInterrupt:
64
- print("Test interrupted.")
65
- exit()
66
tovid-0.34.tar.bz2/libtovid/standard.py
Deleted
149
1
2
-# standard.py
3
-
4
-"""This module defines functions for retrieving information about multimedia
5
-standards, including functions for determining the appropriate resolution,
6
-video and audio codec, fps, and bitrates for a given format.
7
-"""
8
-
9
-__all__ = [
10
- 'abitrate',
11
- 'acodec',
12
- 'fps',
13
- 'fps_ratio',
14
- 'resolution',
15
- 'samprate',
16
- 'vbitrate',
17
- 'vcodec',
18
-]
19
-
20
-def resolution(format, tvsys):
21
- """Return the pixel resolution (x,y) for the given format and TV system.
22
- For example::
23
-
24
- >>> resolution('dvd', 'pal')
25
- (720, 576)
26
- >>> resolution('half-dvd', 'ntsc')
27
- (352, 480)
28
- """
29
- # Valid resolutions, indexed by format and tvsys
30
- valid_size = {
31
- 'vcd':
32
- {'pal': (352, 288), 'ntsc': (352, 240)},
33
- 'dvd-vcd':
34
- {'pal': (352, 288), 'ntsc': (352, 240)},
35
- 'svcd':
36
- {'pal': (480, 576), 'ntsc': (480, 480)},
37
- 'half-dvd':
38
- {'pal': (352, 576), 'ntsc': (352, 480)},
39
- 'dvd':
40
- {'pal': (720, 576), 'ntsc': (720, 480)}
41
- }
42
- return valid_size[format][tvsys]
43
-
44
-
45
-def vcodec(format):
46
- """Return the video codec used by the given format.
47
- For example::
48
-
49
- >>> vcodec('vcd')
50
- 'mpeg1'
51
- >>> vcodec('svcd')
52
- 'mpeg2'
53
- """
54
- if format == 'vcd':
55
- return 'mpeg1'
56
- else:
57
- return 'mpeg2'
58
-
59
-
60
-def acodec(format):
61
- """Return the audio codec (or codecs) supported by the given format.
62
- For example::
63
-
64
- >>> acodec('vcd')
65
- 'mp2'
66
- >>> acodec('dvd')
67
- 'ac3'
68
- """
69
- if format in ['vcd', 'svcd']:
70
- return 'mp2'
71
- else:
72
- return 'ac3'
73
-
74
-
75
-def samprate(format):
76
- """Return the audio sampling rate used by the given format.
77
- """
78
- if format in ['vcd', 'svcd']:
79
- return 44100
80
- else:
81
- return 48000
82
-
83
-
84
-def fps(tvsys):
85
- """Return the number of frames per second for the given TV system.
86
- For example::
87
-
88
- >>> print(fps('ntsc'))
89
- 29.97
90
- >>> print(fps('pal'))
91
- 25.0
92
- """
93
- # Valid frames per second, by TV system
94
- _fps = {
95
- 'pal': 25.0,
96
- 'ntsc': 29.97,
97
- 'ntscfilm': 23.976,
98
- }
99
- return _fps[tvsys]
100
-
101
-
102
-def fps_ratio(tvsys):
103
- """Return the number of frames per second for the given TV system,
104
- in ratio form. For example::
105
-
106
- >>> fps_ratio('ntsc')
107
- '30000:1001'
108
- >>> fps_ratio('pal')
109
- '25:1'
110
- """
111
- # Valid frames per second, by TV system
112
- _fps = {
113
- 'pal': '25:1',
114
- 'ntsc': '30000:1001',
115
- 'ntscfilm': '24000:1001',
116
- }
117
- return _fps[tvsys]
118
-
119
-
120
-def vbitrate(format):
121
- """Return the range (min, max) of valid video bitrates (in kilobits per
122
- second) for the given format. min and max are the same for constant-bitrate
123
- formats.
124
- """
125
- # Valid video bitrates, indexed by format
126
- valid_bitrates = {
127
- 'vcd': (1150, 1150),
128
- 'svcd': (0, 2600),
129
- 'dvd-vcd': (0, 9800),
130
- 'half-dvd': (0, 9800),
131
- 'dvd': (0, 9800)
132
- }
133
- return valid_bitrates[format]
134
-
135
-
136
-def abitrate(format):
137
- """Return the range (min, max) of valid audio bitrates (in kilobits per
138
- second) for the given format. For constant-bitrate formats, min == max.
139
- """
140
- if format == 'vcd':
141
- return (224, 224)
142
- elif format == 'svcd':
143
- return (32, 384)
144
- else:
145
- return (32, 1536)
146
-
147
-
148
-
149
tovid-0.34.tar.bz2/libtovid/stats.py
Deleted
240
1
2
-# stats.py
3
-
4
-"""Classes and functions for dealing with tovid statistics.
5
-
6
-Future interface ideas:
7
-
8
-* Display certain records, or a range of records (records 1-10; last 15 records;
9
- records with a certain field (or any field) matching given text/regexp
10
-* Display formatted output of all records, or a selection of records,
11
- with control over which fields are displayed
12
-
13
-"""
14
-
15
-import csv
16
-import sys
17
-from copy import copy
18
-
19
-# Order of fields in stats.tovid
20
-FIELDS = [
21
- 'tovid_version',
22
- 'final_name',
23
- 'length', # a.k.a. CUR_LENGTH
24
- 'format', # RES
25
- 'tvsys',
26
- 'final_size',
27
- 'tgt_bitrate',
28
- 'avg_bitrate',
29
- 'peak_bitrate',
30
- 'gop_minsize',
31
- 'gop_maxsize',
32
- 'encoding_time', # SCRIPT_TOT_TIME
33
- 'cpu_model',
34
- 'cpu_speed',
35
- 'in_vcodec',
36
- 'in_acodec',
37
- 'encoding_mode',
38
- 'in_md5',
39
- 'in_width',
40
- 'in_height',
41
- 'quant',
42
- 'kbpm',
43
- 'enc_time_ratio',
44
- 'backend',
45
- ]
46
-
47
-# Integer numeric fields
48
-int_fields = [
49
- 'length',
50
- 'avg_bitrate',
51
- 'tgt_bitrate',
52
- 'peak_bitrate',
53
- 'encoding_time',
54
- 'final_size',
55
- 'cpu_speed',
56
- 'in_width',
57
- 'in_height',
58
- 'quant',
59
- 'kbpm',
60
- ]
61
-
62
-class Statlist:
63
- """A list of statistics that may be queried with a simple database-like
64
- interface."""
65
- def __init__(self, records=None, filename=''):
66
- """Create a Statlist, using the given list of records, or by reading
67
- from the given filename (CSV text).
68
- """
69
- # Use provided records, if any
70
- if records:
71
- self.records = copy(records)
72
- # Otherwise, read from any provided filename
73
- else:
74
- self.records = []
75
- if filename != '':
76
- self.read_csv(filename)
77
-
78
-
79
- def read_csv(self, filename):
80
- """Import stats from a CSV (comma-delimited quoted text) file."""
81
- self.records = []
82
- statfile = open(filename, 'r')
83
- csv_reader = csv.DictReader(statfile, FIELDS, skipinitialspace=True)
84
- for line in csv_reader:
85
- # Convert some string and numeric fields
86
- line['format'] = str.lower("%s" % line['format'])
87
- line['tvsys'] = str.lower("%s" % line['tvsys'])
88
- for field in int_fields:
89
- try:
90
- num = int("%s" % line[field])
91
- except (ValueError, TypeError):
92
- num = 0
93
- line[field] = num
94
- self.records.append(line)
95
-
96
- statfile.close()
97
- print("Read %s lines from %s" % (len(self.records), filename))
98
-
99
-
100
- def unique(self, field):
101
- """Return a list of unique values of the given field."""
102
- unique_values = []
103
- for record in self.records:
104
- if record[field] not in unique_values:
105
- unique_values.append(record[field])
106
- return unique_values
107
-
108
-
109
- def count_unique(self, field):
110
- """Count the occurrences of each unique value of the given field.
111
- Return a dictionary of unique values and the number of occurrences
112
- of each."""
113
- counts = {}
114
- # Go through all records and total up occurrences of each value
115
- for record in self.records:
116
- value = record[field]
117
- if value is None or value == '':
118
- pass
119
- elif value not in counts:
120
- counts[value] = 1
121
- else:
122
- counts[value] += 1
123
- return counts
124
-
125
-
126
- def average(self, attribute):
127
- """Calculate the average value for a given numeric VidStat attribute.
128
- For example, average('bitrate') returns the average overall bitrate of
129
- all videos in the list."""
130
- # Error if attribute is non-numeric
131
- if attribute not in int_fields:
132
- print("Can't average %s: not defined as a numeric field")
133
- sys.exit()
134
-
135
- values = []
136
- for record in self.records:
137
- # Only append non-zero values
138
- if record[attribute] != 0:
139
- values.append(record[attribute])
140
- if len(values) > 0:
141
- return float(sum(values) / len(values))
142
- else:
143
- return 0.0
144
-
145
-
146
- def average_by(self, attribute, by_attribute):
147
- """Return a dictionary of averages of an attribute, indexed by another
148
- attribute. For example, average_by('bitrate', 'format') returns average
149
- bitrates for each format."""
150
- # Error if attribute is non-numeric
151
- if attribute not in int_fields:
152
- print("Can't average %s: not defined as a numeric field")
153
- sys.exit()
154
-
155
- values_by = self.list_by(attribute, by_attribute)
156
- # Calculate averages for each value-list
157
- averages = {}
158
- if len(values_by) > 0:
159
- for key, samples in values_by.iteritems():
160
- try:
161
- averages[key] = float(sum(samples) / len(samples))
162
- except ZeroDivisionError:
163
- averages[key] = 0.0
164
- return averages
165
-
166
-
167
- def list_by(self, attribute, by_attribute, sort_lists=False):
168
- """Return a dictionary of lists of values of the given attribute,
169
- indexed by another attribute. If sort_lists is True, sort all lists."""
170
- # Create a dictionary of value-lists, indexed by by_attribute
171
- values_by = {}
172
- for record in self.records:
173
- byval = record[by_attribute]
174
- if not values_by.has_key(byval):
175
- values_by[byval] = []
176
- # Only include non-zero values
177
- if record[attribute] != 0:
178
- values_by[byval].append(record[attribute])
179
- if sort_lists:
180
- for index in values_by.iterkeys():
181
- values_by[index].sort()
182
- return values_by
183
-
184
-
185
- def get_matching(self, attribute, value):
186
- """Return a list of records where the given attribute equals the given
187
- value. Records are field-indexed dictionaries of values.
188
- """
189
- # List of matching records
190
- matches = []
191
- for record in self.records:
192
- if record[attribute] == value:
193
- matches.append(record)
194
- return matches
195
-
196
-
197
- def length(self, field):
198
- """Return the length of the longest record in the given field, or the
199
- width of the field name itself, whichever is greater."""
200
- longest = len(field)
201
- for record in self.records:
202
- cur_len = len(str(record[field]))
203
- if cur_len > longest:
204
- longest = cur_len
205
- return longest
206
-
207
-
208
- def show(self, show_records='all', show_fields='all'):
209
- """Print records matching given criteria, showing only the given fields.
210
-
211
- show_records
212
- Number of record to show, or range of numbers
213
- show_fields
214
- List of fields, by name as shown in FIELDS
215
- """
216
- # Remember field sizes (character widths)
217
- size = {}
218
- # Create field headings
219
- heading = ''
220
- if show_fields == 'all':
221
- show_fields = FIELDS
222
- for field in show_fields:
223
- if field in FIELDS:
224
- size[field] = self.length(field)
225
- heading += "%s " % str.ljust(field, size[field])
226
- else:
227
- print("Error: field '%s' does not exist" % field)
228
- sys.exit()
229
- print(heading)
230
- # Print fields from matching records
231
- for record in self.records:
232
- # TODO: support show_records
233
- line = ''
234
- for field in show_fields:
235
- line += "%s " % str.ljust(str(record[field]), size[field])
236
- print(line)
237
- # Print heading at end too
238
- print(heading)
239
-
240
tovid-0.34.tar.bz2/libtovid/xml.py
Deleted
140
1
2
-"""This module is for defining XML elements and attributes, and for creating
3
-element hierarchies.
4
-
5
-To create a new element, use the `Element` constructor, providing at
6
-least the element name::
7
-
8
- >>> video = Element('video')
9
-
10
-To see an XML representation of the Element::
11
-
12
- >>> print(video)
13
- <video></video>
14
-
15
-Since this is an empty element with no attributes yet, it's pretty boring.
16
-You can add or change attributes using the `~Element.set` method::
17
-
18
- >>> video.set(file="Brian.mpg")
19
- >>> print(video)
20
- <video file="Brian.mpg"></video>
21
-
22
-To add children to an element, use the `~Element.add` method::
23
-
24
- >>> length = video.add('length', '15')
25
- >>> print(video)
26
- <video file="Brian.mpg">
27
- <length>15</length>
28
- </video>
29
-
30
-See `libtovid.author` and `libtovid.backend.spumux` for additional
31
-examples.
32
-"""
33
-
34
-__all__ = ['Element']
35
-
36
-class Element (object):
37
- """A named XML element having optional content, attributes, and children.
38
-
39
- Attribute values may be set in the constructor, or by calling `set` with a
40
- dictionary and/or attribute=value keywords.
41
-
42
- Use `add` or `add_child` to create a hierarchy of Elements.
43
- """
44
- def __init__(self, name, content='', **attributes):
45
- """Create a new Element with the given attributes.
46
-
47
- name
48
- Name of the Element
49
- content
50
- Text content of the Element
51
- attributes
52
- Keyword=value for specific attributes
53
- """
54
- self.name = name
55
- self.content = content
56
- self.attributes = {}
57
- self.children = []
58
- # Set attributes from those provided
59
- self.set(**attributes)
60
-
61
-
62
- def set(self, **attributes):
63
- """Set values for one or more attributes.
64
-
65
- attributes
66
- Keyword arguments for setting specific attributes
67
-
68
- Underscores in attribute names are converted to hyphens. If you don't
69
- like this behavior, please suggest a workaround :-)
70
- """
71
- # Set attribute values; convert underscores to hyphens
72
- for key, value in attributes.iteritems():
73
- key = key.replace('_', '-')
74
- self.attributes[key] = value
75
-
76
-
77
- def add(self, child_name, content='', **attributes):
78
- """Create and add a new child Element by providing its name, content,
79
- and attributes. Return the newly-added Element.
80
-
81
- child
82
- String name of child element
83
- content
84
- String content of child element
85
- attributes
86
- Keyword arguments for setting child's attributes
87
-
88
- This is a convenience function for creating and adding children
89
- on-the-fly.
90
- """
91
- child = Element(child_name, content, **attributes)
92
- self.children.append(child)
93
- return child
94
-
95
-
96
- def add_child(self, element):
97
- """Add the given Element as a child of this Element.
98
- """
99
- assert isinstance(element, Element)
100
- self.children.append(element)
101
-
102
-
103
- def xml(self, indent_level=0):
104
- """Return formatted XML for this Element and all descendants.
105
- """
106
- indent = ' ' * indent_level
107
- # No children; write a single line
108
- if len(self.children) == 0:
109
- text = indent + self._open() + self.content + self._close() + '\n'
110
- # If children, write an indented block
111
- else:
112
- text = indent + self._open() + self.content + '\n'
113
- for child in self.children:
114
- text += child.xml(indent_level + 1)
115
- text += indent + self._close() + '\n'
116
- return text
117
-
118
-
119
- def __str__(self):
120
- """Return a string containing formatted XML for the Element.
121
- """
122
- return self.xml().rstrip('\n')
123
-
124
-
125
- def _open(self):
126
- """Return the XML opening tag for the Element.
127
- """
128
- attribs = ''
129
- for key, value in self.attributes.items():
130
- attribs += ' %s="%s"' % (key, value)
131
- return '<' + self.name + attribs + '>'
132
-
133
-
134
- def _close(self):
135
- """Return the XML closing tag for the Element.
136
- """
137
- return '</' + self.name + '>'
138
-
139
-
140
tovid-0.34.tar.bz2/src/make_titlesets
Deleted
261
1
2
-#!/bin/bash
3
-# Part of the tovid suite
4
-# =======================
5
-# A bash script that calls the tovid GUI in order to allow titlesets,
6
-# something the GUI is not capable of on its own at the moment.
7
-# This script depends on the GUI, in addition to the other command
8
-# line scripts of the tovid suite such as todisc, makempg, and idvid.
9
-#
10
-# Project homepage: http://tovid.wikia.com
11
-#
12
-# Copyright (C) 2005-2010
13
-#
14
-# This program is free software; you can redistribute it and/or
15
-# modify it under the terms of the GNU General Public License
16
-# as published by the Free Software Foundation; either
17
-# version 2 of the License, or (at your option) any later
18
-# version.
19
-#
20
-# This program is distributed in the hope that it will be useful,
21
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
-# GNU General Public License for more details.
24
-#
25
-# You should have received a copy of the GNU General Public License
26
-# along with this program; if not, write to the Free Software
27
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
28
-#
29
-# http://www.gnu.org/licenses/gpl.txt
30
-
31
-
32
-# Written by Robert ("grepper") Sohn
33
-# grepper at gmail dot com
34
-
35
-#############################################################################
36
-###############################Variables ####################################
37
-#############################################################################
38
-path=$(tovid -prefix)
39
-PATH=$path:$PATH
40
-SEP=$(for i in {1..79}; do printf '='; done)
41
-final_tmp_script=$(mktemp -t todisc.XXXXXXXX)
42
-final_script="$PWD/todisc_commands.bash"
43
-
44
-##############################################################################
45
-################################## Functions #################################
46
-##############################################################################
47
-# read_script name
48
-read_script()
49
-{
50
- script_exists=0
51
- script_name="$1"
52
- # if user just pressed enter, test that the default name exists (it should)
53
- if [[ -z $script_name ]]; then
54
- script_name="$final_script"
55
- [[ -e $script_name ]] && script_exists=1
56
- fi
57
- # else test if the file name path passed in exists
58
- while ! (( script_exists )); do
59
- read script_name
60
- script_name=$(readlink -f "$script_name")
61
- if [[ -e "$script_name" ]] ; then
62
- script_exists=1
63
- else
64
- echo "Sorry, $script_name does not point to an existing file."
65
- echo "Please re-enter the path to the script."
66
- echo "You can use the full path or the path relative to $PWD"
67
- fi
68
- done
69
- SCRIPT="$script_name"
70
-}
71
-
72
-run_gui()
73
-{
74
- todiscgui &>/dev/null &
75
- tovid_pid=$!
76
- sleep 2
77
- echo $SEP
78
- echo "Make your selections, then save your script and exit GUI to continue..."
79
- wait $tovid_pid
80
- echo $SEP
81
- echo "Press <ENTER> to accept the default path and filename "
82
- echo "for the file you just saved."
83
- echo "Or enter the relative or full path"
84
- echo "[${final_script}]"
85
- read script
86
- read_script "$script"
87
-
88
- todisc_tmp=$(mktemp todisc_tmpXXXXXX)
89
- mv "$SCRIPT" "$todisc_tmp"
90
- echo $SEP
91
- echo "Okay, the content is saved, please save to the same file next time."
92
- echo "Press <ENTER> to continue"
93
- read cont
94
-}
95
-
96
-# clean_script file
97
-clean_script()
98
-{
99
- file="$1"
100
- # remove shebang and PATH
101
- sed -i '/\#\!\/usr\/bin\/env bash/d;/PATH/d' "$file"
102
- # remove todisc command
103
- sed -i '/^todisc \\$/d' "$file"
104
- # remove opening blank lines
105
- sed -i '/./,/^$/!d' "$file"
106
-}
107
-
108
-##############################################################################
109
-############################ Main body starts here ###########################
110
-##############################################################################
111
-
112
-##############################################################################
113
-############################## General Options ###############################
114
-##############################################################################
115
-cat <<EOF
116
-
117
-$SEP
118
-We are going to create a complete DVD with titlesets and menus.
119
-
120
-I am going to start tovid gui. Please enter the general
121
-options there that you would like to apply to every titleset.
122
-"Output name" (bottom of main screen) is the only required general
123
-option. When you are done, press the 'Save script' button and save to
124
-"${final_script}"
125
-accepting the default filename and making sure you are
126
-in the correct directory. You must then close the GUI in order to continue.
127
-
128
-Press <ENTER> to continue...
129
-EOF
130
-read cont
131
-if [[ -e $final_script ]]; then
132
- new_name=$(TMPDIR=`pwd` mktemp -t todisc_commands.bash.XXXXXX)
133
- echo "The file we will use to save options: \"${final_script}\",
134
- exists in the current directory. It will be renamed:
135
- to $new_name if you continue." |sed 's/^[ \t]*//;s/[ \t]*$//'
136
- echo "press <ENTER> to continue..."
137
- read cont
138
-fi
139
-[[ -e "$final_script" ]] && mv "$final_script" "$new_name"
140
-
141
-run_gui
142
-##############################################################################
143
-################################# VMGM Menu ##################################
144
-##############################################################################
145
-
146
-####################### Titleset Titles for VMGM menu ########################
147
-cat <<EOF
148
-
149
-Now we will save options for your root (VMGM) menu
150
-The only option you really need is the titleset titles.
151
-Since you can not save titles in the GUI without loading videos
152
-you will need to enter them here.
153
-These titleset names will appear as menu titles for the respective menu
154
-in your DVD
155
-EOF
156
-echo $SEP
157
-echo "Press <ENTER> to continue..."
158
-read cont
159
-cat <<EOF
160
-
161
-Enter the names of your titlesets, one per line pressing <ENTER> each time.
162
-Do not use quotes unless you want them to appear literally in the title.
163
-Type "done" when you are finished.
164
-EOF
165
-
166
-done=0
167
-while ! ((done)); do
168
- read title
169
- if [[ $title == "done" ]]; then
170
- done=1
171
- else
172
- MENU_TITLES+=("$title")
173
- fi
174
-done
175
-# add backslash to last line; add -vmgm and -titles; add menu titles
176
-sed -i "\$s/$/ \\\/" "$todisc_tmp"
177
-sed -i '$ a -vmgm \\' "$todisc_tmp"
178
-sed -i '$ a -titles \\' "$todisc_tmp"
179
-printf '"%s" \\\n' "${MENU_TITLES[@]}" >> "$todisc_tmp"
180
-mv "$todisc_tmp" "$final_tmp_script"
181
-
182
-############################# VMGM Menu options ##############################
183
-cat <<EOF
184
-
185
-Now I will bring the GUI up again - enter options for your root
186
-(VMGM) menu.
187
-Remember that this menu (VMGM) does not need video files.
188
-You still have many options, but none are strictly necessary. For example
189
-you may wish to use background (audio and/or image/video), a
190
-showcased image/video, set the fonts, use a "Playall" button...
191
-You should also set the menu title to a new name. When you are done save
192
-the script again to
193
-$final_script
194
-and close the GUI to continue.
195
-EOF
196
-echo "Press <ENTER> to continue..."
197
-read cont
198
-run_gui
199
-clean_script "$todisc_tmp"
200
-# add backslash to last line
201
-sed -i "\$s/$/ \\\/" "$todisc_tmp"
202
-# add -end-vmgm as last line
203
-sed -i '$ a -end-vmgm \\' "$todisc_tmp"
204
-cat "$todisc_tmp" >> "$final_tmp_script"
205
-rm -f "$todisc_tmp"
206
-done=0
207
-
208
-##############################################################################
209
-################################## Titlesets #################################
210
-##############################################################################
211
-
212
-echo "Now finally we will make your titlesets"
213
-get_message()
214
-{
215
- message=$(
216
- cat <<EOF
217
-
218
-Bringing up the GUI for titleset $tset.
219
-Make your titleset, leaving out the general options you gave earlier
220
-unless you wish to change them (-out can not be changed).
221
-Press <ENTER> to continue or type "done" if you have no more titlesets
222
-EOF
223
- )
224
- echo "$message"
225
-}
226
-while ! ((done)); do
227
- ((tset++))
228
- get_message
229
- read title
230
- if [[ $title == "done" ]]; then
231
- done=1
232
- else
233
- run_gui
234
- clean_script "$todisc_tmp"
235
- # add backslash to last line of temp file
236
- sed -i "\$s/$/ \\\/" "$todisc_tmp"
237
- # add "-titleset \" as 1st line
238
- sed -i '1i -titleset \\' "$todisc_tmp"
239
- # add "-end-titleset" as last line
240
- sed -i '$a -end-titleset \\' "$todisc_tmp"
241
- # concatenate
242
- cat "$todisc_tmp" >> "$final_tmp_script"
243
- rm -f "$todisc_tmp"
244
- fi
245
-done
246
-
247
-###############################################################################
248
-############################## Run Final Script ###############################
249
-###############################################################################
250
-
251
-# remove backslash on last line
252
-sed -i "\$s/\\\//" "$final_tmp_script"
253
-echo $SEP
254
-mv "$final_tmp_script" "$final_script"
255
-echo final script is "$final_script"
256
-echo "Do you want to run it now?, type yes if you do, or press <ENTER> to leave"
257
-read answer
258
-if [[ $answer == "yes" ]]; then
259
- bash "$final_script"
260
-fi
261
tovid-0.34.tar.bz2/src/makemenu
Deleted
880
1
2
-#!/usr/bin/env bash
3
-ME="[makemenu]:"
4
-. tovid-init 2>/dev/null ||
5
-{ echo -e "===============================================================\n"
6
-echo -e "'tovid-init' not found. Was tovid improperly installed?"
7
-echo -e "Or are you trying to run the script directly?"
8
-echo -e "Please run makemenu as:\ntovid menu OPTIONS"
9
-exit 1 ; }
10
-
11
-# version $Id: makemenu 3336 2011-06-30 21:49:22Z grepper $
12
-# makemenu
13
-# Part of the tovid suite
14
-# =======================
15
-# A bash script for generating menus for use with DVD, VCD, or SVCD.
16
-# Given a background image and a list of titles, and an optional audio
17
-# file to use as background music, this script produces an MPEG video
18
-# displaying the specified text, with subtitle-multiplexed menu
19
-# highlights (for DVD) or enumerated titles (for (S)VCD).
20
-#
21
-# Project homepage: http://tovid.wikia.com
22
-#
23
-# Copyright (C) 2005-2010
24
-#
25
-# This program is free software; you can redistribute it and/or
26
-# modify it under the terms of the GNU General Public License
27
-# as published by the Free Software Foundation; either
28
-# version 2 of the License, or (at your option) any later
29
-# version.
30
-#
31
-# This program is distributed in the hope that it will be useful,
32
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
33
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
-# GNU General Public License for more details.
35
-#
36
-# You should have received a copy of the GNU General Public License
37
-# along with this program; if not, write to the Free Software
38
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
39
-#
40
-# http://www.gnu.org/licenses/gpl.txt
41
-
42
-# Options to consider
43
-# font selection
44
-# font color, highlight color, selection color
45
-# font shadow, border
46
-# icons, graphic overlays
47
-# Support for full-motion video menus
48
-
49
-SCRIPT_NAME=`cat << EOF
50
---------------------------------
51
-tovid menu
52
-Generate DVD/(S)VCD menus
53
-Version $TOVID_VERSION
54
-$TOVID_HOME_PAGE
55
---------------------------------
56
-EOF`
57
-
58
-USAGE=`cat << EOF
59
-Usage: tovid menu [OPTIONS] "Title1" "Title2" ... -out {output prefix}
60
-
61
-Common options:
62
-
63
- -pal | -ntsc | -ntscfilm Set TV standard
64
- -dvd | -vcd | -svcd Encode to standard format
65
- -background IMAGE ex: -background star_field.png
66
- -audio AUDIOFILE ex: -audio foo_fighters.mp3
67
- -font "FONTNAME" ex: -font Courier
68
-
69
-Example:
70
-
71
- tovid menu -background ocean.jpg "First" "Second" "Third" -out mymenu
72
- Create 'mymenu.mpg' with three titles and a custom background image.
73
-
74
-See the tovid manual page ('man tovid') for additional documentation.
75
-
76
-EOF`
77
-
78
-# Defaults and function definitions
79
-
80
-# Print script name, usage notes, and optional error message, then exit.
81
-# Args: $@ == text string containing error message
82
-usage_error ()
83
-{
84
- printf "%s\n" "$USAGE"
85
- printf "%s\n" "$SEPARATOR"
86
- printf "*** %s\n" "$@"
87
- exit 1
88
-}
89
-
90
-# Clean up the temporary files
91
-function cleanup()
92
-{
93
- if $DEBUG; then
94
- echo "Leaving temporary files in $TMP_DIR"
95
- echo "Debugging log saved to $LOG_FILE"
96
- else
97
- echo "Cleaning up... "
98
- rm -rf "$TMP_DIR"
99
- fi
100
-}
101
-
102
-# Initializations
103
-
104
-# No background image or audio
105
-BG_IMAGE=""
106
-BG_AUDIO=""
107
-MENU_LENGTH=""
108
-# NTSC DVD
109
-TVSYS="ntsc"
110
-RES="dvd"
111
-# Use a safe area
112
-SAFE_AREA=:
113
-# Number of titles
114
-NUM_TITLES=0
115
-MAX_VCD_TITLES=9
116
-MAX_DVD_TITLES=36
117
-OVER_MAX_TITLES=false
118
-# Scale up and crop non-4:3 images by default
119
-SCALECROP="crop"
120
-# Colors for menu items (RGB)
121
-TEXT_COLOR="white"
122
-HIGHLIGHT_COLOR="yellow"
123
-SELECT_COLOR="red"
124
-# Default title font and point size
125
-TITLE_FONT="Helvetica"
126
-TITLE_SIZE="24"
127
-FONT_DECO="-stroke black -strokewidth 1"
128
-TEXT_ALIGN="northwest"
129
-# Default menu title settings
130
-MAKE_TITLE=false
131
-# Button char
132
-BUTTON_FONT=""
133
-BUTTON_CHAR=">"
134
-BTN_STROKE="none"
135
-# NTSC DVD
136
-SAMPRATE="48000"
137
-ASUF="ac3"
138
-VSUF="m2v"
139
-FPS="2997"
140
-MPEG2ENC_FMT="-f 8"
141
-MPLEX_OPTS="-V"
142
-MPEG2ENC_SYS="-F 4 -n n"
143
-# Figure out what version of ppmtoy4m is in use;
144
-# mjpegtools 1.6.2 seems to require 420_mpeg2
145
-if mplex 2>&1 | grep -q "version 1.6.2"; then
146
- CHROMA_MODE="420_mpeg2"
147
-else
148
- CHROMA_MODE="420mpeg2"
149
-fi
150
-IM_VERSION=$(convert -list configure | awk '/LIB_VERSION_NUMBER/ {print $2}')
151
-if test_version $IM_VERSION 6.3.5.7; then
152
- IM_LISTARG='font'
153
-else
154
- IM_LISTARG='type'
155
-fi
156
-# imagemagick's font listing structure depends on version
157
-if test_version $IM_VERSION 6.4.0.0; then
158
- im_field=2
159
-else
160
- im_field=1
161
-fi
162
-PPM_OPTS="-S $CHROMA_MODE -A 10:11 -F 30000:1001"
163
-# Direct stuff to /dev/null
164
-REDIR="/dev/null"
165
-# Not doing debugging
166
-DEBUG=false
167
-QUIET=false
168
-# Don't overwrite output files
169
-OVERWRITE=false
170
-OUT_PREFIX=""
171
-LOG_FILE="makemenu.log"
172
-NOASK=false
173
-# How far to space titles and buttons
174
-TITLE_BOTTOM_SPACE=12
175
-TITLE_LEFT_SPACE=10
176
-
177
-
178
-# =========================================================================\
179
-# E X E C U T I O N B E G I N S H E R E
180
-#
181
-#
182
-
183
-echo "$SCRIPT_NAME"
184
-
185
-assert_dep "$magick" "You are missing dependencies required for making menus!"
186
-
187
-# Process all options
188
-while test $# -gt 0; do
189
- case "$1" in
190
- "-ntsc" | "-ntscfilm" )
191
- TVSYS="ntsc"
192
- MPEG2ENC_SYS="-F 4 -n n"
193
- PPM_OPTS="-S $CHROMA_MODE -A 10:11 -F 30000:1001"
194
- FPS="2997"
195
- ;;
196
- "-pal" )
197
- TVSYS="pal"
198
- MPEG2ENC_SYS="-F 3 -n p"
199
- PPM_OPTS="-S $CHROMA_MODE -A 59:54 -F 25:1"
200
- FPS="2500"
201
- ;;
202
- "-dvd" )
203
- RES="dvd"
204
- MPEG2ENC_FMT="-f 8"
205
- # Variable bitrate
206
- MPLEX_OPTS="-V"
207
- VSUF="m2v"
208
- ;;
209
- "-vcd" )
210
- RES="vcd"
211
- MPEG2ENC_FMT="-f 1"
212
- # Constant bitrate
213
- MPLEX_OPTS=""
214
- VSUF="m1v"
215
- ;;
216
- "-svcd" )
217
- RES="vcd"
218
- MPEG2ENC_FMT="-f 4"
219
- # Variable bitrate
220
- MPLEX_OPTS="-V"
221
- VSUF="m2v"
222
- ;;
223
- "-audio" )
224
- shift
225
- # Make sure file exists
226
- if test -f "$1"; then
227
- BG_AUDIO=$1
228
- else
229
- usage_error "Can't find background audio file: $1"
230
- fi
231
- ;;
232
- "-background" )
233
- shift
234
- # Make sure file exists
235
- if test -f "$1"; then
236
- BG_IMAGE=$1
237
- else
238
- usage_error "Can't find background image file: $1"
239
- fi
240
- ;;
241
- "-overwrite" ) OVERWRITE=: ;;
242
- "-crop" ) SCALECROP="crop" ;;
243
- "-scale" ) SCALECROP="scale" ;;
244
- "-nosafearea" ) SAFE_AREA=false ;;
245
- "-font" )
246
- shift
247
- TITLE_FONT="$1"
248
- ;;
249
- "-fontsize" )
250
- shift
251
- TITLE_SIZE="$1"
252
- ;;
253
- "-fontdeco" )
254
- shift
255
- FONT_DECO="$1"
256
- ;;
257
- "-textcolor" )
258
- shift
259
- TEXT_COLOR="$1"
260
- ;;
261
- "-highlightcolor" )
262
- shift
263
- HIGHLIGHT_COLOR="$1"
264
- ;;
265
- "-selectcolor" )
266
- shift
267
- SELECT_COLOR="$1"
268
- ;;
269
- "-align" )
270
- shift
271
- case "$1" in
272
- "left" ) TEXT_ALIGN="northwest" ;;
273
- "right" ) TEXT_ALIGN="northeast" ;;
274
- "center" ) TEXT_ALIGN="north" ;;
275
- "middle" ) TEXT_ALIGN="center" ;;
276
- * ) TEXT_ALIGN=$(echo "$1" | tr A-Z a-z)
277
- esac
278
- ;;
279
- "-button" )
280
- shift
281
- case "$1" in
282
- "play" )
283
- BUTTON_FONT="Webdings"
284
- BUTTON_CHAR=4
285
- ;;
286
- "movie" )
287
- BUTTON_FONT="Webdings"
288
- OFFICIAL_PRINTF=$(which printf)
289
- BUTTON_CHAR=$($OFFICIAL_PRINTF '\u00b8')
290
- ;;
291
- "utf8" )
292
- shift
293
- OFFICIAL_PRINTF=$(which printf)
294
- BUTTON_CHAR=$($OFFICIAL_PRINTF "\u$1")
295
- ;;
296
- * )
297
- BUTTON_CHAR="$1"
298
- if test $(echo -n "$BUTTON_CHAR" | wc -c ) -ne 1; then
299
- usage_error "Buttons must have only _one_ characater."
300
- fi
301
- ;;
302
- esac
303
- ;;
304
- "-debug" )
305
- DEBUG=:
306
- REDIR="$LOG_FILE"
307
- ;;
308
- "-quiet" )
309
- QUIET=:
310
- ;;
311
- "-out" )
312
- shift
313
- OUT_PREFIX="$1"
314
- ;;
315
- "-noask" ) NOASK=: ;;
316
- "-button-outline" )
317
- shift
318
- BTN_STROKE="$1"
319
- ;;
320
- "-button-font" )
321
- shift
322
- BUTTON_FONT="$1"
323
- ;;
324
- "-menu-title" )
325
- shift
326
- MENU_TITLE="$1"
327
- MAKE_TITLE=:
328
- ;;
329
- "-menu-title-fontsize" )
330
- shift
331
- MENU_TITLE_SIZE="$1"
332
- ;;
333
- "-length" )
334
- shift
335
- MENU_LENGTH="-t $1"
336
- ;;
337
- # Assume anything in quotes is a video title
338
- ""*"" )
339
- TITLES=("${TITLES[@]}" "$1")
340
- ;;
341
- * )
342
- test -n "$1" && usage_error "Unrecognized command-line option: $1"
343
- ;;
344
- esac
345
-
346
- # Get the next argument
347
- shift
348
-done
349
-
350
-NUM_TITLES=${#TITLES[@]}
351
-# If no titles were provided, exit with error
352
-if test $NUM_TITLES -eq 0; then
353
- usage_error "Please provide at least one title string, enclosed in double-quotes."
354
-fi
355
-
356
-# If output prefix was not provided, exit with error
357
-if test -z "$OUT_PREFIX"; then
358
- usage_error "Please provide an output prefix with the -out option."
359
-fi
360
-
361
-# Make sure we're not overwriting an existing menu
362
-if test -f "$OUT_PREFIX.mpg"; then
363
- if $OVERWRITE; then
364
- rm -f "$OUT_PREFIX.mpg"
365
- else
366
- echo "There is already a file named \"$OUT_PREFIX.mpg\" in this directory!"
367
- echo "Use '-overwrite' to replace this file. (tovid menu -overwrite ...)"
368
- echo "Exiting..."
369
- exit 1
370
- fi
371
-fi
372
-
373
-
374
-OUT_FILENAME="$OUT_PREFIX.mpg"
375
-# Temporary directory named after the given -out prefix
376
-OUTNAME=$(basename "$OUT_PREFIX")
377
-TMP_DIR=$(tempdir "$WORKING_DIR/$OUTNAME")
378
-$DEBUG && echo "Storing temporary files in $TMP_DIR"
379
-BG_CANVAS="$TMP_DIR/bg_canvas.png"
380
-MENU_PPM="$TMP_DIR/menu.ppm"
381
-MENU_MPEG="$TMP_DIR/menu.mpg"
382
-SPUMUX_XML="$TMP_DIR/menu_buttons.xml"
383
-
384
-SELECT_PNG="$TMP_DIR/select.png"
385
-HIGHLIGHT_PNG="$TMP_DIR/highlight.png"
386
-TILE_CANVAS="$TMP_DIR/00_tile_canvas.png"
387
-BUTTON_PAD="$TMP_DIR/00_button_pad.png"
388
-BUTTON_PLACEHOLDER="$TMP_DIR/00_button-placeholder.png"
389
-HIGHLIGHT_BUTTON="$TMP_DIR/00_highlight-button.png"
390
-SELECT_BUTTON="$TMP_DIR/00_select-button.png"
391
-HIGHLIGHT_TEXT="$TMP_DIR/02_highlight-text.png"
392
-MENU_TEXT="$TMP_DIR/02_menu-text.png"
393
-SAFETY_CANVAS="$TMP_DIR/02_safety-canvas.png"
394
-SELECT_TEXT="$TMP_DIR/02_select-text.png"
395
-ACTIVE_TEXT="$TMP_DIR/03_active-text.png"
396
-ACTIVE_HIGHLIGHT="$TMP_DIR/03_active-highlight.png"
397
-ACTIVE_SELECT="$TMP_DIR/03_active-select.png"
398
-MENU_TITLE_TEXT="$TMP_DIR/02_menu-title.png"
399
-MENU_TITLE_PLACEHOLDER="$TMP_DIR/02_menu-title-placeholder.png"
400
-
401
-# Use appropriate settings for DVD
402
-if test $RES = "dvd"; then
403
- assert_dep "$dvd" "You are missing dependencies required for making DVD menus!"
404
- WIDTH="720"
405
- SAMPRATE="48000"
406
- test $TVSYS = "ntsc" && HEIGHT="480"
407
- test $TVSYS = "pal" && HEIGHT="576"
408
-# And for (S)VCD
409
-else
410
- WIDTH="352"
411
- SAMPRATE="44100"
412
- test $TVSYS = "ntsc" && HEIGHT="240"
413
- test $TVSYS = "pal" && HEIGHT="288"
414
- # Reduce font size and spacing
415
- TITLE_SIZE=$(expr $TITLE_SIZE \/ 2)
416
-fi
417
-
418
-# Set audio stream format
419
-if test "$RES" = "dvd"; then
420
- ASUF="ac3"
421
-else
422
- ASUF="mp2"
423
-fi
424
-VIDEO_STREAM="$TMP_DIR/video.$VSUF"
425
-AUDIO_STREAM="$TMP_DIR/audio.$ASUF"
426
-
427
-# Make sure there are 9 or fewer titles for VCD and 36 or fewere for DVD
428
-if test "$RES" = "vcd" && test "$NUM_TITLES" -gt $MAX_VCD_TITLES; then
429
- OVER_MAX_TITLES=:
430
- DISC_TYPE="(S)VCD"
431
- MAX_TITLES=$MAX_VCD_TITLES
432
-elif test "$RES" = "dvd" && test "$NUM_TITLES" -gt $MAX_DVD_TITLES; then
433
- OVER_MAX_TITLES=:
434
- DISC_TYPE="DVD"
435
- MAX_TITLES=$MAX_DVD_TITLES
436
-fi
437
-if $OVER_MAX_TITLES; then
438
- echo $SEPARATOR
439
- echo "I read $NUM_TITLES titles for your $DISC_TYPE menu, which is more than the maximum number"
440
- echo "of titles allowed on one menu for ${DISC_TYPE}s ($MAX_TITLES is the limit)."
441
- echo "Please try using fewer titles on this menu."
442
- cleanup
443
- exit 1
444
-fi
445
-
446
-# Use a foreground canvas the size of the background minus safe area
447
-if $SAFE_AREA; then
448
- FG_WIDTH=$(expr $WIDTH \* 4 \/ 5)
449
- FG_HEIGHT=$(expr $HEIGHT \* 4 \/ 5)
450
-else
451
- FG_WIDTH=$(expr $WIDTH \- 10)
452
- FG_HEIGHT=$(expr $HEIGHT \- 10)
453
-fi
454
-
455
-# If no button font was given with -button-font, default to the title font
456
-if test -z "$BUTTON_FONT"; then
457
- BUTTON_FONT=$TITLE_FONT
458
-fi
459
-
460
-# Confirm the title font, or use a similar one
461
-if test -s "$TITLE_FONT"; then
462
- # Using ttf font file for ImageMagick
463
- USE_TITLE_FONT="$TITLE_FONT"
464
-else
465
- # Check to see if the given font name is available in ImageMagick
466
- # (only return the first exact match)
467
- USE_TITLE_FONT=$( convert -list $IM_LISTARG | \
468
- grep -m 1 "$TITLE_FONT" | awk -v f=$im_field '{print $f}' )
469
-
470
- # If not available, try to use something similar
471
- if test -z $USE_TITLE_FONT ; then
472
- echo $SEPARATOR
473
- echo "Font: \"$TITLE_FONT\" does not appear to be either a font file or registered with ImageMagick."
474
- USE_TITLE_FONT=$( convert -list $IM_LISTARG | \
475
- grep -i -m 1 "${TITLE_FONT:0:20}" | awk -v f=$im_field '{print $f}' )
476
-
477
- # If a similarly-named one does't exist, default to Helvetica
478
- if test -z "$USE_TITLE_FONT"; then
479
- echo "A similarly-named font was not found. Sorry!"
480
- USE_TITLE_FONT="Helvetica"
481
- fi
482
- echo "The font \"$USE_TITLE_FONT\" will be used instead."
483
- echo $SEPARATOR
484
- fi
485
-fi
486
-
487
-# Set the title font with the one that was found/compatible
488
-TITLE_FONT="$USE_TITLE_FONT"
489
-
490
-# Confirm the button font and button's existance in the font
491
-if test $RES = 'dvd'; then
492
- # Confirm the button font, or use a similar one
493
- if test -s "$BUTTON_FONT"; then
494
- # Using ttf font file for ImageMagick
495
- USE_BUTTON_FONT="$BUTTON_FONT"
496
- else
497
- # Check to see if the given button font is available in ImageMagick
498
- # (only return the first exact match)
499
- USE_BUTTON_FONT=$( convert -list $IM_LISTARG | \
500
- grep -m 1 "$BUTTON_FONT" | awk -v f=$im_field '{print $f}' )
501
-
502
- # If not available, try to use something similar
503
- if test -z $USE_BUTTON_FONT ; then
504
- echo $SEPARATOR
505
- echo "Button: \"$BUTTON_FONT\" does not appear to be either a font file or registered with ImageMagick."
506
- USE_BUTTON_FONT=$( convert -list $IM_LISTARG | \
507
- grep -i -m 1 "${BUTTON_FONT:0:20}" | awk -v f=$im_field '{print $f}' )
508
-
509
- # If a similarly-named one does't exist, default to Helvetica
510
- if test -z "$USE_BUTTON_FONT"; then
511
- echo "A similarly-named font was not found. Sorry!"
512
- USE_BUTTON_FONT="$TITLE_FONT"
513
- fi
514
- echo "The font \"$USE_BUTTON_FONT\" will be used instead."
515
- echo $SEPARATOR
516
- fi
517
- fi
518
-
519
-# Confirm that the button character exists in the font
520
- if convert -size 720x200 xc:none -fill white \
521
- -font $USE_BUTTON_FONT -pointsize $TITLE_SIZE -weight bold \
522
- +antialias -annotate +20+80 "$BUTTON_CHAR" -trim +repage \
523
- -bordercolor none -border 10 info: >> /dev/null 2>&1; then :
524
- else
525
- echo $SEPARATOR
526
- echo "The button \"$BUTTON_CHAR\" doesn't exist in \"$USE_BUTTON_FONT\""
527
- USE_BUTTON_FONT="$TITLE_FONT"
528
- echo "The font \"$USE_BUTTON_FONT\" will be used instead."
529
- echo $SEPARATOR
530
- fi
531
-fi
532
-
533
-# Set the button font with the one that was found/compatible
534
-BUTTON_FONT="$USE_BUTTON_FONT"
535
-
536
-# ==========================================================================\
537
-# M E N U D R A W I N G
538
-#
539
-#
540
-
541
-# Measure the font's vertical height
542
-TILE_HEIGHT=$(convert -format %h -size 720x200 xc:none -fill white -pointsize $TITLE_SIZE -font $TITLE_FONT -antialias $FONT_DECO -annotate +20+80 "Al" -trim +repage info:)
543
-
544
-let "TILE_HEIGHT=TILE_HEIGHT+TITLE_BOTTOM_SPACE"
545
-
546
-# Make text 'tiles' for each title. These will be pieced together later on.
547
-echo "Adding $NUM_TITLES titles to the menu:"
548
-for ((i=0; i<$NUM_TITLES; i++)); do
549
- SEQNUM=$(printf "%02d" ${i})
550
- let "j=i+1"
551
- echo " $j: ${TITLES[i]}"
552
- # Enumerate (S)VCD titles
553
- if test $RES = "vcd" ; then
554
- ENTRY="${j}. ${TITLES[i]}"
555
-
556
- # Get the width of text and pad it
557
- TILE_WIDTH=$(convert -format %w -size 720x200 xc:none -fill $TEXT_COLOR -pointsize $TITLE_SIZE -font $TITLE_FONT -antialias $FONT_DECO -annotate +20+80 "$ENTRY" -trim +repage info:)
558
- let "TILE_WIDTH=TILE_WIDTH+TITLE_LEFT_SPACE"
559
-
560
- # Draw the text, and put it on a blank tile
561
- convert -size 720x100 xc:none -font $TITLE_FONT -antialias $FONT_DECO -fill $TEXT_COLOR -pointsize $TITLE_SIZE -annotate +20+80 "$ENTRY" -trim +repage "$TMP_DIR/01_entry-$SEQNUM.png"
562
- convert -size ${TILE_WIDTH}x${TILE_HEIGHT} xc:none "$TILE_CANVAS"
563
- composite -compose Over -gravity north "$TMP_DIR/01_entry-$SEQNUM.png" \
564
- "$TILE_CANVAS" "$TMP_DIR/01_entry-$SEQNUM.png"
565
-
566
- # Use a highlight cursor for DVD titles (drawn later, for now just text)
567
- else
568
- ENTRY="${TITLES[i]}"
569
-
570
- # Get the width of the text and pad it
571
- TILE_WIDTH=$(convert -format %w -size 720x200 xc:none -fill $TEXT_COLOR -pointsize $TITLE_SIZE -font $TITLE_FONT -antialias $FONT_DECO -annotate +20+80 "$ENTRY" -trim +repage info:)
572
- let "TILE_WIDTH=TILE_WIDTH+TITLE_LEFT_SPACE"
573
-
574
- # Draw the text, and put it on a blank tile
575
- convert -size 720x100 xc:none -font $TITLE_FONT -antialias $FONT_DECO -fill $TEXT_COLOR -pointsize $TITLE_SIZE -annotate +20+80 "$ENTRY" -trim +repage "$TMP_DIR/00_title-$SEQNUM.png"
576
- convert -size ${TILE_WIDTH}x${TILE_HEIGHT} xc:none "$TILE_CANVAS"
577
- composite -compose Over -gravity northeast \
578
- "$TMP_DIR/00_title-$SEQNUM.png" "$TILE_CANVAS" \
579
- "$TMP_DIR/00_title-$SEQNUM.png"
580
-
581
- # Blank placeholder: no font decorations or color
582
- DIMS=$(identify "$TMP_DIR/00_title-$SEQNUM.png" | grep -o -e " [0-9]\{1,\}x[0-9]\{1,\} " | tr -d ' ')
583
- convert \
584
- -size $DIMS xc:none "$TMP_DIR/00_title-${SEQNUM}_placeholder.png"
585
- fi
586
-done
587
-
588
-# Finish DVD menu entries (all we have so far is text, no buttons!)
589
-if test $RES = "dvd"; then
590
- echo "Making the DVD buttons... "
591
-
592
- # Get the dimensions of the button
593
- TILE_WIDTH=$(convert -format %w -size 720x200 xc:none -fill white -stroke $BTN_STROKE -strokewidth 1 -pointsize $TITLE_SIZE -font $BUTTON_FONT +antialias -weight bold -annotate +20+80 "$BUTTON_CHAR" -trim +repage info:)
594
- BUTTON_HEIGHT=$(convert -format %w -size 720x200 xc:none -fill white -stroke $BTN_STROKE -strokewidth 1 -pointsize $TITLE_SIZE -font $BUTTON_FONT +antialias -weight bold -annotate +20+80 "$BUTTON_CHAR" -trim +repage info:)
595
- # Find how much to pad the top of the button and make the pad
596
- let "BUTTON_PADDING=(TILE_HEIGHT-BUTTON_HEIGHT-TITLE_BOTTOM_SPACE)/2"
597
- convert -size ${TILE_WIDTH}x${BUTTON_PADDING} xc:none "$BUTTON_PAD"
598
-
599
- # Draw the buttons
600
- convert -size 720x100 xc:none -font $BUTTON_FONT -stroke $BTN_STROKE -strokewidth 1 +antialias -weight bold -fill $HIGHLIGHT_COLOR -pointsize $TITLE_SIZE -annotate +20+80 "$BUTTON_CHAR" -trim +repage "$HIGHLIGHT_BUTTON"
601
- convert -size 720x100 xc:none -font $BUTTON_FONT -stroke $BTN_STROKE -strokewidth 1 +antialias -weight bold -fill $SELECT_COLOR -pointsize $TITLE_SIZE -annotate +20+80 "$BUTTON_CHAR" -trim +repage "$SELECT_BUTTON"
602
-
603
- # Pad the buttons so that they line up with the font's baseline
604
- convert -background none "$BUTTON_PAD" "$HIGHLIGHT_BUTTON" -append \
605
- "$HIGHLIGHT_BUTTON"
606
- convert -background none "$BUTTON_PAD" "$SELECT_BUTTON" -append \
607
- "$SELECT_BUTTON"
608
-
609
- # Make a blank button tile according to measured dimensions
610
- convert -size ${TILE_WIDTH}x${TILE_HEIGHT} xc:none "$TILE_CANVAS"
611
-
612
- # Put padded buttons on the blank tile
613
- composite -compose Over -gravity north "$HIGHLIGHT_BUTTON" \
614
- "$TILE_CANVAS" "$HIGHLIGHT_BUTTON"
615
- composite -compose Over -gravity north "$SELECT_BUTTON" \
616
- "$TILE_CANVAS" "$SELECT_BUTTON"
617
-
618
- # A placeholder to space the title text correctly
619
- DIMS=$(identify "$HIGHLIGHT_BUTTON" | grep -o -e " [0-9]\{1,\}x[0-9]\{1,\} " | tr -d ' ')
620
- convert -size $DIMS xc:none "$BUTTON_PLACEHOLDER"
621
-
622
- # Next, join the button tiles with the title tiles:
623
- i=0
624
- while test $i -lt $NUM_TITLES; do
625
- SEQNUM=$(printf "%02d" $i)
626
- # Text entries
627
- convert -background none "$BUTTON_PLACEHOLDER" \
628
- "$TMP_DIR/00_title-$SEQNUM.png" +append \
629
- "$TMP_DIR/01_entry-$SEQNUM.png"
630
- # Highlight entries
631
- convert -background none "$HIGHLIGHT_BUTTON" \
632
- "$TMP_DIR/00_title-${SEQNUM}_placeholder.png" \
633
- +append "$TMP_DIR/01_highlight_entry-$SEQNUM.png"
634
- # Select entries
635
- convert -background none "$SELECT_BUTTON" \
636
- "$TMP_DIR/00_title-${SEQNUM}_placeholder.png" \
637
- +append "$TMP_DIR/01_select_entry-$SEQNUM.png"
638
- let "i=i+1"
639
- done
640
-fi
641
-
642
-# Stack all 01_entry-N.png lines
643
-echo "Creating the text menu... "
644
-convert -background none "$TMP_DIR/01_entry-*.png" -append "$MENU_TEXT"
645
-
646
-# Stack all DVD button lines
647
-if test $RES = "dvd"; then
648
-echo "Creating the DVD button overlays... "
649
- convert -background none "$TMP_DIR/01_highlight_entry-*.png" -append \
650
- "$HIGHLIGHT_TEXT"
651
- convert -background none "$TMP_DIR/01_select_entry-*.png" -append \
652
- "$SELECT_TEXT"
653
-fi
654
-
655
-# If specified, add a menu title
656
-if $MAKE_TITLE; then
657
- echo "Adding the menu title..."
658
-
659
- # Default title font size = current text size + 4
660
- if test -z "$MENU_TITLE_SIZE"; then
661
- let "MENU_TITLE_SIZE=TITLE_SIZE+8"
662
- fi
663
-
664
- # Calculate number of \n characters in title, so menu title height
665
- # will be set correctly
666
- TITLE_LINES=$(echo "$MENU_TITLE" | sed 's/!//g;s/\\n/!/g;s/[^!]//g' | wc -c)
667
- TITLE_HEIGHT=$((100 * $TITLE_LINES))
668
-
669
- # Draw the menu title and pad the bottom with TILE_HEIGHT pixels
670
- convert -size 720x$TITLE_HEIGHT xc:none -font $TITLE_FONT -antialias $FONT_DECO -fill $TEXT_COLOR -pointsize $MENU_TITLE_SIZE -annotate +20+80 "$MENU_TITLE" -trim +repage "$MENU_TITLE_TEXT"
671
-
672
- convert "$MENU_TITLE_TEXT" -gravity south -background none -splice 0x$TILE_HEIGHT "$MENU_TITLE_TEXT"
673
-
674
- # Put the menu title above the menu text (and buttons for DVDs)
675
- convert -background none "$MENU_TITLE_TEXT" "$MENU_TEXT" -append \
676
- "$MENU_TEXT"
677
- if test $RES = "dvd"; then
678
- # DVD menus need an empty placeholder for the buttons
679
- DIMS=$(identify "$MENU_TITLE_TEXT" | grep -o -e " [0-9]\{1,\}x[0-9]\{1,\} " | tr -d ' ')
680
- convert -size $DIMS xc:none "$MENU_TITLE_PLACEHOLDER"
681
- convert -background none "$MENU_TITLE_PLACEHOLDER" "$HIGHLIGHT_TEXT" \
682
- -append "$HIGHLIGHT_TEXT"
683
- convert -background none "$MENU_TITLE_PLACEHOLDER" "$SELECT_TEXT" \
684
- -append "$SELECT_TEXT"
685
- fi
686
-
687
-fi
688
-
689
-# Put the text menus inside the safety area
690
-if $SAFE_AREA; then FRAME_TYPE="safe area"; else FRAME_TYPE="frame"; fi
691
-echo "Placing text menu in the $FRAME_TYPE... "
692
-convert -size ${FG_WIDTH}x${FG_HEIGHT} xc:none "$SAFETY_CANVAS"
693
-composite -compose Over -gravity $TEXT_ALIGN \
694
- "$MENU_TEXT" "$SAFETY_CANVAS" "$ACTIVE_TEXT"
695
-
696
-# Same for DVD buttons: into the safety area
697
-if test $RES = 'dvd'; then
698
- echo "Placing DVD buttons in the $FRAME_TYPE... "
699
- composite -compose Over -gravity $TEXT_ALIGN \
700
- "$HIGHLIGHT_TEXT" "$SAFETY_CANVAS" "$ACTIVE_HIGHLIGHT"
701
- composite -compose Over -gravity $TEXT_ALIGN \
702
- "$SELECT_TEXT" "$SAFETY_CANVAS" "$ACTIVE_SELECT"
703
-fi
704
-
705
-# Background image:
706
-# If none was provided, create a default one (blue-black gradient)
707
-if test -z "$BG_IMAGE"; then
708
- BG_CMD="convert -size ${WIDTH}x${HEIGHT} gradient:blue-black \
709
- -gravity center -matte \"$BG_CANVAS\""
710
-# Otherwise, scale/crop the provided image
711
-else
712
- if test "$SCALECROP" = "crop"; then
713
- SCALECROP="-resize ${WIDTH}x -resize \"x${HEIGHT}<\" -gravity center \
714
- -crop ${WIDTH}x${HEIGHT}+0+0"
715
- else
716
- SCALECROP="-resize ${WIDTH}x${HEIGHT}!"
717
- fi
718
- BG_CMD="convert \"$BG_IMAGE\" $SCALECROP -matte \"$BG_CANVAS\""
719
-fi
720
-echo "Working on the background... "
721
-$DEBUG && echo -e "\n\nBackground:\n$BG_CMD" >> $REDIR
722
-eval $BG_CMD
723
-
724
-# Put menu text over the background image
725
-MAGICK_CMD="composite -compose Over -gravity center \
726
- \"$ACTIVE_TEXT\" \"$BG_CANVAS\" -depth 8 \"$MENU_PPM\""
727
-echo "Centering the $FRAME_TYPE over the background... "
728
-$DEBUG && echo -e "\n\nMenu Text:\n$MAGICK_CMD" >> $REDIR
729
-eval $MAGICK_CMD
730
-
731
-# Same for DVDs
732
-if test $RES = 'dvd'; then
733
- echo "Positioning the DVD button overlays on the background... "
734
- composite -compose Src -gravity center \
735
- "$ACTIVE_HIGHLIGHT" "$BG_CANVAS" "$HIGHLIGHT_PNG"
736
- composite -compose Src -gravity center \
737
- "$ACTIVE_SELECT" "$BG_CANVAS" "$SELECT_PNG"
738
-fi
739
-
740
-
741
-# ======================================================================\
742
-# P R E V I E W & F I N I S H
743
-#
744
-#
745
-
746
-if ! $NOASK; then
747
- echo "Generating preview..."
748
- echo "Type 'q' to close the preview window."
749
- if test "$RES" = vcd; then
750
- display "$MENU_PPM"
751
- else
752
- composite -compose Over -gravity center "$HIGHLIGHT_PNG" \
753
- "$MENU_PPM" miff: | display
754
- fi
755
- wait
756
- echo -n "Was the preview ok [y/N]? "
757
- ANSWER="N"
758
- read ANSWER
759
- if ! ( test "$ANSWER" = "y" || test "$ANSWER" = "Y" ); then
760
- echo "Preview was not OK, exiting..."
761
- cleanup
762
- echo
763
- echo "Try: -font FONT -fontsize NUM -textcolor '#RGB'"
764
- echo " -fontdeco 'ImageMagick instr' -align left|center|right"
765
- echo " -background IMAGE -audio AUDIOFILE"
766
- echo "to change the appearance. More in 'man tovid'"
767
- exit 0
768
- else
769
- echo "Preview was OK. Continuing..."
770
- fi
771
-fi
772
-
773
-# Background audio:
774
-# If no background audio was provided, generate 4 seconds of silence
775
-if test -z "$BG_AUDIO"; then
776
- if test -z "$MENU_LENGTH"; then
777
- MENU_LENGTH="-t 4"
778
- fi
779
- echo "Creating $(echo "$MENU_LENGTH" | cut -c 4-)-second silent $ASUF audio... "
780
- AUDIO_CMD="ffmpeg -f s16le -i /dev/zero -ac 2 -ar $SAMPRATE -ab 224k \
781
- $MENU_LENGTH -acodec $ASUF -y \"$AUDIO_STREAM\""
782
- $DEBUG && echo -e "\n\nBG audio:\n$AUDIO_CMD" >> $REDIR
783
- eval $AUDIO_CMD >> $REDIR 2>&1
784
-# Otherwise, convert provided audio to the target format
785
-else
786
- echo "Converting \"$BG_AUDIO\" to $ASUF... "
787
- AUDIO_CMD="ffmpeg -i \"$BG_AUDIO\" -ac 2 -ar $SAMPRATE -ab 224k \
788
- $MENU_LENGTH -acodec $ASUF -y \"$AUDIO_STREAM\""
789
- $DEBUG && echo -e "\n\nBG audio:\n$AUDIO_CMD" >> $REDIR
790
- eval $AUDIO_CMD >> $REDIR 2>&1
791
-fi
792
-
793
-# Calculate video length from length of audio
794
-VID_LENGTH=$(mplayer -quiet -nomsgcolor -identify -frames 0 -vo null -ao null \
795
- "$AUDIO_STREAM" 2>&1 | grep '^ID_LENGTH' | awk -F '=' '{print $2}' | \
796
- sed -e "s/\.[0-9]*//g")
797
-VID_LENGTH=$(expr "$VID_LENGTH" \* $FPS \/ 100)
798
-
799
-# Make sure VID_LENGTH is nonzero
800
-if test "$VID_LENGTH" -eq 0 ; then
801
- # Use 30 seconds as a sensible default
802
- VID_LENGTH=$(expr 30 \* $FPS \/ 100)
803
-fi
804
-
805
-# Make video of specified length from PPM background image
806
-echo "Converting menu image to video. This may take a while... "
807
-VIDEO_CMD="ppmtoy4m $PPM_OPTS -n $VID_LENGTH -r \"$MENU_PPM\" 2>>$REDIR | \
808
- mpeg2enc -a 2 $MPEG2ENC_FMT $MPEG2ENC_SYS -o \"$VIDEO_STREAM\" >> $REDIR 2>&1"
809
-$DEBUG && echo -e "\n\nTo mpeg:\n$VIDEO_CMD" >> $REDIR
810
-eval $VIDEO_CMD
811
-
812
-# Multiplex audio and video
813
-echo "Multiplexing video and audio streams... "
814
-MPLEX_CMD="mplex $MPLEX_OPTS $MPEG2ENC_FMT -o \"$MENU_MPEG\" \
815
- \"$VIDEO_STREAM\" \"$AUDIO_STREAM\" >> $REDIR 2>&1"
816
-$DEBUG && echo -e "\n\nMux:\n$MPLEX_CMD" >> $REDIR
817
-eval $MPLEX_CMD
818
-
819
-# For DVD, create spumux XML
820
-if test "$RES" = "dvd"; then
821
-
822
-(cat << EOF
823
-<subpictures>
824
- <stream>
825
- <spu force="yes" start="00:00:00.00"
826
- highlight="$HIGHLIGHT_PNG"
827
- select="$SELECT_PNG"
828
- autooutline="infer">
829
- </spu>
830
- </stream>
831
-</subpictures>
832
-EOF
833
-) > "$SPUMUX_XML"
834
- wait
835
- SPUMUX_CMD="spumux \"$SPUMUX_XML\" < \"$MENU_MPEG\" > \"$OUT_FILENAME\" 2>>$REDIR"
836
- echo "Adding the DVD buttons to menu... "
837
- $DEBUG && echo -e "\n\nSpumux buttons:\n$SPUMUX_CMD" >> $REDIR
838
- eval $SPUMUX_CMD
839
-
840
-# Rename the output menu for VCD and SVCD
841
-else
842
- mv "$MENU_MPEG" "$OUT_FILENAME"
843
-fi
844
-
845
-cleanup
846
-
847
-echo $SEPARATOR
848
-if test -s "$OUT_FILENAME"; then
849
- if ! $QUIET; then
850
- echo "Finished! Your menu should be in the file \"$OUT_FILENAME\"."
851
- if test "$RES" = "vcd"; then
852
- echo "You can use this menu on an SVCD or VCD disc with:"
853
- echo
854
- echo " tovid xml -vcd -menu \"$OUT_FILENAME\" <title 1> <title 2> ... \\"
855
- echo " <output name>"
856
- else
857
- echo "You can use this menu on a DVD disc with:"
858
- echo
859
- echo " tovid xml -dvd -menu \"$OUT_FILENAME\" <title 1> <title 2> ... \\"
860
- echo " -out <output name>"
861
- fi
862
-
863
- echo
864
- echo "where <title N> is an MPEG video file corresponding to title N as listed"
865
- echo "on your menu. Run tovid xml' without any options for more usage information."
866
- else
867
- echo "Done!"
868
- fi
869
-else
870
- echo "It looks like something went wrong, because there is no output file."
871
- echo "Please submit a bug report to http://code.google.com/p/tovid/issues."
872
- echo "Please add -debug to your command (tovid menu -debug ...) and post the"
873
- echo "log file and terminal output. Sorry for the inconvenience."
874
- exit 1
875
-fi
876
-
877
-$QUIET || echo $SEPARATOR
878
-$QUIET || echo "Thanks for using makemenu!"
879
-exit 0
880
tovid-0.34.tar.bz2/src/makevcd
Deleted
232
1
2
-#!/usr/bin/env bash
3
-ME="[makevcd]:"
4
-. tovid-init 2>/dev/null ||
5
-{ echo -e "===============================================================\n"
6
-echo -e "'tovid-init' not found. Was tovid improperly installed?"
7
-echo -e "Or are you trying to run the script directly?"
8
-echo -e "Please run makevcd as:\ntovid vcd OPTIONS"
9
-exit 1 ; }
10
-
11
-# makevcd
12
-# Part of the tovid suite
13
-# =======================
14
-# A bash script for creating a VCD cue/bin set and burning it
15
-# to a recordable CD.
16
-#
17
-# Project homepage: http://tovid.wikia.com
18
-#
19
-# Copyright (C) 2005-2010
20
-#
21
-# This program is free software; you can redistribute it and/or
22
-# modify it under the terms of the GNU General Public License
23
-# as published by the Free Software Foundation; either
24
-# version 2 of the License, or (at your option) any later
25
-# version.
26
-#
27
-# This program is distributed in the hope that it will be useful,
28
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
29
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30
-# GNU General Public License for more details.
31
-#
32
-# You should have received a copy of the GNU General Public License
33
-# along with this program; if not, write to the Free Software
34
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
35
-#
36
-# http://www.gnu.org/licenses/gpl.txt
37
-
38
-SCRIPTNAME=`cat << EOF
39
---------------------------------
40
-tovid vcd
41
-Create cue/bin files for a (S)VCD and burn them to a CD
42
-Version $TOVID_VERSION
43
-$TOVID_HOME_PAGE
44
---------------------------------
45
-EOF`
46
-
47
-USAGE=`cat << EOF
48
-Usage: tovid vcd [OPTIONS] {VCDIMAGER.xml}
49
-
50
-Where OPTIONS may be any of the following:
51
-
52
- -overwrite Overwrite existing cue/bin image
53
- -burn (default only make image)
54
- -device DEVICE (default /dev/cdrw)
55
- -speed NUM (default 12)
56
- -force Add --force to cdrdao command (needed for short slides)
57
-
58
-And:
59
-
60
- VCDIMAGER.xml is the name of a file containing a VCDImager XML
61
- description (For XML format, see http://www.vcdimager.org/).
62
- If you use(d) 'makexml' to create the XML file, you can use
63
- that as input here.
64
-
65
-See the tovid manual page ('man tovid') for additional documentation.
66
-
67
-EOF`
68
-
69
-SEPARATOR="=========================================="
70
-
71
-# Print script name, usage notes, and optional error message, then exit.
72
-# Args: $1 == text string containing error message
73
-usage_error ()
74
-{
75
- echo "$USAGE"
76
- echo $SEPARATOR
77
- echo "$@"
78
- exit 1
79
-}
80
-
81
-# Print out a runtime error specified as an argument, and exit
82
-runtime_error ()
83
-{
84
- killsubprocs
85
- echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
86
- echo "makevcd encountered an error during the VCD creation process:"
87
- echo $@
88
- echo "See if anything in the above output helps you diagnose the"
89
- echo "problem, and please file a bug report containing the above"
90
- echo "output to http://code.google.com/p/tovid/issues."
91
- echo "Sorry for the inconvenience!"
92
- echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
93
- exit 1
94
-}
95
-# Defaults
96
-QUIET=false
97
-IMAGE=:
98
-CDRW_DEVICE="/dev/cdrw"
99
-BURN_SPEED=12
100
-OVERWRITE=false
101
-BURN=false
102
-
103
-# ==========================================================
104
-# EXECUTION BEGINS HERE
105
-echo $"$SCRIPTNAME"
106
-
107
-assert_dep "$vcd" "You are missing dependencies required to image and burn (S)VCDs!"
108
-
109
-# check for valid CD burner. This may fail but at least we tried
110
-OIFS=$IFS \
111
-IFS=$'\n' device=($(find -L /dev -type b -name 'cdrw*' 2>/dev/null )) IFS=$OIFS
112
-CDRW_DEVICE=${device:-$CDRW_DEVICE}
113
-
114
-while test x"${1:0:1}" = "x-"; do
115
- case "$1" in
116
- "-quiet" ) QUIET=: ;;
117
- "-overwrite" )
118
- OVERWRITE=:
119
- ;;
120
- "-burn" )
121
- BURN=:
122
- ;;
123
- "-device" )
124
- shift
125
- CDRW_DEVICE="$1"
126
- ;;
127
- "-speed" )
128
- shift
129
- BURN_SPEED=$1
130
- ;;
131
- "-force" )
132
- FORCE="--force"
133
- ;;
134
- * )
135
- usage_error "Error: Unrecognized command-line option $1"
136
- ;;
137
- esac
138
-
139
- # Get next argument
140
- shift
141
-done
142
-
143
-if test $# -ne 1; then
144
- usage_error "Please provide the name of a VCDimager XML file \
145
-containing the (S)VCD description."
146
-else
147
- # XML input is last argument
148
- VCDIMAGER_XML="$1"
149
-fi
150
-
151
-# Look for earlier attempts to image this VCD
152
-for prev_try in "$VCDIMAGER_XML.cue" "$VCDIMAGER_XML.bin"; do
153
- if test -f "$prev_try"; then
154
- echo "Found a previous makevcd attempt: $prev_try!"
155
- if $OVERWRITE; then
156
- echo -n "Removing it... "
157
- rm -fv "$prev_try"
158
- elif $BURN; then
159
- echo "Will use this for burning the disc."
160
- IMAGE=false
161
- else
162
- echo "Use '-overwrite' to override and re-image; or"
163
- echo "use '-burn' to write this existing image."
164
- echo "Exiting..."
165
- exit 1
166
- fi
167
- fi
168
-done
169
-
170
-
171
-# Create the cue/bin image
172
-if $IMAGE; then
173
- # TODO: Warn if there isn't enough space to make cue/bin
174
- VCDIMAGER_CMD="vcdxbuild -c \"$VCDIMAGER_XML.cue\" -b \
175
- \"$VCDIMAGER_XML.bin\" \"$VCDIMAGER_XML\""
176
- echo $SEPARATOR
177
- echo "Creating cue/bin disc image with the following command:"
178
- echo $VCDIMAGER_CMD
179
- if eval $VCDIMAGER_CMD; then
180
- echo "Done."
181
- $QUIET || echo "Use 'tovid vcd -burn $VCDIMAGER_XML' to burn your VCD."
182
- $QUIET || echo "Thanks for using tovid!"
183
- else
184
- runtime_error "Imaging failed, please see vcdxbuild output above."
185
- fi
186
-fi
187
-
188
-# Burn the VCD
189
-if $BURN; then
190
- # Sanity check: Make sure given device is valid (somehow)
191
- # before creating the cue/bin. Give option to proceed anyway?
192
- # (i.e., could there be any point to proceeding?)
193
- # Here's a simple way: just quit
194
- if test -b $CDRW_DEVICE; then :
195
- else
196
- echo "Couldn't find $CDRW_DEVICE! Stopping here."
197
- exit 1
198
- fi
199
-
200
- # Remind user to insert a CD
201
- $QUIET || echo "Please insert a blank CD-R(W) disc into your CD-recorder"
202
- $QUIET || echo "($CDRW_DEVICE) if you have not already done so."
203
-
204
- # check for cdrw and blank if so
205
- if cdrdao disk-info --device $CDRW_DEVICE --driver generic-mmc 2>&1 |
206
- grep -q CD-RW.*yes; then
207
- echo $SEPARATOR
208
- echo "Found rewritable CD - starting to blank in 10 seconds - press ctrl-c to quit"
209
- countdown 10
210
- cdrdao blank --driver generic-mmc $CDRW_DEVICE
211
- fi
212
- # Burn the disc
213
- CDRDAO_CMD="cdrdao write --device $CDRW_DEVICE --driver generic-mmc \
214
- --speed $BURN_SPEED $FORCE \"$VCDIMAGER_XML.cue\""
215
- echo $SEPARATOR
216
- echo "Burning cue/bin image to $CDRW_DEVICE with the following command:"
217
- echo $CDRDAO_CMD
218
- if eval $CDRDAO_CMD; then
219
- if ! $QUIET; then
220
- echo "Done. You should now have a working VCD or SVCD. Please report"
221
- echo "any problems to http://code.google.com/p/tovid/issues."
222
- echo "Thanks for using tovid!"
223
- else
224
- echo "Done."
225
- fi
226
- else
227
- runtime_error "Could not burn the disc to $CDRW_DEVICE at speed $BURN_SPEED."
228
- fi
229
-fi
230
-
231
-exit 0
232
tovid-0.34.tar.bz2/src/makexml
Deleted
831
1
2
-#!/usr/bin/env bash
3
-ME="[makexml]:"
4
-. tovid-init 2>/dev/null ||
5
-{ echo -e "===============================================================\n"
6
-echo -e "'tovid-init' not found. Was tovid improperly installed?"
7
-echo -e "Or are you trying to run the script directly?"
8
-echo -e "Please run makexml as:\ntovid xml OPTIONS"
9
-exit 1 ; }
10
-
11
-# makexml
12
-# Part of the tovid suite
13
-# =======================
14
-# This bash script generates XML output describing the structure of
15
-# a VCD, SVCD, or DVD disc. The resulting output can be given as input
16
-# to vcdxbuild or dvdauthor. Format, and a list of menus and
17
-# video files in MPEG format, are specified on the command-line, and
18
-# the resulting XML is written to the specified file. Currently
19
-# supports an optional top-level menu, any number of optional sub-menus,
20
-# and any number of videos reachable through those menus.
21
-#
22
-# Project homepage: http://tovid.wikia.com
23
-#
24
-# Copyright (C) 2005-2010
25
-#
26
-# This program is free software; you can redistribute it and/or
27
-# modify it under the terms of the GNU General Public License
28
-# as published by the Free Software Foundation; either
29
-# version 2 of the License, or (at your option) any later
30
-# version.
31
-#
32
-# This program is distributed in the hope that it will be useful,
33
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
34
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
-# GNU General Public License for more details.
36
-#
37
-# You should have received a copy of the GNU General Public License
38
-# along with this program; if not, write to the Free Software
39
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
40
-#
41
-# http://www.gnu.org/licenses/gpl.txt
42
-
43
-SCRIPTNAME=`cat << EOF
44
---------------------------------
45
-tovid xml
46
-Generate XML for authoring a VCD, SVCD, or DVD.
47
-Version $TOVID_VERSION
48
-$TOVID_HOME_PAGE
49
---------------------------------
50
-EOF`
51
-
52
-USAGE=`cat << EOF
53
-Usage: tovid xml [OPTIONS] {video1.mpg video2.mpg ...} -out OUT_PREFIX
54
-
55
-Common OPTIONS:
56
-
57
- -dvd | -vcd | -svcd Specify the target disc format
58
- -overwrite Overwrite any existing output files
59
-
60
-Provide a list of .mpg video files, and they will be played back in
61
-sequence. You may organize several lists of videos into menus by
62
-providing the name of a menu .mpg:
63
-
64
- tovid xml -menu menu1.mpg \\\\
65
- video1.mpg video2.mpg video3.mpg \\\\
66
- -out mydisc
67
- tovid xml -topmenu topmenu.mpg \\\\
68
- -menu submenu1.mpg vid1.mpg vid2.mpg vid3.mpg \\\\
69
- -menu submenu2.mpg vid4.mpg vid5.mpg vid6.mpg \\\\
70
- -out mydisc2
71
-
72
-See the tovid manual page ('man tovid') for additional documentation.
73
-
74
-EOF`
75
-
76
-SEPARATOR="=========================================="
77
-
78
-# Print script name, usage notes, and optional error message, then exit.
79
-# Args: $1 == text string containing error message
80
-usage_error ()
81
-{
82
- echo "$USAGE"
83
- echo $SEPARATOR
84
- echo "$@"
85
- exit 1
86
-}
87
-
88
-QUIET=false
89
-# Currently-numbered titleset (must have at least 1 titleset)
90
-CUR_TS=1
91
-# Currently-numbered video title under a titleset menu (0 for no titles)
92
-CUR_TITLE=0
93
-# Do we have a top menu yet?
94
-HAVE_TOP_MENU=false
95
-# Do we have any menus yet?
96
-HAVE_MENU=false
97
-# Do not overwrite by default
98
-OVERWRITE=false
99
-# Use dvdauthor XML for DVD authoring
100
-XML_FORMAT="dvd"
101
-# No un-found files yet
102
-FILE_NOT_FOUND=false
103
-# Not doing still titles
104
-STILL_TITLES=false
105
-FIRST_TITLE=:
106
-# Avoid some unbound variables
107
-TOP_MENU_XML=""
108
-TOP_MENU_BUTTONS=""
109
-MENU_BUTTONS=""
110
-TS_TITLES=""
111
-ALL_MENU_XML=""
112
-SEGMENT_ITEMS_XML=""
113
-SEQUENCE_ITEMS_XML=""
114
-PBC_XML=""
115
-PLAYLIST_XML=""
116
-
117
-MAKE_GROUP=false
118
-MAKE_CHAPTERS=:
119
-FORCE_TITLESETS=false
120
-CUR_VIDEO=0
121
-CHAPTER_INTERVAL=5
122
-
123
-STANDARD=133
124
-WIDESCREEN=177
125
-NOPANSCAN=''
126
-TV_FORMAT=ntsc
127
-PAUSE=0
128
-
129
-# ==========================================================
130
-# Backslash-escape the given special character (and any EOLs)
131
-# Usage:
132
-# sedprep "$TEXT" /
133
-# echo $TEXT | sed "s/PATTERN/$(sedprep "$REPLACEMENT" /)/"
134
-function sedprep ()
135
-{
136
- delim=${2:-/}
137
- echo "$1" |sed -e 's/[\&'"$delim"']/\\&/g' -e '$!s,$,\\,';
138
-}
139
-
140
-# ==========================================================
141
-# Check for the existence of a file and print an error if it
142
-# does not exist in the current directory
143
-# Args: $1 = file to look for
144
-function checkExistence ()
145
-{
146
- if test -e "$1"; then :
147
- else
148
- echo "The file "$1" was not found. Exiting."
149
- FILE_NOT_FOUND=:
150
- exit 1
151
- fi
152
-}
153
-
154
-# ==========================================================
155
-# Find a video's aspect ratio and set dvd behavior accordingly
156
-# Args: $1 = video file to find aspect for
157
-# Usage: noPanScan foo.avi
158
-# Sets NOPANSCAN to either: widescreen="nopanscan"
159
-# or: <null>
160
-function noPanScan ()
161
-{
162
- ASPECT=$(idvid -fast -terse "$1" | grep "ASPECT" | awk -F '=' '{print $2}')
163
- $QUIET || echo -n " $1 has aspect $ASPECT "
164
- if test $ASPECT -eq $WIDESCREEN; then
165
- NOPANSCAN='widescreen="nopanscan"'
166
- $QUIET || echo "(widescreen)."
167
- else
168
- NOPANSCAN=''
169
- $QUIET || echo "(standard)."
170
- fi
171
-
172
-}
173
-
174
-function getFormat ()
175
-{
176
- # Set TV format - default is ntsc
177
- VID_INFO=$(tovid id -fast -terse "$1")
178
- grep -q PAL_DVD <<< "$VID_INFO" && TV_FORMAT=pal
179
-}
180
-
181
-# ==========================================================
182
-# Add a top-level VMGM menu to the DVD
183
-# Args: $1 = video file to use for top menu
184
-function addTopMenu ()
185
-{
186
- HAVE_TOP_MENU=:
187
- echo "Adding top-level menu using file: $1"
188
-
189
- # --------------------------
190
- # For DVD
191
- if test $XML_FORMAT = "dvd"; then
192
- # Set NOPANSCAN
193
- noPanScan "$1"
194
- # Generate XML for the top menu, with a placeholder for
195
- # the titleset menu buttons (to be replaced later by sed)
196
- TOP_MENU_XML=`cat << EOF
197
- <menus>
198
- <video $NOPANSCAN />
199
- <pgc entry="title">
200
- <vob file="$1" />
201
-__TOP_MENU_BUTTONS__
202
- </pgc>
203
- </menus>
204
-EOF`
205
-
206
- # --------------------------
207
- # For (S)VCD
208
- else
209
-
210
- # Generate XML for the segment-item
211
- SEGMENT_ITEMS_XML=`cat << EOF
212
-$SEGMENT_ITEMS_XML
213
- <segment-item src="$1" id="seg-top-menu"/>
214
-EOF`
215
-
216
- # Generate XML for the selection to go in pbc
217
- TOP_MENU_XML=`cat << EOF
218
- <selection id="select-top-menu">
219
- <bsn>1</bsn>
220
- <loop jump-timing="immediate">0</loop>
221
- <play-item ref="seg-top-menu"/>
222
-__TOP_MENU_BUTTONS__
223
- </selection>
224
-EOF`
225
-
226
- fi
227
-}
228
-
229
-# ==========================================================
230
-# Add a menu to the disc.
231
-# Args: $1 = video file to use for the menu
232
-function addMenu ()
233
-{
234
- # --------------------------
235
- # For DVD
236
- if test $XML_FORMAT = "dvd"; then
237
- echo "Adding a titleset-level menu using file: $1"
238
-
239
- # Generate XML for the button linking to this titleset menu from the top menu
240
- TOP_MENU_BUTTONS=`cat << EOF
241
- $TOP_MENU_BUTTONS
242
- <button>jump titleset $CUR_TS menu;</button>
243
-EOF`
244
-
245
- # Set NOPANSCAN
246
- noPanScan "$1"
247
- # Set TV_FORMAT
248
- getFormat "$1"
249
-
250
- # Generate XML for the menu header, with a placeholder for
251
- # the video segment buttons (to be replaced later by sed)
252
- MENU_XML=`cat << EOF
253
- <menus>
254
- <video $NOPANSCAN format="$TV_FORMAT"/>
255
- <pgc entry="root">
256
- <vob file="$1" />
257
-__MENU_BUTTONS__
258
- </pgc>
259
- </menus>
260
-EOF`
261
-
262
- # --------------------------
263
- # For (S)VCD
264
- else
265
- echo "Adding a menu using file: $1"
266
-
267
- # Generate XML for the button linking to this menu from the top menu
268
- TOP_MENU_BUTTONS=`cat << EOF
269
-$TOP_MENU_BUTTONS
270
- <select ref="select-menu-$CUR_TS"/>
271
-EOF`
272
-
273
- # Generate XML for the segment item
274
- SEGMENT_ITEMS_XML=`cat << EOF
275
-$SEGMENT_ITEMS_XML
276
- <segment-item src="$1" id="seg-menu-$CUR_TS"/>
277
-EOF`
278
-
279
- # Generate XML for the selection to go in pbc
280
- # If there's a top menu, "return" goes back to it.
281
- # Otherwise, don't use a "return" command.
282
- if $HAVE_TOP_MENU; then
283
- RETURN_CMD="<return ref=\"select-top-menu\"/>"
284
- else
285
- RETURN_CMD=""
286
- fi
287
- SELECTION_XML=`cat << EOF
288
- <selection id="select-menu-$CUR_TS">
289
- <bsn>1</bsn>
290
- $RETURN_CMD
291
- <loop jump-timing="immediate">0</loop>
292
- <play-item ref="seg-menu-$CUR_TS"/>
293
-__MENU_BUTTONS__
294
- </selection>
295
-EOF`
296
-
297
- fi
298
-}
299
-
300
-# ==========================================================
301
-# Add a video title to a titleset menu, or a still image to
302
-# a slideshow
303
-# Args: $1 = video file to use for the title
304
-function addTitle ()
305
-{
306
- if $FORCE_TITLESETS && test $CUR_VIDEO -eq 0; then
307
- closeTitleset
308
- fi
309
- # Increment the current title number
310
- if ! $MAKE_GROUP; then
311
- (( CUR_TITLE++ ))
312
- else
313
- # Grouping several videos within one title
314
- if test $CUR_VIDEO -eq 0; then
315
- (( CUR_TITLE++ ))
316
- fi
317
- (( CUR_VIDEO++ ))
318
- fi
319
- # --------------------------
320
- # For DVD
321
- if test $XML_FORMAT = "dvd"; then
322
- if ! $MAKE_GROUP; then
323
- echo "Adding title: $1 as title number $CUR_TITLE of titleset $CUR_TS"
324
- else
325
- if test $CUR_VIDEO -eq 1; then
326
- echo "Adding title number $CUR_TITLE of titleset $CUR_TS"
327
- fi
328
- echo "Adding $1 as video $CUR_VIDEO of title $CUR_TITLE"
329
- fi
330
-
331
- # Set NOPANSCAN
332
- noPanScan "$1"
333
-
334
- # Generate XML for the button linking to this title from the titleset menu
335
- if ! $FORCE_TITLESETS; then
336
- if test $CUR_VIDEO -lt 2; then
337
- MENU_BUTTONS=`cat << EOF
338
-$MENU_BUTTONS
339
- <button>jump title $CUR_TITLE;</button>
340
-EOF`
341
- fi
342
- else
343
- # Add a button for the current titleset to the top menu
344
- if test $CUR_VIDEO -le 1; then
345
- TOP_MENU_BUTTONS=`cat << EOF
346
-$TOP_MENU_BUTTONS
347
- <button>jump titleset $CUR_TS menu;</button>
348
-EOF`
349
- fi
350
- fi
351
-
352
- # Generate the chapters tag
353
- # If file exists, get duration and add appropriate chapter breaks
354
- if test -e "$1" && $MAKE_CHAPTERS; then
355
- CMD="idvid -terse \"$1\""
356
- echo " Calculating the duration of the video with:"
357
- echo " $CMD"
358
- echo " This may take a few minutes, so please be patient..."
359
- DURATION=$(eval $CMD | grep DURATION | awk -F '=' '{print $2}')
360
- echo $DURATION | awk '{hh=int($1/3600);mm=int(($1-hh*3600)/60);ss=$1-hh*3600-mm*60;\
361
- printf " The duration of the video is %02d:%02d:%02d\n",hh,mm,ss}'
362
-
363
- CHAPTERS=$(make_chapters $DURATION $CHAPTER_INTERVAL)
364
- # If file doesn't exist, or -nochapters was passed, use 0 chapters
365
- else
366
- CHAPTERS="0"
367
- fi
368
-
369
- # Generate the XML for the title itself, appending to existing titles
370
- if $MAKE_GROUP; then
371
- if test $CUR_VIDEO -eq 1; then
372
- TS_TITLES=`cat << EOF
373
-$TS_TITLES
374
- <pgc>
375
-EOF`
376
- fi
377
- TS_TITLES=`cat << EOF
378
- $TS_TITLES
379
- <vob file="$1" chapters="$CHAPTERS" />
380
-EOF`
381
- else
382
- TS_TITLES=`cat << EOF
383
-$TS_TITLES
384
- <pgc>
385
- <vob file="$1" chapters="$CHAPTERS" />
386
- __POST_CMD__
387
- </pgc>
388
-EOF`
389
- fi
390
-
391
- # --------------------------
392
- # For (S)VCD
393
- else
394
-
395
- # If there's a menu, "return" goes back to it; if not,
396
- # do not generate a "return" command
397
- if $HAVE_MENU; then
398
- RETURN_CMD="<return ref=\"select-menu-$CUR_TS\"/>"
399
- else
400
- RETURN_CMD=""
401
- fi
402
- # If this is the first title or slide in a series
403
- if $FIRST_TITLE; then
404
- # For the first titles, PREV stays on the current title
405
- let "PREV_TITLE=$CUR_TITLE"
406
- # For all other titles
407
- else
408
- # PREV goes to the previous slide
409
- let "PREV_TITLE=$CUR_TITLE - 1"
410
- fi
411
-
412
- # Fill in the NEXT command for the previous slide, if there was one
413
- NEXT_TITLE="<next ref=\"play-title-$CUR_TITLE\"\/>"
414
- SELECTION_XML=$( echo "$SELECTION_XML" | sed -e "s/__NEXT_TITLE__/$NEXT_TITLE/g" )
415
- PLAYLIST_XML=$( echo "$PLAYLIST_XML" | sed -e "s/__NEXT_TITLE__/$NEXT_TITLE/g" )
416
-
417
- # --------------------------
418
- # If doing a still-image slideshow, use segment/selection
419
- if $STILL_TITLES; then
420
- echo "Adding title: $1 as number $CUR_TITLE in a slideshow"
421
-
422
- # Generate XML for the selection (menu) "buttons" that will
423
- # jump to this slideshow. Only the first slide gets a button.
424
- if $FIRST_TITLE; then
425
- MENU_BUTTONS=`cat << EOF
426
-$MENU_BUTTONS
427
- <select ref="play-title-$CUR_TITLE"/>
428
-EOF`
429
- fi
430
-
431
- # Generate XML for the segment item
432
- SEGMENT_ITEMS_XML=`cat << EOF
433
-$SEGMENT_ITEMS_XML
434
- <segment-item src="$1" id="seg-slide-$CUR_TITLE"/>
435
-EOF`
436
-
437
- # Generate XML for the selection to go in pbc
438
- # The slide will play indefinitely until NEXT, PREV,
439
- # or RETURN is pressed. __NEXT_TITLE__ is a placeholder
440
- # until we're sure there is a next slide; it will be
441
- # filled in on the next addition if there is.
442
- SELECTION_XML=`cat << EOF
443
-$SELECTION_XML
444
- <playlist id="play-title-$CUR_TITLE">
445
- <prev ref="play-title-$PREV_TITLE"/>
446
- __NEXT_TITLE__
447
- $RETURN_CMD
448
- <wait>-1</wait>
449
- <play-item ref="seg-slide-$CUR_TITLE"/>
450
- </playlist>
451
-EOF`
452
-
453
- # --------------------------
454
- # If doing normal video titles, use select/playlist
455
- else
456
-
457
- echo "Adding title: $1 as title number $CUR_TITLE"
458
-
459
- # Generate XML for the selection (menu) "buttons" that will
460
- # jump to this playlist (title)
461
- MENU_BUTTONS=`cat << EOF
462
-$MENU_BUTTONS
463
- <select ref="play-title-$CUR_TITLE"/>
464
-EOF`
465
-
466
- # Generate XML for the sequence item
467
- SEQUENCE_ITEMS_XML=`cat << EOF
468
-$SEQUENCE_ITEMS_XML
469
- <sequence-item src="$1" id="seq-title-$CUR_TITLE"/>
470
-EOF`
471
-
472
- # Generate XML for the playlist for this title
473
- PLAYLIST_XML=`cat << EOF
474
-$PLAYLIST_XML
475
- <playlist id="play-title-$CUR_TITLE">
476
- <prev ref="play-title-$PREV_TITLE"/>
477
- __NEXT_TITLE__
478
- $RETURN_CMD
479
- <wait>$PAUSE</wait>
480
- <play-item ref="seq-title-$CUR_TITLE"/>
481
- </playlist>
482
-EOF`
483
-
484
- fi # (S)VCD slides or normal titles
485
-
486
- fi # DVD or (S)VCD
487
-
488
- FIRST_TITLE=false
489
-}
490
-
491
-# ==========================================================
492
-# Finalize the XML for a titleset, containing a menu and titles
493
-function closeTitleset ()
494
-{
495
- # Proceed only if there are titles in this titleset
496
- if (( $CUR_TITLE > 0 )); then
497
-
498
- # --------------------------
499
- # For DVD
500
- if test $XML_FORMAT = "dvd"; then
501
- echo "Closing titleset $CUR_TS with $CUR_TITLE title(s)."
502
-
503
- # Give each menu a button linking back to the top menu, if there is one
504
- if $HAVE_TOP_MENU; then
505
- MENU_BUTTONS=`cat << EOF
506
-$MENU_BUTTONS
507
- <button>jump vmgm menu;</button>
508
-
509
-EOF`
510
- fi
511
-
512
- # Fill in titleset menu buttons
513
- MENU_XML=$(echo "$MENU_XML" | \
514
- sed -e "s/__MENU_BUTTONS__/$(sedprep "$MENU_BUTTONS" /)/g")
515
-
516
- # Fill in the POST command. If there is a menu to jump back to, use that;
517
- # otherwise, do not insert a POST command.
518
- if $HAVE_MENU; then
519
- POST_CMD="<post>call menu;<\/post>"
520
- elif $FORCE_TITLESETS && $HAVE_TOP_MENU; then
521
- POST_CMD="<post>call vmgm menu;<\/post>"
522
- else
523
- POST_CMD=""
524
- fi
525
- TS_TITLES=$( echo "$TS_TITLES" | sed -e "s/__POST_CMD__/$POST_CMD/g" )
526
-
527
- # Append titleset info to ALL_MENU_XML
528
- if ! $FORCE_TITLESETS || ! $HAVE_TOP_MENU; then
529
- ALL_MENU_XML=`cat << EOF
530
-$ALL_MENU_XML
531
-<titleset>
532
-$MENU_XML
533
- <titles>
534
- <video $NOPANSCAN format="$TV_FORMAT" />
535
-$TS_TITLES
536
- </titles>
537
-</titleset>
538
-EOF`
539
- else
540
- # One titleset for each title -> add a dummy menu to the titleset
541
- ALL_MENU_XML=`cat << EOF
542
-$ALL_MENU_XML
543
-<titleset>
544
- <menus>
545
- <pgc>
546
- <post>
547
- jump title 1;
548
- </post>
549
- </pgc>
550
- </menus>
551
- <titles>
552
- <video $NOPANSCAN format="$TV_FORMAT"/>
553
-$TS_TITLES
554
- </titles>
555
-</titleset>
556
-EOF`
557
- fi
558
- # Clear existing XML to prepare for next titleset
559
- MENU_XML=""
560
- TS_TITLES=""
561
- CUR_TITLE=0
562
- MENU_BUTTONS=""
563
-
564
- # --------------------------
565
- # For (S)VCD
566
- else
567
-
568
- # Fill in menu title selections ("buttons")
569
- # and remove any remaining __NEXT_TITLE__s
570
- SELECTION_XML=$(echo "$SELECTION_XML" | \
571
- sed -e "s/__MENU_BUTTONS__/$(sedprep "$MENU_BUTTONS" /)/g" -e "s/__NEXT_TITLE__//g")
572
- PLAYLIST_XML=$(echo "$PLAYLIST_XML" | sed -e "s/__NEXT_TITLE__//g")
573
-
574
- # Append new PBC menus/playlists to PBC_XML
575
- PBC_XML=`cat << EOF
576
-$PBC_XML
577
-$SELECTION_XML
578
-$PLAYLIST_XML
579
-
580
-EOF`
581
-
582
- # Clear existing XML to prepare for next menu/titles
583
- SELECTION_XML=""
584
- PLAYLIST_XML=""
585
- MENU_BUTTONS=""
586
- # Go back to doing normal video titles
587
- STILL_TITLES=false
588
- fi
589
-
590
- # Increment the current titleset number
591
- (( CUR_TS++ ))
592
-
593
- fi # End if there are titles
594
-}
595
-
596
-# ==========================================================
597
-# EXECUTION BEGINS HERE
598
-echo "$SCRIPTNAME"
599
-
600
-if test $# -lt 1; then
601
- usage_error "Please provide at least one video to author, and the name of an output file to use."
602
-fi
603
-
604
-while test $# -gt 0; do
605
- case "$1" in
606
- "-quiet" )
607
- QUIET=:
608
- ;;
609
- "-out" )
610
- shift
611
- OUT_PREFIX="$1"
612
- ;;
613
- "-pause" )
614
- shift
615
- PAUSE="$1"
616
- ;;
617
- # Format and overwriting options
618
- "-dvd" ) XML_FORMAT="dvd" ;;
619
- "-vcd" ) XML_FORMAT="vcd" ;;
620
- "-svcd" ) XML_FORMAT="svcd" ;;
621
- "-overwrite" ) OVERWRITE=: ;;
622
- # Menus and video titles
623
- "-topmenu" )
624
- shift
625
- if ! $HAVE_TOP_MENU; then
626
- checkExistence "$1"
627
- addTopMenu "$1"
628
- else
629
- usage_error "Please specify only one -topmenu option. If you would like to have multiple menus, please use the -menu option."
630
- fi
631
- ;;
632
- "-menu" )
633
- if $FORCE_TITLESETS; then
634
- usage_error "You can not use -titlesets with -menu. Please use -topmenu instead."
635
- fi
636
- shift
637
- HAVE_MENU=:
638
- FIRST_TITLE=:
639
- checkExistence "$1"
640
- closeTitleset
641
- addMenu "$1"
642
- ;;
643
- "-slides" )
644
- STILL_TITLES=:
645
- FIRST_TITLE=:
646
- ;;
647
- "-group" )
648
- MAKE_GROUP=:
649
- CUR_VIDEO=0
650
- ;;
651
- "-endgroup" )
652
- if $MAKE_GROUP; then
653
- TS_TITLES=`cat << EOF
654
- $TS_TITLES
655
- __POST_CMD__
656
- </pgc>
657
-EOF`
658
- fi
659
- MAKE_GROUP=false
660
- CUR_VIDEO=0
661
- ;;
662
- "-chapter-points" )
663
- # Space-separated list of comma-separated chapter points
664
- MAKE_CHAPTERS=:
665
- shift
666
- IFS=""; while test $# -gt 0 && test ${1:0:1} != "-"; do
667
- CHAPTER_POINTS=("${CHAPTER_POINTS[@]}" "$1")
668
- shift
669
- done
670
- if test $# -gt 0 && test ${1:0:1} = "-"; then
671
- DO_SHIFT=false;
672
- fi
673
- unset IFS
674
- ;;
675
- "-chapters" )
676
- # Fixed chapter intervals
677
- MAKE_CHAPTERS=:
678
- shift
679
- CHAPTER_INTERVAL=$1
680
- if test "$CHAPTER_INTERVAL" -lt "0" || \
681
- test "$CHAPTER_INTERVAL" -gt "9999";
682
- then
683
- usage_error "Please use a -chapters interval between 0 and 9999."
684
- fi
685
- ;;
686
- "-nochapters" )
687
- MAKE_CHAPTERS=false
688
- ;;
689
- "-titlesets" )
690
- if $HAVE_MENU; then
691
- usage_error "You can not use -titlesets with -menu. Please use -topmenu instead."
692
- fi
693
- FORCE_TITLESETS=:
694
- echo "Creation of titlesets forced ..."
695
- ;;
696
- * )
697
- checkExistence "$1"
698
- addTitle "$1"
699
- ;;
700
- esac
701
- # Get the next argument
702
- shift
703
-done
704
-
705
-# Last argument should be the name of the output file
706
-if test -z "$OUT_PREFIX"; then
707
- usage_error "Please provide an output filename with -out."
708
-fi
709
-
710
-# See if selected output file exists. If so, confirm for overwrite.
711
-if test -e "$OUT_PREFIX.xml"; then
712
- echo $SEPARATOR
713
- echo "*** The output file you specified: $OUT_PREFIX.xml already exists."
714
- if $OVERWRITE; then
715
- echo "Overwriting existing file."
716
- else
717
- echo "Please re-run the script with the -overwrite option to overwrite."
718
- exit 1
719
- fi
720
- echo $SEPARATOR
721
-fi
722
-
723
-
724
-# Close current titleset
725
-closeTitleset
726
-
727
-# Fill in top menu buttons
728
-TOP_MENU_XML=$(echo "$TOP_MENU_XML" | \
729
- sed -e "s/__TOP_MENU_BUTTONS__/$(sedprep "$TOP_MENU_BUTTONS" /)/g")
730
-
731
-# If there is a top menu with no other menus, print an error and
732
-# a suggestion that user specify -menu instead of -topmenu
733
-if $HAVE_TOP_MENU && ! $HAVE_MENU && ! $FORCE_TITLESETS; then
734
- echo "You have specified a top menu without any other menus. If you only want to have one menu, please use the -menu option instead of -topmenu."
735
- echo "Exiting without writing XML file."
736
- exit 1
737
-fi
738
-
739
-# Assemble the final XML file
740
-
741
-# dvdauthor format for a DVD
742
-if test $XML_FORMAT = "dvd" ; then
743
-FINAL_DISC_XML=`cat << EOF
744
-<dvdauthor dest="$OUT_PREFIX">
745
-<!-- makexml $TOVID_VERSION -->
746
-<vmgm>
747
-$TOP_MENU_XML
748
-</vmgm>
749
-$ALL_MENU_XML
750
-</dvdauthor>
751
-EOF`
752
-
753
-# vcdxbuild (vcdimager) format for a VCD or SVCD
754
-else
755
- # Determine what version number to use
756
- if test $XML_FORMAT = "vcd" ; then
757
- VCD_VERSION="2.0"
758
- OPTION_LINE=''
759
- # Use 1.0 for SVCD
760
- else
761
- VCD_VERSION="1.0"
762
- OPTION_LINE='<option name="update scan offsets" value="true" />'
763
- fi
764
-
765
- # Make sure there are segment-items and sequence-items
766
- if test -n "$SEGMENT_ITEMS_XML" ; then
767
- SEGMENT_ITEMS_XML=`cat << EOF
768
-<segment-items>
769
-$SEGMENT_ITEMS_XML
770
-</segment-items>
771
-EOF`
772
- fi
773
- if test -n "$SEQUENCE_ITEMS_XML" ; then
774
- SEQUENCE_ITEMS_XML=`cat << EOF
775
-<sequence-items>
776
-$SEQUENCE_ITEMS_XML
777
-</sequence-items>
778
-EOF`
779
- fi
780
-
781
-FINAL_DISC_XML=`cat << EOF
782
-<?xml version="1.0"?>
783
-<!DOCTYPE videocd PUBLIC "-//GNU/DTD VideoCD//EN"
784
- "http://www.gnu.org/software/vcdimager/videocd.dtd">
785
-<videocd xmlns="http://www.gnu.org/software/vcdimager/1.0/"
786
- class="$XML_FORMAT" version="$VCD_VERSION">
787
-$OPTION_LINE
788
-<info>
789
- <album-id>VIDEO_DISC</album-id>
790
- <volume-count>1</volume-count>
791
- <volume-number>1</volume-number>
792
- <restriction>0</restriction>
793
-</info>
794
-
795
-<pvd>
796
- <volume-id>VIDEO_DISC</volume-id>
797
- <system-id>CD-RTOS CD-BRIDGE</system-id>
798
-</pvd>
799
-
800
-$SEGMENT_ITEMS_XML
801
-
802
-$SEQUENCE_ITEMS_XML
803
-
804
-<pbc>
805
-$TOP_MENU_XML
806
-
807
-$PBC_XML
808
-</pbc>
809
-</videocd>
810
-EOF`
811
-fi
812
-
813
-# Remove blank lines and write final result to output file
814
-echo "$FINAL_DISC_XML" | sed -e '/^ *$/d' > "$OUT_PREFIX.xml"
815
-
816
-echo "Done. The resulting XML was written to $OUT_PREFIX.xml."
817
-
818
-if ! $QUIET; then
819
- if test $XML_FORMAT = "dvd" ; then
820
- echo "You can now author, image and/or burn the disc by running:"
821
- echo " tovid dvd \"$OUT_PREFIX.xml\""
822
- else
823
- echo "You can create the (S)VCD .bin and .cue files by running the command:"
824
- echo " tovid vcd \"$OUT_PREFIX.xml\""
825
- fi
826
- echo "Thanks for using makexml!"
827
-fi
828
-
829
-exit 0
830
-
831
tovid-0.34.tar.bz2/src/postproc
Deleted
298
1
2
-#!/usr/bin/env bash
3
-ME="[postproc]:"
4
-. tovid-init 2>/dev/null ||
5
-{ echo -e "===============================================================\n"
6
-echo -e "'tovid-init' not found. Was tovid improperly installed?"
7
-echo -e "Or are you trying to run the script directly?"
8
-echo -e "Please run postproc as:\ntovid postproc OPTIONS"
9
-exit 1 ; }
10
-
11
-# postproc
12
-# Part of the tovid suite
13
-# =======================
14
-# A bash script for doing post-encoding processing on
15
-# MPEG video files. Can requantize (shrink) video and
16
-# adjust A/V sync.
17
-#
18
-# Project homepage: http://tovid.wikia.com
19
-#
20
-# Copyright (C) 2005-2010
21
-#
22
-# This program is free software; you can redistribute it and/or
23
-# modify it under the terms of the GNU General Public License
24
-# as published by the Free Software Foundation; either
25
-# version 2 of the License, or (at your option) any later
26
-# version.
27
-#
28
-# This program is distributed in the hope that it will be useful,
29
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
30
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
-# GNU General Public License for more details.
32
-#
33
-# You should have received a copy of the GNU General Public License
34
-# along with this program; if not, write to the Free Software
35
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
36
-#
37
-# http://www.gnu.org/licenses/gpl.txt
38
-
39
-SCRIPT_NAME=`cat << EOF
40
---------------------------------
41
-tovid postproc
42
-Post-process video files
43
-Version $TOVID_VERSION
44
-$TOVID_HOME_PAGE
45
---------------------------------
46
-EOF`
47
-
48
-USAGE=`cat << EOF
49
-Usage: tovid postproc [OPTIONS] {input file} {output file}
50
-
51
-Where OPTIONS may be any of the following:
52
-
53
- -audiodelay NUM Delay audio by NUM milliseconds
54
- -normalize Normalize the audio
55
- -amplitudeNUM[dB] Apply a gain of NUM (0 - 1.0, add dB for decibel gain)
56
- -shrink NUM Shrink video by factor NUM (1.0 - 2.0)
57
- -parallel Run all processes in parallel (can save time)
58
- -debug Keep a log of actions and output
59
-
60
-See the tovid manual page ('man tovid') for additional documentation.
61
-
62
-EOF`
63
-
64
-SEPARATOR="========================================================="
65
-
66
-# Default values
67
-TMP_FILE="postproc.fileinfo.$PPID"
68
-AUDIO_DELAY=""
69
-SHRINK_FACTOR=""
70
-DO_NORM=false
71
-AUDIO_AMPLITUDE=""
72
-DO_SHRINK=false
73
-MUX_OPTS=""
74
-DEBUG=false
75
-# File to use for saving postprocessing statistics
76
-STAT_DIR=$HOME/.tovid
77
-STAT_FILE="$STAT_DIR/stats.postproc"
78
-SHRINK_PERCENT="0"
79
-PARALLEL=false
80
-# Video format in use
81
-VIDEO_FORMAT="DVD"
82
-BACKGR=""
83
-
84
-# Print script name, usage notes, and optional error message, then exit.
85
-# Args: $1 == text string containing error message
86
-usage_error ()
87
-{
88
- echo "$USAGE"
89
- echo "$SEPARATOR"
90
- echo "$@"
91
- exit 1
92
-}
93
-
94
-# Remove temporary files
95
-cleanup ()
96
-{
97
- echo "Cleaning up..."
98
- rm -fv video_shrink video_dump audio_dump normed_audio
99
-
100
-}
101
-
102
-
103
-# ***********************************
104
-# EXECUTION BEGINS HERE
105
-# ***********************************
106
-
107
-echo "$SCRIPT_NAME"
108
-
109
-# Make sure there are at least two arguments (infile and outfile)
110
-if test $# -lt 2; then
111
- usage_error "Error: Please provide an input filename and an output filename."
112
-fi
113
-
114
-while test ${1:0:1} = "-"; do
115
- case "$1" in
116
- "-audiodelay" )
117
- shift
118
- AUDIO_DELAY="-O ${1}ms"
119
- ;;
120
- "-shrink" )
121
- shift
122
- DO_SHRINK=:
123
- SHRINK_FACTOR="$1"
124
- assert_dep "$transcode" "You are missing dependencies required for shrinking video!"
125
- ;;
126
- "-parallel" )
127
- PARALLEL=:
128
- cleanup
129
- mkfifo video_dump
130
- mkfifo audio_dump
131
- mkfifo video_shrink
132
- BACKGR="&"
133
- ;;
134
- "-normalize" )
135
- DO_NORM=:
136
- ;;
137
- "-amplitude" )
138
- shift
139
- AUDIO_AMPLITUDE="--amplitude=$1"
140
- DO_NORM=:
141
- ;;
142
- "-debug" )
143
- DEBUG=:
144
- ;;
145
- esac
146
-
147
- # Get next argument
148
- shift
149
-done
150
-
151
-
152
-IN_FILE="$1"
153
-shift
154
-OUT_FILE="$1"
155
-
156
-echo $SEPARATOR
157
-
158
-$DO_NORM && assert_dep "sox" "You are missing dependancies necessarily for processing audio wav's"
159
-if $DO_NORM && $PARALLEL; then
160
- echo "Cannot normalize audio in parallel mode! Turning off -parallel."
161
- PARALLEL=false
162
- cleanup
163
-fi
164
-
165
-# Figure out what format it is. 44.1khz audio can be VCD or SVCD,
166
-# 48khz audio is DVD.
167
-echo "Gathering file information. This may take a while."
168
-if eval $(idvid -terse "$IN_FILE"); then :; else
169
- echo "Could not identify source video: $IN_FILE"
170
- exit 1
171
-fi
172
-video_format=$(tr A-Z a-z <<< $ID_VIDEO_FORMAT)video
173
-
174
-if test $ID_AUDIO_RATE -eq "48000"; then
175
- MUX_OPTS="-V -f 8"
176
- VIDEO_FORMAT="DVD"
177
-elif test $ID_AUDIO_RATE -eq "44100"; then
178
- # VCD is 352 wide, SVCD is 480 wide
179
- if test $ID_VIDEO_WIDTH -eq "352"; then
180
- MUX_OPTS="-f 1"
181
- VIDEO_FORMAT="VCD"
182
- elif test $ID_VIDEO_WIDTH -eq "480"; then
183
- MUX_OPTS="-V -f 4"
184
- VIDEO_FORMAT="SVCD"
185
- fi
186
-fi
187
-
188
-echo "Dumping audio and video streams with the following commands:"
189
-
190
-# Dump audio and video
191
-if $DO_NORM; then
192
- AUDIO_DUMP="ffmpeg -i \"$IN_FILE\" -vn -f wav -y audio_dump"
193
-else
194
- #AUDIO_DUMP="mplayer \"$IN_FILE\" -quiet -dumpaudio -dumpfile audio_dump"
195
- AUDIO_DUMP="ffmpeg -i \"$IN_FILE\" -vn -f $ID_AUDIO_CODEC -acodec copy -y audio_dump"
196
-fi
197
-VIDEO_DUMP="ffmpeg -i \"$IN_FILE\" -an -f $video_format -vcodec copy -y video_dump"
198
-VID_STREAM="video_dump"
199
-
200
-echo "$AUDIO_DUMP"
201
-echo "$VIDEO_DUMP"
202
-# Should always be safe to put audio decode in the background
203
-eval $AUDIO_DUMP > $TMP_FILE 2>&1 &
204
-eval $VIDEO_DUMP >> $TMP_FILE 2>&1 $BACKGR
205
-
206
-# Let the audio process finish if not in parallel mode (should always finish
207
-# before video, so this is just precautionary)
208
-$PARALLEL || wait
209
-
210
-# Normalize/gain
211
-if $DO_NORM; then
212
- AUDIO_NORM="$NORMALIZE $AUDIO_AMPLITUDE audio_dump"
213
-
214
- echo "Normalizing audio/applying gain with the following command:"
215
- echo "$AUDIO_NORM"
216
- eval $AUDIO_NORM
217
-
218
- # Re-encode audio
219
- mv -v audio_dump normed_audio
220
- AUDIO_BITRATE=$(expr $ID_AUDIO_BITRATE / 1000)
221
- AUDIO_ENC="ffmpeg -i normed_audio -vn -ab ${AUDIO_BITRATE}k -ar $ID_AUDIO_RATE"
222
- AUDIO_ENC="$AUDIO_ENC -ac $ID_AUDIO_NCH -acodec $ID_AUDIO_CODEC"
223
- AUDIO_ENC="$AUDIO_ENC -y audio_dump.$ID_AUDIO_CODEC"
224
-
225
- echo "Encoding the normalized/gained audio stream with the following command:"
226
- echo "$AUDIO_ENC"
227
- eval $AUDIO_ENC
228
-
229
- mv -v audio_dump.$ID_AUDIO_CODEC audio_dump
230
-fi
231
-
232
-# Shrink, if requested
233
-if $DO_SHRINK; then
234
- # Can't shrink VCD
235
- if test $VIDEO_FORMAT = "VCD"; then
236
- echo $SEPARATOR
237
- echo "This file appears to be in VCD format. Unfortunately, the"
238
- echo "VCD specification does not allow shrinking (requantization)."
239
- echo "Shrinking will be skipped."
240
- echo $SEPARATOR
241
- else
242
- START_SIZE=$( ls -l video_dump | awk '{print $5}' )
243
- echo $SEPARATOR
244
- echo "Shrinking video stream by a factor of $SHRINK_FACTOR"
245
- SHRINK_CMD="tcrequant -i video_dump -o video_shrink -f $SHRINK_FACTOR"
246
- echo "$SHRINK_CMD"
247
- eval $SHRINK_CMD $BACKGR
248
- VID_STREAM="video_shrink"
249
- if $PARALLEL; then
250
- :
251
- else
252
- wait
253
- SHRINK_SIZE=$( ls -l video_shrink | awk '{print $5}' )
254
- SHRINK_PERCENT=$(expr 100 \- \( 100 \* $SHRINK_SIZE \/ $START_SIZE \))
255
- echo "Video stream was shrunk by $SHRINK_PERCENT%"
256
- fi
257
- fi
258
-fi
259
-
260
-echo $SEPARATOR
261
-
262
-# Multiplex audio and video back together
263
-echo "Multiplexing audio and video streams with the following command:"
264
-MPLEX_CMD="mplex $VID_STREAM audio_dump -o \"$OUT_FILE\" $MUX_OPTS $AUDIO_DELAY"
265
-echo "$MPLEX_CMD"
266
-eval $MPLEX_CMD >> $TMP_FILE 2>&1
267
-
268
-# For parallel, compare infile and outfile sizes
269
-if $PARALLEL; then
270
- START_SIZE=$( ls -l "$IN_FILE" | awk '{print $5}' )
271
- SHRINK_SIZE=$( ls -l "$OUT_FILE" | awk '{print $5}' )
272
- SHRINK_PERCENT=$(expr 100 \- \( 100 \* $SHRINK_SIZE \/ $START_SIZE \))
273
- echo "Video stream was shrunk by $SHRINK_PERCENT%"
274
-fi
275
-
276
-echo $SEPARATOR
277
-
278
-cleanup
279
-
280
-# Create stats directory and save video statistics
281
-mkdir -p $STAT_DIR
282
-FINAL_STATS=`cat << EOF
283
-postproc $TOVID_VERSION
284
-File: $OUT_FILE
285
-Shrink factor: $SHRINK_FACTOR
286
-Shrunk by: $SHRINK_PERCENT%
287
-EOF`
288
-echo $"$FINAL_STATS" >> $STAT_FILE
289
-
290
-# If doing debugging, keep log and print message
291
-if $DEBUG; then
292
- echo "All output has been saved in the file: $TMP_FILE."
293
-else
294
- rm $TMP_FILE
295
-fi
296
-
297
-echo "Done. Thanks for using postproc!"
298
tovid-0.34.tar.bz2/src/tovid-batch
Deleted
98
1
2
-#!/usr/bin/env bash
3
-ME="[tovid-batch]:"
4
-. tovid-init 2>/dev/null ||
5
-{ echo -e "===============================================================\n"
6
-echo -e "'tovid-init' not found. Was tovid improperly installed?"
7
-echo -e "Or are you trying to run the script directly?"
8
-echo -e "Please run tovid-batch as:\ntovid batch OPTIONS"
9
-exit 1 ; }
10
-
11
-# tovid-batch
12
-# Part of the tovid suite
13
-# =======================
14
-# A bash script for batch video conversion.
15
-#
16
-# Project homepage: http://tovid.wikia.com
17
-#
18
-# Copyright (C) 2005-2010
19
-#
20
-# This program is free software; you can redistribute it and/or
21
-# modify it under the terms of the GNU General Public License
22
-# as published by the Free Software Foundation; either
23
-# version 2 of the License, or (at your option) any later
24
-# version.
25
-#
26
-# This program is distributed in the hope that it will be useful,
27
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
28
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
-# GNU General Public License for more details.
30
-#
31
-# You should have received a copy of the GNU General Public License
32
-# along with this program; if not, write to the Free Software
33
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
34
-#
35
-# http://www.gnu.org/licenses/gpl.txt
36
-
37
-SCRIPT_NAME=`cat << EOF
38
---------------------------------
39
-tovid-batch
40
-A batch conversion script using tovid
41
-Part of the tovid suite, version $TOVID_VERSION
42
-$TOVID_HOME_PAGE
43
---------------------------------
44
-EOF`
45
-
46
-USAGE=`cat << EOF
47
-Usage: tovid batch [OPTIONS] -infiles <input files>
48
-
49
-OPTIONS may be any options that tovid accepts. See 'man tovid'.
50
-
51
-EOF`
52
-
53
-SEPARATOR="=============================================================================="
54
-
55
-# No tovid arguments to start with
56
-TOVID_ARGS=""
57
-
58
-# ***********************************
59
-# EXECUTION BEGINS HERE
60
-# ***********************************
61
-
62
-precho "$SCRIPT_NAME"
63
-
64
-# Get all arguments up to -infiles
65
-while test $# -gt 0; do
66
- if test "$1" = "-infiles"; then
67
- shift
68
- break
69
- else
70
- TOVID_ARGS="$TOVID_ARGS $1"
71
- fi
72
-
73
- # Get next argument
74
- shift
75
-done
76
-
77
-# If no infiles, print usage notes
78
-if test $# -le 0; then
79
- precho "$USAGE"
80
- echo "$SEPARATOR"
81
- echo "Please provide a list of files to encode using -infiles"
82
- exit 1
83
-fi
84
-
85
-# For every input filename provided, run tovid with the given options
86
-for FILE in "$@"; do
87
- echo $SEPARATOR
88
- if test -e "$FILE"; then
89
- EXT=$(echo "$FILE" | awk -F '.' '{ print $NF }')
90
- FILENAME=$(basename "$FILE" ."$EXT")
91
- TOVID_CMD="tovid mpg -noask $TOVID_ARGS -in \"$FILE\" -out \"$FILENAME.tovid_encoded\""
92
- precho $TOVID_CMD
93
- eval $TOVID_CMD
94
- else
95
- echo "Couldn't find file \"$FILE\", not encoding it."
96
- fi
97
-done
98
tovid-0.34.tar.bz2/src/tovid-interactive
Deleted
183
1
2
-#!/usr/bin/env bash
3
-ME="[tovid-interactive]:"
4
-. tovid-init 2>/dev/null ||
5
-{ echo -e "===============================================================\n"
6
-echo -e "'tovid-init' not found. Was tovid improperly installed?"
7
-echo -e "Or are you trying to run the script directly?"
8
-echo -e "Please run tovid-interactive as:\ntovid interactive OPTIONS"
9
-exit 1 ; }
10
-
11
-# tovid-interactive
12
-# Part of the tovid suite
13
-# =======================
14
-# A bash script with an interactive frontend to the tovid
15
-# script. This script prompts the user for all options, and
16
-# then runs the tovid script with the selected options.
17
-#
18
-# Project homepage: http://tovid.wikia.com
19
-#
20
-# Copyright (C) 2005-2010
21
-#
22
-# This program is free software; you can redistribute it and/or
23
-# modify it under the terms of the GNU General Public License
24
-# as published by the Free Software Foundation; either
25
-# version 2 of the License, or (at your option) any later
26
-# version.
27
-#
28
-# This program is distributed in the hope that it will be useful,
29
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
30
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
-# GNU General Public License for more details.
32
-#
33
-# You should have received a copy of the GNU General Public License
34
-# along with this program; if not, write to the Free Software
35
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
36
-#
37
-# http://www.gnu.org/licenses/gpl.txt
38
-
39
-WELCOME=`cat << EOF
40
---------------------------------
41
-tovid-interactive
42
-Interactive CLI front-end to tovid
43
-Part of the tovid suite, version $TOVID_VERSION
44
-$TOVID_HOME_PAGE
45
---------------------------------
46
-
47
-Welcome to the tovid-interactive script. This script is an interactive front-end for the tovid video conversion script. I will ask you several questions about the video you want to encode, and then run the tovid script with the options you choose.
48
-
49
-EOF`
50
-
51
-SEPARATOR="==============================================================================="
52
-
53
-precho $"$WELCOME"
54
-echo $SEPARATOR
55
-
56
-# Make sure tovid is in the path
57
-if ! test -x $(which tovid); then
58
- precho "Oops! I can't find tovid in your path. Before you use this script, please install the tovid suite by running the 'configure' script from the directory where you unzipped tovid."
59
- exit 1
60
-fi
61
-
62
-# 7 Get the file to encode
63
-echo "Step 1 of 7:"
64
-if test $# -eq 1; then
65
- INFILE="$1"
66
- echo "Encoding the filename provided on the command-line:"
67
- echo "$1"
68
- echo $SEPARATOR
69
-else
70
- INFILE=""
71
- if test $# -gt 1; then
72
- echo "I found more than one command line paramter! Please give only one"
73
- echo "video to encode. You gave me $#:"
74
- echo "$@"
75
- fi
76
- precho "What video file do you want to encode? Please use the full path name if the file is not in the current directory. Hint: if you don't know the full name of the file, you can press [control]-C now, and run tovid-interactive followed by the name of the file."
77
- while ! test -e "$INFILE"; do
78
- echo -n "filename: "
79
- read INFILE
80
- if ! test -e "$INFILE"; then
81
- echo "Cannot find \"$INFILE\"! Please try again."
82
- fi
83
- done
84
- echo $SEPARATOR
85
-fi
86
-
87
-# 6 Ask for format
88
-echo "Step 2 of 7:"
89
-echo "You can encode this video to one of the following formats:"
90
-echo "For burning onto DVD:"
91
-echo " dvd DVD format 720x480 NTSC, 720x576 PAL"
92
-echo " half-dvd Half-DVD format 352x480 NTSC, 352x576 PAL"
93
-echo " dvd-vcd VCD-on-DVD format 352x240 NTSC, 352x288 PAL"
94
-echo "For burning onto CD:"
95
-echo " vcd Video CD format 352x240 NTSC, 352x288 PAL"
96
-echo " svcd Super Video CD format 480x480 NTSC, 480x576 PAL"
97
-
98
-VIDFORMAT="none"
99
-until $(verify $VIDFORMAT set "dvd half-dvd dvd-vcd vcd svcd")
100
-do
101
- echo "Please enter one of the formats listed (dvd, half-dvd, dvd-vcd, vcd, svcd)."
102
- echo -n "format: "
103
- read VIDFORMAT
104
-done
105
- echo $SEPARATOR
106
-
107
-# 5 Ask for NTSC or PAL
108
-echo "Step 3 of 7:"
109
-precho "Do you want the video to be NTSC or PAL? If you live in the Americas or Japan, you probably want NTSC; if you live in Europe, Australia, or New Zealand, you probably want PAL."
110
-
111
-TVSYS="none"
112
-until $(verify $TVSYS set "ntsc pal")
113
-do
114
- echo "Please use lowercase (ntsc, pal)."
115
- echo -n "ntsc or pal: "
116
- read TVSYS
117
-done
118
-echo $SEPARATOR
119
-
120
-# 4 Ask for aspect ratio
121
-echo "Step 4 of 7:"
122
-echo "You can encode to three different screen formats:"
123
-echo " full If your video is full-screen (4:3 aspect ratio)"
124
-echo " wide If your video is wide-screen (16:9 aspect ratio)"
125
-echo " panavision If your video is theatrical wide-screen (2.35:1 aspect ratio)"
126
-precho "If you choose wide or panavision, the video will be 'letterboxed' to fit a standard TV screen. Most TV programs are 'full'; many movies are 'wide', and some movies are 'panavision' (if they look very wide and skinny)."
127
-
128
-ASPECT="none"
129
-until $(verify $ASPECT set "full wide panavision")
130
-do
131
-echo "Please enter one of the screen formats listed (full, wide, panavision)."
132
-echo -n "screen format: "
133
-read ASPECT
134
-done
135
-echo $SEPARATOR
136
-
137
-# 3 Normalize audio?
138
-echo "Step 5 of 7:"
139
-precho "In some videos, the volume may be too quiet or too loud. You can fix this by normalizing the audio."
140
-
141
-NORMALIZE="none"
142
-until $(verify $NORMALIZE set "n N y Y yes Yes")
143
-do
144
-echo -n "normalize audio (default yes) [y/n]? "
145
-read NORMALIZE
146
-done
147
-if test "x$NORMALIZE" = "xn" || test "x$NORMALIZE" = "xN"; then
148
- NORMALIZE=""
149
-else
150
- NORMALIZE="-normalize"
151
-fi
152
-echo $SEPARATOR
153
-
154
-# 2 Any custom options?
155
-echo "Step 6 of 7:"
156
-precho "Would you like to pass other options to tovid? (see man tovid for more) Add any other options you want as if you were calling tovid. For example, if you wanted to add subtitles, you would type '-subtitles <file>'. Type [enter] for no custom options."
157
-echo -n "custom tovid options: "
158
-read CUSTOM_OPTIONS
159
-echo $SEPARATOR
160
-
161
-# 1 Get output prefix
162
-echo "Step 7 of 7:"
163
-precho "You are almost ready to encode your video. All I need now is the name you want to use for the output file. You don't need to give a filename extension (like .mpg); just type a name like 'MyVideo1'."
164
-echo -n "output name: "
165
-read OUT_PREFIX
166
-echo $SEPARATOR
167
-
168
-# Print last message and call tovid
169
-echo "Great! I will now start tovid with the options you chose. Here is the"
170
-echo "command that will be executed:"
171
-TOVID_CMD="tovid $NORMALIZE -$VIDFORMAT -$TVSYS -$ASPECT $CUSTOM_OPTIONS -in \"$INFILE\" -out \"$OUT_PREFIX\""
172
-echo $SEPARATOR
173
-precho "$TOVID_CMD"
174
-echo $SEPARATOR
175
-echo "Starting tovid in 5 seconds..."
176
-for COUNTER in 5 4 3 2 1; do
177
- sleep 1s
178
- echo -n "$COUNTER "
179
-done
180
-echo "Here goes!"
181
-eval $TOVID_CMD
182
-exit 0
183
tovid-0.34.tar.bz2/INSTALL -> tovid-0.35.tar.gz/INSTALL
Changed
32
1
2
3
This file contains configuration and installation instructions for tovid.
4
5
-!!!!
6
-NOTE: Prior releases of tovid used autoconf and automake, but these will
7
-be discontinued in a future release. As of tovid-0.33, setup.py is the
8
-recommended installation method.
9
-!!!!
10
-
11
-
12
=====================================================
13
INSTALLING FROM DISTRIBUTED SOURCE (*.tar.gz)
14
=====================================================
15
16
or
17
$ sudo ./setup.py install
18
19
+If you want to install to somewhere other than /usr/local, you can use:
20
+ $ su -c './setup.py install --prefix=/opt' for example.
21
+Note: with some versions of python's distutils this will by default install
22
+modules to .../site-packages rather than .../dist-packages even if that is
23
+where your system's python looks for them. See:
24
+https://bugs.launchpad.net/ubuntu/+source/python2.6/+bug/362570
25
+As a workaround, if you are using --prefix you can add:
26
+ --install-layout=deb .
27
+
28
+
29
If you want to uninstall tovid, do this:
30
31
$ su -c './setup.py uninstall'
32
tovid-0.34.tar.bz2/PKG-INFO -> tovid-0.35.tar.gz/PKG-INFO
Changed
9
1
2
Metadata-Version: 1.0
3
Name: tovid
4
-Version: 0.34
5
+Version: 0.35
6
Summary: UNKNOWN
7
Home-page: http://tovid.wikia.com/
8
Author: Eric Pierce
9
tovid-0.34.tar.bz2/docs/man/tovid.1 -> tovid-0.35.tar.gz/docs/man/tovid.1
Changed
1712
1
2
.TH "tovid manual" 1 "" ""
3
4
+
5
.SH Name
6
+
7
.P
8
tovid: Make DVDs from video files
9
10
.SH Description
11
+
12
.P
13
\fBtovid\fR is a command\-line tool for creating DVDs. It can encode your video
14
files to DVD\-compliant MPEG format, generate simple or complex DVD menus,
15
16
graphical interface is also provided to make the process even easier.
17
18
.P
19
-\fBNOTE\fR: As of tovid 0.32, this is the only manual page provided by tovid.
20
-There is now a single executable frontend to all functionality in the suite, so
21
-if you were expecting to find manpages for \fBtodisc\fR, \fBidvid\fR, \fBmakemenu\fR
22
-and their kin, they can all be found in the \fBtovid\fR manpage you are reading now.
23
+\fBNOTE\fR: As of tovid 0.35, the legacy scripts \fBmakemenu\fR and \fBmakexml\fR
24
+have been removed and no longer appear in this manpage.
25
+All of their functions and more can be done with the 'tovid disc' command,
26
+(todisc script). See \fBCommand:disc\fR and the wiki (http://tovid.wikia.com)
27
+for more info.
28
29
.P
30
+Also note that as of tovid 0.32, this is the only manual page provided by tovid.
31
+There is now a single executable frontend to all functionality in the suite, so
32
+if you were expecting to find manpages for \fBtodisc\fR, \fBidvid\fR, \fBmakempg\fR
33
+and their kin, they can all be found in the \fBtovid\fR manpage you are reading now.
34
And yes, this makes for a pretty large manual page. If you are viewing this
35
manpage from the command\-line \fBman\fR utility, which normally pages through the
36
\fBless\fR utility, you can skip to a section by searching with the \fB/\fR key,
37
38
to navigate.
39
40
.SH Usage
41
+
42
.P
43
\fBtovid\fR \fICOMMAND\fR [\fIOPTIONS\fR]
44
45
.P
46
Where \fICOMMAND\fR is one of the following:
47
48
+.P
49
+ Main Commands
50
+
51
+.TP
52
+\fBdisc\fR
53
+Encode, make menus, author, burn. (was \fBtodisc\fR. See \fBCommand:disc\fR)
54
.TP
55
\fBgui\fR
56
Start the tovid GUI (was \fBtodiscgui\fR. See \fBCommand:gui\fR)
57
.TP
58
\fBtitlesets\fR
59
-A tovid GUI wizard for multiple titlesets. (new: See \fBCommand:titlesets\fR)
60
-.TP
61
-\fBdisc\fR
62
-Create a DVD with menus (was \fBtodisc\fR. See \fBCommand:disc\fR)
63
+A GUI wizard for multiple titlesets. (new: See \fBCommand:titlesets\fR)
64
+
65
+.P
66
+ Helper Commands
67
+
68
.TP
69
\fBmpg\fR
70
Encode videos to MPEG format (was \fBtovid\fR. See \fBCommand:mpg\fR)
71
.TP
72
-\fBid\fR
73
-Identify one or more video files (was \fBidvid\fR. See \fBCommand:id\fR)
74
-.TP
75
-\fBmenu\fR
76
-Create an MPEG menu (was \fBmakemenu\fR. See \fBCommand:menu\fR)
77
-.TP
78
-\fBxml\fR
79
-Create (S)VCD or DVD .xml file (was \fBmakexml\fR. See \fBCommand:xml\fR)
80
-.TP
81
\fBdvd\fR
82
Author and/or burn a DVD (was \fBmakedvd\fR. See \fBCommand:dvd\fR)
83
.TP
84
-\fBvcd\fR
85
-Author and/or burn a VCD (was \fBmakevcd\fR. See \fBCommand:vcd\fR)
86
-.TP
87
-\fBpostproc\fR
88
-Post\-process an MPEG video file (was \fBpostproc\fR. See \fBCommand:postproc\fR)
89
+\fBid\fR
90
+Identify one or more video files (was \fBidvid\fR. See \fBCommand:id\fR)
91
.TP
92
\fBchapters\fR
93
A GUI using mplayer for setting chapter points. It will return a string of
94
-chapter points in a format recognized by 'tovid disc' (todisc) or
95
-by 'tovid gui', for the \fB\-chapters\fR option.
96
+chapter points to the terminal, in a format recognized by 'tovid disc'
97
+(todisc) or by 'tovid gui', for the \fB\-chapters\fR option.
98
99
.P
100
The \fIOPTIONS\fR differ for each command; run \fBtovid <command>\fR with no
101
further arguments to get help on a command, and what options it expects.
102
103
.SH Configuration
104
+
105
.P
106
Two configuration files are created the first time you run tovid:
107
108
.TP
109
\fB~/.tovid/preferences\fR
110
Defines working directory for all scripts.
111
-In addition you can define the output directory for makempg here.
112
+You can define the output directory for makempg here.
113
+The 'ffmpeg' executable can be set here: ffmpeg or avconv (TOVID_FFMPEG)
114
.TP
115
\fB~/.tovid/tovid.ini\fR
116
Includes command\-line options that should be passed to the various
117
-\fBtovid\fR sub\-commands.
118
+\fBtovid\fR sub\-commands. Note: each sub\-command has its own section,
119
+starting with the line [sub\-command], for example:
120
+.nf
121
+ [disc]
122
+ ; -no-warn
123
+ -static
124
+ -no-ask
125
+.fi
126
+
127
128
+
129
+.P
130
Edit these files if you wish to change your configuration.
131
132
+.P
133
The following environment variables are also honoured:
134
-TOVID_WORKING_DIR (working directory for all scripts).
135
-TOVID_OUTPUT_DIR (output directory for the makempg script).
136
+
137
+.nf
138
+ TOVID_HOME (directory containing preferences: ~/.tovid)
139
+ TOVID_WORKING_DIR (working directory for all scripts).
140
+ TOVID_OUTPUT_DIR (output directory for the makempg script).
141
+ TOVID_FFMPEG_CMD (the 'ffmpeg' executable to use: ffmpeg or avconv)
142
+.fi
143
+
144
+
145
+.P
146
+These will override 'TOVID_HOME', 'WORKING_DIR', 'OUTPUT_DIR',
147
+and 'TOVID_FFMPEG' if set in ~/.tovid/preferences.
148
149
.SH Command:gui
150
+
151
+.SH Usage
152
+
153
+.P
154
+\fBtovid gui\fR [\fIOPTIONS\fR]
155
+
156
.P
157
\fBtovid gui\fR starts the graphical user interface (GUI) for tovid. This is
158
-the easiest way to start creating DVDs with tovid. At this time, there are no
159
-additional command\-line options; the GUI controls take care of everything,
160
-and all help is integrated in the form of tooltips. You can also see
161
-**Command:disc ** for more detail about the options. Note: if you wish to
162
-make multiple titlesets on the same DVD use 'tovid titlesets', which is a wizard
163
-that uses the the tovid GUI. Chapter submenus can be made with 'tovid gui'
164
-however.
165
+the easiest way to start creating DVDs with tovid. The optional arguments
166
+\fIOPTIONS\fR are any option used by todisc ('tovid disc') which will save
167
+entering it manually, OR the full path to a saved script from the GUI.
168
+You can also combine these, but the script must be the FIRST option
169
+directly after \fBtovid gui\fR . (This option to save the contents of your
170
+project allows you to use it as a bash script later, or to reload the
171
+project to continue working with it at another time.)
172
+
173
+.P
174
+\fBtovid gui\fR will also take the option \fB\-\-position\fR, which denotes the
175
+screen position that the GUI will start at, in the form '+X+Y', similar to
176
+this part of the Xorg \-geometry string.
177
+
178
+.P
179
+All help is integrated in the form of tooltips. You can also see
180
+**Command:disc ** for more detail about the options. Note: if you wish to use
181
+a GUI to make multiple titlesets on the same DVD use \fB*tovid titlesets*\fR,
182
+which is a wizard that uses the the 'tovid gui. See \fB*Command:titlesets*\fR.
183
+
184
+.P
185
+Please note that although the interface may seem complex with so many options,
186
+you can create a fully functional DVD with only a few options on the opening
187
+tab of the GUI (select video files and an output name).
188
189
.SH Command:titlesets
190
+
191
.P
192
\fBtovid titlesets\fR will assist in making a DVD with multiple titlesets. It can
193
be started without any options, or you can feed it the path to a saved titleset
194
-script as an option.
195
+script as an option. The option to save a script is also useful as the resulting
196
+script can be run later from a terminal.
197
198
.SH Command:disc
199
+
200
.P
201
-\fBtovid disc\fR creates a DVD file\-system with menus, from a list of multimedia
202
-video files and their titles. As this is a low level script it is the easiest
203
-command line program for creating a DVD from start to finish, including
204
-automatically converting non\-compliant videos and prompting to burn at
205
-completion. It does animated menus, static thumbnail menus and text only
206
-menus. In addition, it can do slideshows, using images as input, and combine
207
-slideshows with videos. It supports sub\-menus for chapter breaks, configurable
208
-menu style, animated backgrounds and transparency effects.
209
+\fBtovid disc\fR creates a DVD file\-system with optional menus, from a list of
210
+multimedia video files and their titles. As todisc can function as a master
211
+script, calling other scripts as it needs them, it is the easiest command line
212
+program for creating a DVD from start to finish, including automatically
213
+converting non\-compliant videos and prompting to burn at completion. It can do
214
+animated menus, static thumbnail menus, text\-only menus, or author with no menu.
215
+In addition, it can do slideshows, using images as input, and even combine
216
+slideshows with videos. It supports sub\-menus for chapter breaks,
217
+configurable menu style, animated backgrounds and transparency effects.
218
+From simple (no menu) to complex (switched menus and titlesets), you should
219
+be able to do what you want with 'tovid disc'.
220
221
.SS Usage
222
+
223
.nf
224
- tovid disc [OPTIONS] \e
225
- -files <file list> -titles <title list>
226
- -out OUT_PREFIX
227
+ tovid disc [OPTIONS] \e
228
+ -files <file list> -titles <title list>
229
+ -out mydvd
230
.fi
231
232
233
234
For example:
235
236
.nf
237
- $ tovid disc -files File1.mpg File2.mpg File3.mpg \e
238
- -titles "Episode 1" "Episode 2" "Episode 3" \e
239
- -out Season_one
240
+ $ tovid disc -files File1.mpg File2.mpg File3.mpg \e
241
+ -titles "Episode 1" "Episode 2" "Episode 3" \e
242
+ -out Season_one
243
.fi
244
245
246
247
as titles. If you are doing a slideshow or multiple slideshows, use
248
\fB\-slides\fR rather than \fB\-files\fR for passing in the images. You may use
249
\-files and \-slides more than once to create an ordering in a mixed
250
-slideshows/videos menu. See SLIDESHOWS part of Usage section, below.
251
+slideshows/videos menu. See Slideshows part of Usage section, below.
252
253
.P
254
If the input files are not mpeg, you will have the option to auto\-encode them.
255
256
.P
257
+General Options
258
+
259
+.P
260
\fBAt present there are 2 display arrangements or "templates":\fR
261
262
.TP
263
264
sub\-menus, which can display longer titles, for example:
265
266
.nf
267
- $ tovid disc -submenus \e
268
- -files file1.mpg file2.mpg ... \e
269
- -titles "Short 1" "Short 2" \e
270
- -submenu-titles "Long Title One" "Long Title Two" \e
271
- -out foo
272
-
273
+ $ tovid disc -submenus \e
274
+ -files file1.mpg file2.mpg ... \e
275
+ -titles "Short 1" "Short 2" \e
276
+ -submenus \e
277
+ -submenu-titles "Long Title One" "Long Title Two" \e
278
+ -out foo
279
+
280
.fi
281
282
283
.P
284
The \fB\-align\fR argument will position both titles and thumbs either south,
285
north east, west, southwest, northwest, southeast, northeast, subject to
286
-certain constraints of each arrangement.
287
+certain constraints of each arrangement. For example a showcase style with
288
+a showcase thumb can only do north|south|center.
289
+
290
+.P
291
+More Examples:
292
+
293
+.P
294
+A text\-only menu:
295
+
296
+.nf
297
+ $ tovid disc -textmenu ...
298
+.fi
299
+
300
+
301
+.P
302
+No menu:
303
+
304
+.nf
305
+ $ tovid -nomenu -files file1.mpg file2.mp4 "file 3.avi" -out mydvd
306
+.fi
307
+
308
309
.P
310
\fBTitlesets\fR
311
312
313
.P
314
Any options outside the \fB\-titleset\fR \fB\-end\-titleset\fR and \fB\-vmgm\fR
315
-\fB\-end\-vmgm\fR areas will be general options applying to every titleset.
316
-If a general option is duplicated inside a \fB\-titleset\fR or \fB\-vmgm\fR area, the
317
-general option will be overridden.
318
+\fB\-end\-vmgm\fR areas will be global options applying to every titleset.
319
+If a global option is duplicated inside a \fB\-titleset\fR or \fB\-vmgm\fR area, the
320
+global option will be overridden.
321
322
.P
323
Note: you do not need titlesets for a single menu with chapter break menus, for
324
325
Example of using \fBtovid disc\fR with titlesets:
326
327
.nf
328
- $ tovid disc -static -out MY_DVD \e
329
- \e
330
- -titleset -files 1.mpg 2.mpg 3.mpg \e
331
- -titles "Title One" "Title Two" "Title Three" \e
332
- -end-titleset \e
333
- \e
334
- -titleset -files 4.mpg 5.mpg \e
335
- -titles "Title Four" "Title Five" \e
336
- -background foo.jpg \e
337
- -showcase bar.png \e
338
- -end-titleset \e
339
- \e
340
- -vmgm \e
341
- -titles "Season One" "Season Two" \e
342
- -background bg.jpg \e
343
- -bgaudio foo.mp3 \e
344
- -titles-fontsize 20 \e
345
- -end-vmgm
346
+ $ tovid disc -static -out MY_DVD \e
347
+ \e
348
+ -titleset \e
349
+ -files 1.mpg 2.mpg 3.mpg \e
350
+ -titles "Title One" "Title Two" "Title Three" \e
351
+ -end-titleset \e
352
+ \e
353
+ -titleset \e
354
+ -files 4.mpg 5.mpg \e
355
+ -titles "Title Four" "Title Five" \e
356
+ -background foo.jpg \e
357
+ -showcase bar.png \e
358
+ -end-titleset \e
359
+ \e
360
+ -vmgm \e
361
+ -titles "Season One" "Season Two" \e
362
+ -background bg.jpg \e
363
+ -bgaudio foo.mp3 \e
364
+ -titles-fontsize 20 \e
365
+ -end-vmgm
366
.fi
367
368
369
370
Example of a single slideshow with an animated menu with transitions:
371
372
.nf
373
- $ tovid disc -menu-title "Autumn in Toronto" -slides images/*.jpg \e
374
- -menu-slide-total 20 -slide-transition crossfade -bgaudio slideshow.wav \e
375
- -out myslideshow
376
+ $ tovid disc -menu-title "Autumn in Toronto" -slides images/*.jpg \e
377
+ -menu-slide-total 20 -slide-transition crossfade -bgaudio slideshow.wav \e
378
+ -out myslideshow
379
.fi
380
381
+
382
.P
383
Example of multiple slideshows on one menu:
384
385
.nf
386
- $ tovid disc -menu-title "Autumn in Toronto" \e
387
- -slides photos/september/*.jpg \e
388
- -slides photos/october/*.jpg \e
389
- -slides photos/november/*.jpg \e
390
- -tile3x1 -rotate -5 5 -5 -align center \e
391
- -bgaudio background.wav \e
392
- -out myslideshow
393
+ $ tovid disc -menu-title "Autumn in Toronto" \e
394
+ -slides photos/september/*.jpg \e
395
+ -slides photos/october/*.jpg \e
396
+ -slides photos/november/*.jpg \e
397
+ -tile3x1 -rotate -5 5 -5 -align center \e
398
+ -bgaudio background.wav \e
399
+ -out myslideshow
400
.fi
401
402
+
403
.P
404
Example of mixed videos and slideshows:
405
406
.nf
407
- $ tovid disc -menu-title "Autumn in Toronto" \e
408
- -files fall_fair.mov \e
409
- -slides photos/september/*.jpg \e
410
- -files harvest.mpg \e
411
- -slides photos/october/*.jpg \e
412
- -titles "Fall Fair" "September" "Harvest" "October" \e
413
- -background autumn.png \e
414
- -bgaudio bg.mp3 \e
415
- -out myslideshow
416
+ $ tovid disc -menu-title "Autumn in Toronto" \e
417
+ -files fall_fair.mov \e
418
+ -slides photos/september/*.jpg \e
419
+ -files harvest.mpg \e
420
+ -slides photos/october/*.jpg \e
421
+ -titles "Fall Fair" "September" "Harvest" "October" \e
422
+ -background autumn.png \e
423
+ -bgaudio bg.mp3 \e
424
+ -out myslideshow
425
.fi
426
427
428
.P
429
-See the other slideshow options in the SLIDESHOWS options section.
430
+See the other slideshow options in the Slideshows options section.
431
432
.P
433
\fBEncoding Options\fR
434
435
\fB\-vbitrate\fR, \fB\-quality\fR, \fB\-safe\fR, \fB\-crop\fR, \fB\-filters\fR,
436
\fB\-abitrate\fR, \fB\-priority\fR, \fB\-deinterlace\fR, \fB\-progressive\fR,
437
\fB\-interlaced\fR, \fB\-interlaced_bf\fR, \fB\-type\fR, \fB\-fit\fR, \fB\-discsize\fR,
438
- \fB\-parallel\fR, \fB\-mkvsub\fR, \fB\-autosubs\fR, \fB\-subtitles\fR, \fB\-update\fR, \e
439
+ \fB\-parallel\fR, \fB\-mkvsub\fR, \fB\-autosubs\fR, \fB\-subtitles\fR, \fB\-update\fR,
440
\fB\-mplayeropts\fR, \fB\-audiotrack\fR, \fB\-downmix\fR, \fB\-ffmpeg\fR, \fB\-nofifo\fR,
441
\fB\-from\-gui\fR, \fB\-slice\fR, \fB\-quiet\fR,
442
\fB\-fake\fR, \fB\-keepfiles\fR
443
444
-.SS Options
445
+.SS General Options
446
+
447
.TP
448
\fB\-keep\-files\fR, \fB\-keepfiles\fR
449
Keep all intermediate/temporary files (helps with debugging)
450
.TP
451
+\fB\-no\-ask\fR | \fB\-noask\fR
452
+Skip all interactive questions. No preview, automatic re\-encoding with
453
+tovid if needed, no interactive option to use background video for bgaudio.
454
+.TP
455
+\fB\-no\-warn\fR, \fB\-nowarn\fR
456
+Don't pause after outputting warning or info messages
457
+.TP
458
+\fB\-jobs\fR
459
+By default, \fBtovid disc\fR starts a parallel job for each processor
460
+detected. With this option you can manually set the number of jobs. For
461
+example if you have a computer with 2 CPUs you can set "\-jobs 1" to keep
462
+one processor free for other things. At present this applies to the time
463
+consuming imagemagick loops: you will notice a substantial speedup now if
464
+you have a multi\-cpu system.
465
+.TP
466
+\fB\-grid\fR
467
+Show a second preview image with a grid and numbers that will help in finding
468
+coordinates for options that might use them, like \fB\-text\-start\fR
469
+.TP
470
+\fB\-no\-confirm\-backup\fR
471
+This option is for when your DVD contains images for a slideshow.
472
+Slideshows are an experimental (but well tested) feature. Todisc is
473
+unlikely to overwrite your personal files, but you should take precautions
474
+and backup your images, as you would with any beta software. Todisc
475
+will prompt you to backup your files normally. If you have already backed
476
+up your images, use this option to disable the prompt.
477
+
478
+==Options==
479
+
480
+.TP
481
\fB\-ntsc\fR
482
720x480 output, compatible with NTSC standard (default)
483
.TP
484
485
\fB\-no\-menu | \-nomenu\fR
486
With this option todisc will just create a DVD file system, ready for
487
burning, with NO MENU, just the supplied video files. These do not need
488
-to be compliant, as non\-compliant files will be encoded as usual. Each
489
-video will be a chapter unless \fB\-chapters\fR OPTION is passed. The
490
-\fB\-chapters\fR option is a number indicating the chapter interval in
491
-minutes, or a HH:MM:SS string indicating chapter points. See \fB\-chapters\fR
492
+to be compliant, as non\-compliant files will be encoded as usual. The
493
+\fB\-out\fR option is not required. Each video will be a chapter unless
494
+\fB\-chapters\fR OPTION is passed. The \fB\-chapters\fR option is a number
495
+indicating the chapter interval in minutes, or a HH:MM:SS string
496
+indicating chapter points. See \fB\-chapters\fR
497
+.TP
498
+\fB\-encode\-only\fR
499
+This option was originally meant for the GUI, to allow it to be used for
500
+just encoding rather than making a DVD structure. But it works well from
501
+the command line as well as it has the added advantage that you can input
502
+a list of files. Remember any makempg ('tovid mpg') options you use will
503
+be passed on to the makempg script when encoding.
504
505
.SS Menu style
506
+
507
.TP
508
\fB\-showcase\fR IMAGE|VIDEO
509
If used without an argument, use showcase style without a central thumb.
510
This is a different arrangement of images for the menu: small thumbnails
511
go at left (and right) side of screen, with a larger image in the centre.
512
Maximum of 10 videos. If the provided argument is a video file, the
513
-central thumb will be animated. Only 4:3 or 16:9 videos and images are
514
-accepted for the showcase file: if not one of these todisc will assume it
515
-is the same ratio as the videos in the titleset.
516
+central thumb will be animated (regardless of whether \fB\-static\fR is part
517
+of the command line). Only 4:3 or 16:9 videos and images are accepted for
518
+for the showcase file: if not one of these todisc will assume it is the
519
+aspect ratio as the videos in the titleset.
520
.TP
521
\fB\-textmenu\fR, \fB\-text\-menu\fR NUM
522
If used without an argument, create a textmenu out of the supplied titles
523
524
i.e. giving 4 titles and using "\-textmenu 2" would make 2 columns of 2
525
titles. The default is to put all titles up to 13 in the first column
526
before starting a second column. Maximum: 2 columns and 26 titles.
527
-Note that column 2 titles are aligned to the right.
528
-If no video files for either \fB\-background\fR or \fB\-showcase\fR are supplied,
529
-the menu will be static.
530
+Note that column 2 titles are justified to the left unless you add
531
+\fB\-edge\-justify\fR to the command line. The menu will be static if no video
532
+files are supplied with either \fB\-background\fR or \fB\-showcase\fR options.
533
.TP
534
\fB\-quick\-menu\fR
535
If you are using ffmpeg 0.8 or newer you can use this option. This will
536
537
text\-menu style of menu, with no video thumbs, and a central showcase
538
IMAGE(static) | VIDEO(animated).
539
(i) see \fB\-bg\-color\fR if you are not using a \fB\-background\fR and want to
540
-change the default black )
541
-(ii) Note: todisc will still work with vhooks if you have an old ffmpeg with
542
-vhooks compiled in.
543
+change the default. (default is dark blue for \-quick\-menu arrangements). )
544
+(ii) Note: todisc will still work with 'vhooks' if you have an old ffmpeg
545
+with vhooks compiled in.
546
547
Specifying the IMAGE|VIDEO argument to \fB\-showcase\fR is mandatory for this
548
style of menu, unless used in conjunction with \fB\-switched\-menus\fR
549
in which case the videos passed with \fB\-files\fR automatically become the
550
-showcase videos. If this is used in combination with \fB\-switched\-menus\fR
551
-it can really speed up an otherwise time consuming process.
552
+showcase videos. If \fB\-quick\-menu\fR is used in combination with
553
+\fB\-switched\-menus\fR it really speeds up an otherwise time consuming process.
554
555
Example:
556
.nf
557
- -quick-menu -showcase /home/robert/showcase.mpg
558
+ -quick-menu -showcase /home/grepper/showcase.mpg
559
.fi
560
561
+
562
See \fB\-switched\-menus\fR for example of making switched menus with
563
\fB\-quick\-menu\fR
564
565
566
The color to use for the menu background. (default: ntsc\-safe black)
567
Note: use a color a great deal darker than you want, as it appears quite
568
a bit lighter in the video version. You can use hexadecimal ('#ffac5f')
569
-or named colors notation.
570
+notation or named colors ('Lime'). convert \-list color will show them.
571
+See colors (http://www.imagemagick.org/script/color.php) for more details.
572
.TP
573
\fB\-submenu\-bg\-color\fR, \fB\-submenu\-bg\-colour\fR
574
The color to use as background for the submenu(s).
575
576
a 'moving' menu, in spite of the static buttons. This option also does
577
double duty for the \fB\-switched\-menus\fR option, and will create static
578
"switched" images.
579
-See also \fB\-switched\-menu\fR
580
+See also \fB\-switched\-menus\fR
581
.TP
582
\fB\-background\fR IMAGE|VIDEO
583
Menu background. This can be a image file or an video file. If it is a
584
585
\fB\-menu\-title\fR
586
Title for the root menu \- may be longer than thumbnail labels
587
Also if you use \en in the title, you can use multi line titles, but you
588
-would need to adjust \fB\-menu\-fontsize\fR to something smaller than default
589
+would need to adjust \fB\-title\-fontsize\fR to something smaller than default
590
for example:
591
592
.nf
593
- $ tovid disc ... -menu-title "A\enMultilined\enTitle" -menu-fontsize 24
594
+ $ tovid disc ... -menu-title "A\enMultilined\enTitle" -title-fontsize 24
595
.fi
596
597
+
598
.TP
599
-\fB\-menu\-font\fR FONT
600
+\fB\-title\-font\fR, \fB\-menu\-font\fR FONT
601
Font to use for titles, either by ImageMagick font name (ex., "Arial") or
602
explicit pathname (ex., "/full/path/to/arial.ttf"). To see a complete
603
list of acceptable ImageMagick font names, run \fBconvert \-list type\fR, and
604
refer to the leftmost column
605
.TP
606
-\fB\-menu\-fontsize\fR
607
+\fB\-title\-fontsize\fR, \fB\-menu\-fontsize\fR
608
Font size for main menu \- best to \-preview if you use this
609
.TP
610
\fB\-submenu\-font\fR
611
-Font to use for the sub\-menu main titles. See \fB\-menu\-font\fR
612
+Font to use for the sub\-menu main titles. See \fB\-title\-font\fR
613
.TP
614
\fB\-submenu\-fontsize\fR
615
Font size for the sub\-menu main titles
616
617
\fB\-skip\-vmgm\fR
618
Start DVD from the first titleset instead of the VMGM ( root ) menu.
619
.TP
620
-\fB\-switched\-menus\fR
621
+\fB\-switched\-menus\fR, \fB\-switched\-menu\fR
622
This will make a "switched menu": there will be a central image where the
623
showcase image would go, and text menu titles along the menu edge where
624
textmenu titles go. As you select a video title with the down or up arrow
625
626
627
Example for using with \fB\-quick\-menu\fR:
628
.nf
629
- -switched-menus -quick-menu
630
+ -switched-menus -quick-menu
631
.fi
632
633
634
+
635
.SS Thumbnail style
636
+
637
+.TP
638
+\fB\-titles\-font\fR FONT
639
+Display thumbnail or textmenu titles in the given font
640
+.TP
641
+\fB\-titles\-fontsize\fR POINTS
642
+Font size to use for thumbnail or textmenu titles
643
.TP
644
\fB\-thumb\-shape\fR
645
normal|oval|vignette|plectrum|arch|spiral|blob|star|flare
646
647
\fB\-3d\-thumbs\fR, \fB\-3dthumbs\fR
648
This will give an illusion of 3D to the thumbnails: dynamic lighting on
649
rounded thumbs, and a raised effect on rectangular thumbs. Try it !
650
-.TP
651
-\fB\-titles\-font\fR FONT
652
-Display thumbnail or textmenu titles in the given font
653
-.TP
654
-\fB\-titles\-fontsize\fR POINTS
655
-Font size to use for thumbnail or textmenu titles
656
657
.SS Slideshows
658
+
659
.TP
660
\fB\-slides\fR IMAGES
661
Use \fB\-slides\fR IMAGES to pass in images for a slideshow. The default is
662
663
be static. If you used with a mixed menu of videos and slideshows, then
664
the video thumbs WILL be animated, so you may wish to use \-static or
665
\-textmenu with the option in that case. If you want to use the
666
-**\-switched\-menus option with a mixed menu leave this option out.
667
+**\-switched\-menus option with a mixed menu leave this option out.
668
669
.TP
670
\fB\-background\-slideshow\fR, \fB\-bg\-slideshow\fR
671
672
and backup your images, as you would with any beta software. Todisc
673
will prompt you to backup your files normally. If you have already backed
674
up your images, use this option to disable the prompt.
675
+See \fBGeneral Options\fR
676
677
.TP
678
\fB\-use\-dvd\-slideshow\fR CONFIG (FILE)
679
680
override many of the above options for slideshows.
681
682
.SS Burning the disc
683
+
684
.TP
685
\fB\-burn\fR
686
Prompt to burn the DVD directory on completion.
687
688
\fB\-speed\fR
689
The speed to use for burning the disc.
690
691
-.SS ADVANCED USAGE
692
+.SS Advanced usage
693
+
694
.SS Options
695
+
696
.TP
697
\fB\-menu\-length\fR
698
The desired animated main menu length in seconds
699
700
The default is to use 10 seconds of audio for static menus.
701
.TP
702
\fB\-submenu\-stroke\fR COLOR
703
-The color for the sub\-menu font outline (stroke)
704
+The color for the sub\-menu font shadow
705
.TP
706
\fB\-submenu\-title\-color\fR, \fB\-submenu\-title\-colour\fR
707
The fill color used for sub\-menu title fonts
708
.TP
709
\fB\-submenu\-titles\fR
710
-You can supple a list of titles here for sub\-menus without the length
711
+You can supply a list of titles here for sub\-menus without the length
712
restrictions found in thumb titles. Must equal number of videos
713
.TP
714
\fB\-chapters\fR [ NUM | CHAPTER POINTS in HH:MM:SS ]
715
716
717
Example for passing just number of chapters ( 4 videos ):
718
.nf
719
- -chapters 5 2 4 8
720
+ -chapters 5 2 4 8
721
.fi
722
723
724
+
725
Example of passing chapter points ( 4 videos ):
726
.nf
727
- -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45 \e
728
- 00:00:00,00:04:25.623,00:09:12,00:15:51 \e
729
- 00:00:00,00:05:10,00:13:41,00:18:13.033 \e
730
- 00:00:00,00:15:23.342,00:26:42.523
731
+ -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45 \e
732
+ 00:00:00,00:04:25.623,00:09:12,00:15:51 \e
733
+ 00:00:00,00:05:10,00:13:41,00:18:13.033 \e
734
+ 00:00:00,00:15:23.342,00:26:42.523
735
.fi
736
737
738
+
739
Example of passing grouped chapters using the '+' separator:
740
.nf
741
- -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45+00:04:23,00:09:35 \e
742
- 00:00:00... etc.
743
+ -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45+00:04:23,00:09:35 \e
744
+ 00:00:00... etc.
745
.fi
746
747
748
+
749
.TP
750
\fB\-chapter\-titles\fR LIST
751
If you are using submenus, you can pass a list of titles for the
752
753
The color for the chapters font.
754
.TP
755
\fB\-chapter\-stroke\fR COLOR
756
-The color for the chapters font outline (stroke)
757
+The color for the chapters font shadow
758
759
.TP
760
\fB\-seek\fR NUM | "NUM1 NUM2 NUM3 . . ."
761
762
video. Example:
763
764
.nf
765
- -group 2 2.mpg 3.mpg 4.mpg
766
+ -group 2 2.mpg 3.mpg 4.mpg
767
.fi
768
769
770
+
771
will group these 3 videos with the 2nd video given with \fB\-files\fR, so that
772
they will play sequentially as one title. Only one thumbnail and/or title
773
will appear on the menu for the group: it will be made from the 1st video
774
in the group. In the above example if you passed:
775
.nf
776
- -files foo.mpg bar.mpg baz.mpg -group 2 2.mpg 3.mpg 4.mpg
777
+ -files foo.mpg bar.mpg baz.mpg -group 2 2.mpg 3.mpg 4.mpg
778
.fi
779
780
+
781
then the group will consist of bar.mpg 2.mpg, 3.mpg and 4.mpg, and only the
782
title and/or thumbnail for bar.mpg will appear in the menu. You can use
783
\fB\-group\fR more than once for multiple groups. Be sure to quote video
784
filenames if they contain spaces.
785
-.TP
786
-\fB\-jobs\fR
787
-By default, \fBtovid disc\fR starts a parallel job for each processor
788
-detected. With this option you can manually set the number of jobs. For
789
-example if you have a computer with 2 CPUs you can set "\-jobs 1" to keep
790
-one processor free for other things. At present this applies to the time
791
-consuming imagemagick loops: you will notice a substantial speedup now if
792
-you have a multi\-cpu system.
793
-.TP
794
-\fB\-no\-ask\fR, \fB\-noask\fR
795
-Skip all interactive questions. No preview, automatic re\-encoding with
796
-tovid if needed, no interactive option to use background video for bgaudio.
797
-.TP
798
-\fB\-no\-warn\fR, \fB\-nowarn\fR
799
-Don't pause after outputting warning or info messages
800
-.TP
801
-\fB\-grid\fR
802
-Show a second preview image with a grid and numbers that will help in finding
803
-coordinates for options that might use them, like \fB\-text\-start\fR
804
805
.SS Menu Style
806
+
807
.TP
808
\fB\-menu\-title\-geo\fR north|south|east|west|center [south]
809
The position of the menu title. You may need to use \-align as well if
810
811
may need to use \-align as well if you don't want your title covering other
812
parts of your menu. See \fB\-align\fR
813
.TP
814
-\fB\-button\-style\fR rect|text|line|text\-rect
815
+\fB\-button\-style\fR line|rect|text|text\-rect [line]
816
The style of button that you will see when you play the DVD.
817
-"rect" draws a rectangle around the thumb when you select it
818
-in the DVD player. "text" highlights the video title text, "line"
819
-underlines the title, and "text\-rect" draws a rectangle around the title
820
+"line" style underlines the title, "rect" draws a rectangle around the
821
+thumb when you select it in the DVD player, "text" highlights the video
822
+title text, and "text\-rect" draws a rectangle around the title
823
text.
824
.TP
825
\fB\-title\-color\fR, \fB\-title\-colour\fR COLOR
826
827
http://www.imagemagick.org/script/color.php
828
.TP
829
\fB\-title\-stroke\fR COLOR
830
-Outline color for the main menu's title font. Use "none" for transparent
831
-outline (see title\-color)
832
+Shadow color for the main menu's title font. Use "none" for transparent
833
+outline (see title\-color). Note: this is not a \-stroke in the sense that
834
+imagemagick uses the term, but a shadow (the font is drawn twice). To get
835
+a true imagemagick stroke see \fB\-title\-font\-deco\fR
836
+.TP
837
+\fB\-title\-font\-deco\fR, \fB\-title\-fontdeco\fR "IMAGEMAGICK STRING"
838
+Sets the font decoration method to FONTDECORATION. It is used by the 'convert'
839
+ImageMagick command to draw the menu text. You can add colored text
840
+outlines, gradient fills, and many others. See \fBUsage notes\fR
841
.TP
842
\fB\-titles\-stroke\fR COLOR
843
-Outline color for the thumb or textmenu video titles font. Use "none" for
844
-transparent outline (see \fB\-titles\-color\fR).
845
+Shadow color for the thumb or textmenu video titles font. Use "none" for
846
+transparent outline (see \fB\-titles\-color\fR). Note: this is not a \-stroke
847
+in the sense that imagemagick uses the term, but a shadow
848
+(the font is drawn twice). To get a true imagemagick stroke,
849
+see \fB\-titles\-font\-deco\fR
850
+.TP
851
+\fB\-titles\-font\-deco\fR, \fB\-titles\-fontdeco\fR "IMAGEMAGICK STRING"
852
+Sets the font decoration method to FONTDECORATION. It is used by the 'convert'
853
+ImageMagick command to draw the menu text. You can add colored text
854
+outlines, gradient fills, and others. See \fBUsage notes\fR for more info.
855
.TP
856
\fB\-highlight\-color\fR, \fB\-highlight\-colour\fR
857
Color to use for the menu buttons that your DVD remote uses to navigate.
858
859
At present it must be a DVD compatible video at the correct resolution etc.
860
Only 4:3 aspect is supported: 16:9 will give unexpected results.
861
862
-.SS Menu Style options specific to showcase and textmenu arrangements
863
+.SS Style options specific to showcase/textmenu arrangements
864
+
865
.TP
866
\fB\-text\-start\fR N
867
This option is for \fB\-textmenu\fR menus. The titles will start at the Nth
868
869
this will not turn a portait image into a landscape image!
870
.TP
871
\fB\-showcase\-geo\fR GEOMETRY
872
-The position of the showcase image. ( XxY position )
873
+The position of the showcase image. ( +X+Y position )
874
+For example: \fB\-showcase\-geo\fR +300+200
875
.TP
876
\fB\-wave\fR default|GEOMETRY
877
Wave effect for showcase image|video. Alters thumbs along a sine wave using
878
879
rounded thumbs, and a raised effect on rectangular thumbs. Try it !
880
881
.SS Thumbnail Style
882
+
883
.TP
884
-\fB\-user\-thumbs\fR IMAGE
885
+\fB\-user\-thumbs\fR IMAGE(S)
886
Supply your own images for menu buttons, rather than relying on todisc to
887
generate them from the video. They must be the same aspect ratio as the
888
videos in the titleset (4:3 or 16:9), as todisc will resize them without
889
-checking and cropping.
890
+checking and cropping. There must be on image for each thumb that will be
891
+displayed on the menu (ie. one thumb for each video in a titleset).
892
.TP
893
\fB\-opacity\fR [0\-100] (default 100)
894
Opacity of thumbnail videos as a percentage (no percent sign).
895
896
values between 0.1 and 2.0. This option has no effect on \fB\-3d\-showcase\fR.
897
See \fB\-thumb\-blur\fR for more info.
898
.TP
899
-\fB\-align\fR north|south
900
-This will align thumbs/titles north or south.
901
+\fB\-align\fR DIRECTION
902
+This will align thumbs/titles in DIRECTION, which is a compass direction
903
+as used by imagemagick: ie. north|south|east|west|northeast|northwest etc.
904
If \fB\-align\fR south then menu title will align north, unless you manually
905
set one or both of \fB\-menu\-title\-geo\fR or \fB\-menu\-title\-offset\fR.
906
+Only \fB\-align\fR north|south|center has any effect on showcase with thumb,
907
+or with the default montage arrangement of central thumbs. The most
908
+apparent changes with be with textmenu, though with 2 column arrangements
909
+only the north* and south* changes will show an effect.
910
+
911
+Diagram:
912
+.TP
913
+ . northwest north northeast .
914
+.TP
915
+ . .
916
+.TP
917
+ . west center east .
918
+.TP
919
+ . .
920
+.TP
921
+ . southwest south souteast .
922
.TP
923
\fB\-thumb\-mist\fR [COLOR]
924
Use a mist behind thumbnails. The optional argument is the color of the
925
926
showcase template the titles will remain the same size. Example:
927
928
.nf
929
- -rotate-thumbs -10 10 -10 10 -10 (for 5 files)
930
+ -rotate-thumbs -10 10 -10 10 -10 (for 5 files)
931
.fi
932
933
+
934
**Note: this option will not turn a portrait image into a landscape image!
935
936
.SS Dvdauthor options
937
+
938
.TP
939
\fB\-loop\fR PAUSE
940
Pause in seconds at end of menu. Use "inf" if you wish indefinite pause.
941
942
the \fB\-vmgm\fR ... \fB\-end\-vmgm\fR options to allow playing ALL titlesets.
943
(If you want also to have a playall button in each titleset you could use
944
this option between each \fB\-titleset\fR ... \fB\-end\-titleset\fR option or put
945
-it outside of the vmgm and titlset options as a general option.
946
+it outside of the vmgm and titlset options as a global option.
947
.TP
948
\fB\-videos\-are\-chapters\fR
949
A button will be made on the main menu for each video, which you can use as
950
951
xml file. It will affect all videos in the titleset. Example:
952
953
.nf
954
- -aspect 16:9
955
+ -aspect 16:9
956
.fi
957
958
+
959
.TP
960
\fB\-widescreen\fR nopanscan|noletterbox [nopanscan]
961
This will output a <video widescreen=nopanscan /> tag (for example)
962
963
Example:
964
965
.nf
966
- -aspect 16:9 -widescreen
967
+ -aspect 16:9 -widescreen
968
.fi
969
970
+
971
.TP
972
\fB\-quick\-nav\fR
973
This option will allow navigation of a menu with more than one titleset by
974
975
for the last video in the group. If providing a list of values they must
976
equal the number of grouped videos.
977
978
+.SS Usage notes
979
+
980
+.P
981
+The argument given to various *\-font options that set the font to use must be
982
+one of the fonts listed by the command 'convert \-list type'. Please note that
983
+many of your installed fonts may not be available; if you want to maximize the
984
+number of fonts available to todisc, download and run
985
+Anthony Thyssen's (http://www.cit.gu.edu.au/~anthony/anthony.html)
986
+imagick_type_gen (http://www.imagemagick.org/Usage/scripts/imagick_type_gen)
987
+script and run it like this:
988
+imagick_type_gen > ~/.magick/type.xml.
989
+If that doesn't work, try imagick_type_gen > ~/.magick/type.mgk.
990
+
991
+.P
992
+Or you can specify a ttf font file directly to the *\-font options if you don't
993
+want to install fonts to ImageMagick.
994
+
995
+.P
996
+The *\-stroke options in todisc are not a stroke in the sense that ImageMagick
997
+uses the term, but rather a font shadow (the text is drawn twice) To get a
998
+truer Imagemagick \-stroke try something like:
999
+\-title\-font\-deco "\-stroke black" (or \-titles\-font\-deco "\-stroke black"). The
1000
+\fB\-fontdeco\fR option is quite flexible and takes a lot of ImageMagick's
1001
+\fIconvert\fR options. Please refer to the tovid
1002
+wiki (http://tovid.wikia.com/wiki/Making_a_DVD_with_text_menus) and Anthony
1003
+Thyssen's guide [http://www.imagemagick.org/Usage] for further explanation and examples.
1004
+
1005
.SH Command:mpg
1006
+
1007
.P
1008
\fBtovid mpg\fR converts arbitrary video files into (S)VCD/DVD\-compliant
1009
MPEG format, suitable for burning to CD/DVD\-R for playback on a
1010
standalone DVD player.
1011
1012
.SS Usage
1013
+
1014
.P
1015
\fBtovid mpg\fR [\fIOPTIONS\fR] \fB\-in\fR \fIINFILE\fR \fB\-out\fR \fIOUTPREFIX\fR
1016
1017
1018
Convert 'foo.avi' to PAL VCD format, saving to 'foo_encoded.mpg'.
1019
1020
.SS Basic options
1021
+
1022
.TP
1023
\fB\-v\fR, \fB\-version\fR
1024
Print tovid version number only, then exit.
1025
1026
\fB\-subtitles\fR or \fB\-filters\fR.
1027
1028
.SS Television standards
1029
+
1030
.TP
1031
\fB\-ntsc\fR
1032
NTSC format video (USA, Americas) (default)
1033
1034
PAL format video (Europe and others)
1035
1036
.SS Formats
1037
+
1038
.P
1039
Standard formats, should be playable in most DVD players:
1040
1041
1042
format.
1043
1044
.SS Advanced options
1045
+
1046
.SS Aspect ratios
1047
+
1048
.P
1049
tovid automatically determines aspect ratio of the input video by playing it in
1050
mplayer. If your video plays with correct aspect in mplayer, you should not
1051
1052
for a widescreen monitor or TV.
1053
1054
.SS Video stream options
1055
+
1056
.TP
1057
\fB\-quality\fR \fINUM\fR (default 6)
1058
Desired output quality, on a scale of 1 to 10, with 10 giving the best
1059
1060
\fB\-bdvd\fR), for optimal viewing on a widescreen monitor or TV.
1061
1062
.SS Audio stream options
1063
+
1064
.TP
1065
\fB\-normalize\fR
1066
Analyze the audio stream and then normalize the volume of the audio.
1067
1068
will revert to the default behavior of using the original channels.
1069
1070
.SS Other options
1071
+
1072
.TP
1073
\fB\-config\fR \fIFILE\fR
1074
Read configuration from \fIFILE\fR, containing 'tovid' alone on the first
1075
1076
seconds.
1077
1078
.TP
1079
-\fB\-mplayeropts\fR \fB"\fR\fIOPTIONS\fR\fB"\fR
1080
+\fB\-mplayeropts\fR \fIOPTIONS\fR
1081
Append \fIOPTIONS\fR to the mplayer command run during video encoding. Use
1082
this if you want to add specific video filters (documented in the mplayer
1083
manual page). Overriding some options will cause encoding to fail, so use
1084
1085
answers.
1086
1087
.SH Command:id
1088
+
1089
.P
1090
\fBtovid id\fR identifies each multimedia video file in a
1091
list, and reports its compliance with video disc standards such as VCD,
1092
SVCD, and DVD.
1093
1094
.SS Usage
1095
+
1096
.P
1097
\fBtovid id\fR [\fIOPTIONS\fR] \fIVIDEO_FILE(s)\fR
1098
1099
1100
tovid id \-tabluar videos/*.mpg
1101
1102
.SS Options
1103
+
1104
.TP
1105
\fB\-terse\fR
1106
Print raw video characteristics, no formatting. Helpful when
1107
1108
when identifying multiple video files.
1109
1110
.TP
1111
+\fB\-keepfiles\fR
1112
+Keep temporary directory for debugging.
1113
+
1114
+.TP
1115
\fB\-isformat\fR [\fIpal\-dvd\fR|\fIntsc\-dvd\fR] (same syntax for vcd and svcd)
1116
Check \fIVIDEO_FILE\fR for compliance with the given disc format.
1117
If \fIVIDEO_FILE\fR matches the given format, then \fBtovid id\fR reports "true"
1118
1119
and pal/ntsc.
1120
1121
.SS Examples
1122
+
1123
.TP
1124
tovid id \-verbose homevideo.avi
1125
Report everything mplayer, ffmpeg, and transcode can determine about
1126
1127
tovid id \-isformat dvd homevideo.mpg
1128
Check to see if homevideo.mpg is compliant with the DVD standard.
1129
1130
-.SH Command:menu
1131
-.P
1132
-\fBtovid menu\fR generates textual (S)VCD\- or DVD\-compliant MPEG videos for use
1133
-as navigational menus, given a list of text strings to use for title names. You
1134
-can customize the menu by providing an optional background image or audio clip,
1135
-or by using custom font and font color.
1136
-
1137
-.SS Usage
1138
-.P
1139
-\fBtovid menu\fR [\fIOPTIONS\fR] \fITITLES\fR \fB\-out\fR \fIOUT_PREFIX\fR
1140
-
1141
-.P
1142
-For example:
1143
-
1144
-.TP
1145
-tovid menu "Season One" "Season Two" "Featurettes" \-out MainMenu
1146
-
1147
-.SS Options
1148
-.TP
1149
-\fB\-ntsc\fR (default)
1150
-Generate an NTSC\-format menu
1151
-.TP
1152
-\fB\-ntscfilm\fR
1153
-Generate an NTSC\-format menu (24000/1001fps)
1154
-.TP
1155
-\fB\-pal\fR
1156
-Generate a PAL\-format menu
1157
-.TP
1158
-\fB\-dvd\fR (default)
1159
-Generate a DVD\-format menu, with highlighted text included
1160
-as a multiplexed subtitle stream.
1161
-.TP
1162
-\fB\-vcd\fR
1163
-.TP
1164
-\fB\-svcd\fR
1165
-Generate a VCD/SVCD menu; each menu option will have a
1166
-number associated with it. You can have up to nine menu
1167
-options per menu.
1168
-
1169
-.P
1170
-Menu background/audio options:
1171
-
1172
-.TP
1173
-\fB\-background\fR \fIIMAGE\fR
1174
-Use \fIIMAGE\fR (in most any graphic format) as a background. If image is not
1175
-the correct aspect ratio (4:3), it will be scaled and/or cropped,
1176
-depending on the \fB\-crop\fR and \fB\-scale\fR options. If no background is
1177
-supplied, a default background will be created.
1178
-
1179
-.TP
1180
-\fB\-crop\fR (default)
1181
-If provided background image is not 4:3 aspect ratio, crop edges
1182
-to make it so. Image will be scaled up if it is too small. Cropping
1183
-keeps the center area of image. If you want to do cropping/scaling
1184
-yourself in another program, provide an image of 768x576 pixels.
1185
-
1186
-.TP
1187
-\fB\-scale\fR
1188
-If provided background image is not 4:3 aspect ratio, scale/stretch
1189
-it to make it fit. May cause visible distortion!
1190
-
1191
-.TP
1192
-\fB\-audio\fR \fIAUDIOFILE\fR
1193
-Use \fIAUDIOFILE\fR (in most any audio format) for background music. The
1194
-menu will play for long enough to hear the whole audio clip. If
1195
-one is not provided, 4 seconds of silence will be used.
1196
-
1197
-.TP
1198
-\fB\-length\fR \fINUM\fR
1199
-Make the menu \fINUM\fR seconds long. Useful for menus with \fB\-audio\fR:
1200
-if you don't want the entire \fIAUDIOFILE\fR in the menu, then you can trim
1201
-the length of the menu with \fB\-length\fR.
1202
-
1203
-.P
1204
-Menu text options:
1205
-
1206
-.TP
1207
-\fB\-menu\-title\fR \fB"\fR\fIMENU TITLE TEXT\fR\fB"\fR
1208
-Add \fIMENU TITLE TEXT\fR as a title/header to the menu.
1209
-
1210
-.TP
1211
-\fB\-font\fR \fIFONTNAME\fR (default Helvetica)
1212
-Use \fIFONTNAME\fR for the menu text. Run 'convert \-list type' to see a
1213
-list of the fonts that you can use; choose a font name from the
1214
-leftmost column that is displayed. Or you can specify a ttf font file instead.
1215
-E.g., '\-font /path/to/myfont.ttf'.
1216
-
1217
-.TP
1218
-\fB\-fontsize\fR \fINUM\fR (default 24)
1219
-Sets the size for the font to \fINUM\fR pixels.
1220
-
1221
-.TP
1222
-\fB\-menu\-title\-fontsize\fR \fINUM\fR (default \fB\-fontsize\fR + 8)
1223
-Sets the size of the menu title.
1224
-
1225
-.TP
1226
-\fB\-fontdeco\fR \fB'\fR\fIFONTDECORATION\fR\fB'\fR
1227
-Sets the font decoration method to \fIFONTDECORATION\fR. It is used by the
1228
-'convert' ImageMagick command to draw the menu text. You can add colored
1229
-text outlines, gradient fills, and many others. See \fBUsage notes\fR.
1230
-
1231
-.TP
1232
-\fB\-align\fR {\fBleft\fR|\fBcenter\fR|\fBmiddle\fR|\fBright\fR}
1233
-Align the text at the top left, top center, very middle, or top right
1234
-side of the screen. You may also substitute any "gravity" keyword
1235
-allowed by ImageMagick (north|south|east|west|northeast|southwest|...).
1236
-
1237
-.TP
1238
-\fB\-textcolor\fR {\fB#\fR\fIRRGGBB\fR|\fB#\fR\fIRGB\fR|\fICOLORNAME\fR}
1239
-Use specified color for menu text. #\fIRRGGBB\fR and #\fIRGB\fR are
1240
-hexadecimal triplets (e.g., #FF8035). \fICOLORNAME\fR may be any of
1241
-several hundred named colors; run 'convert \-list color' to see them.
1242
-White (#FFF) is the default color.
1243
-
1244
-.P
1245
-DVD\-only options:
1246
-
1247
-.TP
1248
-\fB\-button\fR \fIBUTTON\fR (default '>')
1249
-Specify the button used for menu selection. Specify either a _single_
1250
-character or one of the shortcuts:
1251
-.RS
1252
-.IP \(bu 3
1253
-\fBplay\fR \-\- Use a button shaped like 'Play' on many A/V electronics:
1254
-a triangle pointing to the right. (uses the font Webdings)
1255
-.IP \(bu 3
1256
-\fBmovie\fR \-\- Use a button shaped like an old movie projector.
1257
-(uses the font Webdings)
1258
-.IP \(bu 3
1259
-\fButf8\fR \-\- Use your own non\-keyboard character as a button. Provide
1260
-only the four hex digits: eg '\-button utf8 00b7'. Beware that
1261
-ImageMagick's utf8 characters aren't the same as those drawn in
1262
-character browsers like gucharmap.
1263
-.RE
1264
-
1265
-.TP
1266
-\fB\-highlightcolor\fR {\fB#\fR\fIRRGGBB\fR|\fB#\fR\fIRGB\fR|\fICOLORNAME\fR}
1267
-Use the specified color for button highlighting. Yellow (#FF0) is the
1268
-default color.
1269
-
1270
-.TP
1271
-\fB\-selectcolor\fR {\fB#\fR\fIRRGGBB\fR|\fB#\fR\fIRGB\fR|\fICOLORNAME\fR}
1272
-Use the specified color for button selections (when a menu item is played
1273
-or activated). Red (#F00) is the default color.
1274
-
1275
-.TP
1276
-\fB\-button\-outline\fR {\fB#\fR\fIRRGGBB\fR|\fB#\fR\fIRGB\fR|\fICOLORNAME\fR}
1277
-Outline buttons with the specified color. 'none' is the default.
1278
-
1279
-.TP
1280
-\fB\-button\-font\fR \fIFONTNAME\fR
1281
-Specify a differnt font to use for the buttons. By default, the button
1282
-font will be inherited from the title font (see \fB\-font\fR). Use this
1283
-option to use a different font for the buttons. The button font size is
1284
-inherited from \fB\-fontsize\fR and cannot be changed.
1285
-
1286
-.P
1287
-Other options:
1288
-
1289
-.TP
1290
-\fB\-debug\fR
1291
-Print extra debugging information to the log file. Useful in
1292
-diagnosing problems if they occur. This option also leaves
1293
-the log file (with a .log extension) in the directory after
1294
-encoding finishes as well as all the temporary files created.
1295
-
1296
-.TP
1297
-\fB\-nosafearea\fR
1298
-Do not attempt to put text inside a TV\-safe viewing area. Most
1299
-television sets cut off about 10% of the image border, so the script
1300
-automatically leaves a substantial margin. This option turns that
1301
-behavior off, leaving only a tiny margin. Use at your own risk.
1302
-
1303
-.TP
1304
-\fB\-overwrite\fR
1305
-Overwrite any existing output menu.
1306
-
1307
-.TP
1308
-\fB\-noask\fR
1309
-Don't ask interactive questions, and assume answers that will
1310
-continue making the menu until completion.
1311
-
1312
-.TP
1313
-\fB\-quiet\fR
1314
-Limit output to essential messages.
1315
-
1316
-.P
1317
-If the word "\fBback\fR" is given as an episode title, a "back" button for
1318
-returning to a higher\-level menu will be added at the end of the list
1319
-of titles. "\fBBack\fR" \fImust be the last title listed\fR.
1320
-
1321
-.SS Examples
1322
-.P
1323
-Make an NTSC VCD menu with white Helvetica text containing three centered
1324
-selections: Episode 1, Episode 2, and Episode 3. The finished menu will be
1325
-called Season\-1.mpg:
1326
-
1327
-.nf
1328
- tovid menu -ntsc -vcd \e
1329
- -align center -textcolor white -font "Helvetica" \e
1330
- "Episode 1" "Episode 2" "Episode 3" \e
1331
- -out "Season-1"
1332
-.fi
1333
-
1334
-
1335
-.P
1336
-Make an NTSC DVD menu with white Kirsty text containing three lower\-left
1337
-aligned selections: Episode 1, Episode 2, and Episode 3. Items under the cursor
1338
-will be highlighted a pale blue, and selected items will be a pale orange
1339
-(before going to the selected title). The finished menu will be called
1340
-Main\-menu.mpg:
1341
-
1342
-.nf
1343
- tovid menu -ntsc -dvd \e
1344
- -align southwest \e
1345
- -textcolor white \e
1346
- -highlightcolor "#5f65ff" \e
1347
- -selectcolor "#ffac5f" \e
1348
- -font "Kirsty" \e
1349
- "Episode 1" "Episode 2" "Episode 3" \e
1350
- -out "Main_menu"
1351
-.fi
1352
-
1353
-
1354
-.SS Usage notes
1355
-.P
1356
-The argument given to \fB\-font\fR must be one of the fonts listed
1357
-by the command 'convert \-list type'. Please note that many of
1358
-your installed fonts may not be available; if you want to maximize the
1359
-number of fonts available, download and run
1360
-Anthony Thyssen's (http://www.cit.gu.edu.au/~anthony/anthony.html)
1361
-imagick_type_gen.pl (http://www.cit.gu.edu.au/~anthony/software/imagick_type_gen.pl)
1362
-script and run it like this:
1363
-imagick_type_gen.pl > ~/.magick/type.xml.
1364
-If that doesn't work, try
1365
-imagick_type_gen.pl > ~/.magick/type.mgk.
1366
-
1367
-.P
1368
-Or you can specify a ttf font file directly to the \fB\-font\fR options if you
1369
-don't want to install fonts to ImageMagick.
1370
-
1371
-.P
1372
-The \fB\-fontdeco\fR option is quite flexible and takes a lot of ImageMagick's
1373
-\fIconvert\fR options. Please refer to the tovid
1374
-wiki (http://tovid.wikia.com/wiki/Making_a_DVD_with_text_menus)
1375
-and Anthony Thyssen's guide for further explanation and examples.
1376
-
1377
-.SH Command:xml
1378
-.P
1379
-\fBtovid xml\fR generates XML output describing an (S)VCD
1380
-or DVD file structure and navigation hierarchy in the format expected by
1381
-dvdauthor (http://dvdauthor.sourceforge.net/) or
1382
-vcdxbuild (http://www.vcdimager.org/).
1383
-
1384
-.SS Usage
1385
-.P
1386
-\fBtovid xml\fR [\fIOPTIONS\fR] \fIVIDEOS\fR \-out \fIOUTFILE\fR
1387
-
1388
-.P
1389
-For example:
1390
-
1391
-.nf
1392
- $ tovid xml -menu MainMenu.mpg \e
1393
- Season1.mpg Season2.mpg Featurettes.mpg \e
1394
- -out MyDisc
1395
-.fi
1396
-
1397
-
1398
-.SS Options
1399
-.TP
1400
-\fB\-dvd\fR (default)
1401
-Generate the XML for a DVD disc, to be used with dvdauthor or \fBtovid dvd\fR.
1402
-.TP
1403
-\fB\-vcd\fR
1404
-Generate the XML for a VCD disc, to be used with vcdxbuild or \fBtovid vcd\fR.
1405
-.TP
1406
-\fB\-svcd\fR
1407
-Generate the XML for an SVCD disc, to be used with vcdxbuild or \fBtovid vcd\fR.
1408
-.TP
1409
-\fB\-overwrite\fR
1410
-Overwrite any existing output files.
1411
-.TP
1412
-\fB\-quiet\fR
1413
-Limit output to essential messages.
1414
-
1415
-.P
1416
-\fIVIDEOS\fR may be any of the following:
1417
-
1418
-.TP
1419
-\fI<file list>\fR
1420
-List of one or more video files to include, separated by spaces. At
1421
-minimum, a DVD must have one video file. You can use shell wildcards
1422
-(i.e., "*.mpg") to include multiple files easily. Put filenames in
1423
-quotes if they have spaces in them.
1424
-
1425
-.TP
1426
-\fB\-menu\fR \fIVIDEO\fR \fI<file list>\fR
1427
-Use video file \fIVIDEO\fR as a menu from which you can jump to each of
1428
-the listed video files. If you have multiple menus, include a
1429
-top menu so they are reachable.
1430
-
1431
-.TP
1432
-\fB\-slides\fR \fI<file list>\fR
1433
-Create a slide\-show of still images
1434
-
1435
-.P
1436
-DVD\-only options
1437
-
1438
-.TP
1439
-\fB\-group\fR \fI<file list>\fR \fB\-endgroup\fR
1440
-(DVD only) List of video files to include as one single title. This is useful
1441
-if you have split a movie into several video files.
1442
-
1443
-.TP
1444
-\fB\-topmenu\fR \fIVIDEO\fR [\fB\-menu\fR \fIVIDEO\fR \fI<file list>\fR] [\fB\-menu\fR \fIVIDEO\fR \fI<file list>\fR]...
1445
-(DVD only) Use video file \fIVIDEO\fR for the top\-level (VMGM) menu. The
1446
-top menu will jump to each of the subsequent [\-menu...] videos listed.
1447
-Use this only if you have multiple sub\-menus to jump to. You can only
1448
-have one top menu.
1449
-
1450
-.TP
1451
-\fB\-titlesets\fR
1452
-(DVD only) Forces the creation of a separate titleset per title. This
1453
-is useful if the titles of a DVD have different video formats,
1454
-e.g. PAL + NTSC or 4:3 + 16:9. If used with menus, there must be a
1455
-\fB\-topmenu\fR option that specifies a menu file with an entry for each of the
1456
-titlesets.
1457
-
1458
-.TP
1459
-\fB\-chapters\fR \fIINTERVAL\fR
1460
-(DVD only) Creates a chapter every \fIINTERVAL\fR minutes (default 5 minutes:
1461
-without \fB\-chapters\fR, each movie will be divided into 5\-minute chapters).
1462
-This option can be put at any position in a \fI<file list>\fR and is valid
1463
-for all subsequent titles until a new \fB\-chapters\fR option is encountered.
1464
-Using this option may take some time, since the duration of the video is
1465
-calculated.
1466
-
1467
-.TP
1468
-\fB\-nochapters\fR
1469
-(DVD only) Don't create chapters for the videos.
1470
-
1471
-.P
1472
-\fIOUT_PREFIX\fR is the file that will receive the resulting XML.
1473
-
1474
-.SS Usage notes
1475
-.P
1476
-The 'xml' command checks to make sure the video filenames you
1477
-give it exist, but it does not check whether they are valid for the
1478
-chosen disc format. MPEG videos of menus should have the specified
1479
-number of buttons for reaching each of the videos, and, if you're
1480
-using DVD, should be multiplexed with their corresponding subtitles
1481
-using spumux of the dvdauthor 0.6.0 package prior to
1482
-authoring using dvdauthor. If you use the 'tovid menu'
1483
-component to generate the menu, this should all be handled for you.
1484
-
1485
-.SS Examples
1486
-.TP
1487
-tovid xml \-dvd title\-1.mpg title\-2.mpg title\-3.mpg \-out My_DVD
1488
-Make a DVD without a menu. Title 1, 2, and 3 will play in sequence.
1489
-
1490
-.TP
1491
-tovid xml \-dvd \-group chapter\-1.mpg chapter\-2.mpg chapter\-3.mpg \-endgroup \-out My_DVD
1492
-Group the file chapter\-1|2|3.mpg into one title and make a DVD without a menu.
1493
-
1494
-.TP
1495
-tovid xml \-dvd \-menu main_menu.mpg \-chapters 3 movie\-1.mpg \-chapters 10 movie\-2.mpg \-out My_DVD
1496
-Make a DVD with a main menu that points to two movies, with movie\-1.mpg
1497
-divided into 3\-minute chapters, and movie\-2.mpg into 10\-minute chapters.
1498
-
1499
.SH Command:dvd
1500
+
1501
.P
1502
-\fBtovid dvd\fR takes a dvdauthor XML file (as generated by the \fBtovid xml\fR
1503
-command) and authors a DVD filesytem. This command can also burn a DVD disc
1504
-from either the XML file or from an existing DVD file\-system.
1505
+\fBtovid dvd\fR takes a DVD directory as generated by tovid with 'tovid disc' or
1506
+one of the GUI frontends like 'tovid gui' or 'tovid titlesets' and burns
1507
+it to appropriate media. This will also work if the DVD directory is
1508
+generated by the dvdauthor backend that tovid also uses.
1509
1510
.P
1511
-To ensure that this script successfully executes, please run it from a
1512
-directory with plenty of free space. "Plenty" would be 10 GB for single\-layer
1513
-discs, and 20 GB for dual\-layer discs. Running this program may slow down your
1514
-other applications, due to intense disk activity.
1515
+Running this program may slow down your other applications, due to intense
1516
+disk activity.
1517
1518
.SS Usage
1519
-.P
1520
-\fBtovid dvd\fR [\fIOPTIONS\fR] \fIFILE.xml\fR
1521
1522
.P
1523
\fBtovid dvd\fR [\fIOPTIONS\fR] \fIDVD_DIR\fR
1524
1525
For example:
1526
1527
.TP
1528
-tovid dvd \-burn MyDisc.xml
1529
-.TP
1530
-tovid dvd \-burn /path/to/DVD/directory
1531
+tovid dvd /path/to/DVD/directory
1532
1533
.SS Options
1534
-.TP
1535
-\fB\-author\fR
1536
-Author the DVD described by \fIFILE.xml\fR. Overwrites an existing
1537
-directory containing the dvdauthor output if already present.
1538
1539
.TP
1540
\fB\-burn\fR
1541
Burn a DVD file\-system in \fIDVD_DIR\fR (must contain a VIDEO_TS folder).
1542
+This option is currently not necessary as the makedvd script ONLY burns
1543
+now that legacy scripts like makexml have been removed. Left for
1544
+compatibility only.
1545
1546
.TP
1547
\fB\-eject\fR
1548
1549
Don't ask interactive questions and assume answers that will continue
1550
execution.
1551
1552
-.SS Examples
1553
-.TP
1554
-tovid dvd \-burn \-device /dev/dvdrw foo.xml
1555
-Author the dvd file\-system and burn to /dev/dvdrw. This will
1556
-automatically call dvdauthor to make the file\-system. \fB\-author\fR
1557
-is not explicitly needed. If there's an existing file\-system, it
1558
-will be burned.
1559
-
1560
-.TP
1561
-tovid dvd \-author foo.xml
1562
-Author the DVD file\-system and exit without burning. If the output
1563
-directory given in foo.xml already exists, then the contents are
1564
-removed before authoring. At this point, the DVD can be previewed
1565
-by calling \fI\fBxine\fR dvd:/path/to/output/directory\fR.
1566
-
1567
-.SH Command:vcd
1568
.P
1569
-\fBtovid vcd\fR takes an XML file (which may be generated by \fBtovid xml\fR) and
1570
-creates a cue/bin (S)VCD image. It can also burn (S)VCD discs.
1571
+ After burning, the DVD can be previewed by calling:
1572
+ \fI\fBxine\fR dvd:/path/to/output/directory\fR
1573
+ or:
1574
+ \fI\fBvlc\fR /path/to/output/directory\fR
1575
1576
-.P
1577
-To ensure that this script successfully executes, please run it from a directory
1578
-with plenty of free space. "Plenty" would be about 1 GB. Running this program
1579
-may slow down your other applications, due to intense disk activity.
1580
+.SH Command:chapters
1581
1582
-.SS Usage
1583
.P
1584
-\fBtovid vcd\fR [\fIOPTIONS\fR] \fIVCDIMAGER.xml\fR
1585
+\fBtovid chapters\fR will start a GUI using mplayer to set chapter points in a
1586
+video. If the video plays through and you want to add more chapters you can
1587
+press the play button again, but remember that new chapter points will be
1588
+appended (in correct sequential order). It will display the resulting chapter
1589
+points, and also output to a terminal (useful for scripts). As well it will
1590
+give the option of saving the chapters string to a text file.
1591
1592
.P
1593
-For example:
1594
-
1595
-.TP
1596
-tovid vcd \-burn MyDisc.xml
1597
-
1598
-.SS Options
1599
-.TP
1600
-\fB\-overwrite\fR (default off \-\- nothing is overwritten)
1601
-Overwrite any existing cue/bin files matching \fIVCDIMAGER.xml\fR. Useful
1602
-if you modified the xml file and wish to re\-image or burn the new (S)VCD.
1603
-
1604
-.TP
1605
-\fB\-burn\fR (default off \-\- no images are burned)
1606
-Burn the (S)VCD described by \fIVCDIMAGER.xml\fR.
1607
-
1608
-.TP
1609
-\fB\-device\fR \fIDEVICE\fR (default /dev/cdrw)
1610
-Burn the disc image to \fIDEVICE\fR, the Linux device file\-system
1611
-name of your CD\-recorder. Common examples might be /dev/cdrw,
1612
-/dev/scd1, and /dev/hdc.
1613
-
1614
-.TP
1615
-\fB\-speed\fR \fINUM\fR (default 12)
1616
-Burn the disc at speed \fINUM\fR.
1617
-
1618
-.TP
1619
-\fB\-quiet\fR
1620
-Limit output to essential messages.
1621
+Note that the 'tovid gui' now features a similar widget when you press the
1622
+chapters button on the opening page.
1623
1624
.SS Examples
1625
-.TP
1626
-tovid vcd \-burn \-device /dev/cdrw foo.xml
1627
-Create the (S)VCD image and burn it to /dev/cdrw. This will
1628
-automatically call vcdxbuild to make the image. If there is an existing
1629
-image, it will be burned.
1630
-
1631
-.TP
1632
-tovid vcd \-overwrite foo.xml
1633
-Create the (S)VCD image and exit without burning. If the image
1634
-already exists, then it is removed before re\-imaging.
1635
-
1636
-.SH Command:postproc
1637
-.P
1638
-\fBtovid postproc\fR is designed to do simple post\-processing on MPEG video files, such
1639
-as those generated by tovid. It can adjust audio/video sync, and re\-quantize
1640
-(shrink) without re\-encoding.
1641
-
1642
-.SS Usage
1643
-.P
1644
-\fBtovid postproc\fR [\fIOPTIONS\fR] \fIIN_FILE\fR \fIOUT_FILE\fR
1645
-
1646
-.SS Options
1647
-.TP
1648
-\fB\-audiodelay\fR \fINUM\fR
1649
-Delay the audio stream by \fINUM\fR milliseconds. Use this if
1650
-your final output has audio that is not synced with the
1651
-video. For example, if the audio comes 2 seconds sooner than
1652
-the video, use "\-audiodelay 2000". Use a negative number for
1653
-audio that comes later than the video.
1654
-
1655
-.TP
1656
-\fB\-normalize\fR
1657
-Analyze the audio stream and then normalize the volume of the audio.
1658
-This is useful if the audio is too quiet or too loud, or you want to
1659
-make volume consistent for a bunch of videos. Similar to running
1660
-normalize without any parameters. The default is \-12dB average level
1661
-with 0dB gain.
1662
-
1663
-.TP
1664
-\fB\-amplitude\fR \fINUM\fR[dB]
1665
-In addition to analyzing and normalizing, apply the gain to the audio
1666
-such that the 'average' (RMS) sound level is \fINUM\fR. Valid values
1667
-range 0.0 \- 1.0, with 0.0 being silent and 1.0 being full scale. Use
1668
-\fINUM\fRdB for a decibel gain below full scale (the default without
1669
-\-amplitude is \-12dB).
1670
-
1671
-.TP
1672
-\fB\-shrink\fR \fINUM\fR
1673
-Shrink the video stream by a factor of \fINUM\fR. May be a decimal
1674
-value. A value of 1.0 means the video will be the same size;
1675
-larger values cause more reduction in size. Beyond 2.0, the
1676
-returns are diminishing.
1677
1678
.TP
1679
-\fB\-parallel\fR
1680
-Run all processes in parallel and pipe into multiplexer, should
1681
-increase speed significantly.
1682
-
1683
-.TP
1684
-\fB\-debug\fR
1685
-Save output in a temporary file, for later viewing if
1686
-something goes wrong.
1687
-
1688
-.SH Command:chapters
1689
-.P
1690
-\fBtovid chapters\fR will start a GUI using mplayer to set chapter points in a
1691
-video. Its only (mandatory) option is the path to a video file.
1692
-
1693
-.SS Examples
1694
-.TP
1695
tovid chapters foo.avi
1696
1697
.TP
1698
-tovid chapters /home/grepper/videos/foo.avi
1699
+chapters=$(tovid chapters /home/grepper/videos/foo.avi)
1700
1701
.SH CONTACT
1702
+
1703
.P
1704
For further assistance, contact information, forum and IRC links,
1705
please refer to the tovid homepage (http://tovid.wikia.com/).
1706
1707
-
1708
-.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net)
1709
+.\" man code generated by txt2tags 2.6 (http://txt2tags.org)
1710
.\" cmdline: txt2tags -t man -i docs/src/en/tovid.t2t -o docs/man/tovid.1
1711
-
1712
tovid-0.34.tar.bz2/docs/sphinx/conf.py -> tovid-0.35.tar.gz/docs/sphinx/conf.py
Changed
13
1
2
# built documents.
3
#
4
# The short X.Y version.
5
-version = '0.33'
6
+version = '0.34'
7
# The full version, including alpha/beta/rc tags.
8
-release = '0.33'
9
+release = '0.34'
10
11
# The language for content autogenerated by Sphinx. Refer to documentation
12
# for a list of supported languages.
13
tovid-0.34.tar.bz2/docs/sphinx/man/tovid.rst -> tovid-0.35.tar.gz/docs/sphinx/man/tovid.rst
Changed
3149
1
2
-===============================================================
3
-tovid manual
4
-===============================================================
5
+Name
6
+====
7
8
+tovid: Make DVDs from video files
9
10
Description
11
-===============================================================================
12
+===========
13
+
14
+**tovid** is a command-line tool for creating DVDs. It can encode your
15
+video files to DVD-compliant MPEG format, generate simple or complex DVD
16
+menus, author and burn a ready-to-watch DVD, with just a few shell
17
+commands. A graphical interface is also provided to make the process
18
+even easier.
19
+
20
+**NOTE**: As of tovid 0.35, the legacy scripts **makemenu**,
21
+**makexml**, **makevcd** have been deprecated and no longer appear in
22
+this manpage. They are still included with tovid for now, and can be
23
+used by doing: tovid menu|xml|vcd|postproc
24
+as done in the previous 3 versions of tovid.
25
+
26
+Also note that as of tovid 0.32, this is the only manual page provided
27
+by tovid. There is now a single executable frontend to all functionality
28
+in the suite, so if you were expecting to find manpages for **todisc**,
29
+**idvid**, **makempg** and their kin, they can all be found in the
30
+**tovid** manpage you are reading now.
31
+
32
+And yes, this makes for a pretty large manual page. If you are viewing
33
+this manpage from the command-line **man** utility, which normally pages
34
+through the **less** utility, you can skip to a section by searching
35
+with the **/** key, followed by a **^** to match the given section name.
36
+For example, to skip to the **mpg** command, type **/^Command:mpg**. See
37
+**man less** for more on how to navigate.
38
39
-**tovid** is a command-line tool for creating DVDs. It can encode your video
40
-files to DVD-compliant MPEG format, generate simple or complex DVD menus,
41
-author and burn a ready-to-watch DVD, with just a few shell commands. A
42
-graphical interface is also provided to make the process even easier.
43
+Usage
44
+=====
45
46
-**NOTE**: As of tovid 0.32, this is the only manual page provided by tovid.
47
-There is now a single executable frontend to all functionality in the suite, so
48
-if you were expecting to find manpages for **todisc**, **idvid**, **makemenu**
49
-and their kin, they can all be found in the **tovid** manpage you are reading now.
50
+**tovid** *COMMAND* [*OPTIONS*]
51
52
-And yes, this makes for a pretty large manual page. If you are viewing this
53
-manpage from the command-line **man** utility, which normally pages through the
54
-**less** utility, you can skip to a section by searching with the **/** key,
55
-followed by a **^** to match the given section name. For example, to skip to
56
-the **mpg** command, type **/^Command:mpg**. See :manpage:`less(1)` for more on how
57
-to navigate.
58
+Where *COMMAND* is one of the following:
59
60
-Usage
61
-===============================================================================
62
+Main Commands
63
64
-::
65
+**disc**
66
+ Encode, make menus, author, burn. (was **todisc**. See
67
+ **Command:disc**)
68
69
- tovid COMMAND [OPTIONS]
70
+**gui**
71
+ Start the tovid GUI (was **todiscgui**. See **Command:gui**)
72
73
-Where *COMMAND* is one of the following:
74
+**titlesets**
75
+ A GUI wizard for multiple titlesets. (new: See
76
+ **Command:titlesets**)
77
78
- gui
79
- Start the tovid GUI (was **todiscgui**. See :ref:`command-gui`)
80
- disc
81
- Create a DVD with menus (was **todisc**. See :ref:`command-disc`)
82
- mpg
83
- Encode videos to MPEG format (was **tovid**. See :ref:`command-mpg`)
84
- id
85
- Identify one or more video files (was **idvid**. See :ref:`command-id`)
86
- menu
87
- Create an MPEG menu (was **makemenu**. See :ref:`command-menu`)
88
- xml
89
- Create (S)VCD or DVD .xml file (was **makexml**. See :ref:`command-xml`)
90
- dvd
91
- Author and/or burn a DVD (was **makedvd**. See :ref:`command-dvd`)
92
- vcd
93
- Author and/or burn a VCD (was **makevcd**. See :ref:`command-vcd`)
94
- postproc
95
- Post-process an MPEG video file (was **postproc**. See :ref:`command-postproc`)
96
-
97
-The *OPTIONS* differ for each command; run **tovid <command>** with no
98
-further arguments to get help on a command, and what options it expects.
99
+Helper Commands
100
101
-Configuration
102
-===============================================================================
103
+**mpg**
104
+ Encode videos to MPEG format (was **tovid**. See **Command:mpg**)
105
106
-Two configuration files are created the first time you run tovid:
107
+**dvd**
108
+ Author and/or burn a DVD (was **makedvd**. See **Command:dvd**)
109
110
-``~/.tovid/preferences``
111
- Defines working directory for all scripts.
112
- In addition you can define the output directory for makempg here.
113
-``~/.tovid/tovid.config``
114
- Includes command-line options that should always be passed to
115
- makempg.
116
+**id**
117
+ Identify one or more video files (was **idvid**. See **Command:id**)
118
119
- Edit these files if you wish to change your configuration.
120
+**chapters**
121
+ A GUI using mplayer for setting chapter points. It will return a
122
+ string of chapter points to the terminal, in a format recognized by
123
+ ’tovid disc’ (todisc) or by ’tovid gui’, for the **-chapters**
124
+ option.
125
126
-The following environment variables are also honoured:
127
+The *OPTIONS* differ for each command; run **tovid
128
+<command>** with no further arguments to get help on
129
+a command, and what options it expects.
130
131
-``TOVID_WORKING_DIR``
132
- working directory for all scripts
133
-``TOVID_OUTPUT_DIR``
134
- output directory for the makempg script
135
+Configuration
136
+=============
137
138
+Two configuration files are created the first time you run tovid:
139
140
-.. _command-gui:
141
+**~{**/.tovid/preferences}
142
+ Defines working directory for all scripts. In addition you can
143
+ define the output directory for makempg here.
144
145
-Command:gui
146
-===============================================================================
147
+**~{**/.tovid/tovid.ini}
148
+ Includes command-line options that should be passed to the various
149
+ **tovid** sub-commands.
150
151
-**tovid gui** starts the graphical user interface (GUI) for tovid. This is
152
-the easiest way to start creating DVDs with tovid. At this time, there are no
153
-additional command-line options; the GUI controls take care of everything,
154
-and all help is integrated in the form of tooltips. You can also see
155
-:ref:`command-disc` for more detail about the options. Note: one limitation of
156
-the gui at present is that it does not do multiple titlesets (though it will do
157
-chapter menus). Use the **tovid disc** command (below) for titlesets.
158
+ Edit these files if you wish to change your configuration.
159
160
+ The following environment variables are also honoured:
161
+ TOVID\_WORKING\_DIR (working directory for all scripts).
162
+ TOVID\_OUTPUT\_DIR (output directory for the makempg script).
163
164
-.. _command-disc:
165
+Command:gui
166
+===========
167
+
168
+**tovid gui** starts the graphical user interface (GUI) for tovid. This
169
+is the easiest way to start creating DVDs with tovid. The optional
170
+arguments are any option used by todisc (’tovid disc’) which will save
171
+entering it manually, OR the full path to a saved script from the GUI.
172
+This option to save the contents of your project allows you to use it as
173
+a bash script later, or to reload the project to continue working with
174
+it at another time. Note: this feature is still in development so some
175
+options may not load properly - make sure to check that your selections
176
+were all loaded.
177
+
178
+All help is integrated in the form of tooltips. You can also see
179
+\*\*Command:disc \*\* for more detail about the options. Note: if you
180
+wish to use a GUI to make multiple titlesets on the same DVD use ’tovid
181
+titlesets’, which is a wizard that uses the the ’tovid gui.
182
+
183
+Command:titlesets
184
+=================
185
+
186
+**tovid titlesets** will assist in making a DVD with multiple titlesets.
187
+It can be started without any options, or you can feed it the path to a
188
+saved titleset script as an option. The option to save a script is also
189
+useful as the resulting script can be run later from a terminal.
190
191
Command:disc
192
-===============================================================================
193
-
194
-**tovid disc** creates a DVD file-system with menus, from a list of multimedia
195
-video files and their titles. As this is a low level script it is the easiest
196
-command line program for creating a DVD from start to finish, including
197
-automatically converting non-compliant videos and prompting to burn at
198
-completion. It does animated menus, static thumbnail menus and text only
199
-menus. In addition, it can do slideshows, using images as input, and combine
200
-slideshows with videos. It supports sub-menus for chapter breaks, configurable
201
-menu style, animated backgrounds and transparency effects.
202
+============
203
+
204
+**tovid disc** creates a DVD file-system with optional menus, from a
205
+list of multimedia video files and their titles. As todisc can function
206
+as a master script, calling other scripts as it needs them, it is the
207
+easiest command line program for creating a DVD from start to finish,
208
+including automatically converting non-compliant videos and prompting to
209
+burn at completion. It can do animated menus, static thumbnail menus,
210
+text-only menus, or author with no menu. In addition, it can do
211
+slideshows, using images as input, and even combine slideshows with
212
+videos. It supports sub-menus for chapter breaks, configurable menu
213
+style, animated backgrounds and transparency effects. From simple (no
214
+menu) to complex (switched menus and titlesets), you should be able to
215
+do what you want with ’tovid disc’.
216
+
217
+Please note that although the interface may seem complex with so many
218
+options, you can create a fully functional DVD with only a few options
219
+on the opening tab of the GUI (select video files and an output name).
220
221
Usage
222
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
223
+-----
224
225
::
226
227
- tovid disc [OPTIONS] \
228
- -files <file list> -titles <title list>
229
- -out OUT_PREFIX
230
-
231
-For example::
232
+ tovid disc [OPTIONS] \
233
+ -files <file list> -titles <title list>
234
+ -out OUT_PREFIX
235
236
- tovid disc -files File1.mpg File2.mpg File3.mpg \
237
- -titles "Episode 1" "Episode 2" "Episode 3" \
238
- -out Season_one
239
+For example:
240
241
-The number of **-files** and **-titles** must be equal, though if you do not
242
-include any titles **tovid disc** will use the basename of the included files
243
-as titles. If you are doing a slideshow or multiple slideshows, use
244
-**-slides** rather than **-files** for passing in the images. You may use
245
--files and -slides more than once to create an ordering in a mixed
246
-slideshows/videos menu. See :ref:`usage-slideshows` under usage below.
247
+::
248
249
-If the input files are not mpeg, you will have the option to auto-encode them.
250
+ $ tovid disc -files File1.mpg File2.mpg File3.mpg \
251
+ -titles "Episode 1" "Episode 2" "Episode 3" \
252
+ -out Season_one
253
254
+The number of **-files** and **-titles** must be equal, though if you do
255
+not include any titles **tovid disc** will use the basename of the
256
+included files as titles. If you are doing a slideshow or multiple
257
+slideshows, use **-slides** rather than **-files** for passing in the
258
+images. You may use -files and -slides more than once to create an
259
+ordering in a mixed slideshows/videos menu. See Slideshows part of Usage
260
+section, below.
261
262
-Display arrangements
263
--------------------------------------------------------------------------------
264
+If the input files are not mpeg, you will have the option to auto-encode
265
+them.
266
267
-At present there are 2 display arrangements or "templates":
268
+**At present there are 2 display arrangements or "templates":**
269
270
A. (Default)
271
Thumbs will be centred, and as large as space restraints allow.
272
273
B. **-showcase** IMAGE|VIDEO
274
- Produces an arrangement with small buttons on
275
- the side and the showcase image/video in the centre. If no IMAGE or VIDEO
276
- argument is supplied, the central thumb will be omitted.
277
+ Produces an arrangement with small buttons on the side and the
278
+ showcase image/video in the centre. If no IMAGE or VIDEO argument is
279
+ supplied, the central thumb will be omitted.
280
+
281
+ Note: **-textmenu**, **-quick-menu** and **-switched-menus** are all
282
+ types of showcase style menus. See descriptions under **Menu style**
283
+ section.
284
+
285
+The **-titles** arguments should be double or single quoted, or have the
286
+spaces backslash-escaped. Special characters (like ", !, \*, &, ?) may
287
+need to be backslash-escaped. To include a quoted string within a title,
288
+backslash-escape the quotes. These titles are used for labelling
289
+thumbnails on the main menu, and for the submenu title for that video. (
290
+see also **-submenu-titles** )
291
+
292
+The **-showcase** styles can use longer titles than the default
293
+arrangement. With a showcase style, use: **-showcase-titles-align west**
294
+to give more space for the title, or use **-showcase-titles-align east**
295
+to allow titles of more than one line.
296
+
297
+The default style can only show about 16 characters (depending on the
298
+number of thumbs, and what **-titles-font** and **-titles-fontsize** is
299
+being used). If your titles are too long to fit in the label area, you
300
+may try using sub-menus, which can display longer titles, for example:
301
302
- Note: **-textmenu**, **-quick-menu** and **-switched-menus** are all types
303
- of showcase style menus. See descriptions in the :ref:`menu-style` section.
304
+::
305
306
-The **-titles** arguments should be double or single quoted, or have the spaces
307
-backslash-escaped. Special characters (like ", !, \*, &, ?) may need to be
308
-backslash-escaped. To include a quoted string within a title, backslash-escape
309
-the quotes. These titles are used for labelling thumbnails on the main menu,
310
-and for the submenu title for that video. ( see also **-submenu-titles** )
311
+ $ tovid disc -submenus \
312
+ -files file1.mpg file2.mpg ... \
313
+ -titles "Short 1" "Short 2" \
314
+ -submenus \
315
+ -submenu-titles "Long Title One" "Long Title Two" \
316
+ -out foo
317
318
-The **-showcase** styles can use longer titles than the default arrangement.
319
-With a showcase style, use: **-showcase-titles-align west** to give more space
320
-for the title, or use **-showcase-titles-align east** to allow titles of more
321
-than one line.
322
+The **-align** argument will position both titles and thumbs either
323
+south, north east, west, southwest, northwest, southeast, northeast,
324
+subject to certain constraints of each arrangement.
325
326
-The default style can only show about 16 characters (depending on the number
327
-of thumbs, and what **-titles-font** and **-titles-fontsize** is being used).
328
-If your titles are too long to fit in the label area, you may try using
329
-sub-menus, which can display longer titles, for example::
330
+More Examples:
331
332
- $ tovid disc -submenus \
333
- -files file1.mpg file2.mpg ... \
334
- -titles "Short 1" "Short 2" \
335
- -submenu-titles "Long Title One" "Long Title Two" \
336
- -out foo
337
+A text-only menu:
338
339
-The **-align** argument will position both titles and thumbs either south,
340
-north east, west, southwest, northwest, southeast, northeast, subject to
341
-certain constraints of each arrangement.
342
+::
343
344
+ $ tovid disc -textmenu ...
345
346
-.. _usage-titlesets:
347
+No menu:
348
349
-Titlesets
350
--------------------------------------------------------------------------------
351
+::
352
353
-A word should be mentioned here about titlesets, which is really just a
354
-hierarchy of menus. You need to use titlesets, for example, if you have videos
355
-of different resolutions, or otherwise want to arrange videos on separate menus.
356
-If you want to have titlesets you need to put all the options for each titleset
357
-menu you would like to have between **-titleset** and **-end-titleset** options.
358
+ $ tovid -nomenu -files file1.mpg [file2.mpg "file 3.mpg" ...]
359
+
360
+**Titlesets**
361
362
-Additionally, for the main menu (the opening menu that will let you jump to
363
-each titleset), you need to put options between **-vmgm** and **-end-vmgm**.
364
-You do not use **-files** for the opening menu options (**-vmgm**), but you
365
-will need as many TITLES after **-titles** as you have menus.
366
+A word should be mentioned here about titlesets, which is really just a
367
+hierarchy of menus. You need to use titlesets, for example, if you have
368
+videos of different resolutions, or otherwise want to arrange videos on
369
+separate menus. If you want to have titlesets you need to put all the
370
+options for each titleset menu you would like to have between
371
+**-titleset** and **-end-titleset** options.
372
+
373
+Additionally, for the main menu (the opening menu that will let you jump
374
+to each titleset), you need to put options between **-vmgm** and
375
+**-end-vmgm**. You do not use **-files** for the opening menu options
376
+(**-vmgm**), but you will need as many TITLES after **-titles** as you
377
+have menus.
378
379
Any options outside the **-titleset** **-end-titleset** and **-vmgm**
380
**-end-vmgm** areas will be general options applying to every titleset.
381
-If a general option is duplicated inside a **-titleset** or **-vmgm** area, the
382
-general option will be overridden.
383
-
384
-Note: you do not need titlesets for a single menu with chapter break menus, for
385
-that just use **-submenus** or **-ani-submenus**
386
-
387
-Example of using **tovid disc** with titlesets::
388
-
389
- $ tovid disc -static -out MY_DVD \
390
- \
391
- -titleset -files 1.mpg 2.mpg 3.mpg \
392
- -titles "Title One" "Title Two" "Title Three" \
393
- -end-titleset \
394
- \
395
- -titleset -files 4.mpg 5.mpg \
396
- -titles "Title Four" "Title Five" \
397
- -background foo.jpg \
398
- -showcase bar.png \
399
- -end-titleset \
400
- \
401
- -vmgm \
402
- -titles "Season One" "Season Two" \
403
- -background bg.jpg \
404
- -bgaudio foo.mp3 \
405
- -titles-fontsize 20 \
406
- -end-vmgm
407
+If a general option is duplicated inside a **-titleset** or **-vmgm**
408
+area, the general option will be overridden.
409
+
410
+Note: you do not need titlesets for a single menu with chapter break
411
+menus, for that just use **-submenus** or **-ani-submenus**
412
+
413
+Example of using **tovid disc** with titlesets:
414
+
415
+::
416
+
417
+ $ tovid disc -static -out MY_DVD \
418
+ \
419
+ -titleset -files 1.mpg 2.mpg 3.mpg \
420
+ -titles "Title One" "Title Two" "Title Three" \
421
+ -end-titleset \
422
+ \
423
+ -titleset -files 4.mpg 5.mpg \
424
+ -titles "Title Four" "Title Five" \
425
+ -background foo.jpg \
426
+ -showcase bar.png \
427
+ -end-titleset \
428
+ \
429
+ -vmgm \
430
+ -titles "Season One" "Season Two" \
431
+ -background bg.jpg \
432
+ -bgaudio foo.mp3 \
433
+ -titles-fontsize 20 \
434
+ -end-vmgm
435
436
See also **-titleset** and **-vmgm**
437
438
+**Slideshows**
439
+
440
+You can also use **tovid disc** to make slideshows. This can either be a
441
+single slideshow, or multiple slideshows on the same menu. Remember to
442
+use **-slides** rather than **-files** for passing in the images. Images
443
+can be any filetype that imagemagick supports: for example JPEG, PNG,
444
+GIF, TGA BMP etc. For a single slideshow do not use **-titles**: use
445
+-menu-title to set the slideshow title.
446
+
447
+For a single slideshow the default is an animated menu that transitions
448
+from slide to slide. The default transition type is ’crossfade’, which
449
+fades each slide into the next and loops back to the first slide at the
450
+end. If instead you use **-static**, then a static ’polaroid stack’ menu
451
+of all the slides is created, with a single spumux’ed button for
452
+navigating with the enter key. You may have to experiment to find out
453
+which DVD remote button advances the slides. Try the ’next chapter’(skip
454
+?) button and the play or enter buttons. If you want to limit the number
455
+of slides in the menu to a subset of all files entered with **-slides**,
456
+then use **-menu-slide-total** INT. Be sure to use a long enough audio
457
+file for **-bgaudio** or set **-menu-length** so the menu is long enough
458
+to support the slides plus transitions.
459
+
460
+You can also put multiple slideshows on one menu. To do this, use
461
+**-slides IMAGES** for each slideshow desired. You can even mix videos
462
+with slideshows by using **-files** **-slides** **-titles** multiple
463
+times.
464
+
465
+Example of a single slideshow with an animated menu with transitions:
466
467
-.. _usage-slideshows:
468
+::
469
470
-Slideshows
471
--------------------------------------------------------------------------------
472
-
473
-You can also use **tovid disc** to make slideshows. This can either be a single
474
-slideshow, or multiple slideshows on the same menu.
475
-Remember to use **-slides** rather than **-files** for passing in the
476
-images. Images can be any filetype that imagemagick supports: for example
477
-JPEG, PNG, GIF, TGA BMP etc. For a single slideshow do not use **-titles**:
478
-use -menu-title to set the slideshow title.
479
-
480
-For a single slideshow the default is an animated menu that transitions from
481
-slide to slide. The default transition type is 'crossfade', which fades each
482
-slide into the next and loops back to the first slide at the end. If instead
483
-you use **-static**, then a static 'polaroid stack' menu of all the slides is
484
-created, with a single spumux'ed button for navigating with the enter key. You
485
-may have to experiment to find out which DVD remote button advances the slides.
486
-Try the 'next chapter'(skip ?) button and the play or enter buttons.
487
-If you want to limit the number of slides in the menu to a subset of all files
488
-entered with **-slides**, then use **-menu-slide-total** INT. Be sure to use
489
-a long enough audio file for **-bgaudio** or set **-menu-length** so the menu
490
-is long enough to support the slides plus transitions.
491
-
492
-You can also put multiple slideshows on one menu. To do this, use
493
-**-slides IMAGES** for each slideshow desired. You can even mix videos
494
-with slideshows by using **-files** **-slides** **-titles** multiple times.
495
-
496
-Example of a single slideshow with an animated menu with transitions::
497
-
498
- $ tovid disc -menu-title "Autumn in Toronto" -slides images/*.jpg \
499
- -menu-slide-total 20 -slide-transition crossfade -bgaudio slideshow.wav \
500
- -out myslideshow
501
-
502
-Example of multiple slideshows on one menu::
503
-
504
- $ tovid disc -menu-title "Autumn in Toronto" \
505
- -slides photos/september/*.jpg \
506
- -slides photos/october/*.jpg \
507
- -slides photos/november/*.jpg \
508
- -tile3x1 -rotate -5 5 -5 -align center \
509
- -bgaudio background.wav \
510
- -out myslideshow
511
-
512
-Example of mixed videos and slideshows::
513
-
514
- $ tovid disc -menu-title "Autumn in Toronto" \
515
- -files fall_fair.mov \
516
- -slides photos/september/*.jpg \
517
- -files harvest.mpg \
518
- -slides photos/october/*.jpg \
519
- -titles "Fall Fair" "September" "Harvest" "October" \
520
- -background autumn.png \
521
- -bgaudio bg.mp3 \
522
- -out myslideshow
523
-
524
-See the other slideshow options in the :ref:`usage-slideshows` options section.
525
-
526
-Encoding options
527
--------------------------------------------------------------------------------
528
-
529
-These are options for reencoding your non-compliant videos. They are passed
530
-directly to the **tovid mpg** command which is invoked by **tovid disc** when
531
-non-compliant files are found. For details, see the :ref:`command-mpg` section.
532
-Here is a list of possible options you can pass:
533
-
534
-**-config**, **-ntscfilm**, **-dvd-vcd**, **-half-dvd**, **-kvcd**,
535
-**-kvcdx3**, **-kvcdx3a**, **-kdvd**, **-bdvd**, **-704**, **-normalize**,
536
-**-amplitude**, **-overwrite**, **-panavision**, **-force**, **-fps**,
537
-**-vbitrate**, **-quality**, **-safe**, **-crop**, **-filters**,
538
-**-abitrate**, **-priority**, **-deinterlace**, **-progressive**,
539
-**-interlaced**, **-interlaced_bf**, **-type**, **-fit**, **-discsize**,
540
-**-parallel**, **-mkvsub**, **-autosubs**, **-subtitles**, **-update**, \
541
-**-mplayeropts**, **-audiotrack**, **-downmix**, **-ffmpeg**, **-nofifo**,
542
-**-from-gui**, **-slice**, **-async**, **-quiet**,
543
-**-fake**, **-keepfiles**
544
+ $ tovid disc -menu-title "Autumn in Toronto" -slides images/*.jpg \
545
+ -menu-slide-total 20 -slide-transition crossfade -bgaudio slideshow.wav \
546
+ -out myslideshow
547
548
+Example of multiple slideshows on one menu:
549
550
-Basic options
551
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
552
+::
553
+
554
+ $ tovid disc -menu-title "Autumn in Toronto" \
555
+ -slides photos/september/*.jpg \
556
+ -slides photos/october/*.jpg \
557
+ -slides photos/november/*.jpg \
558
+ -tile3x1 -rotate -5 5 -5 -align center \
559
+ -bgaudio background.wav \
560
+ -out myslideshow
561
+
562
+Example of mixed videos and slideshows:
563
+
564
+::
565
+
566
+ $ tovid disc -menu-title "Autumn in Toronto" \
567
+ -files fall_fair.mov \
568
+ -slides photos/september/*.jpg \
569
+ -files harvest.mpg \
570
+ -slides photos/october/*.jpg \
571
+ -titles "Fall Fair" "September" "Harvest" "October" \
572
+ -background autumn.png \
573
+ -bgaudio bg.mp3 \
574
+ -out myslideshow
575
+
576
+See the other slideshow options in the Slideshows options section.
577
+
578
+**Encoding Options**
579
+
580
+These are options for reencoding your non-compliant videos. They are
581
+passed directly to the **tovid mpg** command which is invoked by **tovid
582
+disc** when non-compliant files are found. For details, see the
583
+**Command:mpg** section. Here is a list of possible options you can
584
+pass: **-config**, **-ntscfilm**, **-dvd-vcd**, **-half-dvd**,
585
+**-kvcd**, **-kvcdx3**, **-kvcdx3a**, **-kdvd**, **-bdvd**, **-704**,
586
+**-normalize**, **-amplitude**, **-overwrite**, **-panavision**,
587
+**-force**, **-fps**, **-vbitrate**, **-quality**, **-safe**, **-crop**,
588
+**-filters**, **-abitrate**, **-priority**, **-deinterlace**,
589
+**-progressive**, **-interlaced**, **-interlaced\_bf**, **-type**,
590
+**-fit**, **-discsize**, **-parallel**, **-mkvsub**, **-autosubs**,
591
+**-subtitles**, **-update**, **-mplayeropts**,
592
+**-audiotrack**, **-downmix**, **-ffmpeg**, **-nofifo**, **-from-gui**,
593
+**-slice**, **-quiet**, **-fake**, **-keepfiles**
594
+
595
+Options
596
+-------
597
598
**-keep-files**, **-keepfiles**
599
Keep all intermediate/temporary files (helps with debugging)
600
601
720x576 output, compatible with PAL standard
602
603
**-submenus**
604
- Create a sub-menu with chapters for each video (default: no sub-menus)
605
+ Create a sub-menu with chapters for each video (default: no
606
+ sub-menus)
607
608
**-ani-submenus**
609
- Create an animated sub-menu with chapters for each video (default: not
610
- animated)
611
+ Create an animated sub-menu with chapters for each video (default:
612
+ not animated)
613
614
**-no-menu | -nomenu**
615
- With this option todisc will just create a DVD file system, ready for
616
- burning, with NO MENU, just the supplied video files. These do not need
617
- to be compliant, as non-compliant files will be encoded as usual. Each
618
- video will be a chapter unless **-chapters** OPTION is passed. The
619
- **-chapters** option is a number indicating the chapter interval in
620
- minutes, or a HH:MM:SS string indicating chapter points. See **-chapters**
621
-
622
-
623
-.. _menu-style:
624
-
625
-Basic menu style options
626
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
627
+ With this option todisc will just create a DVD file system, ready
628
+ for burning, with NO MENU, just the supplied video files. These do
629
+ not need to be compliant, as non-compliant files will be encoded as
630
+ usual. The **-out** option is not required. Each video will be a
631
+ chapter unless **-chapters** OPTION is passed. The **-chapters**
632
+ option is a number indicating the chapter interval in minutes, or a
633
+ HH:MM:SS string indicating chapter points. See **-chapters**
634
+
635
+**-encode-only**
636
+ This option was originally meant for the GUI, to allow it to be used
637
+ for just encoding rather than making a DVD structure. But it works
638
+ well from the command line as well as it has the added advantage
639
+ that you can input a list of files. Remember any makempg (’tovid
640
+ mpg’) options you use will be passed on to the the makempg script
641
+ when encoding.
642
+
643
+Menu style
644
+----------
645
646
**-showcase** IMAGE|VIDEO
647
- If used without an argument, use showcase style without a central thumb.
648
- This is a different arrangement of images for the menu: small thumbnails
649
- go at left (and right) side of screen, with a larger image in the centre.
650
- Maximum of 10 videos. If the provided argument is a video file, the
651
- central thumb will be animated. Pick a file of correct aspect ratio:
652
- i.e. it should still look good when resized to 720x480 (PAL 720x576),
653
- then resized to proper aspect ratio.
654
+ If used without an argument, use showcase style without a central
655
+ thumb. This is a different arrangement of images for the menu: small
656
+ thumbnails go at left (and right) side of screen, with a larger
657
+ image in the centre. Maximum of 10 videos. If the provided argument
658
+ is a video file, the central thumb will be animated. Only 4:3 or
659
+ 16:9 videos and images are accepted for the showcase file: if not
660
+ one of these todisc will assume it is the same ratio as the videos
661
+ in the titleset.
662
663
**-textmenu**, **-text-menu** NUM
664
- If used without an argument, create a textmenu out of the supplied titles
665
- The optional argument specifies how many titles are in the 1st column,
666
- i.e. giving 4 titles and using **-textmenu 2** would make 2 columns of 2
667
- titles. The default is to put all titles up to 13 in the first column
668
- before starting a second column. Maximum: 2 columns and 26 titles.
669
- Note that column 2 titles are aligned to the right.
670
- If no video files for either **-background** or **-showcase** are supplied,
671
- the menu will be static.
672
+ If used without an argument, create a textmenu out of the supplied
673
+ titles The optional argument specifies how many titles are in the
674
+ 1st column, i.e. giving 4 titles and using "-textmenu 2" would make
675
+ 2 columns of 2 titles. The default is to put all titles up to 13 in
676
+ the first column before starting a second column. Maximum: 2 columns
677
+ and 26 titles. Note that column 2 titles are aligned to the right.
678
+ If no video files for either **-background** or **-showcase** are
679
+ supplied, the menu will be static.
680
681
**-quick-menu**
682
- (Note: unfortunately ffmpeg's 'vhooks' have been removed, so this
683
- option may not be available for you depending on your ffmpeg version)
684
- This will make a very quick menu by using ffmpeg instead of imagemagick.
685
- There are two choices: you can either use **-showcase IMAGE|VIDEO** or
686
- **-background VIDEO**. There are no fancy effects like **-wave**
687
- or **-rotate** available for it, but it is extremely fast. It will be a
688
- text-menu style of menu, with no video thumbs, and a central showcase
689
- IMAGE (static) | VIDEO (animated). See **-bg-color** if you are not using
690
- a **-background** and want to change the default black.
691
-
692
- Specifying the IMAGE|VIDEO argument to **-showcase** is mandatory for this
693
- style of menu, unless used in conjunction with **-switched-menus**
694
- in which case the videos passed with **-files** automatically become the
695
- showcase videos. If this is used in combination with **-switched-menus**
696
- it can really speed up an otherwise time consuming process.
697
-
698
- Example::
699
-
700
- -quick-menu -showcase /home/robert/showcase.mpg
701
+ If you are using ffmpeg 0.8 or newer you can use this option. This
702
+ will make a very quick menu by using ffmpeg instead of imagemagick.
703
+ There are two choices: you can either use ’-showcase
704
+ IMAGE|VIDEO or ’-background VIDEO’. There are no fancy
705
+ effects like **-wave** or **-rotate** available for it, but it is
706
+ extremely fast. It will be a text-menu style of menu, with no video
707
+ thumbs, and a central showcase IMAGE(static) | VIDEO(animated).
708
+ (i) see **-bg-color** if you are not using a **-background** and
709
+ want to change the default black ) (ii) Note: todisc will still work
710
+ with vhooks if you have an old ffmpeg with vhooks compiled in.
711
+
712
+ Specifying the IMAGE|VIDEO argument to **-showcase** is
713
+ mandatory for this style of menu, unless used in conjunction with
714
+ **-switched-menus** in which case the videos passed with **-files**
715
+ automatically become the showcase videos. If this is used in
716
+ combination with **-switched-menus** it can really speed up an
717
+ otherwise time consuming process.
718
+
719
+ Example:
720
+
721
+ ::
722
+
723
+ -quick-menu -showcase /home/robert/showcase.mpg
724
725
See **-switched-menus** for example of making switched menus with
726
**-quick-menu**
727
728
-**-bg-color** | **-bg-colour**
729
+**-bg-color**, **-bg-colour**
730
The color to use for the menu background. (default: ntsc-safe black)
731
- Note: use a color a great deal darker than you want, as it appears quite
732
- a bit lighter in the video version. You can use hexadecimal ('#ffac5f')
733
- or named colors notation.
734
-
735
-**-submenu-bg-color** | **-submenu-bg-colour**
736
- The color to use as background for the submenu(s).
737
- (default: ntsc-safe black) See **-bg-color**
738
+ Note: use a color a great deal darker than you want, as it appears
739
+ quite a bit lighter in the video version. You can use hexadecimal
740
+ (’#ffac5f’) or named colors notation.
741
742
-**-use-makemenu**
743
- This will use **tovid menu** to create a menu with the provided titles.
744
+**-submenu-bg-color**, **-submenu-bg-colour**
745
+ The color to use as background for the submenu(s). (default:
746
+ ntsc-safe black) See **-bg-color**
747
748
**-static**
749
- Main menu will just be static thumbs (not animated) (default: animated)
750
+ Main menu will consist of static thumbnail links. (default:
751
+ animated) If you use a video for -showcase or -background then it
752
+ will still be a ’moving’ menu, in spite of the static buttons. This
753
+ option also does double duty for the **-switched-menus** option, and
754
+ will create static "switched" images. See also **-switched-menu**
755
756
**-background** IMAGE|VIDEO
757
- Menu background. This can be a image file or an video file. If it is a
758
- video file the background will be animated. Pick a file of correct aspect
759
- ratio: i.e. it should still look good when resized to 720x480 (PAL 720x576)
760
+ Menu background. This can be a image file or an video file. If it is
761
+ a video file the background will be animated. Pick a file of correct
762
+ aspect ratio: i.e. it should still look good when resized to 4:3
763
+ aspect ratio. It will be resized to fill the entire background.
764
765
**-submenu-background** IMAGE
766
- Submenu background. This can be only be an image file. Pick a file of
767
- correct aspect ratio: i.e. it should still look good when resized to
768
- 720x480 (PAL 720x576)
769
+ Submenu background. This can be only be an image file. Pick a file
770
+ of correct aspect ratio: i.e. it should still look good when resized
771
+ to 4:3 aspect ratio. It will be resized to fill the entire
772
+ background.
773
774
**-menu-title**
775
- Title for the root menu - may be longer than thumbnail labels
776
- Also if you use \n in the title, you can use multi line titles, but you
777
- would need to adjust **-menu-fontsize** to something smaller than default
778
- for example::
779
+ Title for the root menu - may be longer than thumbnail labels Also if you
780
+ use \n in the title, you can use multi line titles, but you would need to
781
+ adjust **-menu-fontsize** to something smaller than default for example:
782
783
- $ tovid disc ... -menu-title "A\nMultilined\nTitle" -menu-fontsize 24
784
+ ::
785
+
786
+ $ tovid disc ... -menu-title "A\nMultilined\nTitle" -menu-fontsize 24
787
788
**-menu-font** FONT
789
- Font to use for titles, either by ImageMagick font name (ex., "Arial") or
790
- explicit pathname (ex., "/full/path/to/arial.ttf"). To see a complete
791
- list of acceptable ImageMagick font names, run **convert -list type**, and
792
- refer to the leftmost column
793
+ Font to use for titles, either by ImageMagick font name (ex.,
794
+ "Arial") or explicit pathname (ex., "/full/path/to/arial.ttf"). To
795
+ see a complete list of acceptable ImageMagick font names, run
796
+ **convert -list type**, and refer to the leftmost column
797
798
**-menu-fontsize**
799
- Font size for main menu - best to **-preview** if you use this
800
+ Font size for main menu - best to -preview if you use this
801
802
**-submenu-font**
803
- Font to use for the sub-menu main titles. See **-menu-font**
804
+ Font to use for the sub-menu main titles. See **-menu-font**
805
806
**-submenu-fontsize**
807
Font size for the sub-menu main titles
808
809
-**-menu-fade** ['BACKGROUND DURATION']
810
- Fade the menu in and out The background will fade in first, then title (and
811
- mist if called for), then the menu thumbs. The fadeout is in reverse
812
- order. 'BACKGROUND DURATION' is an integer denoting the amount of time the
813
- background will play before the menu begins to fade in. This can allow you
814
- to do a 'transition' to the menu: if you supply a **-background VIDEO** it
815
- will play for the indicated time before the menu fades in. Leave the
816
- optional argument empty (just **-menu-fade**) to get the default behavior
817
- of showing the background for 1 second before fading the menu in. To
818
- disable the fadeout portion, use '**-loop** inf'. See also:
819
+**-menu-fade** [’BACKGROUND DURATION’]
820
+ Fade the menu in and out The background will fade in first, then
821
+ title (and mist if called for), then the menu thumbs. The fadeout is
822
+ in reverse order. ’BACKGROUND DURATION’ is an integer denoting the
823
+ amount of time the background will play before the menu begins to
824
+ fade in. This can allow you to do a ’transition’ to the menu: if you
825
+ supply a -background VIDEO it will play for the indicated time
826
+ before the menu fades in. Leave the optional argument empty (just
827
+ **-menu-fade**) to get the default behavior of showing the
828
+ background for 1 second before fading the menu in. To disable the
829
+ fadeout portion, use ’**-loop** inf’. See also:
830
**-transition-to-menu** and **-loop**
831
832
**-transition-to-menu**
833
This option goes with the **-menu-fade** option above, which must be
834
- enabled for it to have effect. It is a convenience option for animated
835
- backgrounds: the background will become static at the exact point the
836
- thumbs finish fading in. This menu does not loop unless you pass
837
- **-loop VALUE**. See also: **-loop**
838
+ enabled for it to have effect. It is a convenience option for
839
+ animated backgrounds: the background will become static at the exact
840
+ point the thumbs finish fading in. This menu does not loop unless
841
+ you pass **-loop** VALUE. See also: **-loop**
842
843
-**-bgaudio**, **-bg-audio** FILE
844
- An file containing audio for the main menu background. For static menus
845
- the default is to use 20 seconds of audio. You can change this using the
846
- **-menu-length** option.
847
+**-bgaudio**, **-bg-audio\*** FILE
848
+ An file containing audio for the main menu background. For static
849
+ menus the default is to use 20 seconds of audio. You can change this
850
+ using the **-menu-length** option.
851
852
**-submenu-audio** FILE(S)
853
- List of files for sub-menu audio backgrounds. If one file is given, then
854
- it will be used for all sub-menus. Otherwise the number given must equal
855
- the number of submenus, though the keyword "none" in this list may be used for
856
- silence. See also **-submenu-length**
857
+ List of files for sub-menu audio backgrounds. If one file is given,
858
+ then it will be used for all sub-menus. Otherwise the number given
859
+ must equal the number of submenus, though the keyword "none" in this
860
+ list may be used for silence. See also **-submenu-length**
861
862
**-titleset** . . . **-end-titleset**
863
- If you have more than one titleset, put options for each titleset between
864
- **-titleset** and **-end-titleset**. A separate menu will be created that
865
- can be accessed from the main menu (VMGM). You can create this main menu
866
- using the **-vmgm** **-end-vmgm** options. See **-vmgm** below and
867
- :ref:`usage-titlesets` under the **Usage** section.
868
+ If you have more than one titleset, put options for each titleset
869
+ between **-titleset** and **-end-titleset**. A separate menu will be
870
+ created that can be accessed from the main menu (VMGM). You can
871
+ create this main menu using the **-vmgm** **-end-vmgm** options. See
872
+ **-vmgm** below and TITLESET paragraph opening **Usage** section.
873
874
**-vmgm** . . . **-end-vmgm**
875
- The VMGM menu is the root menu when you use titlesets.
876
- Put your VMGM menu options between **-vmgm** and **-end-vmgm**.
877
- You only need **-titles** "Titleset One title" "Titleset Two title"
878
- . . . , and not **-files**.
879
- Any other options can be used, but the menu will be a textmenu style by
880
- default. **Hint**: use **-showcase** IMAGE/VIDEO to create a fancier
881
- VMGM menu.
882
-
883
-**-no-vmgm-menu** | **-no-vmgm**
884
- This will skip the creation of a VMGM ( root menu ) for titlesets. The DVD
885
- will start with the first titleset. You can not use this option unless also
886
- using **-quick-nav** as you would not have a way to get to other titlesets.
887
+ The VMGM menu is the root menu when you use titlesets. Put your VMGM
888
+ menu options between **-vmgm** and **-end-vmgm**. You only need
889
+ **-titles** "Titleset One title" "Titleset Two title" . . . , and
890
+ not **-files**. Any other options can be used, but the menu will be
891
+ a textmenu style by default. **Hint**: use **-showcase** IMAGE/VIDEO
892
+ to create a fancier VMGM menu.
893
+
894
+**-no-vmgm-menu**, **-no-vmgm**
895
+ This will skip the creation of a VMGM ( root menu ) for titlesets.
896
+ The DVD will start with the first titleset. You can not use this
897
+ option unless also using **-quick-nav** as you would not have a way
898
+ to get to other titlesets.
899
900
**-skip-vmgm**
901
Start DVD from the first titleset instead of the VMGM ( root ) menu.
902
903
**-switched-menus**
904
- This will make a "switched menu": there will be a central image where the
905
- showcase image would go, and text menu titles along the menu edge where
906
- textmenu titles go. As you select a video title with the down or up arrow
907
- on your DVD remote, the image in the centre will change to the image or
908
- video made from that selected video. Do not use **-showcase** IMAGE/VIDEO
909
- with this option.
910
+ This will make a "switched menu": there will be a central image
911
+ where the showcase image would go, and text menu titles along the
912
+ menu edge where textmenu titles go. As you select a video title with
913
+ the down or up arrow on your DVD remote, the image in the centre
914
+ will change to the image or video made from that selected video. Do
915
+ not use **-showcase** IMAGE/VIDEO with this option.
916
+
917
+ This can be a time consuming process for making animated menus as
918
+ you need to make a separate menu for each video provided with
919
+ **-files**. The process can be greatly sped up by using
920
+ **-quick-menu** in conjunction with this, though you will lose fancy
921
+ options like **-rotate** and **-wave**.
922
923
- This can be a time consuming process for making animated menus as you need
924
- to make a separate menu for each video provided with **-files**. The
925
- process can be greatly sped up by using **-quick-menu** in conjunction with
926
- this, though you will lose fancy options like **-rotate** and **-wave**.
927
+ Note that if you want to just have a static rather than an
928
+ ’animated’ image, add **-static** to the command line.
929
930
- Example for using with **-quick-menu**::
931
+ Example for using with **-quick-menu**:
932
933
- -switched-menus -quick-menu
934
+ ::
935
936
+ -switched-menus -quick-menu
937
938
Thumbnail style
939
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
940
-
941
-**-thumb-shape** normal|oval|vignette|plectrum|arch|spiral|blob|star|flare
942
- Apply a shaped transparency mask to thumbnail videos.
943
- These "feathered" shapes look best against a plain background (or used
944
- in conjunction with **-thumb-mist** [COLOR]). For this rectangular
945
- semi-transparent misted background for each thumb: see **-thumb-mist**.
946
- Note: if you wish to make your own mask PNGS you can put them in
947
- $PREFIX/lib/tovid/masks/ or $HOME/.tovid/masks/ and use them on the
948
- command line using the filename minus the path and extension.
949
- (i.e ~/.tovid/masks/tux.png becomes **-thumb-shape tux**)
950
+---------------
951
+
952
+**-thumb-shape**
953
+ normal|oval|vignette|plectrum|arch|spiral|blob|star|flare
954
+ Apply a shaped transparency mask to thumbnail videos. These
955
+ "feathered" shapes look best against a plain background (or used in
956
+ conjunction with **-thumb-mist** [COLOR]). For this rectangular
957
+ semi-transparent misted background for each thumb: see
958
+ **-thumb-mist**. Note: if you wish to make your own mask PNGS you
959
+ can put them in $PREFIX/lib/tovid/masks/ or $HOME/.tovid/masks/ and
960
+ use them on the command line using the filename minus the path and
961
+ extension. (i.e ~{}/.tovid/masks/tux.png becomes -thumb-shape tux)
962
No frame is used for shaped thumbs.
963
964
**-thumb-frame-size** INT
965
- The size (thickness) of the thumb frames in pixels. This will also set the
966
- thickness of the raised "frame" of thumbs when you use **-3d-thumbs**.
967
- See also **-showcase-frame-size** and **-thumb-frame-color**
968
+ The size (thickness) of the thumb frames in pixels. This will also
969
+ set the thickness of the raised "frame" of thumbs when you use
970
+ **-3d-thumbs**. See also **-showcase-frame-size** and
971
+ **-thumb-frame-color**
972
973
**-thumb-frame-color**, **-thumb-frame-colour** COLOR
974
- The color of frames for video thumbnails. Use hexadecimal or named colors
975
- notation. Remember to quote if using hexadecimal! ( '#ffac5f' ).
976
+ The color of frames for video thumbnails. Use hexadecimal or named
977
+ colors notation. Remember to quote if using hexadecimal! ( ’#ffac5f’
978
+ ).
979
980
**-3d-thumbs**, **-3dthumbs**
981
- This will give an illusion of 3D to the thumbnails: dynamic lighting on
982
- rounded thumbs, and a raised effect on rectangular thumbs. Try it !
983
+ This will give an illusion of 3D to the thumbnails: dynamic lighting
984
+ on rounded thumbs, and a raised effect on rectangular thumbs. Try it
985
+ !
986
987
**-titles-font** FONT
988
Display thumbnail or textmenu titles in the given font
989
990
**-titles-fontsize** POINTS
991
Font size to use for thumbnail or textmenu titles
992
993
-
994
Slideshows
995
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
996
+----------
997
998
**-slides** IMAGES
999
- Use **-slides** IMAGES to pass in images for a slideshow. The default is
1000
- to make an animated menu of the slides, moving from one slide to the
1001
- next. If you use **-static**, a 'polaroid stack' montage is created. This
1002
- composites the slides onto the background in 'random' locations with random
1003
- rotations. **-slides** IMAGES can be used multiple times if you wish to
1004
- make a menu with multiple slideshows. You can also make a menu
1005
- of mixed videos and slideshows by using **-slides** IMAGES, and **-files**
1006
- VIDEOS multiple times. For such a menu, the number of **-titles**
1007
- needs to match the number of **-files** passed in plus the number of
1008
- slideshows. (Each time you use **-slides** counts as one title.) To use
1009
- a transition between the slides, use **-slide-transition**
1010
- crossfade|fade. See **-slide-transition** **-menu-slide-total**
1011
+ Use **-slides** IMAGES to pass in images for a slideshow. The
1012
+ default is to make an animated menu of the slides, moving from one
1013
+ slide to the next. If you use **-static**, a ’polaroid stack’
1014
+ montage is created. This composites the slides onto the background
1015
+ in ’random’ locations with random rotations. **-slides** IMAGES can
1016
+ be used multiple times if you wish to make a menu with multiple
1017
+ slideshows. You can also make a menu of mixed videos and slideshows
1018
+ by using **-slides** IMAGES, and **-files** VIDEOS multiple times.
1019
+ For such a menu, the number of **-titles** needs to match the number
1020
+ of **-files** passed in plus the number of slideshows. (Each time
1021
+ you use **-slides** counts as one title.) To use a transition
1022
+ between the slides, use **-slide-transition**
1023
+ crossfade|fade. See **-slide-transition** **-menu-slide-total**
1024
1025
**-menu-slide-total** INT
1026
- Use INT number of the slides that were passed in with **-slides**
1027
- to make the animated or static slide menu. The length of the menu is
1028
- determined by 1) **-menu-length** NUM if given, and by 2) the length
1029
- of the audio from **-bgaudio**. For submenu slideshows, it is determined
1030
- by 1) **-submenu-length** NUM if given, and by 2) the length of the
1031
- audio from **-submenu-audio** FILE(S).
1032
+ Use INT number of the slides that were passed in with **-slides** to
1033
+ make the animated or static slide menu. The length of the menu is
1034
+ determined by 1) **-menu-length** NUM if given, and by 2) the length
1035
+ of the audio from **-bgaudio**. For submenu slideshows, it is
1036
+ determined by 1) **-submenu-length** NUM if given, and by 2) the
1037
+ length of the audio from **-submenu-audio** FILE(S).
1038
1039
**-submenu-slide-total** INT
1040
This option is the same as **-menu-slide-total** except that it is
1041
for submenu slideshows.
1042
1043
**-slide-transition** crossfade|fade [crossfade]
1044
- The type of fade transition between slides in a animated slide menu. Be
1045
- sure the menu length is long enough to support the 1 second transitions
1046
- between the slides. The length is determined by 1) the length of the
1047
- **-bgaudio AUDIO** and 2) the length given with **-menu-length NUM**. For
1048
- submenu slideshows, it is determined by 1) **-submenu-length NUM** if
1049
- given, and by 2) the length of the audio from **-submenu-audio** FILE(S).
1050
+ The type of fade transition between slides in a animated slide menu.
1051
+ Be sure the menu length is long enough to support the 1 second
1052
+ transitions between the slides. The length is determined by 1) the
1053
+ length of the -bgaudio AUDIO 2) the length given with -menu-length
1054
+ NUM. For submenu slideshows, it is determined by 1)
1055
+ **-submenu-length** NUM if given, and by 2) the length of the audio
1056
+ from **-submenu-audio** FILE(S).
1057
1058
See **-menu-slide-total** , **-bgaudio** , **-menu-length** ,
1059
**-submenu-length**, and **-submenu-audio**.
1060
1061
- The 'crossfade' transition fades from one slide to another. The 'fade'
1062
- transition fades in and out from and to black. If you don't use this
1063
- option, the default is to use a 'crossfade' transition.
1064
+ The ’crossfade’ transition fades from one slide to another. The
1065
+ ’fade’ transition fades in and out from and to black. If you don’t
1066
+ use this option, the default is to use a ’crossfade’ transition.
1067
1068
**-slideshow-menu-thumbs** FILES
1069
Use the FILES instead of the 1st image in each slideshow as the
1070
- thumb that shows on the menu. This option is for multiple slideshows
1071
+ thumb that shows on the menu. This option is for multiple slideshows
1072
or mixed slideshow/video menus only.
1073
1074
**-slides-to-bin** FILES
1075
- FILES will be resized to 640x480 using a 'box' filter - this
1076
- is called 'binning'. It will reduce the 'signal to noise' ratio for the
1077
- image in the animated slide menu. Use this if you get some unwanted
1078
- effects for certain images, such as pixels shifting in what should be a
1079
- static image. See also **-slides-to-blur** and **-slide-border**
1080
+ FILES will be resized to 640x480 using a ’box’ filter - this is
1081
+ called ’binning’. It will reduce the ’signal to noise’ ratio for the
1082
+ image in the animated slide menu. Use this if you get some unwanted
1083
+ effects for certain images, such as pixels shifting in what should
1084
+ be a static image. See also **-slides-to-blur** and
1085
+ **-slide-border**
1086
1087
**-slides-to-blur** FILES
1088
- FILES will be blurred a small amount - which will help on
1089
- slides that still have noise even after 'binning' with -slides-to-bin.
1090
- The default blur is 0x0.2 - you can increase this with
1091
- -slide-blur ARG. See also **-slides-to-bin** and **-slide-border**
1092
+ FILES will be blurred a small amount - which will help on slides
1093
+ that still have noise even after ’binning’ with -slides-to-bin. The
1094
+ default blur is 0x0.2 - you can increase this with -slide-blur ARG.
1095
+ See also **-slides-to-bin** and **-slide-border**
1096
1097
**-slide-blur** VALUE or LIST of VALUES [0x0.2]
1098
- The argument to use for blurring files. It will be passed to
1099
- imagemagick: convert -blur ARG. The format of the arg is {radius}x{sigma}
1100
- and the default is 0x0.2. Using values between 0x0.1 and 0x0.9 is probably
1101
- the best range. Use a single value for all, or a list to have a different
1102
- blur for each file passed with **-slides-to-blur**. You must pass in
1103
- **-files-to-blur** FILES to use this option. Blurring can help 'noise'
1104
- problems in the video. See also **-slides-to-bin** and **-slide-border**
1105
+ The argument to use for blurring files. It will be passed to
1106
+ imagemagick: convert -blur ARG. The format of the arg is
1107
+ {radius}x{sigma} and the default is 0x0.2. Using values between
1108
+ 0x0.1 and 0x0.9 is probably the best range. Use a single value for
1109
+ all, or a list to have a different blur for each file passed with
1110
+ **-slides-to-blur**. You must pass in **-files-to-blur** FILES to
1111
+ use this option. Blurring can help ’noise’ problems in the video.
1112
+ See also **-slides-to-bin** and **-slide-border**
1113
1114
**-slide-border** WIDTH [100]
1115
- Pad the slides with a border for the animated slide menu. The default
1116
- without using an argument is 100. Using this option can also solve some
1117
- noise/ringing effects if used alone or in conjunction with 'binning'
1118
- (**-slides-to-bin**) or blurring (**-slides-to-blur**).
1119
+ Pad the slides with a border for the animated slide menu. The
1120
+ default without using an argument is 100. Using this option can also
1121
+ solve some noise/ringing effects if used alone or in conjunction
1122
+ with ’binning’ (**-slides-to-bin**) or blurring
1123
+ (**-slides-to-blur**).
1124
1125
**-slide-frame** WIDTH [12]
1126
- Frame the slides for the animated slideshow menu. The default width
1127
- without using an argument is 12. See also **-slide-frame-color**
1128
+ Frame the slides for the animated slideshow menu. The default width
1129
+ without using an argument is 12. See also **-slide-frame-color**
1130
1131
-**-slide-frame-color** | **-slide-frame-colour**
1132
- The color of the slide frame if passing **-slide-frame**. The default if
1133
- you don't use this option is a color-safe white: rgb(235,235,235).
1134
+**-slide-frame-color**, **-slide-frame-colour**
1135
+ The color of the slide frame if passing **-slide-frame**. The
1136
+ default if you don’t use this option is a color-safe white:
1137
+ rgb(235,235,235).
1138
1139
**-showcase-slideshow**
1140
- If doing multiple slideshows or mixed videos and slideshow(s), then use
1141
- the animated slideshow as a showcase video. It will be composed of slides
1142
- from each slideshow in the menu. The thumb for each slideshow button will
1143
- be static. If you used with a mixed menu of videos and slideshows, then
1144
- the video thumbs WILL be animated, so you may wish to use -static or
1145
- -textmenu with the option in that case.
1146
+ If doing multiple slideshows or mixed videos and slideshow(s), then
1147
+ use the animated slideshow as a showcase video. It will be composed
1148
+ of slides from each slideshow in the menu. The thumb for each
1149
+ slideshow button will be static. If you used with a mixed menu of
1150
+ videos and slideshows, then the video thumbs WILL be animated, so
1151
+ you may wish to use -static or -textmenu with the option in that
1152
+ case. If you want to use the \*\*-switched-menus option with a mixed
1153
+ menu leave this option out.
1154
1155
**-background-slideshow**, **-bg-slideshow**
1156
- If doing multiple slideshows or mixed videos and slideshow(s), then use
1157
- the animated slideshow as a background video. See **-showcase-slideshow**
1158
- for additional details.
1159
+ If doing multiple slideshows or mixed videos and slideshow(s), then
1160
+ use the animated slideshow as a background video. See
1161
+ **-showcase-slideshow** for additional details.
1162
1163
**-no-confirm-backup**
1164
- Slideshows are an experimental (but well tested) feature. Todisc is
1165
- unlikely to overwrite your personal files, but you should take precautions
1166
- and backup your images, as you would with any beta software. Todisc
1167
- will prompt you to backup your files normally. If you have already backed
1168
- up your images, use this option to disable the prompt.
1169
-
1170
-**-use-dvd-slideshow** [FILE CONFIG]
1171
+ Slideshows are an experimental (but well tested) feature. Todisc is
1172
+ unlikely to overwrite your personal files, but you should take
1173
+ precautions and backup your images, as you would with any beta
1174
+ software. Todisc will prompt you to backup your files normally. If
1175
+ you have already backed up your images, use this option to disable
1176
+ the prompt.
1177
+
1178
+**-use-dvd-slideshow** {CONFIG} {FILE}
1179
If you pass this option without an argument, tovid will use the
1180
- dvd-slideshow program to create the animated slide menu, assuming you have
1181
- this program installed. The optional argument is the dvd-slideshow
1182
- configuration file - if you don't use this argument tovid will create it
1183
- for you. If you want to use the 'Ken Burns effect' - then the
1184
- configuration file argument is required. Note: the configuration file will
1185
- override many of the above options for slideshows.
1186
+ dvd-slideshow program to create the animated slide menu, assuming
1187
+ you have this program installed. The optional argument is the
1188
+ dvd-slideshow configuration file - if you don’t use this argument
1189
+ tovid will create it for you. If you want to use the ’Ken Burns
1190
+ effect’ - then the configuration file argument is required. Note:
1191
+ the configuration file will override many of the above options for
1192
+ slideshows.
1193
+
1194
+Burning the disc
1195
+----------------
1196
1197
+**-burn**
1198
+ Prompt to burn the DVD directory on completion.
1199
1200
-Advanced Options
1201
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1202
+**-device**
1203
+ Device to use for the burning program [ /dev/dvdrw ]
1204
+
1205
+**-speed**
1206
+ The speed to use for burning the disc.
1207
+
1208
+Advanced usage
1209
+--------------
1210
+
1211
+Options
1212
+~~~~~~~
1213
1214
**-menu-length**
1215
The desired animated main menu length in seconds
1216
1217
**-submenu-length**
1218
- The desired submenu length. This will also affect the length of submenu
1219
- audio for static submenus. (Assuming that -submenu-audio was passed in).
1220
- The default is to use 10 seconds of audio for static menus.
1221
+ The desired submenu length. This will also affect the length of
1222
+ submenu audio for static submenus. (Assuming that -submenu-audio was
1223
+ passed in). The default is to use 10 seconds of audio for static
1224
+ menus.
1225
1226
**-submenu-stroke** COLOR
1227
- The color for the sub-menu font outline (stroke)
1228
+ The color for the sub-menu font shadow
1229
1230
**-submenu-title-color**, **-submenu-title-colour**
1231
The fill color used for sub-menu title fonts
1232
1233
**-submenu-titles**
1234
- You can supple a list of titles here for sub-menus without the length
1235
- restrictions found in thumb titles. Must equal number of videos
1236
+ You can supple a list of titles here for sub-menus without the
1237
+ length restrictions found in thumb titles. Must equal number of
1238
+ videos
1239
1240
**-chapters** [ NUM | CHAPTER POINTS in HH:MM:SS ]
1241
- The number of chapters for each video (default: 6) OR
1242
- the actual chapter points in HH:MM:SS format.
1243
- Chapter points will be used for generating the submenu thumbs, and for
1244
- seeking with your DVD player. You can pass in just one value that will
1245
- be used for all videos, or supply a list of values (number of chapters)
1246
- or time code strings.
1247
+ The number of chapters for each video (default: 6) OR the actual
1248
+ chapter points in HH:MM:SS format. Chapter points will be used for
1249
+ generating the submenu thumbs, and for seeking with your DVD player.
1250
+ You can pass in just one value that will be used for all videos, or
1251
+ supply a list of values (number of chapters) or time code strings.
1252
1253
- If you just pass an integer for 'number of chapters', then tovid will
1254
- make the chapter points for you by dividing the video length by the number
1255
- you supply. If using the **-no-menu** option, the INT passed in will be
1256
- the chapter interval in minutes, rather than the above formula.
1257
+ If you just pass an integer for ’number of chapters’, then tovid
1258
+ will make the chapter points for you by dividing the video length by
1259
+ the number you supply. If using the **-no-menu** option, the INT
1260
+ passed in will be the chapter interval in minutes, rather than the
1261
+ above formula.
1262
1263
- If passing HH:MM:SS format you need to pass the string of chapter points for
1264
- each video and each string should have comma separated values.
1265
- Additionally, the first chapter should always start at 00:00:00 as
1266
- dvdauthor will add that if it is not there already.
1267
+ If passing HH:MM:SS format you need to pass the string of chapter
1268
+ points for each video and each string should have comma separated
1269
+ values. Additionally, the first chapter should always start at
1270
+ 00:00:00 as dvdauthor will add that if it is not there already.
1271
1272
- To get your time codes, you can play your videos in mplayer and press 'o'
1273
- to see them on-screen. I have found these to be very accurate in my short
1274
- tests. For greater frame accuracy you could try loading the file in
1275
- avidemux and find the time codes for the frames you want.
1276
+ To get your time codes, you can play your videos in mplayer and
1277
+ press ’o’ to see them on-screen. I have found these to be very
1278
+ accurate in my short tests. For greater frame accuracy you could try
1279
+ loading the file in avidemux and find the time codes for the frames
1280
+ you want.
1281
1282
- If passing grouped chapters you need to join the chapters from all the
1283
- videos in a group with a '+' separator. If you want to skip creating
1284
- chapters for a video in the group use '0' for its chapters.
1285
+ If passing grouped chapters you need to join the chapters from all
1286
+ the videos in a group with a ’+’ separator. If you want to skip
1287
+ creating chapters for a video in the group use ’0’ for its chapters.
1288
1289
- Note: chapters for grouped videos should probably be passed in using the
1290
- above HH:MM:SS format. (Arbitrary chapters using just an INT for the # of
1291
- chapters is not guaranteed to work reliably in all cases for grouped videos
1292
- at the moment.)
1293
+ Note: chapters for grouped videos should probably be passed in using
1294
+ the above HH:MM:SS format. (Arbitrary chapters using just an INT for
1295
+ the # of chapters is not guaranteed to work reliably in all cases
1296
+ for grouped videos at the moment.)
1297
1298
- Example for passing just number of chapters ( 4 videos )::
1299
+ Example for passing just number of chapters ( 4 videos ):
1300
1301
- -chapters 5 2 4 8
1302
+ ::
1303
1304
- Example of passing chapter points ( 4 videos )::
1305
+ -chapters 5 2 4 8
1306
1307
- -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45 \
1308
- 00:00:00,00:04:25.623,00:09:12,00:15:51 \
1309
- 00:00:00,00:05:10,00:13:41,00:18:13.033 \
1310
- 00:00:00,00:15:23.342,00:26:42.523
1311
+ Example of passing chapter points ( 4 videos ):
1312
1313
- Example of passing grouped chapters using the '+' separator::
1314
+ ::
1315
1316
- -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45+00:04:23,00:09:35 \
1317
- 00:00:00... etc.
1318
+ -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45 \
1319
+ 00:00:00,00:04:25.623,00:09:12,00:15:51 \
1320
+ 00:00:00,00:05:10,00:13:41,00:18:13.033 \
1321
+ 00:00:00,00:15:23.342,00:26:42.523
1322
+
1323
+ Example of passing grouped chapters using the ’+’ separator:
1324
+
1325
+ ::
1326
+
1327
+ -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45+00:04:23,00:09:35 \
1328
+ 00:00:00... etc.
1329
1330
**-chapter-titles** LIST
1331
If you are using submenus, you can pass a list of titles for the
1332
- chapters. Each title must be quoted, and the number of titles given
1333
- must equal the total number of chapters for all videos. In other words
1334
- if you use -chapters 4 6 8 , you must give 18 chapter titles, in the same
1335
- order that the videos were passed in.
1336
+ chapters. Each title must be quoted, and the number of titles given
1337
+ must equal the total number of chapters for all videos. In other
1338
+ words if you use -chapters 4 6 8 , you must give 18 chapter titles,
1339
+ in the same order that the videos were passed in. Note: if you are
1340
+ passing in options on the command line to the ’tovid disc’ GUI, you
1341
+ must repeat the option **-chapter-titles** for each video,
1342
+ accompanied by its respective chapter titles. (you can also choose
1343
+ to use this syntax for the todisc script.)
1344
1345
**-chapter-font** FONT
1346
Use FONT as the font for submenu chapters.
1347
1348
The color for the chapters font.
1349
1350
**-chapter-stroke** COLOR
1351
- The color for the chapters font outline (stroke)
1352
+ The color for the chapters font shadow
1353
1354
**-seek** NUM | "NUM1 NUM2 NUM3 . . ."
1355
- Seek to NUM seconds before generating thumbnails (default: 2.0 seconds)
1356
- If a quoted string of values matching the number of videos is used, then
1357
- each video can use a different seek value
1358
- If using switched menus, the **-seek** value(s) will be used to generate
1359
- the showcase image that displays on switching to another video choice with
1360
- the up/down arrow keys.
1361
+ Seek to NUM seconds before generating thumbnails (default: 2.0
1362
+ seconds) If a quoted string of values matching the number of videos
1363
+ is used, then each video can use a different seek value If using
1364
+ switched menus, the **-seek** value(s) will be used to generate the
1365
+ showcase image that displays on switching to another video choice
1366
+ with the up/down arrow keys.
1367
+
1368
+**-fast-seek**
1369
+ Use faster seek method for ffmpeg. This is not as accurate as the
1370
+ default method, and may produce grey frames.
1371
+
1372
+**-frame-safe** Instead of seeking and then outputting one frame for
1373
+ previews and static menus, output 9 frames and choose the largest.
1374
+ Not frame accurate (may be as much as 9 frames off), but safer.
1375
+ Choose this if you are getting grey frames/thumbnails with some
1376
+ videos. You can also use it to try to get the ’best’ frame. This
1377
+ option has no effect on submenus at present.
1378
1379
**-showcase-seek** NUM
1380
Seek to NUM seconds before generating thumbnails for showcase video
1381
1382
Seek to NUM seconds before generating images for background video
1383
(default: 2.0 seconds)
1384
1385
-**-bgaudio-seek**, **-bg-audio-seek** NUM
1386
- Seek to NUM seconds before generating audio for bgaudio
1387
- (default: 2.0 seconds)
1388
+**-bgaudio-seek**, \*\*-bg-audio-seek NUM
1389
+ Seek to NUM seconds before generating audio for bgaudio (default:
1390
+ 2.0 seconds)
1391
1392
**-group** N VIDEO1 VIDEO2 . . .
1393
- Allow grouping videos in dvdauthor.xml, so they will play sequentially as
1394
- a group. The videos passed in after the 'N' will be grouped with the 'Nth'
1395
- video. Example::
1396
+ Allow grouping videos in dvdauthor.xml, so they will play
1397
+ sequentially as a group. The videos passed in after the ’N’ will be
1398
+ grouped with the ’Nth’ video. Example:
1399
1400
- -group 2 2.mpg 3.mpg 4.mpg
1401
+ ::
1402
1403
- will group these 3 videos with the 2nd video given with **-files**, so that
1404
- they will play sequentially as one title. Only one thumbnail and/or title
1405
- will appear on the menu for the group: it will be made from the 1st video
1406
- in the group. In the above example if you passed::
1407
+ -group 2 2.mpg 3.mpg 4.mpg
1408
1409
- -files foo.mpg bar.mpg baz.mpg -group 2 2.mpg 3.mpg 4.mpg
1410
+ will group these 3 videos with the 2nd video given with **-files**,
1411
+ so that they will play sequentially as one title. Only one thumbnail
1412
+ and/or title will appear on the menu for the group: it will be made
1413
+ from the 1st video in the group. In the above example if you passed:
1414
1415
- then the group will consist of bar.mpg 2.mpg, 3.mpg and 4.mpg, and only the
1416
- title and/or thumbnail for bar.mpg will appear in the menu. You can use
1417
- **-group** more than once for multiple groups. Be sure to quote video
1418
- filenames if they contain spaces.
1419
+ ::
1420
+
1421
+ -files foo.mpg bar.mpg baz.mpg -group 2 2.mpg 3.mpg 4.mpg
1422
+
1423
+ then the group will consist of bar.mpg 2.mpg, 3.mpg and 4.mpg, and
1424
+ only the title and/or thumbnail for bar.mpg will appear in the menu.
1425
+ You can use **-group** more than once for multiple groups. Be sure
1426
+ to quote video filenames if they contain spaces.
1427
1428
**-jobs**
1429
By default, **tovid disc** starts a parallel job for each processor
1430
- detected. With this option you can manually set the number of jobs. For
1431
- example if you have a computer with 2 CPUs you can set **-jobs 1** to keep
1432
- one processor free for other things. At present this applies to the time
1433
- consuming imagemagick loops: you will notice a substantial speedup now if
1434
- you have a multi-cpu system.
1435
+ detected. With this option you can manually set the number of jobs.
1436
+ For example if you have a computer with 2 CPUs you can set "-jobs 1"
1437
+ to keep one processor free for other things. At present this applies
1438
+ to the time consuming imagemagick loops: you will notice a
1439
+ substantial speedup now if you have a multi-cpu system.
1440
1441
-**-no-ask**, **-noask**
1442
- Skip all interactive questions. No preview, automatic re-encoding with
1443
- tovid if needed, no interactive option to use background video for bgaudio.
1444
+**-no-ask** | **-noask**
1445
+ Skip all interactive questions. No preview, automatic re-encoding
1446
+ with tovid if needed, no interactive option to use background video
1447
+ for bgaudio.
1448
1449
**-no-warn**, **-nowarn**
1450
- Don't pause after outputting warning or info messages
1451
+ Don’t pause after outputting warning or info messages
1452
1453
**-grid**
1454
- Show a second preview image with a grid and numbers that will help in finding
1455
- coordinates for options that might use them, like **-text-start**
1456
-
1457
+ Show a second preview image with a grid and numbers that will help
1458
+ in finding coordinates for options that might use them, like
1459
+ **-text-start**
1460
1461
Menu Style
1462
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1463
+----------
1464
1465
-**-menu-title-geo** north|south|east|west|center [south]
1466
- The position of the menu title. You may need to use **-align** as well if
1467
- you don't want your title covering other parts of your menu. See
1468
+**-menu-title-geo**
1469
+north|south|east|west|center|[south]
1470
+ The position of the menu title. You may need to use -align as well
1471
+ if you don’t want your title covering other parts of your menu. See
1472
**-align**
1473
1474
**-menu-title-offset** OFFSET (+X+Y)
1475
- Move menu title by this offset from its N|S|E|W|Center position. You
1476
- may need to use **-align** as well if you don't want your title covering other
1477
- parts of your menu. See **-align**
1478
+ Move menu title by this offset from its
1479
+ N|S|E|W|Center position. You
1480
+ may need to use -align as well if you don’t want your title covering
1481
+ other parts of your menu. See **-align**
1482
1483
**-button-style** rect|text|line|text-rect
1484
- The style of button that you will see when you play the DVD. "rect" draws
1485
- a rectangle around the thumb when you select it in the DVD player. "text"
1486
- highlights the video title text, "line" underlines the title, and
1487
- "text-rect" draws a rectangle around the title text.
1488
+ The style of button that you will see when you play the DVD. "rect"
1489
+ draws a rectangle around the thumb when you select it in the DVD
1490
+ player. "text" highlights the video title text, "line" underlines
1491
+ the title, and "text-rect" draws a rectangle around the title text.
1492
1493
**-title-color**, **-title-colour** COLOR
1494
- Color to use for the main menu title. For list of supported colors do:
1495
- **convert -list** color. HTML notation may be used: "#ff0000". See:
1496
- http://www.imagemagick.org/script/color.php
1497
+ Color to use for the main menu title. For list of supported colors
1498
+ do: **convert -list** color. HTML notation may be used: "#ff0000".
1499
+ See: {http://www.imagemagick.org/script/color.php}
1500
+ {http://www.imagemagick.org/script/color.php}
1501
1502
**-title-stroke** COLOR
1503
- Outline color for the main menu's title font. Use "none" for transparent
1504
- outline (see title-color)
1505
+ Shadow color for the main menu’s title font. Use "none" for
1506
+ transparent outline (see title-color). Note: this is not a -stroke
1507
+ in the sense that imagemagick uses the term, but a shadow (the font
1508
+ is drawn twice). To get a true imagemagick stroke see
1509
+ **-title-font-deco**
1510
+
1511
+**-title-font-deco**, **-title-fontdeco** "IMAGEMAGICK STRING"
1512
+ Sets the font decoration method to FONTDECORATION. It is used by the
1513
+ ’convert’ ImageMagick command to draw the menu text. You can add
1514
+ colored text outlines, gradient fills, and many others. See **Usage
1515
+ notes**
1516
1517
**-titles-stroke** COLOR
1518
- Outline color for the thumb or textmenu video titles font. Use "none" for
1519
- transparent outline (see **-titles-color**).
1520
+ Shadow color for the thumb or textmenu video titles font. Use "none"
1521
+ for transparent outline (see **-titles-color**). Note: this is not a
1522
+ -stroke in the sense that imagemagick uses the term, but a shadow
1523
+ (the font is drawn twice). To get a true imagemagick stroke, see
1524
+ **-titles-font-deco**
1525
+
1526
+**-titles-font-deco**, **-titles-fontdeco** "IMAGEMAGICK STRING"
1527
+ Sets the font decoration method to FONTDECORATION. It is used by the
1528
+ ’convert’ ImageMagick command to draw the menu text. You can add
1529
+ colored text outlines, gradient fills, and others. See **Usage
1530
+ notes** for more info.
1531
1532
**-highlight-color**, **-highlight-colour**
1533
- Color to use for the menu buttons that your DVD remote uses to navigate.
1534
+ Color to use for the menu buttons that your DVD remote uses to
1535
+ navigate.
1536
1537
**-select-color**, **-select-colour**
1538
- Color to use for the menu buttons that your DVD remote uses to select.
1539
+ Color to use for the menu buttons that your DVD remote uses to
1540
+ select.
1541
1542
**-text-mist**
1543
- Put a semi-transparent misted background behind the text for the menu's
1544
- title, just slightly larger than the text area.
1545
+ Put a semi-transparent misted background behind the text for the
1546
+ menu’s title, just slightly larger than the text area.
1547
1548
**-text-mist-color**, **-text-mist-colour** COLOR
1549
- Color of the mist behind the menu's title (see title-color).
1550
+ Color of the mist behind the menu’s title (see title-color).
1551
1552
**-text-mist-opacity**
1553
- Opacity of the mist behind the menu's title - see **-opacity**
1554
+ Opacity of the mist behind the menu’s title - see **-opacity**
1555
1556
**-title-opacity**
1557
Opacity of the menu title text
1558
1559
Opacity of the text for submenu chapter titles
1560
1561
**-menu-audio-fade**
1562
- Number of sec to fade given menu audio in and out (default: 1.0 seconds)
1563
- If you use **-menu-audio-fade** 0 then the audio will not be faded.
1564
+ Number of sec to fade given menu audio in and out (default: 1.0
1565
+ seconds) If you use **-menu-audio-fade** 0 then the audio will not
1566
+ be faded.
1567
1568
**-submenu-audio-fade**
1569
- Number of secs to fade sub-menu audio in and out (default: 1.0 seconds).
1570
- See **-menu-audio-fade**
1571
+ Number of secs to fade sub-menu audio in and out (default: 1.0
1572
+ seconds). See **-menu-audio-fade**
1573
1574
**-intro** VIDEO
1575
- Use a introductory video that will play before the main menu.
1576
- At present it must be a DVD compatible video at the correct resolution etc.
1577
- Only 4:3 aspect is supported: 16:9 will give unexpected results.
1578
+ Use a introductory video that will play before the main menu. At
1579
+ present it must be a DVD compatible video at the correct resolution
1580
+ etc. Only 4:3 aspect is supported: 16:9 will give unexpected
1581
+ results.
1582
1583
-
1584
-Showcase and textmenu
1585
--------------------------------------------------------------------------------
1586
-The following menu style options are specific to showcase and textmenu arrangements:
1587
+Style options specific to showcase/textmenu arrangements
1588
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1589
1590
**-text-start** N
1591
- This option is for **-textmenu** menus. The titles will start at the Nth
1592
- pixel from the top of the menu ( Y axis ).
1593
+ This option is for **-textmenu** menus. The titles will start at the
1594
+ Nth pixel from the top of the menu ( Y axis ).
1595
1596
**-title-gap** N
1597
- This option is for **-textmenu** menus. The gap is the space between
1598
+ This option is for **-textmenu** menus. The gap is the space between
1599
titles vertically ( Y axis ).
1600
1601
**-rotate** DEGREES
1602
Rotate the showcase image|video clockwise by DEGREES.
1603
- (default: if used without options, the rotate will be 5 degrees). Note:
1604
- this will not turn a portait image into a landscape image!
1605
+ (default: if used without options, the rotate will be 5 degrees).
1606
+ Note: this will not turn a portait image into a landscape image!
1607
1608
**-showcase-geo** GEOMETRY
1609
- The position of the showcase image. ( XxY position )
1610
+ The position of the showcase image. ( XxY position )
1611
1612
**-wave** default|GEOMETRY
1613
- Wave effect for showcase image|video. Alters thumbs along a sine wave
1614
- using GEOMETRY. (default: no wave) "default" will produce a wave arg of
1615
- **-20x556**, which produces a gentle wave with a small amount of
1616
- distortion. See: http://www.imagemagick.org/Usage/distorts/#wave if you
1617
- want to try other values.
1618
-
1619
-**-showcase-shape** egg|oval|plectrum|arch|spiral|galaxy|flat-tube|normal
1620
- Apply a shaped transparency mask to showcase videos or images.
1621
- Note: if you wish to make your own mask PNGS you can put them in
1622
+ Wave effect for showcase image|video. Alters thumbs along
1623
+ a sine wave using GEOMETRY. (default: no wave) "default" will
1624
+ produce a wave arg of -20x556, which produces a gentle wave with a
1625
+ small amount of distortion. See:
1626
+ {http://www.imagemagick.org/Usage/distorts/#wave}
1627
+ {http://www.imagemagick.org/Usage/distorts/#wave} if you want to try
1628
+ other values.
1629
+
1630
+**-showcase-shape** egg|oval|plectrum|arch|spiral|galaxy|flat-tube|normal
1631
+ Apply a shaped transparency mask to showcase videos or images. Note:
1632
+ if you wish to make your own mask PNGS you can put them in
1633
$PREFIX/lib/tovid/masks/ or $HOME/.tovid/masks/ and use them on the
1634
- command line using the filename minus the path and extension.
1635
- No frame is used for shaped thumbs.
1636
-
1637
-**-showcase-framestyle** none|glass
1638
- For **-showcase-** style template only
1639
- "none" will use the default frame method, using "convert -frame . . ."
1640
- "glass" will use mplayer to make frames, which gives an interesting
1641
- animated effect to the frames, and can be much faster ( especially if you
1642
- don't use **-rotate** or **-wave** as thumbs will not need to be processed
1643
- again after mplayer spits them out. Note: you need to be using either
1644
- **-showcase** IMAGE or **-showcase** VIDEO for this "frame style" to work.
1645
+ command line using the filename minus the path and extension. No
1646
+ frame is used for shaped thumbs.
1647
+
1648
+**-showcase-framestyle** none|glass
1649
+ For -showcase-\* style template only "none" will use the default
1650
+ frame method, using "convert -frame . . ." "glass" will use mplayer
1651
+ to make frames, which gives an interesting animated effect to the
1652
+ frames, and can be much faster ( especially if you don’t use
1653
+ **-rotate** or **-wave** as thumbs will not need to be processed
1654
+ again after mplayer spits them out. Note: you need to be using
1655
+ either **-showcase** IMAGE or **-showcase** VIDEO for this "frame
1656
+ style" to work.
1657
1658
**-showcase-frame-size** PIXELS
1659
- The size of the showcase frame. This value will be used for both width and
1660
- height for the 'thickness' of the frame. This will also set the thickness
1661
- of the raised "frame" of the showcase thumb when you use **-3d-showcase**.
1662
- See also **-thumb-frame-size** and **-showcase-frame-color**
1663
+ The size of the showcase frame. This value will be used for both
1664
+ width and height for the ’thickness’ of the frame. This will also
1665
+ set the thickness of the raised "frame" of the showcase thumb when
1666
+ you use **-3d-showcase**. See also **-thumb-frame-size** and
1667
+ **-showcase-frame-color**
1668
1669
**-showcase-frame-color**, **-showcase-frame-colour** PIXELS
1670
- The color of the showcase frame. Use hexadecimal or named colors notation.
1671
- Remember to quote! ( '#ffac5f' ).
1672
+ The color of the showcase frame. Use hexadecimal or named colors
1673
+ notation. Remember to quote! ( ’#ffac5f’ ).
1674
1675
**-3d-showcase**, **-3dshowcase**
1676
- This will give an illusion of 3D to the showcase thumb: dynamic lighting on
1677
- rounded thumbs, and a raised effect on rectangular thumbs. Try it !
1678
+ This will give an illusion of 3D to the showcase thumb: dynamic
1679
+ lighting on rounded thumbs, and a raised effect on rectangular
1680
+ thumbs. Try it !
1681
1682
+Thumbnail Style
1683
+---------------
1684
1685
-Thumbnail style
1686
--------------------------------------------------------------------------------
1687
+**-user-thumbs** IMAGE
1688
+ Supply your own images for menu buttons, rather than relying on
1689
+ todisc to generate them from the video. They must be the same aspect
1690
+ ratio as the videos in the titleset (4:3 or 16:9), as todisc will
1691
+ resize them without checking and cropping.
1692
1693
**-opacity** [0-100] (default 100)
1694
Opacity of thumbnail videos as a percentage (no percent sign).
1695
- Anything less than 100(%) is semi-transparent. Not recommended with dark
1696
- backgrounds.
1697
+ Anything less than 100(%) is semi-transparent. Not recommended with
1698
+ dark backgrounds.
1699
1700
**-thumb-blur**, **-blur** NUM
1701
- The amount of feather blur to apply to the thumb-shape. The default is 1.0
1702
- which will more or less keep the shape and produces transparency at the
1703
- edges. Choose float or integer values between 0.1 and 2.0. 3D thumbs are
1704
- set to a tiny blur, so this option doesn't affect the **-3dthumbs** option.
1705
+ The amount of feather blur to apply to the thumb-shape. The default
1706
+ is 1.0 which will more or less keep the shape and produces
1707
+ transparency at the edges. Choose float or integer values between
1708
+ 0.1 and 2.0. 3D thumbs are set to a tiny blur, so this option
1709
+ doesn’t affect the **-3dthumbs** option.
1710
1711
**-showcase-blur** NUM
1712
- The amount of 'feather' blur to apply to the showcase image/video. Choose
1713
- values between 0.1 and 2.0. This option has no effect on **-3d-showcase**.
1714
- See **-thumb-blur** for more info.
1715
+ The amount of ’feather’ blur to apply to the showcase image/video.
1716
+ Choose values between 0.1 and 2.0. This option has no effect on
1717
+ **-3d-showcase**. See **-thumb-blur** for more info.
1718
1719
**-align** north|south
1720
- This will align thumbs/titles north or south.
1721
- If **-align** south then menu title will align north, unless you manually
1722
- set one or both of **-menu-title-geo** or **-menu-title-offset**.
1723
+ This will align thumbs/titles north or south. If **-align** south
1724
+ then menu title will align north, unless you manually set one or
1725
+ both of **-menu-title-geo** or **-menu-title-offset**.
1726
1727
**-thumb-mist** [COLOR]
1728
- Use a mist behind thumbnails. The optional argument is the color of the
1729
- mist. This option helps with contrast. Be sure to set the font color
1730
- to an appropriate color if using a colored mist, and/or use a bold font.
1731
+ Use a mist behind thumbnails. The optional argument is the color of
1732
+ the mist. This option helps with contrast. Be sure to set the font
1733
+ color to an appropriate color if using a colored mist, and/or use a
1734
+ bold font.
1735
1736
**-titles-color**, **-titles-colour** COLOR
1737
- Color to use for the thumb or textmenu titles. If your titles are not
1738
- clear enough or look washed out, try using a **-titles-stroke** that
1739
- is the same color as used with **-titles-color** (see **-title-color**)
1740
+ Color to use for the thumb or textmenu titles. If your titles are
1741
+ not clear enough or look washed out, try using a **-titles-stroke**
1742
+ that is the same color as used with **-titles-color** (see
1743
+ **-title-color**)
1744
1745
**-showcase-titles-align** west|east (default: center [centre])
1746
- The default is to center the text above the thumbnails. This option will
1747
- align the titles either to the left (west) or right (east). Aligning west
1748
- gives more space to the titles. Aligning east also does so, and as well
1749
- will facilitate using \n in your titles to achieve multi line titles.
1750
+ The default is to center the text above the thumbnails. This option
1751
+ will align the titles either to the left (west) or right (east).
1752
+ Aligning west gives more space to the titles. Aligning east also
1753
+ does so, and as well will facilitate using \n in
1754
+ your titles to achieve multi line titles.
1755
1756
**-tile-3x1**, **-tile3x1**
1757
- Use a montage tile of 3x1 instead of the usual 2x2 for 3 videos
1758
- ie.::
1759
+ Use a montage tile of 3x1 instead of the usual 2x2 for 3 videos ie.
1760
1761
- [movie1] [movie2] [movie3] instead of:
1762
+ [movie1] [movie2] [movie3] instead of:
1763
1764
- [movie1] [movie2]
1765
+ [movie1] [movie2]
1766
1767
- [movie3]
1768
+ [movie3]
1769
1770
- This option only comes into play if the number of videos supplied equals 3
1771
- Otherwise it will be silently ignored. Not used for **-showcase-\*** style.
1772
+ This option only comes into play if the number of videos supplied
1773
+ equals 3 Otherwise it will be silently ignored. Not used for
1774
+ -showcase-\* style.
1775
1776
**-tile-4x1**, **-tile4x1**
1777
- Same as **-tile-3x1** above, except use tile of 4x1. (one row of 4 videos)
1778
+ Same as **-tile-3x1** above, except use tile of 4x1. (one row of 4
1779
+ videos)
1780
1781
-**-thumb-columns** 3|4
1782
- Same as **-tile-3x1** and **tile-4x1** above, except it accepts either '3'
1783
- (1 row of 3 thumbs), or '4' (one row of 4 thumbs) as an argument. This
1784
- alternative was added to help compact the gui layout.
1785
+\*\*-thumb-columns 3|4
1786
+ Same as **-tile-3x1** and tile-4x1\*\* above, except it accepts
1787
+ either ’3’ (1 row of 3 thumbs), or ’4’ (one row of 4 thumbs) as an
1788
+ argument. This alternative was added to help compact the gui layout.
1789
1790
**-rotate-thumbs** DEGREE LIST ( list of degrees, one for each thumb )
1791
- Rotate thumbs the given amount in degrees - can be positive or negative.
1792
- There must be one value for each file given with **-files**.
1793
- If the values are not the same distance from zero, the thumbs will be of
1794
- different sizes as images are necessarily resized *after* rotating. With
1795
- the default montage template - this will also resize the titles; with the
1796
- showcase template the titles will remain the same size. Example::
1797
+ Rotate thumbs the given amount in degrees - can be positive or
1798
+ negative. There must be one value for each file given with
1799
+ **-files**. If the values are not the same distance from zero, the
1800
+ thumbs will be of different sizes as images are necessarily resized
1801
+ \*after\* rotating. With the default montage template - this will
1802
+ also resize the titles; with the showcase template the titles will
1803
+ remain the same size. Example:
1804
1805
- -rotate-thumbs -10 10 -10 10 -10 (for 5 files)
1806
+ ::
1807
1808
- **Note**: this option will not turn a portrait image into a landscape image!
1809
+ -rotate-thumbs -10 10 -10 10 -10 (for 5 files)
1810
1811
+ \*\*Note: this option will not turn a portrait image into a
1812
+ landscape image!
1813
1814
Dvdauthor options
1815
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1816
+-----------------
1817
1818
**-loop** PAUSE
1819
- Pause in seconds at end of menu. Use "inf" if you wish indefinite pause.
1820
- Note: using "inf" with **-menu-fade** will disable the fadeout portion of
1821
- the fade. (default: "inf" for static menu, 10.0 seconds for animated.)
1822
+ Pause in seconds at end of menu. Use "inf" if you wish indefinite
1823
+ pause. Note: using "inf" with **-menu-fade** will disable the
1824
+ fadeout portion of the fade. (default: "inf" for static menu, 10.0
1825
+ seconds for animated.)
1826
1827
**-playall**
1828
- This option will create a button on the main menu that will allow going
1829
- right to the 1st title and playing all videos in succession before
1830
- returning to the main menu. If doing titlesets you can use this within
1831
- the **-vmgm** ... **-end-vmgm** options to allow playing ALL titlesets.
1832
- (If you want also to have a playall button in each titleset you could use
1833
- this option between each **-titleset** ... **-end-titleset** option or put
1834
- it outside of the vmgm and titlset options as a general option.
1835
+ This option will create a button on the main menu that will allow
1836
+ going right to the 1st title and playing all videos in succession
1837
+ before returning to the main menu. If doing titlesets you can use
1838
+ this within the **-vmgm** ... **-end-vmgm** options to allow playing
1839
+ ALL titlesets. (If you want also to have a playall button in each
1840
+ titleset you could use this option between each **-titleset** ...
1841
+ **-end-titleset** option or put it outside of the vmgm and titlset
1842
+ options as a general option.
1843
1844
**-videos-are-chapters**
1845
- A button will be made on the main menu for each video, which you can use as
1846
- a chapter button. Selecting any video will play them all in order
1847
- starting with the selected one.
1848
+ A button will be made on the main menu for each video, which you can
1849
+ use as a chapter button. Selecting any video will play them all in
1850
+ order starting with the selected one.
1851
1852
**-chain-videos** NUM | N1-NN
1853
Without options this will chain all videos together so they play
1854
- sequentially without returning to the main menu, except for the last, which
1855
- will return. You can also specify which videos you want to behave this way
1856
- by number or by a range. ( ie. **-chain-videos** 1 2 4-6 ).
1857
+ sequentially without returning to the main menu, except for the
1858
+ last, which will return. You can also specify which videos you want
1859
+ to behave this way by number or by a range. ( ie. **-chain-videos**
1860
+ 1 2 4-6 ).
1861
1862
**-subtitle-lang** "lang1 lang2 . . ."
1863
- This allows selectable subtitles in the DVD, assuming you have optional
1864
- subtitles muxed into your videos. Use 2 character language codes.
1865
-
1866
-**-audio-channel** "Video1_track Video2_track Video3_track . . ."
1867
- "VideoN_track" is the track number to use in a multi-track (multi-language)
1868
- mpeg: usually something like **-audio-channel** "1 0 1". The 1st track is
1869
- 0, 2nd is 1 . . . etc. If the tracks are 0. English 1.French, then the
1870
- above would make French the audio language on Video1 and Video3, and
1871
- English the audio language on Video2. You can check the mpeg with
1872
- "mplayer -v . . .".
1873
+ This allows selectable subtitles in the DVD, assuming you have
1874
+ optional subtitles muxed into your videos. Use 2 character language
1875
+ codes.
1876
+
1877
+**-audio-channel** "Video1\_track Video2\_track Video3\_track . . ."
1878
+ "VideoN\_track" is the track number to use in a multi-track
1879
+ (multi-language) mpeg: usually something like **-audio-channel** "1
1880
+ 0 1". The 1st track is 0, 2nd is 1 . . . etc. If the tracks are 0.
1881
+ English 1.French, then the above would make French the audio
1882
+ language on Video1 and Video3, and English the audio language on
1883
+ Video2. You can check the mpeg with "mplayer -v . . .".
1884
1885
**-audio-lang** LANGUAGE CODES
1886
- Identify the audio tracks on the DVD. These language codes are used for
1887
- each video in the titleset. When you use the audio button on your DVD
1888
- remote the language name is displayed. Example: **-audio-lang** en fr
1889
+ Identify the audio tracks on the DVD. These language codes are used
1890
+ for each video in the titleset. When you use the audio button on
1891
+ your DVD remote the language name is displayed. Example:
1892
+ **-audio-lang** en fr
1893
1894
**-aspect** 4:3|16:9
1895
- This will output a <video aspect WIDTH:HEIGHT /> tag for the dvdauthor
1896
- xml file. It will affect all videos in the titleset. Example::
1897
+ This will output a <video aspect WIDTH:HEIGHT />
1898
+ tag for the dvdauthor xml file. It will affect all videos in the
1899
+ titleset. Example:
1900
+
1901
+ ::
1902
1903
- -aspect 16:9
1904
+ -aspect 16:9
1905
1906
**-widescreen** nopanscan|noletterbox [nopanscan]
1907
- This will output a <video widescreen=nopanscan /> tag (for example)
1908
- for the dvdauthor xml file. It will affect all videos in the titleset. Use
1909
- in conjunction with **-aspect** if your dvd player is cropping your videos.
1910
- Example::
1911
+ This will output a <video widescreen=nopanscan
1912
+ /> tag (for example) for the dvdauthor xml file. It will
1913
+ affect all videos in the titleset. Use in conjunction with
1914
+ **-aspect** if your dvd player is cropping your videos. Example:
1915
+
1916
+ ::
1917
1918
- -aspect 16:9 -widescreen
1919
+ -aspect 16:9 -widescreen
1920
1921
**-quick-nav**
1922
- This option will allow navigation of a menu with more than one titleset by
1923
- using the left and right arrow keys of your DVD remote. When you press
1924
- this key the highlight will go the next or previous title. If you are at
1925
- the end of a titleset the right key will go to the next titleset. If you
1926
- are at the beginning of a titleset, the left key will go to the previous
1927
- titleset. If no next or previous titleset it will cycle to the end or
1928
- beginning of the titlesets.
1929
+ This option will allow navigation of a menu with more than one
1930
+ titleset by using the left and right arrow keys of your DVD remote.
1931
+ When you press this key the highlight will go the next or previous
1932
+ title. If you are at the end of a titleset the right key will go to
1933
+ the next titleset. If you are at the beginning of a titleset, the
1934
+ left key will go to the previous titleset. If no next or previous
1935
+ titleset it will cycle to the end or beginning of the titlesets.
1936
1937
**-outlinewidth**, **-outline-width** WIDTH
1938
- For spumux outlinewidth variable. If there is a large gap between words in
1939
- a text button, this option may help.
1940
+ For spumux outlinewidth variable. If there is a large gap between
1941
+ words in a text button, this option may help.
1942
1943
**-video-pause** PAUSE (single value or list)
1944
- The pause in seconds after playing a video title. This is useful for
1945
- slideshows: the 'slide' will remain on the screen for this length of time.
1946
- If you have grouped videos you should probably not pause the videos that
1947
- have a grouped title after it, but instead see **-grouped-video-pause**.
1948
- Note: if you provide a list of values they must be one for each video.
1949
+ The pause in seconds after playing a video title. This is useful for
1950
+ slideshows: the ’slide’ will remain on the screen for this length of
1951
+ time. If you have grouped videos you should probably not pause the
1952
+ videos that have a grouped title after it, but instead see
1953
+ **-grouped-video-pause**. Note: if you provide a list of values they
1954
+ must be one for each video.
1955
1956
**-group-video-pause** PAUSE (single value or list)
1957
- The pause in seconds after a grouped video plays. If you wish to pause
1958
- after the whole group finishes, then only use a value greater than zero
1959
- for the last video in the group. If providing a list of values they must
1960
- equal the number of grouped videos.
1961
+ The pause in seconds after a grouped video plays. If you wish to
1962
+ pause after the whole group finishes, then only use a value greater
1963
+ than zero for the last video in the group. If providing a list of
1964
+ values they must equal the number of grouped videos.
1965
1966
-
1967
-Burning the disc
1968
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1969
-
1970
-**-burn**
1971
- Prompt to burn the DVD directory on completion.
1972
-
1973
-**-device** DEVICE [/dev/dvdrw]
1974
- Device to use for the burning program.
1975
-
1976
-**-speed** N
1977
- The speed to use for burning the disc.
1978
-
1979
-
1980
-
1981
-.. _command-mpg:
1982
+Usage notes
1983
+-----------
1984
+
1985
+The argument given to various \*-font options that set the font to use
1986
+must be one of the fonts listed by the command ’convert -list type’.
1987
+Please note that many of your installed fonts may not be available; if
1988
+you want to maximize the number of fonts available to todisc, download
1989
+and run {Anthony Thyssen’s}
1990
+{http://www.cit.gu.edu.au/~{}anthony/anthony.html} {imagick\_type\_gen}
1991
+{http://www.imagemagick.org/Usage/scripts/imagick\_type\_gen} script and
1992
+run it like this: imagick\_type\_gen > ~{}/.magick/type.xml.
1993
+If that doesn’t work, try imagick\_type\_gen > ~{}/.magick/type.mgk.
1994
+
1995
+Or you can specify a ttf font file directly to the \*-font options if
1996
+you don’t want to install fonts to ImageMagick.
1997
+
1998
+The \*-stroke options in todisc are not a stroke in the sense that
1999
+ImageMagick uses the term, but rather a font shadow (the text is drawn
2000
+twice) To get a truer Imagemagick -stroke try something like:
2001
+-title-font-deco "-stroke black" (or -titles-font-deco "-stroke black").
2002
+The **-fontdeco** option is quite flexible and takes a lot of
2003
+ImageMagick’s *convert* options. Please refer to the tovid {wiki}
2004
+{http://tovid.wikia.com/wiki/Making\_a\_DVD\_with\_text\_menus} and
2005
+Anthony Thyssen’s guide for further explanation and examples.
2006
2007
Command:mpg
2008
-===============================================================================
2009
+-----------
2010
2011
**tovid mpg** converts arbitrary video files into (S)VCD/DVD-compliant
2012
MPEG format, suitable for burning to CD/DVD-R for playback on a
2013
standalone DVD player.
2014
2015
Usage
2016
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2017
-
2018
-::
2019
+-----
2020
2021
- tovid mpg [OPTIONS] -in INFILE -out OUTPREFIX
2022
+**tovid mpg** [*OPTIONS*] **-in** *INFILE* **-out** *OUTPREFIX*
2023
2024
-Where *INFILE* is any multimedia video file, and *OUTPREFIX* is what
2025
-you want to call the output file, minus the file extension. *OPTIONS*
2026
-are additional customizations, described below.
2027
+Where *INFILE* is any multimedia video file, and *OUTPREFIX* is what you
2028
+want to call the output file, minus the file extension. *OPTIONS* are
2029
+additional customizations, described below.
2030
2031
By default, you will (hopefully) end up with an NTSC DVD-compliant
2032
MPEG-2 video file; if you burn this file to a DVD-R, it should be
2033
2034
2035
For example:
2036
2037
-``tovid mpg -in foo.avi -out foo_encoded``
2038
- Convert 'foo.avi' to NTSC DVD format, saving to 'foo_encoded.mpg'.
2039
+{tovid mpg -in foo.avi -out foo\_encoded}
2040
+ Convert ’foo.avi’ to NTSC DVD format, saving to ’foo\_encoded.mpg’.
2041
2042
-``tovid mpg -pal -vcd foo.avi -out foo_encoded``
2043
- Convert 'foo.avi' to PAL VCD format, saving to 'foo_encoded.mpg'.
2044
+{tovid mpg -pal -vcd foo.avi -out foo\_encoded}
2045
+ Convert ’foo.avi’ to PAL VCD format, saving to ’foo\_encoded.mpg’.
2046
2047
Basic options
2048
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2049
+-------------
2050
2051
**-v**, **-version**
2052
Print tovid version number only, then exit.
2053
2054
Reduce output to the console.
2055
2056
**-fake**
2057
- Do not actually encode; only print the commands (mplayer, mpeg2enc etc.)
2058
- that would be executed. Useful in debugging; have tovid give you the
2059
- commands, and run them manually.
2060
+ Do not actually encode; only print the commands (mplayer, mpeg2enc
2061
+ etc.) that would be executed. Useful in debugging; have tovid give
2062
+ you the commands, and run them manually.
2063
2064
**-ffmpeg**
2065
- Use ffmpeg for video encoding, instead of mplayer/mpeg2enc. Try this if
2066
- you have any problems with the default encoding method. Using this option,
2067
- encoding will be considerably faster. Currently does not work with
2068
- **-subtitles** or **-filters**.
2069
+ Use ffmpeg for video encoding, instead of mplayer/mpeg2enc. Try this
2070
+ if you have any problems with the default encoding method. Using
2071
+ this option, encoding will be considerably faster. Currently does
2072
+ not work with **-subtitles** or **-filters**.
2073
2074
Television standards
2075
--------------------------------------------------------------------------------
2076
+~~~~~~~~~~~~~~~~~~~~
2077
2078
**-ntsc**
2079
NTSC format video (USA, Americas) (default)
2080
2081
PAL format video (Europe and others)
2082
2083
Formats
2084
--------------------------------------------------------------------------------
2085
+~~~~~~~
2086
2087
Standard formats, should be playable in most DVD players:
2088
2089
2090
**-bdvd**
2091
(720x480 NTSC, 720x576 PAL) BVCD-enhanced long-playing DVD
2092
2093
-See kvcd.net (http://kvcd.net/) for details on the KVCD specification. Please
2094
-note that KVCD ("K Video Compression Dynamics") is the name of a compression
2095
-scheme that can be applied to any MPEG-1 or MPEG-2 video, and has little to
2096
-do with VCD ("Video Compact Disc"), which is the name of a standard video disc
2097
-format.
2098
+See {kvcd.net} {http://kvcd.net/} for details on the KVCD specification.
2099
+Please note that KVCD ("K Video Compression Dynamics") is the name of a
2100
+compression scheme that can be applied to any MPEG-1 or MPEG-2 video,
2101
+and has little to do with VCD ("Video Compact Disc"), which is the name
2102
+of a standard video disc format.
2103
2104
Advanced options
2105
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2106
+----------------
2107
2108
Aspect ratios
2109
--------------------------------------------------------------------------------
2110
+~~~~~~~~~~~~~
2111
2112
-tovid automatically determines aspect ratio of the input video by playing it in
2113
-mplayer. If your video plays with correct aspect in mplayer, you should not
2114
-need to override the default tovid behavior.
2115
+tovid automatically determines aspect ratio of the input video by
2116
+playing it in mplayer. If your video plays with correct aspect in
2117
+mplayer, you should not need to override the default tovid behavior.
2118
2119
-If mplayer does not play your video with correct aspect, you may provide an
2120
-explicit aspect ratio in one of several ways:
2121
-
2122
-**-aspect** *WIDTH*:*HEIGHT*
2123
- Custom aspect, where *WIDTH* and *HEIGHT* are integers.
2124
+If mplayer does not play your video with correct aspect, you may provide
2125
+an explicit aspect ratio in one of several ways:
2126
2127
**-full**
2128
Same as **-aspect 4:3**
2129
2130
**-panavision**
2131
Same as **-aspect 235:100**
2132
2133
-The above are the intended INPUT aspect ratio. tovid chooses an optimal output
2134
-aspect ratio for the selected disc format (VCD, DVD, etc.) and does the
2135
-appropriate letterboxing or anamorphic scaling. Use **-widetv** to encode
2136
-for a widescreen monitor or TV.
2137
+**-aspect** *WIDTH***:***HEIGHT*
2138
+ Custom aspect, where *WIDTH* and *HEIGHT* are integers.
2139
+The above are the intended INPUT aspect ratio. tovid chooses an optimal
2140
+output aspect ratio for the selected disc format (VCD, DVD, etc.) and
2141
+does the appropriate letterboxing or anamorphic scaling. Use **-widetv**
2142
+to encode for a widescreen monitor or TV.
2143
2144
Video stream options
2145
--------------------------------------------------------------------------------
2146
+~~~~~~~~~~~~~~~~~~~~
2147
2148
**-quality** *NUM* (default 6)
2149
- Desired output quality, on a scale of 1 to 10, with 10 giving the best
2150
- quality at the expense of a larger output file. Default is 6. Output size
2151
- can vary by approximately a factor of 4 (that is, **-quality 1** output
2152
- can be 1/4 the size of **-quality 10** output). Your results may vary.
2153
- WARNING: With **-quality 10**, the output bitrate may be too high for
2154
- your hardware DVD player to handle. Stick with 9 or lower unless you
2155
- have phenomenally good eyesight.
2156
-
2157
- At present, this option affects both output bitrate and quantization (but
2158
- may, in the future, affect other quality/size-related attributes). Use
2159
- **-vbitrate** if you want to explicitly provide a maximum bitrate.
2160
+ Desired output quality, on a scale of 1 to 10, with 10 giving the
2161
+ best quality at the expense of a larger output file. Default is 6.
2162
+ Output size can vary by approximately a factor of 4 (that is,
2163
+ **-quality 1** output can be 1/4 the size of **-quality 10**
2164
+ output). Your results may vary. WARNING: With **-quality 10**, the
2165
+ output bitrate may be too high for your hardware DVD player to
2166
+ handle. Stick with 9 or lower unless you have phenomenally good
2167
+ eyesight.
2168
+
2169
+ At present, this option affects both output bitrate and quantization
2170
+ (but may, in the future, affect other quality/size-related
2171
+ attributes). Use **-vbitrate** if you want to explicitly provide a
2172
+ maximum bitrate.
2173
2174
**-vbitrate** *NUM*
2175
- Maximum bitrate to use for video (in kbits/sec). Must be within allowable
2176
- limits for the given format. Overrides default values. Ignored for VCD,
2177
- which must be constant bitrate.
2178
+ Maximum bitrate to use for video (in kbits/sec). Must be within
2179
+ allowable limits for the given format. Overrides default values.
2180
+ Ignored for VCD, which must be constant bitrate.
2181
2182
**-interlaced**
2183
- Do interlaced encoding of the input video (top fields first). Use this
2184
- option if your video is interlaced, and you want to preserve as much
2185
- picture quality as possible. This option is ignored for VCD, which
2186
- doesn't support it.
2187
+ Do interlaced encoding of the input video (top fields first). Use
2188
+ this option if your video is interlaced, and you want to preserve as
2189
+ much picture quality as possible. This option is ignored for VCD,
2190
+ which doesn’t support it.
2191
2192
- You can tell your source video is interlaced by playing it, and pausing
2193
- during a scene with horizontal motion; if you see a "comb" effect at the
2194
- edges of objects in the scene, you have interlaced video. Use this option
2195
- to encode it properly.
2196
+ You can tell your source video is interlaced by playing it, and
2197
+ pausing during a scene with horizontal motion; if you see a "comb"
2198
+ effect at the edges of objects in the scene, you have interlaced
2199
+ video. Use this option to encode it properly.
2200
2201
If you would prefer to have output in progressive format, use
2202
- **-progressive**. If you have a DV camera, use **-interlaced_bf** since
2203
- DV footage is generally bottom fields first.
2204
+ **-progressive**. If you have a DV camera, use **-interlaced\_bf**
2205
+ since DV footage is generally bottom fields first.
2206
2207
-**-interlaced_bf**
2208
+**-interlaced\_bf**
2209
Do interlaced encoding of the input video (bottom fields first).
2210
2211
-**-deinterlace** | **-progressive**
2212
- Convert interlaced source video into progressive output video. Because
2213
- deinterlacing works by averaging fields together, some picture quality is
2214
- invariably lost. Uses an adaptive kernel deinterlacer (kerndeint), or,
2215
- if that's not available, the libavcodec deinterlacer (lavcdeint).
2216
+**-deinterlace**, **-progressive**
2217
+ Convert interlaced source video into progressive output video.
2218
+ Because deinterlacing works by averaging fields together, some
2219
+ picture quality is invariably lost. Uses an adaptive kernel
2220
+ deinterlacer (kerndeint), or, if that’s not available, the
2221
+ libavcodec deinterlacer (lavcdeint).
2222
2223
**-mkvsub** *LANG* (EXPERIMENTAL)
2224
- Attempt to encode an integrated subtitle stream (such as may be found in
2225
- Matroska .mkv files) in the given language code (eng, jpn, etc.) May work
2226
- for other formats.
2227
+ Attempt to encode an integrated subtitle stream (such as may be
2228
+ found in Matroska .mkv files) in the given language code (eng, jpn,
2229
+ etc.) May work for other formats.
2230
2231
**-autosubs**
2232
- Automatically include subtitle files with the same name as the input video.
2233
+ Automatically include subtitle files with the same name as the input
2234
+ video.
2235
2236
**-subtitles** *FILE*
2237
- Get subtitles from *FILE* and encode them into the video. WARNING: This
2238
- hard-codes the subtitles into the video, and you cannot turn them off while
2239
- viewing the video. By default, no subtitles are loaded. If your video is
2240
- already compliant with the chosen output format, it will be re-encoded to
2241
- include the subtitles.
2242
+ Get subtitles from *FILE* and encode them into the video. WARNING:
2243
+ This hard-codes the subtitles into the video, and you cannot turn
2244
+ them off while viewing the video. By default, no subtitles are
2245
+ loaded. If your video is already compliant with the chosen output
2246
+ format, it will be re-encoded to include the subtitles.
2247
2248
**-type** {live|animation|bw}
2249
- Optimize video encoding for different kinds of video. Use 'live' (default)
2250
- for live-action video, use 'animation' for cartoons or anime, and 'bw' for
2251
- black-and-white video. This option currently only has an effect with
2252
- KVCD/KSVCD output formats; other formats may support this in the future.
2253
+ Optimize video encoding for different kinds of video. Use ’live’
2254
+ (default) for live-action video, use ’animation’ for cartoons or
2255
+ anime, and ’bw’ for black-and-white video. This option currently
2256
+ only has an effect with KVCD/KSVCD output formats; other formats may
2257
+ support this in the future.
2258
2259
**-safe** *PERCENT*
2260
Fit the video within a safe area defined by *PERCENT*. For example,
2261
- **-safe 90%** will scale the video to 90% of the width/height of the output
2262
- resolution, and pad the edges with a black border. Use this if some of the
2263
- picture is cut off when played on your TV. The percent sign is optional.
2264
+ **-safe 90%** will scale the video to 90% of the width/height of the
2265
+ output resolution, and pad the edges with a black border. Use this
2266
+ if some of the picture is cut off when played on your TV. The
2267
+ percent sign is optional.
2268
2269
**-filters** {none,denoise,deblock,contrast,all} (default none)
2270
- Apply post-processing filters to enhance the video. If your input video is
2271
- very high quality, use 'none'. If your input video is grainy, use 'denoise';
2272
- if it looks washed out or faded, use 'contrast'. You can use multiple
2273
- filters separated by commas. To apply all filters, use 'all'.
2274
+ Apply post-processing filters to enhance the video. If your input
2275
+ video is very high quality, use ’none’. If your input video is
2276
+ grainy, use ’denoise’; if it looks washed out or faded, use
2277
+ ’contrast’. You can use multiple filters separated by commas. To
2278
+ apply all filters, use ’all’.
2279
2280
**-fps** *RATIO*
2281
- Force input video to be interpreted as *RATIO* frames per second. May be
2282
- necessary for some ASF, MOV, or other videos. *RATIO* should be an
2283
- integer ratio such as "24000:1001" (23.976fps), "30000:1001" (29.97fps), or
2284
- "25:1" (25fps). This option is temporary, and may disappear in future
2285
- releases. (Hint: To convert a decimal like 23.976 to an integer ratio, just
2286
- multiply by 1000, i.e. 23976:1000)
2287
+ Force input video to be interpreted as *RATIO* frames per second.
2288
+ May be necessary for some ASF, MOV, or other videos. *RATIO* should
2289
+ be an integer ratio such as "24000:1001" (23.976fps), "30000:1001"
2290
+ (29.97fps), or "25:1" (25fps). This option is temporary, and may
2291
+ disappear in future releases. (Hint: To convert a decimal like
2292
+ 23.976 to an integer ratio, just multiply by 1000, i.e. 23976:1000)
2293
2294
**-crop** *WIDTH*:*HEIGHT*:*X*:*Y*
2295
Crop a portion of the video *WIDTH* by *HEIGHT* in size, with the
2296
top-left corner at *X*, *Y*.
2297
2298
**-widetv**
2299
- Always encode to 16:9 widescreen (only supported by **-dvd**, **-kdvd**,
2300
- **-bdvd**), for optimal viewing on a widescreen monitor or TV.
2301
+ Always encode to 16:9 widescreen (only supported by **-dvd**,
2302
+ **-kdvd**, **-bdvd**), for optimal viewing on a widescreen monitor
2303
+ or TV.
2304
2305
Audio stream options
2306
--------------------------------------------------------------------------------
2307
+~~~~~~~~~~~~~~~~~~~~
2308
2309
**-normalize**
2310
Analyze the audio stream and then normalize the volume of the audio.
2311
2312
normalize without any parameters. The default is -12dB average level
2313
with 0dB gain.
2314
2315
-**-amplitude** *NUM[dB]*
2316
- In addition to analyzing and normalizing, apply the gain to the audio
2317
- such that the 'average' (RMS) sound level is *NUM*. Valid values
2318
- range 0.0 - 1.0, with 0.0 being silent and 1.0 being full scale. Use
2319
- *NUMdB* for a decibel gain below full scale (the default without
2320
- **-amplitude** is -12dB).
2321
+**-amplitude** *NUM*[dB]
2322
+ In addition to analyzing and normalizing, apply the gain to the
2323
+ audio such that the ’average’ (RMS) sound level is *NUM*. Valid
2324
+ values range 0.0 - 1.0, with 0.0 being silent and 1.0 being full
2325
+ scale. Use *NUM*dB for a decibel gain below full scale (the default
2326
+ without -amplitude is -12dB).
2327
2328
**-abitrate** *NUM*
2329
- Encode audio at *NUM* kilobits per second. Reasonable values include
2330
- 128, 224, and 384. The default is 224 kbits/sec, good enough for most
2331
- encodings. The value must be within the allowable range for the chosen disc
2332
- format; Ignored for VCD, which must be 224.
2333
+ Encode audio at *NUM* kilobits per second. Reasonable values include
2334
+ 128, 224, and 384. The default is 224 kbits/sec, good enough for
2335
+ most encodings. The value must be within the allowable range for the
2336
+ chosen disc format; Ignored for VCD, which must be 224.
2337
2338
**-audiotrack** *NUM*
2339
- Encode the given audio track, if the input video has multiple audio tracks.
2340
- *NUM* is *1* for the first track, *2* for the second, etc. You may
2341
- also provide a list of tracks, separated by spaces or commas, for example
2342
- **-audiotrack 3,1,2**. Use **tovid id** on your source video to determine
2343
- which audio tracks it contains.
2344
+ Encode the given audio track, if the input video has multiple audio
2345
+ tracks. *NUM* is *1* for the first track, *2* for the second, etc.
2346
+ You may also provide a list of tracks, separated by spaces or
2347
+ commas, for example **-audiotrack 3,1,2**. Use **tovid id** on your
2348
+ source video to determine which audio tracks it contains.
2349
2350
**-downmix**
2351
- Encode all audio tracks as stereo. This can save space on your DVD if
2352
- your player only does stereo. The default behavior of tovid is to use
2353
- the original number of channels in each track. For aac audio, downmixing
2354
- is not possible: tovid runs a quick 1 frame test to try to downmix the
2355
- input track with the largest number of channels, and if it fails then it
2356
- will revert to the default behavior of using the original channels.
2357
-
2358
-**-async** *NUM*
2359
- Adjust audio synchronization by *NUM* seconds.
2360
+ Encode all audio tracks as stereo. This can save space on your DVD
2361
+ if your player only does stereo. The default behavior of tovid is to
2362
+ use the original number of channels in each track. For aac audio,
2363
+ downmixing is not possible: tovid runs a quick 1 frame test to try
2364
+ to downmix the input track with the largest number of channels, and
2365
+ if it fails then it will revert to the default behavior of using the
2366
+ original channels.
2367
2368
Other options
2369
--------------------------------------------------------------------------------
2370
+~~~~~~~~~~~~~
2371
2372
**-config** *FILE*
2373
- Read configuration from *FILE*, containing 'tovid' alone on the first
2374
- line, and free-formatted (whitespace-separated) tovid command-line options
2375
- on remaining lines.
2376
+ Read configuration from *FILE*, containing ’tovid’ alone on the
2377
+ first line, and free-formatted (whitespace-separated) tovid
2378
+ command-line options on remaining lines.
2379
2380
**-force**
2381
Force encoding of already-compliant video or audio streams.
2382
2383
**-out** option).
2384
2385
**-priority** {low|medium|high}
2386
- Sets the main encoding process to the given priority. With high priority,
2387
- it may take other programs longer to load and respond. With lower priority,
2388
- other programs will be more responsive, but encoding may take 30-40%
2389
- longer. The default is high priority.
2390
+ Sets the main encoding process to the given priority. With high
2391
+ priority, it may take other programs longer to load and respond.
2392
+ With lower priority, other programs will be more responsive, but
2393
+ encoding may take 30-40% longer. The default is high priority.
2394
2395
**-discsize** *NUM*
2396
- When encoding, tovid automatically splits the output file into several
2397
- pieces if it exceeds the size of the target media. This option sets the
2398
- desired target DVD/CD-R size to *NUM* mebibytes (MiB, 2^20). By default,
2399
- splitting occurs at 700 for CD, 4300 for DVD. Use higher values at your
2400
- own risk. Use 650 or lower if you plan to burn to smaller-capacity CDs.
2401
- Doesn't work with the **-ffmpeg** option.
2402
+ When encoding, tovid automatically splits the output file into
2403
+ several pieces if it exceeds the size of the target media. This
2404
+ option sets the desired target DVD/CD-R size to *NUM* mebibytes
2405
+ (MiB, 2^20). By default, splitting occurs at 700 for CD, 4300 for
2406
+ DVD. Use higher values at your own risk. Use 650 or lower if you
2407
+ plan to burn to smaller-capacity CDs. Doesn’t work with the
2408
+ **-ffmpeg** option.
2409
2410
**-fit** *NUM*
2411
Fit the output file into *NUM* MiB. Rather than using default (or
2412
- specified) video bitrates, tovid will calculate the correct video bitrate
2413
- that will limit the final output size to *NUM* MiB. This is different
2414
- than **-discsize**, which cuts the final file into *NUM* MiB pieces.
2415
- **-fit** makes sure that the file never exceeds *NUM* MiB. This works
2416
- with **-ffmpeg**, but not with **-vcd** since VCDs have a standardized
2417
- constant bitrate.
2418
+ specified) video bitrates, tovid will calculate the correct video
2419
+ bitrate that will limit the final output size to *NUM* MiB. This is
2420
+ different than **-discsize**, which cuts the final file into *NUM*
2421
+ MiB pieces. **-fit** makes sure that the file never exceeds *NUM*
2422
+ MiB. This works with **-ffmpeg**, but not with **-vcd** since VCDs
2423
+ have a standardized constant bitrate.
2424
2425
**-parallel**
2426
- Perform ripping, encoding, and multiplexing processes in parallel using
2427
- named pipes. Maximizes CPU utilization and minimizes disk usage. Note that
2428
- this option simply does more tasks simultaneously, in order to make better
2429
- use of available CPU cycles; it's unrelated to multi-CPU processing (which
2430
- is done automatically anyway). Has no effect when **-ffmpeg** is used.
2431
+ Perform ripping, encoding, and multiplexing processes in parallel
2432
+ using named pipes. Maximizes CPU utilization and minimizes disk
2433
+ usage. Note that this option simply does more tasks simultaneously,
2434
+ in order to make better use of available CPU cycles; it’s unrelated
2435
+ to multi-CPU processing (which is done automatically anyway). Has no
2436
+ effect when **-ffmpeg** is used.
2437
2438
**-update** *SECS*
2439
- Print status updates at intervals of *SECS* seconds. This affects how
2440
- regularly the progress-meter is updated. The default is once every five
2441
- seconds.
2442
+ Print status updates at intervals of *SECS* seconds. This affects
2443
+ how regularly the progress-meter is updated. The default is once
2444
+ every five seconds.
2445
2446
-**-mplayeropts** "**OPTIONS**"
2447
- Append *OPTIONS* to the mplayer command run during video encoding. Use
2448
- this if you want to add specific video filters (documented in the mplayer
2449
- manual page). Overriding some options will cause encoding to fail, so use
2450
- this with caution!
2451
+**-mplayeropts** **"***OPTIONS***"**
2452
+ Append *OPTIONS* to the mplayer command run during video encoding.
2453
+ Use this if you want to add specific video filters (documented in
2454
+ the mplayer manual page). Overriding some options will cause
2455
+ encoding to fail, so use this with caution!
2456
2457
**-nofifo** (EXPERIMENTAL)
2458
- Do not use a FIFO pipe for video encoding. If you are getting "Broken pipe"
2459
- errors with normal encoding, try this option. WARNING: This uses lots of
2460
- disk space (about 2 GB per minute of video).
2461
+ Do not use a FIFO pipe for video encoding. If you are getting
2462
+ "Broken pipe" errors with normal encoding, try this option. WARNING:
2463
+ This uses lots of disk space (about 2 GB per minute of video).
2464
2465
**-keepfiles**
2466
- Keep the intermediate files after encoding. Usually, this means the audio
2467
- and video streams are kept (eg the .ac3 and .m2v files for an NTSC DVD).
2468
- This doesn't work with **-parallel** because the intermediate files are named
2469
- pipes, and not real files.
2470
+ Keep the intermediate files after encoding. Usually, this means the
2471
+ audio and video streams are kept (eg the .ac3 and .m2v files for an
2472
+ NTSC DVD). This doesn’t work with -parallel because the intermediate
2473
+ files are named pipes, and not real files.
2474
2475
**-slice** *START*-*END*
2476
Encode a segment from *START* to *END* (in seconds). Only works with
2477
- **-ffmpeg**.
2478
+ -ffmpeg.
2479
2480
**-from-gui**
2481
- Put makempg into a fully non-interactive state, suitable for calling from
2482
- a gui.
2483
+ Put makempg into a fully non-interactive state, suitable for calling
2484
+ from a gui.
2485
2486
**-noask**
2487
- Don't ask questions when choices need to be made. Assume reasonable
2488
+ Don’t ask questions when choices need to be made. Assume reasonable
2489
answers.
2490
2491
-
2492
-.. _command-id:
2493
-
2494
Command:id
2495
-===============================================================================
2496
+==========
2497
2498
-**tovid id** identifies each multimedia video file in a
2499
-list, and reports its compliance with video disc standards such as VCD,
2500
-SVCD, and DVD.
2501
+**tovid id** identifies each multimedia video file in a list, and
2502
+reports its compliance with video disc standards such as VCD, SVCD, and
2503
+DVD.
2504
2505
Usage
2506
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2507
-
2508
-::
2509
+-----
2510
2511
- tovid id [OPTIONS] VIDEO_FILE(s)
2512
+**tovid id** [*OPTIONS*] *VIDEO\_FILE(s)*
2513
2514
For example:
2515
2516
2517
``tovid id -tabluar videos/*.mpg``
2518
2519
Options
2520
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2521
+-------
2522
2523
**-terse**
2524
- Print raw video characteristics, no formatting. Helpful when
2525
- calling from other scripts.
2526
+ Print raw video characteristics, no formatting. Helpful when calling
2527
+ from other scripts.
2528
2529
**-verbose**
2530
Print extra information from mplayer, tcprobe, and ffmpeg.
2531
2532
**-accurate**
2533
- Do lengthy play-time estimation by scanning through the entire video file.
2534
- Use this if the default behavior is giving you inaccurate play times.
2535
+ Do lengthy play-time estimation by scanning through the entire video
2536
+ file. Use this if the default behavior is giving you inaccurate play
2537
+ times.
2538
2539
**-fast**
2540
Skip lengthy play-time estimation, and go with what mplayer reports
2541
as being the video duration. Unlike pre-0.32 versions of tovid, this
2542
- is now the default behavior, and the **-fast** option doesn't do anything.
2543
+ is now the default behavior, and the **-fast** option doesn’t do
2544
+ anything.
2545
2546
**-tabular**
2547
Display output in a table format for easier comparison. Most useful
2548
when identifying multiple video files.
2549
2550
-**-isformat** [pal-dvd|ntsc-dvd] (same syntax for vcd and svcd)
2551
- Check *VIDEO_FILE* for compliance with the given disc format.
2552
- If *VIDEO_FILE* matches the given format, then **tovid id** reports "true"
2553
- and exits successfully. Otherwise, **tovid id** reports "false" and exits
2554
- with status 1 (failure). This checks and reports both vcd/svcd/dvd
2555
- and pal/ntsc.
2556
+**-isformat** [*pal-dvd*|*ntsc-dvd*] (same syntax for vcd and svcd)
2557
+ Check *VIDEO\_FILE* for compliance with the given disc format. If
2558
+ *VIDEO\_FILE* matches the given format, then **tovid id** reports
2559
+ "true" and exits successfully. Otherwise, **tovid id** reports
2560
+ "false" and exits with status 1 (failure). This checks and reports
2561
+ both vcd/svcd/dvd and pal/ntsc.
2562
2563
Examples
2564
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2565
+--------
2566
2567
``tovid id -verbose homevideo.avi``
2568
Report everything mplayer, ffmpeg, and transcode can determine about
2569
2570
``tovid id -isformat dvd homevideo.mpg``
2571
Check to see if homevideo.mpg is compliant with the DVD standard.
2572
2573
-
2574
-.. _command-menu:
2575
-
2576
-Command:menu
2577
-===============================================================================
2578
-
2579
-**tovid menu** generates textual (S)VCD- or DVD-compliant MPEG videos for use
2580
-as navigational menus, given a list of text strings to use for title names. You
2581
-can customize the menu by providing an optional background image or audio clip,
2582
-or by using custom font and font color.
2583
-
2584
-Usage
2585
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2586
-
2587
-::
2588
-
2589
- tovid menu [OPTIONS] TITLES -out OUT_PREFIX
2590
-
2591
-For example:
2592
-
2593
-``tovid menu "Season One" "Season Two" "Featurettes" -out MainMenu``
2594
-
2595
-Options
2596
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2597
-
2598
-**-ntsc** (default)
2599
- Generate an NTSC-format menu
2600
-
2601
-**-ntscfilm**
2602
- Generate an NTSC-format menu (24000/1001fps)
2603
-
2604
-**-pal**
2605
- Generate a PAL-format menu
2606
-
2607
-**-dvd** (default)
2608
- Generate a DVD-format menu, with highlighted text included
2609
- as a multiplexed subtitle stream.
2610
-
2611
-**-vcd** or **-svcd**
2612
- Generate a VCD/SVCD menu; each menu option will have a
2613
- number associated with it. You can have up to nine menu
2614
- options per menu.
2615
-
2616
-Menu background/audio options:
2617
-
2618
-**-background** *IMAGE*
2619
- Use *IMAGE* (in most any graphic format) as a background. If image is not
2620
- the correct aspect ratio (4:3), it will be scaled and/or cropped,
2621
- depending on the **-crop** and **-scale** options. If no background is
2622
- supplied, a default background will be created.
2623
-
2624
-**-crop** (default)
2625
- If provided background image is not 4:3 aspect ratio, crop edges
2626
- to make it so. Image will be scaled up if it is too small. Cropping
2627
- keeps the center area of image. If you want to do cropping/scaling
2628
- yourself in another program, provide an image of 768x576 pixels.
2629
-
2630
-**-scale**
2631
- If provided background image is not 4:3 aspect ratio, scale/stretch
2632
- it to make it fit. May cause visible distortion!
2633
-
2634
-**-audio** *AUDIOFILE*
2635
- Use *AUDIOFILE* (in most any audio format) for background music. The
2636
- menu will play for long enough to hear the whole audio clip. If
2637
- one is not provided, 4 seconds of silence will be used.
2638
-
2639
-**-length** *NUM*
2640
- Make the menu *NUM* seconds long. Useful for menus with **-audio**:
2641
- if you don't want the entire *AUDIOFILE* in the menu, then you can trim
2642
- the length of the menu with **-length**.
2643
-
2644
-Menu text options:
2645
-
2646
-**-menu-title** "*MENU TITLE TEXT*"
2647
- Add *MENU TITLE TEXT* as a title/header to the menu.
2648
-
2649
-**-font** *FONTNAME* (default Helvetica)
2650
- Use *FONTNAME* for the menu text. Run 'convert -list type' to see a
2651
- list of the fonts that you can use; choose a font name from the
2652
- leftmost column that is displayed. Or you can specify a ttf font file instead.
2653
- E.g., **-font /path/to/myfont.ttf**.
2654
-
2655
-**-fontsize** *NUM* (default 24)
2656
- Sets the size for the font to *NUM* pixels.
2657
-
2658
-**-menu-title-fontsize** *NUM* (default **-fontsize** + 8)
2659
- Sets the size of the menu title.
2660
-
2661
-**-fontdeco** '*FONTDECORATION*'
2662
- Sets the font decoration method to *FONTDECORATION*. It is used by the
2663
- 'convert' ImageMagick command to draw the menu text. You can add colored
2664
- text outlines, gradient fills, and many others. See **Usage notes**.
2665
-
2666
-**-align** {left|center|middle|right}
2667
- Align the text at the top left, top center, very middle, or top right
2668
- side of the screen. You may also substitute any "gravity" keyword
2669
- allowed by ImageMagick (north|south|east|west|northeast|southwest|...).
2670
-
2671
-**-textcolor** {#RRGGBB|#RGB|COLORNAME}
2672
- Use specified color for menu text. #RRGGBB and #RGB are
2673
- hexadecimal triplets (e.g., #FF8035). COLORNAME may be any of
2674
- several hundred named colors; run 'convert -list color' to see them.
2675
- White (#FFF) is the default color.
2676
-
2677
-DVD-only options:
2678
-
2679
-**-button** *BUTTON* (default '>')
2680
- Specify the button used for menu selection. Specify either a *single*
2681
- character or one of the shortcuts:
2682
-
2683
- **play**
2684
- Use a button shaped like 'Play' on many A/V electronics:
2685
- a triangle pointing to the right. (uses the font Webdings)
2686
- **movie**
2687
- Use a button shaped like an old movie projector.
2688
- (uses the font Webdings)
2689
- **utf8**
2690
- Use your own non-keyboard character as a button. Provide
2691
- only the four hex digits: eg **-button utf8 00b7**. Beware that
2692
- ImageMagick's utf8 characters aren't the same as those drawn in
2693
- character browsers like gucharmap.
2694
-
2695
-**-highlightcolor** {#RRGGBB|#RGB|COLORNAME}
2696
- Use the specified color for button highlighting. Yellow (#FF0) is the
2697
- default color.
2698
-
2699
-**-selectcolor** {#RRGGBB|#RGB|COLORNAME}
2700
- Use the specified color for button selections (when a menu item is played
2701
- or activated). Red (#F00) is the default color.
2702
-
2703
-**-button-outline** {#RRGGBB|#RGB|COLORNAME}
2704
- Outline buttons with the specified color. 'none' is the default.
2705
-
2706
-**-button-font** *FONTNAME*
2707
- Specify a differnt font to use for the buttons. By default, the button
2708
- font will be inherited from the title font (see **-font**). Use this
2709
- option to use a different font for the buttons. The button font size is
2710
- inherited from **-fontsize** and cannot be changed.
2711
-
2712
-Other options:
2713
-
2714
-**-debug**
2715
- Print extra debugging information to the log file. Useful in
2716
- diagnosing problems if they occur. This option also leaves
2717
- the log file (with a .log extension) in the directory after
2718
- encoding finishes as well as all the temporary files created.
2719
-
2720
-**-nosafearea**
2721
- Do not attempt to put text inside a TV-safe viewing area. Most
2722
- television sets cut off about 10% of the image border, so the script
2723
- automatically leaves a substantial margin. This option turns that
2724
- behavior off, leaving only a tiny margin. Use at your own risk.
2725
-
2726
-**-overwrite**
2727
- Overwrite any existing output menu.
2728
-
2729
-**-noask**
2730
- Don't ask interactive questions, and assume answers that will
2731
- continue making the menu until completion.
2732
-
2733
-**-quiet**
2734
- Limit output to essential messages.
2735
-
2736
-If the word "**back**" is given as an episode title, a "back" button for
2737
-returning to a higher-level menu will be added at the end of the list
2738
-of titles. "**Back**" *must be the last title listed*.
2739
-
2740
-Examples
2741
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2742
-
2743
-Make an NTSC VCD menu with white Helvetica text containing three centered
2744
-selections: Episode 1, Episode 2, and Episode 3. The finished menu will be
2745
-called Season-1.mpg::
2746
-
2747
- $ tovid menu -ntsc -vcd \
2748
- -align center -textcolor white -font "Helvetica" \
2749
- "Episode 1" "Episode 2" "Episode 3" \
2750
- -out "Season-1"
2751
-
2752
-Make an NTSC DVD menu with white Kirsty text containing three lower-left
2753
-aligned selections: Episode 1, Episode 2, and Episode 3. Items under the cursor
2754
-will be highlighted a pale blue, and selected items will be a pale orange
2755
-(before going to the selected title). The finished menu will be called
2756
-Main-menu.mpg::
2757
-
2758
- $ tovid menu -ntsc -dvd \
2759
- -align southwest \
2760
- -textcolor white \
2761
- -highlightcolor "#5f65ff" \
2762
- -selectcolor "#ffac5f" \
2763
- -font "Kirsty" \
2764
- "Episode 1" "Episode 2" "Episode 3" \
2765
- -out "Main_menu"
2766
-
2767
-Usage notes
2768
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2769
-
2770
-The argument given to **-font** must be one of the fonts listed by the command
2771
-'convert -list type'. Please note that many of your installed fonts may not be
2772
-available; if you want to maximize the number of fonts available, download and
2773
-run Anthony Thyssen's (http://www.cit.gu.edu.au/~anthony/anthony.html)
2774
-imagick_type_gen.pl (http://www.cit.gu.edu.au/~anthony/software/imagick_type_gen.pl)
2775
-script and run it like this::
2776
-
2777
- imagick_type_gen.pl > ~/.magick/type.xml.
2778
-
2779
-If that doesn't work, try::
2780
-
2781
- imagick_type_gen.pl > ~/.magick/type.mgk.
2782
-
2783
-Or you can specify a ttf font file directly to the **-font** options if you
2784
-don't want to install fonts to ImageMagick.
2785
-
2786
-The **-fontdeco** option is quite flexible and takes a lot of ImageMagick's
2787
-*convert* options. Please refer to the tovid wiki
2788
-(http://tovid.wikia.com/wiki/Making_a_DVD_with_text_menus)
2789
-and Anthony Thyssen's guide for further explanation and examples.
2790
-
2791
-
2792
-.. _command-xml:
2793
-
2794
-Command:xml
2795
-===============================================================================
2796
-
2797
-**tovid xml** generates XML output describing an (S)VCD
2798
-or DVD file structure and navigation hierarchy in the format expected by
2799
-dvdauthor (http://dvdauthor.sourceforge.net/) or
2800
-vcdxbuild (http://www.vcdimager.org/).
2801
-
2802
-Usage
2803
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2804
-
2805
-::
2806
-
2807
- tovid xml [OPTIONS] VIDEOS -out OUTFILE
2808
-
2809
-For example::
2810
-
2811
- tovid xml -menu MainMenu.mpg \
2812
- Season1.mpg Season2.mpg Featurettes.mpg \
2813
- -out MyDisc
2814
-
2815
-Options
2816
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2817
-
2818
-**-dvd** (default)
2819
- Generate the XML for a DVD disc, to be used with dvdauthor or **tovid dvd**.
2820
-
2821
-**-vcd**
2822
- Generate the XML for a VCD disc, to be used with vcdxbuild or **tovid vcd**.
2823
-
2824
-**-svcd**
2825
- Generate the XML for an SVCD disc, to be used with vcdxbuild or **tovid vcd**.
2826
-
2827
-**-overwrite**
2828
- Overwrite any existing output files.
2829
-
2830
-**-quiet**
2831
- Limit output to essential messages.
2832
-
2833
-*VIDEOS* may be any of the following:
2834
-
2835
-*<file list>*
2836
- List of one or more video files to include, separated by spaces. At
2837
- minimum, a DVD must have one video file. You can use shell wildcards
2838
- (i.e., "\*.mpg") to include multiple files easily. Put filenames in
2839
- quotes if they have spaces in them.
2840
-
2841
-**-menu** *VIDEO* *<file list>*
2842
- Use video file *VIDEO* as a menu from which you can jump to each of
2843
- the listed video files. If you have multiple menus, include a
2844
- top menu so they are reachable.
2845
-
2846
-**-slides** *<file list>*
2847
- Create a slide-show of still images
2848
-
2849
-DVD-only options
2850
-
2851
-**-group** *<file list>* **-endgroup**
2852
- (DVD only) List of video files to include as one single title. This is useful
2853
- if you have split a movie into several video files.
2854
-
2855
-**-topmenu** *VIDEO* [**-menu** *VIDEO* *<file list>*] [**-menu** *VIDEO* *<file list>*]...
2856
- (DVD only) Use video file *VIDEO* for the top-level (VMGM) menu. The
2857
- top menu will jump to each of the subsequent [-menu...] videos listed.
2858
- Use this only if you have multiple sub-menus to jump to. You can only
2859
- have one top menu.
2860
-
2861
-**-titlesets**
2862
- (DVD only) Forces the creation of a separate titleset per title. This
2863
- is useful if the titles of a DVD have different video formats,
2864
- e.g. PAL + NTSC or 4:3 + 16:9. If used with menus, there must be a
2865
- **-topmenu** option that specifies a menu file with an entry for each of the
2866
- titlesets.
2867
-
2868
-**-chapters** *INTERVAL*
2869
- (DVD only) Creates a chapter every *INTERVAL* minutes (default 5 minutes:
2870
- without **-chapters**, each movie will be divided into 5-minute chapters).
2871
- This option can be put at any position in a *<file list>* and is valid
2872
- for all subsequent titles until a new **-chapters** option is encountered.
2873
- Using this option may take some time, since the duration of the video is
2874
- calculated.
2875
-
2876
-**-nochapters**
2877
- (DVD only) Don't create chapters for the videos.
2878
-
2879
-*OUT_PREFIX* is the file that will receive the resulting XML.
2880
-
2881
-Usage notes
2882
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2883
-
2884
-The 'xml' command checks to make sure the video filenames you
2885
-give it exist, but it does not check whether they are valid for the
2886
-chosen disc format. MPEG videos of menus should have the specified
2887
-number of buttons for reaching each of the videos, and, if you're
2888
-using DVD, should be multiplexed with their corresponding subtitles
2889
-using spumux of the dvdauthor 0.6.0 package prior to
2890
-authoring using dvdauthor. If you use the 'tovid menu'
2891
-component to generate the menu, this should all be handled for you.
2892
-
2893
-Examples
2894
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2895
-
2896
-``tovid xml -dvd title-1.mpg title-2.mpg title-3.mpg -out My_DVD``
2897
- Make a DVD without a menu. Title 1, 2, and 3 will play in sequence.
2898
-
2899
-``tovid xml -dvd -group chapter-1.mpg chapter-2.mpg chapter-3.mpg -endgroup -out My_DVD``
2900
- Group the file chapter-1|2|3.mpg into one title and make a DVD without a menu.
2901
-
2902
-``tovid xml -dvd -menu main_menu.mpg -chapters 3 movie-1.mpg -chapters 10 movie-2.mpg -out My_DVD``
2903
- Make a DVD with a main menu that points to two movies, with movie-1.mpg
2904
- divided into 3-minute chapters, and movie-2.mpg into 10-minute chapters.
2905
-
2906
-
2907
-.. _command-dvd:
2908
-
2909
Command:dvd
2910
-===============================================================================
2911
+===========
2912
2913
-**tovid dvd** takes a dvdauthor XML file (as generated by the **tovid xml**
2914
-command) and authors a DVD filesytem. This command can also burn a DVD disc
2915
-from either the XML file or from an existing DVD file-system.
2916
+**tovid dvd** takes a dvdauthor XML file (as generated by the **tovid
2917
+xml** command) and authors a DVD filesytem. This command can also burn a
2918
+DVD disc from either the XML file or from an existing DVD file-system.
2919
2920
To ensure that this script successfully executes, please run it from a
2921
-directory with plenty of free space. "Plenty" would be 10 GB for single-layer
2922
-discs, and 20 GB for dual-layer discs. Running this program may slow down your
2923
-other applications, due to intense disk activity.
2924
+directory with plenty of free space. "Plenty" would be 10 GB for
2925
+single-layer discs, and 20 GB for dual-layer discs. Running this program
2926
+may slow down your other applications, due to intense disk activity.
2927
2928
Usage
2929
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2930
-
2931
-::
2932
+-----
2933
2934
- tovid dvd [OPTIONS] FILE.xml
2935
- tovid dvd [OPTIONS] DVD_DIR
2936
+**tovid dvd** [*OPTIONS*] *DVD\_DIR* **tovid dvd** [*OPTIONS*]
2937
+*FILE.xml*
2938
2939
For example:
2940
2941
-``tovid dvd -burn MyDisc.xml``
2942
``tovid dvd -burn /path/to/DVD/directory``
2943
+``tovid dvd -burn MyDisc.xml``
2944
2945
Options
2946
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2947
+-------
2948
2949
**-author**
2950
Author the DVD described by *FILE.xml*. Overwrites an existing
2951
directory containing the dvdauthor output if already present.
2952
2953
**-burn**
2954
- Burn a DVD file-system in *DVD_DIR* (must contain a VIDEO_TS folder).
2955
+ Burn a DVD file-system in *DVD\_DIR* (must contain a VIDEO\_TS
2956
+ folder).
2957
+
2958
+**-eject**
2959
+ Eject the DVD tray after burning is complete. By default, the DVD is
2960
+ not ejected.
2961
2962
**-device** *DEVICE* (default /dev/dvdrw)
2963
- Burn the disc image to *DEVICE*, the Linux device file-system
2964
- name of your DVD-recorder. Common examples might be /dev/dvdrw,
2965
- /dev/scd1, and /dev/hdc. You can also use a bus/id/lun triple
2966
- such as ATAPI:0,1,0
2967
+ Burn the disc image to *DEVICE*, the Linux device file-system name
2968
+ of your DVD-recorder. Common examples might be /dev/dvdrw,
2969
+ /dev/scd1, and /dev/hdc. You can also use a bus/id/lun triple such
2970
+ as ATAPI:0,1,0
2971
2972
**-speed** *NUM* (default 1)
2973
Burn disc at speed *NUM*.
2974
2975
-**-label** *DISC_LABEL*
2976
- Uses *DISC_LABEL* as the volume ID. This appears as the mount
2977
- name of the disc on some computer platforms. Must be <=32
2978
+**-label** *DISC\_LABEL*
2979
+ Uses *DISC\_LABEL* as the volume ID. This appears as the mount name
2980
+ of the disc on some computer platforms. Must be <=32
2981
alphanumeric digits without spaces.
2982
2983
**-quiet**
2984
Limit output to essential messages.
2985
2986
**-noask**
2987
- Don't ask interactive questions and assume answers that will continue
2988
- execution.
2989
+ Don’t ask interactive questions and assume answers that will
2990
+ continue execution.
2991
2992
Examples
2993
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2994
+--------
2995
2996
``tovid dvd -burn -device /dev/dvdrw foo.xml``
2997
Author the dvd file-system and burn to /dev/dvdrw. This will
2998
- automatically call dvdauthor to make the file-system. **-author**
2999
- is not explicitly needed. If there's an existing file-system, it
3000
- will be burned.
3001
+ automatically call dvdauthor to make the file-system. **-author** is
3002
+ not explicitly needed. If there’s an existing file-system, it will
3003
+ be burned.
3004
3005
``tovid dvd -author foo.xml``
3006
Author the DVD file-system and exit without burning. If the output
3007
directory given in foo.xml already exists, then the contents are
3008
- removed before authoring. At this point, the DVD can be previewed
3009
- by calling ``xine dvd:/path/to/output/directory``.
3010
-
3011
-
3012
-.. _command-vcd:
3013
-
3014
-Command:vcd
3015
-===============================================================================
3016
-
3017
-**tovid vcd** takes an XML file (which may be generated by **tovid xml**) and
3018
-creates a cue/bin (S)VCD image. It can also burn (S)VCD discs.
3019
-
3020
-To ensure that this script successfully executes, please run it from a directory
3021
-with plenty of free space. "Plenty" would be about 1 GB. Running this program
3022
-may slow down your other applications, due to intense disk activity.
3023
-
3024
-Usage
3025
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3026
-
3027
-::
3028
-
3029
- tovid vcd [OPTIONS] VCDIMAGER.xml
3030
-
3031
-For example:
3032
-
3033
-``tovid vcd -burn MyDisc.xml``
3034
-
3035
-Options
3036
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3037
-
3038
-**-overwrite** (default off -- nothing is overwritten)
3039
- Overwrite any existing cue/bin files matching *VCDIMAGER.xml*. Useful
3040
- if you modified the xml file and wish to re-image or burn the new (S)VCD.
3041
-
3042
-**-burn** (default off -- no images are burned)
3043
- Burn the (S)VCD described by *VCDIMAGER.xml*.
3044
+ removed before authoring. At this point, the DVD can be previewed by
3045
+ calling ***xine** dvd:/path/to/output/directory*.
3046
3047
-**-device** *DEVICE* (default /dev/cdrw)
3048
- Burn the disc image to *DEVICE*, the Linux device file-system
3049
- name of your CD-recorder. Common examples might be /dev/cdrw,
3050
- /dev/scd1, and /dev/hdc.
3051
+Command:chapters
3052
+================
3053
3054
-**-speed** *NUM* (default 12)
3055
- Burn the disc at speed *NUM*.
3056
+**tovid chapters** will start a GUI using mplayer to set chapter points
3057
+in a video. If the video plays through and you want to add more chapters
3058
+you can press the play button again, but remember that new chapter
3059
+points will be appended (in correct sequential order). It will display
3060
+the resulting chapter points, and also output to a terminal (useful for
3061
+scripts). As well it will give the option of saving the chapters string
3062
+to a text file.
3063
3064
-**-quiet**
3065
- Limit output to essential messages.
3066
+Note that the ’tovid gui’ now features a similar widget when you press
3067
+the chapters button on the opening page.
3068
3069
Examples
3070
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3071
-
3072
-``tovid vcd -burn -device /dev/cdrw foo.xml``
3073
- Create the (S)VCD image and burn it to /dev/cdrw. This will
3074
- automatically call vcdxbuild to make the image. If there is an existing
3075
- image, it will be burned.
3076
-
3077
-``tovid vcd -overwrite foo.xml``
3078
- Create the (S)VCD image and exit without burning. If the image
3079
- already exists, then it is removed before re-imaging.
3080
-
3081
-
3082
-.. _command-postproc:
3083
-
3084
-Command:postproc
3085
-===============================================================================
3086
-
3087
-**tovid postproc** is designed to do simple post-processing on MPEG video files, such
3088
-as those generated by tovid. It can adjust audio/video sync, and re-quantize
3089
-(shrink) without re-encoding.
3090
-
3091
-Usage
3092
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3093
-
3094
-::
3095
-
3096
- tovid postproc [OPTIONS] IN_FILE OUT_FILE
3097
-
3098
-Options
3099
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3100
-
3101
-**-audiodelay** *NUM*
3102
- Delay the audio stream by *NUM* milliseconds. Use this if
3103
- your final output has audio that is not synced with the
3104
- video. For example, if the audio comes 2 seconds sooner than
3105
- the video, use **-audiodelay 2000**. Use a negative number for
3106
- audio that comes later than the video.
3107
-
3108
-**-normalize**
3109
- Analyze the audio stream and then normalize the volume of the audio.
3110
- This is useful if the audio is too quiet or too loud, or you want to
3111
- make volume consistent for a bunch of videos. Similar to running
3112
- normalize without any parameters. The default is -12dB average level
3113
- with 0dB gain.
3114
-
3115
-**-amplitude** *NUM[dB]*
3116
- In addition to analyzing and normalizing, apply the gain to the audio
3117
- such that the 'average' (RMS) sound level is *NUM*. Valid values
3118
- range 0.0 - 1.0, with 0.0 being silent and 1.0 being full scale. Use
3119
- *NUMdB[dB]* for a decibel gain below full scale (the default without
3120
- -amplitude is -12dB).
3121
-
3122
-**-shrink** *NUM*
3123
- Shrink the video stream by a factor of *NUM*. May be a decimal
3124
- value. A value of 1.0 means the video will be the same size;
3125
- larger values cause more reduction in size. Beyond 2.0, the
3126
- returns are diminishing.
3127
-
3128
-**-parallel**
3129
- Run all processes in parallel and pipe into multiplexer, should
3130
- increase speed significantly.
3131
-
3132
-**-debug**
3133
- Save output in a temporary file, for later viewing if
3134
- something goes wrong.
3135
+--------
3136
3137
-Contact
3138
-===============================================================================
3139
+``tovid chapters foo.avi``
3140
+{chapters=$(tovid chapters /home/grepper/videos/foo.avi)}
3141
3142
-For further assistance, contact information, forum and IRC links,
3143
-please refer to the tovid homepage (http://tovid.wikia.com/).
3144
+CONTACT
3145
+=======
3146
3147
+For further assistance, contact information, forum and IRC links, please
3148
+refer to the {tovid homepage} {http://tovid.wikia.com/}.
3149
tovid-0.34.tar.bz2/docs/src/en/tovid.t2t -> tovid-0.35.tar.gz/docs/src/en/tovid.t2t
Changed
1249
1
2
author and burn a ready-to-watch DVD, with just a few shell commands. A
3
graphical interface is also provided to make the process even easier.
4
5
-**NOTE**: As of tovid 0.32, this is the only manual page provided by tovid.
6
+**NOTE**: As of tovid 0.35, the legacy scripts **makemenu** and **makexml**
7
+have been removed and no longer appear in this manpage.
8
+All of their functions and more can be done with the 'tovid disc' command,
9
+(todisc script). See **Command:disc** and the [wiki http://tovid.wikia.com]
10
+for more info.
11
+
12
+Also note that as of tovid 0.32, this is the only manual page provided by tovid.
13
There is now a single executable frontend to all functionality in the suite, so
14
-if you were expecting to find manpages for **todisc**, **idvid**, **makemenu**
15
+if you were expecting to find manpages for **todisc**, **idvid**, **makempg**
16
and their kin, they can all be found in the **tovid** manpage you are reading now.
17
-
18
And yes, this makes for a pretty large manual page. If you are viewing this
19
manpage from the command-line **man** utility, which normally pages through the
20
**less** utility, you can skip to a section by searching with the **/** key,
21
22
23
Where //COMMAND// is one of the following:
24
25
+ Main Commands
26
+: **disc**
27
+ Encode, make menus, author, burn. (was **todisc**. See **Command:disc**)
28
: **gui**
29
Start the tovid GUI (was **todiscgui**. See **Command:gui**)
30
: **titlesets**
31
- A tovid GUI wizard for multiple titlesets. (new: See **Command:titlesets**)
32
-: **disc**
33
- Create a DVD with menus (was **todisc**. See **Command:disc**)
34
+ A GUI wizard for multiple titlesets. (new: See **Command:titlesets**)
35
+
36
+
37
+ Helper Commands
38
: **mpg**
39
Encode videos to MPEG format (was **tovid**. See **Command:mpg**)
40
-: **id**
41
- Identify one or more video files (was **idvid**. See **Command:id**)
42
-: **menu**
43
- Create an MPEG menu (was **makemenu**. See **Command:menu**)
44
-: **xml**
45
- Create (S)VCD or DVD .xml file (was **makexml**. See **Command:xml**)
46
: **dvd**
47
Author and/or burn a DVD (was **makedvd**. See **Command:dvd**)
48
-: **vcd**
49
- Author and/or burn a VCD (was **makevcd**. See **Command:vcd**)
50
-: **postproc**
51
- Post-process an MPEG video file (was **postproc**. See **Command:postproc**)
52
+: **id**
53
+ Identify one or more video files (was **idvid**. See **Command:id**)
54
: **chapters**
55
A GUI using mplayer for setting chapter points. It will return a string of
56
- chapter points in a format recognized by 'tovid disc' (todisc) or
57
- by 'tovid gui', for the **-chapters** option.
58
-
59
+ chapter points to the terminal, in a format recognized by 'tovid disc'
60
+ (todisc) or by 'tovid gui', for the **-chapters** option.
61
+
62
63
The //OPTIONS// differ for each command; run **tovid <command>** with no
64
further arguments to get help on a command, and what options it expects.
65
66
67
: **~/.tovid/preferences**
68
Defines working directory for all scripts.
69
- In addition you can define the output directory for makempg here.
70
+ You can define the output directory for makempg here.
71
+ The 'ffmpeg' executable can be set here: ffmpeg or avconv (TOVID_FFMPEG)
72
: **~/.tovid/tovid.ini**
73
Includes command-line options that should be passed to the various
74
- **tovid** sub-commands.
75
+ **tovid** sub-commands. Note: each sub-command has its own section,
76
+ starting with the line [sub-command], for example:
77
+```
78
+ [disc]
79
+ ; -no-warn
80
+ -static
81
+ -no-ask
82
+```
83
+
84
85
Edit these files if you wish to change your configuration.
86
87
+
88
The following environment variables are also honoured:
89
-TOVID_WORKING_DIR (working directory for all scripts).
90
-TOVID_OUTPUT_DIR (output directory for the makempg script).
91
+```
92
+ TOVID_HOME (directory containing preferences: ~/.tovid)
93
+ TOVID_WORKING_DIR (working directory for all scripts).
94
+ TOVID_OUTPUT_DIR (output directory for the makempg script).
95
+ TOVID_FFMPEG_CMD (the 'ffmpeg' executable to use: ffmpeg or avconv)
96
+```
97
+These will override 'TOVID_HOME', 'WORKING_DIR', 'OUTPUT_DIR',
98
+and 'TOVID_FFMPEG' if set in ~/.tovid/preferences.
99
100
101
=Command:gui=
102
103
+=Usage=
104
+
105
+**tovid gui** [//OPTIONS//]
106
+
107
**tovid gui** starts the graphical user interface (GUI) for tovid. This is
108
-the easiest way to start creating DVDs with tovid. At this time, there are no
109
-additional command-line options; the GUI controls take care of everything,
110
-and all help is integrated in the form of tooltips. You can also see
111
-**Command:disc ** for more detail about the options. Note: if you wish to
112
-make multiple titlesets on the same DVD use 'tovid titlesets', which is a wizard
113
-that uses the the tovid GUI. Chapter submenus can be made with 'tovid gui'
114
-however.
115
+the easiest way to start creating DVDs with tovid. The optional arguments
116
+//OPTIONS// are any option used by todisc ('tovid disc') which will save
117
+entering it manually, OR the full path to a saved script from the GUI.
118
+You can also combine these, but the script must be the FIRST option
119
+directly after **tovid gui** . (This option to save the contents of your
120
+project allows you to use it as a bash script later, or to reload the
121
+project to continue working with it at another time.)
122
+
123
+
124
+**tovid gui** will also take the option **--position**, which denotes the
125
+screen position that the GUI will start at, in the form '+X+Y', similar to
126
+this part of the Xorg -geometry string.
127
+
128
+All help is integrated in the form of tooltips. You can also see
129
+**Command:disc ** for more detail about the options. Note: if you wish to use
130
+a GUI to make multiple titlesets on the same DVD use ***tovid titlesets***,
131
+which is a wizard that uses the the 'tovid gui. See ***Command:titlesets***.
132
+
133
+
134
+Please note that although the interface may seem complex with so many options,
135
+you can create a fully functional DVD with only a few options on the opening
136
+tab of the GUI (select video files and an output name).
137
138
139
=Command:titlesets=
140
141
**tovid titlesets** will assist in making a DVD with multiple titlesets. It can
142
be started without any options, or you can feed it the path to a saved titleset
143
-script as an option.
144
+script as an option. The option to save a script is also useful as the resulting
145
+script can be run later from a terminal.
146
147
148
=Command:disc=
149
150
-**tovid disc** creates a DVD file-system with menus, from a list of multimedia
151
-video files and their titles. As this is a low level script it is the easiest
152
-command line program for creating a DVD from start to finish, including
153
-automatically converting non-compliant videos and prompting to burn at
154
-completion. It does animated menus, static thumbnail menus and text only
155
-menus. In addition, it can do slideshows, using images as input, and combine
156
-slideshows with videos. It supports sub-menus for chapter breaks, configurable
157
-menu style, animated backgrounds and transparency effects.
158
+**tovid disc** creates a DVD file-system with optional menus, from a list of
159
+multimedia video files and their titles. As todisc can function as a master
160
+script, calling other scripts as it needs them, it is the easiest command line
161
+program for creating a DVD from start to finish, including automatically
162
+converting non-compliant videos and prompting to burn at completion. It can do
163
+animated menus, static thumbnail menus, text-only menus, or author with no menu.
164
+In addition, it can do slideshows, using images as input, and even combine
165
+slideshows with videos. It supports sub-menus for chapter breaks,
166
+configurable menu style, animated backgrounds and transparency effects.
167
+From simple (no menu) to complex (switched menus and titlesets), you should
168
+be able to do what you want with 'tovid disc'.
169
170
171
==Usage==
172
173
```
174
tovid disc [OPTIONS] \
175
-files <file list> -titles <title list>
176
- -out OUT_PREFIX
177
+ -out mydvd
178
```
179
180
For example:
181
182
as titles. If you are doing a slideshow or multiple slideshows, use
183
**-slides** rather than **-files** for passing in the images. You may use
184
-files and -slides more than once to create an ordering in a mixed
185
-slideshows/videos menu. See SLIDESHOWS part of Usage section, below.
186
+slideshows/videos menu. See Slideshows part of Usage section, below.
187
188
If the input files are not mpeg, you will have the option to auto-encode them.
189
190
+General Options
191
+
192
**At present there are 2 display arrangements or "templates":**
193
194
: A. (Default)
195
196
$ tovid disc -submenus \
197
-files file1.mpg file2.mpg ... \
198
-titles "Short 1" "Short 2" \
199
+ -submenus \
200
-submenu-titles "Long Title One" "Long Title Two" \
201
-out foo
202
203
204
205
The **-align** argument will position both titles and thumbs either south,
206
north east, west, southwest, northwest, southeast, northeast, subject to
207
-certain constraints of each arrangement.
208
+certain constraints of each arrangement. For example a showcase style with
209
+a showcase thumb can only do north|south|center.
210
+
211
+More Examples:
212
+
213
+A text-only menu:
214
+
215
+```
216
+ $ tovid disc -textmenu ...
217
+```
218
+No menu:
219
+
220
+```
221
+ $ tovid -nomenu -files file1.mpg file2.mp4 "file 3.avi" -out mydvd
222
+```
223
+
224
225
**Titlesets**
226
227
228
will need as many TITLES after **-titles** as you have menus.
229
230
Any options outside the **-titleset** **-end-titleset** and **-vmgm**
231
-**-end-vmgm** areas will be general options applying to every titleset.
232
-If a general option is duplicated inside a **-titleset** or **-vmgm** area, the
233
-general option will be overridden.
234
+**-end-vmgm** areas will be global options applying to every titleset.
235
+If a global option is duplicated inside a **-titleset** or **-vmgm** area, the
236
+global option will be overridden.
237
238
Note: you do not need titlesets for a single menu with chapter break menus, for
239
that just use **-submenus** or **-ani-submenus**
240
241
242
```
243
$ tovid disc -static -out MY_DVD \
244
- \
245
- -titleset -files 1.mpg 2.mpg 3.mpg \
246
+ \
247
+ -titleset \
248
+ -files 1.mpg 2.mpg 3.mpg \
249
-titles "Title One" "Title Two" "Title Three" \
250
-end-titleset \
251
\
252
- -titleset -files 4.mpg 5.mpg \
253
+ -titleset \
254
+ -files 4.mpg 5.mpg \
255
-titles "Title Four" "Title Five" \
256
- -background foo.jpg \
257
- -showcase bar.png \
258
- -end-titleset \
259
- \
260
- -vmgm \
261
- -titles "Season One" "Season Two" \
262
- -background bg.jpg \
263
- -bgaudio foo.mp3 \
264
- -titles-fontsize 20 \
265
- -end-vmgm
266
+ -background foo.jpg \
267
+ -showcase bar.png \
268
+ -end-titleset \
269
+ \
270
+ -vmgm \
271
+ -titles "Season One" "Season Two" \
272
+ -background bg.jpg \
273
+ -bgaudio foo.mp3 \
274
+ -titles-fontsize 20 \
275
+ -end-vmgm
276
```
277
278
See also **-titleset** and **-vmgm**
279
280
-out myslideshow
281
```
282
283
-See the other slideshow options in the SLIDESHOWS options section.
284
+See the other slideshow options in the Slideshows options section.
285
286
287
288
289
**-vbitrate**, **-quality**, **-safe**, **-crop**, **-filters**,
290
**-abitrate**, **-priority**, **-deinterlace**, **-progressive**,
291
**-interlaced**, **-interlaced_bf**, **-type**, **-fit**, **-discsize**,
292
- **-parallel**, **-mkvsub**, **-autosubs**, **-subtitles**, **-update**, \
293
+ **-parallel**, **-mkvsub**, **-autosubs**, **-subtitles**, **-update**,
294
**-mplayeropts**, **-audiotrack**, **-downmix**, **-ffmpeg**, **-nofifo**,
295
**-from-gui**, **-slice**, **-quiet**,
296
**-fake**, **-keepfiles**
297
298
-==Options==
299
+==General Options==
300
301
: **-keep-files**, **-keepfiles**
302
Keep all intermediate/temporary files (helps with debugging)
303
+: **-no-ask** | **-noask**
304
+ Skip all interactive questions. No preview, automatic re-encoding with
305
+ tovid if needed, no interactive option to use background video for bgaudio.
306
+: **-no-warn**, **-nowarn**
307
+ Don't pause after outputting warning or info messages
308
+: **-jobs**
309
+ By default, **tovid disc** starts a parallel job for each processor
310
+ detected. With this option you can manually set the number of jobs. For
311
+ example if you have a computer with 2 CPUs you can set "-jobs 1" to keep
312
+ one processor free for other things. At present this applies to the time
313
+ consuming imagemagick loops: you will notice a substantial speedup now if
314
+ you have a multi-cpu system.
315
+: **-grid**
316
+ Show a second preview image with a grid and numbers that will help in finding
317
+ coordinates for options that might use them, like **-text-start**
318
+: **-no-confirm-backup**
319
+ This option is for when your DVD contains images for a slideshow.
320
+ Slideshows are an experimental (but well tested) feature. Todisc is
321
+ unlikely to overwrite your personal files, but you should take precautions
322
+ and backup your images, as you would with any beta software. Todisc
323
+ will prompt you to backup your files normally. If you have already backed
324
+ up your images, use this option to disable the prompt.
325
+
326
+==Options==
327
+
328
: **-ntsc**
329
720x480 output, compatible with NTSC standard (default)
330
: **-pal**
331
332
: **-no-menu | -nomenu**
333
With this option todisc will just create a DVD file system, ready for
334
burning, with NO MENU, just the supplied video files. These do not need
335
- to be compliant, as non-compliant files will be encoded as usual. Each
336
- video will be a chapter unless **-chapters** OPTION is passed. The
337
- **-chapters** option is a number indicating the chapter interval in
338
- minutes, or a HH:MM:SS string indicating chapter points. See **-chapters**
339
+ to be compliant, as non-compliant files will be encoded as usual. The
340
+ **-out** option is not required. Each video will be a chapter unless
341
+ **-chapters** OPTION is passed. The **-chapters** option is a number
342
+ indicating the chapter interval in minutes, or a HH:MM:SS string
343
+ indicating chapter points. See **-chapters**
344
+: **-encode-only**
345
+ This option was originally meant for the GUI, to allow it to be used for
346
+ just encoding rather than making a DVD structure. But it works well from
347
+ the command line as well as it has the added advantage that you can input
348
+ a list of files. Remember any makempg ('tovid mpg') options you use will
349
+ be passed on to the makempg script when encoding.
350
351
352
==Menu style==
353
354
This is a different arrangement of images for the menu: small thumbnails
355
go at left (and right) side of screen, with a larger image in the centre.
356
Maximum of 10 videos. If the provided argument is a video file, the
357
- central thumb will be animated. Only 4:3 or 16:9 videos and images are
358
- accepted for the showcase file: if not one of these todisc will assume it
359
- is the same ratio as the videos in the titleset.
360
+ central thumb will be animated (regardless of whether **-static** is part
361
+ of the command line). Only 4:3 or 16:9 videos and images are accepted for
362
+ for the showcase file: if not one of these todisc will assume it is the
363
+ aspect ratio as the videos in the titleset.
364
: **-textmenu**, **-text-menu** NUM
365
If used without an argument, create a textmenu out of the supplied titles
366
The optional argument specifies how many titles are in the 1st column,
367
i.e. giving 4 titles and using "-textmenu 2" would make 2 columns of 2
368
titles. The default is to put all titles up to 13 in the first column
369
before starting a second column. Maximum: 2 columns and 26 titles.
370
- Note that column 2 titles are aligned to the right.
371
- If no video files for either **-background** or **-showcase** are supplied,
372
- the menu will be static.
373
+ Note that column 2 titles are justified to the left unless you add
374
+ **-edge-justify** to the command line. The menu will be static if no video
375
+ files are supplied with either **-background** or **-showcase** options.
376
: **-quick-menu**
377
If you are using ffmpeg 0.8 or newer you can use this option. This will
378
make a very quick menu by using ffmpeg instead of imagemagick.
379
380
text-menu style of menu, with no video thumbs, and a central showcase
381
IMAGE(static) | VIDEO(animated).
382
(i) see **-bg-color** if you are not using a **-background** and want to
383
- change the default black )
384
- (ii) Note: todisc will still work with vhooks if you have an old ffmpeg with
385
- vhooks compiled in.
386
+ change the default. (default is dark blue for -quick-menu arrangements). )
387
+ (ii) Note: todisc will still work with 'vhooks' if you have an old ffmpeg
388
+ with vhooks compiled in.
389
390
Specifying the IMAGE|VIDEO argument to **-showcase** is mandatory for this
391
style of menu, unless used in conjunction with **-switched-menus**
392
in which case the videos passed with **-files** automatically become the
393
- showcase videos. If this is used in combination with **-switched-menus**
394
- it can really speed up an otherwise time consuming process.
395
+ showcase videos. If **-quick-menu** is used in combination with
396
+ **-switched-menus** it really speeds up an otherwise time consuming process.
397
398
Example:
399
```
400
- -quick-menu -showcase /home/robert/showcase.mpg
401
+ -quick-menu -showcase /home/grepper/showcase.mpg
402
```
403
See **-switched-menus** for example of making switched menus with
404
**-quick-menu**
405
406
The color to use for the menu background. (default: ntsc-safe black)
407
Note: use a color a great deal darker than you want, as it appears quite
408
a bit lighter in the video version. You can use hexadecimal ('#ffac5f')
409
- or named colors notation.
410
+ notation or named colors ('Lime'). convert -list color will show them.
411
+ See [colors http://www.imagemagick.org/script/color.php] for more details.
412
: **-submenu-bg-color**, **-submenu-bg-colour**
413
The color to use as background for the submenu(s).
414
(default: ntsc-safe black) See **-bg-color**
415
416
a 'moving' menu, in spite of the static buttons. This option also does
417
double duty for the **-switched-menus** option, and will create static
418
"switched" images.
419
- See also **-switched-menu**
420
+ See also **-switched-menus**
421
: **-background** IMAGE|VIDEO
422
Menu background. This can be a image file or an video file. If it is a
423
video file the background will be animated. Pick a file of correct aspect
424
425
: **-menu-title**
426
Title for the root menu - may be longer than thumbnail labels
427
Also if you use \n in the title, you can use multi line titles, but you
428
- would need to adjust **-menu-fontsize** to something smaller than default
429
+ would need to adjust **-title-fontsize** to something smaller than default
430
for example:
431
432
```
433
- $ tovid disc ... -menu-title "A\nMultilined\nTitle" -menu-fontsize 24
434
+ $ tovid disc ... -menu-title "A\nMultilined\nTitle" -title-fontsize 24
435
```
436
-: **-menu-font** FONT
437
+: **-title-font**, **-menu-font** FONT
438
Font to use for titles, either by ImageMagick font name (ex., "Arial") or
439
explicit pathname (ex., "/full/path/to/arial.ttf"). To see a complete
440
list of acceptable ImageMagick font names, run **convert -list type**, and
441
refer to the leftmost column
442
-: **-menu-fontsize**
443
+: **-title-fontsize**, **-menu-fontsize**
444
Font size for main menu - best to -preview if you use this
445
: **-submenu-font**
446
- Font to use for the sub-menu main titles. See **-menu-font**
447
+ Font to use for the sub-menu main titles. See **-title-font**
448
: **-submenu-fontsize**
449
Font size for the sub-menu main titles
450
: **-menu-fade** ['BACKGROUND DURATION']
451
452
using **-quick-nav** as you would not have a way to get to other titlesets.
453
: **-skip-vmgm**
454
Start DVD from the first titleset instead of the VMGM ( root ) menu.
455
-: **-switched-menus**
456
+: **-switched-menus**, **-switched-menu**
457
This will make a "switched menu": there will be a central image where the
458
showcase image would go, and text menu titles along the menu edge where
459
textmenu titles go. As you select a video title with the down or up arrow
460
461
462
==Thumbnail style==
463
464
+: **-titles-font** FONT
465
+ Display thumbnail or textmenu titles in the given font
466
+: **-titles-fontsize** POINTS
467
+ Font size to use for thumbnail or textmenu titles
468
: **-thumb-shape**
469
normal|oval|vignette|plectrum|arch|spiral|blob|star|flare
470
Apply a shaped transparency mask to thumbnail videos.
471
472
: **-3d-thumbs**, **-3dthumbs**
473
This will give an illusion of 3D to the thumbnails: dynamic lighting on
474
rounded thumbs, and a raised effect on rectangular thumbs. Try it !
475
-: **-titles-font** FONT
476
- Display thumbnail or textmenu titles in the given font
477
-: **-titles-fontsize** POINTS
478
- Font size to use for thumbnail or textmenu titles
479
480
481
==Slideshows==
482
483
be static. If you used with a mixed menu of videos and slideshows, then
484
the video thumbs WILL be animated, so you may wish to use -static or
485
-textmenu with the option in that case. If you want to use the
486
- **-switched-menus option with a mixed menu leave this option out.
487
+ **-switched-menus option with a mixed menu leave this option out.
488
489
: **-background-slideshow**, **-bg-slideshow**
490
If doing multiple slideshows or mixed videos and slideshow(s), then use
491
492
and backup your images, as you would with any beta software. Todisc
493
will prompt you to backup your files normally. If you have already backed
494
up your images, use this option to disable the prompt.
495
+ See **General Options**
496
497
: **-use-dvd-slideshow** [CONFIG FILE]
498
If you pass this option without an argument, tovid will use the
499
500
The speed to use for burning the disc.
501
502
503
-==ADVANCED USAGE==
504
+==Advanced usage==
505
506
===Options===
507
508
509
audio for static submenus. (Assuming that -submenu-audio was passed in).
510
The default is to use 10 seconds of audio for static menus.
511
: **-submenu-stroke** COLOR
512
- The color for the sub-menu font outline (stroke)
513
+ The color for the sub-menu font shadow
514
: **-submenu-title-color**, **-submenu-title-colour**
515
The fill color used for sub-menu title fonts
516
: **-submenu-titles**
517
- You can supple a list of titles here for sub-menus without the length
518
+ You can supply a list of titles here for sub-menus without the length
519
restrictions found in thumb titles. Must equal number of videos
520
: **-chapters** [ NUM | CHAPTER POINTS in HH:MM:SS ]
521
The number of chapters for each video (default: 6) OR
522
523
: **-chapter-color** COLOR
524
The color for the chapters font.
525
: **-chapter-stroke** COLOR
526
- The color for the chapters font outline (stroke)
527
+ The color for the chapters font shadow
528
529
: **-seek** NUM | "NUM1 NUM2 NUM3 . . ."
530
Seek to NUM seconds before generating thumbnails (default: 2.0 seconds)
531
532
title and/or thumbnail for bar.mpg will appear in the menu. You can use
533
**-group** more than once for multiple groups. Be sure to quote video
534
filenames if they contain spaces.
535
-: **-jobs**
536
- By default, **tovid disc** starts a parallel job for each processor
537
- detected. With this option you can manually set the number of jobs. For
538
- example if you have a computer with 2 CPUs you can set "-jobs 1" to keep
539
- one processor free for other things. At present this applies to the time
540
- consuming imagemagick loops: you will notice a substantial speedup now if
541
- you have a multi-cpu system.
542
-: **-no-ask**, **-noask**
543
- Skip all interactive questions. No preview, automatic re-encoding with
544
- tovid if needed, no interactive option to use background video for bgaudio.
545
-: **-no-warn**, **-nowarn**
546
- Don't pause after outputting warning or info messages
547
-: **-grid**
548
- Show a second preview image with a grid and numbers that will help in finding
549
- coordinates for options that might use them, like **-text-start**
550
551
552
==Menu Style==
553
554
Move menu title by this offset from its N|S|E|W|Center position. You
555
may need to use -align as well if you don't want your title covering other
556
parts of your menu. See **-align**
557
-: **-button-style** rect|text|line|text-rect
558
+: **-button-style** line|rect|text|text-rect [line]
559
The style of button that you will see when you play the DVD.
560
- "rect" draws a rectangle around the thumb when you select it
561
- in the DVD player. "text" highlights the video title text, "line"
562
- underlines the title, and "text-rect" draws a rectangle around the title
563
+ "line" style underlines the title, "rect" draws a rectangle around the
564
+ thumb when you select it in the DVD player, "text" highlights the video
565
+ title text, and "text-rect" draws a rectangle around the title
566
text.
567
: **-title-color**, **-title-colour** COLOR
568
Color to use for the main menu title. For list of supported colors do:
569
**convert -list** color. HTML notation may be used: "#ff0000". See:
570
http://www.imagemagick.org/script/color.php
571
: **-title-stroke** COLOR
572
- Outline color for the main menu's title font. Use "none" for transparent
573
- outline (see title-color)
574
+ Shadow color for the main menu's title font. Use "none" for transparent
575
+ outline (see title-color). Note: this is not a -stroke in the sense that
576
+ imagemagick uses the term, but a shadow (the font is drawn twice). To get
577
+ a true imagemagick stroke see **-title-font-deco**
578
+: **-title-font-deco**, **-title-fontdeco** "IMAGEMAGICK STRING"
579
+ Sets the font decoration method to FONTDECORATION. It is used by the 'convert'
580
+ ImageMagick command to draw the menu text. You can add colored text
581
+ outlines, gradient fills, and many others. See **Usage notes**
582
: **-titles-stroke** COLOR
583
- Outline color for the thumb or textmenu video titles font. Use "none" for
584
- transparent outline (see **-titles-color**).
585
+ Shadow color for the thumb or textmenu video titles font. Use "none" for
586
+ transparent outline (see **-titles-color**). Note: this is not a -stroke
587
+ in the sense that imagemagick uses the term, but a shadow
588
+ (the font is drawn twice). To get a true imagemagick stroke,
589
+ see **-titles-font-deco**
590
+: **-titles-font-deco**, **-titles-fontdeco** "IMAGEMAGICK STRING"
591
+ Sets the font decoration method to FONTDECORATION. It is used by the 'convert'
592
+ ImageMagick command to draw the menu text. You can add colored text
593
+ outlines, gradient fills, and others. See **Usage notes** for more info.
594
: **-highlight-color**, **-highlight-colour**
595
Color to use for the menu buttons that your DVD remote uses to navigate.
596
: **-select-color**, **-select-colour**
597
598
Only 4:3 aspect is supported: 16:9 will give unexpected results.
599
600
601
-===Menu Style options specific to showcase and textmenu arrangements===
602
+===Style options specific to showcase/textmenu arrangements===
603
: **-text-start** N
604
This option is for **-textmenu** menus. The titles will start at the Nth
605
pixel from the top of the menu ( Y axis ).
606
607
(default: if used without options, the rotate will be 5 degrees). Note:
608
this will not turn a portait image into a landscape image!
609
: **-showcase-geo** GEOMETRY
610
- The position of the showcase image. ( XxY position )
611
+ The position of the showcase image. ( +X+Y position )
612
+ For example: **-showcase-geo** +300+200
613
: **-wave** default|GEOMETRY
614
Wave effect for showcase image|video. Alters thumbs along a sine wave using
615
GEOMETRY. (default: no wave)
616
617
618
619
==Thumbnail Style==
620
-: **-user-thumbs** IMAGE
621
+: **-user-thumbs** IMAGE(S)
622
Supply your own images for menu buttons, rather than relying on todisc to
623
generate them from the video. They must be the same aspect ratio as the
624
videos in the titleset (4:3 or 16:9), as todisc will resize them without
625
- checking and cropping.
626
+ checking and cropping. There must be on image for each thumb that will be
627
+ displayed on the menu (ie. one thumb for each video in a titleset).
628
: **-opacity** [0-100] (default 100)
629
Opacity of thumbnail videos as a percentage (no percent sign).
630
Anything less than 100(%) is semi-transparent. Not recommended with dark
631
632
The amount of 'feather' blur to apply to the showcase image/video. Choose
633
values between 0.1 and 2.0. This option has no effect on **-3d-showcase**.
634
See **-thumb-blur** for more info.
635
-: **-align** north|south
636
- This will align thumbs/titles north or south.
637
+: **-align** DIRECTION
638
+ This will align thumbs/titles in DIRECTION, which is a compass direction
639
+ as used by imagemagick: ie. north|south|east|west|northeast|northwest etc.
640
If **-align** south then menu title will align north, unless you manually
641
set one or both of **-menu-title-geo** or **-menu-title-offset**.
642
+ Only **-align** north|south|center has any effect on showcase with thumb,
643
+ or with the default montage arrangement of central thumbs. The most
644
+ apparent changes with be with textmenu, though with 2 column arrangements
645
+ only the north* and south* changes will show an effect.
646
+
647
+ Diagram:
648
+: . northwest north northeast .
649
+: . .
650
+: . west center east .
651
+: . .
652
+: . southwest south souteast .
653
: **-thumb-mist** [COLOR]
654
Use a mist behind thumbnails. The optional argument is the color of the
655
mist. This option helps with contrast. Be sure to set the font color
656
657
the **-vmgm** ... **-end-vmgm** options to allow playing ALL titlesets.
658
(If you want also to have a playall button in each titleset you could use
659
this option between each **-titleset** ... **-end-titleset** option or put
660
- it outside of the vmgm and titlset options as a general option.
661
+ it outside of the vmgm and titlset options as a global option.
662
: **-videos-are-chapters**
663
A button will be made on the main menu for each video, which you can use as
664
a chapter button. Selecting any video will play them all in order
665
666
equal the number of grouped videos.
667
668
669
+
670
+==Usage notes==
671
+
672
+The argument given to various *-font options that set the font to use must be
673
+one of the fonts listed by the command 'convert -list type'. Please note that
674
+many of your installed fonts may not be available; if you want to maximize the
675
+number of fonts available to todisc, download and run
676
+[Anthony Thyssen's http://www.cit.gu.edu.au/~anthony/anthony.html]
677
+[imagick_type_gen http://www.imagemagick.org/Usage/scripts/imagick_type_gen]
678
+script and run it like this:
679
+imagick_type_gen > ~/.magick/type.xml.
680
+If that doesn't work, try imagick_type_gen > ~/.magick/type.mgk.
681
+
682
+Or you can specify a ttf font file directly to the *-font options if you don't
683
+want to install fonts to ImageMagick.
684
+
685
+The *-stroke options in todisc are not a stroke in the sense that ImageMagick
686
+uses the term, but rather a font shadow (the text is drawn twice) To get a
687
+truer Imagemagick -stroke try something like:
688
+-title-font-deco "-stroke black" (or -titles-font-deco "-stroke black"). The
689
+**-fontdeco** option is quite flexible and takes a lot of ImageMagick's
690
+//convert// options. Please refer to the tovid
691
+[wiki http://tovid.wikia.com/wiki/Making_a_DVD_with_text_menus] and Anthony
692
+Thyssen's guide [http://www.imagemagick.org/Usage] for further explanation and examples.
693
+
694
+
695
+
696
=Command:mpg=
697
698
**tovid mpg** converts arbitrary video files into (S)VCD/DVD-compliant
699
700
standalone DVD player.
701
702
703
+
704
==Usage==
705
706
**tovid mpg** [//OPTIONS//] **-in** //INFILE// **-out** //OUTPREFIX//
707
708
regularly the progress-meter is updated. The default is once every five
709
seconds.
710
711
-: **-mplayeropts** **"**//OPTIONS//**"**
712
+: **-mplayeropts** //OPTIONS//
713
Append //OPTIONS// to the mplayer command run during video encoding. Use
714
this if you want to add specific video filters (documented in the mplayer
715
manual page). Overriding some options will cause encoding to fail, so use
716
717
Display output in a table format for easier comparison. Most useful
718
when identifying multiple video files.
719
720
+: **-keepfiles**
721
+ Keep temporary directory for debugging.
722
+
723
: **-isformat** [//pal-dvd//|//ntsc-dvd//] (same syntax for vcd and svcd)
724
Check //VIDEO_FILE// for compliance with the given disc format.
725
If //VIDEO_FILE// matches the given format, then **tovid id** reports "true"
726
727
Check to see if homevideo.mpg is compliant with the DVD standard.
728
729
730
-=Command:menu=
731
-
732
-**tovid menu** generates textual (S)VCD- or DVD-compliant MPEG videos for use
733
-as navigational menus, given a list of text strings to use for title names. You
734
-can customize the menu by providing an optional background image or audio clip,
735
-or by using custom font and font color.
736
-
737
-
738
-==Usage==
739
-
740
-**tovid menu** [//OPTIONS//] //TITLES// **-out** //OUT_PREFIX//
741
-
742
-For example:
743
-
744
-: ``tovid menu "Season One" "Season Two" "Featurettes" -out MainMenu``
745
-
746
-
747
-==Options==
748
-
749
-: **-ntsc** (default)
750
- Generate an NTSC-format menu
751
-: **-ntscfilm**
752
- Generate an NTSC-format menu (24000/1001fps)
753
-: **-pal**
754
- Generate a PAL-format menu
755
-: **-dvd** (default)
756
- Generate a DVD-format menu, with highlighted text included
757
- as a multiplexed subtitle stream.
758
-: **-vcd**
759
-: **-svcd**
760
- Generate a VCD/SVCD menu; each menu option will have a
761
- number associated with it. You can have up to nine menu
762
- options per menu.
763
-
764
-
765
-Menu background/audio options:
766
-
767
-: **-background** //IMAGE//
768
- Use //IMAGE// (in most any graphic format) as a background. If image is not
769
- the correct aspect ratio (4:3), it will be scaled and/or cropped,
770
- depending on the **-crop** and **-scale** options. If no background is
771
- supplied, a default background will be created.
772
-
773
-: **-crop** (default)
774
- If provided background image is not 4:3 aspect ratio, crop edges
775
- to make it so. Image will be scaled up if it is too small. Cropping
776
- keeps the center area of image. If you want to do cropping/scaling
777
- yourself in another program, provide an image of 768x576 pixels.
778
-
779
-: **-scale**
780
- If provided background image is not 4:3 aspect ratio, scale/stretch
781
- it to make it fit. May cause visible distortion!
782
-
783
-: **-audio** //AUDIOFILE//
784
- Use //AUDIOFILE// (in most any audio format) for background music. The
785
- menu will play for long enough to hear the whole audio clip. If
786
- one is not provided, 4 seconds of silence will be used.
787
-
788
-: **-length** //NUM//
789
- Make the menu //NUM// seconds long. Useful for menus with **-audio**:
790
- if you don't want the entire //AUDIOFILE// in the menu, then you can trim
791
- the length of the menu with **-length**.
792
-
793
-
794
-Menu text options:
795
-
796
-: **-menu-title** **"**//MENU TITLE TEXT//**"**
797
- Add //MENU TITLE TEXT// as a title/header to the menu.
798
-
799
-: **-font** //FONTNAME// (default Helvetica)
800
- Use //FONTNAME// for the menu text. Run 'convert -list type' to see a
801
- list of the fonts that you can use; choose a font name from the
802
- leftmost column that is displayed. Or you can specify a ttf font file instead.
803
- E.g., '-font /path/to/myfont.ttf'.
804
-
805
-: **-fontsize** //NUM// (default 24)
806
- Sets the size for the font to //NUM// pixels.
807
-
808
-: **-menu-title-fontsize** //NUM// (default **-fontsize** + 8)
809
- Sets the size of the menu title.
810
-
811
-: **-fontdeco** **'**//FONTDECORATION//**'**
812
- Sets the font decoration method to //FONTDECORATION//. It is used by the
813
- 'convert' ImageMagick command to draw the menu text. You can add colored
814
- text outlines, gradient fills, and many others. See **Usage notes**.
815
-
816
-: **-align** {**left**|**center**|**middle**|**right**}
817
- Align the text at the top left, top center, very middle, or top right
818
- side of the screen. You may also substitute any "gravity" keyword
819
- allowed by ImageMagick (north|south|east|west|northeast|southwest|...).
820
-
821
-: **-textcolor** {**#**//RRGGBB//|**#**//RGB//|//COLORNAME//}
822
- Use specified color for menu text. #//RRGGBB// and #//RGB// are
823
- hexadecimal triplets (e.g., #FF8035). //COLORNAME// may be any of
824
- several hundred named colors; run 'convert -list color' to see them.
825
- White (#FFF) is the default color.
826
-
827
-
828
-DVD-only options:
829
-
830
-: **-button** //BUTTON// (default '>')
831
- Specify the button used for menu selection. Specify either a _single_
832
- character or one of the shortcuts:
833
- - **play** -- Use a button shaped like 'Play' on many A/V electronics:
834
- a triangle pointing to the right. (uses the font Webdings)
835
- - **movie** -- Use a button shaped like an old movie projector.
836
- (uses the font Webdings)
837
- - **utf8** -- Use your own non-keyboard character as a button. Provide
838
- only the four hex digits: eg '-button utf8 00b7'. Beware that
839
- ImageMagick's utf8 characters aren't the same as those drawn in
840
- character browsers like gucharmap.
841
-
842
-
843
-: **-highlightcolor** {**#**//RRGGBB//|**#**//RGB//|//COLORNAME//}
844
- Use the specified color for button highlighting. Yellow (#FF0) is the
845
- default color.
846
-
847
-: **-selectcolor** {**#**//RRGGBB//|**#**//RGB//|//COLORNAME//}
848
- Use the specified color for button selections (when a menu item is played
849
- or activated). Red (#F00) is the default color.
850
-
851
-: **-button-outline** {**#**//RRGGBB//|**#**//RGB//|//COLORNAME//}
852
- Outline buttons with the specified color. 'none' is the default.
853
-
854
-: **-button-font** //FONTNAME//
855
- Specify a differnt font to use for the buttons. By default, the button
856
- font will be inherited from the title font (see **-font**). Use this
857
- option to use a different font for the buttons. The button font size is
858
- inherited from **-fontsize** and cannot be changed.
859
-
860
-
861
-Other options:
862
-
863
-: **-debug**
864
- Print extra debugging information to the log file. Useful in
865
- diagnosing problems if they occur. This option also leaves
866
- the log file (with a .log extension) in the directory after
867
- encoding finishes as well as all the temporary files created.
868
-
869
-: **-nosafearea**
870
- Do not attempt to put text inside a TV-safe viewing area. Most
871
- television sets cut off about 10% of the image border, so the script
872
- automatically leaves a substantial margin. This option turns that
873
- behavior off, leaving only a tiny margin. Use at your own risk.
874
-
875
-: **-overwrite**
876
- Overwrite any existing output menu.
877
-
878
-: **-noask**
879
- Don't ask interactive questions, and assume answers that will
880
- continue making the menu until completion.
881
-
882
-: **-quiet**
883
- Limit output to essential messages.
884
-
885
-
886
-If the word "**back**" is given as an episode title, a "back" button for
887
-returning to a higher-level menu will be added at the end of the list
888
-of titles. "**Back**" //must be the last title listed//.
889
-
890
-
891
-==Examples==
892
-
893
-Make an NTSC VCD menu with white Helvetica text containing three centered
894
-selections: Episode 1, Episode 2, and Episode 3. The finished menu will be
895
-called Season-1.mpg:
896
-
897
-```
898
-tovid menu -ntsc -vcd \
899
- -align center -textcolor white -font "Helvetica" \
900
- "Episode 1" "Episode 2" "Episode 3" \
901
- -out "Season-1"
902
-```
903
-
904
-Make an NTSC DVD menu with white Kirsty text containing three lower-left
905
-aligned selections: Episode 1, Episode 2, and Episode 3. Items under the cursor
906
-will be highlighted a pale blue, and selected items will be a pale orange
907
-(before going to the selected title). The finished menu will be called
908
-Main-menu.mpg:
909
-
910
-```
911
-tovid menu -ntsc -dvd \
912
- -align southwest \
913
- -textcolor white \
914
- -highlightcolor "#5f65ff" \
915
- -selectcolor "#ffac5f" \
916
- -font "Kirsty" \
917
- "Episode 1" "Episode 2" "Episode 3" \
918
- -out "Main_menu"
919
-```
920
-
921
-
922
-
923
-==Usage notes==
924
-
925
-The argument given to **-font** must be one of the fonts listed
926
-by the command 'convert -list type'. Please note that many of
927
-your installed fonts may not be available; if you want to maximize the
928
-number of fonts available, download and run
929
-[Anthony Thyssen's http://www.cit.gu.edu.au/~anthony/anthony.html]
930
-[imagick_type_gen.pl http://www.cit.gu.edu.au/~anthony/software/imagick_type_gen.pl]
931
-script and run it like this:
932
-imagick_type_gen.pl > ~/.magick/type.xml.
933
-If that doesn't work, try
934
-imagick_type_gen.pl > ~/.magick/type.mgk.
935
-
936
-Or you can specify a ttf font file directly to the **-font** options if you
937
-don't want to install fonts to ImageMagick.
938
-
939
-The **-fontdeco** option is quite flexible and takes a lot of ImageMagick's
940
-//convert// options. Please refer to the tovid
941
-[wiki http://tovid.wikia.com/wiki/Making_a_DVD_with_text_menus]
942
-and Anthony Thyssen's guide for further explanation and examples.
943
-
944
-
945
-=Command:xml=
946
-
947
-**tovid xml** generates XML output describing an (S)VCD
948
-or DVD file structure and navigation hierarchy in the format expected by
949
-[dvdauthor http://dvdauthor.sourceforge.net/] or
950
-[vcdxbuild http://www.vcdimager.org/].
951
-
952
-
953
-==Usage==
954
-
955
-**tovid xml** [//OPTIONS//] //VIDEOS// -out //OUTFILE//
956
-
957
-For example:
958
-
959
-```
960
-$ tovid xml -menu MainMenu.mpg \
961
- Season1.mpg Season2.mpg Featurettes.mpg \
962
- -out MyDisc
963
-```
964
-
965
-
966
-==Options==
967
-
968
-: **-dvd** (default)
969
- Generate the XML for a DVD disc, to be used with dvdauthor or **tovid dvd**.
970
-: **-vcd**
971
- Generate the XML for a VCD disc, to be used with vcdxbuild or **tovid vcd**.
972
-: **-svcd**
973
- Generate the XML for an SVCD disc, to be used with vcdxbuild or **tovid vcd**.
974
-: **-overwrite**
975
- Overwrite any existing output files.
976
-: **-quiet**
977
- Limit output to essential messages.
978
-
979
-
980
-//VIDEOS// may be any of the following:
981
-
982
-: //<file list>//
983
- List of one or more video files to include, separated by spaces. At
984
- minimum, a DVD must have one video file. You can use shell wildcards
985
- (i.e., "*.mpg") to include multiple files easily. Put filenames in
986
- quotes if they have spaces in them.
987
-
988
-: **-menu** //VIDEO// //<file list>//
989
- Use video file //VIDEO// as a menu from which you can jump to each of
990
- the listed video files. If you have multiple menus, include a
991
- top menu so they are reachable.
992
-
993
-: **-slides** //<file list>//
994
- Create a slide-show of still images
995
-
996
-
997
-DVD-only options
998
-
999
-: **-group** //<file list>// **-endgroup**
1000
- (DVD only) List of video files to include as one single title. This is useful
1001
- if you have split a movie into several video files.
1002
-
1003
-: **-topmenu** //VIDEO// [**-menu** //VIDEO// //<file list>//] [**-menu** //VIDEO// //<file list>//]...
1004
- (DVD only) Use video file //VIDEO// for the top-level (VMGM) menu. The
1005
- top menu will jump to each of the subsequent [-menu...] videos listed.
1006
- Use this only if you have multiple sub-menus to jump to. You can only
1007
- have one top menu.
1008
-
1009
-: **-titlesets**
1010
- (DVD only) Forces the creation of a separate titleset per title. This
1011
- is useful if the titles of a DVD have different video formats,
1012
- e.g. PAL + NTSC or 4:3 + 16:9. If used with menus, there must be a
1013
- **-topmenu** option that specifies a menu file with an entry for each of the
1014
- titlesets.
1015
-
1016
-: **-chapters** //INTERVAL//
1017
- (DVD only) Creates a chapter every //INTERVAL// minutes (default 5 minutes:
1018
- without **-chapters**, each movie will be divided into 5-minute chapters).
1019
- This option can be put at any position in a //<file list>// and is valid
1020
- for all subsequent titles until a new **-chapters** option is encountered.
1021
- Using this option may take some time, since the duration of the video is
1022
- calculated.
1023
-
1024
-: **-nochapters**
1025
- (DVD only) Don't create chapters for the videos.
1026
-
1027
-
1028
-//OUT_PREFIX// is the file that will receive the resulting XML.
1029
-
1030
-
1031
-==Usage notes==
1032
-
1033
-The 'xml' command checks to make sure the video filenames you
1034
-give it exist, but it does not check whether they are valid for the
1035
-chosen disc format. MPEG videos of menus should have the specified
1036
-number of buttons for reaching each of the videos, and, if you're
1037
-using DVD, should be multiplexed with their corresponding subtitles
1038
-using spumux of the dvdauthor 0.6.0 package prior to
1039
-authoring using dvdauthor. If you use the 'tovid menu'
1040
-component to generate the menu, this should all be handled for you.
1041
-
1042
-
1043
-==Examples==
1044
-
1045
-: ``tovid xml -dvd title-1.mpg title-2.mpg title-3.mpg -out My_DVD``
1046
- Make a DVD without a menu. Title 1, 2, and 3 will play in sequence.
1047
-
1048
-: ``tovid xml -dvd -group chapter-1.mpg chapter-2.mpg chapter-3.mpg -endgroup -out My_DVD``
1049
- Group the file chapter-1|2|3.mpg into one title and make a DVD without a menu.
1050
-
1051
-: ``tovid xml -dvd -menu main_menu.mpg -chapters 3 movie-1.mpg -chapters 10 movie-2.mpg -out My_DVD``
1052
- Make a DVD with a main menu that points to two movies, with movie-1.mpg
1053
-divided into 3-minute chapters, and movie-2.mpg into 10-minute chapters.
1054
-
1055
-
1056
1057
=Command:dvd=
1058
1059
-**tovid dvd** takes a dvdauthor XML file (as generated by the **tovid xml**
1060
-command) and authors a DVD filesytem. This command can also burn a DVD disc
1061
-from either the XML file or from an existing DVD file-system.
1062
+**tovid dvd** takes a DVD directory as generated by tovid with 'tovid disc' or
1063
+one of the GUI frontends like 'tovid gui' or 'tovid titlesets' and burns
1064
+it to appropriate media. This will also work if the DVD directory is
1065
+generated by the dvdauthor backend that tovid also uses.
1066
1067
-To ensure that this script successfully executes, please run it from a
1068
-directory with plenty of free space. "Plenty" would be 10 GB for single-layer
1069
-discs, and 20 GB for dual-layer discs. Running this program may slow down your
1070
-other applications, due to intense disk activity.
1071
+Running this program may slow down your other applications, due to intense
1072
+disk activity.
1073
1074
1075
==Usage==
1076
1077
-**tovid dvd** [//OPTIONS//] //FILE.xml//
1078
1079
**tovid dvd** [//OPTIONS//] //DVD_DIR//
1080
1081
For example:
1082
1083
-: ``tovid dvd -burn MyDisc.xml``
1084
-: ``tovid dvd -burn /path/to/DVD/directory``
1085
+: ``tovid dvd /path/to/DVD/directory``
1086
1087
1088
==Options==
1089
1090
-: **-author**
1091
- Author the DVD described by //FILE.xml//. Overwrites an existing
1092
- directory containing the dvdauthor output if already present.
1093
-
1094
: **-burn**
1095
Burn a DVD file-system in //DVD_DIR// (must contain a VIDEO_TS folder).
1096
+ This option is currently not necessary as the makedvd script ONLY burns
1097
+ now that legacy scripts like makexml have been removed. Left for
1098
+ compatibility only.
1099
1100
: **-eject**
1101
Eject the DVD tray after burning is complete. By default, the DVD is not
1102
1103
execution.
1104
1105
1106
-==Examples==
1107
-
1108
-: ``tovid dvd -burn -device /dev/dvdrw foo.xml``
1109
- Author the dvd file-system and burn to /dev/dvdrw. This will
1110
- automatically call dvdauthor to make the file-system. **-author**
1111
- is not explicitly needed. If there's an existing file-system, it
1112
- will be burned.
1113
-
1114
-: ``tovid dvd -author foo.xml``
1115
- Author the DVD file-system and exit without burning. If the output
1116
- directory given in foo.xml already exists, then the contents are
1117
- removed before authoring. At this point, the DVD can be previewed
1118
- by calling //**xine** dvd:/path/to/output/directory//.
1119
-
1120
-
1121
-=Command:vcd=
1122
-
1123
-**tovid vcd** takes an XML file (which may be generated by **tovid xml**) and
1124
-creates a cue/bin (S)VCD image. It can also burn (S)VCD discs.
1125
-
1126
-To ensure that this script successfully executes, please run it from a directory
1127
-with plenty of free space. "Plenty" would be about 1 GB. Running this program
1128
-may slow down your other applications, due to intense disk activity.
1129
-
1130
-
1131
-==Usage==
1132
-
1133
-**tovid vcd** [//OPTIONS//] //VCDIMAGER.xml//
1134
-
1135
-For example:
1136
-
1137
-: ``tovid vcd -burn MyDisc.xml``
1138
-
1139
-
1140
-==Options==
1141
-
1142
-: **-overwrite** (default off -- nothing is overwritten)
1143
- Overwrite any existing cue/bin files matching //VCDIMAGER.xml//. Useful
1144
- if you modified the xml file and wish to re-image or burn the new (S)VCD.
1145
-
1146
-: **-burn** (default off -- no images are burned)
1147
- Burn the (S)VCD described by //VCDIMAGER.xml//.
1148
-
1149
-: **-device** //DEVICE// (default /dev/cdrw)
1150
- Burn the disc image to //DEVICE//, the Linux device file-system
1151
- name of your CD-recorder. Common examples might be /dev/cdrw,
1152
- /dev/scd1, and /dev/hdc.
1153
-
1154
-: **-speed** //NUM// (default 12)
1155
- Burn the disc at speed //NUM//.
1156
-
1157
-: **-quiet**
1158
- Limit output to essential messages.
1159
-
1160
-
1161
-==Examples==
1162
-
1163
-: ``tovid vcd -burn -device /dev/cdrw foo.xml``
1164
- Create the (S)VCD image and burn it to /dev/cdrw. This will
1165
- automatically call vcdxbuild to make the image. If there is an existing
1166
- image, it will be burned.
1167
-
1168
-: ``tovid vcd -overwrite foo.xml``
1169
- Create the (S)VCD image and exit without burning. If the image
1170
- already exists, then it is removed before re-imaging.
1171
-
1172
-
1173
-
1174
-=Command:postproc=
1175
-
1176
-**tovid postproc** is designed to do simple post-processing on MPEG video files, such
1177
-as those generated by tovid. It can adjust audio/video sync, and re-quantize
1178
-(shrink) without re-encoding.
1179
+ After burning, the DVD can be previewed by calling:
1180
+ //**xine** dvd:/path/to/output/directory//
1181
+ or:
1182
+ //**vlc** /path/to/output/directory//
1183
1184
1185
-==Usage==
1186
-
1187
-**tovid postproc** [//OPTIONS//] //IN_FILE// //OUT_FILE//
1188
-
1189
-
1190
-==Options==
1191
-
1192
-: **-audiodelay** //NUM//
1193
- Delay the audio stream by //NUM// milliseconds. Use this if
1194
- your final output has audio that is not synced with the
1195
- video. For example, if the audio comes 2 seconds sooner than
1196
- the video, use "-audiodelay 2000". Use a negative number for
1197
- audio that comes later than the video.
1198
-
1199
-: **-normalize**
1200
- Analyze the audio stream and then normalize the volume of the audio.
1201
- This is useful if the audio is too quiet or too loud, or you want to
1202
- make volume consistent for a bunch of videos. Similar to running
1203
- normalize without any parameters. The default is -12dB average level
1204
- with 0dB gain.
1205
-
1206
-: **-amplitude** //NUM//[dB]
1207
- In addition to analyzing and normalizing, apply the gain to the audio
1208
- such that the 'average' (RMS) sound level is //NUM//. Valid values
1209
- range 0.0 - 1.0, with 0.0 being silent and 1.0 being full scale. Use
1210
- //NUM//dB for a decibel gain below full scale (the default without
1211
- -amplitude is -12dB).
1212
-
1213
-: **-shrink** //NUM//
1214
- Shrink the video stream by a factor of //NUM//. May be a decimal
1215
- value. A value of 1.0 means the video will be the same size;
1216
- larger values cause more reduction in size. Beyond 2.0, the
1217
- returns are diminishing.
1218
-
1219
-: **-parallel**
1220
- Run all processes in parallel and pipe into multiplexer, should
1221
- increase speed significantly.
1222
-
1223
-: **-debug**
1224
- Save output in a temporary file, for later viewing if
1225
- something goes wrong.
1226
-
1227
1228
=Command:chapters=
1229
1230
**tovid chapters** will start a GUI using mplayer to set chapter points in a
1231
-video. Its only (mandatory) option is the path to a video file.
1232
+video. If the video plays through and you want to add more chapters you can
1233
+press the play button again, but remember that new chapter points will be
1234
+appended (in correct sequential order). It will display the resulting chapter
1235
+points, and also output to a terminal (useful for scripts). As well it will
1236
+give the option of saving the chapters string to a text file.
1237
+
1238
+Note that the 'tovid gui' now features a similar widget when you press the
1239
+chapters button on the opening page.
1240
1241
==Examples==
1242
: ``tovid chapters foo.avi``
1243
1244
-: ``tovid chapters /home/grepper/videos/foo.avi``
1245
+: ``chapters=$(tovid chapters /home/grepper/videos/foo.avi)``
1246
1247
1248
=CONTACT=
1249
tovid-0.34.tar.bz2/libtovid/__init__.py -> tovid-0.35.tar.gz/libtovid/__init__.py
Changed
49
1
2
3
__all__ = [
4
# Subdirectories
5
- 'backend',
6
- 'gui',
7
'guis',
8
'metagui',
9
- 'render',
10
- 'template',
11
- 'test',
12
- 'util',
13
# .py files
14
- 'author',
15
'cli',
16
- 'deps',
17
- 'encode',
18
'odict',
19
- 'opts',
20
- 'rip',
21
- 'standard',
22
- 'stats',
23
'utils',
24
- 'xml',
25
]
26
27
import os
28
+from sys import version_info
29
30
# Python < 3.x
31
try:
32
33
except ImportError:
34
from configparser import ConfigParser
35
36
+# Python 3.x compatibility assignments
37
+if version_info[0] < 3: # python 3.x
38
+ unicode = unicode
39
+ basestring = basestring
40
+ xrange = xrange
41
+else: # Python 3.x
42
+ unicode = str
43
+ basestring = str
44
+ xrange = range
45
+
46
# Configuration file reader/writer
47
class Config (ConfigParser):
48
"""Interface for reading/writing tovid configuration files. Just a wrapper
49
tovid-0.34.tar.bz2/libtovid/cli.py -> tovid-0.35.tar.gz/libtovid/cli.py
Changed
16
1
2
import subprocess
3
import signal
4
import os
5
-
6
# Small workaround for Python 3.x
7
-try:
8
- _temp = unicode
9
-except NameError:
10
- unicode = str
11
+from libtovid import unicode, basestring
12
+
13
14
class ProgramNotFound (ValueError):
15
"""Raised when the program given to a command is not available.
16
tovid-0.34.tar.bz2/libtovid/guis/helpers.py -> tovid-0.35.tar.gz/libtovid/guis/helpers.py
Changed
994
1
2
-import Tkinter as tk
3
import time
4
import shlex
5
-import commands
6
import re
7
import os
8
import fnmatch
9
from libtovid.metagui import *
10
from libtovid.metagui.control import _SubList
11
from libtovid.util import filetypes
12
-from subprocess import Popen, PIPE, STDOUT
13
-from tempfile import mkdtemp
14
+from subprocess import Popen, PIPE
15
+from tempfile import mkdtemp, mkstemp
16
+from sys import stdout
17
+
18
+try:
19
+ from commands import getstatusoutput, getoutput
20
+ import Tkinter as tk
21
+except ImportError:
22
+ # python 3
23
+ from subprocess import getstatusoutput, getoutput
24
+ import tkinter as tk
25
26
__all__ = [ 'VideoGui', 'SetChapters', 'Chapters', 'strip_all', 'to_title',
27
'find_masks', 'nodupes', 'video_filetypes', 'image_filetypes',
28
'visual_filetypes', 'dvd_video_files', 'av_filetypes', 'sys_dir',
29
'thumb_masks', 'home_dir', 'tovid_prefix', 'tovid_icon', 'os_path',
30
-'heading_text', '_files_and_titles', '_out' ]
31
+'heading_text', '_files_and_titles', '_out', 'CopyableInfo' ]
32
+
33
34
class VideoGui(tk.Frame):
35
"""A basic GUI to play video files. It runs mplayer in slave mode
36
37
Without subclassing it only contains a 'play/pause button
38
and an 'exit' button.
39
"""
40
- def __init__(self, master, args='', title='', callback=None, style='popup'):
41
+ def __init__(self, master, args='', title='', callback=None):
42
"""Initialize GUI
43
44
master
45
46
the wm title given to the master widget.
47
callback
48
a function run at program exit, before cleanup of temp files
49
- style
50
- may be one of 'popup' (default), 'standalone', or 'embedded'(TBA)
51
"""
52
tk.Frame.__init__(self, master)
53
54
55
try:
56
self.master.title(title)
57
except AttributeError:
58
- print "Error: " + \
59
- "VideoGui master must be a root window for 'title' option"
60
+ print("Error: " + \
61
+ "VideoGui master must be a root window for 'title' option")
62
self.callback = callback
63
- self.style = style
64
-
65
+ self.v_width = 540
66
+ self.v_height = 405
67
self.is_running = tk.BooleanVar()
68
self.is_running.set(False)
69
self.pauseplay = tk.StringVar()
70
- self.pauseplay.set('play')
71
+ self.pauseplay.set('Play')
72
# temporary directory for fifo and other mplayer files
73
+ self.make_tmps()
74
+ self.draw()
75
+
76
+ def make_tmps(self):
77
+ """Make temporary directory containing fifo for mplayer commmands,
78
+ editlist, and log
79
+ """
80
self.tempdir = mkdtemp(prefix='tovid-')
81
self.cmd_pipe = os.path.join(self.tempdir, 'slave.fifo')
82
self.editlist = os.path.join(self.tempdir, 'editlist')
83
os.mkfifo(self.cmd_pipe)
84
self.log = os.path.join(self.tempdir, 'mplayer.log')
85
- self.draw()
86
-
87
+
88
def draw(self):
89
"""Draw the GUI in self.master and get X11 identifier for container"""
90
self.root_frame = tk.Frame(self)
91
self.root_frame.pack(side='top', fill='both', expand=1, pady=20)
92
self.container = tk.Frame(self.root_frame, bg='black', container=1, colormap='new')
93
+ self.container.configure(width=self.v_width, height=self.v_height, bg='black')
94
self.container.pack()
95
# X11 identifier for the container frame
96
self.xid = self.tk.call('winfo', 'id', self.container)
97
- # bindings for exit
98
- if self.style == 'standalone':
99
- self._root().protocol("WM_DELETE_WINDOW", self.confirm_exit)
100
- self._root().bind('<Control-q>', self.confirm_exit)
101
self.add_widgets()
102
103
def add_widgets(self):
104
- """
105
- Add buttons to the VideoGui. Override this to customize buttons.
106
+ """Add buttons to the VideoGui. Override this to customize buttons.
107
root_frame has 'grab_set()' applied to it so make sure widgets go
108
into this frame or they will not be functional!
109
This function is called in draw()
110
"""
111
button_frame = tk.Frame(self.root_frame)
112
button_frame.pack(side='bottom', fill='x', expand=1)
113
- control_frame = tk.Frame(button_frame, borderwidth=1, relief='groove')
114
- control_frame.pack()
115
- exit_button = tk.Button(control_frame, command=self.exit_mplayer, text='exit')
116
- pause_button = tk.Button(control_frame, command=self.pause,
117
+ self.control_frame = tk.Frame(button_frame, borderwidth=1, relief='groove')
118
+ self.control_frame.pack()
119
+ self.load_button = tk.Button(self.control_frame,
120
+ command=self.load, text='load video')
121
+ self.load_button.pack(side='left')
122
+ exit_button = tk.Button(self.control_frame, command=self.exit_mplayer, text='exit')
123
+ self.pause_button = tk.Button(self.control_frame, command=self.pause,
124
width=12, textvariable=self.pauseplay)
125
- exit_button.pack(side='left')
126
- pause_button.pack(side='left')
127
+ self.pause_button.pack(side='left')
128
+ exit_button.pack(side='left', padx=5)
129
+ self.mp_ctrls = [self.pause_button]
130
+ self.toggle_controls('disabled', self.mp_ctrls)
131
132
133
def identify(self, video):
134
- """
135
- Get information about video from mplayer -identify.
136
+ """Get information about video from mplayer -identify.
137
Called by set_container()
138
"""
139
140
- output = commands.getoutput('mplayer -vo null -ao null -frames 5 \
141
- -channels 6 -identify %s' %video)
142
- return output
143
+ cmd = 'mplayer -vo null -ao null -frames 5 -channels 6 -identify'
144
+ cmd = shlex.split(cmd) + [video]
145
+ output = Popen(cmd, stdout=PIPE, stderr=PIPE)
146
+ return output.communicate()[0]
147
148
- def set_container(self, video):
149
+ def load(self, event=None):
150
+ """Load a file to play in the GUI"""
151
+ try:
152
+ from tkFileDialog import askopenfilename
153
+ except ImportError:
154
+ # python 3
155
+ from tkinter.filedialog import askopenfilename
156
+ vid_name = askopenfilename()
157
+ if vid_name:
158
+ self.toggle_controls('normal', self.mp_ctrls)
159
+ if self.pauseplay.get() == 'Pause':
160
+ self.pauseplay.set('Play')
161
+ self.run(vid_name)
162
+
163
+ def set_container(self, video=None):
164
"""Get aspect ratio and set dimensions of video container.
165
Called by run().
166
"""
167
- if self.style == 'standalone':
168
- v_width = 600
169
- else:
170
- v_width = 540
171
media_info = self.identify(video)
172
- asr = re.findall('ID_VIDEO_ASPECT=.*', media_info)
173
+ asr = re.findall('ID_VIDEO_ASPECT=.*', str(media_info))
174
# get last occurence as the first is 0.0 with mplayer
175
if asr:
176
asr = sorted(asr, reverse=True)[0].split('=')[1]
177
- try:
178
- asr = float(asr)
179
- except ValueError:
180
- asr = 0.0
181
+ try:
182
+ asr = float(asr)
183
+ except ValueError:
184
+ asr = 0.0
185
# get largest value as mplayer prints it out before playing file
186
if asr and asr > 0.0:
187
- v_height = int(v_width/asr)
188
+ v_height = int(self.v_width/asr)
189
else:
190
# default to 4:3 if identify fails
191
- v_height = int(v_width/1.333)
192
- self.container.configure(width=v_width, height=v_height)
193
+ v_height = int(self.v_width/1.333)
194
+ self.container.configure(width=self.v_width, height=v_height)
195
196
def run(self, video):
197
"""Play video in this GUI using mplayer."""
198
+ if video == None:
199
+ self.toggle_controls('disabled', self.mp_ctrls)
200
+ return
201
+ elif not os.path.exists(video):
202
+ try:
203
+ from tkMessageBox import showerror
204
+ except ImportError:
205
+ from tkinter.messagebox import showerror
206
+ showerror('Oops', video + ' does not exist')
207
+ self.toggle_controls('disabled', self.mp_ctrls)
208
+ self.master.master.withdraw()
209
+ else:
210
+ self.toggle_controls('enabled', self.mp_ctrls)
211
+ # a new video has been loaded if no temp files, so make them
212
+ if not os.path.exists(self.tempdir):
213
+ self.make_tmps()
214
+ # set the container size, then run the video
215
self.set_container(video)
216
command = 'mplayer -wid %s -nomouseinput -slave \
217
-input nodefault-bindings:conf=/dev/null:file=%s \
218
- -edlout %s %s %s' \
219
- %(self.xid, self.cmd_pipe, self.editlist, self.args, video)
220
- self.command = shlex.split(command)
221
+ -edlout %s %s' \
222
+ %(self.xid, self.cmd_pipe, self.editlist, self.args)
223
+ self.command = shlex.split(command) + [video]
224
+
225
+ def toggle_controls(self, state, widgets):
226
+ """
227
+ Enable/disable mplayer control widgets
228
+ state is either 'normal' or 'disabled', widgets is an instance list
229
+ """
230
+ for widget in widgets:
231
+ try:
232
+ widget.configure(state=state)
233
+ except tk.TclError:
234
+ pass
235
236
def poll(self):
237
"""
238
239
"""
240
if not self.is_running.get():
241
return
242
- tail = 'tail -n 1 %s' %self.log
243
- log_output = commands.getoutput(tail)
244
- # restart mplayer with same commands if it exits without being sent
245
- # an explict 'quit'.
246
- if '(End of file)' in log_output:
247
- self.on_eof()
248
- # check for is_running again as on_oef() might set it to false
249
- if self.is_running.get():
250
- cmd = Popen(self.command, stderr=open(os.devnull, 'w'), \
251
- stdout=open(self.log, "w"))
252
- if self.show_osd:
253
- self.send('osd 3\n')
254
- self.pause()
255
- self.master.after(200, self.poll)
256
+ f = open(self.log, 'r')
257
+ # seek to 50 bytes from end of file
258
+ try:
259
+ f.seek(-50, 2)
260
+ if '(End of file)' in f.read():
261
+ self.on_eof()
262
+ # check for is_running again as on_oef() might set it to false
263
+ if self.is_running.get():
264
+ cmd = Popen(self.command, stderr=open(os.devnull, 'w'), \
265
+ stdout=open(self.log, "w"))
266
+ if self.show_osd:
267
+ self.send('osd 3')
268
+ self.pause()
269
+ # if file does not contain 50 bytes, do nothing
270
+ except IOError:
271
+ pass
272
+ self.master.after(100, self.poll)
273
+
274
275
def on_eof(self):
276
"""
277
278
pass
279
280
def send(self, text):
281
- """send command to mplayer's slave fifo"""
282
+ """Send command to mplayer's slave fifo"""
283
if self.is_running.get():
284
- commands.getstatusoutput('echo -e "%s" > %s' %(text, self.cmd_pipe))
285
+ getstatusoutput('echo "%s" > %s' %(text, self.cmd_pipe))
286
287
def pause(self):
288
- """send pause to mplayer via slave and set button var to opposite value"""
289
+ """Send pause to mplayer via slave and set button var to opposite value"""
290
# mplayer's 'pause' pauses if playing and plays if paused
291
- # pauseplay ==play in pause mode, and ==pause in play mode (button text)
292
+ # pauseplay ==Play in pause mode, and ==Pause in play mode (button text)
293
if self.is_running.get():
294
- if self.pauseplay.get() == 'pause':
295
- self.pauseplay.set('play')
296
+ if self.pauseplay.get() == 'Pause':
297
+ self.pauseplay.set('Play')
298
else:
299
- self.pauseplay.set('pause')
300
- self.send('pause\n')
301
+ self.pauseplay.set('Pause')
302
+ self.send('pause')
303
else:
304
# start the video for the 1st time
305
cmd = Popen(self.command, stderr=open(os.devnull, 'w'), stdout=open(self.log, "w"))
306
307
self.poll()
308
# show osd time and remaining time
309
if self.show_osd:
310
- self.send('osd 3\n')
311
- self.pauseplay.set('pause')
312
+ self.send('osd 3')
313
+ self.pauseplay.set('Pause')
314
315
- def exit_mplayer(self):
316
+ def exit_mplayer(self): # called by [done] button
317
"""
318
Close mplayer if it is running, then exit, running callback if it exists
319
"""
320
# unpause so mplayer doesn't hang
321
if self.is_running.get():
322
- if self.pauseplay.get() == 'play':
323
- self.send('mute 1\n')
324
- self.send('pause\n')
325
- self.send('quit\n')
326
+ if self.pauseplay.get() == 'Play':
327
+ self.send('mute 1')
328
+ self.send('pause')
329
+ self.send('quit')
330
self.is_running.set(False)
331
time.sleep(0.3)
332
self.confirm_exit()
333
334
+ def confirm_msg(self):
335
+ mess = "osd_show_text 'please exit mplayer first' 4000 3"
336
+ if not self.show_osd:
337
+ self.send('osd 3\n%s' %mess)
338
+ self.after(2500, lambda:self.send('osd 0'))
339
+ else:
340
+ self.send(mess)
341
+
342
def confirm_exit(self, event=None):
343
- """on exit, make sure that mplayer is not running before quit"""
344
+ """On exit, make sure that mplayer is not running before quit"""
345
if self.is_running.get():
346
- mess = "osd_show_text 'please exit mplayer first' 4000 3\n"
347
- if not self.show_osd:
348
- self.send('osd 3\n%s' %mess)
349
- self.after(2500, lambda:self.send('osd 0\n'))
350
- else:
351
- self.send(mess)
352
+ self.confirm_msg()
353
else:
354
# run any custom commands on exit
355
if callable(self.callback):
356
357
os.remove(f)
358
if os.path.exists(self.tempdir):
359
os.rmdir(self.tempdir)
360
- if self.style == 'standalone':
361
- self.quit()
362
- else:
363
- self.destroy()
364
+ self.quit()
365
+
366
+ def quit(self):
367
+ """Quit the application. This detroys the root window, exiting Tkinter"""
368
+ self.destroy()
369
370
371
class SetChapters(VideoGui):
372
- """A GUI to set video chapter points using mplayer"""
373
- def __init__(self, master, args='', title='', callback=None, style='popup'):
374
+ """Elements for a GUI to set video chapter points using Mplayer"""
375
+ def __init__(self, master, args='', title='', callback=None):
376
"""
377
master
378
Pack into this widget
379
380
Window manager titlebar title (master must be root window for this)
381
callback
382
Function to run on application exit, run before temp file cleanup
383
- style
384
- Can one of: 'popup' (default), 'standalone', or 'embedded'(TBA)
385
"""
386
- VideoGui.__init__(self, master, args, title, callback, style)
387
-
388
+ VideoGui.__init__(self, master, args, title, callback)
389
self.chapter_var = tk.StringVar()
390
391
def add_widgets(self):
392
+ """
393
+ Add buttons to the Gui. root_frame has 'grab_set()' applied to it so
394
+ make sure widgets go into this frame or they will not be functional!
395
+ This function is called in draw()
396
+ """
397
# button frame and buttons
398
button_frame = tk.Frame(self.root_frame)
399
button_frame.pack(side='bottom', fill='x', expand=1)
400
- control_frame = tk.Frame(button_frame, borderwidth=1, relief='groove')
401
- control_frame.pack()
402
- exit_button = tk.Button(control_frame, command=self.exit_mplayer, text='done !')
403
- mark_button = tk.Button(control_frame, command=self.set_chapter,text='set chapter')
404
- pause_button = tk.Button(control_frame, command=self.pause,
405
+ self.control_frame = tk.Frame(button_frame, borderwidth=1, relief='groove')
406
+ self.control_frame.pack()
407
+ exit_button = tk.Button(self.control_frame, command=self.exit_mplayer, text='done !')
408
+ mark_button = tk.Button(self.control_frame, command=self.set_chapter,text='set chapter')
409
+ pause_button = tk.Button(self.control_frame, command=self.pause,
410
width=12, textvariable=self.pauseplay)
411
- framestep_button = tk.Button(control_frame, text='step >', command=self.framestep)
412
- forward_button = tk.Button(control_frame, text='seek >', command=self.forward)
413
- back_button = tk.Button(control_frame, text='< seek', command=self.back)
414
- # seek frame and scale widget
415
- seek_frame = tk.Frame(self.root_frame)
416
- seek_frame.pack(side='left', fill='x', expand=1, padx=30)
417
- self.seek_scale = tk.Scale(seek_frame, from_=0, to=100, tickinterval=10,
418
- orient='horizontal', label='Use slider to seek to point in file (%)')
419
- self.seek_scale.bind('<ButtonRelease-1>', self.seek)
420
+ framestep_button = tk.Button(self.control_frame, text='step>',
421
+ command=self.framestep)
422
+ forward_button = tk.Button(self.control_frame, text='>>',
423
+ command=self.forward)
424
+ fast_forward_button = tk.Button(self.control_frame, text='>>>',
425
+ command=self.fastforward)
426
+ back_button = tk.Button(self.control_frame, text='<<', command=self.back)
427
+ fast_back_button = tk.Button(self.control_frame, text='<<<', command=self.fast_back)
428
+# self.seek_scale = tk.Scale(seek_frame, from_=0, to=100, tickinterval=10,
429
+# orient='horizontal', label='Use slider to seek to point in file (%)')
430
+# self.seek_scale.bind('<ButtonRelease-1>', self.seek)
431
# pack the buttons and scale in their frames
432
mark_button.pack(side='bottom', fill='both', expand=1)
433
- self.seek_scale.pack(side='left', fill='x', expand=1)
434
+ #self.seek_scale.pack(side='left', fill='x', expand=1)
435
exit_button.pack(side='left')
436
+ fast_back_button.pack(side='left')
437
back_button.pack(side='left')
438
- pause_button.pack(side='left')
439
+ pause_button.pack(side='left', expand=1)
440
framestep_button.pack(side='left')
441
forward_button.pack(side='left')
442
+ fast_forward_button.pack(side='left')
443
+ self.mp_ctrls = self.control_frame.winfo_children()
444
445
- def seek(self, event=None):
446
- """seek in video according to value set by slider"""
447
- self.send('seek %s 3\n' %self.seek_scale.get())
448
+# def seek(self, event=None):
449
+# """Seek in video according to value set by slider"""
450
+# self.send('seek %s 3\n' %self.seek_scale.get())
451
+# self.after(500, lambda:self.seek_scale.set(0))
452
453
def forward(self):
454
- """seek forward 10 seconds and make sure button var is set to 'pause'"""
455
- self.send('seek 10\n')
456
- self.pauseplay.set('pause')
457
+ """Seek forward 10 seconds and make sure button var is set to 'Pause'"""
458
+ self.send('seek 10')
459
+ self.pauseplay.set('Pause')
460
+
461
+ def fastforward(self):
462
+ """Seek forward 5 minutes and make sure button var is set to 'Pause'"""
463
+ self.send('seek 300')
464
+ self.pauseplay.set('Pause')
465
466
def back(self):
467
- """seek backward 10 seconds and make sure button var is set to 'pause'"""
468
- self.send('seek -10\n')
469
- self.pauseplay.set('pause')
470
+ """Seek backward 10 seconds and make sure button var is set to 'Pause'"""
471
+ self.send('seek -10')
472
+ self.pauseplay.set('Pause')
473
+
474
+ def fast_back(self):
475
+ """Seek backward 10 seconds and make sure button var is set to 'Pause'"""
476
+ self.send('seek -300')
477
+ self.pauseplay.set('Pause')
478
479
def framestep(self):
480
- """step frame by frame forward and set button var to 'play'"""
481
- self.send('pausing frame_step\n')
482
- self.pauseplay.set('play')
483
+ """Step frame by frame forward and set button var to 'Play'"""
484
+ self.send('pausing frame_step')
485
+ self.pauseplay.set('Play')
486
487
def set_chapter(self):
488
- """send chapter mark (via slave) twice so mplayer writes the data.
489
+ """Send chapter mark (via slave) twice so mplayer writes the data.
490
we only take the 1st mark on each line
491
"""
492
for i in range(2):
493
- self.send('edl_mark\n')
494
- mess = "osd_show_text 'chapter point saved' 2000 3\n"
495
+ self.send('edl_mark')
496
+ mess = "osd_show_text 'chapter point saved' 2000 3"
497
if not self.show_osd:
498
- self.send('osd 3\n%s' %mess)
499
- self.after(2500, lambda:self.send('osd 0\n'))
500
+ self.send('osd 3%s' %mess)
501
+ self.after(2500, lambda:self.send('osd 0'))
502
else:
503
self.send(mess)
504
505
506
def get_chapters(self):
507
+ """Read mplayer's editlist to get chapter points and return
508
+ HH:MM:SS.xxx format string, comma separated
509
+ """
510
# need a sleep to make sure mplayer gives up its data
511
if not os.path.exists(self.editlist):
512
return
513
514
f = open(self.editlist)
515
c = f.readlines()
516
f.close()
517
- # if chapter_var has value, editlist has been reset. Append value, if any.
518
- # only 1st value on each line is taken (2nd is to make mplayer write out)
519
+ # if chapter_var has value, editlist has been reset. Append value.
520
+ # only 1st value on each line is taken (the 2nd makes mplayer write out)
521
s = [ i.split()[0] for i in self.chapter_var.get().splitlines() if i]
522
c.extend(s)
523
times = [ float(shlex.split(i)[0]) for i in c ]
524
525
chapters.append(time.strftime('%H:%M:%S', time.gmtime(t)) + fraction)
526
if c:
527
return '%s' %','.join(chapters)
528
+
529
+ def on_eof(self):
530
+ """
531
+ Run when 'End of file' discovered in mplayer output by poll().
532
+ """
533
+ f = open(self.editlist)
534
+ self.chapter_var.set(f.read())
535
+ f.close()
536
+
537
+class SetChaptersGui(SetChapters):
538
+ """A standalone GUI to set video chapter points using SetChapters class"""
539
+ def __init__(self, master, args='', title='', callback=None):
540
+ """
541
+ master
542
+ Pack into this widget
543
+ args
544
+ Additional args to pass to mplayer
545
+ title
546
+ Window manager titlebar title (master must be root window for this)
547
+ callback
548
+ Function to run on application exit, run before temp file cleanup
549
+ """
550
+ SetChapters.__init__(self, master, args, title, callback)
551
+ self.callback = self.print_chapters
552
+ # bindings for exit
553
+ self._root().protocol("WM_DELETE_WINDOW", self.exit)
554
+ self._root().bind('<Control-q>', self.exit)
555
+
556
+
557
+ def add_widgets(self):
558
+ """Override add_widgets() from SetChapters, calling it first
559
+ then adding widgets to it
560
+ """
561
+ SetChapters.add_widgets(self)
562
+ self.result_frame = tk.Frame(self)
563
+ self.text_frame = tk.Frame(self.result_frame)
564
+ self.result_frame.pack(side='bottom', fill='x', expand=1)
565
+ self.text_frame.pack(side='bottom', fill='x', expand=1)
566
+ self.load_button = tk.Button(self.text_frame,
567
+ command=self.load, text='Load Video')
568
+ self.load_button.pack(side='left', padx=5)
569
+ self.entry = tk.Entry(self.text_frame)
570
+ self.entry.insert(0, "00:00:00.0")
571
+ self.entry.pack(side='left', fill='x', expand=1)
572
+ self.exit_button = tk.Button(self.text_frame,
573
+ command=self.exit, text='Exit')
574
+ self.exit_button.pack(side='left')
575
+ # keep a list of mplayer controls so we can disable/enable them later
576
+ self.mp_ctrls = self.control_frame.winfo_children()
577
+
578
+ def load(self, event=None):
579
+ """Load a file to play in the GUI"""
580
+ try:
581
+ from tkFileDialog import askopenfilename
582
+ except ImportError:
583
+ # python 3
584
+ from tkinter.filedialog import askopenfilename
585
+ vid_name = askopenfilename()
586
+ if vid_name:
587
+ self.toggle_controls('normal', self.mp_ctrls)
588
+ # reset entry to 0 and chapter_var if we have a new video loaded
589
+ self.entry.delete(0, tk.END)
590
+ self.entry.insert(0, "00:00:00.0")
591
+ if self.pauseplay.get() == 'Pause':
592
+ self.pauseplay.set('Play')
593
+ self.run(vid_name)
594
+
595
+ def print_chapters(self):
596
+ """
597
+ Run get_chapters(), output result to stdout, entry box, and write
598
+ to tempory file. Disable mplayer controls.
599
+ This functions as the callback on mplayer exit.
600
+ """
601
+ if self.get_chapters():
602
+ try:
603
+ from tkMessageBox import askyesno, showinfo
604
+ except ImportError:
605
+ # python 3
606
+ from tkinter.messagebox import askyesno, showinfo
607
+ output = self.get_chapters()
608
+ stdout.write(output + '\n')
609
+ self.entry.delete(0, tk.END)
610
+ self.entry.insert(0, output)
611
+ self.toggle_controls('disabled', self.mp_ctrls)
612
+ string1 = "Chapter string will be saved to: "
613
+ string2 = '\nDo you wish to save it ?'
614
+ #string2 += ' Choose "Yes" to save it.'
615
+ # get basename of video, remove extension, add a '_'
616
+ vid = os.path.basename(self.command[-1]) + '_'
617
+ tmpfile = mkstemp(prefix=vid)
618
+ if askyesno(title="Save chapter string",
619
+ message= '%s%s%s' %(string1, tmpfile[1], string2)):
620
+ save_msg = "%s%s\n" %('Saved ', tmpfile[1])
621
+ showinfo(title='Chapters saved', message=save_msg)
622
+ if os.path.exists(tmpfile[1]):
623
+ f = open(tmpfile[1], 'w')
624
+ f.write(output)
625
+ f.close()
626
+ else:
627
+ os.remove(tmpfile[1])
628
+
629
+ def quit(self):
630
+ """Override quit() from base class, as standalone uses exit()"""
631
+ # disable controls, because tempdir has been deleted
632
+ self.toggle_controls('disabled', self.mp_ctrls)
633
+ if self.chapter_var.get():
634
+ self.chapter_var.set('')
635
+
636
+ def exit(self, event=None):
637
+ """Exit the GUI after confirming that mplayer is not running."""
638
+ if self.is_running.get():
639
+ self.confirm_msg()
640
+ else:
641
+ self.master.destroy()
642
643
644
# class for control that allow setting chapter points
645
class Chapters(ListToOne):
646
"""A popup version of the ListToOne Control, that also
647
- allows setting chapter points with a mplayer GUI
648
- (SetChapters). This Control is specific to the tovid GUI.
649
+ allows setting chapter points with a mplayer GUI
650
+ (SetChapters). This Control is specific to the tovid GUI.
651
"""
652
def __init__(self,
653
parent,
654
655
text='',
656
**kwargs):
657
"""initialize Chapters
658
- text
659
- The text for the button that calls mplayer
660
- For other options see help(control.ListToOne)
661
+ text
662
+ The text for the button that calls mplayer
663
+ For other options see help(control.ListToOne)
664
"""
665
ListToOne.__init__(self, parent, label, option, default, help,
666
control, filter, side, **kwargs)
667
668
self.top_height = 540
669
670
def draw(self, master):
671
- """initialize Toplevel popup, video/chapters lists, and mplayer GUI.
672
+ """Initialize Toplevel popup, video/chapters lists, and mplayer GUI.
673
Only pack the video/chapter lists (_SubList). Withdraw until called.
674
"""
675
chapters_button = tk.Button(master, text='edit', command=self.popup)
676
677
' 2. Or, use a different auto chapter value for each video.\n' + \
678
'HH:MM:SS format:\n' + \
679
' 1. Enter timecode for each video, eg. 00:00:00,00:05:00 ...\n' + \
680
- ' 2. Or use the "set with mplayer" button to use a GUI'
681
+ ' 2. Or use the "set with mplayer" button to use a GUI.'
682
self.top.label = tk.Label(self.top, text=txt, justify=tk.LEFT)
683
self.top.label.pack(side=tk.TOP)
684
self.top_button = tk.Button(self.top, text='Okay', command=self.top.withdraw)
685
686
687
def get_geo(self, widget):
688
"""Get geometry of a widget.
689
- Returns List (integers): width, height, Xpos, Ypos
690
+ Returns List (integers): width, height, Xpos, Ypos
691
"""
692
geo = widget.winfo_geometry()
693
return [ int(x) for x in geo.replace('x', '+').split('+') ]
694
695
def center_popup(self, master, width, height):
696
"""Get centered screen location of popup, relative to master.
697
- Returns geometry string in form of 'WxH+Xpos+Ypos'
698
+ Returns geometry string in form of 'WxH+Xpos+Ypos'
699
"""
700
root_width, root_height, rootx, rooty = self.get_geo(master)
701
xoffset = (root_width - width) / 2
702
703
return '%dx%d+%d+%d' %(width, height, rootx + xoffset, rooty + yoffset)
704
705
def popup(self):
706
- """popup the list of chapters, with button to run mplayer GUI"""
707
+ """Popup the list of chapters, with button to run mplayer GUI"""
708
videolist = self.parent_listbox
709
self.top.transient(self.parent._root())
710
w = self.top_width
711
712
self.parent_listbox.select_index(0)
713
714
def run_mplayer(self, event=None):
715
- """run the mplayer GUI to set chapters"""
716
+ """Run the mplayer GUI to set chapters"""
717
selected = self.parent_listbox.selected.get()
718
if selected:
719
# initialize mplayer GUI
720
721
self.top.bind('<Escape>', self.mpl.confirm_exit)
722
723
def on_exit(self):
724
- """callback run when mplayer GUI exits. This sets the chapters list
725
- to the timecodes set by the mplayer gui, repacks the label and the
726
- list frame, sets/resets bindings, and releases the grab_set().
727
+ """Callback run when mplayer GUI exits. This sets the chapters list
728
+ to the timecodes set by the mplayer gui, repacks the label and the
729
+ list frame, sets/resets bindings, and releases the grab_set().
730
"""
731
if self.mpl.get_chapters():
732
self.control.variable.set(self.mpl.get_chapters())
733
734
self.top.bind('<Escape>', self.withdraw_popup)
735
736
def withdraw_popup(self, event=None):
737
+ """Withdraw the chapters popup window"""
738
self.top.withdraw()
739
740
def select(self, index, value):
741
"""Select an item in the list and enable editing.
742
- List select method overriden in order to clear entry selection.
743
+ List select method overriden in order to clear entry selection.
744
"""
745
List.select(self, index, value)
746
# don't make it easy to erase a chapters string with a keypress
747
748
[noDupes.append(i) for i in seq if not noDupes.count(i)]
749
return noDupes
750
751
+def get_loadable_opts(opts):
752
+ good_opts = []
753
+ bad_opts = []
754
+ add_opt = False
755
+ for index, opt in enumerate(opts):
756
+ if opt.startswith('-'):
757
+ if opt in no_load_opts:
758
+ add_opt = False
759
+ else:
760
+ add_opt = True
761
+ # -colour is not loadable, but is a valid todisc option
762
+ if '-colour' in opt:
763
+ opt = opt.replace('-colour','-color')
764
+ if add_opt:
765
+ good_opts.append(opt)
766
+ else:
767
+ bad_opts.append(opt)
768
+
769
+ return [good_opts, bad_opts]
770
+
771
+# this is part of the HACK in working around broken load_args
772
+# load_script was lifted from gui.py in metagui, with mods
773
+def load_script(filename):
774
+ #"""Load current script options and arguments from a text file.
775
+ #"""
776
+ # Read lines from the file and reassemble the command
777
+ command = ''
778
+ for line in open(filename, 'r'):
779
+ line = line.strip()
780
+ # Discard comment lines and PATH assignment
781
+ if line and not (line.startswith('#') or line.startswith('PATH=')):
782
+ command += line.rstrip('\\')
783
+ # Split the full command into arguments, according to shell syntax
784
+ args = shlex.split(command)
785
+
786
+ # Ensure the expected program is being run
787
+ program = args.pop(0)
788
+ if program != 'todisc':
789
+ raise ValueError("This script runs '%s', expected '%s'" %
790
+ (program, 'todisc'))
791
+ return args
792
+
793
+
794
+def filter_args(master=None, args=None):
795
+ # HACK
796
+ # we need to sanitize the GUI args as load_args in metagui is broken
797
+ # this function and imports of it can be removed when it is fixed
798
+ a = get_loadable_opts(args)
799
+ args = a[0]
800
+ if a[1]:
801
+ #import Tkinter as tk
802
+ from textwrap import dedent
803
+ heading = '''
804
+ The tovid GUI did not load some of your options.
805
+ This is normal as loading options externally
806
+ is experimental. Sorry for the inconvenience.
807
+
808
+ You can copy this for reference as you will need
809
+ to set the following options yourself in the GUI:
810
+
811
+ '''
812
+
813
+ #u = unloadable_opts[:]
814
+ #data = ['\n' + x + '\n' if x.startswith('-') else x for x in u]
815
+ nonloadable = []
816
+ for i in a[1]:
817
+ if i.startswith('-'):
818
+ nonloadable.append('\n' + i)
819
+ elif ' ' in i:
820
+ nonloadable.append("'" + i + "'")
821
+ else:
822
+ nonloadable.append(i)
823
+ #data = ' '.join(nonloadable)
824
+ master.title('Important!')
825
+ info_msg = CopyableInfo(master, 'Important', dedent(heading),
826
+ ' '.join(nonloadable), tovid_icon)
827
+ info_msg.mainloop()
828
+ return args
829
+
830
+
831
+from libtovid.metagui.support import show_icons
832
+from libtovid.metagui import Style
833
+class CopyableInfo(tk.Frame):
834
+ def __init__(self, master, title='', heading='', data='', icon=None):
835
+ tk.Frame.__init__(self, master)
836
+ self.pack()
837
+ master.minsize(300, 300)
838
+ text_frame = tk.Frame(self)
839
+ text_frame.pack(side='top')
840
+ style = Style()
841
+ inifile = os.path.expanduser('~/.metagui/config')
842
+ if os.path.exists(inifile):
843
+ style.load(inifile)
844
+ font = style.font or None
845
+ else:
846
+ font = None
847
+ text_widget = tk.Text(text_frame, width=50, height=20, wrap='word')
848
+ text_widget["bg"] = self.cget('background')
849
+ text_widget["relief"] = 'flat'
850
+ master["relief"] = 'flat'
851
+ if font:
852
+ text_widget["font"] = font
853
+ text_widget.pack(side='top', fill='both', expand=1)
854
+ text_widget.insert('1.0',heading)
855
+ #text_widget.bind("<1>", self.set_focus(self, text_widget))
856
+ text_widget.insert('end',data)
857
+ text_widget['state'] = 'disabled'
858
+ lines = int(text_widget.index('end-1c').split('.')[0])
859
+ text_widget['height'] = lines + 3
860
+ rclick = RightClickMenu(text_widget)
861
+ text_widget.bind("<3>", rclick)
862
+ exit_button = tk.Button(self, text='Close',
863
+ command=lambda:self._quit())
864
+ #exit_button.focus_set()
865
+ exit_button.pack(side='bottom')
866
+ master.bind('<Control-q>', lambda event=None: self._quit())
867
+ master.bind('<Escape>', lambda event=None: self._quit())
868
+ if icon:
869
+ show_icons(self.master, icon)
870
+ master.update_idletasks() # update geometry
871
+ # center the popup
872
+ m = master
873
+ x = int((m.winfo_screenwidth() / 2) - (m.winfo_width() /2))
874
+ y = int((m.winfo_screenheight() / 2) - int((m.winfo_height() /2)))
875
+ master.geometry('+%s+%s' %(x, y))
876
+
877
+
878
+
879
+ def _quit(self, event=None):
880
+ self.master.destroy()
881
+ #self.master.destroy()
882
+
883
+
884
+class RightClickMenu(object):
885
+ # thanks to 'paperrobot' at:
886
+ # http://paperrobot.wordpress.com for this gem
887
+ """
888
+ Simple widget to add basic right click menus to entry widgets.
889
+
890
+ usage:
891
+
892
+ rclickmenu = RightClickMenu(some_entry_widget)
893
+ some_entry_widget.bind("<3>", rclickmenu)
894
+
895
+ Replace all Tix references with Tkinter and this will still work fine.
896
+ """
897
+ def __init__(self, parent):
898
+ self.parent = parent
899
+ # bind Control-A to select_all() to the widget. Others work ok without
900
+ self.parent.bind("<Control-a>", lambda e: self.select_all(), add='+')
901
+ self.parent.bind("<Control-A>", lambda e: self.select_all(), add='+')
902
+ def __call__(self, event):
903
+ # grab focus of the entry widget. this way you can see
904
+ # the cursor and any marking selections
905
+ self.parent.focus_force()
906
+ self.build_menu(event)
907
+ def build_menu(self, event):
908
+ self.menu = tk.Menu(self.parent, tearoff=0)
909
+ #self.parent.bind("<Button-1>", self.close_menu)
910
+ #self.parent.bind("<Escape>", self.close_menu)
911
+ if self.parent.tag_ranges("sel"):
912
+ self.menu.add_command(
913
+ label="Copy",
914
+ command=lambda: self.parent.event_generate("<<Copy>>"))
915
+ else:
916
+ self.menu.add_command(label="Copy", state=tk.DISABLED)
917
+ self.menu.add_command(label="Cut", state=tk.DISABLED)
918
+ self.menu.add_command(label="Paste", state=tk.DISABLED)
919
+ # make things pretty with a horizontal separator
920
+ self.menu.add_separator()
921
+ self.menu.add_command(label="Select All", command=self.select_all)
922
+ self.menu.tk_popup(event.x_root, event.y_root)
923
+ def select_all(self):
924
+ self.parent.tag_add(tk.SEL, 1.0, tk.END)
925
+ # return 'break' because doesn't work otherwise.
926
+ return 'break'
927
+
928
+
929
+
930
# List of file-type selections for Filename controls
931
image_filetypes = [filetypes.image_files]
932
image_filetypes.append(filetypes.all_files)
933
934
# video file-types from filetypes needs some additions
935
v_filetypes = 'm2v vob ts '
936
v_filetypes += filetypes.get_extensions('video').replace('*.', '')
937
-v_filetypes += ' mp4 mpeg4 mp4v divx mkv ogv ogm ram rm rmvb wmv'
938
+v_filetypes += ' mp4 mpeg4 mp4v divx mkv ogv ogm ram rm rmvb wmv webm'
939
vid_filetypes = filetypes.new_filetype('Video files', v_filetypes)
940
video_filetypes = [vid_filetypes]
941
video_filetypes += [filetypes.all_files]
942
943
# Users can use their own thumb masks. Add to thumb mask control drop-down
944
masks = [ 'none', 'normal', 'oval', 'vignette', 'plectrum', 'arch', 'spiral', \
945
'blob', 'star', 'flare' ]
946
+
947
+# some options can not be loaded by the gui:
948
+# options with multiple choices for args, for example: none, single, multiple
949
+# this is a list of 'unloadable' options for the GUI
950
+no_load_opts = ['-chapter-titles', '-menu-fade', '-loop', '-video-pause', '-group-video-pause', '-slide-blur', '-slide-border', '-slide-frame', '-chain-videos', '-showcase', '-titles-font-deco', '-chapters', '-subtitle-lang', '-audio-channel', '-audio-lang', '-seek', '-showcase-seek', '-bg-video-seek', '-bgvideo-seek', '-bg-audio-seek', '-bgaudio-seek', '-submenu-audio-seek', '-rotate-thumbs', '-tile3x1', '-tile-3x1', '-tile4x1', '-tile-4x1']
951
+
952
# $PREFIX/lib/tovid is already added to end of PATH
953
os_path = os.environ['PATH'].rsplit(':')
954
sys_dir = os_path[-1] + '/masks'
955
956
for dir in sys_dir, home_dir:
957
masks.extend(find_masks(dir, '*.png'))
958
thumb_masks = '|'.join(nodupes(masks))
959
-tovid_prefix = commands.getoutput('tovid -prefix')
960
+tovid_prefix = getoutput('tovid -prefix')
961
tovid_icon = os.path.join(tovid_prefix, 'lib', 'tovid', 'tovid.png')
962
963
+# default heading text for tovid GUI (opening pane)
964
+heading_text = 'You can author (and burn) a DVD with a simple menu '
965
+heading_text += 'using ONLY this "Basic" pane\n'
966
+heading_text += 'Required: video files (and/or slideshows) and "Output name"'
967
+
968
### configuration for titleset wizard ( 'tovid titlesets' )
969
-wizard = os.getenv('METAGUI_WIZARD')
970
+wizard = os.getenv('METAGUI_WIZARD') or '0'
971
if wizard == '1':
972
# General options
973
heading_text = 'General options applying to all titlesets.\n'
974
975
# titleset options
976
heading_text = 'Options for titleset %s\n' %(int(wizard) - 2)
977
heading_text += 'Required: 1 or more videos and/or slideshows'
978
-else:
979
- heading_text = 'You can author (and burn) a DVD with a simple menu '
980
- heading_text += 'using ONLY this "Basic" pane\n'
981
- heading_text += 'Required: video files (and/or slideshows) and "Output name"'
982
983
if wizard == '2':
984
# Root menu options
985
986
Text(),
987
filter=to_title)
988
989
-if wizard and wizard != '1':
990
+if int(wizard) and wizard != '1':
991
# 'Output name' only for General Options ( '1' )
992
_out = Label(' ')
993
else:
994
tovid-0.34.tar.bz2/libtovid/guis/todisc.py -> tovid-0.35.tar.gz/libtovid/guis/todisc.py
Changed
238
1
2
"""A GUI for the todisc command-line program.
3
"""
4
5
-import Tkinter as tk
6
+try:
7
+ import Tkinter as tk
8
+except ImportError:
9
+ # python 3
10
+ import tkinter as tk
11
12
# Get supporting classes from libtovid.metagui
13
from libtovid.metagui import *
14
15
Number('Columns', '', 13, '', 0, 13))
16
17
_quick_menu = Flag('Quick menu (may need a menu video)',
18
- '-quick-menu', False, 'Note: may not be available in your ffmpeg '
19
- 'as the needed "vhooks" have been deprecated. Ten times faster than '
20
- 'normal showcase animation. A showcase or background video is required '
21
- 'unless doing switched menus. Menu links are text only. Not compatible '
22
- 'with wave or rotate options.')
23
+ '-quick-menu', False, 'Note: you need a recent ffmpeg with the "movie" '
24
+ 'filter enabled. Ten times faster than normal showcase animation. A '
25
+ 'showcase or background video is required unless doing switched menus. '
26
+ 'Menu links are text only. Not compatible with wave or rotate options.')
27
28
_switched_menus = Flag('Switched menus (try with "Quick menu" !)',
29
'-switched-menus', False,
30
31
_thumb_shape = Choice('Thumb shape', '-thumb-shape', 'none',
32
'Apply a shaped transparency mask to thumbnail videos or images. These '
33
'"feathered" shapes look best against a plain background or used with '
34
- '**-thumb-mist** [COLOR]. To use a "mist" background behind each thumb, '
35
+ '-thumb-mist [COLOR]. To use a "mist" background behind each thumb, '
36
'see "Thumb mist" section. No frame will be used for this option. '
37
+ 'See "man tovid" (-thumb-shape) for info on how to add your own masks.'
38
'Leave at "none" to not use a feathered shape.',
39
thumb_masks, 'dropdown')
40
41
42
'(4 videos only). Not a showcase option.')
43
44
_align = Choice('Align', '-align', 'north',
45
- 'Controls positioning of the thumbnails and their titles. '
46
- 'With some arrangements this will have limited effects however.',
47
+ 'Controls positioning of the thumbnails (if any) and video titles. '
48
+ 'With some arrangements this will have limited effects however.'
49
+ 'For example only north|south|center can be used with the default montage '
50
+ 'of thumbs arrangement, or with showcase with thumb arrangement. '
51
+ 'It will be most effective with single column showcase and textmenu styles',
52
'north|south|east|west|center', 'dropdown')
53
54
_seek = SpacedText('Thumbnail seek(s)', '-seek', '',
55
56
'A single value or space separated list, 1 value per video. '
57
'Also used for seeking in switched menus.')
58
59
+_user_thumbs = List('Image(s)', '-user-thumbs', None,
60
+ 'Images for thumbnails. This option requires one image for each title.',
61
+ Filename('', filetypes=image_filetypes))
62
63
### --------------------------------------------------------------------
64
### Fonts and font colors
65
### --------------------------------------------------------------------
66
67
# Menu title font
68
-_menu_font = Font('', '-menu-font', 'Helvetica',
69
+_menu_font = Font('', '-title-font', 'Helvetica',
70
'The font to use for the menu title')
71
72
-_menu_fontsize = Number('Size', '-menu-fontsize', 24,
73
+_menu_fontsize = Number('Size', '-title-fontsize', 24,
74
'The font size to use for the menu title',
75
0, 80, 'pixels', toggles=True)
76
77
78
# Video title font
79
_titles_font = Font('', '-titles-font', 'Helvetica',
80
'The font to use for the video titles')
81
+# unused FIXME
82
+_titles_font_deco = SpacedText('Custom font decoration', '', '',
83
+ 'Space-separated list of custom options to imagemagick.'),
84
85
_titles_fontsize = Number('Size', '-titles-fontsize', 12,
86
'The font size to use for the video titles. '
87
88
),
89
VPanel('Backgrounds',
90
VPanel('Image or video options',
91
- _bgvideo_seek,
92
- _bg_color),
93
+ HPanel('', _bgvideo_seek,
94
+ _bg_color)),
95
VPanel('Audio options',
96
HPanel('', _bgaudio_seek, _menu_audio_fade)),
97
+ HPanel('Menu alignment', _align),
98
),
99
),
100
),
101
102
HPanel('',
103
Number('Number of slides shown on menu', '-menu-slide-total', 0,
104
'Use this many slides for making the slideshow menu. '
105
- 'The default is to use all the slides given.',
106
+ 'Leave at 0 for default: use all slides given.',
107
0, 100),
108
_submenu_slide_total,
109
),
110
111
slideshows = Tabs('Slideshows', *tab_list)
112
113
114
-thumbnails = VPanel("Thumbnails",
115
+thumbnails = Tabs("Thumbnails",
116
+ VPanel('Menu link thumbnails',
117
+ VPanel('',
118
HPanel('',
119
- VPanel('Menu link thumbnails',
120
- HPanel('Seeking', _seek),
121
+ VPanel('',
122
+ HPanel('',
123
+ VPanel('Aspect ratio', Label('Automatic: force video ratio on "Playback" tab')),
124
+ VPanel('Seeking', _seek),
125
+ ),
126
+ HPanel('',
127
VPanel("Effects",
128
HPanel('',_opacity, Label('(Also affects showcase thumb)')),
129
HPanel('', _blur, _3dthumbs),
130
131
_thumb_framesize,
132
_thumb_frame_color,
133
_thumb_columns,
134
- _align,
135
+ ),
136
),
137
),
138
+ ),
139
+ VPanel('User supplied thumbs',
140
+ VPanel('',
141
+ Label("Use this only if you want to substitute your own thumbs for default thumbnails.", 'center'),
142
+ _user_thumbs,
143
+ ),
144
+ ),
145
+ ),
146
+ ),
147
VPanel("Showcase thumbnail",
148
HPanel('Seeking', _showcase_seek),
149
+ HPanel('',
150
VPanel('Effects',
151
_wave,
152
HPanel('', _showcase_blur, _3dshowcase),
153
154
_showcase_frame_color,
155
_showcase_geo),
156
),
157
- ),
158
- HPanel('Aspect ratio', Label('Note: the aspect ratio of menu link '
159
- 'thumbnails is automatic: (force video ratio on "Playback" tab)')),
160
+ ),
161
)
162
163
from libtovid.guis import tovid
164
165
166
encoding = VPanel('Encoding',
167
Label("\nVideo re-encoding options - you may leave these at defaults.", 'center'),
168
- Tabs('tovid options',
169
+ Tabs('',
170
tovid.BASIC_OPTS,
171
tovid.VIDEO,
172
tovid.AUDIO,
173
tovid.BEHAVIOR,
174
),
175
- SpacedText('Custom makempg options', '', '',
176
+ Flag('Encode only', '-encode-only', False,
177
+ 'Use this GUI for encoding only. On the Main tab, load files and '
178
+ 'select an out filename'),
179
+ SpacedText('Custom makempg ("tovid mpg") options', '', '',
180
'Space-separated list of custom options to pass to makempg.'),
181
+
182
)
183
184
### --------------------------------------------------------------------
185
186
-def run(args=None):
187
+def run(args=None, position='', project=''):
188
+ from libtovid.guis.helpers import get_loadable_opts, load_script
189
+ import os
190
+ # if the first arg is a text file, treat it as a script and try to load
191
+ # the options from it as a list into args
192
+ # load_script from helpers overrides load_script from gui.py as the latter
193
+ # suffers from the load_args bug mentioned in that file.
194
+ if args:
195
+ script = args[0]
196
+ if not script.startswith('-'):
197
+ try:
198
+ from commands import getoutput
199
+ except ImportError:
200
+ # python 3
201
+ from subprocess import getoutput
202
+ if os.path.exists(script) \
203
+ and 'text' in getoutput('file %s' %script):
204
+ script = args.pop(0)
205
+ args.extend(load_script(script))
206
+ # now check if we have unloadable options, this first call does only that
207
+ # this will return 2 lists, [0] is loadable and [1] is unloadable
208
+ # probably don't want to do this anyway, as filter_args will just return
209
+ # the args it is sent if none are unloadable
210
+ a = get_loadable_opts(args)
211
+ if a[1]:
212
+ from libtovid.guis.helpers import filter_args
213
+ r = tk.Tk()
214
+ args = filter_args(r, args)
215
+ # workaround for netbooks (could use xrandr perhaps, but this works fine)
216
+ gui_width, gui_height = 800, 660
217
+ root = tk.Tk()
218
+ root.withdraw()
219
+ root.update_idletasks()
220
+ screen_height = root.winfo_screenheight()
221
+ # insure screen is not 800x600 or somesuch which doesn't work for gui anyway
222
+ # need float like 1.3333333 that we multiply * 100 and convert back to int
223
+ screen_width = float(root.winfo_screenwidth())
224
+ if int(screen_height) < 660 and not int(screen_width / screen_height * 100) == 133:
225
+ gui_height = 600
226
+ root.destroy()
227
+
228
+ # finally, run it
229
app = Application('todisc',
230
main, main_menu, submenus, thumbnails, slideshows, playback, behavior, encoding)
231
- gui = GUI("tovid gui", 800, 660, app, icon=tovid_icon)
232
- gui.run(args)
233
+ gui = GUI("tovid gui", gui_width, gui_height, app, icon=tovid_icon, position=position)
234
+ gui.run(args, script=project)
235
236
if __name__ == '__main__':
237
238
tovid-0.34.tar.bz2/libtovid/guis/tovid.py -> tovid-0.35.tar.gz/libtovid/guis/tovid.py
Changed
10
1
2
0, 4400, units='MiB')
3
4
# Encoder options
5
-_mplayeropts = SpacedText('mplayer options', '-mplayeropts', '', 'TODO: Tooltip')
6
+_mplayeropts = Text('mplayer options', '-mplayeropts', '', 'TODO: Tooltip')
7
_filters = Choice('mplayer filters', '-filters', 'none', 'TODO: Tooltip',
8
'none|denoise|deblock|contrast|all', side='top')
9
_ffmpeg = Flag('Encode using ffmpeg', '-ffmpeg', False)
10
tovid-0.34.tar.bz2/libtovid/metagui/control.py -> tovid-0.35.tar.gz/libtovid/metagui/control.py
Changed
48
1
2
def any(iterable):
3
"""Return True if bool(x) is True for any x in iterable."""
4
for item in iterable:
5
- if not item:
6
- return False
7
- return True
8
+ if item:
9
+ return True
10
+ return False
11
+
12
+
13
14
# Python < 3.x
15
try:
16
17
(asksaveasfilename, askopenfilename, askopenfilenames)
18
from tkinter.colorchooser import askcolor
19
20
+# Python 3.x
21
+from libtovid import basestring
22
+
23
from libtovid.metagui.widget import Widget
24
from libtovid.metagui.variable import VAR_TYPES, ListVar
25
from libtovid.metagui.support import \
26
27
"""Event handler to update the color preview.
28
"""
29
color = self.variable.get().strip()
30
- self.set(color)
31
+ try:
32
+ self.set(color)
33
+ except (ValueError):
34
+ pass
35
36
37
def pick_color(self):
38
39
def next_item(self, event):
40
"""Select the next item in the parent listbox.
41
"""
42
- self.parent_list.listbox.next_item(event)
43
+ if self.parent_list is not None:
44
+ self.parent_list.listbox.next_item(event)
45
46
47
class SpacedText (Text):
48
tovid-0.34.tar.bz2/libtovid/metagui/gui.py -> tovid-0.35.tar.gz/libtovid/metagui/gui.py
Changed
281
1
2
import tempfile
3
import shlex
4
import subprocess
5
-from sys import exit
6
+from sys import exit, argv
7
8
# Python < 3.x
9
try:
10
+ import Tix
11
import Tkinter as tk
12
from ScrolledText import ScrolledText
13
- from tkFileDialog import \
14
- (asksaveasfilename, askopenfilename)
15
from tkMessageBox import showinfo, showerror
16
- import Tix
17
+ from tkFileDialog import (
18
+ asksaveasfilename, askopenfilename
19
+ )
20
21
# Python 3.x
22
except ImportError:
23
import tkinter as tk
24
+ import tkinter.tix as Tix
25
from tkinter.scrolledtext import ScrolledText
26
- from tkinter.filedialog import \
27
- (asksaveasfilename, askopenfilename)
28
from tkinter.messagebox import showinfo, showerror
29
- import tkinter.tix as Tix
30
+ from tkinter.filedialog import (
31
+ asksaveasfilename, askopenfilename
32
+ )
33
34
from libtovid import cli
35
from libtovid.metagui.widget import Widget
36
from libtovid.metagui.panel import Panel, Tabs
37
-from libtovid.metagui.support import \
38
- (ConfigWindow, Style, ensure_type, askyesno, get_photo_image, show_icons)
39
from libtovid.metagui.control import Control, NoSuchControl
40
+from libtovid.metagui.support import (
41
+ ConfigWindow, Style, ensure_type, askyesno, get_photo_image, show_icons
42
+ )
43
44
45
DEFAULT_CONFIG = os.path.expanduser('~/.metagui/config')
46
47
self.notify("Output saved to '%s'" % filename)
48
49
50
+from textwrap import dedent
51
class Application (Widget):
52
"""Graphical frontend for a command-line program
53
"""
54
55
"""Draw the Application in the given master.
56
"""
57
Widget.draw(self, master)
58
+ self.master = master
59
# Draw all panels as tabs
60
self.tabs = Tabs('', *self.panels)
61
self.tabs.draw(self)
62
self.tabs.pack(anchor='n', fill='both', expand=True)
63
+ # need to wait until draw is called before setting this variable
64
+ self.script = tk.StringVar()
65
+ self.script.set('')
66
67
68
def draw_toolbar(self, config_function, exit_function):
69
70
self.executor.notify("Cancelled.")
71
self.toolbar.enable()
72
73
+ def set_scriptname(self, name):
74
+ """Set script filename. Called externally, this sets the variable
75
+ that used used for save_exit() as well as the 'initial file' for
76
+ prompt_save_script().
77
+ """
78
+ self.script.set(name)
79
+
80
81
def prompt_save_script(self):
82
"""Prompt for a script filename, then save the current
83
84
# TODO: Make initialfile same as last saved script, if it exists
85
filename = asksaveasfilename(parent=self,
86
title="Select a filename for the script",
87
- initialfile='%s_commands.bash' % self.program)
88
+ #initialfile='%s_commands.bash' % self.program)
89
+ initialfile=self.script.get() or '%s_commands.bash' % self.program)
90
91
if not filename:
92
return
93
94
showerror(title="Error", message="Failed to save '%s'" % filename)
95
raise
96
else:
97
+ saved_script = os.path.split(filename)[1]
98
showinfo(title="Script saved", message="Saved '%s'" % filename)
99
100
101
def save_exit(self):
102
- filename = os.getcwd() + os.path.sep + '%s_commands.bash' % self.program
103
+ """Save current command to script and exit, without prompt
104
+ """
105
+ # hack for titleset wizard to get gui's screen position
106
+ from sys import stderr
107
+ stderr.write("%s %+d%+d"
108
+ %('gui position', self._root().winfo_x(), self._root().winfo_y()))
109
+
110
+ default = os.getcwd() + os.path.sep + '%s_commands.bash' % self.program
111
+ filename = self.script.get() or default
112
self.save_script(filename)
113
- # exit code borrowed from apache so wizard knows it has a file to read
114
- exit(200)
115
+ exit()
116
117
118
def prompt_load_script(self):
119
- """Prompt for a script filename, then load current Control settings
120
- from that file.
121
+ """Prompt for script filename; reload gui with current Control settings
122
"""
123
+ #"""Prompt for a script filename, then load current Control settings
124
+ #from that file.
125
+ #"""
126
+ # Hack: This is broken (commented section), presumably because of
127
+ # load_args limitations. This hack fixes it for libtovid, but does not
128
+ # belong in metagui. So refactor this when load_args is fixed.
129
+ # see http://code.google.com/p/tovid/issues/detail?id=121
130
filename = askopenfilename(parent=self,
131
title="Select a shell script or text file to load",
132
filetypes=[('Shell scripts', '*.sh *.bash'),
133
134
135
if not filename:
136
return
137
-
138
+ # begin Hack
139
+ geometry = self._root().winfo_x(), self._root().winfo_y()
140
+ command = argv[0]
141
try:
142
- self.reset()
143
- self.load_script(filename)
144
+ cmd = command, '--position', '+%s+%s' %geometry, filename
145
+ os.execlp(cmd[0], *cmd)
146
except:
147
- showerror(title="Error", message="Failed to load '%s'" % filename)
148
+ showerror(title="Error", message="Failed load '%s'" %filename)
149
raise
150
- else:
151
- showinfo(title="Script loaded", message="Loaded '%s'" % filename)
152
+ #try:
153
+ # self.reset()
154
+ # self.load_script(filename)
155
+ #except:
156
+ # showerror(title="Error", message="Failed to load '%s')
157
+ # raise
158
+ #else:
159
+ # showinfo(title="Script loaded", message="Loaded '%s'" % filename)
160
161
162
def save_script(self, filename):
163
164
165
166
def load_script(self, filename):
167
- """Load current Control settings from a text file.
168
- """
169
+ # this is now disabled and its functionality passed to guis.helpers.py
170
+ # see http://code.google.com/p/tovid/issues/detail?id=121
171
+ pass
172
+ #"""Load current Control settings from a text file.
173
+ #"""
174
# Read lines from the file and reassemble the command
175
- command = ''
176
- for line in open(filename, 'r'):
177
- line = line.strip()
178
+ #command = ''
179
+ #for line in open(filename, 'r'):
180
+ # line = line.strip()
181
# Discard comment lines and PATH assignment
182
- if line and not (line.startswith('#') or line.startswith('PATH=')):
183
- command += line.rstrip('\\')
184
+ # if line and not (line.startswith('#') or line.startswith('PATH=')):
185
+ # command += line.rstrip('\\')
186
# Split the full command into arguments, according to shell syntax
187
- args = shlex.split(command)
188
+ #args = shlex.split(command)
189
190
# Ensure the expected program is being run
191
- program = args.pop(0)
192
- if program != self.program:
193
- raise ValueError("This script runs '%s', expected '%s'" %
194
- (program, self.program))
195
+ #program = args.pop(0)
196
+ #if program != self.program:
197
+ # raise ValueError("This script runs '%s', expected '%s'" %
198
+ # (program, self.program))
199
# Load the rest of the arguments
200
- self.load_args(args)
201
- print("Done reading '%s'" % filename)
202
+ #self.load_args(args)
203
+ #print("Done reading '%s'" % filename)
204
205
206
# TODO: Relocate all this stuff into Control and its subclasses
207
208
Name of an .ini-formatted file with GUI configuration
209
icon
210
Full path to an image to use as the titlebar icon
211
+ position
212
+ position on screen: '+X+Y'
213
"""
214
Tix.Tk.__init__(self)
215
216
217
ensure_type("GUI needs Application", Application, application)
218
self.application = application
219
220
+ # Get keyword arguments
221
+ self.inifile = kwargs.get('inifile', DEFAULT_CONFIG)
222
+ self.icon_file = kwargs.get('icon', None)
223
+ self.position = kwargs.get('position', '')
224
+
225
# Set main window attributes
226
- self.geometry("%dx%d" % (width, height))
227
+ self.geometry("%dx%d%s" % (width, height, self.position))
228
self.title(title)
229
self.width = width
230
self.height = height
231
232
- # Get keyword arguments
233
- self.inifile = kwargs.get('inifile', DEFAULT_CONFIG)
234
- self.icon_file = kwargs.get('icon', None)
235
-
236
self.style = Style()
237
if os.path.exists(self.inifile):
238
- print("Loading style from config file: '%s'" % self.inifile)
239
+ print("Loading style from the config file: '%s'" % self.inifile)
240
self.style.load(self.inifile)
241
else:
242
print("Creating config file: '%s'" % self.inifile)
243
244
self.bind('<Control-q>', self.confirm_exit)
245
246
247
- def run(self, args=None):
248
+ def run(self, args=None, script=''):
249
"""Run the GUI and enter the main event handler.
250
This function does not return until the GUI is closed.
251
+ args: arguments to the programe being run
252
+ script: a filename to save the GUI command output to
253
"""
254
self.draw()
255
+
256
if args:
257
# If first argument looks like a filename, load
258
# a script from that file
259
260
# If more args remain, load those too
261
if args:
262
self.application.load_args(args)
263
+ # if a script/project name was provided, set it in 'application'
264
+ if script:
265
+ self.application.set_scriptname(script)
266
267
# Enter the main event handler
268
self.mainloop()
269
270
def confirm_exit(self, event=None):
271
"""Exit the GUI, with confirmation prompt.
272
"""
273
+ # Hack to sync titleset wizard's position with exiting GUI's position
274
+ if os.getenv('METAGUI_WIZARD'):
275
+ from sys import stderr
276
+ stderr.write("%s %+d%+d"
277
+ %('gui position', self._root().winfo_x(), self._root().winfo_y()))
278
if askyesno(message="Exit?"):
279
self.quit()
280
281
tovid-0.34.tar.bz2/libtovid/metagui/panel.py -> tovid-0.35.tar.gz/libtovid/metagui/panel.py
Changed
20
1
2
except ImportError:
3
import tkinter as tk
4
5
+from base64 import b64encode
6
from libtovid import cli
7
from libtovid.odict import Odict
8
from libtovid.metagui.widget import Widget
9
from libtovid.metagui.control import Control, Flag
10
-from libtovid.metagui.support import \
11
- (ComboBox, ensure_type, divide_list, get_photo_image)
12
from libtovid.metagui.variable import ListVar
13
-from base64 import b64encode
14
+from libtovid.metagui.support import (
15
+ ComboBox, ensure_type, divide_list, get_photo_image
16
+ )
17
18
19
class Label (Widget):
20
tovid-0.34.tar.bz2/libtovid/metagui/support.py -> tovid-0.35.tar.gz/libtovid/metagui/support.py
Changed
18
1
2
import tkinter.tix as Tix
3
import tkinter.font as tkFont
4
5
+# Python 2.4
6
+try:
7
+ all
8
+except NameError:
9
+ def all(iterable):
10
+ for element in iterable:
11
+ if not element:
12
+ return False
13
+ return True
14
+
15
from libtovid import cli
16
from libtovid.util import imagemagick_fonts
17
from libtovid.metagui.variable import ListVar
18
tovid-0.34.tar.bz2/libtovid/metagui/widget.py -> tovid-0.35.tar.gz/libtovid/metagui/widget.py
Changed
11
1
2
except ImportError:
3
import tkinter as tk
4
5
+# Python 3 compatibility
6
+from libtovid import basestring
7
+
8
class Widget (tk.Frame):
9
"""Generic metagui widget, suitable for Controls, Panels, etc.
10
"""
11
tovid-0.34.tar.bz2/libtovid/util/__init__.py -> tovid-0.35.tar.gz/libtovid/util/__init__.py
Changed
43
1
2
import doctest
3
import mimetypes
4
import tempfile
5
+# Python 3 compatibility
6
+from libtovid import basestring, unicode
7
8
# Special characters that may need escaping
9
special_chars = '\\ #*:;&?!<>[]()"\''
10
11
# Split text into lines, converting tabs to spaces
12
lines = text.expandtabs().splitlines()
13
# Determine minimum indentation (except first line)
14
- indent = sys.maxint
15
+ try:
16
+ MAXINT = sys.maxint
17
+ # python 3 compatibility
18
+ except AttributeError:
19
+ MAXINT = sys.maxsize
20
+
21
+ indent = MAXINT
22
+
23
for line in lines[1:]:
24
stripped = line.lstrip()
25
if stripped:
26
indent = min(indent, len(line) - len(stripped))
27
# Remove indentation (first line is special)
28
trimmed = [lines[0].strip()]
29
- if indent < sys.maxint:
30
+ if indent < MAXINT:
31
for line in lines[1:]:
32
# Append line, minus indentation
33
trimmed.append(line[indent:].rstrip())
34
35
"""Print a message and pause for the given number of seconds.
36
"""
37
print("Resuming in %s seconds..." % seconds)
38
- os.system('sleep %ss' % seconds)
39
+ os.system('sleep %s' % seconds)
40
41
42
def imagemagick_version():
43
tovid-0.34.tar.bz2/setup.py -> tovid-0.35.tar.gz/setup.py
Changed
60
1
2
as a string like 'svn-r1234'. If svn is not installed, or if something goes
3
wrong, return 'svn-unknown'
4
"""
5
- from commands import getoutput
6
+ try:
7
+ from commands import getoutput
8
+ except ImportError:
9
+ # python 3
10
+ from subprocess import getoutput
11
+
12
rev_line = getoutput('svn info 2>/dev/null | grep ^Revision')
13
# If rev_line is found, get the revision number
14
if rev_line:
15
16
# Current SVN version number
17
#_tovid_version = svn_version()
18
# Official release number
19
-_tovid_version = '0.34'
20
+_tovid_version = '0.35'
21
22
23
import os
24
25
26
# Build tovid-init with regular 'build' command
27
build.sub_commands.append(('build_tovid_init', None))
28
-#build.sub_commands.append(('build_docs', None))
29
+build.sub_commands.append(('build_docs', None))
30
31
# The actual setup
32
setup(
33
34
'libtovid.guis',
35
'libtovid.util',
36
'libtovid.metagui',
37
- 'libtovid.render',
38
- 'libtovid.backend',
39
],
40
41
# Executable files go into /$PREFIX/bin/
42
43
# Bash scripts
44
'src/idvid',
45
'src/makedvd',
46
- 'src/makemenu',
47
- 'src/makevcd',
48
- 'src/makexml',
49
- 'src/postproc',
50
'src/todisc',
51
'src/todisc-fade-routine',
52
'src/makempg',
53
- 'src/tovid-batch',
54
'src/tovid-init',
55
- 'src/tovid-interactive',
56
- 'src/make_titlesets',
57
58
# Python scripts
59
'src/todiscgui',
60
tovid-0.34.tar.bz2/src/idvid -> tovid-0.35.tar.gz/src/idvid
Changed
565
1
2
#!/usr/bin/env bash
3
-#set -u
4
5
ME="[idvid]:"
6
. tovid-init 2>/dev/null ||
7
8
echo -e "Or are you trying to run the script directly?"
9
echo -e "Please run idvid as:\ntovid id OPTIONS"
10
exit 1 ; }
11
-
12
# idvid
13
# Part of the tovid suite
14
# =======================
15
16
#
17
# Project homepage: http://tovid.wikia.com
18
#
19
-# Copyright (C) 2005-2010
20
+# Copyright (C) 2005-2015
21
#
22
# This program is free software; you can redistribute it and/or
23
# modify it under the terms of the GNU General Public License
24
25
-terse Suitable for parsing
26
-verbose Also use ffmpeg and tcprobe
27
-accurate Do accurate duration estimation
28
+ -keepfiles Keep temporary directory for debugging
29
-isformat [ntsc-vcd|pal-vcd|ntsc-svcd|pal-svcd|ntsc-dvd|pal-dvd]
30
Tell whether the first file is compliant with the given
31
format; prints "true" or "false" (returns shell 0 or 1)
32
33
MATCH_FORMAT=""
34
MATCH_TVSYS=""
35
TABULAR=false
36
-USE_MENCODER=:
37
+GET_FFMPEG_LEN=:
38
USE_NAVLOG=false
39
+KEEPFILES=false
40
ID_FILES=""
41
42
mkdir -p "$STAT_DIR"
43
44
echo "Identifying video with ffmpeg..."
45
echo $SEPARATOR
46
# ffmpeg puts its output on standard error
47
- ffmpeg -i "$INFILE" 2>&1 | tee -a "$SCRATCH_FILE"
48
+ $FFmpeg -i "$INFILE" 2>&1 | tee -a "$SCRATCH_FILE"
49
else
50
- ffmpeg -i "$INFILE" >> "$SCRATCH_FILE" 2>&1
51
+ $FFmpeg -i "$INFILE" >> "$SCRATCH_FILE" 2>&1
52
fi
53
fi
54
+ # avconv messed with formatting, so we need to move to ffprobe/avprobe
55
+ # ffprobe and avprobe show slightly different formatting, but this should do
56
+ # adds a new line after [/STREAM] (ffmpeg). avconv already has it.
57
+ if test -n $FFprobe; then
58
+ i=0
59
+ while IFS= read -r line; do
60
+ [[ $line ]] || { ((++i)); continue; }
61
+ probe_info[i]+=$line$'\n'
62
+ done < <($FFprobe -show_streams "$INFILE" 2>/dev/null | \
63
+ sed '/\[\/STREAM\]/{G;s/$//;};/DISPOSITION/d')
64
+ fi
65
+ # avprobe begins with a # comment\n so delete that index and flatten array
66
+ for i in ${!probe_info[@]}; do
67
+ grep -q '^#' <<< ${probe_info[i]} && unset probe_info[i]
68
+ done
69
+ # if index 0 is unset flatten array
70
+ [[ ${probe_info[0]+unset} ]] || probe_info=( "${probe_info[@]}" )
71
+
72
# Identify video using tcprobe
73
if test -n "$TCPROBE"; then
74
if $VERBOSE ; then
75
echo $SEPARATOR
76
echo "Identifying video with tcprobe..."
77
echo $SEPARATOR
78
- tcprobe -i "$INFILE" 2>&1 | tee -a "$SCRATCH_FILE"
79
+ tcprobe -i "$INFILE" 2>&1 | tee -a "$SCRATCH_FILE" 2>/dev/null
80
else
81
tcprobe -i "$INFILE" >> "$SCRATCH_FILE" 2>/dev/null
82
fi
83
84
fi
85
exit 1
86
fi
87
+ # remove ffmpeg metadata from scratch file
88
+ # make portable for bsd sed etc
89
+ #sed '/Metadata/,/Duration/{//!d}' "$SCRATCH_FILE" > "${SCRATCH_FILE}2"
90
+ #mv "${SCRATCH_FILE}2" "$SCRATCH_FILE"
91
92
# Defaults. Many of these values may be overridden by
93
# vars from mplayer's output to be sourced later.
94
95
V_DURATION=""
96
ID_LENGTH="0"
97
98
- # bash appears to have no way of initializing empty arrays; we append to these later,
99
- # so unsetting them clears out their previous contents
100
- unset A_SAMPRATES
101
- unset A_BITRATES
102
- unset A_CODECS
103
- unset A_HEX_TRACKS
104
- unset A_TRACKS
105
- unset wavs
106
+ # arrays
107
+ A_SAMPRATES=()
108
+ A_BITRATES=()
109
+ A_CODECS=()
110
+ A_HEX_TRACKS=()
111
+ A_TRACKS=()
112
+ MPL_AIDS=()
113
+ wavs=()
114
+ probe_audio_info=()
115
116
# send formated mplayer's output to a vars file to be sourced to set relevant variables.
117
# (ID_V(ideo), ID_A(udio), and ID_L(ength))
118
119
# get array of mplayer audio ids, used if no hextracks from ffmpeg
120
while read; do MPL_AIDS+=(${REPLY##*=}); done < <(grep ID_AUDIO_ID "$SCRATCH_FILE")
121
122
- ID_VIDEO_FRAMES=$(grep 'length:' "$SCRATCH_FILE" | \
123
- awk -F ' ' '{print $2}')
124
- test -z $ID_VIDEO_FRAMES && ID_VIDEO_FRAMES="0"
125
-
126
- # ffmpeg has a better concept of the actual bitrate than mplayer
127
- TOTAL_AV_BITRATE=$(awk -F: '{gsub("kb/s", "")}; /bitrate:/ {print $6*1000}' "$SCRATCH_FILE")
128
- ## take the lower of the two
129
- if test $ID_VIDEO_BITRATE -eq 0 || test $TOTAL_AV_BITRATE -lt $ID_VIDEO_BITRATE; then
130
- # make sure we have a value from ffmpeg
131
- if test_is_number $TOTAL_AV_BITRATE; then
132
- ID_VIDEO_BITRATE=$TOTAL_AV_BITRATE
133
+ # try tcprobe to determine length (# of frames)
134
+ # assuming it is installed, otherwise this should 'fail' silently
135
+ ID_VIDEO_FRAMES=$(awk '/length:/ {print $2}' "$SCRATCH_FILE")
136
+ ((ID_VIDEO_FRAMES)) || ID_VIDEO_FRAMES="0"
137
+
138
+ FF_V_BITRATE=$(sed -n 's/.*Stream.*Video:.*\(\ [0-9][0-9][0-9]*\) kb\/s.*/\1/p' "$SCRATCH_FILE" |uniq)
139
+ FF_V_BITRATE=${FF_V_BITRATE// /} # trim spaces
140
+ # make sure we have a value from ffmpeg (a number and non zero)
141
+ if test_is_number "$FF_V_BITRATE" && (( FF_V_BITRATE )); then
142
+ # kilobits to bits
143
+ ID_VIDEO_BITRATE=${FF_V_BITRATE}000
144
+ elif [[ -z $ID_VIDEO_BITRATE || $ID_VIDEO_BITRATE = 0 ]]; then
145
+ mplayer_stats_br=$(sed '/VIDEO:/!d;s/.*(//; s/).*=\ /:/;s/[kK][bB].*//g' "$SCRATCH_FILE")
146
+ # make an integer
147
+ mplayer_stats_br=${mplayer_stats_br%.*}
148
+ # make sure it is a number
149
+ if test_is_number $mplayer_stats_br && (( mplayer_stats_br )); then
150
+ ID_VIDEO_BITRATE=$(( mplayer_stats_br * 8 * 1000 ))
151
fi
152
- else
153
- ID_VIDEO_BITRATE=$ID_VIDEO_BITRATE
154
fi
155
+ # if mplayer decides there is no video, unset ID_VIDEO_BITRATE
156
+ # else it will still show a value from TOTAL_AV_BITRATE
157
+ grep -qi "no video" "$SCRATCH_FILE" && unset ID_VIDEO_BITRATE
158
# if we still don't have a value for ID_VIDEO_WIDTH and ID_VIDEO_HEIGHT
159
MP_FRAMESIZE=$(awk '/=>/ {print $3}' "$SCRATCH_FILE")
160
if test $ID_VIDEO_WIDTH -eq 0; then
161
- test_is_number ${MP_FRAMESIZE%x*} && ID_VIDEO_WIDTH=${MP_FRAMESIZE%x*}
162
+ test_is_number ${MP_FRAMESIZE%x*} && ID_VIDEO_WIDTH=${MP_FRAMESIZE%x*}
163
fi
164
if test $ID_VIDEO_HEIGHT -eq 0; then
165
test_is_number ${MP_FRAMESIZE#*x} && ID_VIDEO_HEIGHT=${MP_FRAMESIZE#*x}
166
167
168
# Find out which channel is the video channel ( 1st )
169
# TODO Do we want to worry about videos with multiple channels of video ?
170
- VIDEO_INFO=$(grep "Video:" "$SCRATCH_FILE")
171
- ID_VIDEO_TRACKS=( $(sed -r 's/.*Stream #([0-9]\.[0-9]+).*/\1/' <<< "$VIDEO_INFO") )
172
- ID_VIDEO_TRACK="${ID_VIDEO_TRACKS[0]}"
173
+ VIDEO_INFO=$(grep "Video:" "$SCRATCH_FILE" 2>&1| uniq)
174
+ ID_VIDEO_TRACKS=( $(sed -r 's/.*Stream #([0-9][:.][0-9]+).*/\1/' <<< "$VIDEO_INFO") )
175
+ #ID_VIDEO_TRACKS=( $(awk '/Stream.*Video/ { gsub("#|: ", " ") ; print $2}' <<< "$VIDEO_INFO") )
176
+ test_is_number "${ID_VIDEO_TRACKS[0]/:/}" && ID_VIDEO_TRACK="${ID_VIDEO_TRACKS[0]}"
177
# Find out what audio channels are available
178
+ for p in ${!probe_info[@]}; do
179
+ if grep -q codec_type=audio <<< "${probe_info[p]}"; then
180
+ probe_audio_info+=( "${probe_info[p]}" )
181
+ fi
182
+ done
183
if test -n "$ID_AUDIO_ID"; then
184
- AUDIO_INFO=$(grep -w "Audio:" "$SCRATCH_FILE")
185
+ # grep for Steam.*Audio instead of just "Audio:" fixes some wmv issues
186
+ AUDIO_INFO=$(grep "Stream.*Audio:" "$SCRATCH_FILE")
187
# ID_AUDIO_ID needs "TRACKS" var to remain in columns
188
- TRACKS=$(sed -r 's/.*Stream #([0-9]\.[0-9]+).*/\1/' <<< "$AUDIO_INFO")
189
+ TRACKS=$(sed -r 's/.*Stream #([0-9][:.][0-9]+).*/\1/' <<< "$AUDIO_INFO")
190
A_TRACKS=(${TRACKS//$'\n'/ })
191
# Get hexadecimal track IDs, if present
192
if grep -q "\[0x[0-9a-fA-F]*]" <<< $AUDIO_INFO; then
193
- HEX_TRACKS=$(awk -F [][] '{gsub("0x", ""); print $2}' <<< "$AUDIO_INFO")
194
+ HEX_TRACKS=$(awk -F '[][]' '{gsub("0x", ""); print $2}' <<< "$AUDIO_INFO")
195
HEX_TRACKS=(${HEX_TRACKS//$'\n'/ })
196
USE_HEX_TRACKS=:
197
else
198
199
# Loop through available tracks and get specs on each
200
for ((i=0; i<${#A_TRACKS[@]}; i++)); do
201
CUR_CHAN=$(grep "Stream #${A_TRACKS[i]}" <<< "$AUDIO_INFO")
202
- A_SAMPRATES=("${A_SAMPRATES[@]}" "$(echo $CUR_CHAN | \
203
- sed -r 's/.* ([0-9]+) Hz.*/\1/')")
204
- ! test_is_number ${A_SAMPRATES[i]} && A_SAMPRATES[i]=?
205
- A_BITRATES=("${A_BITRATES[@]}" "$(echo $CUR_CHAN | \
206
- sed -r 's/.* ([0-9]+) kb\/s.*/\1/')")
207
- # make sure the above is a number, else set A_BITRATE to 0
208
- ! test_is_number ${A_BITRATES[i]} && A_BITRATES[i]=0
209
- A_CODECS=("${A_CODECS[@]}" "$(echo $CUR_CHAN | \
210
- sed -r 's/.*Audio: ([^,]+),.*/\1/')")
211
+ A_SAMPRATES[i]=$(sed -r 's/.* ([0-9]+) Hz.*/\1/' <<< "$CUR_CHAN")
212
+ if ! test_is_number ${A_SAMPRATES[i]}; then
213
+ # probe_audio_info should have same indexes as A_TRACKS
214
+ aud_samplerate=$(awk -F= '/^sample_rate=/ {print $2}' <<< "${probe_audio_info[i]}")
215
+ if test_is_number $aud_samplerate; then
216
+ A_SAMPRATES[i]=${aud_samplerate%.*}
217
+ else
218
+ A_SAMPRATES[i]=0
219
+ fi
220
+ fi
221
+ A_BITRATES[i]=$(sed -r 's/.* ([0-9]+) kb\/s.*/\1/' <<< "$CUR_CHAN")
222
+ # test for a number, add 3 zeros (bits), else set A_BITRATE to 0
223
+ if test_is_number ${A_BITRATES[i]} && (( ${A_BITRATES[i]} )); then
224
+ A_BITRATES[i]=${A_BITRATES[i]}000
225
+ else
226
+ # probe_audio_info should have same indexes as A_TRACKS
227
+ aud_bitrate=$(awk -F= '/^bit_rate=/ {print $2}' <<< "${probe_audio_info[i]}")
228
+ if test_is_number $aud_bitrate; then
229
+ A_BITRATES[i]=${aud_bitrate%.*}
230
+ else
231
+ A_BITRATES[i]=0
232
+ fi
233
+ fi
234
+ A_CODECS[i]=$(sed -nr 's/.*Audio: (\w+).*/\1/p' <<< "$CUR_CHAN")
235
if $USE_HEX_TRACKS; then
236
MP_TRACKNUM=$((16#${HEX_TRACKS[i]}))
237
else
238
239
fi
240
ID_AUDIO_IDS="$ID_AUDIO_IDS ${MP_TRACKNUM//$'\n'/ }"
241
242
- # last ditch efforts to get audio bitrate if we still don't have it
243
- if test ${A_BITRATES[i]} -eq 0; then
244
- MP_ABITRATE=$(mplayer -nomsgcolor -vo null -ao null -frames 30 \
245
- -channels 6 -identify -aid $MP_TRACKNUM -noconsolecontrols \
246
- "$INFILE" 2>&1 | grep ID_AUDIO_BITRATE|awk -F= 'END{print $2}')
247
- if test_is_number $MP_ABITRATE; then
248
- MP_ABITRATE=${MP_ABITRATE%.*}
249
- A_BITRATES[i]=${MP_ABITRATE/000*}
250
- else # final attempt
251
- MENC_ABITRATE=$(mencoder "$INFILE" -aid $MP_TRACKNUM -oac pcm -ovc copy \
252
- -frames 30 -o /dev/null 2>&1 | awk '/AUDIO/ {print $7}')
253
- test_is_number $MENC_ABITRATE && A_BITRATES[i]=${MENC_ABITRATE%.*}
254
+ # last ditch efforts to get audio {bit,sample}rate if 0
255
+ if (( ${A_BITRATES[i]} == 0 )) || (( ${A_SAMPRATES[i]} == 0 )); then
256
+ MP_CHAN_INFO=$(mplayer -nomsgcolor -vo null -ao null -frames 30 \
257
+ -channels 6 -identify -aid ${MPL_AIDS[i]} -noconsolecontrols \
258
+ "$INFILE" 2>&1)
259
+ # we want the last match: AFTER mplayer plays it a bit
260
+ MP_ABITRATE=$(awk -F= '/^ID_AUDIO_BITRATE=/ {b=$2} END{print b}' <<< "$MP_CHAN_INFO")
261
+ MP_SAMPRATE=$(awk -F= '/^ID_AUDIO_RATE=/ {b=$2} END{print b}' <<< "$MP_CHAN_INFO")
262
+ MP_ABITRATE=${MP_ABITRATE%.*}
263
+ MP_SAMPRATE=${MP_SAMPRATE%.*}
264
+ if test_is_number $MP_ABITRATE && (( MP_ABITRATE )); then
265
+ [[ ${A_BITRATES[i]} = 0 ]] && A_BITRATES[i]=$MP_ABITRATE
266
+ fi
267
+ if test_is_number $MP_SAMPRATE && (( MP_SAMPRATE )); then
268
+ [[ ${A_SAMPRATES[i]} = 0 ]] && A_SAMPRATES[i]=$MP_SAMPRATE
269
fi
270
fi
271
- A_HEX_TRACKS=("${A_HEX_TRACKS[@]}" "$MP_TRACKNUM")
272
+ A_HEX_TRACKS[i]=$MP_TRACKNUM
273
done
274
# use comma separator and remove possible leading comma
275
ID_AUDIO_IDS=${ID_AUDIO_IDS// /,}
276
277
tracks=( ${TRACKS[@]} )
278
if (( ${#tracks[@]} > 0 )); then
279
for i in ${!tracks[@]}; do
280
- map_cmd[i]="-map ${tracks[i]}"
281
- wavs=( "${wavs[@]}" "$TMP_DIR/$i.wav" )
282
+ # for -map seperator needs to be ':' not '.'
283
+ map_cmd[i]="-map ${tracks[i]/./:}"
284
+ wavs[i]="$TMP_DIR/$i.wav"
285
done
286
for r in ${!tracks[@]}; do
287
- test_tracks[r]="$(ffmpeg -i "$INFILE" -ss 2 -t 1 ${map_cmd[r]} -y ${wavs[r]} 2>&1)"
288
+ test_tracks[r]="$($FFmpeg -i "$INFILE" -ss 2 -t 1 ${map_cmd[r]} -y ${wavs[r]} 2>&1)"
289
if grep -q Unsupported <<< "${test_tracks[r]}"; then
290
tracks[r]="Unsupported"
291
fi
292
done
293
- #test_tracks=( "$(ffmpeg -i "$INFILE" -ss 2 -t 1 ${map_cmd[@]} -y ${wavs[@]} 2>&1)" )
294
echo "${test_tracks[@]}" >> "$SCRATCH_FILE"
295
rm -f "${wavs[@]}"
296
fi
297
298
ID_AUDIO_TRACKS=${TRACKS// /,}
299
fi # if test -n "$ID_AUDIO_ID"
300
301
- # If tcprobe reports an aspect ratio, use that
302
- if grep -q "aspect ratio" "$SCRATCH_FILE"; then
303
- RATIO=$(awk '/aspect ratio/ {print $3}' "$SCRATCH_FILE")
304
- V_ASPECT_WIDTH=$(expr ${RATIO%:*} \* 100 \/ ${RATIO#*:})
305
- # Otherwise, infer from mplayer
306
- else
307
- # Infer aspect ratio from width/height of mplayer playback
308
- MPLAYER_RES=$(grep '^VO:' "$SCRATCH_FILE" | \
309
- sed -e "s/..*=> *//g" -e "s/ .*$//g")
310
- #PLAY_WIDTH=$(echo $MPLAYER_RES | awk -F 'x' '{print $1}')
311
- #PLAY_HEIGHT=$(echo $MPLAYER_RES | awk -F 'x' '{print $2}')
312
- # patch from ML:
313
- PLAY_WIDTH=$(echo "$MPLAYER_RES" | awk -F '[x ]' 'BEGIN {wid = 0}; {if ($1 > wid) wid = $1}; END {print wid}')
314
- PLAY_HEIGHT=$(echo "$MPLAYER_RES" | awk -F '[x ]' 'BEGIN {hgt = 0}; {if ($2 > hgt) hgt = $2}; END {print hgt}')
315
- # Fix nulls
316
- if test -z "$PLAY_WIDTH" || test -z "$PLAY_HEIGHT"; then
317
- PLAY_WIDTH="100"
318
- PLAY_HEIGHT="100"
319
- fi
320
- V_ASPECT_WIDTH=$(expr $PLAY_WIDTH \* 100 \/ $PLAY_HEIGHT)
321
+ # Infer aspect ratio from width/height of mplayer playback
322
+ MPLAYER_RES=$(grep '^VO:' "$SCRATCH_FILE" | \
323
+ sed -e "s/..*=> *//g" -e "s/ .*$//g")
324
+ # patch from ML:
325
+ PLAY_WIDTH=$(awk -F '[x ]' 'BEGIN {wid = 0}; {if ($1 > wid) wid = $1}; END {print wid}'<<< "$MPLAYER_RES")
326
+ PLAY_HEIGHT=$(awk -F '[x ]' 'BEGIN {hgt = 0}; {if ($2 > hgt) hgt = $2}; END {print hgt}' <<< "$MPLAYER_RES")
327
+ # fix nulls and division by 0 errors as well (( xxx ))
328
+ if ! (( PLAY_WIDTH )) || ! (( PLAY_HEIGHT )); then
329
+ PLAY_WIDTH="100"
330
+ PLAY_HEIGHT="100"
331
fi
332
+ V_ASPECT_WIDTH=$(expr $PLAY_WIDTH \* 100 \/ $PLAY_HEIGHT)
333
# Normalized aspect ratio
334
- V_ASPECT_RATIO=$(echo $V_ASPECT_WIDTH | \
335
- sed -r -e 's/([0-9]*)([0-9][0-9])/\1.\2:1/g')
336
+ if test_is_number "$V_ASPECT_WIDTH"; then
337
+ V_ASPECT_RATIO=$(sed -r -e 's/([0-9]*)([0-9][0-9])/\1.\2:1/g' \
338
+ <<< "$V_ASPECT_WIDTH")
339
+ fi
340
+ # if mplayer decides there is no video, unset V_ASPECT_WIDTH
341
+ grep -qi "no video" "$SCRATCH_FILE" && unset V_ASPECT_WIDTH
342
343
NAV_LOG="${INFILE}.nav_log"
344
USE_NAVLOG=false
345
346
# if a nav_log file exists and we have a value for FPS, use the log
347
if [[ -s "$NAV_LOG" && ${ID_VIDEO_FPS%%.*} -ne 0 ]]; then
348
! $TERSE && echo "Using $NAV_LOG"
349
- USE_MENCODER=false
350
+ GET_FFMPEG_LEN=false
351
USE_NAVLOG=:
352
else # no nav_log or ID_VIDEO_FPS missing
353
# If doing -fast identification, skip "accurate" length determination
354
if $FAST; then # skip this long process
355
- USE_MENCODER=false # USE_NAV_LOG already set to false
356
+ GET_FFMPEG_LEN=false # USE_NAV_LOG already set to false
357
else
358
- # check if tcdemux present, and if mpg extension (vob uses mencoder)
359
- if grep -qi mpg <<< "${INFILE##*.}" && hash tcdemux 2>/dev/null && \
360
+ # check if tcdemux present, and if mpg extension (vob uses ffmpeg)
361
+ if egrep -qi 'mpg$|mpeg$|vob$' <<< "${INFILE##*.}" && hash tcdemux 2>/dev/null && \
362
[[ ${ID_VIDEO_FPS%%.*} -ne 0 ]]; then
363
NAVSEEK_CMD=(nice tcdemux -f $ID_VIDEO_FPS -W -i "$INFILE")
364
# or check if aviindex installed, and if extension is avi
365
elif grep -qi avi <<< "${INFILE##*.}" && hash aviindex 2>/dev/null && \
366
[[ ${ID_VIDEO_FPS%%.*} -ne 0 ]]; then
367
NAVSEEK_CMD=(nice aviindex -x -i "$INFILE" -o "$NAV_LOG")
368
- else # not $FAST and indexing not possible, so use mencoder
369
- USE_MENCODER=:
370
+ else # not $FAST, no indexing: so use ffmpeg for length/frames
371
+ GET_FFMPEG_LEN=:
372
fi
373
fi
374
if [[ "${NAVSEEK_CMD[@]}" ]]; then
375
"${NAVSEEK_CMD[@]}" > "$NAV_LOG" 2>/dev/null
376
if [[ -s "$NAV_LOG" ]]; then # if non empty lets use it
377
- USE_MENCODER=false
378
+ GET_FFMPEG_LEN=false
379
USE_NAVLOG=:
380
else
381
- # remove empty log and we will use mencoder in next code block
382
+ # remove empty log and we will use ffmpeg in next code block
383
[[ -e "$NAV_LOG" ]] && rm -f "$NAV_LOG"
384
- USE_MENCODER=:
385
+ GET_FFMPEG_LEN=:
386
fi
387
fi
388
fi
389
# set variables from NAV_LOG results
390
if $USE_NAVLOG; then
391
- if grep -qi mpg <<< "${INFILE##*.}"; then
392
- ID_VIDEO_FRAMES=$(cat "$NAV_LOG" | awk 'END{print NR}')
393
+ if egrep -qi 'mpeg$|mpg$|vob$' <<< "${INFILE##*.}"; then
394
+ ID_VIDEO_FRAMES=$(awk 'END{print NR}' "$NAV_LOG" )
395
V_DUR=$(bc <<< "$ID_VIDEO_FRAMES / $ID_VIDEO_FPS")
396
V_DURATION=${V_DUR%%.*} # final value is integer ( seconds )
397
else
398
399
# final value is in seconds
400
V_DURATION=${V_DURATION%%.*} # integer
401
fi
402
- # if no usable value, use mencoder
403
- { ! test_is_number $V_DURATION || ((V_DURATION == 0)) ; } && USE_MENCODER=:
404
+ # if no usable value, use ffmpegs
405
+ { ! test_is_number $V_DURATION || ((V_DURATION == 0)) ; } && GET_FFMPEG_LEN=:
406
fi
407
- # find duration by playing the video with mencoder into /dev/null
408
+ # find duration by playing the video with ffmpeg into /dev/null
409
# any of: no/empty log file, ! $FAST, no tcdemux/aviindex, or not an mpg/avi
410
- if $USE_MENCODER; then
411
- MENCODER_STATS=$(LC_ALL=C mencoder -ovc copy -nosound -noskiplimit \
412
- "$INFILE" -o /dev/null 2>/dev/null)
413
- V_DURATION=$(awk 'END{print $(NF-3)}' <<< "$MENCODER_STATS")
414
- V_DURATION=${V_DURATION%%.*} # integer in seconds
415
+ if $GET_FFMPEG_LEN; then
416
+ ff_opts="-an -vcodec copy -f null -y /dev/null"
417
+ ffmpeg_cmd=($FFmpeg -i "$INFILE" $ff_opts)
418
+ ffmpeg_full_output=$( "${ffmpeg_cmd[@]}" 2>&1 )
419
+ sed_var_time='x;$s/^.*time= *\([^ ]*\).*/\1/p'
420
+ sed_var_frames='{s/^.*frame= *\([^ ]*\).*/\1/p}'
421
+ V_DURATION=$(sed -n "$sed_var_time" <<< "$ffmpeg_full_output")
422
+ test_is_number ${V_DURATION//:} && V_DURATION=$(unformat_time $V_DURATION int) || \
423
+ V_DURATION=0
424
# overwrite ID_VIDEO_FRAMES since we have a more accurate count now
425
- ID_VIDEO_FRAMES=$(awk 'END{print $(NF-1)}' <<< "$MENCODER_STATS")
426
- # if we failed to get a video bitrate earlier, use mencoder stats
427
- if test $ID_VIDEO_BITRATE -eq 0; then
428
- MENCODER_STATS_BR=$(awk -F: 'END{print $2}' <<< "$MENCODER_STATS" | awk '{print $1}')
429
- # make sure it is a number
430
- if test_is_number $MENCODER_STATS_BR; then
431
- ID_VIDEO_BITRATE=${MENCODER_STATS_BR%.*}000
432
- fi
433
+ ID_V_FRAMES=$(sed -n "$sed_var_frames" <<< "$ffmpeg_full_output")
434
+ test_is_number "$ID_V_FRAMES" && ID_VIDEO_FRAMES=$ID_V_FRAMES
435
+ if $VERBOSE; then
436
+ echo "getting video length with ffmpeg"
437
+ echo "$ffmpeg_full_output"
438
fi
439
- $VERBOSE && echo "$MENCODER_STATS"
440
- fi
441
442
- # Use mplayer-reported length as a last resort (truncate floating-point)
443
- test -z $V_DURATION && V_DURATION=$(echo $ID_LENGTH | sed 's/\.[0-9]*//')
444
+ # old stuff
445
+ fi
446
447
+ # try ffmpeg's estimate of duration first, then tcprobe's, then mplayers
448
+ if ! (( ${V_DURATION//:} )); then
449
+ # below from go|dfish on #sed, quits after 1st match (we have 2 matches)
450
+ V_DURATION=$(sed -n '/.*Duration: /{ s///; s/\..*//; p; q; }' "$SCRATCH_FILE")
451
+ if egrep -q '([0-9]+:[0-9][0-9]:[0-9][0-9])' <<< "$V_DURATION"; then
452
+ V_DURATION=$(unformat_time $V_DURATION int)
453
+ else
454
+ V_DURATION=0
455
+ fi
456
+ if ! (( ${V_DURATION//:} )); then
457
+ V_DUR=$(sed -n '/.*duration=/{ s///; s/\..*//; p; q; }' "$SCRATCH_FILE")
458
+ # try ffprobe's (avprobe) output first
459
+ if (( ${vid_duration%.*} )); then
460
+ V_DURATION=${vid_duration%.*}
461
+ # try tcprobe if above fails, if installed, 'failing' silently otherwise
462
+ elif (( ${V_DUR%.*} )); then
463
+ egrep -q '([0-9]+:[0-9][0-9]:[0-9][0-9])' <<< "$V_DURATION" && \
464
+ V_DURATION=$(unformat_time $V_DURATION int)
465
+ else
466
+ V_DURATION=0
467
+ fi
468
+ fi
469
+ # Lastly try mplayer-reported length (secs) (truncate floating-point)
470
+ if ! (( ${V_DURATION} )); then
471
+ V_DURATION=$(sed 's/\.[0-9]*//' <<< "$ID_LENGTH")
472
+ (( V_DURATION )) || V_DURATION=0
473
+ fi
474
+ fi
475
+ # now we have (hopefully) duration and audio bitrate, we can try other ways
476
+ # to get video bitrate if we don't have it yet, from the total bitate
477
+ # or from the file size.
478
+ # make sure of numerical values for audio and video bitrate, then subtract
479
+ if ! test_is_number $ID_VIDEO_BITRATE || ! (( ID_VIDEO_BITRATE )); then
480
+ TOTAL_AV_BITRATE=$(awk -F: '{gsub("kb/s", "")}; /Duration:.*bitrate:/ {print $6*1000;exit}' "$SCRATCH_FILE")
481
+ if test_is_number $TOTAL_AV_BITRATE && (( TOTAL_AV_BITRATE )); then
482
+ (( ID_AUDIO_BITRATE )) && test_is_number $ID_AUDIO_BITRATE && \
483
+ ID_VIDEO_BITRATE=$(( TOTAL_AV_BITRATE - ID_AUDIO_BITRATE ))
484
+ #echo -e "Probed video bitrate not available, infering from total bitrate and audio bitrate\n"
485
+ else
486
+ # infer bitrate from file size and duration
487
+ v_size=$(( $(du -m "$INFILE" | awk '{ print $1 }') * 8192 ))
488
+ if (( ${V_DURATION%.*} )); then
489
+ ID_VIDEO_BITRATE=$(bc -l <<< "$v_size / $V_DURATION")
490
+ ID_VIDEO_BITRATE=$(( v_size / V_DURATION ))000
491
+ #echo -e "Probed video bitrate not available, infering from file size and duration\n"
492
+ fi
493
+ fi
494
+ fi
495
+ # use 0 for unknown video bitrate, same as unknown audio bitrate
496
+ [[ $ID_VIDEO_BITRATE = 0 ]] && ID_VIDEO_BITRATE=0
497
+
498
+ # use {ff,av}probe info to infer frames count, from duration and fps
499
+ # if we already have ID_VIDEO_FRAMES from mplayer, this block does nothing
500
+ if test_is_number $vid_frames && ((vid_frames)); then
501
+ (( $ID_VIDEO_FRAMES == 0 )) && ID_VIDEO_FRAMES=$vid_frames
502
+ elif (( ${V_DURATION%.*} )) && (( ${ID_VIDEO_FPS/./} )); then
503
+ VIDEO_FRAMES=$(bc -l <<< "$V_DURATION * $ID_VIDEO_FPS")
504
+ if (( $ID_VIDEO_FRAMES == 0 )); then
505
+ ID_VIDEO_FRAMES=${VIDEO_FRAMES%.*}
506
+ #echo -e "Probed frame count not available, infering from duration and framerate\n"
507
+ fi
508
+ fi
509
# TODO: WARN if video is less than one second!
510
511
# Mplayer reports ac3 and mp2 incorrectly, so refer to numeric codes
512
513
echo "---------------------------"
514
echo " Codec: ${A_CODECS[j]}"
515
if [[ ${tracks[j]} != Unsupported ]]; then
516
- echo " Bitrate: ${A_BITRATES[j]}000 bits per second"
517
+ echo " Bitrate: ${A_BITRATES[j]} bits per second"
518
echo " Sampling rate: ${A_SAMPRATES[j]} Hz"
519
fi
520
done
521
522
523
# VCD/SVCD must be 44.1khz mp2
524
elif test "$ID_AUDIO_RATE" = "44100" && test "$ID_AUDIO_CODEC" = "mp2"; then
525
- # SVCD can be 32-384 bps, 1-4 channels
526
- if test "$ID_AUDIO_NCH" -le "4" && \
527
+ # SVCD can be 32-384 bps, 1-4 channels - check 1st audio stream only
528
+ if test "${ID_AUDIO_NCH%%,*}" -le "4" && \
529
test "$ID_AUDIO_BITRATE" -ge "32000" && \
530
test "$ID_AUDIO_BITRATE" -le "384000"; then
531
A_SVCD="$ID_AUDIO_NCH-channel $ID_AUDIO_BITRATE bps SVCD"
532
533
esac
534
535
# Find matching video profile(s)
536
+ # some mplayer versions report MPG2 instead of MPEG2 or hex
537
+ test "$ID_VIDEO_FORMAT" = "MPG2" && ID_VIDEO_FORMAT=MPEG2
538
# Test for VCD/DVD-VCD MPEG1 compliance
539
if test "$ID_VIDEO_FORMAT" = "MPEG1" && test "$ID_VIDEO_BITRATE" -le "1856000"; then
540
# VCD compliance
541
542
543
# See what programs are available for doing identification
544
MPLAYER=$(type -p mplayer)
545
-FFMPEG=$(type -p ffmpeg)
546
+FFMPEG=$(type -p $FFmpeg)
547
TCPROBE=$(type -p tcprobe)
548
549
550
551
"-fast" ) FAST=: ;;
552
"-accurate" ) FAST=false ;;
553
"-tabular" ) TABULAR=: ;;
554
+ "-keepfiles" ) KEEPFILES=: ;;
555
"-isformat" )
556
shift
557
MATCH_FORMAT="$1"
558
559
column -s "||" -t "$TABLE"
560
fi
561
562
-rm -rf "$TMP_DIR"
563
+$KEEPFILES || rm -rf "$TMP_DIR"
564
exit 0
565
tovid-0.34.tar.bz2/src/makedvd -> tovid-0.35.tar.gz/src/makedvd
Changed
55
1
2
#
3
# Project homepage: http://tovid.wikia.com
4
#
5
-# Copyright (C) 2005-2010
6
+# Copyright (C) 2005-2015
7
#
8
# This program is free software; you can redistribute it and/or
9
# modify it under the terms of the GNU General Public License
10
11
EOF`
12
13
USAGE=`cat << EOF
14
-Usage: tovid dvd [OPTIONS] FILE.xml
15
- or: tovid dvd [OPTIONS] DVD_DIR
16
+Usage: tovid dvd [OPTIONS] DVD_DIR
17
18
-With FILE.xml, containing dvdauthor XML as generated by 'makexml',
19
-or DVD_DIR, a directory containing a DVD filesystem (VIDEO_TS, namely).
20
+DVD_DIR: a directory containing a DVD filesystem (VIDEO_TS, namely).
21
22
OPTIONS may be any of the following:
23
24
- -author Create DVD filesystem from FILE.xml
25
-burn Burn DVD filesystem from DVD_DIR
26
-eject Eject the DVD tray after burning
27
-device DEVFS_NAME DVD recorder device name (Default: /dev/dvdrw)
28
29
30
# See what kind of file we're working with, and do the right thing
31
# Author an XML file
32
+# This first if block is no longer really needed as makexml has
33
+# been removed from tovid but I will leave it here for now.
34
if echo "$DISC_NAME" | grep -q -i '\.xml$'; then
35
DVDAUTHOR_XML="$DISC_NAME"
36
DO_AUTHOR=:
37
38
export VIDEO_FORMAT=ntsc
39
echo -e '\n***'
40
echo "No default video format defined!!!"
41
- echo "Was this xml created by a recent version of tovid/makexml?"
42
+ echo "Was this xml created by a recent version of tovid/todisc?"
43
echo "Using default video format of 'ntsc'."
44
echo "Run 'export VIDEO_FORMAT=\"pal\"' if this is wrong for your disc."
45
echo -e '\n***'
46
47
echo "Found $DISC_STATUS $DISC_TYPE. Please insert a usable DVD into $DVDRW_DEVICE."
48
for COUNTER in {10..1}; do
49
printf "Trying again in %2s seconds...\r" $((COUNTER * TIME_SCALE))
50
- sleep ${TIME_SCALE}s
51
+ sleep $TIME_SCALE
52
done
53
((COUNT++))
54
echo
55
tovid-0.34.tar.bz2/src/makempg -> tovid-0.35.tar.gz/src/makempg
Changed
440
1
2
#!/usr/bin/env bash
3
-ME="[tovid]:"
4
+ME="[makempg]:"
5
. tovid-init 2>/dev/null ||
6
{ echo -e "===============================================================\n"
7
echo -e "'tovid-init' not found. Was tovid improperly installed?"
8
9
#
10
# Project homepage: http://tovid.wikia.com
11
#
12
-# Copyright (C) 2005-2010
13
+# Copyright (C) 2005-2015
14
#
15
# This program is free software; you can redistribute it and/or
16
# modify it under the terms of the GNU General Public License
17
18
# Audio bitrate (for ac3 or mp2)
19
AUD_BITRATE="224"
20
# Don't generate an empty audio stream
21
+NEWAUDIO_OPT=false
22
GENERATE_AUDIO=false
23
# Amplitude used when adjusting audio (-amplitude)
24
AUDIO_AMPLITUDE=""
25
26
yecho
27
return
28
else
29
- eval "$@" 2>&1 | strings >> "$LOG_FILE" &
30
+ eval "$@" 2>&1 | $std_buf strings >> "$LOG_FILE" &
31
PIDS="$PIDS $!"
32
fi
33
}
34
35
# ******************************************************************************
36
function check_disk_space()
37
{
38
+ # this function is very inaccurate, needs attention
39
# Determine space available in current directory (in MB)
40
- AVAIL_SPACE=$(df -mP . | awk 'NR != 1 {print $4;}')
41
+ # os compatibility patch from 'virtualestates' as per issue #152
42
+ AVAIL_SPACE=$(df -P . | awk 'NR==1 {sub("-blocks", "", $2); blocksize=$2} NR!=1 {print int($4/1024*blocksize/1024)}')
43
# Rough estimates of KB/sec for different formats
44
K_PER_SEC=200
45
test "$TGT_RES" = "VCD" && K_PER_SEC=172
46
47
# based on original file size
48
$SLICE && VIDEO_DURATION=$CLIP_LENGTH || VIDEO_DURATION=$V_DURATION
49
if test "$VIDEO_DURATION" = "0"; then
50
- CUR_SIZE=$(du -Dck \"$IN_FILE\" | awk 'END{print $1}')
51
+ CUR_SIZE=$(du -Dck "$IN_FILE" | awk 'END{print $1}')
52
NEED_SPACE=$(expr $CUR_SIZE \* 2)
53
- yecho "The encoding process will require about"
54
# Estimate space based as kbps * duration
55
else
56
NEED_SPACE=$(expr $VIDEO_DURATION \* $K_PER_SEC \/ 500)
57
- yecho "The encoding process is estimated to require $NEED_SPACE MB of disk space."
58
fi
59
-
60
+ # ffmpeg can do a+v 'at once' so half as much space needed
61
+ $USE_FFMPEG && ! $DO_NORM && ! [[ $ASYNC ]] && NEED_SPACE=$((NEED_SPACE/2))
62
+ yecho "The encoding process is estimated to require $NEED_SPACE MB of disk space."
63
yecho "You currently have $AVAIL_SPACE MB available in this directory."
64
}
65
66
67
"-downmix" )
68
DOWNMIX=:
69
;;
70
- "-ffmpeg" )
71
+ "-ffmpeg" | "-avconv" )
72
USE_FFMPEG=:
73
;;
74
"-nofifo" )
75
76
PEAK_BITRATE=$(grep 'Peak bit-rate' "$LOG_FILE" | awk '{print $6}')
77
if $USE_FFMPEG && ! $DO_NORM && ! $VIDEO_OK; then
78
# get lines with frame= , and print last field with kbit/s removed
79
- bitrates=$(awk -F= '/^frame=/ {gsub("kbits/s", ""); print $NF}' "$LOG_FILE")
80
+ bitrates=$(sed -n 's/kbits\/s//g;s/^.*bitrate= *\([^ ]*\).*/\1/p' "$LOG_FILE")
81
# get highest value, and remove spaces with sed
82
bitrates=$(sort -un <<< "$bitrates" | sed 's/^[ \t]*//;s/[ \t]*$//')
83
# average the values. Add 000, so it is in bits.
84
85
KB_PER_MIN=$(expr $FINAL_SIZE \* 60 \/ $V_DURATION \+ 1)
86
ENC_TIME_RATIO=$(echo "scale = 2; $SCRIPT_TOT_TIME / $V_DURATION" | bc)
87
if $USE_FFMPEG; then
88
- BACKEND="ffmpeg"
89
+ BACKEND="$FFmpeg"
90
else
91
BACKEND="mpeg2enc"
92
fi
93
94
if ! $QUIET; then
95
yecho "Your encoded video should be in the file(s) $OUT_FILENAME."
96
echo
97
- echo "You can author a disc with this video on it by running:"
98
- echo " tovid xml $OUT_FILENAME -out MyDisc"
99
- echo " tovid dvd MyDisc.xml"
100
- echo "You can also use todisc or makemenu to create menus for your disc."
101
- echo "See the tovid manual page ('man tovid') for more information."
102
+ echo "You can author a simple disc with this video on it by running:"
103
+ echo " tovid disc -no-menu \"$OUT_FILENAME\" -out MyDisc"
104
+ echo "Add -burn for a prompt to burn (-device and -speed optional)"
105
+ echo "Or use todisc (tovid disc) to create text-only or animated menus."
106
+ echo "See the manual ('man tovid') for more information and options."
107
echo
108
echo "Please report bugs to:"
109
echo " http://code.google.com/p/tovid/issues/list"
110
111
fi
112
113
if ((USE_FILTERS)) && $USE_FFMPEG; then
114
- usage_error "Sorry, you are using ffmpeg to encode
115
+ usage_error "Sorry, you are using $FFmpeg to encode
116
video, either by choice or another option requires it.
117
You can not use -filters with -ffmpeg"
118
fi
119
+
120
+# see if ffmpeg is new enough to support -b:v etc
121
+# remove this when 0.9x ffmpeg is the oldest tovid will support
122
+# note ffmpeg is used for audio so this must run even when using mpeg2enc
123
+if $FFmpeg -f rawvideo -pix_fmt yuv420p -s cif \
124
+ -i /dev/zero -t 1 -r 30 -f rawvideo \
125
+ -b:v 500k -y /dev/null > /dev/null 2>&1; then
126
+ VB=-b:v
127
+ AB=-b:a
128
+ CA=-c:a
129
+else
130
+ VB=-b
131
+ AB=-ab
132
+ CA=-acodec
133
+fi
134
+
135
# make sure we are not running from the gui and set some options
136
! $FROM_GUI && NOCONSOLE_CONTROLS="-noconsolecontrols"
137
138
139
usage_error "Please provide an output name with the -out option."
140
fi
141
142
+# check that outfile does not contain a comma because of a mpeg2enc limitation
143
+if ! $USE_FFMPEG && [[ "$OUT_PREFIX" = *,* || "$IN_FILE" = *,* ]]; then
144
+ exit_with_error "Comma illegal in -out and -in NAME (mpeg2enc limitation)"
145
+fi
146
+# check that outfile or infile don't use $$ or $[0-9] because of mpeg2 'bug'
147
+if ! $USE_FFMPEG && [[ "$OUT_PREFIX" = *\$\$* || "$IN_FILE" = *\$\$* ]]; then
148
+ exit_with_error '"$$" illegal in -out and -in NAME (mpeg2enc limitation)'
149
+elif ! $USE_FFMPEG && [[ "$OUT_PREFIX" = *\$[0-9]* || "$IN_FILE" = *\$[0-9]* ]]; then
150
+ exit_with_error '"$" followed by a digit illegal in -out and -in NAME (mpeg2enc limitation)'
151
+fi
152
# check that outfile is not a directory
153
if test -d "$OUT_PREFIX"; then
154
exit_with_error "Error: The specified output file is a directory. A filename must be specified."
155
156
157
# If multiple CPUs are available, do multithreading in mpeg2enc
158
if $MULTIPLE_CPUS; then
159
- yecho "Multiple CPUs detected; mpeg2enc and ffmpeg will use multithreading."
160
+ yecho "Multiple CPUs detected; mpeg2enc and $FFmpeg will use multithreading."
161
MTHREAD="--multi-thread 2"
162
FF_THREAD="-threads 4"
163
else
164
165
166
# Check for available space and prompt if it's not enough
167
# not needed if using ffmpeg to encode video and audio "at once"
168
- if ($USE_FFMPEG && (! $DO_NORM || ! [[ $ASYNC ]])) || $PARALLEL; then
169
+ if $PARALLEL; then
170
:
171
else
172
check_disk_space
173
- if test "$AVAIL_SPACE" -lt "$NEED_SPACE" && ! test $FROM_GUI -o $NOASK ; then
174
+ if ((AVAIL_SPACE < NEED_SPACE)) && ! $FROM_GUI && ! $NOASK; then
175
yecho "Available: $AVAIL_SPACE, needed: $NEED_SPACE"
176
echo "It doesn't look like you have enough space to encode this video."
177
echo "Of course, I could be wrong. Do you want to proceed anyway? (y/n)"
178
179
yecho "I can't find any deinterlacing options to use. No deinterlacing"
180
yecho "will be done on this video (but encoding will continue)."
181
yecho "Encoding will resume in 5 seconds..."
182
- sleep 5s
183
+ sleep 5
184
fi
185
# Deinterlacing for ffmpeg
186
FF_ILACE="-deinterlace"
187
188
fi
189
190
# ffmpeg's -vf aspect is more dependable than -aspect, if ffmpeg is new enough
191
-FF_FILTERS=$(ffmpeg -filters 2>&1)
192
+FF_FILTERS=$($FFmpeg -filters 2>&1)
193
# newer ffmpeg's use setdar= and setsar=
194
-if grep -qw ^setdar <<< "$FF_FILTERS"; then
195
+if grep -qw setdar <<< "$FF_FILTERS"; then
196
FF_ASPECT="setdar="
197
# somewhat older rev's used aspect=
198
elif grep -qw ^aspect <<< "$FF_FILTERS"; then
199
200
FF_ASPECT='-aspect '
201
fi
202
# newer ffmpegs using filters use "-vf"
203
-FF_HELP=$(ffmpeg -h 2>&1)
204
+FF_HELP=$($FFmpeg -h full 2>&1)
205
if grep -qw -- -vf <<< "$FF_HELP"; then
206
VF="-vf"
207
# somewhat older is "-vfilters"
208
elif grep -qw -- -vfilters <<< "$FF_HELP"; then
209
VF="-vfilters"
210
else
211
- VF=""
212
+ runtime_error "Your $FFmpeg is too old to support video filters"
213
+fi
214
+# newaudio was removed in ffmpeg 0.9 as it was redundant because of -map opt
215
+grep -qw -- -newaudio <<< "$FF_HELP" && NEWAUDIO_OPT=true
216
+
217
+# we can't really parse which syntax to use for all filters, so here is a test
218
+errors=$( $FFmpeg -i "$IN_FILE" -t 1 \
219
+-vf scale=w=720:h=352,pad=width=720:height=480:x=0:y=64,setdar=16/9 \
220
+-f null -y /dev/null 2>&1)
221
+if grep -qE "Error.*\(width\|height\|setdar\|w=\|h=\)" <<< "$errors"; then
222
+ ff_legacy=1
223
fi
224
225
# Anamorphic widescreen (16:9 output)
226
227
# wasted on letterbox bars (or if the user requested -widetv output).
228
if $ANAMORPH && { ((V_ASPECT_WIDTH >= 153)) || $WIDE_TV ; }; then
229
TGT_ASPECT_WIDTH=177
230
- FF_ASPECT="${FF_ASPECT}16:9"
231
+ ((ff_legacy)) && asp=16:9 || asp=16/9
232
+ FF_ASPECT="${FF_ASPECT}${asp}"
233
ASPECT_FMT="--aspect 3"
234
# For all others, use "non-anamorphic" (4:3 output)
235
# Aspects from 133:100 to 153:100 have minimum pixel wastage
236
# when letterboxed in 4:3
237
else
238
TGT_ASPECT_WIDTH=133
239
- FF_ASPECT="${FF_ASPECT}4:3"
240
+ ((ff_legacy)) && asp=4:3 || asp=4/3
241
+ FF_ASPECT="${FF_ASPECT}${asp}"
242
ASPECT_FMT="--aspect 2"
243
fi
244
245
246
FORCE_FPSRATIO=$TGT_FPSRATIO
247
yecho "Found 1000fps (wmv) source, setting input to $TGT_FPS fps."
248
yecho "Use -fps to force a different input fps (see 'man tovid')"
249
- # TODO: Instead, use a two-pass encoding (since mencoder can
250
- # do -ofps)
251
- # mencoder -ovc copy -oac copy -ofps $TGT_FPSRATIO $INFILE -o twopass
252
- # then do normal encoding on twopass
253
fi
254
255
# If forced FPS was used, apply it
256
257
done
258
testfile="/tmp/$(date +%s).mpg"
259
track_key=${AUDIO_TRACK[max_key]}
260
- ffm_cmd=( ffmpeg -i "$IN_FILE" $FF_THREAD -ss 2 -ab 224k -ac 2 \
261
- -target ntsc-dvd -b 6000k -vframes 1 $VIDEO_MAP \
262
+ ffm_cmd=( $FFmpeg -i "$IN_FILE" $FF_THREAD -ss 2 $AB 224k -ac 2 \
263
+ -target ntsc-dvd $VB 6000k -vframes 1 $VIDEO_MAP \
264
-map ${AIDS[track_key-1]//./:} "$testfile")
265
yecho "Running ${ffm_cmd[@]}"
266
if ! "${ffm_cmd[@]}" >/dev/null 2>&1; then
267
268
AUDIO_WAV_MAP=( "${AUDIO_WAV_MAP[@]}" -map $i:0 )
269
AUDIO_STREAM=( "${AUDIO_STREAM[@]}" "${TMP_DIR}/audio${i}.$AUD_SUF" )
270
STREAM_CHANS=( "${STREAM_CHANS[@]}" ${AUDIO_CHAN[track-1]} "${AUDIO_STREAM[i]}" )
271
- NEW_AUDIO[i]="-acodec ac3 -ab 224k ${AUDIO_CHAN[track-1]} -newaudio"
272
+ # -newaudio for ffmpeg versions prior to 0.9
273
+ $NEWAUDIO_OPT && \
274
+ NEW_AUDIO[i]="$CA ac3 $AB 224k ${AUDIO_CHAN[track-1]} -newaudio"
275
AUDIO_WAV[i]="$TMP_DIR/audio${i}.wav"
276
AUDIO_WAV_CHANS=( "${AUDIO_WAV_CHANS[@]}" ${AUDIO_CHAN[track-1]} "${AUDIO_WAV[i]}" )
277
done
278
279
FF_CHANNEL_MAP="$VIDEO_MAP $AUDIO_MAP"
280
# we don't need the 1st track for -newaudio
281
- unset NEW_AUDIO[0]
282
+ $NEWAUDIO_OPT && unset NEW_AUDIO[0]
283
((${#AUDIO_TRACK[@]} > 1)) && OUTPUT_FILES="each file" && s=s
284
fi
285
286
287
# ******************************************************************************
288
289
if $USE_FFMPEG; then
290
- FF_BITRATE="-b ${VID_BITRATE}k"
291
- FF_SIZE="-s ${INNER_WIDTH}x${INNER_HEIGHT}"
292
+ FF_BITRATE="$VB ${VID_BITRATE}k"
293
+ if ((ff_legacy)); then
294
+ FF_SIZE="scale=${INNER_WIDTH}:${INNER_HEIGHT}"
295
+ else
296
+ FF_SIZE="scale=w=${INNER_WIDTH}:h=${INNER_HEIGHT}"
297
+ fi
298
FF_CODEC="-f mpeg1video"
299
FF_FPS="-r $TGT_FPS"
300
FF_SAMPRATE="-ar $SAMPRATE"
301
# try to get -quality 9 between quality 8 and 10
302
if ((VID_QUALITY == 9)); then
303
FF_ADD_ARGS="-trellis 1"
304
- ! ffmpeg -h 2>&1 | grep -q trellis && usage_error \
305
- "Your ffmpeg is too old to have the '-trellis' switch. Use a -quality setting other than '9'."
306
+ ! grep -q trellis <<< "$FF_HELP" && usage_error \
307
+ "Your $FFmpeg is too old to have the '-trellis' switch. Use a -quality setting other than '9'."
308
fi
309
[[ $TARGET = "DVD-VCD" ]] && FF_ADD_ARGS="$FF_ADD_ARGS -g 12" # experiment FIXME
310
311
312
(( FF_VPIX )) || (( FF_HPIX )) && PAD=1
313
# changed options: -pad{side} to -vf(ilters) pad= .
314
if ((PAD)); then
315
- if [[ $VF ]]; then
316
+ if ((ff_legacy)); then
317
FF_PAD="pad=${TGT_WIDTH}:${TGT_HEIGHT}:${FF_HPIX}:${FF_VPIX}"
318
else
319
- ((FF_HPIX)) && FF_HPAD="-padleft $FF_HPIX -padright $FF_HPIX"
320
- ((FF_VPIX)) && FF_VPAD="-padtop $FF_VPIX -padbottom $FF_VPIX"
321
- FF_PAD="$FF_HPAD $FF_VPAD"
322
- fi
323
+ FF_PAD="pad=width=${TGT_WIDTH}:height=${TGT_HEIGHT}:x=${FF_HPIX}:y=${FF_VPIX}"
324
+ fi
325
fi
326
327
# use single variable for current, or legacy ffmpeg: VF_FILTERS and OLD_OPTS
328
if [[ $VF ]]; then # libavfilter is being used, FF_ASPECT always passed
329
- VF_FILTERS="${FF_PAD},${FF_ASPECT}"
330
+ VF_FILTERS="${FF_SIZE},${FF_PAD},${FF_ASPECT}"
331
VF_FILTERS="$VF ${VF_FILTERS#,}" # add -vf*, axe possible leading comma
332
else # legacy ffmpeg
333
OLD_OPTS="$FF_PAD $FF_ASPECT"
334
fi
335
+ # Remove extraneous commas from filter command
336
+ if test -n "$VF_FILTERS"; then
337
+ VF_FILTERS=$(sed 's/,,/,/g;s/,$//' <<< "$VF_FILTERS")
338
+ fi
339
340
# Target TV system
341
test "$TVSYS" = "PAL" && FF_TARGET="-target pal"
342
343
if $USE_FFMPEG && ! $DO_NORM && [[ -z "$AUDIO_SYNC" ]] && ! $GENERATE_AUDIO; then
344
chan1=${AUDIO_TRACK[0]}
345
yecho
346
- yecho "Using ffmpeg to encode audio and video."
347
+ yecho "Using $FFmpeg to encode audio and video."
348
349
- FF_BITRATE="-b ${VID_BITRATE}k -ab ${AUD_BITRATE}k ${AUDIO_CHAN[chan1-1]} "
350
- FF_ENC_CMD="$PRIORITY ffmpeg -i \"$IN_FILE\" $FF_THREAD $CLIP_SEEK $FF_LENGTH $ASYNC $ASYNC1 \
351
- $FF_TARGET $FF_QUANT $FF_BITRATE $FF_ADD_ARGS $FF_FPS $FF_ILACE \
352
- $FF_SIZE $VF_FILTERS $OLD_OPTS $FF_CHANNEL_MAP"
353
+ FF_BITRATE="$VB ${VID_BITRATE}k $AB ${AUD_BITRATE}k ${AUDIO_CHAN[chan1-1]} "
354
+ FF_ENC_CMD="$PRIORITY $FFmpeg -i \"$IN_FILE\" $FF_THREAD $CLIP_SEEK $FF_LENGTH $ASYNC $ASYNC1 \
355
+ $FF_TARGET $FF_QUANT $FF_ADD_ARGS $FF_ILACE \
356
+ $VF_FILTERS $OLD_OPTS $FF_BITRATE $FF_CHANNEL_MAP"
357
$OVERWRITE && FF_ENC_CMD="$FF_ENC_CMD -y "
358
FF_ENC_CMD="$FF_ENC_CMD \"$OUT_FILENAME\" ${NEW_AUDIO[@]}"
359
yecho "Encoding video and audio with the following command:"
360
361
if $FAKE; then
362
:
363
else
364
- file_output_progress "$OUT_FILENAME" "Encoding with ffmpeg"
365
+ file_output_progress "$OUT_FILENAME" "Encoding with $FFmpeg"
366
wait
367
fi
368
yecho
369
370
yecho "Found compliant audio and dumping the stream."
371
precho "This sometimes causes errors when multiplexing; add '-force' to the tovid command line to re-encode if multiplexing fails."
372
yecho "Copying the existing audio stream with the following command:"
373
- AUDIO_CMD=($PRIORITY ffmpeg $FF_THREAD $CLIP_SEEK $FF_LENGTH -i "$IN_FILE" -vn -acodec copy $AUDIO_MAP "${STREAM_CHANS[@]}")
374
+ AUDIO_CMD=($PRIORITY $FFmpeg $FF_THREAD $CLIP_SEEK $FF_LENGTH -i "$IN_FILE" -vn $CA copy $AUDIO_MAP "${STREAM_CHANS[@]}")
375
yecho "${AUDIO_CMD[@]}"
376
#AUDIO_CMD="$PRIORITY mplayer $MPLAYER_OPTS \"$IN_FILE\" -dumpaudio -dumpfile \"$AUDIO_STREAM\""
377
run_audio_cmd()
378
{
379
"${AUDIO_CMD[@]}" >> "$LOG_FILE" 2>&1 &
380
- #$PRIORITY ffmpeg $CLIP_SEEK $FF_LENGTH -i "$IN_FILE" -vn -acodec copy \
381
- #$AUDIO_MAP "${AUDIO_STREAM[@]}" >> "$LOG_FILE" 2>&1
382
}
383
run_audio_cmd &
384
PIDS="$PIDS $!"
385
386
AUDIO_IN_FILE[1]="${AUDIO_WAV[0]}"
387
388
#AUDIO_CMD="$PRIORITY mplayer $MPLAYER_OPTS -quiet -vc null -vo null $MP_AUDIOTRACK_CMD -ao pcm:waveheader:file=\"$AUDIO_WAV\" \"$IN_FILE\""
389
- AUDIO_CMD=( $PRIORITY ffmpeg -y $FF_THREAD $CLIP_SEEK $FF_LENGTH -i "$IN_FILE" $ASYNC1 $AUDIO_MAP -ar $SAMPRATE -acodec pcm_s16le "${AUDIO_WAV_CHANS[@]}" )
390
+ AUDIO_CMD=( $PRIORITY $FFmpeg -y $FF_THREAD $CLIP_SEEK $FF_LENGTH -i "$IN_FILE" $ASYNC1 $AUDIO_MAP -ar $SAMPRATE $CA pcm_s16le "${AUDIO_WAV_CHANS[@]}" )
391
392
# Generate or dump audio
393
yecho "Normalizing the audio stream${s}."
394
395
yecho
396
fi
397
398
- AUDIO_ENC=( $PRIORITY ffmpeg )
399
+ AUDIO_ENC=( $PRIORITY $FFmpeg )
400
401
if $GENERATE_AUDIO; then
402
# Read input from /dev/zero to generate a silent audio file
403
- AUDIO_ENC=( "${AUDIO_ENC[@]}" -f s16le -i /dev/zero -t $V_DURATION )
404
+ AUDIO_ENC=( "${AUDIO_ENC[@]}" -f s16le -ar 48000 -i /dev/zero -t $V_DURATION )
405
yecho "Generating a silent audio stream with the following command:"
406
else
407
# Encode audio stream directly from the input file
408
AUDIO_ENC=( "${AUDIO_ENC[@]}" -i "${AUDIO_IN_FILE[@]}" )
409
yecho "Encoding audio stream to $AUD_SUF with the following command:"
410
fi
411
- AUDIO_ENC=( "${AUDIO_ENC[@]}" -vn -ab ${AUD_BITRATE}k -ar $SAMPRATE )
412
+ AUDIO_ENC=( "${AUDIO_ENC[@]}" -vn $AB ${AUD_BITRATE}k -ar $SAMPRATE )
413
! $DO_NORM && AUDIO_ENC=( "${AUDIO_ENC[@]}" $CLIP_SEEK $FF_LENGTH $AUDIO_MAP )
414
- AUDIO_ENC=( "${AUDIO_ENC[@]}" -acodec $AUD_SUF)
415
+ AUDIO_ENC=( "${AUDIO_ENC[@]}" $CA $AUD_SUF)
416
$DO_NORM && AUDIO_ENC=( "${AUDIO_ENC[@]}" "${AUDIO_WAV_MAP[@]}" )
417
AUDIO_ENC=( "${AUDIO_ENC[@]}" -y "${STREAM_CHANS[@]}" )
418
"${AUDIO_ENC[@]}" >> "$LOG_FILE" 2>&1 &
419
420
421
# If existing video is OK, skip video encoding and just copy the stream
422
if ! $FORCE_ENCODING && $VIDEO_OK; then
423
- VID_COPY_CMD="mencoder -of rawvideo -nosound -ovc copy \"$IN_FILE\" -o \"$VIDEO_STREAM\""
424
+ VID_COPY_CMD="$FFmpeg -i \"$IN_FILE\" -an -sn -vcodec copy -f rawvideo -o \"$VIDEO_STREAM\""
425
yecho "Copying existing video stream with the following command:"
426
yecho "$VID_COPY_CMD"
427
428
429
if $USE_FIFO; then
430
mkfifo "$YUV_STREAM" || runtime_error "Cannot create fifo $YUV_STREAM"
431
fi
432
- VID_PLAY_CMD="$PRIORITY $MPLAYER $NOCONSOLE_CONTROLS -benchmark -nosound -noframedrop $SUBTITLES -vo yuv4mpeg:file=\"$YUV_STREAM\"${YUV4MPEG_ILACE} $VID_FILTER $MPLAYER_OPTS \"$IN_FILE\" $CLIP_SEEK $MP_FRAMES"
433
+ VID_PLAY_CMD="$PRIORITY $MPLAYER -nomsgcolor $NOCONSOLE_CONTROLS -benchmark -nosound -noframedrop $SUBTITLES -vo yuv4mpeg:file=\"$YUV_STREAM\"${YUV4MPEG_ILACE} $VID_FILTER $MPLAYER_OPTS \"$IN_FILE\" $CLIP_SEEK $MP_FRAMES"
434
if $USE_FFMPEG ; then
435
- VID_ENC_CMD="ffmpeg -i \"$IN_FILE\" $FF_THREAD $CLIP_SEEK $FF_LENGTH -an $FF_TARGET $FF_CODEC $FF_QUANT $FF_BITRATE $FF_ADD_ARGS $FF_ILACE $FF_SIZE $VF_FILTERS $OLD_OPTS -y \"$VIDEO_STREAM\""
436
+ VID_ENC_CMD="$FFmpeg -i \"$IN_FILE\" $FF_THREAD $CLIP_SEEK $FF_LENGTH -an $FF_TARGET $FF_CODEC $FF_QUANT $FF_ADD_ARGS $FF_ILACE $VF_FILTERS $OLD_OPTS $FF_BITRATE -y \"$VIDEO_STREAM\""
437
else
438
VID_ENC_CMD="cat \"$YUV_STREAM\" | $YUVDENOISE $ADJUST_FPS $PRIORITY mpeg2enc --sequence-length $DISC_SIZE --nonvideo-bitrate $NONVIDEO_BITRATE $MTHREAD $ASPECT_FMT $MPEG2_FMT $VID_FPS $VERBOSE $VID_NORM $MPEG2_QUALITY -o \"$VIDEO_STREAM\""
439
fi
440
tovid-0.34.tar.bz2/src/set_chapters -> tovid-0.35.tar.gz/src/set_chapters
Changed
37
1
2
3
import sys
4
import Tkinter as tk
5
-from libtovid.guis.helpers import SetChapters
6
+from libtovid.guis.helpers import SetChaptersGui
7
from os import path
8
9
if len(sys.argv) < 2:
10
- print("Usage: set_chapters.py video")
11
- exit()
12
-
13
-video = sys.argv[1]
14
-if not path.exists(video):
15
- print('Error: %s does not exist' %video)
16
- exit()
17
-
18
-def print_chapters():
19
- if app.get_chapters():
20
- sys.stdout.write(app.get_chapters() + '\n')
21
+ video = None
22
+else:
23
+ video = sys.argv[1]
24
+ if not path.exists(video):
25
+ print('Error: the video file "%s" does not exist' %video)
26
+ exit()
27
28
root = tk.Tk()
29
-app = SetChapters(root, '-menu', 'Mplayer', print_chapters, style='standalone')
30
+app = SetChaptersGui(root, '-osdlevel 3', 'Set chapter points with Mplayer')
31
app.run(video)
32
app.pack()
33
34
-root.mainloop()
35
+app.mainloop()
36
37
tovid-0.34.tar.bz2/src/titleset-wizard -> tovid-0.35.tar.gz/src/titleset-wizard
Changed
1164
1
2
3
import os.path
4
import shlex
5
-import commands
6
-import tkFont
7
import re
8
-from Tkinter import *
9
-from tkMessageBox import *
10
-from tkSimpleDialog import askstring
11
-from tkFileDialog import asksaveasfilename
12
-from subprocess import Popen, PIPE
13
-from libtovid.metagui import Style
14
-from libtovid.metagui.support import PrettyLabel, show_icons, get_photo_image
15
-from libtovid.cli import _enc_arg, Command
16
-from libtovid.util import trim
17
from time import sleep
18
from tempfile import mktemp
19
from sys import argv, exit
20
from base64 import b64encode
21
from copy import deepcopy
22
-
23
-class Wizard(Frame):
24
- """A frame to hold the wizard pages. It will also hold the commands
25
- that will be processed and written out as a script. Its base frame
26
- holds a frame common to all pages that displays an icon, title, and
27
- status panel. It also has a bottom frame that contains the [Next] and
28
- [Exit] buttons. It will hold a list of all of the wizard pages.
29
+from subprocess import Popen, PIPE
30
+from libtovid import xrange
31
+from libtovid.cli import _enc_arg, Command
32
+from libtovid.util import trim
33
+from libtovid.metagui import Style
34
+from libtovid.metagui.support import (
35
+ PrettyLabel, show_icons, get_photo_image
36
+)
37
+
38
+# Python 3 compatibility
39
+try:
40
+ import Tkinter as tk
41
+ import tkFont
42
+ from tkSimpleDialog import askstring
43
+ from tkFileDialog import asksaveasfilename
44
+ from commands import getoutput, getstatusoutput
45
+ from tkMessageBox import (
46
+ askyesno, showwarning, showinfo, showerror, askokcancel
47
+ )
48
+except ImportError:
49
+ import tkinter as tk
50
+ import tkinter.font as tkFont
51
+ from tkinter.simpledialog import askstring
52
+ from tkinter.filedialog import asksaveasfilename
53
+ from subprocess import getoutput, getstatusoutput
54
+ from tkinter.messagebox import (
55
+ askyesno, showwarning, showinfo, showerror, askokcancel
56
+ )
57
+
58
+def get_screen_info(icon):
59
+ """Get window manager's title bar height and screen height.
60
+ This function masquerades as a progress bar.
61
+ winfo_? includes the top panel if it exists, xwininfo just the titlebar.
62
+ Returns tuple: screen h, deco w, deco h.
63
+ """
64
+ try:
65
+ import Tix
66
+ # Python 3
67
+ except ImportError:
68
+ import tkinter.tix as Tix
69
+ import time
70
+ r = Tix.Tk()
71
+ r.withdraw()
72
+ top = Tix.Toplevel(r)
73
+ top.title('Loading ...')
74
+ top.geometry('+0+0')
75
+ show_icons(top, icon)
76
+ top.update_idletasks()
77
+ p = Tix.Meter(top, value=0.0)
78
+ p.pack()
79
+ for i in range(100):
80
+ time.sleep(0.01)
81
+ p.configure(value=(i/100.0))
82
+ p.update_idletasks()
83
+ xid = top.wm_frame()
84
+ # xwininfo returns a geometry string like '+2+23': split it on '+'
85
+ # it tends to give just window decoration h, w rather than including a panel
86
+ Xwininfo = \
87
+ getoutput("xwininfo -frame -id %s |awk '/Corners:/ {print $2}'" %xid)
88
+ X_x = Xwininfo.split('+')[1]
89
+ X_y = Xwininfo.split('+')[2]
90
+ # winfo_x() winfo_y() tend to give panel AND window decoration
91
+ TK_x = top.winfo_x()
92
+ TK_y = top.winfo_y()
93
+ # so subtract the xwininfo x dimension from winfo_x; same for the y dimensions
94
+ # if xwininfo gives a lesser value, assume it just window deco, and subtract it
95
+ # else default to the greater (or equal) value of winfo_x (same for y dimension)
96
+ if TK_x > int(X_x):
97
+ frame_width = TK_x - int(X_x)
98
+ else:
99
+ frame_width = TK_x
100
+ if TK_y > int(X_y):
101
+ frame_height = TK_y - int(X_y)
102
+ else:
103
+ frame_height = TK_y
104
+ screeninfo = top.winfo_screenheight(), frame_width, frame_height
105
+ r.destroy()
106
+ return screeninfo
107
+
108
+
109
+
110
+class Wizard(tk.Frame):
111
+ """A frame to hold the wizard pages.
112
+ It will also hold the commands that will be processed and written out
113
+ as a script. Its base frame holds a frame common to all pages that
114
+ displays an icon, title, and status panel. It also has a bottom frame
115
+ that contains the [Next] and [Exit] buttons.
116
+ It will hold a list of all of the wizard pages.
117
118
master: the Tk() instance called by __main__
119
- icon: Path to an image file (gif) to display on the left frame
120
text: The text for the wizard title above and/or below the icon
121
Use \n to break title into above\nbelow.
122
+ icon: Path to an image file (gif) to display on the left frame
123
+ infile: an infile provided as a saved project, that will be loaded
124
125
"""
126
- def __init__(self, master, text, icon):
127
- Frame.__init__(self, master)
128
+ def __init__(self, master, text, icon, infile=''):
129
+ tk.Frame.__init__(self, master)
130
self.pages = []
131
- self.index = IntVar()
132
+ self.index = tk.IntVar()
133
self.text = text
134
self.icon = icon
135
self.master = master
136
self.root = self._root()
137
self.commands = []
138
+ self.screen_info = []
139
# for cancelling run_gui if exit is called
140
- self.is_running = BooleanVar()
141
+ self.is_running = tk.BooleanVar()
142
self.is_running.set(True)
143
# for waiting on [Next>>>] being pushed to continue titleset loop
144
- self.waitVar = BooleanVar()
145
+ self.waitVar = tk.BooleanVar()
146
self.waitVar.set(False)
147
- # pid for xterm, to allow clean exit
148
- # need this to make sure we don't have zombie processes
149
- self.xterm_is_running = BooleanVar()
150
- self.check = ''
151
- self.xterm_is_running.set(False)
152
+ # variable for name of final script
153
+ self.project = ''
154
+ # variable for possible pre-loaded script -
155
+ self.is_infile = False
156
# bindings for exit
157
self.root.protocol("WM_DELETE_WINDOW", self.confirm_exit)
158
self.root.bind('<Control-q>', self.confirm_exit)
159
self.root.title('Tovid titleset wizard')
160
161
# button frame
162
- self.button_frame = Frame(master)
163
+ self.button_frame = tk.Frame(master)
164
self.button_frame.pack(side='bottom', fill='x', expand=1, anchor='se')
165
- self.exit_button = Button(self.button_frame, text='Exit',
166
+ self.exit_button = tk.Button(self.button_frame, text='Exit',
167
command=self.confirm_exit)
168
self.exit_button.pack(side='left', anchor='sw')
169
- self.next_button = Button(self.button_frame, text='Next >>',
170
+ self.next_button = tk.Button(self.button_frame, text='Next >>',
171
command=self.next)
172
self.next_button.pack(side='right', anchor='se')
173
- self.prev_button = Button(self.button_frame, text='<< Back',
174
+ self.prev_button = tk.Button(self.button_frame, text='<< Back',
175
command=self.previous)
176
# frame for icon and status display
177
- self.frame1 = Frame(master)
178
+ self.frame1 = tk.Frame(master)
179
self.frame1.pack(side='left', anchor='nw', padx=10, pady=80)
180
inifile = os.path.expanduser('~/.metagui/config')
181
style = Style()
182
- style.load(inifile)
183
+ # make sure ~/.metagui and the config file exist
184
+ if os.path.exists(inifile):
185
+ style.load(inifile)
186
+ print("Loading style from config file: '%s'" % inifile)
187
+ else:
188
+ print("Creating config file: '%s'" % inifile)
189
+ style.save(inifile)
190
self.font = style.font
191
self.draw()
192
193
+ # if a script is being loaded (infile), then assign to self.project
194
+ if infile:
195
+ self.is_infile = True
196
+ self.project = infile
197
+
198
def draw(self):
199
# get fonts
200
font = self.font
201
self.lrg_font = self.get_font(font, size=font[1]+4, _style='bold')
202
self.medium_font = self.get_font(font, size=font[1]+2)
203
self.heading_font = self.get_font(font, size=font[1]+8, _style='bold')
204
- fixed = '-misc-fixed-medium-r-normal--13-100-100-100-c-70-iso8859-1'
205
- self.fixed_font = tkFont.Font(font=fixed)
206
+ #fixed = '-misc-fixed-medium-r-normal--13-100-100-100-c-70-iso8859-1'
207
self.background = self.root.cget('background')
208
if self.text:
209
txt = self.text.split('\n')
210
- app_label1 = Label(self.frame1, text=txt[0], font=self.heading_font)
211
+ app_label1 = tk.Label(self.frame1, text=txt[0], font=self.heading_font)
212
app_label1.pack(side='top', fill='both', expand=1, anchor='nw')
213
# icons and image
214
if os.path.isfile(self.icon):
215
img = get_photo_image(self.icon, 0, 0, self.background)
216
self.img = img
217
# Display the image in a label on all pages
218
- img_label = Label(self.frame1, image=self.img)
219
+ img_label = tk.Label(self.frame1, image=self.img)
220
img_label.pack(side='top', fill='both', expand=1,
221
anchor='nw', pady=20)
222
# If Tcl supports it, generate an icon for the window manager
223
224
print('%s does not exist' % img_file)
225
# if 2 lines of text for image, split top and bottom
226
if self.text and len(txt) > 1:
227
- app_label2 = Label(self.frame1, text=txt[1], font=self.lrg_font)
228
+ app_label2 = tk.Label(self.frame1, text=txt[1], font=self.lrg_font)
229
app_label2.pack(side='top', fill='both', expand=1, anchor='nw')
230
231
def next(self):
232
- """Move to the next wizard page"""
233
+ """Move to the next wizard page.
234
+ """
235
index = self.index.get()
236
try:
237
self.pages[index].hide_page()
238
239
self.pages[index].previous()
240
241
def set_pages(self, page):
242
- """Accept incoming list of wizard page instances"""
243
+ """Accept incoming list of wizard page instances.
244
+ """
245
self.pages.append(page)
246
247
+ def set_screen_info(self, iterable):
248
+ self.screen_info = iterable
249
+
250
def get_font(self, font_descriptor, name='', size='', _style=''):
251
- """Get metagui font configuration
252
+ """Get metagui font configuration.
253
"""
254
font = [name, size, _style]
255
for i in range(len(font_descriptor)):
256
257
return tuple(font)
258
259
def show_status(self, status):
260
- """Show status label on all pages, with timeout
261
+ """Show status label on all pages, with timeout.
262
"""
263
if status == 0:
264
text='\nOptions saved!\n'
265
else:
266
text='\nCancelled!\n'
267
font = self.medium_font
268
- status_frame = Frame(self.frame1, borderwidth=1, relief=RAISED)
269
+ status_frame = tk.Frame(self.frame1, borderwidth=1, relief=tk.RAISED)
270
status_frame.pack(pady=40)
271
- label1 = Label(status_frame, text=text, font=font, fg='blue')
272
+ label1 = tk.Label(status_frame, text=text, font=font, fg='blue')
273
label1.pack(side='top')
274
- label2 = Label(status_frame, text='ok', borderwidth=2, relief=GROOVE)
275
+ label2 = tk.Label(status_frame, text='ok', borderwidth=2, relief=tk.GROOVE)
276
label2.pack(side='top')
277
- self.root.after(1000, lambda: label2.configure(relief=SUNKEN))
278
+ self.root.after(1000, lambda: label2.configure(relief=tk.SUNKEN))
279
self.root.after(2000, lambda: status_frame.pack_forget())
280
281
def confirm_exit(self, event=None):
282
"""Exit the GUI, with confirmation prompt.
283
"""
284
- mess = 'Xterm is still open: is todisc still running? ' + \
285
- 'If so, please ctrl-c in the terminal if you wish to quit. ' + \
286
- 'In any case, you will need to close the terminal ' + \
287
- 'by pressing <ENTER> in it.'
288
- if self.xterm_is_running.get() == True:
289
- showwarning(message=mess)
290
- return
291
if askyesno(message="Exit?"):
292
# set is_running to false so the gui doesn't get run
293
self.is_running.set(False)
294
+ # remove project file if we quit early and it exists and is empty
295
+ if os.path.exists(self.project):
296
+ if os.stat(self.project).st_size == 0:
297
+ print('removing empty file: %s' %self.project)
298
+ os.remove(self.project)
299
# waitVar may cause things to hang, spring it
300
self.set_waitvar()
301
self.root.quit()
302
303
# unused
304
def kill_pid(self, pid):
305
- """Test and kill xterm pid in case of premature exit"""
306
+ """Test and kill xterm pid in case of premature exit.
307
+ """
308
if not pid:
309
return
310
- test_pid = commands.getstatusoutput('kill -0 %s' %pid)
311
+ test_pid = getstatusoutput('kill -0 %s' %pid)
312
if test_pid[0] == 0:
313
cmd = ['kill', '%s' %pid]
314
Popen(cmd, stderr=PIPE)
315
316
def set_waitvar(self):
317
- """Set a BooleanVar() so tk.wait_var can exit
318
+ """Set a BooleanVar() so tk.wait_var can exit.
319
"""
320
self.waitVar.set(True)
321
322
323
-class WizardPage(Frame):
324
- """Base class for the wizard pages. As such it contains everythig
325
- common to all wizard pages.
326
+class WizardPage(tk.Frame):
327
+ """Base class for the wizard pages.
328
+ As such it contains everythig common to all wizard pages.
329
"""
330
def __init__(self, master):
331
- Frame.__init__(self, master)
332
- Frame.pack(master)
333
+ tk.Frame.__init__(self, master)
334
+ tk.Frame.pack(master)
335
self.master = master
336
self.root = self._root()
337
- # a temp file name for the final script name if it exists already
338
- curdir = os.path.abspath('')
339
- self.newname = mktemp(suffix='.bash', prefix='todisc_commands.',
340
- dir=curdir)
341
# get tovid prefix
342
- tovid_prefix = commands.getoutput('tovid -prefix')
343
+ tovid_prefix = getoutput('tovid -prefix')
344
self.tovid_prefix = os.path.join(tovid_prefix, 'lib', 'tovid')
345
os.environ['PATH'] = self.tovid_prefix + os.pathsep + os.environ['PATH']
346
- # the script we will be using for options
347
- cur_dir = os.path.abspath('')
348
- self.script_file = cur_dir + '/todisc_commands.bash'
349
# get script header
350
shebang = '#!/usr/bin/env bash'
351
_path = 'PATH=' + self.tovid_prefix + ':$PATH'
352
353
identifier = '# tovid project script\n# tovid version %s' % _version
354
self.header = '%s\n\n%s\n\n%s\n\n' % (shebang, identifier, _path )
355
# ititialize a frame, but don't pack yet
356
- self.frame = Frame(self.master)
357
+ self.frame = tk.Frame(self.master)
358
# initialize widgets, but don't show yet
359
self.master.set_pages(self)
360
+ self.titlebar_width, self.titlebar_height = self.master.screen_info[1:]
361
362
def show_page(self):
363
wizard = self.master
364
365
def hide_page(self):
366
self.frame.pack_forget()
367
368
- def run_gui(self, args=[], index='', script=''):
369
- """Run the tovid GUI, collecting options, and saving to wizard
370
+ def get_screen_position(self):
371
+ """get real screen position, taking into account window decorations.
372
+ """
373
+ r = self.root
374
+ r.update_idletasks() # make sure geometry is updated before we 'get' it
375
+ geo_x = r.winfo_rootx() - self.titlebar_width
376
+ geo_y = r.winfo_rooty() - self.titlebar_height
377
+ return '+%s+%s' %(geo_x, geo_y)
378
+
379
+ def check_int(self, List):
380
+ """return list of ints from list of strings, checking 1st if castable.
381
+ """
382
+ for index, item in enumerate(List):
383
+ try:
384
+ List[index] = int(item)
385
+ except ValueError:
386
+ return []
387
+ return List
388
+
389
+ def run_gui(self, args=[], index='', project=''):
390
+ """Run the tovid GUI, collecting options, and saving to wizard.
391
"""
392
title = 'load saved script'
393
- script = 'todisc_commands.bash'
394
- set_env = []
395
if index:
396
os.environ['METAGUI_WIZARD'] = '%s' %index
397
- cmd = ['todiscgui'] + args
398
- todiscgui_cmd = Popen(cmd, stdout=PIPE)
399
+ self.root.update_idletasks() # update geometry before it is 'deiconified'
400
+ self.screen_pos = self.get_screen_position()
401
+ # these 2 are just convenience vars for shorter line length
402
+ script = self.master.project
403
+ position = self.screen_pos
404
+ # get modification time of the script, so we can see if it changes
405
+ mtime = os.path.getmtime(script)
406
+ #cmd = ['todiscgui'] + ['--position', self.screen_pos] + ['--project', self.master.project.get()] + args
407
+ cmd = ['todiscgui', '--position', position, '--project', script] + args
408
+ todiscgui_cmd = Popen(cmd, stdout=PIPE, stderr=PIPE)
409
# sleep to avoid the 'void' of time before the GUI loads
410
sleep(0.5)
411
if self.root.state() is not 'withdrawn':
412
self.root.withdraw()
413
- status = todiscgui_cmd.wait()
414
- if status == 200:
415
- # if script doesn't exist prompt for load.
416
- if os.path.exists(self.script_file):
417
- script = self.script_file
418
- else:
419
- err = 'A problem has occured with saving your options. ' + \
420
- 'The saved script file was not found. ' + \
421
- 'Please submit a bug report'
422
- showerror(message=err)
423
- return
424
+ todiscgui_cmd.wait()
425
+ # hack to deiconify wizard at same position as the exiting tovid gui
426
+ for line in todiscgui_cmd.stderr.readlines():
427
+ L = line.split(b'+') # python 3 compatibility (b'')
428
+ if b'gui position ' in L and len(L) == 3:
429
+ result = self.check_int(L[-2:])
430
+ if result:
431
+ x = result[0]-self.master.screen_info[1]
432
+ y = result[1]-self.master.screen_info[2]
433
+ self.screen_pos = '+%d+%d' %(x, y)
434
+ break
435
+
436
+ # if modification time changed, then the script was saved from the gui
437
+ if os.path.getmtime(script) > mtime:
438
# Read lines from the file and reassemble the command
439
todisc_opts = self.script_to_list(script)
440
- os.remove(script)
441
+ # blank file: don't remove as we need it to get mtime in run_gui()
442
+ open(script, 'w').close()
443
else:
444
todisc_opts = []
445
+ # set wizard screen position again, then update
446
+ self.root.geometry(self.screen_pos)
447
+ self.root.update_idletasks()
448
return todisc_opts
449
450
def page_controller(self):
451
self.master.next()
452
453
- def script_to_list(self, infile):
454
- """File contents to a list, trimming '-from-gui' and header
455
+ def script_to_list(self, script):
456
+ """File contents to a list, trimming '-from-gui' and header.
457
"""
458
add_line = False
459
command = ''
460
- for line in open(infile, 'r'):
461
+ for line in open(script, 'r'):
462
if line.startswith('-'):
463
add_line = True
464
if add_line and not line.startswith('-from-gui'):
465
466
return shlex.split(command)
467
468
def write_script(self):
469
- """Write out the final script to todisc_commands.bash
470
+ """Write out the final script to project filename.
471
"""
472
commands = self.master.commands
473
header = self.header
474
- cmdout = open(self.script_file, 'w')
475
- os.chmod(self.script_file, 0775)
476
+ cmdout = open(self.master.project, 'w')
477
+ # mode compatibility for 2.4 to 3.x python
478
+ os.chmod(self.master.project, int('755', 8))
479
# add the shebang, PATH, and 'todisc \' lines
480
cmdout.writelines(header)
481
# flatten the list
482
483
cmdout.close()
484
485
def trim_list_header(self, cmds):
486
- """Trim header (items before 1st '-' type option) from a list
487
+ """Trim header (items before 1st '-' type option) from a list.
488
"""
489
# remove shebang, identifier and PATH
490
try:
491
492
return chunk
493
494
def get_list_args(self, items, option):
495
- """Get option arguments from a list (to next item starting with '-')
496
+ """Get option arguments from a list (to next item starting with '-').
497
"""
498
try:
499
index = items.index(option)
500
501
return chunk
502
503
def see_me(self, widget):
504
- """Bring attention to widget by changing text colour
505
+ """Bring attention to widget by changing text colour.
506
"""
507
# 3000 and 4000 ms because show_status uses up 3000 already
508
self.root.after(3000, lambda: widget.configure(foreground='blue'))
509
510
511
512
def refill_listbox(self, listbox, opts):
513
- """Repopulate the rerun listbox with option list titles
514
+ """Repopulate the rerun listbox with option list titles.
515
"""
516
if '-titles' in opts:
517
new_titles = self.get_list_args(opts, '-titles')
518
519
for i in xrange(numtitles):
520
listbox.insert('end', new_titles[i])
521
522
- def rename_script(self):
523
+ # unused (note self.script_file also unused now)
524
+ def rename_script(self, path):
525
# if todisc_commands.bash exists in current dir, prompt for rename
526
rename_msg = 'The option file we will use:\n' + \
527
- '"todisc_commands.bash"\n' + \
528
+ self.master.script.get() + '\n' + \
529
'exists in the current directory.\n' + \
530
'It will be renamed to:\n' + \
531
'"%s"' + \
532
533
534
535
class Page1(WizardPage):
536
- """Wizard intro page"""
537
+ """Wizard intro page.
538
+ """
539
def __init__(self, master):
540
WizardPage.__init__(self, master)
541
# draw the page by default unless script file arg passed
542
- if len(argv) < 2:
543
+ if not self.master.is_infile:
544
self.draw()
545
- index = self.master.pages.index(self)
546
- self.master.index.set(index)
547
+ index = self.master.pages.index(self)
548
+ self.master.index.set(index)
549
550
def draw(self):
551
self.frame.pack(side='right', fill='both', expand=1, anchor='nw')
552
553
554
555
class Page2(WizardPage):
556
- """Wizard general options page"""
557
+ """Wizard general options page.
558
+ """
559
def __init__(self, master):
560
WizardPage.__init__(self, master)
561
562
563
self.frame.pack(side='right', fill='both', expand=1, anchor='nw')
564
text = '''GENERAL OPTIONS
565
566
+ Please set a name for your 'project' in the box at the bottom of the page,
567
+ by pressing the "Browse" button, and browsing to the directory you want
568
+ to save it. This will be a bash script that can be run standalone, or
569
+ reloaded into the titleset-wizard for further editing.
570
+
571
When you press the "Next >>>" button at the bottom of the wizard, we
572
will start the GUI and begin with general options applying to all
573
titlesets. For example you may wish to have all menus share a common
574
575
bottom of the GUI's main tab. Options you enter will be overridden if
576
you use the same option again later for titlesets.
577
578
- After making your selections, press [ Save to wizard ] in the GUI
579
+ In the GUI, after making your selections, press [ Save to wizard ].
580
581
- Press "Next >>>" to begin ...
582
+ Enter a project name, then press "Next >>>"
583
'''
584
text = trim(text)
585
self.label = PrettyLabel(self.frame, text, self.master.font)
586
self.label.pack(fill='both', expand=1, anchor='nw')
587
+ # setting project name
588
+ self.project_label = tk.Label(self.frame, text='Project name', font=self.master.font,
589
+ justify='left', padx=10, pady=10)
590
+ self.project_label.pack(fill='both', expand=1, anchor='sw')
591
+ self.project_frame = tk.Frame(self.frame)
592
+ self.project_entry = tk.Entry(self.project_frame, width=50)
593
+ self.project_entry.insert(0, 'Press Browse Button')
594
+ self.project_entry.bind("<KeyPress>", lambda e: "break")
595
+ self.browse_button = tk.Button(self.project_frame, text="Browse...",
596
+ command=self.browse)
597
+ self.project_frame.pack(fill='both', expand=1, anchor='sw')
598
+ self.project_entry.pack(side='left')
599
+ self.browse_button.pack(side='right')
600
601
def page_controller(self):
602
- if os.path.exists(self.script_file):
603
- self.rename_script()
604
+ if not self.master.project:
605
+ # here we need a popup telling user to enter a project name #FIXME
606
+ return
607
wizard = self.master
608
index = wizard.index.get()
609
move = True
610
611
move = False
612
else:
613
status = 0
614
- cmds = [l for l in cmds if l]
615
+ cmds = [L for L in cmds if L]
616
wizard.commands.append(cmds)
617
wizard.show_status(status)
618
self.root.deiconify()
619
if move:
620
wizard.next()
621
622
+ def browse(self, e=None):
623
+ title = 'Type a filename'
624
+ filename = asksaveasfilename(parent=self, title=title, initialfile='my_project.tovid')
625
+ if filename:
626
+ self.project_entry.delete(0, 'end')
627
+ self.project_entry.insert(0, filename)
628
+ self.master.project = filename
629
+ open(filename, 'w').close()
630
631
class Page3(WizardPage):
632
- """Wizard root menu page"""
633
+ """Wizard root menu page.
634
+ """
635
def __init__(self, master):
636
WizardPage.__init__(self, master)
637
638
639
self.titlebox = TitleBox(self.frame, text="Root 'menu link' titles")
640
641
def save_list(self):
642
- """Save the current listbox contents
643
+ """Save the current listbox contents.
644
"""
645
# get a list of listbox lines
646
temp_list = list(self.titlebox.get(0, 'end'))
647
- return [ l for l in temp_list if l]
648
+ return [ L for L in temp_list if L]
649
650
def page_controller(self):
651
wizard = self.master
652
run_cmds = list(self.titlebox.get(0, 'end'))
653
- run_cmds = [l for l in run_cmds if l]
654
+ run_cmds = [L for L in run_cmds if L]
655
if len(run_cmds) < 2:
656
showerror(message=\
657
'At least two titlesets (titles) must be defined')
658
659
660
661
class Page4(WizardPage):
662
- """Wizard titleset menu page"""
663
+ """Wizard titleset menu page.
664
+ """
665
def __init__(self, master):
666
WizardPage.__init__(self, master)
667
668
669
text1 = trim(text1)
670
self.label1 = PrettyLabel(self.frame, text1, self.master.font)
671
self.label1.pack(fill='both', expand=True, side='top', anchor='nw')
672
- self.frame2 = Frame(self.frame, borderwidth=2, relief=GROOVE)
673
- self.label2 = Label(self.frame2, text='', font=self.master.font,
674
+ self.frame2 = tk.Frame(self.frame, borderwidth=2, relief=tk.GROOVE)
675
+ self.label2 = tk.Label(self.frame2, text='', font=self.master.font,
676
justify='left', padx=10, pady=10)
677
self.label2.pack(fill='both', expand=True, side='top', anchor='nw')
678
679
680
681
682
class Page5(WizardPage):
683
- """Final wizard page. Here you can rerun options that have been saved
684
- from the tovid GUI, and add or remove titlesets. You can also
685
- choose to run the final project
686
+ """Final wizard page.
687
+ Here you can rerun options that have been saved from the tovid GUI, and
688
+ add or remove titlesets. You can also choose to run the final project.
689
"""
690
def __init__(self, master):
691
WizardPage.__init__(self, master)
692
self.curindex = 0
693
self.lastindex = 0
694
- # set commands and draw this page if script file arg passed
695
- if len(argv) > 1:
696
+ # set commands and draw by default if script (infile) arg passed
697
+ # self.master.project.get() would be set to that file
698
+ if self.master.is_infile:
699
self.set_project_commands()
700
self.draw()
701
index = self.master.pages.index(self)
702
703
Edit or reorder your selections using the listbox below. (Note
704
that menu link titles as shown in listbox are saved as titles
705
in the "Root menu" options.) If you are happy with your saved
706
- options, run the script now , or exit and run it later.
707
- You can run it later with:
708
+ options, run the script now in an xterm, or exit and run it later.
709
+ You can run it with:
710
711
bash %s
712
713
714
tovid titlesets %s
715
716
Edit your selections, or press [Run script now] or [Exit].
717
- ''' % (self.script_file, self.script_file)
718
+ ''' % (self.master.project, self.master.project)
719
+
720
text = trim(text)
721
- self.heading_label = Label(self.frame, text='Finished!',
722
- font=wizard.lrg_font)
723
- self.label = PrettyLabel(self.frame, text,
724
- wizard.font, height=18)
725
+ self.heading_label = tk.Label(self.frame,
726
+ text='Your script is ready to run!', font=wizard.lrg_font)
727
+ self.label = tk.Label(self.frame, text=text,
728
+ font=wizard.font, justify='left')
729
self.heading_label.pack(fill='both', expand=1, anchor='nw', pady=5)
730
self.label.pack(fill='both', expand=1, anchor='nw')
731
- # create the listbox (note that size is in characters)
732
+
733
frame_text = "Edit items, or add, remove or drag/drop titlesets"
734
- frame2 = LabelFrame(self.frame, text=frame_text)
735
- button_frame = Frame(frame2)
736
- button_frame.pack(side='bottom', fill=X, expand=1, anchor='sw')
737
- button2 = Button(button_frame, text='Add titleset',
738
+ frame2 = tk.LabelFrame(self.frame, text=frame_text)
739
+ button_frame = tk.Frame(frame2)
740
+ button_frame.pack(side='bottom', fill=tk.X, expand=1, anchor='sw')
741
+ button2 = tk.Button(button_frame, text='Add titleset',
742
command=self.add_titleset)
743
button2.pack(side='left', anchor='w')
744
- button1 = Button(button_frame, text='Edit', command=self.rerun_options)
745
+ button1 = tk.Button(button_frame, text='Edit', command=self.rerun_options)
746
button1.pack(side='left', fill='x', expand=1)
747
- button3 = Button(button_frame, text='Remove titleset',
748
+ button3 = tk.Button(button_frame, text='Remove titleset',
749
command=self.remove_titleset)
750
button3.pack(side='right', anchor='e')
751
- self.listbox = Listbox(frame2, width=50, exportselection=0)
752
+ self.listbox = tk.Listbox(frame2, width=50, exportselection=0)
753
self.listbox.pack(side='left', fill='both', expand=1)
754
self.listbox.bind('<Double-Button-1>', self.rerun_options)
755
# create a vertical scrollbar to the right of the listbox
756
- yscroll = Scrollbar(frame2, command=self.listbox.yview,
757
+ yscroll = tk.Scrollbar(frame2, command=self.listbox.yview,
758
orient='vertical')
759
yscroll.pack(side='right', fill='y', anchor='ne')
760
self.listbox.configure(yscrollcommand=yscroll.set)
761
762
temp_list[index_b] = item_a
763
except IndexError:
764
# should not happen
765
- print 'index out of range!'
766
+ print('index out of range!')
767
# Set the updated list
768
self.listbox.delete(0, 'end')
769
self.listbox.insert(0, *temp_list)
770
771
self.write_script()
772
773
def set_index(self, Event=None):
774
- """Called when item in listbox selected. Set curindex and change
775
- cursor to double-arrow. lastindex==curindex if no drag occurs.
776
+ """Called when item in listbox selected.
777
+ Set curindex and change cursor to double-arrow.
778
+ lastindex==curindex if no drag occurs.
779
"""
780
self.curindex = self.listbox.nearest(Event.y)
781
self.lastindex = self.curindex
782
783
784
# used to repopulate titleset titles after adding new one
785
def get_option(self, items, option):
786
- """Get option and arguments from a list (to next item starting with '-')
787
+ """Get option and args from a list (to next item starting with '-').
788
The list is modified in place.
789
"""
790
try:
791
792
self.write_script()
793
794
def mod_sublist(self, item='', *index):
795
- """Modify commands sublist. If 2 indexes, just swap items. If one
796
- index the default behavior is to delete the index from the sublist
797
- and remove it from commands, but if item is passed, add it as a
798
- new index instead.
799
+ """Modify commands sublist.
800
+ If 2 indexes, just swap items.
801
+ If one index the default behavior is to delete the index from the
802
+ sublist and remove it from commands, but if item is passed,
803
+ add it as a new index instead.
804
"""
805
wizard = self.master
806
vmgm_cmds = [w for w in wizard.commands[1]]
807
808
wizard.commands.insert(1, vmgm_cmds)
809
810
def rerun_options(self, Event=None, index=None):
811
- """Run the gui with the selected options
812
+ """Run the gui with the selected options.
813
"""
814
# self.master is the WizardPage
815
commands = self.master.commands
816
817
# the GUI doesn't understand the titleset type options
818
remove = ['-vmgm', '-end-vmgm', '-titleset', '-end-titleset']
819
options = [ i for i in commands[index] if not i in remove ]
820
- rerun_opts = self.run_gui(options, '%s' %(index+1))
821
+ rerun_opts = self.run_gui(options, '%d' %(index+1))
822
if rerun_opts:
823
status = 0
824
# trim header from todisc_cmds
825
826
def set_project_commands(self):
827
in_contents = self.script_to_list(argv[1])
828
in_cmds = in_contents[:]
829
- all = [self.get_chunk(in_cmds, '-vmgm', '-end-vmgm')]
830
+ _all = [self.get_chunk(in_cmds, '-vmgm', '-end-vmgm')]
831
while '-titleset' in in_cmds:
832
- all.append( self.get_chunk(in_cmds, '-titleset', '-end-titleset') )
833
- all.insert(0, in_cmds)
834
- self.master.commands = all
835
+ _all.append( self.get_chunk(in_cmds, '-titleset', '-end-titleset') )
836
+ _all.insert(0, in_cmds)
837
+ self.master.commands = _all
838
839
def load_project(self):
840
- """Load a saved project script for editing with the wizard and GUI
841
+ """Load a saved project script for editing with the wizard and GUI.
842
"""
843
- self.heading_label.configure(text='Editing a saved project')
844
+ script = os.path.abspath(self.master.project)
845
+ #self.heading_label.configure(text='Editing a saved project')
846
error_msg = 'This is not a saved tovid project script. ' + \
847
'Do you want to try to load it anyway?'
848
if not '# tovid project script\n' in open(argv[1], 'r'):
849
850
quit()
851
numtitles = len(self.master.commands[2:])
852
menu_titles = []
853
- l = self.master.commands[1]
854
- menu_titles.extend(self.get_list_args(l, '-titles'))
855
+ L = self.master.commands[1]
856
+ menu_titles.extend(self.get_list_args(L, '-titles'))
857
self.refill_listbox(self.listbox, menu_titles)
858
self.listbox.selection_set('end')
859
- # write out todisc_commands.bash in current dir
860
- # if it exists in current dir, prompt for rename
861
- if os.path.exists(self.script_file):
862
- mess = '%s has been loaded for editing. Your ' %self.script_file + \
863
- 'new edits will be saved to the same file. Continue?'
864
+ # write out to project filename
865
+ if os.path.exists(script):
866
+ infile_prefix = os.path.basename(script)
867
+ backup = mktemp(prefix=infile_prefix + '.', dir='/tmp')
868
+ backup_prefix = os.path.basename(backup)
869
+ mess = '%s has been loaded for editing, ' %infile_prefix + \
870
+ 'and will be used for new edits. A backup ' + \
871
+ 'will be saved to /tmp .\n' + \
872
+ 'Continue ?'
873
if askokcancel\
874
(message=mess):
875
pass
876
else:
877
quit()
878
+ from shutil import copyfile
879
+ copyfile(script, backup)
880
self.write_script()
881
882
class Page6(WizardPage):
883
884
wizard.prev_button.pack(side='right', anchor='se')
885
886
text1='Running saved project'
887
- self.label = Label(self.frame, text=text1, font=wizard.lrg_font)
888
+ self.label = tk.Label(self.frame, text=text1, font=wizard.lrg_font)
889
self.label.pack(side='top', fill='both', expand=1, anchor='nw', pady=5)
890
cmd_labelfont = wizard.get_font(wizard.font, _style='bold')
891
- self.cmd_title = Label(self.frame,
892
+ self.cmd_title = tk.Label(self.frame,
893
font=cmd_labelfont, text='\n\n\nThe command that will run:')
894
self.cmd_title.pack(fill='both', expand=1)
895
self.cmd_str = ''
896
index = wizard.index.get()
897
- self.cmd_label = Label(self.frame, text=self.cmd_str, justify='left',
898
- font=wizard.fixed_font, wraplength=560, fg='white', bg='black')
899
+ try:
900
+ self.fixed_font = tkFont.Font(font=('TkFixedFont'))
901
+ self.fixed_font.configure(size=9)
902
+ xterm_font = [ '-fa', self.fixed_font.actual()['family']]
903
+ fsize = ['-fs', str(self.fixed_font.actual()['size'])]
904
+ self.xterm_cmd = ['xterm'] + fsize + xterm_font
905
+ # tcl/tk < 8.5: no freetype support or 'Standard fonts' like tkFixedFont
906
+ except tk._tkinter.TclError:
907
+ self.fixed_font = tkFont.Font(font='7x14')
908
+ xterm_font = ['-fn', '7x14']
909
+ self.xterm_cmd = ['xterm'] + xterm_font
910
+ self.cmd_label = tk.Label(self.frame, text=self.cmd_str, justify='left',
911
+ font=self.fixed_font, wraplength=560, fg='white', bg='black')
912
self.cmd_label.pack(fill='both', expand=1)
913
- self.termtitle = Label(self.master, text='\nFocus mouse in terminal')
914
- self.button_frame = Frame(self.frame, borderwidth=2, relief='groove')
915
+ self.termtitle = tk.Label(self.master, text='\nFocus mouse in terminal')
916
+ self.button_frame = tk.Frame(self.frame, borderwidth=2, relief='groove')
917
self.button_frame.pack(side='bottom', fill='both', expand=1)
918
- self.run_button = Button(self.button_frame, text='Run project now',
919
+ self.run_button = tk.Button(self.button_frame, text='Run project now',
920
command=self.run_in_xterm)
921
self.run_button.pack(side='left', fill='both', expand=1)
922
- self.save_button = Button(self.button_frame, text='Save log',
923
+ self.save_button = tk.Button(self.button_frame, text='Save log',
924
command=self.save_log)
925
self.save_button.pack(side='left', fill='both', expand=1)
926
# disable the save log button till xterm is run
927
- self.save_button.configure(state='disabled')
928
+ #self.save_button.configure(state='disabled')
929
930
def set_cmd_label(self):
931
cmds = self.master.commands
932
933
cmd = ''
934
for line in all_lines:
935
cmd += ' ' + line
936
- prompt = commands.getoutput('printf "[${USER}@$(hostname -s) ] $ "')
937
+ prompt = getoutput('printf "[${USER}@$(hostname -s) ] $ "')
938
# probably not necessary, but ...
939
if 'not found' in prompt:
940
prompt = '[me@mymachine ] $ '
941
942
self.cmd_label.configure(text=self.cmd)
943
944
def previous(self):
945
- """Move to the previous wizard page"""
946
+ """Move to the previous wizard page.
947
+ """
948
self.frame.pack_forget()
949
wizard = self.master
950
index = wizard.index.get()
951
952
wizard.next_button.pack_forget()
953
954
def run_in_xterm(self):
955
- ''' run the final script in an xterm, completing the project '''
956
- self.frame.pack_forget()
957
- self.master.prev_button.configure(state='disabled')
958
- self.termtitle.pack(side='top')
959
- self.container = Frame(self.master, container=1, height=600, width=600)
960
- self.container.pack(side='right', fill='both',
961
- padx=20, expand=1, anchor='nw')
962
- lines = '80x44+0+0'
963
- cmd = 'xterm -sb -si -fn %s -rv -sb -rightbar -g %s -e sh -c' \
964
- %(self.master.fixed_font, lines)
965
- cmd = shlex.split(cmd)
966
- try:
967
- id = self.root.tk.call('winfo', 'id', self.container)
968
- frame_id = '%s' %int(id, 16)
969
- self.master.xterm_is_running.set(True)
970
- except TclError, ValueError:
971
- self.master.xterm_is_running.set(False)
972
- frame_id = ''
973
- help = commands.getoutput('xterm -help')
974
- self.logfile = mktemp(suffix='.log', prefix='todisc_commands.',
975
- dir='/tmp')
976
- if re.search('-into ', help) and frame_id:
977
- cmd.insert(1, frame_id)
978
- cmd.insert(1, '-into')
979
- tovid_cmd = """
980
- bash %s | tee -a %s
981
- echo
982
- echo "Press Enter to exit terminal"
983
- read input
984
- """ %(self.script_file, self.logfile)
985
- cmd.append(tovid_cmd)
986
- command = Popen(cmd, stderr=PIPE)
987
- self.after(200, self.poll)
988
-
989
- def poll(self):
990
- # return if container is not created yet, or xterm is not running
991
- if not self.container or not self.master.xterm_is_running.get():
992
+ """Run the final script in an xterm, completing the project.
993
+ """
994
+ if not askyesno(message="Run in xterm now?"):
995
+ self.master.show_status(1)
996
return
997
- try:
998
- # bogus call to container to see if it has been destroyed
999
- self.container.winfo_class()
1000
- except TclError:
1001
- self.termtitle.pack_forget()
1002
- self.master.xterm_is_running.set(False)
1003
- self.frame.pack(fill='both', expand=1, anchor='nw')
1004
- self.master.prev_button.configure(state='normal')
1005
- self.log_contents = commands.getoutput('tr "\r" "\n" < %s' \
1006
- %self.logfile)
1007
- os.remove(self.logfile)
1008
- self.save_button.configure(state='normal')
1009
- self.root.check = self.root.after(200, self.poll)
1010
+ self.screen_pos = self.get_screen_position()
1011
+ xterm_geo = '80x40' + self.screen_pos
1012
+ cmd = \
1013
+ ['-sb', '-title', 'todisc',
1014
+ '-g', xterm_geo, '-e', 'sh', '-c']
1015
+ self.xterm_cmd.extend(cmd)
1016
+ wait_cmd = ';echo ;echo "Press Enter to exit terminal"; read input'
1017
+ tovid_cmd = 'bash %s' % self.master.project
1018
+ self.xterm_cmd.append(tovid_cmd + wait_cmd)
1019
+ self.root.withdraw()
1020
+ command = Popen(self.xterm_cmd, stderr=PIPE)
1021
+ command.wait()
1022
+ # without the following the position of restored window can jump around
1023
+ self.root.geometry(self.screen_pos)
1024
+ self.root.update_idletasks() # update geometry before it is 'deiconified'
1025
+ self.root.deiconify()
1026
+
1027
1028
def save_log(self, event=None):
1029
logfile = asksaveasfilename(initialfile='todisc_output.log')
1030
1031
log.writelines(self.log_contents)
1032
1033
# unfinished and unused
1034
-class Messagebox(Frame):
1035
+class Messagebox(tk.Frame):
1036
def __init__(self, master, use=None, text='', boolean_var=None):
1037
- Frame.__init__(self, master)
1038
+ tk.Frame.__init__(self, master)
1039
self.master = master
1040
self.use = use
1041
- self.var = boolean_var
1042
+ self.var = tk.boolean_var
1043
#self.overrideredirect(1)
1044
- self.top = Toplevel(self.master, use=use)
1045
+ self.top = tk.Toplevel(self.master, use=use)
1046
text = text
1047
- label = Label(self.top, text=text, wraplength=400)
1048
+ label = tk.Label(self.top, text=text, wraplength=400)
1049
label.pack()
1050
- button1 = Button(self.top, text='Yes', command=self.yes)
1051
- button2 = Button(self.top, text='No', command=self.no)
1052
+ button1 = tk.Button(self.top, text='Yes', command=self.yes)
1053
+ button2 = tk.Button(self.top, text='No', command=self.no)
1054
button1.pack(side='left')
1055
button2.pack(side='left')
1056
1057
def yes(self, event=None):
1058
#self.var.set(True)
1059
- print 'from yes() return_code is: ', self.master.return_code.get()
1060
self.quit()
1061
return True
1062
1063
1064
self.quit()
1065
return False
1066
1067
-class TitleBox(Frame):
1068
- """A Listbox in a LabelFrame with Entry associated with it
1069
+class TitleBox(tk.Frame):
1070
+ """A Listbox in a LabelFrame with Entry associated with it.
1071
text: the label for the frame
1072
"""
1073
def __init__(self, master=None, text=''):
1074
- Frame.__init__(self, master)
1075
+ tk.Frame.__init__(self, master)
1076
self.master = master
1077
self.text = text
1078
self.draw()
1079
1080
def draw(self):
1081
# create the listbox (note that size is in characters)
1082
- frame1 = LabelFrame(self.master, text=self.text)
1083
+ frame1 = tk.LabelFrame(self.master, text=self.text)
1084
frame1.pack(side='left', fill='y', expand=False)
1085
# use entry widget to display/edit selection
1086
- self.enter1 = Entry(frame1, width=50)
1087
+ self.enter1 = tk.Entry(frame1, width=50)
1088
self.enter1.pack(side='bottom', fill='both', expand=False)
1089
- self.listbox = Listbox(frame1, width=50, height=12)
1090
+ self.listbox = tk.Listbox(frame1, width=50, height=12)
1091
self.listbox.pack(side='left', fill='y', expand=False, anchor='nw')
1092
self.get = self.listbox.get
1093
1094
# create a vertical scrollbar to the right of the listbox
1095
- yscroll = Scrollbar(frame1, command=self.listbox.yview,
1096
+ yscroll = tk.Scrollbar(frame1, command=self.listbox.yview,
1097
orient='vertical')
1098
yscroll.pack(side='right', fill='y', anchor='ne')
1099
self.listbox.configure(yscrollcommand=yscroll.set)
1100
1101
self.listbox.bind('<ButtonRelease-1>', self.get_list)
1102
1103
def set_list(self, event):
1104
- """Insert an edited line from the entry widget back into the listbox
1105
+ """Insert an edited line from the entry widget back into the listbox.
1106
"""
1107
try:
1108
index = self.listbox.curselection()[0]
1109
1110
self.listbox.selection_set('end')
1111
1112
def get_list(self, event):
1113
- """Read the listbox selection and put the result in an entry widget
1114
+ """Read the listbox selection and put the result in an entry widget.
1115
"""
1116
try:
1117
# get selected line index and text
1118
1119
1120
# Execution
1121
if __name__ == '__main__':
1122
+ args = argv[1:]
1123
+ infile = ''
1124
+ while args:
1125
+ arg = args.pop(0)
1126
+ # check for script to load: if its a file assume it is one (in)
1127
+ if os.path.exists(arg):
1128
+ infile = arg
1129
# get tovid prefix so we can find the app image file
1130
- tovid_prefix = commands.getoutput('tovid -prefix')
1131
+ tovid_prefix = getoutput('tovid -prefix')
1132
tovid_prefix = os.path.join(tovid_prefix, 'lib', 'tovid')
1133
os.environ['PATH'] = tovid_prefix + os.pathsep + os.environ['PATH']
1134
img_file = os.path.join(tovid_prefix, 'titleset-wizard.png')
1135
+ root_height = 660
1136
+ # run a 'progress bar' to get info (tuple):
1137
+ # screen height, title bar height, title bar width
1138
+ screen_info = get_screen_info(img_file)
1139
# instantiate Tk and Wizard
1140
- root = Tk()
1141
- root.minsize(width=800, height=660)
1142
- app = Wizard(root, 'Tovid\nTitleset Wizard', img_file)
1143
+ root = tk.Tk()
1144
+ root.withdraw()
1145
+ # shave height if we are dealing with a netbook resolution
1146
+ if screen_info[0] < 660:
1147
+ root_height = 600
1148
+ root.minsize(width=800, height=root_height)
1149
+ app = Wizard(root, 'Tovid\nTitleset Wizard', img_file, infile=infile)
1150
+ app.set_screen_info(screen_info)
1151
+ root.update_idletasks()
1152
+ root.deiconify()
1153
# instantiate pages
1154
page1 = Page1(app)
1155
page2 = Page2(app)
1156
1157
page6 = Page6(app)
1158
# run it
1159
try:
1160
- mainloop()
1161
+ root.mainloop()
1162
except KeyboardInterrupt:
1163
exit(1)
1164
tovid-0.34.tar.bz2/src/todisc -> tovid-0.35.tar.gz/src/todisc
Changed
5698
1
2
#
3
# Project homepage: http://tovid.wikia.com
4
#
5
-# Copyright (C) 2005-2010
6
+# Copyright (C) 2005-2015
7
#
8
# This program is free software; you can redistribute it and/or
9
# modify it under the terms of the GNU General Public License
10
11
# grepper on irc.freenode.net
12
13
SCRIPT_NAME=`cat << EOF
14
+
15
--------------------------------
16
tovid disc
17
-Generate a DVD filesystem with animated thumbnail menus
18
+Generate a DVD file-system with optional menus, from a list of multimedia files.
19
+Menus can be moving or static thumbnails, or text. Encoding done automatically.
20
+
21
Version $TOVID_VERSION
22
$TOVID_HOME_PAGE
23
--------------------------------
24
+
25
EOF`
26
27
USAGE=`cat << EOF
28
Usage:
29
-
30
- todisc [OPTIONS] \\\\
31
- -files File1.mpg File2.mpg ... \\\\
32
+ tovid disc [OPTIONS] \\\\
33
+ -files File1.mpg File2.avi ... \\\\
34
-titles "Title 1" "Title 2" ... \\\\
35
- -out OUT_PREFIX
36
+ -menu-title "Tovid Demo" \\\\
37
+ -out OUT_DIRECTORY
38
39
You can also do slideshows using -slides IMAGES rather than -files VIDEOS
40
+General Options:
41
+ -no-ask, -no-warn, -keep-files, -jobs, -grid, -no-confirm-backup
42
+Other quick examples:
43
+Create 'text menu' DVD filesystem:
44
+ tovid disc -text-menu -files ... -titles .. -out OUT_DIRECTORY
45
+Create DVD filesystem with no menu, encoding with ffmpeg and prompt for burn:
46
+ tovid disc -files *.mp4 -ffmpeg -no-menu -burn -out OUT_DIRECTORY
47
+Create DVD compatible mpeg2 files using makempg (and ffmpeg) and then quit:
48
+ tovid disc -encode-only -ffmpeg -quality 8 -files *.avi (no -out required)
49
See the tovid manual page ('man tovid') for additional documentation.
50
51
EOF`
52
# check that needed todisc deps are installed
53
assert_dep "$todisc_deps"
54
assert_dep strings "'strings' is part of binutils. In most distros the package
55
-is called by the same name. http://www.gnu.org/software/binutils/ ."
56
+is called binutils. http://www.gnu.org/software/binutils/ ."
57
SCRIPT_START_TIME=`date +%s`
58
59
# check if symlink in /tmp exists and use time stamped link if so
60
WORK_DIR="/tmp/todisc-work"
61
62
LOG_FILE=$(readlink -f todisc.log)
63
-OUT_PREFIX=""
64
+OUT_DIRECTORY=""
65
TV_STANDARD=ntsc
66
PIXEL_AR="10:11"
67
MENU_LEN=( 20 )
68
69
SUBMENU_LEN=(10)
70
MAX_MENU_LEN=""
71
TARGET=dvd
72
-FRAME_RATE=29.970
73
+FRAME_RATE=29.970 # for bc. mjpegtools and transcode convert this to 30000/1001
74
+ff_frame_rate="30000/1001" # ffmpeg needs to be explicitly told exact framerate
75
VIDSIZE=720x480
76
+VF_SCALE=${VIDSIZE%x*}:${VIDSIZE#*x}
77
MENU_TITLE="My Video Collection"
78
STATIC=false
79
SUB_MENU=false
80
81
SM_TITLE_CLR="#EAEAEA"
82
THUMB_BG_CLR=white
83
TITLES_CLR=""
84
-BUTTON_STYLE="rect"
85
+BUTTON_STYLE="line"
86
MIST_COLOUR=white
87
MIST_OPACITY=60
88
-TITLE_STROKE=""
89
+M_TITLE_STROKE=""
90
SUBMENU_STROKE="none"
91
BG_AUDIO=""
92
BG_PIC=""
93
94
USER_SM_AUDIO_SEEK=false
95
SC_THUMB=:
96
TEXTMENU=false
97
-SC_TITLE_ALIGN=center
98
-THUMB_TITLE_ALIGN=center
99
+SC_TITLE_ALIGN="center"
100
+EDGE_JUSTIFY=false
101
ALIGN_OVERRIDE=false
102
MULTILINE_TITLE=false
103
SAFE_AREA=50 # undocumented: you can set this from CLI with -showcase-safe-area
104
-SAFE_OFFSET=36
105
+SAFE_OFFSET=0 # we only add this offset if center title align, to keep onscreen
106
ASPECT_RATIO=4:3
107
AR=1.333
108
ASPECT_ARG=all
109
WIDE_SCREEN=false
110
WIDESCREEN="nopanscan"
111
+GROUP_ARR=""
112
GROUPING=false
113
TEXT_YSTART=$SAFE_AREA
114
BUTTON_GRAVITY=north
115
XGEO=0
116
YGEO=45
117
USER_GRAVITY=false
118
-USER_GEO=false
119
USER_SPLIT=false
120
TITLE_GRAVITY=south
121
SPACER=15
122
123
USER_AUDIOLENGTH=false
124
BURN=false
125
EJECT=''
126
+BURN_PROG="makedvd"
127
BURN_DEVICE="/dev/dvdrw"
128
QUICK_MENU=false
129
BG_CLR='#101010'
130
131
JUSTIFY="center"
132
CONTRAST_CLR='gray'
133
NOMENU=false
134
+ENCODE_ONLY=false
135
SC_AR=133
136
THUMB_COLUMNS=""
137
FAST_SEEK=false # ffmpeg: default:decode during seek (more accurate but slower)
138
USER_THUMBS=false # is user providing images for the menu link thumbs ?
139
-FRAME_SAFE=false # (-static) if true take the best of 9 frames. default: 1 frame
140
-PIPE_FORMAT="-pix_fmt yuv420p -f yuv4mpegpipe"
141
+FRAME_SAFE=false # (-static) if true take the best of 9 frames. default 1 frame
142
+USE_V_TITLES_DECO=false
143
+USE_M_TITLE_DECO=false
144
+PIPE_FORMAT=""
145
IMG_DEPTH="-depth 8" # when converting to png: ppmtoy4m needs 8 bit
146
+AUDIO_EXT="ac3"
147
+SAMPLERATE="48000"
148
+AUDIO_OPTS="-ab 224k -ar $SAMPLERATE -acodec $AUDIO_EXT"
149
+MPLEX_FORMAT="8"
150
+FROM_GUI=false # needed to disable tput (colour output) in GUI
151
TOVID_PREFIX=$(tovid -prefix)
152
+use_transcode=:
153
+yuv_correct="yuvcorrect -T NO_HEADER"
154
155
##############################################################################
156
# Functions #
157
##############################################################################
158
159
-# Y-echo: echo to two places at once (stdout and logfile)
160
+# Y-echo: print to two places at once (stdout and logfile)
161
# Output is preceded by the script name that produced it
162
# Args: $@ == any text string
163
-# If no args are given, echo a separator bar
164
+# If no args are given, print a separator bar
165
+# If empty string is the arg, print a newline
166
# Use yecho if you want output to go to the logfile
167
yecho()
168
{
169
- if test $# -eq 0; then
170
+ # arg supplied but empty (""): just print a newline
171
+ if [[ "${1+defined}" && -z $1 ]]; then
172
+ printf "\n"
173
+ [[ -e "$LOG_FILE" ]] && printf "\n" >> "$LOG_FILE"
174
+ # no arg supplied at all, just 'yecho': print \n[todisc]:\n
175
+ elif test $# -eq 0; then
176
printf "\n%s\n\n" "$SEPARATOR"
177
# If logfile exists, copy output to it (with pretty formatting)
178
test -e "$LOG_FILE" && \
179
180
fold -bs >> "$LOG_FILE"
181
fi
182
}
183
-# ******************************************************************************
184
-# Execute the given command-line string, with appropriate stream redirection
185
-# Args: $@ == text string containing complete command-line
186
-# Returns: Exit status of the subprocess
187
-# To filter/prettify the subprocess output before writing it to the log file,
188
-# set the LOG_FILTER variable before calling this function, to e.g.
189
-# LOG_FILTER="sed 's/\r/\r\n/g'" # Replace LF with CR/LF
190
-# ******************************************************************************
191
192
# Print script name, usage notes, and optional error message, then exit.
193
# Args: $@ == text string(s) containing error message and help
194
195
fi
196
exit 1
197
}
198
-warning_message()
199
+
200
+# Usage: continue_in [SECONDS]
201
+continue_in()
202
{
203
- local MESSAGE=( "$@" )
204
- yecho $SEPARATOR
205
- for ((i=0; i<$#; i++)) ; do printf "%s" "${MESSAGE[i]}"; done |
206
- format_output | tee -a "$LOG_FILE"
207
- echo | tee -a "$LOG_FILE"
208
- yecho "$SEPARATOR"
209
+ yecho ""
210
+ (($1)) && LAST=$1 || LAST=5
211
+ for ((i=LAST; i>=0; i--)); do
212
+ ((i==0)) && count='' || count="continuing in $i seconds ..."
213
+ spin $count
214
+ ((i>0)) && sleep 1
215
+ done
216
+}
217
+
218
+info_message()
219
+{
220
+ local MESSAGE=$(sed "s/ */ /g;s/^ *//" <<< "$@" | fold -w 60 -bs)
221
+ printgreen "*** Note: ***"
222
+ print2log "$MESSAGE"
223
+ while read -r line; do
224
+ printf "%s\n" "$line"
225
+ done <<< "$MESSAGE"
226
+ printgreen "*************"
227
+}
228
+
229
+# print to log, formated with leading/trailing spaces removed
230
+# and prefixed with the script name. [todisc]:
231
+# with no args it just prints [todisc]:, with "" as arg it prints newline
232
+print2log()
233
+{
234
+ local MESSAGE=$(sed "s/ */ /g;s/^ *//" <<< "$@" | fold -w 60 -bs)
235
+ # if "" passed in as arg (ie. defined but empty, print a blank line
236
+ if [[ "${1+defined}" && -z $1 ]]; then
237
+ printf "\n" >> "$LOG_FILE"
238
+ # otherwise print [todisc]: $line for each line of input
239
+ else
240
+ while read -r line; do
241
+ printf "%s %s\n" "$ME" "$line" >> "$LOG_FILE"
242
+ done <<< "$MESSAGE"
243
+ printf "\n" >> "$LOG_FILE"
244
+ fi
245
+}
246
+
247
+# pipe stdout to log prefixed by "[name]:", and ending in newline. 2 opt args
248
+# arg 1: [name to prefix each line of output]
249
+# arg 2: [fold] fold lines appropriately. Usually you don't fold program stdout.
250
+# uses stdbuf (coreutils) if present so stdin is line buffered
251
+pipe2log()
252
+{
253
+ if [[ $1 ]]; then
254
+ name="[$1]: "
255
+ else
256
+ name="[${0##*/}]: "
257
+ fi
258
+ if [[ $2 && $2 = format ]]; then
259
+ cols=$(( 79 - $(wc -c <<< $name) ))
260
+ ((cols)) || cols=60
261
+ format="fold -w $cols -bs"
262
+ else
263
+ format="cat"
264
+ fi
265
+ $std_buf tr "\015" "\012" < /dev/stdin | $std_buf tr -d "\033" | $format | \
266
+ while read line; do
267
+ printf "%s %s\n" "$name" "$line"
268
+ done >> "$LOG_FILE"
269
+ printf "\n" >> "$LOG_FILE"
270
+}
271
+
272
+printgreen()
273
+{
274
+ $FROM_GUI || tput setaf 2
275
+ printf "%s\n" "$@" | sed "s/ */ /g;s/^ *//"
276
+ print2log "$@"
277
+ $FROM_GUI || tput sgr0
278
+ printf ""
279
+}
280
+
281
+printred()
282
+{
283
+ $FROM_GUI || tput setaf 1
284
+ printf "%s\n" "$@" | sed "s/ */ /g;s/^ *//"
285
+ print2log "$@"
286
+ $FROM_GUI || tput sgr0
287
+ printf ""
288
}
289
290
titlesafe_error()
291
{
292
- echo "***** WARNING *****"
293
- yecho "thumb title is $1 pixels from screen edge"
294
+ (($1 > SAFE_AREA)) && preposition='off the' || preposition='from'
295
+ yecho ""
296
+ printred "***** WARNING *****"
297
+ yecho "video title is $1 pixels $preposition screen edge"
298
yecho "Part of the title may not be visible on your tv screen"
299
yecho "Perhaps use a smaller -titles-fontsize, or shorten \"${TITLES[i]}\""
300
- $SHOWCASE && [[ -z $SHOWCASE_FILE ]] && \
301
- yecho "You may also use '-showcase-titles-align east' since you are not
302
- using a -showcase FILE."
303
- echo "****************************"
304
- $WARN && sleep 5
305
+ # no need to test $SHOWCASE: default montage will never be offscreen
306
+ if [[ -z $SHOWCASE_FILE && ! $SC_TITLE_ALIGN = east ]]; then
307
+ yecho \
308
+ "You may also use '-showcase-titles-align east' since you are not
309
+ using a -showcase FILE."
310
+ elif ((NUM_FILES >= SPLIT)); then # two columns
311
+ : # insert message here for east offscreen stuff #fixme
312
+ fi
313
+ yecho "****************************"
314
+ $WARN && continue_in 5
315
}
316
317
format_output()
318
319
# TODO: Check for font availability?
320
}
321
322
-vid_length()
323
-{
324
- check_frames=""
325
- [[ -n $2 ]] && check_frames=$2 && check_frames="-frames $check_frames"
326
- echo "Using mencoder to get length of $1" >> "$LOG_FILE"
327
- L=$(mencoder -nosound -mc 0 -oac pcm -ovc copy $check_frames \
328
- -o /dev/null "$1" 2> /dev/null)
329
- awk 'END{print $(NF-3)}' <<< "$L"
330
- # awk '{for (i=0; i<NF; i++) { if ($i=="secs") {print $(i-1); break} } }' \
331
- # <<< "$L"
332
-}
333
-audio_length()
334
-{
335
- # optional 2nd arg is maximum length checked in file (seconds)
336
- end=""
337
- [[ -n $2 ]] && end="-endpos $2"
338
- mplayer -nomsgcolor -noconsolecontrols -vo null -ao pcm:fast:file=/dev/null $end "$1" \
339
- 2>&1 | tr '\r' '\n' | grep ^A: | tail -1 | sed s/^.*A:// | awk '{print $1}'
340
+# get the length of a stream
341
+# usage: stream_length STREAM [type, duration]
342
+# type is either video or audio, duration is the max length to test
343
+# last 2 args are optional: defaults 'video' and the whole stream.
344
+stream_length()
345
+{
346
+ local end=""
347
+ local stream_type=video
348
+ local ff_opts="-an -vcodec copy"
349
+ [[ -n $2 ]] && stream_type=$2
350
+ [[ -n $3 ]] && end="-t $3"
351
+ sed_var="{s/^.*time= *\([^ ]*\).*/\1/p}"
352
+ stream_name=$stream_type
353
+ if [[ $stream_type = 'audio' ]]; then
354
+ ff_opts="-vn -acodec copy"
355
+ # workaround for avconv which is broken atm wrt getting m2v framerate right
356
+ # overload stream_type to have another meaning,
357
+ elif [[ $stream_type = 'm2v' ]]; then
358
+ sed_var="{s/^.*frame= *\([^ ]*\).*/\1/p}"
359
+ stream_name=video
360
+ fi
361
+ print2log "Using $FFmpeg to get accurate $stream_name length of $1"
362
+ local len=$($FFmpeg -i "$1" $end $ff_opts -f null -y /dev/null 2>&1 |
363
+ sed -n "$sed_var" | tail -n 1)
364
+ # sed -n 's/^.*time= *\([^ ]*\).*/\1/p' | tail -n 1)
365
+ if [[ $stream_type = 'm2v' ]]; then
366
+ bc_math "$len / $FRAME_RATE"
367
+ else
368
+ unformat_time $len # no need for echo, prints to stdout
369
+ fi
370
}
371
+
372
cleanup()
373
{
374
#TODO make a kill_pid function to avoid repetition below
375
376
yecho "todisc encountered an error:"
377
yecho " $@"
378
echo
379
- echo "The error should be shown above, also check the contents of
380
+ echo "See above message, and also you can check the contents of
381
$LOG_FILE to see what went wrong." |format_output
382
- echo "See the tovid website ($TOVID_HOME_PAGE) for possible further info."
383
+ echo "See the tovid website ($TOVID_HOME_PAGE) for further help options."
384
+ echo "Latest fixes for ffmpeg api changes go in svn tovid."
385
+ echo "So you should try that if you get ${FFmpeg##*/} errors in the log."
386
+ echo "See subversion section: http://tovid.wikia.com/wiki/Installing_tovid"
387
echo "Sorry for the inconvenience!"
388
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
389
cleanup
390
391
# usage: bc_math "expression" [int]
392
bc_math()
393
{
394
+ OLC_ALL=$LC_ALL
395
+ LC_ALL=C
396
bc_out=$(bc <<< "scale=3;$1" 2>/dev/null)
397
if [[ -n $2 && $2 = "int" ]]; then
398
echo ${bc_out%.*}
399
else
400
printf "%.03f" $bc_out
401
fi
402
+ LC_ALL=$OLC_ALL
403
}
404
405
confirm_preview()
406
{
407
confirm_msg="type 'yes' to continue, or press <ENTER> to exit: "
408
- yecho
409
+ yecho ""
410
if $SWITCHED || $TITLESET_MODE || $VMGM_ONLY; then
411
echo "If doing titlesets or switched menus and you wish to exit "
412
echo "without seeing more previews, then type: 'exit', else you will "
413
414
confirm_msg="Type yes to continue, press <ENTER> to abort but see "
415
confirm_msg="$confirm_msg other previews, or type 'exit' to quit."
416
fi
417
- echo "If you are happy with the preview, $confirm_msg"
418
+ echo -e "If you are happy with the preview, \n$confirm_msg"
419
read input
420
echo
421
if [ ! -z "$input" -a "$input" = "yes" ]; then
422
yecho "Preview OK, continuing."
423
- yecho
424
+ yecho ""
425
else
426
yecho "Preview not OK, exiting."
427
#echo -n "Deleting symlink in /tmp . . . "
428
429
#echo -n "Deleting "$REAL_WORK_DIR" . . . "
430
rm -fr "$REAL_WORK_DIR"
431
fi
432
- yecho
433
+ yecho ""
434
echo
435
echo "Some configuration options to try, if things look bad:"
436
echo "Color:"
437
438
{
439
SPIN_CHARS=".oOo"
440
SPINNER="${SPIN_CHARS:SP++%${#SPIN_CHARS}:1}"
441
- # Print spaces to overwrite previous line
442
- echo -ne "\r "
443
+ echo -ne "\r$(printf %60s)" # print spaces to overwrite previous line
444
echo -ne "\r$@ "
445
}
446
447
-#EXPAND="expand=-6:-6,"
448
get_framed_pics()
449
{
450
mplayer -ss $MPLAYER_SEEK_VAL -vo $VOUT -noconsolecontrols \
451
452
{
453
awk 'END{print NR}' "$LOG_FILE"
454
}
455
+
456
+# unused
457
+get_ffmpeg_version()
458
+{
459
+local test_version=$1
460
+ff_ver=$($FFmpeg -version 2>&1 | awk '{ gsub(",", ""); if(NR == 1) print $3 }')
461
+(( ${ff_ver:2:1} == test_version )) 2>/dev/null
462
+}
463
+
464
+is_video()
465
+{
466
+file -biL "$1" |grep -qw video || return 1
467
+}
468
469
check_filetype()
470
{
471
fstats=$(file -L "$1" | awk '{ $1 = ""; print }')
472
if [[ $fstats =~ "image" || $fstats =~ "bitmap" ]]; then
473
- TYPE="image"
474
+ file_type="image"
475
CONVRT=:
476
- if [[ $fstats = *JPEG* || $fstats = *PNG || $fstas = *PPM* ]]; then
477
+ if [[ $fstats = *JPEG* || $fstats = *PNG || $fstats = *PPM* ]]; then
478
CONVRT=false
479
fi
480
- elif mencoder \
481
- -endpos 2 -oac pcm -ovc copy "$1" -o /dev/null >/dev/null 2>&1; then
482
- TYPE=video
483
+ elif is_video "$1"; then
484
+ file_type=video
485
else
486
- TYPE=unknown
487
+ file_type=unknown
488
fi
489
}
490
491
get_stats()
492
{
493
-unset IN_STATS FILES_IN
494
-this_set=$1
495
-if [[ $this_set = "group" ]]; then
496
- unset TOT IN_STATS FILES_IN
497
- TOT=${#grouping[@]} # || TOT=${#IN_FILES[@]}
498
- IN_STATS=( "${group_idvid_stats[@]}" )
499
- FILES_IN=( "${grouping[@]}" )
500
-else
501
- TOT=${#IN_FILES[@]}
502
- IN_STATS=( "${idvid_stats[@]}" )
503
- FILES_IN=( "${IN_FILES[@]}" )
504
-fi
505
-for ((i=0; i<TOT; i++)); do
506
- VCODEC="$(awk -F= '/ID_VIDEO_FORMAT/ {print $2}' <<< "${IN_STATS[i]}")"
507
- V_BR="$(awk -F= '/ID_VIDEO_BITRATE/ {print $2}' <<< "${IN_STATS[i]}")"
508
- ACODEC="$(awk -F= '/ID_AUDIO_CODEC/ {print $2}' <<< "${IN_STATS[i]}")"
509
- A_BR="$(awk -F= '/ID_AUDIO_BITRATE/ {print $2}' <<< "${IN_STATS[i]}")"
510
- if [ -z "$A_BR" ]; then
511
- A_BR="No audio found"
512
- fi
513
- V_LENGTH=${VID_LEN[i]}
514
- [[ $this_set = "group" ]] && V_LENGTH=${GROUP_VID_LEN[i]}
515
- FPS="$(awk -F= '/ID_VIDEO_FPS/ {print $2}' <<< "${IN_STATS[i]}")"
516
- yecho
517
- if [[ $this_set = "group" ]] && ((i == 0)); then
518
- echo; echo ". . . Grouped file stats . . ."; echo
519
- yecho
520
- fi
521
- [[ $this_set = "group" ]] && echo -e "Stats for" \
522
- $(readlink -f "${FILES_IN[i]}") "\n" || \
523
- echo -e "Stats for" "${FILES_IN[i]}" "\n"
524
- echo -e \
525
- " video codec: " \
526
- "$VCODEC" "\n" \
527
- "video bitrate: " "$V_BR" "bits per second" "\n" \
528
- "framerate: " "$FPS" "fps" "\n" \
529
- "audio codec: " \
530
- "$ACODEC" "\n" \
531
- "audio bitrate: " \
532
- "$A_BR" "bits per second" "\n" \
533
- "video length: " \
534
- "$V_LENGTH" "seconds" |tee -a "$LOG_FILE"
535
-done
536
+ unset IN_STATS FILES_IN
537
+ this_set=$1
538
+ if [[ $this_set = "group" ]]; then
539
+ unset TOT IN_STATS FILES_IN
540
+ TOT=${#grouping[@]} # || TOT=${#IN_FILES[@]}
541
+ IN_STATS=( "${group_idvid_stats[@]}" )
542
+ FILES_IN=( "${grouping[@]}" )
543
+ else
544
+ TOT=${#IN_FILES[@]}
545
+ IN_STATS=( "${idvid_stats[@]}" )
546
+ FILES_IN=( "${IN_FILES[@]}" )
547
+ fi
548
+ for ((i=0; i<TOT; i++)); do
549
+ VCODEC="$(awk -F= '/ID_VIDEO_FORMAT/ {print $2}' <<< "${IN_STATS[i]}")"
550
+ V_BR="$(awk -F= '/ID_VIDEO_BITRATE/ {print $2}' <<< "${IN_STATS[i]}")"
551
+ ACODEC="$(awk -F= '/ID_AUDIO_CODEC/ {print $2}' <<< "${IN_STATS[i]}")"
552
+ A_BR="$(awk -F= '/ID_AUDIO_BITRATE/ {print $2}' <<< "${IN_STATS[i]}")"
553
+ if [ -z "$A_BR" ]; then
554
+ A_BR="No audio found"
555
+ fi
556
+ V_LENGTH=${VID_LEN[i]}
557
+ [[ $this_set = "group" ]] && V_LENGTH=${GROUP_VID_LEN[i]}
558
+ FPS="$(awk -F= '/ID_VIDEO_FPS/ {print $2}' <<< "${IN_STATS[i]}")"
559
+ yecho ""
560
+ if [[ $this_set = "group" ]] && ((i == 0)); then
561
+ print2log ""; print2log ". . . Grouped file stats . . ."
562
+ yecho ""
563
+ fi
564
+ [[ $this_set = "group" ]] && print2log "Stats for \
565
+ $(readlink -f "${FILES_IN[i]}")" || \
566
+ print2log "Stats for" "${FILES_IN[i]}"
567
+ echo -e \
568
+ " video codec: " \
569
+ "$VCODEC" "\n" \
570
+ "video bitrate: " "$V_BR" "bits per second" "\n" \
571
+ "framerate: " "$FPS" "fps" "\n" \
572
+ "audio codec: " \
573
+ "$ACODEC" "\n" \
574
+ "audio bitrate: " \
575
+ "$A_BR" "bits per second" "\n" \
576
+ "video length: " \
577
+ "$V_LENGTH" "seconds" |pipe2log
578
+ done
579
+
580
}
581
test_compliance()
582
{
583
584
# slide mpg's go in $WORK_DIR, and are moved to BASEDIR later if recursing
585
# for video files: files are named $IN_FILE.enc.mpg
586
unset FILES_TO_ENCODE ENC_IN_FILES CHECK_IN_FILES
587
+ # get user's config options for makempg from the tovid.ini file
588
+ makempg_ini_opts=$(tovid mpg | awk '/Read options/{getline;print}')
589
group_set=false
590
- if [[ $1 = "group" ]]; then
591
+ if $ENCODE_ONLY; then
592
+ # encoding all files as -encode-only was used
593
+ CHECK_IN_FILES=()
594
+ FILES_TO_ENCODE=( "${IN_FILES[@]}" )
595
+ elif [[ $1 = "group" ]]; then
596
group_set=:
597
unset x a
598
CHECK_IN_FILES=( "${grouping[@]}" )
599
600
OUTFILE="$WORK_DIR/${TSET_NUM}-$((i+1)).mpg"
601
fi
602
603
- spin "Checking compliance of file $((i+1))"
604
+ print2log "Checking compliance of file $((i+1))"
605
# if file tested as an image when we were verifying input files
606
if [[ $is_image = "yes" ]]; then
607
$group_set && grp_use_image2mpeg2[i]="yes" ||
608
609
ENC_IN_FILES=("${ENC_IN_FILES[@]}" "${IN_FILE}.enc.mpg")
610
fi
611
done
612
+ echo
613
$DEBUG && etime=$(date +%s) && get_elapsed "compliance check"
614
if test "${#FILES_TO_ENCODE[@]}" -gt 0; then
615
TGT_CAPS=$(tr a-z A-Z <<< "$TARGET")
616
TV_STND_CAPS=$(tr a-z A-Z <<< "$TV_STANDARD")
617
- echo
618
- yecho "Encode input files"
619
+ print2log "Encode input files"
620
if ! $SINGLE_SLIDESHOW; then
621
- echo
622
- yecho "Some of the -files you provided are not \
623
- $TV_STND_CAPS $TGT_CAPS-compliant:"
624
- echo " "
625
+ if $ENCODE_ONLY; then
626
+ yecho "Encoding the following files to \
627
+ $TV_STND_CAPS $TGT_CAPS format:"
628
+ else
629
+ yecho "Some of the -files you provided are not \
630
+ $TV_STND_CAPS $TGT_CAPS-compliant:"
631
+ fi
632
+ print2log ""
633
fi
634
if test ${#FILES_TO_ENCODE[@]} -lt 12 && ! $SINGLE_SLIDESHOW; then
635
+ printgreen '-------------'
636
for i in "${FILES_TO_ENCODE[@]}"; do
637
this_file=$(readlink -f "$i")
638
test -n "$this_file" && yecho " $this_file"
639
done
640
+ printgreen '-------------'
641
fi
642
# this ugly list of OR's are cases we want automatic encoding
643
# all switched runs except the 1st, if -no-ask, if single slideshow
644
# or if all input files are images
645
if { $SWITCHED && [[ $MENU_NUM -ne 2 ]] ; } \
646
- || $NOASK || [[ ${TOVID_OPTS[@]} = *-noask* ]] || \
647
+ || $NOASK || [[ ${TOVID_OPTS[@]} = *-noask* ]] || $ENCODE_ONLY || \
648
[[ ${#NO_PROMPT_FILES[@]} = ${#FILES_TO_ENCODE[@]} ]]; then
649
- yecho " "
650
echo "Encoding files to $TV_STND_CAPS $TGT_CAPS-compliant format."
651
- echo "(This may take a long time)"
652
ENCODE="yes"
653
else
654
- yecho " "
655
+ yecho ""
656
yecho "I can encode them for you, but it may take a long time."
657
yecho "Encoding will ensure that your disc is fully compliant;"
658
yecho "you may skip this, but your disc may not be playable."
659
yecho "Please type 'yes' if you want the files to be encoded:"
660
read ENCODE
661
- fi
662
- if test -n "$ENCODE" && test "$ENCODE" = 'yes'; then
663
- if ! $SINGLE_SLIDESHOW; then
664
- yecho
665
- yecho "Converting files to $TGT_CAPS format"
666
- yecho
667
+ if [[ $ENCODE = "yes" ]]; then
668
+ ! $SINGLE_SLIDESHOW && yecho \
669
+ "Converting files to $TGT_CAPS format"
670
fi
671
+ fi
672
+ if [[ $ENCODE = 'yes' ]]; then
673
for i in "${!FILES_TO_ENCODE[@]}"; do
674
IN=$(readlink -f "${FILES_TO_ENCODE[i]}")
675
if $group_set; then
676
677
fi
678
# AUDIO_FADE=false # do not fade silence FIXME ???
679
else # not an image file - outfile goes beside infile
680
- THIS_FILE=$(readlink -f "${FILES_TO_ENCODE[i]}")
681
- yecho "Converting $THIS_FILE"
682
+ #THIS_FILE=$(readlink -f "${FILES_TO_ENCODE[i]}")
683
+ if [[ -e "$IN.enc.mpg" ]]; then
684
+ if ! grep -w -- -overwrite <<< \
685
+ "$makempg_ini_opts ${script_args[@]}"; then
686
+ : #FIXME echo to terminal what makempg would do ?
687
+ fi
688
+ fi
689
+ yecho "Converting $IN"
690
echo
691
- countdown 3
692
+ continue_in 3
693
TOVID_WORKING_DIR=$WORKING_DIR makempg $NO_ASK \
694
- -$TV_STANDARD -$TARGET -in "$IN" -out "${IN}.enc" "${TOVID_OPTS[@]}"
695
+ -$TV_STANDARD -$TARGET -in "$IN" -out "${IN}.enc" \
696
+ "${TOVID_OPTS[@]}"
697
+ wait
698
+ if [[ -e "${IN}.enc.mpg" ]]; then
699
+ ! $ENCODE_ONLY && yecho "Using ${IN}.enc.mpg for this DVD"
700
+ else
701
+ runtime_error "There appears to be a problem creating \
702
+ the DVD compatible mpeg. See $LOG_FILE for details"
703
+ fi
704
# for grouped files replace symlink in $WORK_DIR
705
$group_set && [[ -L "${FILES_TO_ENCODE[i]}" ]] && \
706
ln -sf "${IN}.enc.mpg" "${FILES_TO_ENCODE[i]}"
707
708
KEEP_FILES=:
709
runtime_error "Could not encode file: $IN"
710
fi
711
- #yecho
712
+ #yecho ""
713
done
714
715
# Replace IN_FILES with ENC_IN_FILES (with .enc extension)
716
# for grouped files the mpeg already replaced the group symlink
717
! $group_set && IN_FILES=("${ENC_IN_FILES[@]}")
718
else
719
- yecho
720
- yecho "Not re-encoding. I will proceed with menu generation, but"
721
- yecho "your authored disc will not be fully $TGT_CAPS-compliant."
722
- yecho
723
+ if $ENCODE_ONLY; then
724
+ info_message "Not re-encoding."
725
+ else
726
+ info_message "Not re-encoding. I will proceed with menu generation, but
727
+ your authored disc will not be fully $TGT_CAPS-compliant."
728
+ fi
729
fi
730
fi
731
}
732
733
VIDEO_IN="$1"
734
VIDEO_IN_SEEK="$2"
735
video_type=$3
736
- yecho
737
+ yecho ""
738
yecho "$VIDEO_IN is not compliant - re-encoding \
739
$(bc <<< "$VIDEO_IN_SEEK + ${MENU_LEN[MENU_NUM-1]}" 2>/dev/null)
740
second slice to DVD compliant file"
741
742
return
743
fi
744
fi
745
- yecho
746
+ yecho ""
747
yecho "Converting files to $TGT_CAPS format with 'makempg'"
748
- countdown
749
+ continue_in 5
750
makempg $NO_ASK -in "$VIDEO_IN" \
751
-slice 0-$(bc <<< "$VIDEO_IN_SEEK + ${MENU_LEN[MENU_NUM-1]}" 2>/dev/null) \
752
-${TV_STANDARD} -${TARGET} -in "$VIDEO_IN" \
753
754
[[ $video_type = background ]] && BG_VIDEO="${VIDEO_IN}.enc.mpg"
755
fi
756
SUPPORT_VIDEOS=( "${SUPPORT_VIDEOS[@]}" "${VIDEO_IN}.enc.mpg" )
757
- yecho
758
+ yecho ""
759
}
760
761
mk_workdir()
762
763
{
764
IN_IMAGE="$1"
765
OUT_MPEG="$2"
766
+ # need to set VIDSIZE here as pal VIDSIZE assignment is later in script
767
+ [ $TV_STANDARD = "pal" ] && VIDSIZE=720x576
768
+ VF_SCALE=${VIDSIZE%x*}:${VIDSIZE#*x}
769
# remove symlinks, as otherwise we overwrite symlink target
770
- IMAGE_ENC_CMD=(ffmpeg -f image2 $LOOP -vframes $vlength \
771
- -i "$IN_IMAGE" -s $VIDSIZE -f s16le -ar 48000 -i /dev/zero -t $alength \
772
+ IMAGE_ENC_CMD=($FFmpeg -f image2 $LOOP \
773
+ -i "$IN_IMAGE" -f s16le -ar 48000 -i /dev/zero -t $alength \
774
-ar $SAMPLERATE -ac 2 -ab 224k -target ${TV_STANDARD}-${TARGET} \
775
- -aspect $ASPECT_RATIO -y "$OUT_MPEG")
776
- echo "Running ${IMAGE_ENC_CMD[@]}" | format_output >> "$LOG_FILE"
777
- "${IMAGE_ENC_CMD[@]}" 2>&1 |strings >> "$LOG_FILE"
778
+ $VF scale=${VF_SCALE},${ASPECT} -y -vframes $vlength "$OUT_MPEG")
779
+ print2log ""
780
+ print2log "Running ${IMAGE_ENC_CMD[@]}"
781
+ print2log ""
782
+ "${IMAGE_ENC_CMD[@]}" 2>&1 | pipe2log fmpeg
783
}
784
785
switched_menu_mode()
786
787
-basedir "$BASEDIR" -menu_num $((i+1)) -showcase "${FILES[i]}""
788
todisc "$@" -switched-mode $IS_TITLESET -basedir "$WORK_DIR" \
789
-menu_num $((i+1)) -todisc_pids "$TODISC_PIDS" -showcase "${FILES[i]}"
790
+ yecho
791
done
792
yecho
793
yecho "Working on switched menu 1"
794
795
fi
796
MC_CMD=(todisc -slides "${IN_SLIDES[@]}" $mix_range \
797
$NO_CONFIRM_BACKUP ${encopt[@]} $sld_tranition $background_carousel \
798
- $showcase_carousel -out "$OUT_PREFIX" -carousel_menu_mode -basedir \
799
+ $showcase_carousel -out "$OUT_DIRECTORY" -carousel_menu_mode -basedir \
800
"$WORK_DIR" $menulen -carousel_num $((c+1)) -todisc_pids "$TODISC_PIDS")
801
- yecho
802
+ yecho ""
803
yecho "Running ${MC_CMD[@]}"
804
"${MC_CMD[@]}"
805
}
806
807
DVDAUTHOR_XML="$BASEDIR/dvdauthor.xml"
808
VMGM_PRE=" if ( g5 eq 0 ) g5=1;"
809
VMGM_PRE="$VMGM_PRE\n if ( g6 eq 0 ) g6=1; button = g6 * 1024;"
810
- egrep -qw -- "-switched-menu[s]" <<< "${args[@]}" && \
811
+ # switch is now singular (-switched-menu) OR plural (-switched-menus)
812
+ egrep -q -- "-switched-menu" <<< "${args[@]}" && \
813
VMGM_PRE="$VMGM_PRE\n if (g1 eq 0) g1=1;"
814
$DO_INTRO && INTRO_PRE=" if (g2==1) jump cell 2; "
815
$SKIP_VMGM_MENU && VMGM_PRE="$VMGM_PRE\n if ( g3 eq 0 ) g3=1 ;"
816
817
################### end titleset options testing #########################
818
819
if [[ -z ${VMGM_OPTS[@]} ]]; then
820
- yecho
821
+ #yecho
822
yecho "You have not supplied -vmgm OPTIONS -end-vmgm"
823
yecho "At a minumum you should have: \
824
'-vmgm -titles "Title one" "Title two" -end-vmgm'"
825
826
fi
827
yecho "Making a generic vmgm menu for you - \
828
you may wish to cancell out and change this."
829
- yecho
830
- $VMGM_MENU && $WARN && sleep 15
831
+ yecho ""
832
+ $VMGM_MENU && $WARN && continue_in 15
833
else
834
unset vmgmtitles
835
get_menu_titles "${VMGM_OPTS[@]}"
836
837
fi
838
################### end titleset options testing #########################
839
# VMGM menu
840
- yecho
841
- yecho "Making a VMGM menu with the following command:"
842
+ print2log "Making a VMGM menu"
843
vmgm_menu_cmd=(todisc "${GEN_OPTS[@]}" -basedir "$WORK_DIR" -vmgm_only \
844
-textmenu -todisc_pids "$TODISC_PIDS" $NO_CONFIRM_BACKUP \
845
-title_count "$num_titles" $vmgm_playall "${VMGM_OPTS[@]}")
846
- yecho "Running: ${vmgm_menu_cmd[@]}"
847
+ print2log "Running: ${vmgm_menu_cmd[@]}"
848
INITIALDIR="$BASEDIR"
849
if ! "${vmgm_menu_cmd[@]}" ; then cleanup && exit 1; fi
850
# TITLESET menus
851
852
yecho
853
yecho "Working on the menu for titleset number $tset"
854
yecho
855
- $WARN && sleep 5
856
- yecho "Running: ${titleset_cmd[@]}"
857
+ $WARN && continue_in 5
858
+ print2log "Running: ${titleset_cmd[@]}"
859
if ! "${titleset_cmd[@]}"; then cleanup && exit 1; fi
860
yecho
861
;;
862
863
done
864
echo -e "</dvdauthor>" >> "$DVDAUTHOR_XML"
865
yecho "Running dvdauthor to create final DVD structure"
866
- dvdauthor -x "$DVDAUTHOR_XML" 2>&1 | tee -a "$LOG_FILE"
867
+ dvdauthor -x "$DVDAUTHOR_XML" 2>&1 | pipe2log dvdauthor
868
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
869
dvdauthor_error
870
fi
871
872
873
burn_disc()
874
{
875
- BURN_CMD=(tovid dvd -burn -device $EJECT "$BURN_DEVICE" \
876
+ BURN_TGT="$OUT_DIR"
877
+ BURN_TGT_STR="DVD directory"
878
+ BURN_CMD=(tovid dvd -burn -device "$BURN_DEVICE" $EJECT \
879
$BURN_SPEED \"$BURN_TGT\")
880
yecho
881
echo "You have indicated you want to burn the $BURN_TGT_STR"
882
883
if [ ! -z "$input" -a "$input" = "yes" ]; then
884
echo "Proceeding to burn, continuing."
885
echo
886
- $BURN_PROG -burn -device "$BURN_DEVICE" \
887
- $BURN_SPEED "$BURN_TGT" | tee -a "$LOG_FILE" 2>&1
888
- if ((${PIPESTATUS[0]}==0)); then
889
+ # probably could do redirection using exec and such, but this is simple
890
+ $BURN_PROG -device "$BURN_DEVICE" \
891
+ $BURN_SPEED "$BURN_TGT" | tee "$WORK_DIR/makedvd.log"
892
+ pipe_status=${PIPESTATUS[0]}
893
+ pipe2log makedvd < "$WORK_DIR/makedvd.log"
894
+ if ((pipe_status==0)); then
895
echo "Your ${BURN_TGT_STR/ *} should be ready"
896
else
897
echo "There was a problem burning the ${BURN_TGT_STR/ *}"
898
899
900
thanks_goodbye()
901
{
902
- echo
903
- echo $SEPARATOR
904
SCRIPT_TIME=$(format_seconds $SECONDS)
905
- echo "todisc took $SCRIPT_TIME to finish on $CPU_MODEL $CPU_SPEED mhz"
906
- echo $SEPARATOR
907
- echo "Your new DVD should be in $OUT_DIR"
908
- echo "You can preview them in gxine with this command:"
909
- echo " gxine \"dvd:/$OUT_DIR\""
910
- echo "If you are satisfied with the results, you can burn a disc with:"
911
- echo " tovid dvd -burn \"$OUT_DIR\""
912
+ goodbye=`cat << EOF
913
+
914
+ $SEPARATOR
915
+ todisc took $SCRIPT_TIME to finish on
916
+ $CPU_MODEL $CPU_SPEED mhz
917
+ $SEPARATOR
918
+
919
+ Your new DVD should be in $OUT_DIR
920
+ You can preview them in gxine with this command:
921
+ $(printf "%s\t" "gxine \"dvd:/$OUT_DIR\"")
922
+ Or in vlc with this command:
923
+ $(printf "%s\t" "vlc \"$OUT_DIR\"")
924
+ If you are satisfied with the results, you can burn a disc with:
925
+ $(printf "%s\t" "tovid dvd -burn \"$OUT_DIR\"")
926
+
927
+ Thanks for using tovid!
928
+EOF`
929
echo
930
- echo "Thanks for using todisc."
931
+ sed 's/^ //g' <<< "$goodbye" | tee -a "$LOG_FILE"
932
}
933
934
-# usage mk_return_button (mk_play_button) COLOUR1 COLOUR2 OUTBUTTON
935
+# usage mk_return_button (mk_play_button) COLOUR1 COLOUR2 outbutton
936
# ex. for menu button ( not spumux ):
937
# mk_return_button "#C6C6C6" black "$WORK_DIR/Main.png"
938
mk_return_button()
939
{
940
941
- COLR1="$1"
942
- COLR2="$2"
943
- TYPE=$3
944
- OUTBUTTON="$4"
945
- if [[ $TYPE = "spu" ]]; then
946
- CLR1="none"
947
- elif [[ $TYPE = "default" ]]; then
948
- CLR1="$COLR1"
949
+ colr1="$1"
950
+ colr2="$2"
951
+ local auth_type=$3
952
+ outbutton="$4"
953
+ if [[ $auth_type = "spu" ]]; then
954
+ clr1="none"
955
+ elif [[ $auth_type = "default" ]]; then
956
+ clr1="$colr1"
957
fi
958
959
- MK_RTN_CMD=(convert -size 100x80 xc:none \
960
- -strokewidth 1 -stroke "$COLR2" -fill "$CLR1" \
961
+ mk_rtn_cmd=(convert -size 100x80 xc:none \
962
+ -strokewidth 1 -stroke "$colr2" -fill "$clr1" \
963
-draw 'rectangle 0,0 70,62' \
964
- -fill "$COLR2" -stroke none \
965
+ -fill "$colr2" -stroke none \
966
-draw "polyline 40,10 40,50 10,30 40,10" \
967
-draw "polyline 60,10 60,50 30,30 60,10" \
968
- -fill "$COLR2" -draw "rectangle 6,10 10,50" \
969
- -resize 30% -trim +repage +antialias "$OUTBUTTON")
970
- echo -e "\nRunning ${MK_RTN_CMD[@]}\n" |format_output
971
- "${MK_RTN_CMD[@]}"
972
- mogrify -channel A -threshold 50% "$OUTBUTTON"
973
- RTN_BTN_DIM=$(get_image_dim "$OUTBUTTON")
974
- rtn_btn_width=$(awk -Fx '{print $1}' <<< $RTN_BTN_DIM )
975
- rtn_btn_height=$(awk -Fx '{print $2}' <<< $RTN_BTN_DIM )
976
+ -fill "$colr2" -draw "rectangle 6,10 10,50" \
977
+ -resize 30% -trim +repage +antialias "$outbutton")
978
+ print2log "Running ${mk_rtn_cmd[@]}"
979
+ "${mk_rtn_cmd[@]}"
980
+ mogrify -channel A -threshold 50% "$outbutton"
981
+ rtn_btn_dim=$(get_image_dim "$outbutton")
982
+ rtn_btn_width=$(awk -Fx '{print $1}' <<< $rtn_btn_dim )
983
+ rtn_btn_height=$(awk -Fx '{print $2}' <<< $rtn_btn_dim )
984
}
985
mk_play_button()
986
{
987
- COLR1="$1"
988
- COLR2="$2"
989
- TYPE=$3
990
- OUTBUTTON="$4"
991
- if [[ $TYPE = "spu" ]]; then
992
- CLR1="none"
993
- elif [[ $TYPE = "default" ]]; then
994
- CLR1="$COLR1"
995
- fi
996
- #-fill "$COLR2" -draw "line 40,10 40,50" \
997
- # -fill "$COLR2" -draw "rectangle 36,10 40,50" \
998
- MK_PLAY_CMD=(convert +antialias -size 100x80 xc:none \
999
- -strokewidth 2 -stroke "$COLR2" -fill "$CLR1" \
1000
+ colr1="$1"
1001
+ colr2="$2"
1002
+ local auth_type=$3
1003
+ outbutton="$4"
1004
+ if [[ $auth_type = "spu" ]]; then
1005
+ clr1="none"
1006
+ elif [[ $auth_type = "default" ]]; then
1007
+ clr1="$colr1"
1008
+ fi
1009
+ #-fill "$colr2" -draw "line 40,10 40,50" \
1010
+ # -fill "$colr2" -draw "rectangle 36,10 40,50" \
1011
+ mk_play_cmd=(convert +antialias -size 100x80 xc:none \
1012
+ -strokewidth 2 -stroke "$colr2" -fill "$clr1" \
1013
-draw 'rectangle 22,0 92,62' \
1014
- -fill "$COLR2" -stroke none \
1015
+ -fill "$colr2" -stroke none \
1016
-draw "polyline 40,10 40,50 80,30 40,10" \
1017
- -resize 30% -trim +repage "$OUTBUTTON")
1018
- echo -e "\nRunning ${MK_PLAY_CMD[@]}\n" |format_output >> "$LOG_FILE"
1019
- "${MK_PLAY_CMD[@]}"
1020
- PLAY_BTN_DIM=$(get_image_dim "$OUTBUTTON")
1021
- play_btn_width=$(awk -Fx '{print $1}' <<< $PLAY_BTN_DIM )
1022
- play_btn_height=$(awk -Fx '{print $2}' <<< $PLAY_BTN_DIM )
1023
+ -resize 30% -trim +repage "$outbutton")
1024
+ print2log "Running ${mk_play_cmd[@]}"
1025
+ "${mk_play_cmd[@]}"
1026
+ play_btn_dim=$(get_image_dim "$outbutton")
1027
+ play_btn_width=$(awk -Fx '{print $1}' <<< $play_btn_dim )
1028
+ play_btn_height=$(awk -Fx '{print $2}' <<< $play_btn_dim )
1029
}
1030
1031
check_menufile()
1032
{
1033
- yecho
1034
+ yecho ""
1035
if test -f "$MENU_FILE"; then
1036
echo "Menu file $MENU_FILE created"
1037
echo
1038
1039
quick_menu()
1040
{
1041
funct_arg=$1
1042
- unset LEFTPAD TOPPAD RIGHTPAD BOTTOMPAD
1043
# is it a preview or main run of menu creation
1044
if [[ -n $funct_arg && $funct_arg = "preview" ]]; then
1045
QM_MENU_TIME=2 && QM_PREVIEW=:
1046
else
1047
QM_MENU_TIME=${MENU_LEN[MENU_NUM-1]} && QM_PREVIEW=false
1048
fi
1049
- # test for filters and vhook
1050
- filters=$(ffmpeg -filters 2>/dev/null)
1051
- if grep -q -w '^movie' <<< "$filters" && \
1052
- grep -q -w '^crop' <<< "$filters"; then
1053
- echo "libavfilter overlay and crop filters are present"
1054
- use_overlay_filter=:
1055
- $use_overlay_filter && echo "Using libavfilter for -quick-menu"
1056
- elif grep -q ^-vhook <<< "$(ffmpeg -h 2>&1)"; then
1057
- # find out where vhook lives for ffmpeg
1058
- local config=$(ffmpeg -version 2>&1 | grep -- --prefix=)
1059
- config=${ffmpeg_prefix//*--prefix=}
1060
- ffmpeg_prefix=${config// *}
1061
- # empty var means no --prefix passed, use default prefix of /usr/local
1062
- ffmpeg_prefix=${ffmpeg_prefix:-/usr/local}
1063
- imlib2_vhook="${ffmpeg_prefix}/lib/vhook/imlib2.so"
1064
- if [[ -s "$imlib2_vhook" ]]; then
1065
- use_vhooks=:
1066
- else
1067
- yecho "!!!!! $imlib2_vhook not found, can not continue !!!!!"
1068
+ # test for filters presense in ffmpeg
1069
+ # ffmpeg has really poor support for scripts so we can't do something
1070
+ # sane like grep for ^movie or ^crop.
1071
+ # using these ugly repeated grep calls because they are easier to
1072
+ # understand/maintain than an awk command.
1073
+ if ! ((filter_test_completed)); then
1074
+ filters=$($FFmpeg -filters 2>/dev/null)
1075
+ if grep -w 'movie' <<< "$filters" | grep -q -v 'amovie' &&
1076
+ grep -w 'crop' <<< "$filters" | grep -q -v 'cropdetect'; then
1077
+ print2log "libavfilter movie filter present, using for -quick-menu"
1078
+ use_overlay_filter=:
1079
+ else
1080
+ # exit if missing a needed video filter
1081
+ runtime_error \
1082
+ "Missing ${FFmpeg##*/} filters
1083
+ (movie or crop) -quick-menu impossible."
1084
fi
1085
fi
1086
1087
- # FIXME this will not be needed when the overlay filter is in SVN proper
1088
- if ! $use_vhooks && ! $use_overlay_filter; then
1089
- runtime_error "You are not able to use -quick-menu:
1090
- you must use the experimental ffmpeg with libavfilter
1091
- or an older (0.52 for example) version of ffmpeg with vhooks.
1092
- See this post for details on installing ffmpeg with filters:
1093
- http://ubuntuforums.org/showthread.php?p=9021636"
1094
- fi
1095
+ # ensure the filter test is only run once
1096
+ filter_test_completed=1
1097
if $QUICKMENU_IS_SHOWCASE; then
1098
- yecho
1099
- yecho "resizing and padding showcase file: $SHOWCASE_VIDEO"
1100
- LEFTPAD=$SC_X
1101
- TOPPAD=$SC_Y
1102
- RIGHTPAD="-padright \
1103
- $(( ${VIDSIZE%%x*} - $LEFTPAD - ${SHOWCASE_SIZE%%x*} ))"
1104
- BOTTOMPAD="-padbottom \
1105
- $(( ${VIDSIZE##*x} - $TOPPAD - ${SHOWCASE_SIZE##*x} ))"
1106
- LEFTPAD="-padleft $SC_X"
1107
- TOPPAD="-padtop $SC_Y"
1108
+ if ! $NOASK; then
1109
+ yecho ""
1110
+ yecho "resizing and padding showcase file: $SHOWCASE_VIDEO"
1111
+ fi
1112
local VF_PADX=$SC_X
1113
local VF_PADY=$SC_Y
1114
QM_FRAMESIZE=$SHOWCASE_SIZE
1115
1116
qm_post_seek=$qm_seek && unset qm_pre_seek
1117
fi
1118
1119
- $QM_PREVIEW && yecho "Creating a quick-menu preview image"
1120
- # pad/resize if needed, use overlay filter (or vhook) to add menu graphics
1121
+ $QM_PREVIEW && ! $NOASK && yecho "Creating a quick-menu preview image"
1122
+ # pad/resize if needed, use overlay filter to add menu graphics
1123
# framing (if showcase) by ntsc-safe black bg
1124
- ! $QM_PREVIEW && yecho
1125
if ! $QM_PREVIEW; then
1126
- yecho "Using ffmpeg to add titles and background"
1127
+ yecho ""
1128
+ yecho "Using $FFmpeg to add titles and background"
1129
fi
1130
if $use_overlay_filter; then
1131
+ local qw=${QM_FRAMESIZE%x*}
1132
+ local qh=${QM_FRAMESIZE#*x}
1133
+ # vhook uses the next var for scaling, but overlay does not
1134
+ unset QM_FRAMESIZE
1135
local overlay="$WORK_DIR/quick_menu_bg.png"
1136
- local PADDING="$VF pad=720:480:$VF_PADX:$VF_PADY"
1137
- local aspect=""
1138
- overlay_filter="movie=$overlay [wm];[in][wm] overlay=0:0:1 [wm2]"
1139
+ local PADDING="$VF scale=${qw}:${qh},pad=$VF_SCALE:${VF_PADX}:${VF_PADY}"
1140
+ overlay_filter="movie=$overlay [wm];[in][wm] overlay=0:0 [wm2]"
1141
ffmpeg_filter=($VF "$overlay_filter; [wm2] setdar=4:3 [out]")
1142
- elif $use_vhooks; then
1143
- local PADDING="$TOPPAD $BOTTOMPAD $LEFTPAD $RIGHTPAD"
1144
- local aspect="-aspect 4:3"
1145
- local PAD_CLR="-padcolor $BG_CLR"
1146
- ffmpeg_filter=(-vhook "$imlib2_vhook -x 0 -y 0 -i $WORK_DIR/quick_menu_bg.png")
1147
fi
1148
# no padding needed for background video, just resizing
1149
$QUICKMENU_IS_BACKGROUND && PADDING=""
1150
1151
yuvout="$WORK_DIR/out.yuv"
1152
rm -f "$yuvout" && mkfifo "$yuvout"
1153
# run the commands to make the final menu m2v video
1154
- PAD_CMD=(ffmpeg -r $FRAME_RATE -async 1 $qm_pre_seek \
1155
- -t "$QM_MENU_TIME" -i "$QUICK_MENU_FILE" $qm_post_seek \
1156
- -s $QM_FRAMESIZE -an $PADDING -r $FRAME_RATE \
1157
+ PAD_CMD=($FFmpeg -async 1 $qm_pre_seek \
1158
+ -i "$QUICK_MENU_FILE" $qm_post_seek -t "$QM_MENU_TIME" \
1159
+ -an $PADDING -r $ff_frame_rate \
1160
$PAD_CLR -f yuv4mpegpipe -vcodec rawvideo -y "$yuvout")
1161
- QUICKMENU_CMD=(ffmpeg -s $VIDSIZE -f yuv4mpegpipe \
1162
- -i "$yuvout" -an -f mpeg2video -r $FRAME_RATE \
1163
- -tvstd $TV_STANDARD -b 7000k -maxrate 8000k -bufsize 224KiB \
1164
- $aspect "${ffmpeg_filter[@]}" -y "$WORK_DIR/intro.m2v")
1165
- $QM_PREVIEW && yecho
1166
- yecho "Running ${PAD_CMD[@]}"|fold -bs
1167
- echo "${QUICKMENU_CMD[@]}" | fold -bs | tee -a "$LOG_FILE"
1168
- "${PAD_CMD[@]}" < /dev/null > "${LOG_FILE}-1.tmp" 2>&1 &
1169
- "${QUICKMENU_CMD[@]}" < /dev/null > "${LOG_FILE}-2.tmp" 2>&1 &
1170
+ # removed-s $VIDSIZE from following cmd, don't think it needs it
1171
+ # check if I need to add a scale filter, perhaps comma sep at end.
1172
+ # http://forum.videohelp.com/threads/338494-Multiple-filter-problem-with-ffmpeg-help-please
1173
+ QUICKMENU_CMD=($FFmpeg -f yuv4mpegpipe \
1174
+ -i "$yuvout" -an -f mpeg2video -r $ff_frame_rate \
1175
+ $VB 7000k -maxrate 8000k -bufsize 224KiB \
1176
+ "${ffmpeg_filter[@]}" -y "$WORK_DIR/intro.m2v")
1177
+ echo "Running ${PAD_CMD[@]}" > "${LOG_FILE}-1.tmp"
1178
+ "${PAD_CMD[@]}" < /dev/null >> "${LOG_FILE}-1.tmp" 2>&1 &
1179
+ echo "Running ${QUICKMENU_CMD[@]}" > "${LOG_FILE}-2.tmp"
1180
+ "${QUICKMENU_CMD[@]}" < /dev/null >> "${LOG_FILE}-2.tmp" 2>&1 &
1181
ffmpeg_pid=$!
1182
- yecho
1183
- while ps -p $ffmpeg_pid >/dev/null; do
1184
- sleep 1
1185
- [[ -s "$WORK_DIR/intro.m2v" ]] && txt="Writing" || txt="Seeking"
1186
- spin $txt $SPINNER
1187
- done
1188
+ if ! $QM_PREVIEW; then
1189
+ while ps -p $ffmpeg_pid >/dev/null; do
1190
+ sleep 1
1191
+ [[ -s "$WORK_DIR/intro.m2v" ]] && txt="Writing" || txt="Seeking"
1192
+ spin $txt $SPINNER
1193
+ done
1194
+ fi
1195
wait
1196
- yecho
1197
+ ! $QM_PREVIEW && yecho ""
1198
# remove control characters and seeking lines
1199
- strings "${LOG_FILE}-1.tmp" | sed '/time=10000000000.00/d' >> "$LOG_FILE"
1200
- strings "${LOG_FILE}-2.tmp" | sed '/time=10000000000.00/d' >> "$LOG_FILE"
1201
+ [[ -e ${LOG_FILE}-1.tmp ]] && \
1202
+ cat "${LOG_FILE}-1.tmp" | sed '/time=10000000000.00/d' | pipe2log ${FFmpeg##*/}
1203
+ [[ -e ${LOG_FILE}-2.tmp ]] && \
1204
+ cat "${LOG_FILE}-2.tmp" | sed '/time=10000000000.00/d' | pipe2log ${FFmpeg##*/}
1205
if [[ ! -s "$WORK_DIR/intro.m2v" ]]; then
1206
runtime_error "There was a problem creating the menu video $funct_arg"
1207
fi
1208
rm -f "${LOG_FILE}*.tmp"
1209
- ! $QM_PREVIEW && yecho
1210
+ ! $QM_PREVIEW && yecho ""
1211
# create preview images if called for, taking largest of 10 images
1212
if $QM_PREVIEW; then
1213
- FFMPEG_CMD=(ffmpeg -i "$WORK_DIR/intro.m2v" -an -vframes 10 \
1214
+ FFMPEG_CMD=($FFmpeg -i "$WORK_DIR/intro.m2v" -an -vframes 10 \
1215
-f image2 -y "$outdir"/%06d.$IMG_FMT)
1216
- yecho "Running ${FFMPEG_CMD[@]}" | strings
1217
- "${FFMPEG_CMD[@]}" 2>&1 | strings >> "$LOG_FILE"
1218
+ print2log "Running ${FFMPEG_CMD[@]}"
1219
+ "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
1220
# take the largest image (best quality?) of a 10 frame sampling
1221
largest_img=$(get_largest 6 10 "$outdir" )
1222
mv "$largest_img" "$PREVIEW_IMG"
1223
- yecho "Removing temporary preview files"
1224
+ print2log "Removing temporary preview files"
1225
rm -f "$WORK_DIR/intro.m2v"
1226
rm -f "$WORK_DIR"/showcase/*.$IMG_FMT "$WORK_DIR"/bg/*.$IMG_FMT
1227
fi
1228
- $QM_PREVIEW && yecho
1229
+ $QM_PREVIEW && yecho ""
1230
}
1231
1232
# 3x1 and 4x1 tile only for default arrangement
1233
tile_warning()
1234
{
1235
- yecho
1236
- echo "-tile-3x1 and -tile-4x1 are not showcase options. Disabling"
1237
- yecho
1238
- $WARN && sleep 5
1239
+ info_message "-tile-3x1 and -tile-4x1 are not showcase options. Disabling"
1240
+ $WARN && continue_in 5
1241
}
1242
dvdauthor_error()
1243
{
1244
1245
1246
make_dummy()
1247
{
1248
- yecho "Creating a blank mpeg for the vmgm menu"
1249
convert -resize $VIDSIZE! xc:"#101010" "$WORK_DIR/dummy.jpg"
1250
- ENC_CMD1=(jpeg2yuv -v 1 -f $FRAME_RATE -I p -n 1 -l 30 \
1251
+ [[ $TV_STANDARD = "ntsc" ]] && local len=30 || local len=25
1252
+ ENC_CMD1=(jpeg2yuv -v 1 -f $FRAME_RATE -I p -n 1 -l $len \
1253
-L 1 -b1 -j "$WORK_DIR/dummy.jpg")
1254
- ENC_CMD2=(ffmpeg -f yuv4mpegpipe -i - -an -r $FRAME_RATE -s $VIDSIZE \
1255
- -tvstd $TV_STANDARD $FFMPEG_OPTS -y "$WORK_DIR/dummy.m2v")
1256
- echo "Running: ${ENC_CMD1[@]} | ${ENC_CMD2[@]}" |
1257
- format_output | tee -a "$LOG_FILE"
1258
- if ! ${ENC_CMD1[@]} 2>> "$LOG_FILE" |
1259
- ${ENC_CMD2[@]} 2>&1 |strings >> "$LOG_FILE"; then
1260
- runtime_error
1261
- fi
1262
- VMGM_TIME=$(vid_length "$WORK_DIR/dummy.m2v")
1263
- yecho
1264
- BGAUDIO_CMD=(ffmpeg -f s16le -ar 48000 -i /dev/zero -t $VMGM_TIME \
1265
+ ENC_CMD2=($FFmpeg -f yuv4mpegpipe -i - -an -r $ff_frame_rate \
1266
+ $FFMPEG_OPTS -vf scale=${VF_SCALE},${ASPECT} -y "$WORK_DIR/dummy.m2v")
1267
+ print2log "Running: ${ENC_CMD1[@]} | ${ENC_CMD2[@]}"
1268
+ ${ENC_CMD1[@]} 2>> "${LOG_FILE}.tmp" |
1269
+ ${ENC_CMD2[@]} 2>&1 |pipe2log ${FFmpeg##*/}
1270
+ [[ -e ${LOG_FILE}.tmp ]] && cat "${LOG_FILE}.tmp" | pipe2log jpeg2yuv
1271
+ rm -f "${LOG_FILE}.tmp"
1272
+ ! [[ -s "$WORK_DIR/dummy.m2v" ]] && \
1273
+ runtime_error "There was a problem creating a dummy vmgm video"
1274
+ local VMGM_TIME=1 # use one second as dummy.m2v or either 30 or 25 frames
1275
+ BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero -t $VMGM_TIME \
1276
$AUDIO_OPTS -y "$WORK_DIR/dummy.$AUDIO_EXT")
1277
- yecho "${BGAUDIO_CMD[@]}"
1278
- "${BGAUDIO_CMD[@]}" 2>&1 | strings >> "$LOG_FILE"
1279
- ! [[ -s "$WORK_DIR/dummy.$AUDIO_EXT" ]] && runtime_error
1280
+ print2log "Creating silent audio stream."
1281
+ print2log "${BGAUDIO_CMD[@]}"
1282
+ "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
1283
+ ! [[ -s "$WORK_DIR/dummy.$AUDIO_EXT" ]] && runtime_error \
1284
+ "There was a problem creating audio for the dummy vmgm menu"
1285
1286
MPLEX_CMD=(mplex -V -f $MPLEX_FORMAT -o "$BASEDIR/dummy.mpg" \
1287
"$WORK_DIR/dummy.$AUDIO_EXT" "$WORK_DIR/dummy.m2v")
1288
- echo "Running: ${MPLEX_CMD[@]}" |fold -bs >> "$LOG_FILE"
1289
- ! "${MPLEX_CMD[@]}" 2>&1 |strings >> "$LOG_FILE" && runtime_error
1290
+ print2log "Running: ${MPLEX_CMD[@]}"
1291
+ "${MPLEX_CMD[@]}" 2>&1 |pipe2log mplex
1292
+ ((${PIPESTATUS[0]} != 0)) && runtime_error \
1293
+ "There was a problem muxing the audio and video with mplex"
1294
}
1295
verify_infiles()
1296
{
1297
1298
IN_FILE="${in_files[i]}"
1299
if test -s "$IN_FILE"; then
1300
check_filetype "$IN_FILE"
1301
- if [[ $TYPE = "image" ]]; then
1302
+ if [[ $file_type = "image" ]]; then
1303
IMG_STATS=( $(identify -ping -format "%z %w %h" "$IN_FILE") )
1304
DEPTH=${IMG_STATS[0]}
1305
IMG_WIDTH=${IMG_STATS[1]}
1306
1307
# also convert if not PNG or JPEG or wrong aspect ratio
1308
# test IN_FILES for preview - group files tested later
1309
if [[ $DEPTH = 16 || $PAD_IMG = "yes" ]] || $CONVRT ; then
1310
- echo "Converting $IN_FILE to proper image format" \
1311
- >> "$LOG_FILE"
1312
+ print2log "Converting $IN_FILE to proper image format"
1313
IMG_CMD=(convert "$IN_FILE" -depth 8 "${CROP_CMD[@]}" \
1314
-quality 01 "$OUTPNG")
1315
- format_output <<< "${IMG_CMD[@]}" \
1316
- >> "LOG_FILE"
1317
- "${IMG_CMD[@]}" |format_output >> "$LOG_FILE" 2>&1
1318
+ print2log "${IMG_CMD[@]}"
1319
+ "${IMG_CMD[@]}" 2>&1| pipe2log imagemagick
1320
# replace IN_FILES[i] OR group symlink
1321
if [[ $verify_type = "infiles" ]]; then
1322
IN_FILES[i]=$OUTPNG
1323
1324
grp_file_is_image[i]="yes"
1325
fi
1326
spin checking "${IN_FILE##*/}"
1327
- elif mencoder -quiet -oac pcm -ovc copy \
1328
- -frames 0 -o /dev/null "$IN_FILE" &>/dev/null; then
1329
+ elif is_video "$IN_FILE"; then
1330
checkfile="${IN_FILE##*/}"
1331
spin checking "$checkfile"
1332
else
1333
1334
usage_error "Sorry, $IN_FILE does not exist or is empty"
1335
fi
1336
done
1337
+ echo
1338
}
1339
1340
# contrasting 'undercolor' for -background from given font colour
1341
1342
1343
transition_slide()
1344
{
1345
- TYPE=$1
1346
+ local fade_type=$1
1347
+ local value
1348
index=$2
1349
outppm="$WORK_DIR/animenu/$(printf %06d%s $index .ppm)"
1350
- if [[ $TYPE = "crossfade" ]]; then
1351
- local VALUE=$(bc -l <<< "scale=2; ($fade_slide + 1) * $fade_incr") >&2
1352
- fade_cmd=(composite -blend $VALUE -depth 8 "$overlay_ppm" \
1353
+ if [[ $fade_type = "crossfade" ]]; then
1354
+ value=$(bc -l <<< "scale=2; ($fade_slide + 1) * $fade_incr") >&2
1355
+ fade_cmd=(composite -blend $value -depth 8 "$overlay_ppm" \
1356
"$base_ppm" "$outppm")
1357
- elif [[ $TYPE = "fadein" ]]; then
1358
- local VALUE=$(bc -l <<< "scale=2; $fade_slide * $fade_incr") >&2
1359
+ elif [[ $fade_type = "fadein" ]]; then
1360
+ value=$(bc -l <<< "scale=2; $fade_slide * $fade_incr") >&2
1361
fade_cmd=(composite -depth 8 "$base_ppm" "$WORK_DIR/black.ppm" \
1362
- -blend ${VALUE}% "$outppm")
1363
- elif [[ $TYPE = "fadeout" ]]; then
1364
- local VALUE=$(bc -l <<< "scale=2;100 - (($fade_slide + 1) * $fade_incr)") >&2
1365
- (( $(bc <<< "$VALUE < 0") == 1 )) && local VALUE=0
1366
+ -blend ${value}% "$outppm")
1367
+ elif [[ $fade_type = "fadeout" ]]; then
1368
+ value=$(bc -l <<< "scale=2;100 - (($fade_slide + 1) * $fade_incr)") >&2
1369
+ (( $(bc <<< "$value < 0") == 1 )) && value=0
1370
fade_cmd=(composite -depth 8 "$base_ppm" "$WORK_DIR/black.ppm" \
1371
- -blend ${VALUE}% "$outppm")
1372
+ -blend ${value}% "$outppm")
1373
fi
1374
"${fade_cmd[@]}" >/dev/null
1375
}
1376
1377
# this function does a loop with transition_slide() ... combine them into 1 ?
1378
do_transitions()
1379
{
1380
- TYPE=$1
1381
+ local fade_type=$1
1382
fade_slide=0
1383
for ((i=0; i<=fade_frames; i++)); do
1384
- transition_slide $TYPE $i &
1385
+ transition_slide $fade_type $i &
1386
transition_pids="$transition_pids $!"
1387
((num_procs++))
1388
if ((num_procs == max_procs || i == fade_frames-1)); then
1389
1390
fi
1391
let fade_slide=fade_slide+1
1392
done
1393
- if [[ $TYPE = "fadeout" ]] && ((f == ${#MIX_IN[@]}-1)); then
1394
+ if [[ $fade_type = "fadeout" ]] && ((f == ${#MIX_IN[@]}-1)); then
1395
for p in {0..12}; do
1396
cp "$WORK_DIR/black.ppm" \
1397
"$WORK_DIR/animenu/$(printf %06d%s $((p +i)) .ppm)" >&2
1398
1399
-bordercolor grey60 -border 1 \
1400
-rotate ${randir}${angle} \
1401
-background black \( +clone -shadow 60x4+4+4 \) +swap \
1402
- -background none -flatten \
1403
+ +repage -background none -flatten \
1404
"$WORK_DIR/tnail${i%.*}.png"
1405
stack_files[i]=$WORK_DIR/tnail${i%.*}.png
1406
1407
1408
{
1409
echo -e "\nIt took $(format_seconds $((etime-stime)) ) for the $1\n"
1410
}
1411
-# make sure correct sample size option for sox is used
1412
-# getting sox version is inconsistent, so just run test command
1413
-get_sox_arg()
1414
-{
1415
-if cat /dev/zero 2>/dev/null | nice -n 0 sox -t raw -c 2 -r 48000 -w -s - \
1416
-"$WORK_DIR/foo.wav" trim 0 1 &>/dev/null; then
1417
- echo -w
1418
-elif cat /dev/zero 2>/dev/null | nice -n 0 sox -t raw -c 2 -r 48000 -2 -s - \
1419
-"$WORK_DIR/foo.wav" trim 0 1 &>/dev/null; then
1420
- echo -2
1421
-else
1422
- runtime_error "Your sox appears to be incompatible with this program. " \
1423
- "Attempted to create a wav file using the -w option, then the -2 option"
1424
-fi
1425
-rm -f "$WORK_DIR/foo.wav"
1426
-
1427
-}
1428
1429
# Usage: check_maskshape SHAPE. Returns 1 if SHAPE not found.
1430
check_maskshape()
1431
1432
if [[ $mask_type == "thumb" ]]; then
1433
local BLUR_CMD=( "${THUMB_BLUR_CMD[@]}" )
1434
else
1435
- local BLUR_CMD=( "${SC_BLUR_CMD[@]]}" )
1436
+ local BLUR_CMD=( "${SC_BLUR_CMD[@]}" )
1437
fi
1438
MASK="$WORK_DIR/${shape}_${mask_type}_mask.png"
1439
1440
1441
convert - -resize $THUMB_SIZE! $MASK
1442
;;
1443
"blob")
1444
- echo $SEPARATOR
1445
- echo "Running convert -size 100x60 xc:none -fill white \
1446
- -draw \"circle 41,39 44,57 circle 59,39 56,57 circle 50,21 50,3\" miff:- |
1447
- convert - -trim +repage -bordercolor none -border 10x10 miff:- |
1448
- ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
1449
- convert - -resize $THUMB_SIZE! $MASK" | format_output
1450
- echo $SEPARATOR
1451
-
1452
convert -size 100x60 xc:none -fill white \
1453
-draw "circle 41,39 44,57 circle 59,39 56,57 circle 50,21 50,3" miff:- |
1454
convert - -trim +repage -bordercolor none -border 10x10 miff:- |
1455
1456
esac
1457
}
1458
1459
+# wait for file to appear
1460
+# name and timeout are optional: defaults to basename of FILE and 12 secs
1461
+# usage: wait_for file [name] [timeout]
1462
wait_for()
1463
{
1464
- # wait for file to appear
1465
- while true; do
1466
- if test -e $1; then
1467
+ local check_file=$1
1468
+ local filename=${check_file##*/}
1469
+ # default timeout of 10 seconds
1470
+ local timeout=${3:-10}
1471
+ timeout=$((timeout * 10))
1472
+ local name=${2:-$filename}
1473
+ x=0
1474
+ while ((x<timeout)); do
1475
+ if test -e "$check_file"; then
1476
return
1477
fi
1478
+ # print a message after 2 seconds: will only run when there is a problem
1479
+ if ((x==20)); then
1480
+ echo Waiting $(( (timeout / 10) - 2)) seconds for $name to appear ...
1481
+ fi
1482
sleep .1
1483
+ ((x++))
1484
done
1485
+ unset x
1486
+ return 1
1487
}
1488
1489
# HACK: transcode produces some scary output when run from python
1490
1491
transcode shown below if it shows transcode finishing the last image. \
1492
These harmless 'broken pipe' messages from transcode appear to be a \
1493
subtle bug in transcode when running it (or a script) from python. \
1494
- \n****\n" | sed "s/ */ /g;s/^ *//" |fold -bs >> "$LOG_FILE"
1495
+ \n****\n" | sed "s/ */ /g;s/^ *//" | pipe2log todisc format
1496
}
1497
1498
# get the largest PNG (1st match sequentially if more than one are same size)
1499
1500
echo $result
1501
}
1502
1503
+# tip from Steven M. Schultz
1504
+# https://www.mail-archive.com/mjpeg-users@lists.sourceforge.net/msg03511.html
1505
+# an alternative to yuvcorrect -T NO_HEADER
1506
+remove_header()
1507
+{
1508
+read junk
1509
+cat
1510
+return 0
1511
+}
1512
+
1513
##############################################################################
1514
# End of Functions #
1515
##############################################################################
1516
1517
1518
egrep -q 'titleset-mode|switched-mode|menu-only|carousel_menu_mode' <<< "$@" \
1519
&& NONAME=:
1520
-! $NONAME && yecho $"$SCRIPT_NAME"
1521
+! $NONAME && echo $"$SCRIPT_NAME"
1522
1523
while test $# -gt 0; do
1524
DO_SHIFT=:
1525
1526
for f in ${!ARGS_ARRAY[@]}; do
1527
FILENAMES[f]=${ARGS_ARRAY[f]}
1528
filenames[f]=$(readlink -f "${ARGS_ARRAY[f]}")
1529
+ if [[ ! -e ${filenames[f]} ]]; then
1530
+ usage_error "${filenames[f]} does not exist"
1531
+ fi
1532
done
1533
if $incoming_slides; then
1534
SLIDESHOW=( ${SLIDESHOW[@]} : ) # is this a slideshow ?
1535
1536
unset group groupkey grp x
1537
for ((i=0; i<${#ARGS_ARRAY[@]}; i++)); do
1538
grp[x++]=$(readlink -f "${ARGS_ARRAY[i]}")
1539
+ if [[ ! -e "${ARGS_ARRAY[i]}" ]]; then
1540
+ usage_error "${ARGS_ARRAY[i]} does not exist"
1541
+ fi
1542
done
1543
unset x
1544
[[ -z ${FILES[@]} ]] && ss_index=0 || ss_index=${#FILES[@]}
1545
1546
FILES[ss_index]=$(readlink -f "${ARGS_ARRAY[0]}")
1547
GROUP_IN_FILES=( "${GROUP_IN_FILES[@]}" "${grp[@]}" )
1548
groupkey=${#FILES[@]}
1549
- GROUP[groupkey-1]=${#grp[@]}
1550
+ GROUP_ARR[groupkey-1]=${#grp[@]}
1551
((groupkeys++))
1552
# create symlinks to ease substitution later
1553
for c in ${!grp[@]}; do
1554
1555
((${ARGS_ARRAY[0]})) 2>/dev/null || usage_error "Arguments to \
1556
-group must be preceeded by a positive integer. See 'man tovid'"
1557
groupkey=$(( ${ARGS_ARRAY[0]} - 1))
1558
- GROUP[groupkey]=${#grp[@]}
1559
+ GROUP_ARR[groupkey]=${#grp[@]}
1560
# temporary till I finish submenu groups TODO
1561
is_vidgroup[groupkey]=1
1562
# create symlinks to ease substitution later
1563
1564
"-nomenu" | "-no-menu" )
1565
NOMENU=:
1566
;;
1567
+ "-encode-only" )
1568
+ ENCODE_ONLY=:
1569
+ NOMENU=:
1570
+ ;;
1571
"-out" )
1572
shift
1573
- OUT_PREFIX="$1"
1574
- OUT_PREFIX=${OUT_PREFIX%/}
1575
+ OUT_DIRECTORY="$1"
1576
+ OUT_DIRECTORY=${OUT_DIRECTORY%/}
1577
;;
1578
"-no-ask" | "-noask" )
1579
NOASK=:
1580
1581
[[ -n $wsarg ]] && WIDESCREEN=$wsarg || WIDESCREEN="nopanscan"
1582
WIDE_SCREEN=:
1583
;;
1584
- "-showcase-safe-area" )
1585
+ "-safe-area" | "-showcase-safe-area" )
1586
ADV_OPT=( "${ADV_OPT[@]}" "$1" )
1587
shift
1588
SAFE_AREA="$1"
1589
- let SAFE_OFFSET="86-SAFE_AREA"
1590
USER_SAFE_AREA=:
1591
;;
1592
"-align" )
1593
ADV_OPT=( "${ADV_OPT[@]}" "$1" )
1594
shift
1595
BUTTON_GRAVITY=$1
1596
+ BUTTON_GRAVITY=$(tr A-Z a-z <<< $BUTTON_GRAVITY) # West => west
1597
[[ $BUTTON_GRAVITY = "centre" ]] && BUTTON_GRAVITY="center"
1598
USER_GRAVITY=:
1599
;;
1600
1601
shift
1602
get_listargs "$@"
1603
arg=${ARGS_ARRAY[0]}
1604
+ [[ -n $arg && $arg = 0 ]] && usage_error "Using '0' as an arg for -textmenu not allowed -
1605
+ use -align east (northeast, southeast) for 1 right-aligned column"
1606
[[ -n $arg ]] && SPLIT=$arg && USER_SPLIT=:
1607
TEXTMENU=:
1608
;;
1609
+ "-edge-justify")
1610
+ EDGE_JUSTIFY=:
1611
+ ;;
1612
"-text-start" )
1613
ADV_OPT=( "${ADV_OPT[@]}" "$1" )
1614
shift
1615
1616
"-showcase-titles-align" )
1617
shift
1618
SC_TITLE_ALIGN="$1"
1619
+ SC_TITLE_ALIGN=$(tr A-Z a-z <<< $SC_TITLE_ALIGN) # West => west
1620
[[ SC_TITLE_ALIGN = "centre" ]] && SC_TITLE_ALIGN="center"
1621
;;
1622
- "-title-gap" )
1623
+ "-titles-gap" | "-title-gap" )
1624
ADV_OPT=( "${ADV_OPT[@]}" "$1" )
1625
shift
1626
SPACER=$1
1627
1628
(( ${SC_BLUR%.*} >= 2 )) && SC_BLUR=2
1629
SC_USER_BLUR=1
1630
;;
1631
+ "-menu-title-colour" | "-menu-title-color" | \
1632
"-title-colour" | "-title-color" )
1633
shift
1634
TITLE_CLR="$1"
1635
1636
shift
1637
SM_TITLE_CLR="$1"
1638
;;
1639
- "-title-stroke" )
1640
+ "-menu-title-stroke" | "-title-stroke" )
1641
shift
1642
- TITLE_STROKE="$1"
1643
+ M_TITLE_STROKE="$1"
1644
;;
1645
"-titles-stroke" )
1646
shift
1647
- TITLES_STROKE="$1"
1648
+ V_TITLES_STROKE="$1"
1649
;;
1650
"-submenu-stroke" )
1651
shift
1652
1653
shift
1654
test_is_number $1 && TITLES_OPACITY="$1"
1655
;;
1656
- "-title-opacity" )
1657
+ "-menu-title-opacity" | "-title-opacity" )
1658
shift
1659
test_is_number $1 && TITLE_OPACITY="$1"
1660
;;
1661
1662
shift
1663
SELECT_CLR="$1"
1664
;;
1665
+ "-menu-title-font-deco" | "-title-font-deco" | \
1666
+ "-menu-title-fontdeco" | "-title-fontdeco")
1667
+ shift
1668
+ USE_M_TITLE_DECO=:
1669
+ M_TITLE_FONT_DECO=($1)
1670
+ ;;
1671
+ "-titles-font-deco" | "-titles-fontdeco" )
1672
+ shift
1673
+ USE_V_TITLES_DECO=:
1674
+ V_TITLES_FONT_DECO=($1)
1675
+ ;;
1676
-thumb-text-col* | "-thumb-font" | "-thumb-fontsize" ) # removed
1677
usage_error \
1678
- "The $1 option has been renamed. Now use: -titles-${1##*-}"
1679
+ "The $1 option now renamed. Try: -titles-${1##*-} or check manual"
1680
;;
1681
*-stroke-col* ) # removed
1682
- usage_error "The $1 option has been renamed. Now use: ${1%-*}"
1683
+ usage_error \
1684
+ "The $1 option now renamed. Try: ${1%-*} or check manual"
1685
;;
1686
"-text-mist" )
1687
MIST=:
1688
1689
shift
1690
MENU_TITLE="$1"
1691
;;
1692
- "-menu-font" )
1693
+ "-menu-title-font" | "-title-font" | "-menu-font" )
1694
shift
1695
MENU_FONT=$(get_font "$1")
1696
;;
1697
- "-menu-fontsize" )
1698
+ "-menu-title-fontsize" | "-title-fontsize" | "-menu-fontsize" )
1699
shift
1700
MENU_FONTSIZE="$1"
1701
;;
1702
1703
shift
1704
USER_SC_GEO=:
1705
SHOWCASE_GEO=$1
1706
+ ! grep -q "+[0-9]*+[0-9]*" <<< $SHOWCASE_GEO && usage_error \
1707
+ "-showcase-geo argument must be the position geometry in form +X+Y"
1708
;;
1709
"-submenu-audio-seek" ) # not implemented yet
1710
shift
1711
1712
USER_TITLE_GEO=:
1713
shift
1714
TITLE_GRAVITY=$1
1715
+ # centre => center ... no other direction has re in it :)
1716
TITLE_GRAVITY=${TITLE_GRAVITY/re/er}
1717
;;
1718
"-menu-title-offset" )
1719
1720
done
1721
USER_THUMBS=:
1722
;;
1723
+ "-from-gui" )
1724
+ FROM_GUI=:
1725
+ ;;
1726
"-config" | "-ntscfilm" | "-dvd-vcd" | "-half-dvd" | "-kvcd" | \
1727
"-kvcdx3" | "-kvcdx3a" | "-kdvd" | "-bdvd" | "-704" | "-normalize" | \
1728
"-amplitude" | "-overwrite" | "-panavision" | "-force" | "-fps" | \
1729
1730
"-abitrate" | "-priority" | "-deinterlace" | "-progressive" | \
1731
"-interlaced" | "-interlaced_bf" | "-type" | "-fit" | "-discsize" | \
1732
"-parallel" | "-mkvsub" | "-autosubs" | "-subtitles" | "-update" | \
1733
- "-mplayeropts" | "-audiotrack" | "-downmix" | "-ffmpeg" | "-nofifo" | \
1734
- "-from-gui" | "-noask" | "-slice" | "-async" | "-quiet" | \
1735
+ "-mplayeropts" | "-audiotrack" | "-downmix" | "-ffmpeg" | "-avconv" | \
1736
+ "-nofifo" | "-from-gui" | "-noask" | "-slice" | "-async" | "-quiet" | \
1737
"-fake" | "-keepfiles" )
1738
# remove this warning for tovid 0.33 TODO
1739
if [[ $1 = "-subtitles" ]]; then
1740
1741
else
1742
TOVID_OPTS+=( "$1" "$(readlink -f "$2")" )
1743
fi
1744
+ elif [[ $1 == '-mplayeropts' ]]; then
1745
+ # -mplayeropts can start with a '-' so just get entire string.
1746
+ # TODO allow using -mplayeropts for each video, use "" for none
1747
+ # [[ "${2+defined}" && -z $2 ]] ... MPLAYER_OPTS+=("")
1748
+ TOVID_OPTS+=("$1" "$2")
1749
+ shift
1750
else
1751
TOVID_OPTS+=( "$1" )
1752
shift
1753
1754
1755
# get script pid so we can kill the parent if doing recursive todisc's
1756
TODISC_PIDS="$TODISC_PIDS $$"
1757
+ ########################################################################
1758
+ ### Setup and error checks (Critical 1st, Warnings after log created ###
1759
+ ########################################################################
1760
+
1761
# make sure dvd-slideshow is installed if user passed -use-dvd-slideshow
1762
$USE_DVD_SLIDESHOW && assert_dep dvd-slideshow \
1763
"The program dvd-slideshow was not found - you can get it from
1764
1765
# for switched menus the 1st menu (MN) made is the 2nd, not the 1st
1766
{ $SWITCHED_MODE || $SWITCHED_MENUS ; } && MN=2 || MN=1
1767
1768
-if [[ ${#TITLES[@]} -eq 0 ]]; then
1769
- if [[ $MENU_NUM = $MN ]] && ! $NOMENU \
1770
- && ! $SINGLE_SLIDESHOW && ! $DO_TITLESETS && $MONTAGE_MENU; then
1771
- yecho
1772
- yecho "You did not provide any titles with -titles"
1773
- yecho "Using the basename of each file provided (minus the extension)."
1774
- yecho
1775
- ((sshows < 1)) && $WARN && sleep 5
1776
- fi
1777
- for i in ${!FILES[@]}; do
1778
- TITLE=${FILES[i]##*/}
1779
- TITLES[i]=" ${TITLE%%.*} "
1780
- done
1781
-fi
1782
-if ! $TITLESET_MODE && ! $DO_TITLESETS && $QUICK_NAV && ! $VMGM_ONLY; then
1783
- QUICK_NAV=false
1784
- yecho
1785
- yecho "No -quick-nav unless doing titlesets ... disabling this option"
1786
- $WARN && sleep 5
1787
- yecho
1788
-fi
1789
if $DO_TITLESETS && ! $VMGM_MENU && ! $QUICK_NAV; then
1790
usage_error \
1791
"You can not use -no-vmgm if doing titlesets unless using -quick-nav"
1792
1793
SC_TITLE_ALIGN="west"
1794
SHOWCASE=:
1795
fi
1796
+# usage error on mispellings for *align* options
1797
+case $BUTTON_GRAVITY in
1798
+ north|south|east|west|northwest|northeast|southwest|southeast|center)
1799
+ :
1800
+ ;;
1801
+ *)
1802
+ usage_error "$BUTTON_GRAVITY is an incorrect argument for '-align'"
1803
+ ;;
1804
+esac
1805
+case $SC_TITLE_ALIGN in
1806
+ west|east|center)
1807
+ :
1808
+ ;;
1809
+ *)
1810
+ usage_error "$SC_TITLE_ALIGN is an incorrect argument for \
1811
+ '-showcase-titles-align'"
1812
+ ;;
1813
+esac
1814
if $TEXTMENU; then
1815
SHOWCASE=:
1816
IMG_FMT="png"
1817
- SC_TITLE_ALIGN="west"
1818
+ # default -align for textmenu is northwest, not north
1819
+ ! $USER_GRAVITY && BUTTON_GRAVITY="northwest"
1820
+elif $SHOWCASE; then
1821
+ ! $USER_GRAVITY && BUTTON_GRAVITY="northwest" # with thumbs, use defaults
1822
fi
1823
# incompatible slideshow options with -switched-menus
1824
if { $CAROUSEL_IS_BG || $CAROUSEL_IS_SHOWCASE ; } && $SWITCHED_MENUS; then
1825
$CAROUSEL_IS_BG && OPT="-background-slideshow" || OPT="-showcase-slideshow"
1826
- yecho
1827
- yecho "$OPT uses slides from ALL slideshows, so its use with
1828
+ info_message "$OPT uses slides from ALL slideshows, so its use with \
1829
-switched-menus makes no sense. Removing this option for you."
1830
- yecho
1831
CAROUSEL_IS_SHOWCASE=false; CAROUSEL_IS_BG=false
1832
- $WARN && sleep 10
1833
+ $WARN && continue_in 5
1834
fi
1835
# slideshows are animated by default like rest of todisc
1836
if ((sshows>=1)); then
1837
1838
SLIDE_FADE=:
1839
fi
1840
fi
1841
+
1842
+# you can not use submenus with slideshows
1843
+if ((num_slideshows>0)) && $SUB_MENU; then
1844
+ usage_error "You can not use submenus with slideshows. If you have
1845
+ a mixed menu of videos and slideshows, but want submenus for the videos,
1846
+ you will have to put the videos in a separate titleset instead."
1847
+fi
1848
+
1849
+
1850
#if $DO_CAROUSEL && $SHOWCASE && ! { $SWITCHED_MODE || $SWITCHED_MENUS ; } && \
1851
# ! $CAROUSEL_IS_BG && ! $CAROUSEL_IS_SHOWCASE && ((sshows<=1)); then
1852
# yecho
1853
1854
: ${BASEDIR:="$WORK_DIR"}
1855
1856
# Make sure -out was provided and it is valid
1857
-if test -n "$OUT_PREFIX"; then
1858
- OUT_DIR=$(readlink -f "$OUT_PREFIX")
1859
+if test -n "$OUT_DIRECTORY"; then
1860
+ OUT_DIR=$(readlink -f "$OUT_DIRECTORY")
1861
if [[ ! -d ${OUT_DIR%/*} ]]; then
1862
- OUT_PATH=$(readlink -m "$OUT_PREFIX")
1863
+ OUT_PATH=$(readlink -m "$OUT_DIRECTORY")
1864
usage_error "The -out path ${OUT_PATH%/*}/ does not exist"
1865
fi
1866
if egrep -q '<|>|&' <<< "$OUT_DIR"; then
1867
1868
Please change the directory you gave as an -out argument."
1869
fi
1870
else
1871
- usage_error "Please provide an output name with -out"
1872
+ ! $ENCODE_ONLY && usage_error "Please provide an output name with -out"
1873
fi
1874
### dvdauthor stuff
1875
# for xml, if -intro was used
1876
1877
[[ -z $NR_AMT ]] && NR_AMT=200
1878
NR="$NR $NR_AMT"
1879
fi
1880
-# check for -loop or -loop_input
1881
-ffmpeg_help=$(ffmpeg -h 2>&1)
1882
-if grep -q -- '^-loop ' <<< "$ffmpeg_help"; then
1883
- LOOP="-loop 1"
1884
-else
1885
- LOOP="-loop_input"
1886
-fi
1887
1888
# assign values for slides
1889
# blurs
1890
1891
# allow -thumb-frame-size (otherwise unused for 3D thumbs) to set -raise
1892
((USER_THUMB_FRAME_SIZE)) && RAISE="-raise $THUMB_FRAME_SIZE"
1893
1894
+# centre aligned titles under showcase thumbs need extra safe room
1895
+if [[ $SC_TITLE_ALIGN = center ]]; then
1896
+ SAFE_OFFSET=36
1897
+ $USER_SAFE_AREA && SAFE_OFFSET=$((86-SAFE_AREA))
1898
+fi
1899
1900
# honour -noask for functions and called scripts that use them
1901
$NOASK && NO_ASK="-noask"
1902
-# Warn if thumb labels have more than 16 characters
1903
-if ! $SHOWCASE; then
1904
- for ((i=0; i<${#TITLES[@]}; i++)); do
1905
- val=${#TITLES[i]}
1906
- [ -z "$MAX_CHARS" ] || ((val > MAX_CHARS)) && MAX_CHARS=$val && key=$i
1907
- done
1908
- if [[ ${#TITLES[@]} -gt 6 \
1909
- && $MAX_CHARS -gt 16 ]] && ! $SINGLE_SLIDESHOW; then
1910
- yecho
1911
- yecho "WARNING! Some titles are longer than 16 characters; \
1912
- they may be chopped off."
1913
- yecho
1914
- #echo "\"${TITLES[key]}\" is too long; please use a shorter title."
1915
- #exit 1
1916
- fi
1917
+
1918
+#####################################
1919
+# backend checks #
1920
+####################################
1921
+
1922
+# transcode is needed for making animated submenu, else we can use just ffmpeg
1923
+hash transcode 2>/dev/null || use_transcode=false
1924
+# todisc should run if mjpegtools not installed, assumes -ffmpeg for 'tovid mpg'
1925
+hash yuvcorrect 2>/dev/null || yuv_correct=remove_header
1926
+#$ANI_SUB_MENU && assert_dep transcode "transcode is required for making
1927
+# animated submenus"
1928
+if $use_transcode; then
1929
+ # transcode version >= 1.1.0 mandated
1930
+ _transcode_version=$(transcode -v 2>&1| awk '{gsub("v", ""); print $2}')
1931
+ _baseline_version=1.1.0
1932
+ if ! test_version $_transcode_version $_baseline_version; then
1933
+ test -f "$LOG_FILE" && rm -f "$LOG_FILE"
1934
+ runtime_error \
1935
+ "transcode version 1.1.0 or newer required to run this script (todisc).
1936
+ If you must use version $_transcode_version use tovid 0.34 or older."
1937
+ fi
1938
+ # stock debian transcode and probably others missing export_yuv4mpeg module
1939
+ if ! ls -1 $( tcmodinfo -p )/export*.so |grep -q yuv4mpeg; then
1940
+ test -f "$LOG_FILE" && rm -f "$LOG_FILE"
1941
+ _url="http://tovid.wikia.com/wiki/Known_bugs#tovid_is_broken_on_Debian"
1942
+ runtime_error \
1943
+ "your transcode is missing the yuv4mpeg export module. See $_url"
1944
+ fi
1945
+fi
1946
+# ffmpeg - minimum version: 0.7, which has necessary filters
1947
+ffmpeg_help=$($FFmpeg -h full 2>&1)
1948
+ff_filters=$($FFmpeg -filters 2>/dev/null | awk 'f;/Filters:/{f=1}')
1949
+# if no filters present show a runtime error and exit
1950
+[[ "$ff_filters" ]] || \
1951
+ runtime_error "Your ${FFmpeg##*/} is too old ! No filter support."
1952
+# newer ffmpeg's use setdar= and setsar=
1953
+if grep -qw setdar <<< "$ff_filters"; then
1954
+ ASPECT="setdar=4:3" # for menu. Always 4:3 aspect
1955
+# somewhat older rev's used aspect=
1956
+elif grep -qw ^aspect <<< "$ff_filters"; then
1957
+ ASPECT="aspect=4:3"
1958
fi
1959
-# backend checks
1960
-# transcode version >= 1.1.0 mandated
1961
-_transcode_version=$(transcode -v 2>&1| awk '{gsub("v", ""); print $2}')
1962
-_baseline_version=1.1.0
1963
-if ! test_version $_transcode_version $_baseline_version; then
1964
- runtime_error \
1965
- "transcode version 1.1.0 or newer is required to run this script (todisc).
1966
- If you must use version $_transcode_version use tovid 0.34 or older."
1967
+# check for -loop or -loop_input (-loop from 0.9 onwards)
1968
+if grep -q -- '^-loop ' <<< "$ffmpeg_help"; then
1969
+ LOOP="-loop 1"
1970
+else
1971
+ LOOP="-loop_input"
1972
fi
1973
-# ffmpeg has been buggy with setting AR with -aspect, use -vf aspect if present
1974
+# switch form video filters: -vf or -vfilters
1975
# "-vf" was "-vfilters" briefly, check
1976
-FF_HELP=$(ffmpeg -h 2>&1)
1977
-if grep -qw -- -vf <<< "$FF_HELP"; then
1978
+if grep -qw -- -vf <<< "$ffmpeg_help"; then
1979
VF="-vf"
1980
# somewhat older is "-vfilters"
1981
-elif grep -qw -- -vfilters <<< "$FF_HELP"; then
1982
+elif grep -qw -- -vfilters <<< "$ffmpeg_help"; then
1983
VF="-vfilters"
1984
+else # this should not run as we would have exited checking for -filters above
1985
+ runtime_error "Your ffmpeg is too old: missing video filters"
1986
fi
1987
-# ffmpeg's -vf aspect is more dependable than -aspect, if ffmpeg is new enough
1988
-FF_FILTERS=$(ffmpeg -filters 2>&1)
1989
-# newer ffmpeg's use setdar= and setsar=
1990
-if grep -qw ^setdar <<< "$FF_FILTERS"; then
1991
- ASPECT="$VF setdar=4:3" # for menu. Always 4:3 aspect
1992
- SS_ASPECT="$VF setdar=4:3" # for slideshows. Always 4:3 aspect
1993
-# somewhat older rev's used aspect=
1994
-elif grep -qw ^aspect <<< "$FF_FILTERS"; then
1995
- ASPECT="$VF aspect=4:3"
1996
- SS_ASPECT="$VF aspect=4:3"
1997
+
1998
+# ffmpeg will not allow setting -pix_fmt before the -i if > 0.8.x
1999
+make_dummy
2000
+if $FFmpeg -pix_fmt yuv420p -t 0.13 -i "$WORK_DIR/dummy.mpg" \
2001
+ -f null -y /dev/null >/dev/null 2>&1; then
2002
+ PIPE_FORMAT="-pix_fmt yuv420p -f yuv4mpegpipe"
2003
else
2004
- ASPECT="-aspect 4:3"
2005
- SS_ASPECT="-aspect 4:3"
2006
+ PIPE_FORMAT="-f yuv4mpegpipe"
2007
fi
2008
-
2009
+# -acodec, -vcodec, -b and -ab now use per stream options (-b:v)
2010
+if $FFmpeg -i "$WORK_DIR/dummy.mpg" -t 0.13 \
2011
+ -b:v 500k -f null -y /dev/null >/dev/null 2>&1; then
2012
+ VB=-b:v
2013
+ AB=-b:a
2014
+ CA=-c:a
2015
+else
2016
+ VB=-b
2017
+ AB=-ab
2018
+ CA=-acodec
2019
+fi
2020
+rm -f "$WORK_DIR/dummy.mpg"
2021
+
2022
+#####################################
2023
+# end backend checks #
2024
+#####################################
2025
+
2026
# set some vars for switched menus so we know where we are
2027
$SWITCHED_MODE && SWITCHED_MENUS=false
2028
{ $SWITCHED_MODE || $SWITCHED_MENUS ; } && SWITCHED=:
2029
+# check if user passed a usable thumb or showcase shape
2030
+if [[ -n $THUMB_SHAPE ]]; then
2031
+ if ! check_maskshape $THUMB_SHAPE; then
2032
+ usage_error "Please supply a usable thumb shape with
2033
+ -thumb-shape option. You gave \"$THUMB_SHAPE\""
2034
+ fi
2035
+
2036
+fi
2037
+# -user-thumbs is only compatible with static thumbs (-static)
2038
+if $USER_THUMBS && ! $STATIC; then
2039
+ if $SWITCHED_MENUS; then
2040
+ usage_error "If doing switched menus -user-thumbs can only be used
2041
+ with a static menu (-static)"
2042
+ else
2043
+ usage_error "-user-thumbs option is for static buttons only (-static)"
2044
+ fi
2045
+fi
2046
+
2047
+# check for legal -button-style option
2048
+case $BUTTON_STYLE in
2049
+ line|text|text-rect|rect)
2050
+ :
2051
+ ;;
2052
+ *)
2053
+ usage_error "\"$BUTTON_STYLE\" is not a -button-style arg"
2054
+ ;;
2055
+esac
2056
+# transparent border around text so rect spumux outline can fit
2057
+if [[ $BUTTON_STYLE = "text-rect" ]]; then
2058
+ TEXT_BORDER="-bordercolor Transparent -border 8x8"
2059
+fi
2060
+
2061
+# If output directory already exists, print a message and exit
2062
+if test -e "$OUT_DIR"; then
2063
+ echo "Cleaning up created dirs"
2064
+ yecho
2065
+ echo "A file or directory named \"$OUT_DIR\" already exists."
2066
+ echo "Please use a different -out name, "
2067
+ echo "or (re)move the existing file or directory."
2068
+ rm -rf "$REAL_WORK_DIR"
2069
+ rm -f "$WORK_DIR"
2070
+ exit 1
2071
+fi
2072
+# Remove any existing log file, and print headers, unless recursing
2073
+if ! $SWITCHED_MODE && ! $TITLESET_MODE && \
2074
+! $MK_CAROUSEL_MODE && ! $VMGM_ONLY; then
2075
+ test -f "$LOG_FILE" && rm -f "$LOG_FILE"
2076
+ echo
2077
+ # script details for the log file
2078
+ PATTERN=$(for ((i=1; i<=79; i++)); do echo -n \*; done)
2079
+ printf "%s\n%s\n%s\n\n\n" "$PATTERN" \
2080
+ "todisc from the tovid suite ($TOVID_VERSION) - log for `date`" \
2081
+ "$PATTERN" >> "$LOG_FILE"
2082
+ script_args=( ${0##*/} "${args[@]}" )
2083
+ #for i in "${script_args[@]}"; do printf "%s %s\n" "$ME" "$i"; done
2084
+ # do some locale debugging
2085
+ printf "\n%s%s\n" "$ME" "You are using the following locale settings:" >> "$LOG_FILE"
2086
+ locale_env=( $(locale) )
2087
+ for v in "${locale_env[@]}"; do printf "%s %s\n" "$ME" "$v"; done >> "$LOG_FILE"
2088
+ printf "\n\n" >> "$LOG_FILE"
2089
+fi
2090
+# put command line into log for debugging - changes with recursive todisc calls
2091
+_args=( todisc "${args[@]}" )
2092
+for i in "${_args[@]}"; do printf "%s %s\n" "$ME" "$i"; done >> "$LOG_FILE"
2093
+print2log ""
2094
+ ##########################################################################
2095
+ ########## More setup, and non-critical info + warning messages ##########
2096
+ ##########################################################################
2097
+
2098
+# information about -titles option in case user doesn't know
2099
+if [[ ${#TITLES[@]} -eq 0 ]]; then
2100
+ if [[ $MENU_NUM = $MN ]] && ! $NOMENU \
2101
+ && ! $SINGLE_SLIDESHOW && ! $DO_TITLESETS && $MONTAGE_MENU; then
2102
+ info_message "You did not provide any titles with -titles. Using the \
2103
+ basename of each file provided (minus the extension)."
2104
+ ((sshows < 1)) && $WARN && continue_in 5
2105
+ fi
2106
+ for i in ${!FILES[@]}; do
2107
+ title=${FILES[i]##*/}
2108
+ TITLES[i]=" ${title%%.*} "
2109
+ done
2110
+ unset title
2111
+fi
2112
+if ! $SINGLE_SLIDESHOW; then
2113
+ for i in ${!FILES[@]}; do
2114
+ if [[ ! ${TITLES[i]} && $BUTTON_STYLE != "rect" ]]; then
2115
+ notitles=1
2116
+ fi
2117
+ done
2118
+ if ((notitles)); then
2119
+ $USER_BSTYLE && notit_mess="You can not use \"$BUTTON_STYLE\" button
2120
+ style with no titles. " || notit_mess="You have no titles. "
2121
+ info_message "$notit_mess Setting button style to 'rect' style for you"
2122
+ BUTTON_STYLE=rect
2123
+ TITLES_CLR=none
2124
+ V_TITLES_STROKE=none
2125
+ $WARN && continue_in 5
2126
+ fi
2127
+fi
2128
+if ! $TITLESET_MODE && ! $DO_TITLESETS && $QUICK_NAV && ! $VMGM_ONLY; then
2129
+ QUICK_NAV=false
2130
+ info_message "No -quick-nav unless doing titlesets ... disabling this option"
2131
+ $WARN && continue_in 5
2132
+fi
2133
+# Warn if thumb labels have more than 16 characters
2134
+if ! $SHOWCASE && ! $ENCODE_ONLY && ! $NOMENU; then
2135
+ for ((i=0; i<${#TITLES[@]}; i++)); do
2136
+ val=${#TITLES[i]}
2137
+ [ -z "$MAX_CHARS" ] || ((val > MAX_CHARS)) && MAX_CHARS=$val && key=$i
2138
+ done
2139
+ if [[ ${#TITLES[@]} -gt 6 \
2140
+ && $MAX_CHARS -gt 16 ]] && ! $SINGLE_SLIDESHOW; then
2141
+ info_message "WARNING! Some titles are longer than 16 characters; \
2142
+ they may be chopped off."
2143
+ $WARN && continue_in 5
2144
+ #echo "\"${TITLES[key]}\" is too long; please use a shorter title."
2145
+ #exit 1
2146
+ fi
2147
+fi
2148
# warn about change in -thumb-mist option
2149
if $FEATHER && ! $USE_FEATHER_MASK; then
2150
- yecho
2151
- yecho "Note: feathered thumb shapes no longer have mist background
2152
+ info_message "Note: feathered thumb shapes no longer have mist background
2153
by default. Use -thumb-mist [COLOR] to get the old behavior"
2154
- yecho
2155
- $WARN && sleep 5
2156
+ $WARN && continue_in 5
2157
fi
2158
#
2159
# sanity checks for button style ( -button-style ) for menu buttons
2160
#
2161
-
2162
# use a suitable button style
2163
if ! $SINGLE_SLIDESHOW; then
2164
for ((i=0; i<${#FILES[@]}; i++)); do
2165
if test $(wc -l <<< "$(echo -e "${TITLES[i]}")") -gt 1; then
2166
MULTILINE_TITLE=:
2167
- if $FEATHER && [ $THUMB_SHAPE != "normal" ]; then
2168
- # multiline titles not suitable for text buttons
2169
- BUTTON_STYLE="text-rect"
2170
- elif $TEXTMENU; then
2171
- [[ $BUTTON_STYLE != "line" ]] && BUTTON_STYLE="text-rect"
2172
- else
2173
- [[ $BUTTON_STYLE != "text-rect" ]] \
2174
- && ! $USER_BSTYLE && BUTTON_STYLE="rect"
2175
- fi
2176
fi
2177
done
2178
+ # multiline titles not suitable for text buttons
2179
+ if $MULTILINE_TITLE && [[ $BUTTON_STYLE = "text" ]]; then
2180
+ BUTTON_STYLE="line"
2181
+ info_message "'text' button style not suitable for multi-line
2182
+ titles, using 'line' style instead"
2183
+ $WARN && continue_in 3
2184
+ fi
2185
2186
- # disallow spaces in thumb titles for text button style
2187
+ # remove multiple spaces in video titles for text button style
2188
if [ "$BUTTON_STYLE" = "text" ]; then
2189
for ((i=0; i<${#TITLES[@]}; i++)); do
2190
T=$(sed 's/^[ \t]*//;s/[ \t]*$//' <<< "${TITLES[i]}")
2191
if grep " " <<< "$T" >/dev/null; then
2192
- echo "Sorry, a maximum of one consecutive space is allowed
2193
+ info_message "Sorry, a maximum of one consecutive space is allowed
2194
in titles for text buttons. \"${TITLES[i]}\" has more than
2195
- one consecutive space in it" |fold -bs
2196
- exit 1
2197
+ one consecutive space in it. Removing the extra spaces for you."
2198
+ new_title=$("s/^ *//;s/ *$//;s/ \{1,\}/ /g" <<< "${TITLES[i]}")
2199
+ TITLES[i]="$new_title"
2200
+ $WARN && continue_in 5
2201
fi
2202
done
2203
fi
2204
fi
2205
if { $TEXTMENU || $QUICK_MENU ; } && [[ $BUTTON_STYLE = "rect" ]]; then
2206
- if $MULTILINE_TITLE; then
2207
- BUTTON_STYLE="text-rect"
2208
- else
2209
- BUTTON_STYLE="line"
2210
- fi
2211
+ BUTTON_STYLE="line"
2212
if ((MENU_NUM==2)) || { ! $SWITCHED_MODE && ! $SWITCHED_MENUS ; }; then
2213
if $USER_BSTYLE; then
2214
- yecho
2215
- yecho "Using button style '$BUTTON_STYLE' instead of 'rect'
2216
+ info_message "Using button style '$BUTTON_STYLE' instead of 'rect'
2217
for textmenu menu"
2218
- yecho
2219
- $WARN && sleep 10
2220
- fi
2221
- fi
2222
-fi
2223
-# allow multiline titles in submenu
2224
-if [[ -n "$SM_TITLES" ]]; then
2225
- for i in ${!SM_TITLES[@]}; do
2226
- if [[ $(echo -e "${SM_TITLES[i]}" |wc -l) -gt 1 ]]; then
2227
- SM_TITLES[i]="$(echo -e "${SM_TITLES[i]}")"
2228
+ $WARN && continue_in 3
2229
fi
2230
- done
2231
-fi
2232
-# check if user passed a usable thumb or showcase shape
2233
-if [[ -n $THUMB_SHAPE ]]; then
2234
- if ! check_maskshape $THUMB_SHAPE; then
2235
- usage_error "Please supply a usable thumb shape with
2236
- -thumb-shape option. You gave \"$THUMB_SHAPE\""
2237
- fi
2238
-
2239
-fi
2240
-if [[ -n $SHOWCASE_SHAPE ]]; then
2241
- if ! check_maskshape $SHOWCASE_SHAPE; then
2242
- usage_error "Please supply a usable showcase shape with
2243
- -showcase-shape option. You gave \"$SHOWCASE_SHAPE\""
2244
fi
2245
fi
2246
if [[ -n ${ROTATE_ARRAY[@]} ]]; then
2247
2248
if [[ $BUTTON_STYLE = *rect* ]]; then
2249
BUTTON_STYLE="line"
2250
if $USER_BSTYLE; then
2251
- yecho
2252
- echo "'*rect' button styles with rotated thumbs don't play well"
2253
- echo "with spumux buttons. Setting button style to "
2254
- echo "'line'. You may also use 'text' style"
2255
- echo "Quit now if you wish to exit and examine your options"
2256
- yecho
2257
- $WARN && sleep 10
2258
+ info_message "'*rect' button styles with rotated thumbs don't
2259
+ play well with spumux buttons. Setting button style to
2260
+ 'line'. You may also use 'text' style.
2261
+ Quit now if you wish to exit and examine your options"
2262
+ $WARN && continue_in 10
2263
fi
2264
fi
2265
fi
2266
fi
2267
-if ! $SINGLE_SLIDESHOW; then
2268
- for i in ${!FILES[@]}; do
2269
- if [[ ! ${TITLES[i]} && $BUTTON_STYLE != "rect" ]]; then
2270
- usage_error "You can not use \"$BUTTON_STYLE\" button style if
2271
- you have no titles. Use 'rect' style instead"
2272
- fi
2273
- done
2274
-fi
2275
#
2276
# end of button-style checks
2277
#
2278
-
2279
-# transparent border around text so rect spumux outline can fit
2280
-if [[ $BUTTON_STYLE = "text-rect" ]]; then
2281
- TEXT_BORDER="-bordercolor Transparent -border 8x8"
2282
+if [[ -n $SHOWCASE_SHAPE ]]; then
2283
+ # if -wave also (incompatible), disable -showcase-shape and give warning
2284
+ if [[ -n $WAVE ]]; then
2285
+ info_message "-showcase-shape incompatible with -wave, \
2286
+ disabling -showcase-shape for you"
2287
+ SHOWCASE_SHAPE=""
2288
+ $WARN && continue_in 3
2289
+ else
2290
+ ! check_maskshape $SHOWCASE_SHAPE && \
2291
+ usage_error "Please supply a usable showcase shape with
2292
+ -showcase-shape option. You gave \"$SHOWCASE_SHAPE\""
2293
+ fi
2294
fi
2295
2296
-# If output directory already exists, print a message and exit
2297
-if test -e "$OUT_DIR"; then
2298
- echo "Cleaning up created dirs"
2299
- yecho
2300
- echo "A file or directory named \"$OUT_DIR\" already exists."
2301
- echo "Please use a different -out name, "
2302
- echo "or (re)move the existing file or directory."
2303
- rm -rf "$REAL_WORK_DIR"
2304
- rm -f "$WORK_DIR"
2305
- exit 1
2306
+# allow multiline titles in submenu
2307
+if [[ -n "$SM_TITLES" ]]; then
2308
+ for i in ${!SM_TITLES[@]}; do
2309
+ if [[ $(echo -e "${SM_TITLES[i]}" |wc -l) -gt 1 ]]; then
2310
+ SM_TITLES[i]="$(echo -e "${SM_TITLES[i]}")"
2311
+ fi
2312
+ done
2313
fi
2314
-# Remove any existing log file unless recursing
2315
-if ! $SWITCHED_MODE && ! $TITLESET_MODE && \
2316
-! $MK_CAROUSEL_MODE && ! $VMGM_ONLY; then
2317
- test -f "$LOG_FILE" && rm -fv "$LOG_FILE"
2318
+# copy symlinks for -group hack
2319
+if $GROUPING && $TITLESET_MODE; then
2320
+ find "$WORK_DIR"/ -name \*group\*.mpg -exec cp -P {} "$BASEDIR" \;
2321
fi
2322
+# carousel's are made BEFORE switched menus - so don't do them in switched mode
2323
+$SWITCHED_MODE && DO_CAROUSEL=false
2324
+
2325
+# save value of default chapters
2326
+! $USER_CHAPTERS && (( ${#CHAPTERS[@]} == 1 )) && default_chapters=${CHAPTERS[0]}
2327
+
2328
# see if imagemagick supports -vignette for the oval shape
2329
if [[ $THUMB_SHAPE == "vignette" || $SHOWCASE_SHAPE == "vignette" ]]; then
2330
if ! convert -help 2>&1 | egrep -q -- "-vignette"; then
2331
2332
[[ $SHOWCASE_SHAPE == "vignette" ]] && SHOWCASE_SHAPE="oval"
2333
! ((USER_BLUR)) && BLUR=3
2334
! ((SC_USER_BLUR)) && SC_BLUR=3
2335
- warning_message \
2336
- "INFO: -vignette option not available in your imagemagick version.
2337
+ info_message \
2338
+ "Note: -vignette option not available in your imagemagick version.
2339
You should upgrade it. Using 'oval' mask shape instead which is
2340
similar. Setting the blur to 3 unless you used '-blur' (thumbs) or
2341
'-showcase-blur' (showcase file)"
2342
- $WARN && sleep 5
2343
+ $WARN && continue_in 5
2344
fi
2345
fi
2346
# see if advanced options were used and give warning if so
2347
if [[ -n "${ADV_OPT[@]}" ]] && ! $SWITCHED_MODE; then
2348
- yecho
2349
- yecho "***** WARNING *****"
2350
+ yecho ""
2351
+ printgreen "*** Note: ***"
2352
yecho "You have used the following advanced options:"
2353
yecho "${ADV_OPT[@]}" | format_output
2354
- yecho "With these options it is possible to create a menu where things \
2355
- overlap or are offscreen, or that has other problems, so please check it \
2356
- with the preview. These are things that todisc tries to avoid normally, \
2357
- so if you have problems, please leave them out."
2358
- yecho
2359
- $WARN && sleep 15
2360
-fi
2361
-
2362
-# copy symlinks for -group hack
2363
-if $GROUPING && $TITLESET_MODE; then
2364
- find "$WORK_DIR"/ -name \*group\*.mpg -exec cp -P {} "$BASEDIR" \;
2365
+ yecho "With these options it is possible to create a menu where things "
2366
+ yecho "overlap or are offscreen, or that has other problems, "
2367
+ yecho "so please check it with the preview."
2368
+ printgreen "***************"
2369
+ yecho ""
2370
+ $WARN && continue_in 7
2371
fi
2372
-# carousel's are made BEFORE switched menus - so don't do them in switched mode
2373
-$SWITCHED_MODE && DO_CAROUSEL=false
2374
-
2375
-# save value of default chapters
2376
-! $USER_CHAPTERS && (( ${#CHAPTERS[@]} == 1 )) && default_chapters=${CHAPTERS[0]}
2377
-
2378
-# script details for the log file
2379
-PATTERN=$(for ((i=1; i<=79; i++)); do echo -n \*; done)
2380
-printf "%s\n%s\n%s\n\n\n" "$PATTERN" \
2381
-"todisc from the tovid suite ($TOVID_VERSION) - log for `date`" \
2382
-"$PATTERN" >> "$LOG_FILE"
2383
-# put the command line into the log file to aid debugging
2384
-printf "%s\n%s\n" todisc "${args[@]}" | sed "s/ */ /g;s/^ *//" | fold -bs >> "$LOG_FILE"
2385
-# do some locale debugging
2386
-echo -e "\nYou are using the following locale settings:" >> "$LOG_FILE"
2387
-locale >> "$LOG_FILE" 2>&1
2388
-echo >> "$LOG_FILE"
2389
2390
# check aspect ratios of infiles so thumbs are in aspect without -aspect passed
2391
-if ((inc_files)) && [[ -z "$V_ASPECT" ]]; then
2392
- yecho
2393
- yecho "Determining aspect ratio of videos"
2394
+# this is done before makempg converts non-compliant files so it is really only
2395
+# useful to get a preview
2396
+if ((inc_files && MENU_NUM == 1)) && [[ ! "$V_ASPECT" ]] \
2397
+ && ! $VMGM_ONLY && ! $ENCODE_ONLY; then
2398
+ yecho "Determining aspect ratio of videos for the preview."
2399
+ yecho ""
2400
+ yecho "If SURE of ratios skip this step with '-aspect ASPECT' \
2401
+ (but it is best if you always run it first to check)."
2402
+ #$WARN && continue_in 3
2403
+ echo
2404
+ cur_aspect=""
2405
for ((i=0; i<${#FILES[@]}; i++)); do
2406
- ! $SINGLE_SLIDESHOW && yecho "Checking aspect ratios: ${FILES[i]}"
2407
- stats[i]=$(idvid -terse -fast "${FILES[i]}" 2>/dev/null |
2408
- awk -F= '/V_ASPECT_WIDTH=/ {print $2}' 2>/dev/null)
2409
- cur_aspect=${stats[i]}
2410
- if ((cur_aspect)); then
2411
- [[ $cur_aspect = 133 ]] && ASPECT_RATIO=4:3
2412
- [[ $cur_aspect = 177 ]] && ASPECT_RATIO=16:9
2413
- yecho "Aspect ratio of $ASPECT_RATIO found.
2414
- Videos in this menu (titleset) will be done using that ratio."
2415
- ((cur_aspect==177||cur_aspect==133)) && break
2416
+ curfile=${FILES[i]}
2417
+ ! $SINGLE_SLIDESHOW && print2log "Checking aspect ratios: ${FILES[i]##*/}"
2418
+ # check if image, then check aspect ratio of image if so
2419
+ check_filetype "$curfile"
2420
+ if [[ $file_type = 'image' ]]; then
2421
+ stat=133
2422
+ elif [[ $file_type = 'video' ]]; then
2423
+ stat=$(idvid -terse -fast "${FILES[i]}" 2>/dev/null |
2424
+ awk -F= '/V_ASPECT_WIDTH=/ {print $2}' 2>/dev/null)
2425
+ else
2426
+ usage_error "Sorry could not identify file ${FILES[i]}"
2427
+ fi
2428
+ #if [[ $(file -L "$curfile" | awk '{ $1 = ""; print }') =~ image ]]; then
2429
+ # stat=133
2430
+ #elif mencoder -quiet -oac pcm -ovc copy \
2431
+ # -frames 0 -o /dev/null "${FILES[i]}" &>/dev/null; then
2432
+ # it is a video, check aspect ratio
2433
+ # stat=$(idvid -terse -fast "${FILES[i]}" 2>/dev/null |
2434
+ # awk -F= '/V_ASPECT_WIDTH=/ {print $2}' 2>/dev/null)
2435
+ #else
2436
+ # usage_error "Sorry could not identify file ${FILES[i]}"
2437
+ #fi
2438
+ # exit from the loop
2439
+ # save list of files without reported aspect ratio for a warning
2440
+ { [[ $stat = 0 ]] || ! test_is_number $stat; } && warn_files[i]=${FILES[i]}
2441
+ stats[i]=${stat:-0}
2442
+ # round up to 177 or down to 133 in the same way as makempg does for
2443
+ # padding, so we know what aspect it will be after conversion
2444
+ if (( ${stats[i]} > 153 )); then
2445
+ ar_stats[i]=177
2446
+ # exit with usage error if videos are 16:9 and a slideshow is included
2447
+ if ((sshows >=1)); then
2448
+ usage_error \
2449
+ "Slides are encoded using 4:3 aspect ratio. You can not mix \
2450
+ 16:9 videos with a slideshow in the same titleset"
2451
+ fi
2452
else
2453
- yecho "No aspect ratio was determined. Videos in ths menu
2454
- (titleset) will be done using a ratio of 4:3"
2455
+ ar_stats[i]=133
2456
fi
2457
-done
2458
- yecho
2459
-fi
2460
-
2461
-# -user-thumbs is only compatible with static thumbs (-static)
2462
-if $USER_THUMBS && ! $STATIC; then
2463
- if $SWITCHED_MENUS; then
2464
- usage_error "If doing switched menus -user-thumbs can only be used
2465
- with a static menu (-static)"
2466
- else
2467
- usage_error "-user-thumbs option is for static buttons only (-static)"
2468
+ #if [[ -n $cur_aspect ]] && [[ ${ar_stats[i]} != $cur_aspect ]]; then
2469
+ # # if we have a value for cur_aspect and it differs from new value
2470
+ # if [[ ${ar_stats[i]} != $cur_aspect ]]; then
2471
+ # we may have this already if the value was 0, but no harm done
2472
+ # warn_files[i]=${FILES[i]}
2473
+ # fi
2474
+ #fi
2475
+ cur_aspect=${ar_stats[i]}
2476
+ # unset stat so we can test it again
2477
+ unset stat
2478
+ done
2479
+ # count the most frequent occurence in ar_stats of 133 or 177.
2480
+ # They should all be the same!, but user can still continue if he wants
2481
+ ws=$(grep 177 <<< "$(printf '%s\n' ${ar_stats[@]})" |wc -l)
2482
+ lb=$(grep 133 <<< "$(printf '%s\n' ${ar_stats[@]})" |wc -l)
2483
+ ((ws > lb)) && ar=177 || ar=133
2484
+ # set the global var for aspect ratio
2485
+ { [[ $ar = 177 ]] && ASPECT_RATIO=16:9; } || ASPECT_RATIO=4:3
2486
+
2487
+ # warn about files that have a differing aspect ratio
2488
+ for i in ${!ar_stats[@]}; do
2489
+ if ! grep -q $ar <<< ${ar_stats[i]}; then
2490
+ warn_files[i]=${FILES[i]}
2491
+ fi
2492
+ done
2493
+ if [[ -n ${warn_files[@]} ]]; then
2494
+ yecho
2495
+ printred "*** CRITICAL WARNING ***"
2496
+ yecho "The following files differ from the $ASPECT_RATIO aspect ratio
2497
+ we are using, even if they are to be re-encoded by makempg here."
2498
+ echo
2499
+ printf "\"%s\"\n" ${warn_files[@]}
2500
+ echo
2501
+ yecho "You can not mix different aspect ratios in the same menu.
2502
+ They need to be put in a separate titleset. You may want to quit
2503
+ at the preview and re-examine the situation."
2504
+ printred "*************"
2505
+ yecho
2506
+ yecho "Press <ENTER> to continue"
2507
+ read input
2508
fi
2509
+ print2log ""
2510
+ print2log "Videos in this titleset will be done using aspect of $ASPECT_RATIO."
2511
fi
2512
2513
################################################
2514
2515
# set some vars for the last run of switched menus (non-recursive )
2516
$SWITCHED_MENUS && SHOWCASE_FILE=${FILES[0]}
2517
2518
-yecho
2519
-yecho "Creating work directories"
2520
-yecho
2521
+print2log "Creating work directories"
2522
2523
# create an array of grouped files.
2524
if $GROUPING; then
2525
unset grp
2526
for ((i=1; i<=${#FILES[@]}; i++)); do
2527
- if [[ -n ${GROUP[i-1]} ]]; then
2528
- for ((j=1; j<=${GROUP[i-1]}; j++)); do
2529
+ if [[ -n ${GROUP_ARR[i-1]} ]]; then
2530
+ for ((j=1; j<=${GROUP_ARR[i-1]}; j++)); do
2531
if [[ -e $WORK_DIR/${TSET_NUM}-group-${i}-${j}.mpg ]]; then
2532
grouping[grp++]=$WORK_DIR/${TSET_NUM}-group-${i}-${j}.mpg
2533
fi
2534
2535
done
2536
fi
2537
2538
-# if no bg supplied, use template.png so we can add a frame (-quick-menu only)
2539
+## if no bg supplied, use template.png so we can add a frame (-quick-menu only)
2540
+# near-black background causes ffmpeg's movie/overlay filter to act weirdly
2541
+if [[ $BG_CLR = '#101010' || $BG_CLR = black ]] && [[ -z $BACKGROUND ]] && $QUICK_MENU; then
2542
+ SUB_CLRS+=("$BG_CLR:'#000030' ('black' bg for quick menu is problematic)")
2543
+ BG_CLR='#000030'
2544
+ #BG_CLR='#101028'
2545
+fi
2546
2547
# check that NTSC menu uses safe colours
2548
if [[ $TV_STANDARD = "ntsc" ]]; then
2549
get_safe_colour $SFRAME_CLR && FRAME_CLR=$SAFE_CLR
2550
get_safe_colour $TITLE_CLR && TITLE_CLR=$SAFE_CLR
2551
get_safe_colour $SM_TITLE_CLR && SM_TITLE_CLR=$SAFE_CLR
2552
- get_safe_colour $TITLE_STROKE && TITLE_STROKE=$SAFE_CLR
2553
+ get_safe_colour $M_TITLE_STROKE && M_TITLE_STROKE=$SAFE_CLR
2554
get_safe_colour $SUBMENU_STROKE && SUBMENU_STROKE=$SAFE_CLR
2555
get_safe_colour $CHAPTER_STROKE && CHAPTER_STROKE=$SAFE_CLR
2556
get_safe_colour $TITLES_CLR && TITLES_CLR=$SAFE_CLR
2557
get_safe_colour $HLIGHT_CLR && HLIGHT_CLR=$SAFE_CLR
2558
get_safe_colour $SELECT_CLR && SELECT_CLR=$SAFE_CLR
2559
get_safe_colour $BG_CLR && BG_CLR=$SAFE_CLR
2560
- get_safe_colour $TITLES_STROKE && TITLES_STROKE=$SAFE_CLR
2561
+ get_safe_colour $V_TITLES_STROKE && V_TITLES_STROKE=$SAFE_CLR
2562
get_safe_colour $SUBMENU_BG_CLR && SUBMENU_BG_CLR=$SAFE_CLR
2563
get_safe_colour $THUMB_FRAME_CLR && THUMB_FRAME_CLR=$SAFE_CLR
2564
echo
2565
if [[ -n ${SUB_CLRS[@]} ]]; then
2566
- echo "*** Note: ***"
2567
+ printgreen "*** Note: ***"
2568
echo "Some of the colors you passed in are not NTSC color safe. "
2569
echo "The following substitutions were made for you:"
2570
for i in ${!SUB_CLRS[@]}; do
2571
echo "${SUB_CLRS[i]/:*} ===> ${SUB_CLRS[i]/*:}"
2572
done
2573
- echo "*************"
2574
+ printgreen "*************"
2575
echo
2576
- $WARN && sleep 5
2577
+ $WARN && continue_in 5
2578
fi
2579
fi
2580
2581
2582
# check file type of background file and assign to BG_VIDEO or BG_IMAGE
2583
if [[ -n $BACKGROUND ]]; then
2584
check_filetype "$BACKGROUND"
2585
- if [[ $TYPE = "image" ]]; then
2586
+ if [[ $file_type = "image" ]]; then
2587
BG_PIC="$BACKGROUND"
2588
- elif [[ $TYPE = "video" ]]; then
2589
+ elif [[ $file_type = "video" ]]; then
2590
BG_VIDEO="$BACKGROUND"
2591
else
2592
usage_error "Sorry, can not identify "$BACKGROUND""
2593
2594
if [[ -n ${SM_BACKGROUND[@]} ]]; then
2595
for smbg in ${!SM_BACKGROUND[@]}; do
2596
check_filetype "${SM_BACKGROUND[smbg]}"
2597
- if [[ $TYPE != "image" ]]; then
2598
+ if [[ $file_type != "image" ]]; then
2599
usage_error "-submenu-background takes image files only"
2600
fi
2601
done
2602
2603
if $SHOWCASE; then
2604
if [[ -n ${SHOWCASE_FILE[@]} ]]; then
2605
check_filetype "${SHOWCASE_FILE[@]}"
2606
- if [[ $TYPE = "image" ]]; then
2607
+ if [[ $file_type = "image" ]]; then
2608
SHOWCASE_IMG=${SHOWCASE_FILE[@]}
2609
- elif [[ $TYPE = "video" ]]; then
2610
+ elif [[ $file_type = "video" ]]; then
2611
SHOWCASE_VIDEO=${SHOWCASE_FILE[@]}
2612
else
2613
usage_error "Can not identify showcase file: "${SHOWCASE_FILE[@]}""
2614
2615
fi
2616
# find out the aspect ratio of the showcase file
2617
if [[ -n $SHOWCASE_VIDEO ]]; then
2618
- SC_AR=$(idvid -fast -terse "$SHOWCASE_VIDEO" 2>/dev/null |
2619
+ SC_AR=$( idvid -fast -terse "$SHOWCASE_VIDEO" 2>> $LOG_FILE |
2620
awk -F= '/V_ASPECT_WIDTH/ {print $2}' 2>/dev/null)
2621
elif [[ -n $SHOWCASE_IMG && $SHOWCASE_IMG != "dummy" ]]; then
2622
SC_AR=$(identify -ping -format %wx%h "$SHOWCASE_IMG")
2623
- SC_AR=$(bc_math "${SC_AR/x*} / ${SC_AR/*x}" )
2624
+ SC_AR=$( bc_math "(${SC_AR/x*} / ${SC_AR/*x}) * 100" int )
2625
fi
2626
2627
# now the showcase image is id'ed, we can find out what kind of quick menu
2628
2629
if $QUICK_MENU && ! $QUICKMENU_IS_SHOWCASE && ! $QUICKMENU_IS_BACKGROUND; then
2630
if ! $SWITCHED; then
2631
yecho
2632
- yecho "***** WARNING *****"
2633
if { $DO_TITLESETS || $TITLESET_MODE ; }; then
2634
yech=yecho
2635
else
2636
2637
BUTTON_STYLE="rect"
2638
SHOWCASE=false
2639
fi
2640
- $WARN && sleep 10
2641
+ $WARN && continue_in 10
2642
fi
2643
fi
2644
$QUICKMENU_IS_BACKGROUND && SHOWCASE_IMG=""
2645
2646
# quick-menu needs TEXTMENU=: , and does its own showcase and bg with ffmpeg
2647
TEXTMENU=:
2648
SC_THUMB=false
2649
- STATIC=: #FIXME
2650
+ STATIC=:
2651
fi
2652
if [[ $SC_FRAMESTYLE = "glass" ]] && [[ -z $SHOWCASE_IMG && -z $SHOWCASE_VIDEO ]]; then
2653
yecho
2654
2655
if ! $VMGM_ONLY; then
2656
for i in "${FILES[@]}"; do
2657
IN_FILES=("${IN_FILES[@]}" "$(readlink -f "$i")")
2658
- (( ${#FILES[@]} < 12 )) && echo "Adding: $i" || spin "Adding: ${i##*/}"
2659
+ spin "Adding: ${i##*/}"
2660
done
2661
+ echo
2662
fi
2663
2664
$VMGM_ONLY && V_TOTAL=$(( ${#TITLES[@]} - 1 )) || V_TOTAL=${#IN_FILES[@]}
2665
2666
$DO_CAROUSEL && MONTAGE_MENU=false
2667
2668
# switch title position when appropriate so it doesn't get covered up
2669
-! $USER_TITLE_GEO && [[ $BUTTON_GRAVITY = *south* ]] && TITLE_GRAVITY="north"
2670
-if [[ $BUTTON_GRAVITY = *east* || $BUTTON_GRAVITY = *west* ]]; then
2671
- ! $USER_GEO && XGEO=45 && YGEO=45
2672
- ! $SHOWCASE && ! $USER_TITLE_GEO && TITLE_GRAVITY=north
2673
+! $USER_TITLE_GEO && [[ $BUTTON_GRAVITY = south* ]] && TITLE_GRAVITY="north"
2674
+# not sure why YGEO is 45, probably from when -align didn't affect montage
2675
+#if [[ $BUTTON_GRAVITY = *east || $BUTTON_GRAVITY = *west ]]; then
2676
+if ! $SHOWCASE; then # XGEO/YGEO for montage style only
2677
+ # montage adds spacing to edge of montage so subtract it. This is a
2678
+ # HACK, it would have been better to -trim +repage but I don't feel
2679
+ # like testing each of the myrid combos to make sure it works okay
2680
+ safe_area=$(( SAFE_AREA - 12 ))
2681
+ case $BUTTON_GRAVITY in
2682
+ northeast|southeast|northwest|southwest)
2683
+ if $USER_GRAVITY; then
2684
+ XGEO=$safe_area && YGEO=$safe_area
2685
+ else
2686
+ XGEO=45 && YGEO=45
2687
+ fi
2688
+ ;;
2689
+ east|west)
2690
+ # move to REAL center if -align centers the montage vertically
2691
+ YGEO=0 && XGEO=$SAFE_AREA
2692
+ ;;
2693
+ center)
2694
+ YGEO=0 && XGEO=0
2695
+ ;;
2696
+ esac
2697
+else # for showcase, move Y position to true north or south at safe area edge
2698
+ :
2699
+ #[[ $BUTTON_GRAVITY = north* ]] && TEXT_YSTART=$SAFE_AREA
2700
+ #[[ $BUTTON_GRAVITY = south* ]] && TEXT_YSTART=$(( ${VIDSIZE/*x} - SAFE_AREA))
2701
fi
2702
+
2703
! $SHOWCASE && \
2704
[[ $BUTTON_GRAVITY = "center" ]] && ! $USER_TITLE_GEO && TITLE_GRAVITY="north"
2705
2706
2707
#CHAPTERS=( ${CHAPTERS%%+*} ) # in case of grouped chapters
2708
# allow user to pass HH:MM:SS chapters
2709
$USER_CHAPTERS && CHAPT_ARRAY=( ${CHAPTERS[@]} )
2710
+if $USER_CHAPTERS; then
2711
+ C=( ${CHAPTERS[@]} )
2712
+ if ((${#C[@]} == 1)) && ((${#C[@]} != ${#FILES[@]})); then
2713
+ for i in ${!FILES[@]}; do
2714
+ CHAPT_ARRAY[i]=${C[0]}
2715
+ done
2716
+ else
2717
+ CHAPT_ARRAY=( ${CHAPTERS[@]} )
2718
+ fi
2719
+fi
2720
+
2721
+
2722
# if arbitrary grouped chapters passed, make an array of them
2723
if $GROUPING && $USER_CHAPTERS; then
2724
for i in ${!IN_FILES[@]}; do
2725
- if [[ -n ${GROUP[i]} ]]; then
2726
+ if [[ -n ${GROUP_ARR[i]} ]]; then
2727
group_arbitrary_chapters[i]=${grouped_user_chapters[i]//+/ }
2728
else
2729
group_arbitrary_chapters[i]=""
2730
2731
# get normal CHAPTERS VAR,i.e.: 'how many chapters'
2732
# Check if 1st is 00:00:00 and all chapters have HH:MM:SS format
2733
if $USER_CHAPTERS; then
2734
+ if [[ ${#FILES[@]} -ne ${#CHAPTERS[@]} ]]; then
2735
+ usage_error "Please give the same number of chapter point strings as
2736
+ videos when using HH:MM:SS form chapters. You gave ${#FILES[@]}
2737
+ videos but only ${#CHAPTERS[@]} chapter point strings."
2738
+ fi
2739
for i in ${!CHAPT_ARRAY[@]}; do
2740
unset newchapts
2741
[[ ${CHAPTERS[i]} != *:* ]] && usage_error \
2742
2743
for ((i=0; i<${#CHAPTERS[@]}; i++)); do
2744
if ((${CHAPTERS[i]} == 0)) && ! ${SLIDESHOW[i]}; then
2745
if ! $USER_CHAPTERS; then
2746
- [[ -z ${GROUP[i]} ]] && usage_error \
2747
+ [[ -z ${GROUP_ARR[i]} ]] && usage_error \
2748
"-chapters 0 is only for grouped videos (each video is a chapter)"
2749
- CHAPTERS[i]=$(( ${GROUP[i]} + 1 )) && nochapt[i]=1
2750
+ CHAPTERS[i]=$(( ${GROUP_ARR[i]} + 1 )) && nochapt[i]=1
2751
fi
2752
fi
2753
done
2754
-echo
2755
2756
# if using chapter titles, they must equal the combined total for all files
2757
if [[ -n ${CHAPTER_TITLES[@]} ]]; then
2758
2759
fi
2760
fi
2761
2762
+# allow using todisc for just encoding mpegs, then exiting
2763
+if $ENCODE_ONLY; then
2764
+ check_compliance
2765
+ if (( ${#FILES_TO_ENCODE[@]} > 1 )); then
2766
+ for f in "${FILES_TO_ENCODE[@]}"; do
2767
+ [[ -s "$f" ]] && arr+=("${f}.enc.mpg")
2768
+ done
2769
+ #((${#arr[@]} > 0)) && printf "%s\n%s.enc.mpg" \
2770
+ if ((${#arr[@]} > 0)); then
2771
+ printf "\n%s\n" "Here are your encoded files:"
2772
+ printgreen '-------------'
2773
+ printf "%s\n" "${arr[@]}"
2774
+ printgreen '-------------'
2775
+ fi
2776
+ fi
2777
+ cleanup
2778
+ exit 0
2779
+fi
2780
# a quick way to allow user to make a dvd with no menus
2781
if $NOMENU; then
2782
cd "$WORK_DIR"
2783
2784
for i in "${!IN_FILES[@]}"; do
2785
ln -s "${IN_FILES[i]}" "$WORK_DIR/$(printf %03d%s%s $i .mpg)"
2786
idvid_stats[i]=$(idvid -terse "${IN_FILES[i]}" 2>/dev/null)
2787
- # run mencoder to get the length if using arbitrary chapters
2788
+ # run stream_length to get the length if using arbitrary chapters
2789
if $USER_CHAPTERS; then
2790
chapter_points[i]=${CHAPT_ARRAY[i]}
2791
else
2792
2793
: # we don't need file length or chapters if not making chapters
2794
else
2795
yecho "Getting video lengths"
2796
- VID_LEN[i]=$(vid_length "${IN_FILES[i]}" )
2797
+ VID_LEN[i]=$(stream_length "${IN_FILES[i]}" )
2798
chapter_points[i]=$(make_chapters ${VID_LEN[i]} ${CHAPTERS[i]} )
2799
fi
2800
fi
2801
2802
fi
2803
nomenu_cmd+=("${IN_FILES[i]}")
2804
done
2805
- yecho
2806
- echo Running: "${nomenu_cmd[@]}" -o "$OUT_DIR" | format_output
2807
- yecho
2808
- "${nomenu_cmd[@]}" -o "$OUT_DIR" | tee -a "$LOG_FILE" 2>&1
2809
- dvdauthor -o "$OUT_DIR" -T
2810
+ print2log "Running: ${nomenu_cmd[@]} -o $OUT_DIR"
2811
+ "${nomenu_cmd[@]}" -o "$OUT_DIR" 2>&1| pipe2log
2812
+ dvdauthor -o "$OUT_DIR" -T 2>&1 |pipe2log
2813
thanks_goodbye
2814
$BURN && burn_disc
2815
cleanup
2816
2817
if $USER_THUMBS && $FRAME_SAFE; then
2818
FRAME_SAFE=false
2819
echo "-frame-safe and -user-thumbs incompatible, disabling -frame-safe"
2820
- sleep 5
2821
+ $WARN && continue_in 5
2822
fi
2823
2824
-yecho "Creating pics directories..."
2825
+print2log "Creating pics directories..."
2826
for ((i=0; i<=NUM_FILES; i++)); do
2827
mkdir -p "$REAL_WORK_DIR/pics/$i"
2828
done
2829
-yecho "${#FILES[@]} pics directories created"
2830
+print2log "${#FILES[@]} pics directories created"
2831
# textmenu is static unless there is an animated background or showcase video
2832
if $TEXTMENU && [[ -z $SHOWCASE_VIDEO && -z $BG_VIDEO ]]; then STATIC=:; fi
2833
2834
2835
${#ROTATE_ARRAY[@]} thumb rotate values."
2836
fi
2837
fi
2838
-# if -wave passed, usage error if -showcase-shape also passed
2839
-#if [[ -n $WAVE && -n $SHOWCASE_SHAPE ]]; then
2840
-# usage_error "You can not use both -wave and a -showcase-shape"
2841
-#fi
2842
2843
# if Fading menu, and no BG IMAGE OR VIDEO, fade thumbs right in after title
2844
if $MENU_FADE; then
2845
2846
alength=$(bc_math "4 / $FRAME_RATE") # 0.16 or 0.133
2847
# float < 1 must begin with 0
2848
[[ -n ${alength/*.} && -z ${alength/.*} ]] && alength=0${alength}
2849
- echo
2850
echo "Verifying that input files are video or image files"
2851
verify_infiles infiles
2852
if [[ ${#file_is_image[@]} -eq ${#FILES[@]} && $inc_files -gt 0 ]]; then
2853
2854
echo
2855
echo "Verifying that grouped input files are video or image files"
2856
verify_infiles group
2857
- echo
2858
fi
2859
- echo
2860
fi
2861
-echo
2862
# some vars for slide mix
2863
# this is only called when todisc running recursively to make ani slideshows
2864
# DO_CAROUSEL is set to false when the self recursion is complete
2865
# this happens earlier in the script.
2866
if $DO_CAROUSEL; then
2867
- if [[ -n ${GROUP[@]} ]] && ! $MK_CAROUSEL_MODE; then
2868
+ if [[ -n ${GROUP_ARR[@]} ]] && ! $MK_CAROUSEL_MODE; then
2869
#*slide_grp*.mpg are symlinks to the original images we have kept intact
2870
mixgroup=( "$WORK_DIR"/${TSET_NUM}-slide_grp-*.mpg )
2871
for g in ${!mixgroup[@]}; do
2872
2873
fi
2874
# All files must be images for slide mix.
2875
# if all are images, then we are doing a slideshow.
2876
-echo
2877
if $SINGLE_SLIDESHOW; then
2878
# if -static was not passed we have already set DO_CAROUSEL to :
2879
# So here we set STATIC to : as ani slideshow has its own code
2880
2881
if [[ ${file_is_image[i]} = "yes" ]]; then
2882
SHORTFILE=:
2883
else
2884
- FRAME_CK=$(vid_length "${IN_FILES[i]}" 90)
2885
+ FRAME_CK=$(stream_length "${IN_FILES[i]}" video 90)
2886
[[ $(bc -l <<< "$FRAME_CK < 2") -eq 1 ]] && SHORTFILE=:
2887
fi
2888
if $SHORTFILE; then
2889
2890
2891
# Some user feedback
2892
if ! $SINGLE_SLIDESHOW; then
2893
- yecho
2894
+ #yecho ""
2895
+ yecho ""
2896
+ printgreen "-------------"
2897
if $VMGM_ONLY; then
2898
yecho "Disc title: \"$MENU_TITLE\""
2899
else
2900
2901
else # echo titles "as is"
2902
echo " \"${TITLES[i]}\" (${IN_FILES[i]})"
2903
fi
2904
+ # FIXME move this before the aspect ratio check for IN_FILES if possible
2905
if [[ $(echo -e "${TITLES[i]}" |wc -l) -gt 1 ]]; then
2906
# if there is a multiline title we need to align to right of thumbs
2907
- SC_TITLE_ALIGN=east
2908
+ $SHOWCASE && ! [[ $SC_TITLE_ALIGN = "east" ]] && \
2909
+ align_warning="\"${TITLE[i]}\" is more than one line: \
2910
+ - setting '-showcase-titles-align east'"
2911
ALIGN_OVERRIDE=:
2912
+ if [[ ! $SC_TITLE_ALIGN = east ]]; then
2913
+ WARN_RE_ALIGN_EAST=1
2914
+ fi
2915
fi
2916
done
2917
yecho "Current font settings: "
2918
2919
if [ ! $STATIC ]; then
2920
yecho " -menu-audio-fade $FADE second(s)"
2921
fi
2922
- yecho
2923
+ #yecho ""
2924
+ printgreen "-------------"
2925
+ yecho ""
2926
fi
2927
fi
2928
+ if ((WARN_RE_ALIGN_EAST)); then
2929
+ #info_message "Multiline titles must be aligned east. \
2930
+ #Setting \"-align east\" for you"
2931
+ info_message "$align_warning"
2932
+ SC_TITLE_ALIGN=east
2933
+ $WARN && continue_in 3
2934
+ fi
2935
fi
2936
# TODO: Merge these globals with the ones up top
2937
# only the 1st 6 are mergable - keeping them here for debugging this beast :)
2938
# 9 /row
2939
-NTSC_1333_DVD=(420x280 300x200 192x128 192x128 186x124 186x124 132x88 132x88 \
2940
+NTSC_1333_DVD=(420x280 288x192 192x128 192x128 186x124 186x124 132x88 132x88 \
2941
132x88 120x80 120x80 120x80 96x64 96x64 96x64 96x64 96x64 96x64 \
2942
96x64 96x64 84x56 84x56 84x56 84x56 84x56 84x56 84x56 \
2943
84x56 84x56 84x56 60x40 60x40 60x40 60x40 60x40 60x40 \
2944
60x40 60x40 60x40 60x40 60x40 60x40 60x40 60x40 60x40
2945
60x40 60x40 60x40 60x40)
2946
# *_1777_DVD is for 16:9 videos displayed in proper res on a 4:3 menu
2947
-NTSC_1777_DVD=(420x210 300x150 240x120 240x120 186x98 186x98 180x90 180x90 \
2948
+NTSC_1777_DVD=(420x210 288x144 240x120 240x120 186x98 186x98 180x90 180x90 \
2949
180x90 132x66 132x66 132x66 132x66 132x66 132x66 132x66 100x50 100x50 \
2950
100x50 100x50 100x50 100x50 100x50 100x50 100x50 88x44 88x44 \
2951
88x44 88x44 88x44 80x40 80x40 80x40 80x40 80x40 80x40)
2952
-PAL_1333_DVD=(420x336 300x240 190x152 190x152 190x152 190x152 130x104 130x104 \
2953
+PAL_1333_DVD=(420x336 280x224 190x152 190x152 190x152 190x152 130x104 130x104 \
2954
130x104 130x104 130x104 130x104 100x80 100x80 100x80 100x80 100x80 100x80 \
2955
100x80 100x80 90x72 90x72 90x72 90x72 90x72 90x72 90x72 \
2956
90x72 90x72 90x72 60x48 60x48 60x48 60x48 60x48 60x48)
2957
-PAL_1777_DVD=(420x252 300x180 240x144 240x144 190x114 190x114 190x114 190x114 \
2958
+PAL_1777_DVD=(420x252 280x168 240x144 240x144 190x114 190x114 190x114 190x114 \
2959
190x114 130x78 130x78 130x78 130x78 130x78 130x78 130x78 100x60 100x60
2960
100x60 100x60 100x60 100x60 100x60 100x60 100x60 90x54 90x54 90x54 90x54 90x54
2961
80x48 80x48 80x48 80x48 80x48 80x48)
2962
2963
SC_THUMB_X_ARRAY=( ${SC_THUMB_X_ARRAY[NUM_FILES]} )
2964
SC_THUMB_Y_ARRAY=( ${SC_THUMB_Y_ARRAY[NUM_FILES]} )
2965
SC_TITLES_X_ARRAY=( ${SC_THUMB_X_ARRAY[@]} )
2966
-SC_TITLES_Y_ARRAY=( ${SC_TITLES_Y_ARRAY[NUM_FILES]} )
2967
+SC_TITLES_Y_ARRAY=( ${SC_TITLES_Y_ARRAY[NUM_FILES]} ) # not used by textmenu
2968
if $TEXTMENU ; then
2969
+ # next line useless as it will always be overwritten for large # of titles
2970
! $USER_SPLIT && SPLIT=13 # max text only titles in one column (-textmenu)
2971
if [[ $NUM_FILES -gt 12 ]] && ! $USER_SPLIT; then
2972
SPLIT=$((V_TOTAL / 2))
2973
- [[ $(( SPLIT * 2)) -ne $V_TOTAL ]] && let SPLIT=SPLIT+1
2974
+ (( (SPLIT * 2) != V_TOTAL)) && ((SPLIT++))
2975
fi
2976
-#for ((b=0; b<=NUM_FILES; b++)); do
2977
-#((b < SPLIT)) && SC_TITLES_X_ARRAY[b]=86||SC_TITLES_X_ARRAY[b]=360
2978
-#done
2979
fi
2980
-# needed to centre showcase img: col 1 will always be larger value than col 2
2981
+
2982
if $SHOWCASE && ! $TEXTMENU; then
2983
- ((NUM_FILES < 5)) && SPLIT=$((NUM_FILES+1))
2984
+ # TODO? allow user to specify the SPLIT?
2985
+ ((NUM_FILES < 5)) && SPLIT=$((NUM_FILES+1)) # col 1 always >= col 2
2986
((NUM_FILES == 5)) && SPLIT=3
2987
((NUM_FILES >= 6)) && SPLIT=4
2988
((NUM_FILES >= 8)) && SPLIT=5
2989
+ # -align *east or *west disallowed for 2 column showcase thumbs
2990
+ if ((NUM_FILES >= SPLIT)); then
2991
+ case $BUTTON_GRAVITY in
2992
+ *east|*west)
2993
+ butgrav=$BUTTON_GRAVITY
2994
+ # northeast or northwest
2995
+ if [[ $BUTTON_GRAVITY = north* ]]; then
2996
+ BUTTON_GRAVITY=north && USER_GRAVITY=false
2997
+ # southeast or southwest
2998
+ elif [[ $BUTTON_GRAVITY = south* ]]; then
2999
+ BUTTON_GRAVITY=south && USER_GRAVITY=false
3000
+ else # east or west
3001
+ BUTTON_GRAVITY=north
3002
+ fi
3003
+ info_message "You can not use \"-align $butgrav\" with 2 \
3004
+ column -showcase, only \"north\", \"south\", \"center\". \
3005
+ Changing to \"-align ${BUTTON_GRAVITY}\", please check preview."
3006
+ $WARN && continue_in 10
3007
+ ;;
3008
+ esac
3009
+ # central alignment disallowed for 1 column showcase
3010
+ else
3011
+ if [[ $SHOWCASE_FILE ]]; then
3012
+ case $BUTTON_GRAVITY in
3013
+ center|north|south)
3014
+ [[ $BUTTON_GRAVITY = center ]] && but_grav="" || \
3015
+ but_grav=$BUTTON_GRAVITY
3016
+ info_message "You can not use a central -align option as in \
3017
+ 'north', 'center', or 'south' when using a showcase image and \
3018
+ a single column of titles.
3019
+ Setting '-align ${but_grav}west' for you, please check it with the preview."
3020
+ BUTTON_GRAVITY=${but_grav}west && USER_GRAVITY=false
3021
+ $WARN && continue_in 5
3022
+ ;;
3023
+ *east)
3024
+ #BUTTON_GRAVITY="northwest"
3025
+ bgrav=$BUTTON_GRAVITY
3026
+ BUTTON_GRAVITY=${BUTTON_GRAVITY/east/west} # could be west/nw/sw
3027
+ info_message "You can not use -align $bgrav when using a showcase image. \
3028
+ Setting -align $BUTTON_GRAVITY"
3029
+ $WARN && continue_in 3
3030
+ esac
3031
+ fi
3032
+ fi
3033
fi
3034
3035
3036
-AUDIO_EXT="ac3"
3037
-SAMPLERATE="48000"
3038
-MPLEX_FORMAT="8"
3039
-FFMPEG_OPTS="-b 7000k -maxrate 8000k -bufsize 224KiB $ASPECT"
3040
-SS_FFMOPTS="-b 8000k -maxrate 9000k -bufsize 224KiB $SS_ASPECT"
3041
+FFMPEG_OPTS="-b 7000k -maxrate 8000k -bufsize 224KiB"
3042
+SS_FFMOPTS="-b 8000k -maxrate 9000k -bufsize 224KiB"
3043
SHOWCASE_SIZE=384x256
3044
-BURN_TGT="$OUT_DIR"
3045
-BURN_TGT_STR="DVD directory"
3046
-BURN_PROG="makedvd"
3047
if [ $TV_STANDARD = "ntsc" ]; then
3048
if [[ $ASPECT_RATIO = "4:3" ]]; then
3049
GEO_ARRAY=("${NTSC_1333_DVD[@]}")
3050
3051
fi
3052
VIDSIZE="720x480"
3053
FRAME_RATE=29.970
3054
+ ff_frame_rate="30000/1001"
3055
if [[ $SC_AR = 133 ]]; then
3056
SHOWCASE_SIZE=384x256
3057
SM_SHOWCASE_SIZE=288x192
3058
3059
VIDSIZE="720x576"
3060
TILE_ARRAY=("${TILE_1333[@]}")
3061
FRAME_RATE=25
3062
+ ff_frame_rate="25/1"
3063
if [[ $SC_AR = 133 ]]; then
3064
SHOWCASE_SIZE=380x304
3065
SM_SHOWCASE_SIZE=290x232
3066
3067
GEO_ARRAY=("${PAL_1777_DVD[@]}")
3068
fi
3069
fi
3070
+# set a variable for vfilter scaling based on above sizes VFSCALE
3071
+VF_SCALE=${VIDSIZE%x*}:${VIDSIZE#*x}
3072
if [[ $TV_STANDARD = "ntsc" ]]; then
3073
YUV_FR=30000:1001
3074
else
3075
3076
yecho
3077
yecho "Reducing thumb blur to 2.0 because you are using -showcase"
3078
yecho
3079
- $WARN && sleep 3
3080
+ $WARN && continue_in 3
3081
fi
3082
fi
3083
if [ $V_TOTAL -lt 3 ]; then
3084
3085
SEEK_FRAMES[i]=$(bc_math "${SEEK_VAL[i]} * $FRAME_RATE" int)
3086
done
3087
3088
-# some choices needed for different title alignments
3089
+# some choices needed for different -align -showcase-titles and alignments
3090
if $SHOWCASE && ! $TEXTMENU; then
3091
- if [ $V_TOTAL -le 5 ]; then
3092
- if [[ $SC_TITLE_ALIGN = "east" ]]; then
3093
- SHOWCASE_SIZE=$SM_SHOWCASE_SIZE # smaller to allow for titles
3094
- fi
3095
+ JUSTIFY="west"
3096
+
3097
+ if ((V_TOTAL <= 5)); then
3098
+ # FIXME move this before the aspect ratio check for IN_FILES if possible
3099
+ # smaller to allow for titles
3100
AUTOORDER="rows" # spumux var
3101
+ [[ $SC_TITLE_ALIGN = "east" ]] && SHOWCASE_SIZE=$SM_SHOWCASE_SIZE
3102
+ case $BUTTON_GRAVITY in
3103
+ south|north|center)
3104
+ SC_TITLE_ALIGN="center" # moves titles to left a bit for room
3105
+ SHOWCASE_SIZE=$SM_SHOWCASE_SIZE
3106
+ ;;
3107
+ esac
3108
else
3109
SHOWCASE_SIZE=$SM_SHOWCASE_SIZE # smaller showcase thumb because we have 2 rows
3110
AUTOORDER="columns"
3111
- if $SC_THUMB && \
3112
- [[ "$SC_TITLE_ALIGN" = "east" ]] && [[ -n $SHOWCASE_FILE ]]; then
3113
- usage_error "Sorry, there is no room for the showcase thumb " \
3114
- "if you use more than 5 videos with -showcase-titles-align " \
3115
- "east|west (also multiline titles). Either change the problem " \
3116
- "option, remove the showcase image/video, or use -textmenu. Or " \
3117
- "consider using -bgimage or -bgvideo instead of a showcase thumb."
3118
+ if [[ $SHOWCASE_FILE ]] && \
3119
+ [[ "$SC_TITLE_ALIGN" = "east" ]]; then
3120
+ info_message "Sorry, no room for showcase thumb with 2 columns and \
3121
+ \"-showcase-titles-align east\" (or multiline titles). Change the \
3122
+ option, remove the showcase image/video, or use -textmenu. Or \
3123
+ use -bgimage or -bgvideo instead of a thumb. Changed for you to: \
3124
+ \"-showcase-titles-align center\". Continuing on to the preview ..."
3125
+ SC_TITLE_ALIGN=center
3126
+ $WARN && continue_in 15
3127
fi
3128
fi
3129
elif ! $SHOWCASE && ! $TEXTMENU; then
3130
3131
fi
3132
$SINGLE_SLIDESHOW && ! $MK_CAROUSEL_MODE && CAROUSEL_SIZE=$VIDSIZE
3133
3134
-$TEXTMENU && LEFT_MAX=$SPLIT || LEFT_MAX=5
3135
-if [ "$SC_TITLE_ALIGN" = "west" ] || $TEXTMENU; then #FIXME
3136
- THUMB_TITLE_ALIGN="west" # for non TEXTMENU menu
3137
- for ((i=0; i<=NUM_FILES; i++)); do
3138
- if [ $i -lt $LEFT_MAX ]; then
3139
- SC_THUMB_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - \
3140
- SAFE_OFFSET ))
3141
- SC_TITLES_X_ARRAY[i]=$(( ${SC_TITLES_X_ARRAY[i]} - \
3142
- SAFE_OFFSET ))
3143
- fi
3144
- if ! $TEXTMENU && ! [[ $SHOWCASE_FILE ]]; then
3145
- if (( ${SC_THUMB_X_ARRAY[i]} > ( ${VIDSIZE/x*} / 2 ) )); then
3146
- SC_THUMB_X_ARRAY[i]=$(( ${VIDSIZE/x*} / 2 ))
3147
- SC_TITLES_X_ARRAY[i]=$(( ${VIDSIZE/x*} / 2 ))
3148
- fi
3149
- fi
3150
- done
3151
-fi
3152
-# centre aligned titles are not for textmenu style
3153
-if $TEXTMENU && [[ $SC_TITLE_ALIGN = "center" ]]; then
3154
- yecho
3155
- yecho "Sorry, you can not use center align for textmenu titles"
3156
- yecho "Using title alignment of 'west': please check the preview"
3157
- yecho
3158
- SC_TITLE_ALIGN="west"
3159
- $WARN && sleep 10
3160
-fi
3161
+# textmenu does not use -showcase-titles-align, unset this to aid block parsing
3162
+$TEXTMENU && unset SC_TITLE_ALIGN
3163
# -align east uses text-rect
3164
if [[ $BUTTON_STYLE = "text-rect" ]] \
3165
&& ! [[ $SC_TITLE_ALIGN = "east" ]] && $SHOWCASE && ! $TEXTMENU; then
3166
- yecho "***Warning***"
3167
- yecho "text-rect buttons need to be aligned east of thumbs: by using:"
3168
- yecho " '-showcase-titles-align east'"
3169
- yecho "Setting this option for you"
3170
- yecho "Ctrl-c now to exit if you wish to reconsider"
3171
+ info_message "text-rect buttons need to be aligned east of thumbs by using:
3172
+ '-showcase-titles-align east'. Setting this option for you.
3173
+ Ctrl-c now to exit if you wish to reconsider"
3174
SC_TITLE_ALIGN="east"
3175
- yecho
3176
- $WARN && sleep 10
3177
-fi
3178
-if $SHOWCASE && [ "$SC_TITLE_ALIGN" = "east" ] && ! $TEXTMENU; then
3179
- THUMB_TITLE_ALIGN="west" # align titles left to allow longer titles
3180
- for ((i=0; i<=NUM_FILES; i++)); do
3181
- if [ $i -lt $LEFT_MAX ] && ! $ALIGN_OVERRIDE; then
3182
- SC_THUMB_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - \
3183
- SAFE_OFFSET ))
3184
- SC_TITLES_X_ARRAY[i]=$(( ${SC_TITLES_X_ARRAY[i]} - \
3185
- SAFE_OFFSET ))
3186
- fi
3187
- if [ ${SC_THUMB_X_ARRAY[i]} -gt 360 ]; then
3188
- SC_THUMB_X_ARRAY[i]=360
3189
- fi
3190
- SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} + \
3191
- ${THUMB_SIZE/x*} + 5 ))
3192
- #SC_TITLES_Y_ARRAY[i]=$(( ${SC_TITLES_Y_ARRAY[i]} + 18 ))
3193
- SC_TITLES_Y_ARRAY[i]=${SC_THUMB_Y_ARRAY[i]} # DEBUG:why not originally?
3194
- done
3195
+ $WARN && continue_in 10
3196
fi
3197
-if { $USER_GRAVITY && $SHOWCASE && ! $TEXTMENU ; } \
3198
- && [[ $BUTTON_GRAVITY != north ]]; then
3199
- SW_CORNER=$(( ${SC_THUMB_Y_ARRAY[SPLIT-1]} + ${THUMB_SIZE/*x} ))
3200
- if [[ $BUTTON_GRAVITY = *south* ]]; then
3201
- Y_OFFSET=$(( ( ${VIDSIZE/*x} - SAFE_AREA) - SW_CORNER ))
3202
- elif [[ $BUTTON_GRAVITY = *st* ]] || [[ $BUTTON_GRAVITY = *center* ]]; then
3203
- COL1_HEIGHT=$(( SW_CORNER - ${SC_TITLES_Y_ARRAY[0]} ))
3204
- Y_OFFSET=$(( ( ${VIDSIZE/*x} / 2) - (COL1_HEIGHT / 2) ))
3205
- Y_OFFSET=$(( Y_OFFSET - ${SC_TITLES_Y_ARRAY[0]} ))
3206
- fi
3207
- for ((i=0; i<=NUM_FILES; i++)); do
3208
- SC_THUMB_Y_ARRAY[i]=$((${SC_THUMB_Y_ARRAY[i]} + Y_OFFSET ))
3209
- SC_TITLES_Y_ARRAY[i]=$((${SC_TITLES_Y_ARRAY[i]}+ Y_OFFSET))
3210
- done
3211
-fi
3212
-# default for showcase style is left justification, for montages: center
3213
-$SHOWCASE && JUSTIFY="west" || JUSTIFY="center"
3214
-# find out the showcase thumb "-page" array for this arrangement
3215
-for ((i=0; i<=NUM_FILES; i++)); do
3216
- if $TEXTMENU; then
3217
- SCTHUMB_PAGES_ARRAY[i]=+${SC_TITLES_Y_ARRAY[i]}+${SC_TITLES_X_ARRAY[i]}
3218
- else
3219
- SCTHUMB_PAGES_ARRAY[i]=+${SC_THUMB_X_ARRAY[i]}+${SC_THUMB_Y_ARRAY[i]}
3220
- fi
3221
-done
3222
3223
# Do everything in $WORK_DIR
3224
-echo -e "**** NOTE ****\n"
3225
-echo "Doing all work in directory $REAL_WORK_DIR"
3226
-echo "$WORK_DIR will be a symlink pointing to this directory"
3227
-echo -e "\n**************"
3228
+yecho "Changing to ${REAL_WORK_DIR} - $WORK_DIR will be the symlink."
3229
+yecho ""
3230
$WARN && sleep 1
3231
cd "$WORK_DIR"
3232
3233
3234
# no 3d thumbs for flare shape
3235
if $THUMBS_3D || $SHOWCASE_3D && \
3236
[[ $THUMB_SHAPE == "flare" || $SHOWCASE_SHAPE == "flare" ]]; then
3237
- warning_message "There is no 3d thumbs available for the 'flare' shape. "
3238
+ info_message "There is no 3d thumbs available for the 'flare' shape. "
3239
"Disabling this option for you"
3240
- $WARN && sleep 3
3241
+ $WARN && continue_in 3
3242
fi
3243
3244
$FOURxONE && $SHOWCASE && FOURxONE=false && tile_warning
3245
3246
THUMB_SIZE=${GEO_ARRAY[6]}
3247
fi
3248
else
3249
- warning_message "Warning: Incorrect number of videos for ${tile_arg}:
3250
+ info_message "Warning: Incorrect number of videos for ${tile_arg}:
3251
this option will be ignored"
3252
- $WARN && sleep 3
3253
+ $WARN && continue_in 3
3254
fi
3255
fi
3256
-if ( ($DO_TITLESETS || $TITLESET_MODE) && $VMGM_MENU ) || $PLAYALL; then
3257
- if [[ $BUTTON_GRAVITY = "south" ]]; then
3258
- BUTTON_GRAVITY="center"
3259
- yecho "Changing thumb alignment to 'center' \
3260
- to make room for navigation button"
3261
+# south* aligned with nav buttons may be a problem, unless aligned southwest
3262
+if { $DO_TITLESETS || $TITLESET_MODE; } && $VMGM_MENU || $PLAYALL; then
3263
+ bydir=${BUTTON_GRAVITY/south}
3264
+ if [[ $BUTTON_GRAVITY = south* && $bydir != west ]]; then
3265
+ if $TEXTMENU; then
3266
+ # textmenu will cover the nav button if southeast aligned
3267
+ # (center and southwest should be okay).Move to "east" (higher up).
3268
+ if [[ $bydir = east ]]; then
3269
+ BUTTON_GRAVITY=east
3270
+ info_message "Changing -align option to 'east' to make room \
3271
+ for navigation button(s) like playall '>'."
3272
+ $WARN && continue_in 5
3273
+ fi
3274
+ else
3275
+ info_message "You are using -align ${BUTTON_GRAVITY}, but need \
3276
+ room for navigation buttons like playall '>'. Please \
3277
+ check the preview and adjust your commands if necessary."
3278
+ $WARN && continue_in 7
3279
+ fi
3280
fi
3281
fi
3282
3283
3284
fi
3285
# easier to have non transparent showcase use the transparent block
3286
if $SHOWCASE && ! $TRANSPARENT; then TRANSPARENT=:; fi
3287
-AUDIO_OPTS="-ab 224k -ar $SAMPLERATE -acodec $AUDIO_EXT"
3288
# spumux and dvdauthor vars
3289
TITLES_VID_TAG="<video format=\"$TV_STANDARD\""
3290
$WIDE_SCREEN && TITLES_VID_TAG=" $TITLES_VID_TAG widescreen=\"$WIDESCREEN\""
3291
3292
# FFMPEG_OPTS="-b 7000k -maxrate 8000k -bufsize 224KiB -aspect 4:3"
3293
#MENU_N=$(bc_math "$FRAME_RATE * ${MENU_LEN[MENU_NUM-1]}" int)
3294
#ffmpeg -f image2 -loop_input -t $MENU_LEN -i "$WORK_DIR/image_stack.png" \
3295
- #-an -r $FRAME_RATE -s $VIDSIZE -tvstd $TV_STANDARD $FFMPEG_OPTS \
3296
+ #-an -r $ff_frame_rate -s $VIDSIZE $FFMPEG_OPTS \
3297
#-f mpeg2video -y "$WORK_DIR/intro.m2v"
3298
fi
3299
# values to use for the blur mask
3300
3301
convert "$WORK_DIR/feather_orig.png" -channel RGBA \
3302
-blur 0x60 "$WORK_DIR/feather_mask2.png"
3303
fi
3304
-if [[ -z "$TITLES_CLR" ]]; then
3305
- if $USE_FEATHER_MASK && ! $SHOWCASE &&
3306
- [[ $THUMB_BG_CLR != "none" && $THUMB_SHAPE != "normal" ]] ; then
3307
- TITLES_CLR="#101010" # dark font for misted backgrounds
3308
- else
3309
- TITLES_CLR="#C6C6C6"
3310
- fi
3311
-fi
3312
+[[ -z "$TITLES_CLR" ]] && TITLES_CLR='#EAEAEA'
3313
# set submenu font colours to defaults if not passed in
3314
[[ -z $CHAPTER_STROKE ]] && CHAPTER_STROKE="$SUBMENU_STROKE"
3315
[[ -z $CHAPTER_CLR ]] && CHAPTER_CLR="$TITLES_CLR"
3316
3317
-# Print and execute the thumb-shape mask command
3318
if $DO_MENU; then
3319
+ # make thumb-shape mask - showcase mask made later after its size is set
3320
if [[ -n $THUMB_SHAPE ]]; then
3321
make_mask $THUMB_SHAPE thumb
3322
THUMB_MASK="$MASK"
3323
fi
3324
- if [[ -n $SHOWCASE_SHAPE ]]; then
3325
- MASK="$WORK_DIR/${SHOWCASE_SHAPE}_mask.png"
3326
- make_mask $SHOWCASE_SHAPE showcase
3327
- convert "$MASK" -resize ${SHOWCASE_SIZE}! "$MASK"
3328
- SHOWCASE_MASK="$MASK"
3329
- fi
3330
- yecho "Creating a menu title image"
3331
- echo
3332
- if [[ -z $TITLE_STROKE ]]; then
3333
- if [[ -z "$BG_PIC" && -z "$BG_VIDEO" ]]; then
3334
- TITLE_STROKE=none
3335
- else
3336
- TITLE_STROKE=gray
3337
- fi
3338
+
3339
+ # make a menu title image
3340
+ print2log "Creating a menu title image"
3341
+ if $USE_M_TITLE_DECO; then
3342
+ # using -title-stroke does a plain 'makemenu' style font with no shadow
3343
+ # but using font outline like makemenu does
3344
+ M_TITLE_CMD=(convert -size 620x100 xc:none -font "$MENU_FONT" \
3345
+ -pointsize $MENU_FONTSIZE -fill "$TITLE_CLR" -gravity center \
3346
+ "${M_TITLE_FONT_DECO[@]}" -annotate +0+0 "$MENU_TITLE")
3347
+ #-stroke none -annotate +0+0 "$MENU_TITLE")
3348
+ else
3349
+ # with no -title-stroke passed, make a font shadow for contrast
3350
+ # but no font outline (it will be a shadow on one side only
3351
+ M_TITLE_STROKE=${M_TITLE_STROKE:-black}
3352
+ M_TITLE_CMD=(convert -size 620x300 xc:none -gravity \
3353
+ $JUSTIFY -font "$MENU_FONT" -pointsize $MENU_FONTSIZE \
3354
+ -fill none -stroke "$M_TITLE_STROKE" -strokewidth 1 \
3355
+ -annotate +0+0 "$MENU_TITLE" \
3356
+ -fill $TITLE_CLR -stroke none \
3357
+ -annotate +1+1 "$MENU_TITLE")
3358
fi
3359
- [[ -z $TITLES_STROKE ]] && TITLES_STROKE='#010101'
3360
-
3361
- # make a title image
3362
- #! [[ -z ${STR// /} || -z $STR ]] && TRIM_CMD="-trim +repage -blur 0x0.4 "
3363
- # allow removal of contrasting 'undercolour' with 'title-stroke none'
3364
- # FIXME this is NOT IM syntax and it would be less confusing to adjust it
3365
- [[ $TITLE_STROKE = 'none' ]] && undercolour='none' || undercolour='#101010'
3366
TRIM_CMD="-trim +repage -blur 0x0.3"
3367
- TITLE_CMD=(convert -size 620x100 xc:none -font "$MENU_FONT" -pointsize \
3368
- $MENU_FONTSIZE -fill $undercolour -stroke $undercolour -gravity center \
3369
- -annotate +0+0 "$MENU_TITLE" -fill "$TITLE_CLR" \
3370
- -stroke "$TITLE_STROKE" -strokewidth 1 -annotate +1+1 "$MENU_TITLE")
3371
- TITLE_CMD0=(composite -blend 0x${TITLE_OPACITY} null: - -matte)
3372
- TITLE_CMD1=(convert - $TRIM_CMD "$WORK_DIR/title_txt.png")
3373
+ M_TITLE_CMD0=(composite -blend 0x${TITLE_OPACITY} null: - -matte)
3374
+ M_TITLE_CMD1=(convert - $TRIM_CMD "$WORK_DIR/title_txt.png")
3375
3376
if [[ -n $TITLE_OPACITY ]]; then
3377
- "${TITLE_CMD[@]}" miff:- | "${TITLE_CMD0[@]}" miff:- |
3378
- "${TITLE_CMD1[@]}" >> "$LOG_FILE" 2>&1
3379
+ "${M_TITLE_CMD[@]}" miff:- | "${M_TITLE_CMD0[@]}" miff:- |
3380
+ "${M_TITLE_CMD1[@]}" >> "$LOG_FILE" 2>&1
3381
else
3382
- "${TITLE_CMD[@]}" miff:- | "${TITLE_CMD1[@]}" >> "$LOG_FILE" 2>&1
3383
+ "${M_TITLE_CMD[@]}" miff:- | "${M_TITLE_CMD1[@]}" >> "$LOG_FILE" 2>&1
3384
fi
3385
-
3386
- # make thumb titles
3387
+fi
3388
+# this is really part of same DO_MENU block above, splitting up for readability
3389
+if $DO_MENU; then
3390
+ # make video titles
3391
if ! $SINGLE_SLIDESHOW; then
3392
for ((i=0; i<=NUM_FILES; i++)); do
3393
- spin "Working on video title $((i+1)) "
3394
- THUMB_TITLE_CMD=(convert -size 620x300 xc:none -gravity $JUSTIFY \
3395
- -font "$TITLES_FONT" -pointsize $TITLES_FONTSIZE \
3396
- -fill $CONTRAST_CLR -stroke $TITLES_STROKE \
3397
- -annotate +0+0 "${TITLES[i]}" \
3398
- -fill $TITLES_CLR -stroke none \
3399
- -annotate +1+1 "${TITLES[i]}")
3400
+ print2log "Working on video title $((i+1)) "
3401
+ if $USE_V_TITLES_DECO; then
3402
+ # use a font outline makemenu style
3403
+ V_TITLES_CMD=(convert -size 620x100 xc:none \
3404
+ -font "$TITLES_FONT" -pointsize $TITLES_FONTSIZE \
3405
+ -fill "$TITLES_CLR" "${V_TITLES_FONT_DECO[@]}" \
3406
+ -gravity center -annotate +0+0 "${TITLES[i]}")
3407
+ # #-stroke none -annotate +0+0 "${TITLES[i]}")
3408
+ else
3409
+ # default is to use a font shadow only on one side of font
3410
+ V_TITLES_STROKE=${V_TITLES_STROKE:-black}
3411
+ V_TITLES_CMD=(convert -size 620x300 xc:none -gravity $JUSTIFY \
3412
+ -font "$TITLES_FONT" -pointsize $TITLES_FONTSIZE \
3413
+ -fill none -stroke "$V_TITLES_STROKE" -strokewidth 1 \
3414
+ -annotate +0+0 "${TITLES[i]}" \
3415
+ -fill $TITLES_CLR -stroke none \
3416
+ -annotate +1+1 "${TITLES[i]}")
3417
+ fi
3418
FADE_CMD=(composite -blend 0x${TITLES_OPACITY} null: - -matte)
3419
+ # only repage and border if not 'text button'
3420
if [[ $BUTTON_STYLE = "text" ]]; then
3421
TRIM_CMD=(convert - -trim "$WORK_DIR/thumb_title${i}.png")
3422
else
3423
TRIM_CMD=(convert - -trim +repage $TEXT_BORDER \
3424
"$WORK_DIR/thumb_title${i}.png")
3425
fi
3426
- # make thumb title, only repage and border if not 'text button'
3427
+ # make thumb title
3428
if [[ -n $TITLES_OPACITY ]]; then
3429
- "${THUMB_TITLE_CMD[@]}" miff:- | "${FADE_CMD[@]}" miff:- |
3430
+ "${V_TITLES_CMD[@]}" miff:- | "${FADE_CMD[@]}" miff:- |
3431
"${TRIM_CMD[@]}"
3432
else
3433
- "${THUMB_TITLE_CMD[@]}" miff:- | "${TRIM_CMD[@]}"
3434
+ "${V_TITLES_CMD[@]}" miff:- | "${TRIM_CMD[@]}"
3435
fi
3436
+ # save dimensions for later use
3437
+ TT_DIM[i]=$(get_image_dim "$WORK_DIR/thumb_title${i}.png")
3438
# now get offset before repaging, for the spumux button crop later
3439
if [[ $BUTTON_STYLE = "text" ]]; then
3440
titles_offset[i]=$(identify -format %O \
3441
3442
at your fontsize. Use a smaller font with -titles-fontsize"
3443
fi
3444
done
3445
+ yecho ""
3446
fi
3447
+fi
3448
+###############################################################################
3449
+############ set showcase/textmenu titles and thumb positions array ###########
3450
+###############################################################################
3451
3452
- if $SHOWCASE; then
3453
- for ((i=0; i<=NUM_FILES; i++)); do
3454
- unset ts_dim j
3455
- # get widest png in each colum for use later for alignment use
3456
+# this is really part of same DO_MENU block above, splitting up for readability
3457
+if $DO_MENU && $SHOWCASE; then
3458
+ # textmenu also uses this block !
3459
+ # get widest png in each colum for use later for alignment use
3460
+ for ((i=0; i<=NUM_FILES; i++)); do
3461
+ unset ts_dim j
3462
+ if ((i < SPLIT)); then
3463
+ # save widest_title x_dim as well as its array index
3464
+ val=${TT_DIM[i]/x*}
3465
+ [ -z "$widest_title" ] || ((val > widest_title)) \
3466
+ && widest_title=$val && widest_title_index=$i
3467
+ else
3468
+ val2=${TT_DIM[i]/x*}
3469
+ [ -z "$widest_title2" ] || ((val2 > widest_title2)) \
3470
+ && widest_title2=$val2 && widest_title2_index=$i
3471
+ fi
3472
+ # get just X demension to help determine final title pos below
3473
+ tt_dim=${TT_DIM[i]/x*}
3474
+ done
3475
+ # so we can do math on the var without error
3476
+ ((widest_title2)) || widest_title2=0
3477
+
3478
+ ######################################################################
3479
+ ############### showcase with thumbs only X dimension ################
3480
+ ######################################################################
3481
+
3482
+ { $TEXTMENU && LEFT_MAX=$SPLIT ; } || LEFT_MAX=5
3483
+ # textmenu doesn't use this block at all
3484
+ # TODO check_space=0 # only check if enough space once if $SHOWCASE_FILE
3485
+ # some shortened var names for the math in this block
3486
+ tt_w=${TT_DIM[i]} # title width
3487
+ tt_w=${tt_w/x*}
3488
+ t_w=${THUMB_SIZE/x*} # thumb width
3489
+ safe_w=$SAFE_AREA # safe area width
3490
+ vsize_w=${VIDSIZE/x*} # video size width (720)
3491
+ for ((i=0; i<=NUM_FILES; i++)); do
3492
+ # get array positions for thumbs and titles. The titles_xdelta is
3493
+ # the amount we subtract later from the thumb position to re-define
3494
+ # the arrays when the various -align options are taken into account
3495
+ case $SC_TITLE_ALIGN in
3496
+ west)
3497
+ # only need extra room after 2nd column for long titles
3498
+ ovflow=$(( widest_title2 - t_w ))
3499
if ((i < SPLIT)); then
3500
- val=${TT_DIM[i]/x*}
3501
- [ -z "$WIDEST_TITLE" ] || ((val > WIDEST_TITLE)) \
3502
- && WIDEST_TITLE=$val
3503
- else
3504
- val2=${TT_DIM[i]/x*}
3505
- [ -z "$WIDEST_TITLE2" ] || ((val2 > WIDEST_TITLE2)) \
3506
- && WIDEST_TITLE2=$val2
3507
- fi
3508
- # get just X demension to help determine final title pos below
3509
- tt_dim=${TT_DIM[i]/x*}
3510
+ SC_THUMB_X_ARRAY[i]=$((${SC_THUMB_X_ARRAY[i]} - SAFE_OFFSET))
3511
+ else
3512
+ # ovflow=0 is the right edge of thumb, so stop there
3513
+ ((ovflow < 0)) && ovflow=0
3514
+ # titles are aligned west: try to align east side close to edge
3515
+ SC_THUMB_X_ARRAY[i]=$(( vsize_w - t_w - safe_w - ovflow ))
3516
+ fi
3517
+ SC_TITLES_X_ARRAY[i]=${SC_THUMB_X_ARRAY[i]}
3518
+ titles_xdelta[i]=0 # for using later in -align options
3519
+ ;;
3520
+ east)
3521
+ #if ((i < SPLIT)) && ! $ALIGN_OVERRIDE; then
3522
+ #SC_THUMB_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - \
3523
+ #SAFE_OFFSET ))
3524
+ #SC_TITLES_X_ARRAY[i]=$(( ${SC_TITLES_X_ARRAY[i]} - \
3525
+ #SAFE_OFFSET ))
3526
+ #fi
3527
+ if ((i >= SPLIT)); then
3528
+ # 2 cols can't -align east/west/center so no ALIGN_OVERRIDE test
3529
+ SC_THUMB_X_ARRAY[i]=$(( ( vsize_w - safe_w) - \
3530
+ $widest_title2 - t_w - 5 ))
3531
+ # titlesafe warnings disabled for now
3532
+ #roffset=$(( ${SC_TITLES_X_ARRAY[i]} + 5 + safe_w ))
3533
+ #if (( roffset + ${TT_DIM[i]/x*} > vsize_w )); then
3534
+ # titlesafe_error $(( roffset - vsize_w ))
3535
+ #fi
3536
+ fi
3537
+ SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} + t_w + 5 ))
3538
+ SC_TITLES_Y_ARRAY[i]=${SC_THUMB_Y_ARRAY[i]}
3539
+ titles_xdelta[i]=$(( ${SC_THUMB_X_ARRAY[i]} - ${SC_TITLES_X_ARRAY[i]} ))
3540
+ ;;
3541
+ center)
3542
+ # make sure the showcase file is not being covered up
3543
+ ! [[ $widest_title ]] && widest_title=0
3544
+ ! [[ $widest_title2 ]] && widest_title2=0
3545
+ #if ((widest_title2)); then
3546
+ # col2_thumb_x=$widest_title2
3547
+ # thumbs_space=$((${THUMB_SIZE/x*} * 2))
3548
+ #else
3549
+ # col2_thumb_x=0
3550
+ # thumbs_space=${THUMB_SIZE/x*}
3551
+ #fi
3552
+ # need to rewrite, checking only the area on sides of the sc thumb
3553
+ #if [[ $SHOWCASE_FILE ]]; then #&& ! ((checked_space)); then
3554
+ # safearea=$((SAFE_AREA * 2))
3555
+ # titles_space=$((widest_title + col2_thumb_x))
3556
+ # if $(( (VS - safearea - \
3557
+ # titles_space - thumbs_space - ShowCaseSize) <= 0)); then
3558
+ # : # problem: do something #FIXME run this only once
3559
+ # fi
3560
+ #fi
3561
+ #checked_space=1
3562
+ # check if "title-safe" (not too close to screen edge or offscreen)
3563
+ # for showcase with thumbs and center aligned titles only # FIXME?
3564
# thumb pos + 1/2 (X dim) of thumbsize - 1/2 (X dim) of title size
3565
- if [ "$SC_TITLE_ALIGN" = "center" ]; then
3566
- f=$(( ${THUMB_SIZE/x*} / 2 ))
3567
- j=$(( (f + ${SC_THUMB_X_ARRAY[i]}) - (tt_dim / 2) ))
3568
- k=( ${k[@]} "$j" )
3569
- l=$((j + tt_dim))
3570
- if [ $j -lt 48 ]; then
3571
+ f=$(( ${THUMB_SIZE/x*} / 2 ))
3572
+ j=$(( ( ${SC_THUMB_X_ARRAY[i]} + f ) - (${TT_DIM[i]/x*} / 2) ))
3573
+ if ((widest_title > ${TT_DIM[i]/x*})); then
3574
+ offset1=$(( (widest_title - ${TT_DIM[i]/x*}) / 2 ))
3575
+ offset2=$((widest_title2 - ${TT_DIM[i]/x*} / 2 ))
3576
+ else
3577
+ offset1=${TT_DIM[i]/x*}
3578
+ fi
3579
+ offset_from_safe_edge1=$offset # unused
3580
+ tt_x=( ${tt_x[@]} "$j" )
3581
+ l=$((j + tt_dim))
3582
+ # FIXME this test gives wrong result and is unused right now !
3583
+ if ((i < SPLIT)); then
3584
+ if (( j < SAFE_AREA + SAFE_OFFSET )); then
3585
off_left=$j
3586
- titlesafe_error $off_left
3587
- elif [ $l -gt 672 ]; then
3588
- off_right=$((720 - l))
3589
- titlesafe_error $off_right
3590
+ # titlesafe warnings disabled for now
3591
+ #titlesafe_error $off_left
3592
+ fi
3593
+ else
3594
+ if (( l > vsize_w - SAFE_AREA - SAFE_OFFSET)); then
3595
+ off_right=$(($vsize_w - l))
3596
+ #titlesafe_error $off_right
3597
fi
3598
fi
3599
- done
3600
+ titles_xdelta[i]=$(( ${SC_THUMB_X_ARRAY[i]} - ${tt_x[i]} ))
3601
+ ;;
3602
+ esac
3603
+ # now that we have the title delta, factor in -align option (E/W/Centre)
3604
+ td=${titles_xdelta[i]}
3605
+ case $BUTTON_GRAVITY in
3606
+ *east) # single column showcase with thumbs only
3607
+ # if title is wider than thumb
3608
+ #if ((tt_w > t_w)); then
3609
+ # SC_TITLES_X_ARRAY[i]=$(( vsize_w - safe_w - tt_w ))
3610
+ # thumb wider, or they are the same
3611
+ #else
3612
+ # SC_TITLES_X_ARRAY[i]=$(( vsize_w - safe_w - t_w ))
3613
+ #fi
3614
+ # titles also aligned east of thumb need to Add the (neg) xdelta
3615
+ #if [[ $SC_TITLE_ALIGN = east ]]; then
3616
+ # SC_THUMB_X_ARRAY[i]=$(( vsize_w - safe_w - t_w - (widest_title / 2) + td ))
3617
+ #else
3618
+ # SC_THUMB_X_ARRAY[i]=$(( vsize_w - safe_w - t_w - (widest_title / 2) ))
3619
+ #fi
3620
+ #SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
3621
+ if [[ $SC_TITLE_ALIGN = east ]]; then
3622
+ SC_TITLES_X_ARRAY[i]=$(( vsize_w - safe_w - widest_title ))
3623
+ SC_THUMB_X_ARRAY[i]=$(( ${SC_TITLES_X_ARRAY[i]} - 5 - t_w ))
3624
+ else
3625
+ SC_THUMB_X_ARRAY[i]=$(( vsize_w - safe_w - t_w - (widest_title / 2) ))
3626
+ SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
3627
+ fi
3628
+ ;;
3629
+ *west) # single column showcase with thumbs only
3630
+ # they are the same, as the west sides are flush (titles_xdelta=0)
3631
+ SC_THUMB_X_ARRAY[i]=$((SAFE_AREA + SAFE_OFFSET))
3632
+ SC_TITLES_X_ARRAY[i]=$((${SC_THUMB_X_ARRAY[i]} - td))
3633
+ ;;
3634
+ north|south|center) # either single or 2 column showcase with thumbs
3635
+ if ((NUM_FILES >= SPLIT)); then # 2 column showcase (N/S/C only)
3636
+ #if ((widest_title2 > t_w)); then
3637
+ # SC_THUMB_X_ARRAY[i]=$((vsize_w - safe_w - t_w + td))
3638
+ #fi
3639
+ SC_TITLES_X_ARRAY[i]=$((${SC_THUMB_X_ARRAY[i]} - td))
3640
+ else # single column showcase (all -align opt should work)
3641
+ SC_THUMB_X_ARRAY[i]=$(( (vsize_w / 2) - (t_w / 2) ))
3642
+ SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
3643
+ fi
3644
+ #if ((tt_w > t_w)); then
3645
+ # SC_THUMB_X_ARRAY[i]=$(( (vsize_w / 2) - (t_w / 2) ))
3646
+ # SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
3647
+ #else
3648
+ # SC_THUMB_X_ARRAY[i]=$(( (vsize_w / 2) - (t_w / 2) ))
3649
+ # SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
3650
+ #fi
3651
+ #echo thumb: ${SC_THUMB_X_ARRAY[i]} title: ${SC_TITLES_X_ARRAY[i]}
3652
+ ;;
3653
+ *)
3654
+ # default is to use original arrays. Subtract titles_xdelta
3655
+ SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
3656
+ ;;
3657
+ esac
3658
+ done
3659
+ ######################################################################
3660
+ ############### showcase with thumbs only Y dimension ################
3661
+ ######################################################################
3662
+
3663
+ # bottom edge of last thumb vertically
3664
+ SW_CORNER=$(( ${SC_THUMB_Y_ARRAY[SPLIT-1]} + ${THUMB_SIZE/*x} ))
3665
+ # TODO add north) so user can align flush with top safearea edge
3666
+ # as the default is not 'exactly' north in these terms, but a compromise
3667
+ # center aligned titles only can use *west -align options
3668
+ case $BUTTON_GRAVITY in
3669
+ northwest)
3670
+ : # no offset
3671
+ ;;
3672
+ south*)
3673
+ Y_OFFSET=$(( ( ${VIDSIZE/*x} - SAFE_AREA) - SW_CORNER ))
3674
+ ;;
3675
+ *east|*west|center)
3676
+ COL1_HEIGHT=$(( SW_CORNER - ${SC_TITLES_Y_ARRAY[0]} ))
3677
+ Y_OFFSET=$(( ( ${VIDSIZE/*x} / 2) - (COL1_HEIGHT / 2) ))
3678
+ Y_OFFSET=$(( Y_OFFSET - ${SC_TITLES_Y_ARRAY[0]} ))
3679
+ ;;
3680
+ esac
3681
+ #if [[ $BUTTON_GRAVITY = south* ]]; then
3682
+ # Y_OFFSET=$(( ( ${VIDSIZE/*x} - SAFE_AREA) - SW_CORNER ))
3683
+ #elif [[ $BUTTON_GRAVITY = *st* ]] || [[ $BUTTON_GRAVITY = *center* ]]; then
3684
+ # COL1_HEIGHT=$(( SW_CORNER - ${SC_TITLES_Y_ARRAY[0]} ))
3685
+ # Y_OFFSET=$(( ( ${VIDSIZE/*x} / 2) - (COL1_HEIGHT / 2) ))
3686
+ # Y_OFFSET=$(( Y_OFFSET - ${SC_TITLES_Y_ARRAY[0]} ))
3687
+ #fi
3688
+ for ((i=0; i<=NUM_FILES; i++)); do
3689
+ SC_THUMB_Y_ARRAY[i]=$((${SC_THUMB_Y_ARRAY[i]} + Y_OFFSET ))
3690
+ SC_TITLES_Y_ARRAY[i]=$((${SC_TITLES_Y_ARRAY[i]} + Y_OFFSET))
3691
+ done
3692
+ #fi
3693
+ # showcase style default: left justification. montages default: center.
3694
+ # find out the showcase thumb "-page" array for this arrangement
3695
+ for ((i=0; i<=NUM_FILES; i++)); do
3696
if $TEXTMENU; then
3697
- # text-rect is OK with a small space between titles for spumux
3698
- [[ $BUTTON_STYLE = "text-rect" ]] && \
3699
- SPACER=${SPACER:-"10"} || SPACER=${SPACER:-"15"}
3700
- # get an array of title Y positions
3701
- offsets1=$(for ((c=0; c<NUM_FILES; c++)); do
3702
- ((c < (LEFT_MAX-1))) && echo $((${TT_DIM[c]#*x} + SPACER)); done)
3703
- if [[ $NUM_FILES -ge $SPLIT ]]; then
3704
- offsets2=$(for ((d=0; d<=NUM_FILES; d++)); do
3705
- ((d >= LEFT_MAX)) && echo $((${TT_DIM[d]#*x} + SPACER)); done)
3706
- [[ $offsets2 ]] && offsets2="$TEXT_YSTART $offsets2"
3707
- tt_ygeos_col2=$(running_total <<< $offsets2)
3708
- fi
3709
- offsets1="$TEXT_YSTART $offsets1"
3710
- tt_ygeos_col1=$(running_total <<< $offsets1)
3711
- tt_ygeos="$tt_ygeos_col1 $tt_ygeos_col2"
3712
- unset SC_TITLES_Y_ARRAY
3713
- SC_TITLES_Y_ARRAY=( $tt_ygeos_col1 $tt_ygeos_col2 )
3714
- # get y position of the last title in 1st column (tt_ygeos_col1)
3715
- endtitle_col1=$(wc -w <<< "$tt_ygeos_col1")
3716
- endtitle_col1_ygeo=${SC_TITLES_Y_ARRAY[endtitle_col1-1]/*x}
3717
- # add y dimension of the last title size to the above y position
3718
- SW_YCORNER=$((${TT_DIM[endtitle_col1-1]/*x} + $endtitle_col1_ygeo))
3719
- avail_space1=$(( ( ${VIDSIZE/*x} - SAFE_AREA ) - $SW_YCORNER ))
3720
- # if there are 2 columns, get same data for column 2
3721
- if [[ -n $tt_ygeos_col2 ]]; then
3722
- endtitle_col2=$NUM_FILES
3723
- endtitle_col2_ygeo=${SC_TITLES_Y_ARRAY[endtitle_col2]/*x}
3724
- endtitle_col2_xgeo=${SC_TITLES_Y_ARRAY[endtitle_col2]/x*}
3725
- SE_YCORNER=$((${TT_DIM[endtitle_col2]/*x}+$endtitle_col2_ygeo))
3726
- avail_space2=$(( ( ${VIDSIZE/*x} - SAFE_AREA ) - $SE_YCORNER ))
3727
- fi
3728
- # available space is lowest value of 2 *space* vars ( if 2 columns)
3729
- if [[ -n $tt_ygeos_col2 ]] && ((SE_YCORNER > SW_YCORNER)); then
3730
- avail_space=$avail_space2
3731
- else
3732
- avail_space=$avail_space1
3733
- fi
3734
- # get the height of each column for -align centre
3735
- if [[ $BUTTON_GRAVITY = "center" \
3736
- || $BUTTON_GRAVITY = "east" || $BUTTON_GRAVITY = "west" ]]; then
3737
- WEST_YSPACE=$(( SW_YCORNER - TEXT_YSTART))
3738
- EAST_YSPACE=$((SE_YCORNER - TEXT_YSTART))
3739
- ((WEST_YSPACE > EAST_YSPACE)) && YSPACE=$WEST_YSPACE \
3740
- || YSPACE=$EAST_YSPACE
3741
- CANVAS=$(( ${VIDSIZE/*x} - (SAFE_AREA * 2) ))
3742
- NEW_TEXT_YSTART=$(( ((CANVAS - YSPACE) / 2) + SAFE_AREA ))
3743
- TEXT_YSTART_OFFSET=$((NEW_TEXT_YSTART - TEXT_YSTART))
3744
- fi
3745
- # add available space to each title position for south alignment
3746
- if [[ $BUTTON_GRAVITY = *south* ]] && ((avail_space > 0)); then
3747
- for ((d=0; d<=NUM_FILES; d++)); do
3748
- SC_TITLES_Y_ARRAY[d]=$(( $avail_space + \
3749
- ${SC_TITLES_Y_ARRAY[d]} ))
3750
- done
3751
- elif [[ $BUTTON_GRAVITY = "center" \
3752
- || $BUTTON_GRAVITY = "east" || $BUTTON_GRAVITY = "west" ]]; then
3753
- for ((d=0; d<=NUM_FILES; d++)); do
3754
- SC_TITLES_Y_ARRAY[d]=$(($TEXT_YSTART_OFFSET + \
3755
- ${SC_TITLES_Y_ARRAY[d]} ))
3756
- done
3757
- fi
3758
- # justify titles to the right on the east side of the menu
3759
- ((NUM_FILES >= SPLIT-1)) && WIDE_TITLE=$WIDEST_TITLE2 \
3760
- || WIDE_TITLE=$WIDEST_TITLE
3761
- for ((d=0; d<=NUM_FILES; d++)); do
3762
- ([[ "$BUTTON_GRAVITY" = *east* ]] \
3763
- || [[ -n $tt_ygeos_col2 ]]) && \
3764
- east_offset=$(( ( ${VIDSIZE/x*} - SAFE_AREA ) - \
3765
- ${TT_DIM[d]/x*} ))
3766
- if (($NUM_FILES < SPLIT)); then
3767
- SC_TITLES_X_ARRAY[d]=$SAFE_AREA
3768
- [[ "$BUTTON_GRAVITY" = *east* ]] && \
3769
- SC_TITLES_X_ARRAY[d]=$east_offset
3770
- else
3771
- if ((d >= LEFT_MAX)); then
3772
- SC_TITLES_X_ARRAY[d]=$east_offset
3773
- else
3774
- SC_TITLES_X_ARRAY[d]=$SAFE_AREA
3775
- fi
3776
- fi
3777
- done
3778
- unset MAX_VAL val max_key
3779
+ SCTHUMB_PAGES_ARRAY[i]=+${SC_TITLES_Y_ARRAY[i]}+${SC_TITLES_X_ARRAY[i]}
3780
+ else
3781
+ SCTHUMB_PAGES_ARRAY[i]=+${SC_THUMB_X_ARRAY[i]}+${SC_THUMB_Y_ARRAY[i]}
3782
fi
3783
- # make SHOWCASE_PAGE arrayS for thumbs and THUMBTITLES_ARRAY for titles
3784
- # use preset values unless doing centre align for titles
3785
- for ((i=0; i<=NUM_FILES; i++)); do
3786
- if [ "$SC_TITLE_ALIGN" != "center" ]; then
3787
- SC_TITLES_ARR[i]=+${SC_TITLES_X_ARRAY[i]}+${SC_TITLES_Y_ARRAY[i]}
3788
+ done
3789
+fi
3790
+
3791
+##############################################################################
3792
+################# textmenu only #################
3793
+##############################################################################
3794
+
3795
+if $DO_MENU && $TEXTMENU; then
3796
+ ############# textmenu Y dimension #############
3797
+ # text-rect is OK with a small space between titles for spumux
3798
+ [[ $BUTTON_STYLE = "text-rect" ]] && \
3799
+ SPACER=${SPACER:-"10"} || SPACER=${SPACER:-"15"}
3800
+
3801
+ # get array of titles Y positions for textmenu
3802
+ offsets1=$(for ((c=0; c<NUM_FILES; c++)); do
3803
+ ((c < (LEFT_MAX-1))) && echo $((${TT_DIM[c]#*x} + SPACER)); done)
3804
+ if ((NUM_FILES >= SPLIT)); then
3805
+ # to line up rows across, use taller of 2 images for space calc.
3806
+ if (( ${TT_DIM[c-SPLIT]#*x} > ${TT_DIM[c]#*x} )); then
3807
+ tt_yspace=${TT_DIM[c-SPLIT]#*x}
3808
+ else
3809
+ tt_yspace=${TT_DIM[c]#*x}
3810
+ fi
3811
+ offsets1=$(for ((c=0; c<NUM_FILES; c++)); do
3812
+ ((c < (LEFT_MAX-1))) && echo $((tt_yspace + SPACER)); done)
3813
+ offsets2=$(for ((d=0; d<=NUM_FILES; d++)); do
3814
+ ((d >= LEFT_MAX)) && echo $((tt_yspace + SPACER)); done)
3815
+ [[ $offsets2 ]] && offsets2="$TEXT_YSTART $offsets2"
3816
+ tt_ygeos_col2=$(running_total <<< $offsets2)
3817
+ fi
3818
+ offsets1="$TEXT_YSTART $offsets1"
3819
+ tt_ygeos_col1=$(running_total <<< $offsets1)
3820
+ tt_ygeos="$tt_ygeos_col1 $tt_ygeos_col2"
3821
+ unset SC_TITLES_Y_ARRAY
3822
+ SC_TITLES_Y_ARRAY=( $tt_ygeos_col1 $tt_ygeos_col2 )
3823
+ # get y position of the last title in 1st column (tt_ygeos_col1)
3824
+ endtitle_col1=$(wc -w <<< "$tt_ygeos_col1")
3825
+ endtitle_col1_ygeo=${SC_TITLES_Y_ARRAY[endtitle_col1-1]/*x}
3826
+ # add y dimension of the last title size to the above y position
3827
+ SW_YCORNER=$((${TT_DIM[endtitle_col1-1]/*x} + $endtitle_col1_ygeo))
3828
+ avail_space1=$(( ( ${VIDSIZE/*x} - SAFE_AREA ) - $SW_YCORNER ))
3829
+ # if there are 2 columns, get same data for column 2
3830
+ if [[ -n $tt_ygeos_col2 ]]; then
3831
+ endtitle_col2=$NUM_FILES
3832
+ endtitle_col2_ygeo=${SC_TITLES_Y_ARRAY[endtitle_col2]/*x}
3833
+ endtitle_col2_xgeo=${SC_TITLES_Y_ARRAY[endtitle_col2]/x*}
3834
+ SE_YCORNER=$((${TT_DIM[endtitle_col2]/*x}+$endtitle_col2_ygeo))
3835
+ avail_space2=$(( ( ${VIDSIZE/*x} - SAFE_AREA ) - SE_YCORNER ))
3836
+ fi
3837
+ # available space is lowest value of 2 *space* vars ( if 2 columns)
3838
+ if [[ -n $tt_ygeos_col2 ]] && ((SE_YCORNER > SW_YCORNER)); then
3839
+ avail_space=$avail_space2
3840
+ end_title_pos=$SE_YCORNER
3841
+ else
3842
+ avail_space=$avail_space1
3843
+ end_title_pos=$SW_YCORNER
3844
+ fi
3845
+ # get the height of each column for -align centre
3846
+ if [[ $BUTTON_GRAVITY = "center" \
3847
+ || $BUTTON_GRAVITY = "east" || $BUTTON_GRAVITY = "west" ]]; then
3848
+ WEST_YSPACE=$(( SW_YCORNER - TEXT_YSTART))
3849
+ EAST_YSPACE=$((SE_YCORNER - TEXT_YSTART))
3850
+ ((WEST_YSPACE > EAST_YSPACE)) && YSPACE=$WEST_YSPACE \
3851
+ || YSPACE=$EAST_YSPACE
3852
+ CANVAS_Y=$(( ${VIDSIZE/*x} - (SAFE_AREA * 2) ))
3853
+ NEW_TEXT_YSTART=$(( ( (CANVAS_Y - YSPACE) / 2) + SAFE_AREA ))
3854
+ TEXT_YSTART_OFFSET=$((NEW_TEXT_YSTART - TEXT_YSTART))
3855
+ fi
3856
+ # add available space to each title position for south alignment
3857
+ if [[ $BUTTON_GRAVITY = *south* ]] && ((avail_space > 0)); then
3858
+ for ((d=0; d<=NUM_FILES; d++)); do
3859
+ SC_TITLES_Y_ARRAY[d]=$(( $avail_space + \
3860
+ ${SC_TITLES_Y_ARRAY[d]} ))
3861
+ done
3862
+ elif [[ $BUTTON_GRAVITY = "center" \
3863
+ || $BUTTON_GRAVITY = "east" || $BUTTON_GRAVITY = "west" ]]; then
3864
+ for ((d=0; d<=NUM_FILES; d++)); do
3865
+ SC_TITLES_Y_ARRAY[d]=$(($TEXT_YSTART_OFFSET + \
3866
+ ${SC_TITLES_Y_ARRAY[d]} ))
3867
+ done
3868
+ fi
3869
+fi
3870
+ ######################## textmenu X dimension ##########################
3871
+# this is really part of block above, split up for readability
3872
+if $DO_MENU && $TEXTMENU; then
3873
+ XSPACE=$(( ${VIDSIZE/x*} - SAFE_AREA ))
3874
+ # title Xdim location for ONE column on right side (left justified)
3875
+ ljustify_eoffset=$((XSPACE-widest_title))
3876
+ # same as above, but for 2nd column when using TWO title columns
3877
+ ljustify_eoffset2=$((XSPACE-widest_title2))
3878
+ for ((d=0; d<=NUM_FILES; d++)); do
3879
+ ([[ "$BUTTON_GRAVITY" = *east* ]] \
3880
+ || [[ -n $tt_ygeos_col2 ]]) && \
3881
+ rjustify_eoffset=$(( XSPACE - ${TT_DIM[d]/x*} ))
3882
+ if ((d < SPLIT)); then
3883
+ # default is northwest alignment
3884
+ SC_TITLES_X_ARRAY[d]=$SAFE_AREA
3885
+ # for centred align add safe area from both sides
3886
+ case "$BUTTON_GRAVITY" in
3887
+ "center" | "north" | "south")
3888
+ SC_TITLES_X_ARRAY[d]=$((( (XSPACE + SAFE_AREA) / 2) - \
3889
+ (${TT_DIM[d]/x*} / 2) ))
3890
+ ;;
3891
+ "northeast"|"southeast"|"east")
3892
+ # allow justifying east column to right instead of left
3893
+ if $EDGE_JUSTIFY; then
3894
+ SC_TITLES_X_ARRAY[d]=$rjustify_eoffset
3895
+ else
3896
+ SC_TITLES_X_ARRAY[d]=$ljustify_eoffset
3897
+ fi
3898
+ ;;
3899
+ esac
3900
+ else # could be single column or a 2nd column, aligned east
3901
+ if ((d >= LEFT_MAX)); then # therefore this is an east column
3902
+ # allow justifying east column to right instead of left
3903
+ if $EDGE_JUSTIFY; then
3904
+ SC_TITLES_X_ARRAY[d]=$rjustify_eoffset
3905
+ else
3906
+ SC_TITLES_X_ARRAY[d]=$ljustify_eoffset2
3907
+ fi
3908
else
3909
- SC_TITLES_ARR[i]=+${k[i]}+${SC_TITLES_Y_ARRAY[i]}
3910
+ SC_TITLES_X_ARRAY[d]=$SAFE_AREA
3911
fi
3912
-
3913
- SHOWCASE_THUMB_PAGES[i]="-page ${SCTHUMB_PAGES_ARRAY[i]}"
3914
- THUMBTITLES_ARRAY[i]="-page ${SC_TITLES_ARR[i]}"
3915
- done
3916
- fi
3917
+ fi
3918
+ done
3919
+ unset MAX_VAL val max_key
3920
+ # END textmenu block
3921
fi
3922
+if $SHOWCASE; then
3923
+ # make -page arrays for thumbs, and for titles
3924
+ # use values set in the above block for textmenu
3925
+ # and for showcase with thumbs unless doing centre align for titles
3926
+ for ((i=0; i<=NUM_FILES; i++)); do
3927
+ #if [ "$SC_TITLE_ALIGN" != "center" ]; then
3928
+ SC_TITLES_ARR[i]=+${SC_TITLES_X_ARRAY[i]}+${SC_TITLES_Y_ARRAY[i]}
3929
+ #else
3930
+ # SC_TITLES_ARR[i]=+${tt_x[i]}+${SC_TITLES_Y_ARRAY[i]}
3931
+ #fi
3932
3933
+ SHOWCASE_THUMB_PAGES[i]="-page ${SCTHUMB_PAGES_ARRAY[i]}"
3934
+ THUMBTITLES_ARRAY[i]="-page ${SC_TITLES_ARR[i]}"
3935
+ done
3936
+ echo
3937
+fi
3938
# make a button for playall and one for jumping to the vmgm menu, if called for
3939
# or make a 'play' button if doing a montage slideshow menu
3940
pa_ind=$((NUM_FILES+1))
3941
3942
if $MIST; then
3943
mist_dim=$(get_image_dim "$WORK_DIR/white.png" )
3944
mist_xdim=${mist_dim/x*}
3945
- mist_xdim_offset=$(( (mist_xdim - TITLE_TEXT_XDIM) / 2 ))
3946
- if [[ $TITLE_GRAVITY = *st* ]]; then
3947
+ mist_xoffset=$(( (mist_xdim - TITLE_TEXT_XDIM) / 2 ))
3948
+ case $TITLE_GRAVITY in
3949
+ northeast|southeast|east)
3950
title_xoffset=${title_xoffset:-"+50"}
3951
- mist_xoffset="$(bc_math "${title_xoffset#*[-+]} \
3952
- - $mist_xdim_offset" int)"
3953
+ mist_xoffset="$(bc_math "${title_xoffset#*[-+]} - $mist_xoffset" int)"
3954
[[ ${mist_xoffset:0:1} != [+-] ]] && mist_xoffset=+${mist_xoffset}
3955
- else
3956
+ ;;
3957
+ *)
3958
title_xoffset=${title_xoffset:-"+0"}
3959
mist_xoffset=$title_xoffset
3960
- fi
3961
+ ;;
3962
+ esac
3963
else
3964
+ # make sure the offset supplied is >= safe_area
3965
+ if [[ $TITLE_GRAVITY = east || $TITLE_GRAVITY = west ]]; then
3966
+ ((${title_xoffset#*[-+]} < SAFE_AREA)) && title_xoffset=+${SAFE_AREA}
3967
+ fi
3968
title_xoffset=${title_xoffset:-"+0"}
3969
fi
3970
###############################################################################
3971
3972
else
3973
bg_post_seek="-ss $BG_SEEK" && unset bg_pre_seek
3974
fi
3975
- FFMPEG_CMD=(ffmpeg $bg_pre_seek -i "$BG_VIDEO" -s $VIDSIZE -vframes 1 \
3976
- -an $bg_post_seek -f image2 -y "$WORK_DIR/pics/template.$IMG_FMT")
3977
- echo -e "\nRunning: "${FFMPEG_CMD[@]}"\n" | fold -bs >> "$LOG_FILE"
3978
+ FFMPEG_CMD=($FFmpeg $bg_pre_seek -i "$BG_VIDEO" $VF scale=$VF_SCALE \
3979
+ -an $bg_post_seek -f image2 -vframes 1 -y "$WORK_DIR/pics/template.$IMG_FMT")
3980
+ #echo -e "\nRunning: "${FFMPEG_CMD[@]}"\n" | fold -bs >> "$LOG_FILE"
3981
+ print2log "Running ${FFMPEG_CMD[@]}"
3982
SED_VAR="frame="
3983
- if ! "${FFMPEG_CMD[@]}" 2>&1 |strings >> "$LOG_FILE";then
3984
+ "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
3985
+ if ((${PIPESTATUS[0]} != 0)); then
3986
runtime_error "Problem creating images from the video."
3987
fi
3988
+ echo | tee -a "$LOG_FILE"
3989
fi
3990
-if $SHOWCASE && ($SC_THUMB || $QUICK_MENU); then
3991
- if [[ $SC_TITLE_ALIGN = "east" ]] && ! $TEXTMENU; then
3992
- TS="+ ${THUMB_SIZE/x*}"
3993
- else
3994
- TS=0
3995
- fi
3996
- if (( (WIDEST_TITLE + SAFE_AREA + TS + \
3997
- ${SHOWCASE_SIZE/x*}) > ( ${VIDSIZE/x*} - SAFE_AREA) )); then
3998
+if $SHOWCASE && { $SC_THUMB || $QUICK_MENU ; }; then
3999
+ #if [[ $SC_TITLE_ALIGN = "east" ]] && ! $TEXTMENU; then
4000
+ # TS=${THUMB_SIZE/x*}
4001
+ #else
4002
+ # TS=0
4003
+ #fi
4004
+ if ((V_TOTAL > SPLIT)); then
4005
SHOWCASE_SIZE=$SM_SHOWCASE_SIZE
4006
fi
4007
if $TEXTMENU && [[ -n $tt_ygeos_col2 ]]; then
4008
SHOWCASE_SIZE=$SM_SHOWCASE_SIZE
4009
fi
4010
+ # make mask for showcase shape, now that the showcase size is set
4011
+ if [[ -n $SHOWCASE_SHAPE ]]; then
4012
+ MASK="$WORK_DIR/${SHOWCASE_SHAPE}_mask.png"
4013
+ make_mask $SHOWCASE_SHAPE showcase
4014
+ convert "$MASK" -resize ${SHOWCASE_SIZE}! "$MASK"
4015
+ SHOWCASE_MASK="$MASK"
4016
+ fi
4017
4018
if $SHOWCASE_3D && [[ -n $SHOWCASE_SHAPE ]]; then
4019
CURVE_VARS="5 3 5 1 1"
4020
4021
if $SWITCHED && $USER_THUMBS; then
4022
echo "Using supplied image for showcased thumb"
4023
else
4024
- echo "Getting video images from $SHOWCASE_VIDEO"
4025
+ ! $QUICK_MENU && \
4026
+ yecho "Getting showcase video images from $SHOWCASE_VIDEO"
4027
fi
4028
if [[ "$SC_FRAMESTYLE" = "glass" ]]; then
4029
# some vars for get_framed_pics function
4030
4031
FRAME_SIZE=$SHOWCASE_SIZE
4032
MPLAYER_SEEK_VAL=$SHOWCASE_SEEK_VAL
4033
$SWITCHED && MPLAYER_SEEK_VAL=${SEEK_VAL[MENU_NUM-1]}
4034
- echo "Using mplayer to get framed images from the showcase video"
4035
+ yecho "Using mplayer to get framed images from the showcase video"
4036
get_framed_pics "$SHOWCASE_VIDEO" >> "$LOG_FILE" 2>&1
4037
largest_img=$(get_largest 8 30 )
4038
- mv -v "$largest_img" "$OUT"
4039
+ mv "$largest_img" "$OUT"
4040
rm -f "$WORK_DIR"/00000*.png
4041
convert "$WORK_DIR/showcase_img.png" \
4042
-background none $ROTATE $WAVE miff:-|
4043
4044
convert ${USER_PICS[MENU_NUM-1]} -resize $SHOWCASE_SIZE \
4045
"$WORK_DIR/showcase_img.png"
4046
else
4047
- FFMPEG_CMD=(ffmpeg $ffm_pre_seek -i "$SHOWCASE_VIDEO" \
4048
- -s $SHOWCASE_SIZE -an $ffm_post_seek -vframes 1 -f image2 -y \
4049
- "$WORK_DIR/showcase_img.png")
4050
- echo -e "\nRunning: "${FFMPEG_CMD[@]}"\n" | fold -bs \
4051
- |tee -a "$LOG_FILE"
4052
+ FFMPEG_CMD=($FFmpeg $ffm_pre_seek -i "$SHOWCASE_VIDEO" \
4053
+ $VF scale=${SHOWCASE_SIZE%x*}:${SHOWCASE_SIZE#*x} -an \
4054
+ $ffm_post_seek -f image2 -y -vframes 1 "$WORK_DIR/showcase_img.png")
4055
+ print2log "Running: ${FFMPEG_CMD[@]}"
4056
SED_VAR="frame="
4057
- if ! "${FFMPEG_CMD[@]}" 2>&1 | strings >> "$LOG_FILE";then
4058
+ "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
4059
+ if ((${PIPESTATUS[0]} != 0)); then
4060
runtime_error "Problem creating images from the video."
4061
fi
4062
fi
4063
4064
else
4065
SHAPE_CMD=(convert -size $SHOWCASE_SIZE "$SHOWCASE_IMG" \
4066
-resize $SHOWCASE_SIZE! $SHOWCASE_FRAME $SC_RAISE)
4067
+ print2log "Running ${SHAPE_CMD[@]}"
4068
fi
4069
"${SHAPE_CMD[@]}" miff:- |
4070
"${sc_3d_cmd[@]}" miff:- |
4071
4072
4073
# create the preview images
4074
if ! $TEXTMENU && ! $SINGLE_SLIDESHOW && $DO_MENU && ! $USER_THUMBS; then
4075
+ print2log "Getting images from your video(s) for the preview"
4076
for ((i=0; i<=NUM_FILES; i++)) ; do
4077
# fast seek disabled by default
4078
if $FAST_SEEK; then
4079
4080
SV=${SEEK_VAL[i]}; CURFILE="${IN_FILES[i]##*/}"
4081
spin "[$((i + 1)) of ${#FILES[@]}] Seeking to $SV seconds in $CURFILE"
4082
4083
- FFMPEG_CMD=(ffmpeg $fmt $ffm_pre_seek -i "${IN_FILES[i]}" -an \
4084
+ FFMPEG_CMD=($FFmpeg $fmt $ffm_pre_seek -i "${IN_FILES[i]}" -an \
4085
$ffm_postseek -f image2 -vframes $V_FRAMES \
4086
- -s $THUMB_SIZE -y $WORK_DIR/pics/$i/%06d.$IMG_FMT)
4087
+ $VF scale=${THUMB_SIZE%x*}:${THUMB_SIZE#*x} -y $WORK_DIR/pics/$i/%06d.$IMG_FMT)
4088
CMD=( "${FFMPEG_CMD[@]}" )
4089
SED_VAR="frame="
4090
! [[ "$SC_FRAMESTYLE" = "glass" ]] \
4091
- && echo -e "\nRunning: "${CMD[@]}"\n" | fold -bs >> "$LOG_FILE"
4092
+ && print2log "Running: ${CMD[@]}"
4093
# some vars for get_framed_pics function
4094
VOUT="png:z=7"; FRAMES=30
4095
FRAME_SIZE=$THUMB_SIZE
4096
4097
mv -f $largest_img "$WORK_DIR/pics/$i/$(printf "%06d%s" 0 .$IMG_FMT)"
4098
rm -f "$WORK_DIR"/000*[0-9].png
4099
elif [ "$SC_FRAMESTYLE" = "none" ]; then
4100
- if ! "${FFMPEG_CMD[@]}" 2>&1 |strings >> "$LOG_FILE";then
4101
+ "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/} 2>&1
4102
+ if ((${PIPESTATUS[0]} != 0)); then
4103
runtime_error "Problem creating images from the video."
4104
fi
4105
4106
# get largest image of 9 if static menu and -frame-safe
4107
- if $FRAME_SAFE; then #FIXME $STATIC not necessary, this is a preview!
4108
+ if $FRAME_SAFE; then
4109
largest_img=$(get_largest 6 $V_FRAMES "$WORK_DIR/pics/$i")
4110
- echo Using $largest_img for menu >2&
4111
mv -f "$largest_img" "$WORK_DIR/pics/largest.$IMG_FMT"
4112
rm -f "$WORK_DIR"/pics/$i/*.$IMG_FMT
4113
mv "$WORK_DIR/pics/largest.$IMG_FMT" \
4114
4115
fi
4116
4117
wait
4118
- unset NAVSEEK_CMD rectangle run_transcode FFMPEG_CMD TRANSCODE_CMD
4119
+ unset NAVSEEK_CMD rectangle FFMPEG_CMD TRANSCODE_CMD
4120
done
4121
echo
4122
fi
4123
# for user supplied thumbs, resize and copy to appropriate directories
4124
-if ! $SWITCHED; then
4125
+if ! $SWITCHED && $USER_THUMBS; then
4126
for i in ${!USER_PICS[@]}; do
4127
convert "${USER_PICS[i]}" -resize $THUMB_SIZE \
4128
"$WORK_DIR/pics/$i/000001.$IMG_FMT"
4129
done
4130
fi
4131
-# overlay menu title and thumb titles on template
4132
+# overlay menu title and video titles on template
4133
if $MIST; then
4134
# overlay white.png onto background
4135
- echo "Overlaying the text mist on the background"
4136
+ print2log "Overlaying the text mist on the background"
4137
composite -dissolve $MIST_OPACITY -gravity $TITLE_GRAVITY \
4138
-geometry ${mist_xoffset}${mist_yoffset} \
4139
"$WORK_DIR/white.png" "$WORK_DIR/pics/template.png" \
4140
4141
sc_thumb_title_cmd=( "${sc_thumb_title_cmd[@]}" \
4142
"${THUMBTITLES_ARRAY[i]}" "$WORK_DIR/thumb_title${i}.png")
4143
done
4144
- echo "Running:
4145
- convert -size $VIDSIZE -background none "$WORK_DIR/pics/template.png"
4146
- ${sc_thumb_title_cmd[@]} -page +210+400 "$WORK_DIR/title_txt.png" \
4147
- -mosaic "$WORK_DIR/pics/template.png" "| format_output >> "$LOG_FILE"
4148
+ print2log "Running \
4149
+ convert -size $VIDSIZE -background none $WORK_DIR/pics/template.png \
4150
+ ${sc_thumb_title_cmd[@]} -page +210+400 $WORK_DIR/title_txt.png \
4151
+ -mosaic $WORK_DIR/pics/template.png"
4152
convert -size $VIDSIZE -background none "$WORK_DIR/pics/template.png" \
4153
${sc_thumb_title_cmd[@]} -mosaic "$WORK_DIR/pics/template.png"
4154
convert "$WORK_DIR/pics/template.png" "$WORK_DIR/title_txt.png" \
4155
4156
4157
# copy the preview for -quick-menu
4158
if $QUICK_MENU && [[ -s "$WORK_DIR/showcase_img.png" ]]; then
4159
- cp -v "$WORK_DIR/pics/template.png" "$WORK_DIR/quick_menu_bg.png"
4160
+ cp "$WORK_DIR/pics/template.png" "$WORK_DIR/quick_menu_bg.png"
4161
fi
4162
4163
# lets be sure of order by using a loop
4164
4165
##############################################################################
4166
4167
if $DO_BUTTONS; then
4168
- echo
4169
- echo "Creating the highlight and selection PNGs for the main menu"
4170
+ print2log "Creating the highlight and selection PNGs for the main menu"
4171
if [ "$BUTTON_STYLE" = "rect" ]; then
4172
MENU_BUTTON_SIZE=$THUMB_SIZE
4173
get_button_geo
4174
4175
# make sure coordinates are even
4176
((X0%2 && X0--)); ((Y0%2 && Y0--))
4177
((X1%2 && X1++)); ((Y1%2 && Y1++))
4178
- button_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\") #FIXME
4179
+ button_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\")
4180
btn_geos[i]=${button_geos[@]}
4181
unset button_geos
4182
echo \
4183
4184
echo text ${i},20 \'$i\'
4185
done >> "$WORK_DIR/grid2.mvg"
4186
fi
4187
-
4188
if $SHOWCASE && $DO_MENU; then
4189
if $SC_THUMB; then
4190
# find out where to put the showcase image/video in the X axis
4191
4192
fi
4193
$QUICK_MENU && \
4194
sc_width=${SHOWCASE_SIZE/x*} && sc_height=${SHOWCASE_SIZE/*x}
4195
- if $SC_THUMB || $QUICK_MENU; then #&& ! $TEXTMENU; then
4196
+ if $SC_THUMB || $QUICK_MENU; then
4197
if [[ "$SC_TITLE_ALIGN" = "center" ]]; then
4198
- if [[ $WIDEST_TITLE -ge ${THUMB_SIZE/x*} ]]; then
4199
- BUTTON_COLUMN1=$(((${THUMB_SIZE/x*} / 2) + (WIDEST_TITLE / 2)))
4200
+ if [[ $widest_title -ge ${THUMB_SIZE/x*} ]]; then
4201
+ BUTTON_COLUMN1=$(((${THUMB_SIZE/x*} / 2) + (widest_title / 2)))
4202
else
4203
BUTTON_COLUMN1=${THUMB_SIZE/x*}
4204
fi
4205
elif [[ "$SC_TITLE_ALIGN" = "west" ]]; then
4206
- if [[ $WIDEST_TITLE -ge ${THUMB_SIZE/x*} ]]; then
4207
- BUTTON_COLUMN1=$((WIDEST_TITLE + 5))
4208
+ if [[ $widest_title -ge ${THUMB_SIZE/x*} ]]; then
4209
+ BUTTON_COLUMN1=$((widest_title + 5))
4210
else
4211
BUTTON_COLUMN1=${THUMB_SIZE/x*}
4212
fi
4213
elif [[ "$SC_TITLE_ALIGN" = "east" ]]; then
4214
- BUTTON_COLUMN1=$(( ${THUMB_SIZE/x*} + WIDEST_TITLE ))
4215
+ BUTTON_COLUMN1=$(( ${THUMB_SIZE/x*} + widest_title ))
4216
fi
4217
- if ! $TEXTMENU; then
4218
- sc_space=$((${VIDSIZE%x*} - \
4219
- ${SC_THUMB_X_ARRAY[0]} - BUTTON_COLUMN1 - SAFE_AREA))
4220
- SC_X=$(( ${SC_THUMB_X_ARRAY[0]} + BUTTON_COLUMN1 \
4221
- + (sc_space / 2) - (sc_width / 2) ))
4222
- else
4223
- BUTTON_COLUMN1=$((WIDEST_TITLE + 5))
4224
+ # work out the general position of the showcase image
4225
+ # these will be modified later according to -align options
4226
+ # TODO it's already consolidated, now split in 1 vs 2 column if/else
4227
+ if $TEXTMENU; then
4228
+ # this is the default, *west aligned, for one column textmenu
4229
+ BUTTON_COLUMN1=$((widest_title + 5))
4230
sc_space=$((${VIDSIZE%x*} - \
4231
${SC_TITLES_X_ARRAY[0]} - BUTTON_COLUMN1 - SAFE_AREA))
4232
SC_X=$(( ${SC_TITLES_X_ARRAY[0]} + BUTTON_COLUMN1 \
4233
+ (sc_space / 2) - (sc_width / 2) ))
4234
if [[ $BUTTON_GRAVITY = *east* ]]; then
4235
- BUTTON_COLUMN1=$WIDEST_TITLE
4236
+ BUTTON_COLUMN1=$widest_title
4237
sc_space=$((${VIDSIZE%x*} - (SAFE_AREA * 2) - BUTTON_COLUMN1))
4238
SC_X=$((SAFE_AREA + (sc_space / 2) - (sc_width / 2) ))
4239
fi
4240
+ center_showcase_pos=$(( (${VIDSIZE/x*} / 2) - (sc_width / 2) ))
4241
+ # this next block is *east or *west for 2 columns, and N|S|Center
4242
+ case $BUTTON_GRAVITY in
4243
+ *east|*west)
4244
+ # for 2 columns the showcase thumb will always be centered
4245
+ [[ -n $tt_ygeos_col2 ]] && SC_X=$center_showcase_pos
4246
+ ;;
4247
+ north|south|center)
4248
+ # for centered 1 column the showcase has no room, so center it
4249
+ # these -align args have no effect on 2 column titles position
4250
+ SC_X=$center_showcase_pos
4251
+ ;;
4252
+ esac
4253
+ else
4254
+ sc_space=$((${VIDSIZE%x*} - \
4255
+ ${SC_THUMB_X_ARRAY[0]} - BUTTON_COLUMN1 - SAFE_AREA))
4256
+ SC_X=$(( ${SC_THUMB_X_ARRAY[0]} + BUTTON_COLUMN1 \
4257
+ + (sc_space / 2) - (sc_width / 2) ))
4258
+ if ((V_TOTAL > 5)); then
4259
+ # for 2 columns just center the thumb between edges of columns
4260
+ inner_edge_col1=$(( ${SC_THUMB_X_ARRAY[0]} + ${THUMB_SIZE/x*} ))
4261
+ inner_edge_col2=${SC_THUMB_X_ARRAY[SPLIT]}
4262
+ canvas=$(( (inner_edge_col2 - inner_edge_col1) / 2 ))
4263
+ canvas=$(( inner_edge_col1 + canvas ))
4264
+ SC_X=$(( canvas - (sc_width / 2) ))
4265
+ fi
4266
fi
4267
- # find out where to put the showcase image in the Y axis
4268
+ # work out the position of the showcase image in the Y axis
4269
if ! $TEXTMENU; then
4270
Y1=${SC_THUMB_Y_ARRAY[0]}
4271
Y2=${SC_THUMB_Y_ARRAY[NUM_FILES]}
4272
4273
4274
fi
4275
4276
- ! $TEXTMENU && [[ $V_TOTAL -gt 5 ]] && \
4277
- SC_X=$(( ( ${VIDSIZE/x*} / 2 ) - (sc_width / 2) ))
4278
- $TEXTMENU && [[ -n $tt_ygeos_col2 ]] \
4279
- && SC_X=$(( ( ${VIDSIZE/x*} / 2 ) - (sc_width / 2) ))
4280
- $USER_SC_GEO && SC_X=${SHOWCASE_GEO/x*}
4281
- $USER_SC_GEO && SC_Y=${SHOWCASE_GEO/*x}
4282
-
4283
# make sure its divisible by 2 for ffmpeg's padding with -quick-menu
4284
if $QUICK_MENU; then
4285
SC_Y=$(( (SC_Y /2) * 2 ))
4286
SC_X=$(( (SC_X / 2) * 2 ))
4287
fi
4288
+ # finally if user passes in a prefered location for showcase, use it
4289
+ $USER_SC_GEO && SC_X=$(awk -F+ '{print $2}' <<< $SHOWCASE_GEO)
4290
+ $USER_SC_GEO && SC_Y=$(awk -F+ '{print $3}' <<< $SHOWCASE_GEO)
4291
+
4292
+ # make the -page part of the IM command for the showcase image
4293
SC_IMG_PAGE="-page +$SC_X+$SC_Y"
4294
SC_IMG_CMD="$SC_IMG_PAGE "$WORK_DIR/showcase_img.png""
4295
fi
4296
4297
IM_CMD3=(convert - -background none $WORK_DIR/title_txt.png \
4298
-gravity $TITLE_GRAVITY -geometry \
4299
${title_xoffset}${title_yoffset} -composite "$PREVIEW_IMG" )
4300
- echo "Running ${IM_CMD0[@]} miff:- | ${IM_CMD1[@]} miff:- |
4301
- ${IM_CMD2[@]} miff:- | ${IM_CMD3[@]}" |format_output >> "$LOG_FILE"
4302
+ print2log "Running ${IM_CMD0[@]} miff:- | ${IM_CMD1[@]} miff:- | \
4303
+ ${IM_CMD2[@]} miff:- | ${IM_CMD3[@]}"
4304
"${IM_CMD0[@]}" miff:- | "${IM_CMD1[@]}" miff:- |
4305
"${IM_CMD2[@]}" miff:- | "${IM_CMD3[@]}"
4306
else
4307
IM_CMD=(convert -size $VIDSIZE "$WORK_DIR/pics/template.png" \
4308
-background none ${sc_cmd[@]} $SC_IMG_CMD \
4309
-mosaic "$PREVIEW_IMG")
4310
- echo "Running ${IM_CMD[@]}" |format_output >> "$LOG_FILE"
4311
+ print2log "Running ${IM_CMD[@]}"
4312
"${IM_CMD[@]}"
4313
fi
4314
unset sc_cmd IM_CMD05 IM_CMD04 IM_CMD03 IM_CMD4
4315
4316
IM_CMD3=(convert - -background none "$WORK_DIR/title_txt.png" \
4317
-gravity $TITLE_GRAVITY -geometry ${title_xoffset}${title_yoffset} \
4318
-composite "$PREVIEW_IMG")
4319
- echo "Running ${IM_CMD1[@]} | ${IM_CMD2[@]} | ${IM_CMD3[@]}" |
4320
- format_output >> "$LOG_FILE"
4321
+ print2log "Running ${IM_CMD1[@]} | ${IM_CMD2[@]} | ${IM_CMD3[@]}"
4322
"${IM_CMD1[@]}" | "${IM_CMD2[@]}" | "${IM_CMD3[@]}"
4323
else # Not transparent
4324
IM_CMD1=(montage ${PICS[@]} $MTG_FRM -tile ${TILE_ARRAY[NUM_FILES]} \
4325
4326
"$WORK_DIR/title_txt.png" -gravity $TITLE_GRAVITY \
4327
-geometry ${title_xoffset}${title_yoffset} -composite - -gravity \
4328
$BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} -composite "$PREVIEW_IMG")
4329
- echo "Running ${IM_CMD1[@]} | ${IM_CMD1[@]}" |
4330
- format_output >> "$LOG_FILE"
4331
+ print2log "Running ${IM_CMD1[@]} | ${IM_CMD2[@]}"
4332
"${IM_CMD1[@]}" | "${IM_CMD2[@]}"
4333
fi
4334
fi
4335
4336
IM_CMD2=(convert - -background none "$WORK_DIR/title_txt.png" \
4337
-gravity $TITLE_GRAVITY -geometry ${title_xoffset}${title_yoffset} \
4338
-composite "${add_playbtn[@]}" "$PREVIEW_IMG" )
4339
- echo "Running ${IM_CMD1[@]} | ${IM_CMD1[@]}" | format_output >> "$LOG_FILE"
4340
+ print2log "Running ${IM_CMD1[@]} | ${IM_CMD2[@]}"
4341
"${IM_CMD1[@]}" | "${IM_CMD2[@]}"
4342
fi
4343
# if there is quickmenu bg, cut out transparent hole for showcase image/video
4344
4345
# make a similar framed blank to composite onto the background
4346
frame_cmd=(convert -size $SHOWCASE_SIZE xc:black \
4347
$SHOWCASE_FRAME "$WORK_DIR/showcase_frame.png")
4348
- yecho "Running ${frame_cmd[@]}" | format_output >> "$LOG_FILE"
4349
- "${frame_cmd[@]}" >> "$LOG_FILE"
4350
+ print2log "Running ${frame_cmd[@]}"
4351
+ "${frame_cmd[@]}" | pipe2log convert
4352
# composite the framed blank onto background subtracting the width \
4353
# of the frame (border) when calculating XxY geometry
4354
convert "$WORK_DIR/pics/template.png" \
4355
4356
echo "(Press 'q' or ESC in the preview window to close it.)"
4357
fi
4358
# make the fake montage with highlighted 1st button and display it
4359
-if $DO_MENU && ! $SINGLE_SLIDESHOW; then #FIXME ?
4360
+if $DO_MENU && ! $SINGLE_SLIDESHOW; then
4361
composite -compose Over "$WORK_DIR/fake_montage.png" \
4362
"$PREVIEW_IMG" "$PREVIEW_IMG"
4363
fi
4364
4365
if [[ -n "$BG_AUDIO" ]]; then
4366
yecho "Getting length of bg audio"
4367
$SINGLE_SLIDESHOW && end_pos="" || end_pos=${MENU_LEN[MENU_NUM-1]}
4368
- BG_AUDIOLENGTH=$(audio_length "$BG_AUDIO")
4369
+ BG_AUDIOLENGTH=$(stream_length "$BG_AUDIO" audio)
4370
4371
# make sure user isn't trying to get a longer menu than the audio allows
4372
if [[ $(bc <<< "${MENU_LEN[MENU_NUM-1]} \
4373
4374
# to make sure files get symlinked properly (Hack)
4375
if [[ $MENU_NUM = [1-2] || -n ${file_is_image[@]} ]]; then
4376
if ! $MK_CAROUSEL_MODE; then
4377
- echo
4378
check_compliance
4379
$GROUPING && check_compliance group
4380
fi
4381
4382
done
4383
fi
4384
fi
4385
-echo
4386
4387
# animated slideshows join the slides and can add audio (-bgaudio)
4388
if $DO_CAROUSEL && ! $USE_DVD_SLIDESHOW; then
4389
4390
fi
4391
done
4392
done
4393
- IMGENC_CMD=(ffmpeg -f yuv4mpegpipe -r $FRAME_RATE -i - -s $VIDSIZE \
4394
- $SS_FFMOPTS -r $FRAME_RATE -bf 2 -y "$WORK_DIR/slideshow.m2v")
4395
- echo
4396
+ IMGENC_CMD=($FFmpeg -f yuv4mpegpipe -i - $VF scale=${VF_SCALE},${ASPECT} \
4397
+ $SS_FFMOPTS -r $ff_frame_rate -bf 2 -y "$WORK_DIR/slideshow.m2v")
4398
for p in ${!MIX_IN[@]}; do
4399
if [[ "${F2BIN[p]}" = "yes" ]]; then
4400
BINNING_CMD=(convert "${MIX_IN[p]}" -depth 8 \
4401
4402
MIX_IN[p]="$WORK_DIR/${p}.ppm"
4403
fi
4404
done
4405
- echo
4406
+ printf "\n\n" | tee -a "$LOG_FILE"
4407
sstime1=$(date +%s)
4408
# make a fifo to send raw yuv to, to be encoded by ffmpeg
4409
mkfifo "$WORK_DIR/ppm.fifo"
4410
- "${IMGENC_CMD[@]}" 2>/dev/null < "$WORK_DIR/ppm.fifo" &
4411
+ print2log "Running ${IMGENC_CMD[@]}"
4412
+ "${IMGENC_CMD[@]}" < "$WORK_DIR/ppm.fifo" 2>&1 | \
4413
+ pipe2log ${FFmpeg##*/} &
4414
+ #"${IMGENC_CMD[@]}" 2>/dev/null < "$WORK_DIR/ppm.fifo" &
4415
encpids="$encpids $!"
4416
#exec 3> "$WORK_DIR/ppm.fifo"
4417
4418
4419
fi
4420
# encode still frames
4421
# need yuvcorrect if for fade style (remove headers)
4422
- [[ $EFFECT = "fade" ]] && YUVCORRECT="yuvcorrect -T NO_HEADER"
4423
+ [[ $EFFECT = "fade" ]] && YUVCORRECT="$yuv_correct"
4424
if [[ $EFFECT = "crossfade" ]]; then
4425
# encoding 1st slide
4426
if ((f==0)); then
4427
YUVCORRECT="cat"
4428
else # subsequent slides and fades need header removed
4429
- YUVCORRECT="yuvcorrect -T NO_HEADER"
4430
+ YUVCORRECT="$yuv_correct"
4431
fi
4432
fi
4433
spin "Doing stills for slide $((f+1))" >&2
4434
"${TOYUV_STILLS_CMD[@]}" "${MIX_IN[f]}" 2>/dev/null |
4435
$YUVCORRECT 2> /dev/null
4436
# now we need yuvcorrect for everything
4437
- YUVCORRECT="yuvcorrect -T NO_HEADER"
4438
+ YUVCORRECT="$yuv_correct"
4439
# do a transition to the next slide
4440
[[ $EFFECT = "fade" ]] && fadetype=fadeout || fadetype="crossfade"
4441
spin "Doing $fadetype for slide $((f+1))" >&2
4442
4443
if $MK_CAROUSEL_MODE; then
4444
# move the m2v to BASEDIR (basedir of -carousel_menu_mode)
4445
echo
4446
- mv -v "$WORK_DIR/slideshow.m2v" "$BASEDIR/carousel-${CAROUSEL_NUM}.m2v"
4447
+ mv "$WORK_DIR/slideshow.m2v" "$BASEDIR/carousel-${CAROUSEL_NUM}.m2v"
4448
cleanup
4449
exit 0
4450
fi
4451
4452
# get length
4453
- bgaudio_time=$(vid_length "$WORK_DIR/slideshow.m2v")
4454
+ bgaudio_time=$(stream_length "$WORK_DIR/slideshow.m2v" m2v)
4455
4456
if [[ -n $BG_AUDIO ]]; then
4457
# convert background audio to wav
4458
- BGAUDIO_CMD=(ffmpeg -i "$BG_AUDIO" -t $bgaudio_time -ar 48000 \
4459
+ BGAUDIO_CMD=($FFmpeg -i "$BG_AUDIO" -t $bgaudio_time -ar 48000 \
4460
-acodec pcm_s16le -y $WORK_DIR/slideshow.wav)
4461
else
4462
# generate silence
4463
- BGAUDIO_CMD=(ffmpeg -f s16le -ar 48000 -t $bgaudio_time -i /dev/zero
4464
- -ar 48000 -ac 2 -acodec pcm_s16le -y $WORK_DIR/slideshow.wav)
4465
+ BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero -ar 48000 \
4466
+ -ac 2 -t $bgaudio_time -acodec pcm_s16le -y $WORK_DIR/slideshow.wav)
4467
fi
4468
echo
4469
- echo "Encoding audio to wav with: ${BGAUDIO_CMD[@]}" | format_output |
4470
- tee -a "$LOG_FILE"
4471
+ echo "Encoding audio to wav with: ${BGAUDIO_CMD[@]}" | format_output | \
4472
+ pipe2log
4473
echo
4474
- "${BGAUDIO_CMD[@]}" >> "$LOG_FILE" 2>&1
4475
+ "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
4476
# fade wav if background audio used and user did not disable fading
4477
if [[ -n $BG_AUDIO ]] && $AUDIO_FADE; then
4478
sox "$WORK_DIR/slideshow.wav" "$WORK_DIR/slideshow-faded.wav" \
4479
4480
fi
4481
4482
# convert the wav to target format
4483
- echo
4484
echo "Converting wav to $TARGET format"
4485
- BGAUDIO_CMD=(ffmpeg -i "$WORK_DIR/slideshow.wav" \
4486
- $AUDIO_OPTS -y "$WORK_DIR/slideshow.ac3")
4487
- echo "Runnning ${BGAUDIO_CMD[@]}" | tee -a "$LOG_FILE"
4488
- "${BGAUDIO_CMD[@]}" | format_output >> "$LOG_FILE" 2>&1
4489
echo
4490
+ BGAUDIO_CMD=($FFmpeg -i "$WORK_DIR/slideshow.wav" \
4491
+ $AUDIO_OPTS -y "$WORK_DIR/slideshow.ac3")
4492
+ print2log "Runnning ${BGAUDIO_CMD[@]}"
4493
+ "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
4494
# multiplex to mpeg-2 ( svcd or dvd )
4495
MPLEX_CMD=(mplex -V -f $MPLEX_FORMAT -o "$WORK_DIR/slideshow.mpg" \
4496
"$WORK_DIR/slideshow.$AUDIO_EXT" "$WORK_DIR/slideshow.m2v")
4497
- yecho
4498
- echo "Running ${MPLEX_CMD[@]}" |format_output |tee -a "$LOG_FILE"
4499
- "${MPLEX_CMD[@]}" |format_output >> "$LOG_FILE" 2>&1
4500
- yecho
4501
+ print2log "Running ${MPLEX_CMD[@]}"
4502
+ "${MPLEX_CMD[@]}" 2>&1 | pipe2log mplex
4503
if [[ -s "$WORK_DIR/slideshow.mpg" ]]; then
4504
mv "$WORK_DIR/slideshow.mpg" "$WORK_DIR/intro.mpg"
4505
else
4506
4507
"${SS_AUDIO[@]}" -f "$WORK_DIR/dvd-slideshow.conf"
4508
mv "$WORK_DIR/slideshow.vob" "$WORK_DIR/intro.mpg"
4509
fi
4510
-# check bgvideo and showcase VIDEO for compliance ( if present ) #FIXME
4511
+# check bgvideo and showcase VIDEO for compliance ( if present )
4512
if [[ -n $BG_VIDEO && $BG_VIDEO = $BG_AUDIO ]]; then
4513
# do not reencode animated slideshow made in MK_CAROUSEL_MODE
4514
if ! [[ $BG_VIDEO = $WORK_DIR/carousel-00.m2v ]]; then
4515
4516
4517
# symlink IN_FILES in $WORK_DIR to solve some quoting issues for dvdauthor
4518
if [[ $MENU_NUM -eq 1 ]]; then
4519
- yecho "Symlinking files to $WORK_DIR"
4520
+ print2log "Symlinking files to $WORK_DIR"
4521
for i in ${!IN_FILES[@]}; do
4522
if ! [[ -e $BASEDIR/${TSET_NUM}-$((i+1)).mpg ]]; then
4523
(cd "$REAL_WORK_DIR" && ln -sf "${IN_FILES[i]}" \
4524
4525
$SINGLE_SLIDESHOW && echo "Getting stats on the slides now"
4526
for ((i=0; i<${#IN_FILES[@]}; i++)); do
4527
if [[ $MENU_NUM -eq 1 ]]; then
4528
- ! $SINGLE_SLIDESHOW && spin "Getting stats on ${IN_FILES[i]}"
4529
- idvid_stats[i]=$(idvid -terse -accurate "${IN_FILES[i]}" 2>/dev/null)
4530
+ ! $SINGLE_SLIDESHOW && \
4531
+ spin "getting stats for the log" $SPINNER #on ${IN_FILES[i]##*/}"
4532
+ idvid_stats[i]=$(idvid -terse -accurate "${IN_FILES[i]}" 2> /dev/null)
4533
fi
4534
if [ -s "${IN_FILES[i]}.nav_log" ]; then
4535
length[i]=$(awk 'END{print NR}' "${IN_FILES[i]}.nav_log")
4536
4537
done
4538
4539
if $GROUPING && [[ $MENU_NUM -eq 1 ]]; then
4540
- echo
4541
- echo ". . . Getting stats on grouped files now . . ."
4542
- echo
4543
+ print2log ". . . Getting stats on grouped files now . . ."
4544
for u in ${!grouping[@]}; do
4545
CUR_VID=$(readlink -f "${grouping[u]}")
4546
- spin "Getting stats on "${CUR_VID##*/}""
4547
- group_idvid_stats[u]=$(idvid -terse -accurate "$CUR_VID" 2>/dev/null)
4548
+ spin "Getting grouped video stats for the log on "${CUR_VID##*/}""
4549
+ group_idvid_stats[u]=$(idvid -terse -accurate "$CUR_VID" 2> /dev/null)
4550
if [ -s "$CUR_VID.nav_log" ]; then
4551
group_length[u]=$(awk 'END{print NR}' "$CUR_VID.nav_log")
4552
fi
4553
done
4554
echo
4555
fi
4556
+#echo -e "\nCheck the stats in todisc.log if you wish"
4557
4558
# get length of videos in a separate loop from other stats
4559
# if we are doing SVCD there will be no nav_seek file
4560
4561
# if we have a non empty nav_log get the length from that
4562
if [ -s "${IN_FILES[i]}".nav_log ]; then
4563
VID_LEN[i]=$(bc_math "${length[i]} / $FRAME_RATE")
4564
- else # otherwise, we run mencoder to get the length
4565
- VID_LEN[i]=$(vid_length "${IN_FILES[i]}" )
4566
+ else # otherwise, we run ffmpeg to get the length
4567
+ VID_LEN[i]=$(stream_length "${IN_FILES[i]}" )
4568
fi
4569
if [[ ${VID_LEN[i]%.*} -lt ${SEEK_VAL[i]%.*} ]]; then
4570
usage_error "A seek of ${SEEK_VAL[i]} seconds is too large for
4571
4572
# if we have a value for ${group_length[g]} get the length from that
4573
if [[ -n "${group_length[g]}" ]]; then
4574
GROUP_VID_LEN[g]=$(bc_math "${group_length[g]} / $FRAME_RATE")
4575
- else # otherwise, we run mencoder to get the length
4576
- GROUP_VID_LEN[g]=$(vid_length "${grouping[g]}")
4577
+ else # otherwise, we run stream_length to get the length
4578
+ GROUP_VID_LEN[g]=$(stream_length "${grouping[g]}")
4579
fi
4580
done
4581
if $GROUPING; then
4582
index=0
4583
for i in "${!IN_FILES[@]}"; do
4584
- if [[ ${GROUP[i]} ]]; then
4585
+ if [[ ${GROUP_ARR[i]} ]]; then
4586
iter=( $BASEDIR/${TSET_NUM}-group-$((i+1))-*.mpg )
4587
for ((t=index; t<index+${#iter[@]}; t++)); do
4588
# get lengths of group videos also in a seperate loop
4589
4590
# put in the log file in case anyone is interested
4591
if ! $VMGM_ONLY && [[ $MENU_NUM -eq 1 ]] && $DO_STATS; then
4592
get_stats files
4593
- echo
4594
+ print2log ""
4595
fi
4596
if ! $VMGM_ONLY && [[ $MENU_NUM -eq 1 ]] && $GROUPING && $DO_STATS; then
4597
get_stats group
4598
- echo; echo $SEPARATOR
4599
+ print2log ""
4600
fi
4601
-echo
4602
4603
# run quick_menu to create an almost finished menu file ( intro.m2v )
4604
$QUICK_MENU && quick_menu
4605
# if doing switched menus, use the bgaudio from each video
4606
# unless "none" is passed for -bgaudio
4607
if $SWITCHED; then
4608
- yecho
4609
+ yecho ""
4610
let vid=MENU_NUM-1
4611
SHOWCASE_SEEK_VAL=${SEEK_VAL[vid]}
4612
# use silence if a short file ( probably a slide ) and no background audio
4613
4614
# the menu audio will be the same length as the switched video
4615
fi
4616
yecho "Using audio from "${FILES[vid]}" for the audio background,"
4617
- ! $STATIC && yecho \
4618
- "using the same seek value for the audio as the video"
4619
- yecho "If you wish to use silence for the switched menu,"
4620
- yecho "use '-bgaudio none'"
4621
+ ! $STATIC && info_message "using the same seek value for the audio \
4622
+ as the video. If you wish to use silence for the switched menu,
4623
+ use '-bgaudio none'"
4624
else
4625
if [[ $BG_AUDIO = "none" ]]; then # no audio if -bgaudio none
4626
BG_AUDIO=""
4627
4628
fi
4629
fi
4630
fi
4631
- yecho
4632
+ yecho ""
4633
fi
4634
for ((i=0; i<${#VID_LEN[@]}; i++)); do
4635
NEW_LENGTH=( ${NEW_LENGTH[@]} ${VID_LEN[i]%.*} )
4636
4637
$WORK_DIR/pics/$i/$(printf "%06d%s" $p .png) 2>/dev/null
4638
done
4639
elif [[ ${file_is_image[i]} = "yes" ]]; then
4640
- spin "Convert ${FILES[i]} to proper size/format"
4641
+ spin "Convert ${FILES[i]##*/} to proper size/format"
4642
convert "${FILES[i]}" -depth 8 \
4643
-resize ${THUMB_SIZE}! \
4644
"$WORK_DIR/pics/$i/$(printf "%06d%s" 0 .${IMG_FMT})"
4645
4646
thumb_frames=$THUMB_FRAMES
4647
fi
4648
# warning to ignore transcode error messages
4649
- print_tcode_info
4650
+ $use_transcode && print_tcode_info
4651
if [ -s "${IN_FILES[i]}.nav_log" ]; then
4652
NAV_SEEK[i]="--nav_seek"
4653
NAVSEEK[i]=${IN_FILES[i]}.nav_log
4654
fi
4655
- yuv_fifo="$WORK_DIR/pics/$i/out.yuv"
4656
- log_tmp="$WORK_DIR/pics/$i/log.tmp"
4657
- [[ ! -p "$yuv_fifo" ]] && mkfifo "$yuv_fifo"
4658
+ ff_log_tmp="$WORK_DIR/pics/$i/ff_log.tmp"
4659
+ tc_log_tmp="$WORK_DIR/pics/$i/tc_log.tmp"
4660
+ if $use_transcode; then
4661
+ vid_stream="$WORK_DIR/pics/$i/out.yuv"
4662
+ [[ ! -p "$vid_stream" ]] && mkfifo "$vid_stream"
4663
+ ff_seek=""
4664
+ ff_frames=""
4665
+ else
4666
+ # using ffmpeg directly on file, PIPE_FORMAT not needed
4667
+ vid_stream="${IN_FILES[i]}"
4668
+ unset PIPE_FORMAT
4669
+ ff_seek="-ss ${SEEK_VAL[i]}"
4670
+ ff_frames="-vframes $thumb_frames"
4671
+ fi
4672
+
4673
# resize using ffmpeg instead of transcode
4674
- FFMPEG_CMD2=(ffmpeg $PIPE_FORMAT -i "$yuv_fifo" -f image2 -s $THUMB_SIZE -y \
4675
- "$WORK_DIR/pics/$i/%06d.$IMG_FMT")
4676
+ FFMPEG_CMD2=($FFmpeg $PIPE_FORMAT -i "$vid_stream" $ff_seek \
4677
+ $ff_frames -f image2 $VF scale=${THUMB_SIZE%x*}:${THUMB_SIZE#*x} \
4678
+ -y "$WORK_DIR/pics/$i/%06d.$IMG_FMT")
4679
TRANSCODE_CMD2=(transcode --progress_rate 10 \
4680
--write_pid $WORK_DIR/tcode$i.pid -q 1 -i "${IN_FILES[i]}" \
4681
-c ${SEEK_FRAMES[i]}-$((${SEEK_FRAMES[i]} + $thumb_frames)) \
4682
- ${NAV_SEEK[i]} "${NAVSEEK[i]}" -o "$yuv_fifo" \
4683
+ ${NAV_SEEK[i]} "${NAVSEEK[i]}" -o "$vid_stream" \
4684
-f $FRAME_RATE $EXPORT)
4685
- yecho "Running ${TRANSCODE_CMD2[@]}" | fold -bs
4686
- yecho "Running ${FFMPEG_CMD2[@]}" | fold -bs
4687
- "${TRANSCODE_CMD2[@]}" 2>&1 | strings >> "$LOG_FILE" &
4688
- "${FFMPEG_CMD2[@]}" > "$log_tmp" 2>&1 &
4689
+ if $use_transcode; then
4690
+ print2log "Running ${TRANSCODE_CMD2[@]}"
4691
+ "${TRANSCODE_CMD2[@]}" 2>&1 | pipe2log transcode &
4692
+ fi
4693
+ print2log "Running ${FFMPEG_CMD2[@]}"
4694
+ "${FFMPEG_CMD2[@]}" > "$ff_log_tmp" 2>&1 &
4695
ffm_pid=$!
4696
- wait_for "$WORK_DIR/tcode$i.pid"
4697
- TRANSCODE_PID=$(<$WORK_DIR/tcode$i.pid)
4698
- tcode_pids="$tcode_pids $TRANSCODE_PID"
4699
+ if $use_transcode; then
4700
+ wait_for "$WORK_DIR/tcode$i.pid"
4701
+ tcode_pids="$tcode_pids $(<$WORK_DIR/tcode$i.pid)"
4702
+ fi
4703
if [[ -n "$ffm_pid" ]]; then
4704
wait_for "$WORK_DIR/pics/$i/000001.$IMG_FMT"
4705
while ps -p $ffm_pid >/dev/null; do
4706
4707
awk -F / '{ field = $NF }; END{ print field }')
4708
spin "Seeking in video and creating images: $last_image"
4709
done
4710
- wait # wait for ffmpeg and transcode to finish
4711
+ # wait for ffmpeg and transcode to finish
4712
+ wait $ffm_pid # get exit code of ffmpeg
4713
+ if (($? != 0)); then
4714
+ cat "$ff_log_tmp" | sed '/time=10000000000.00/d' | pipe2log ${FFmpeg##*/}
4715
+ rm -f "$ff_log_tmp"
4716
+ runtime_error \
4717
+ "Problem with ${FFmpeg##*/} while creating images from video"
4718
+ fi
4719
+ if $use_transcode; then
4720
+ wait $(<$WORK_DIR/tcode$i.pid)
4721
+ # get exit code of transcode
4722
+ if (($? != 0)); then
4723
+ runtime_error \
4724
+ "Problem with transcode while creating images from video"
4725
+ fi
4726
+ fi
4727
# get the largest image if static menu(we made 9)
4728
# get largest image of 9 if static menu and not -frame-safe
4729
if $STATIC && $FRAME_SAFE; then
4730
largest=$(get_largest 6 $V_FRAMES "$WORK_DIR/pics/$i/")
4731
- # remove the unused images after saving the largest as 1st
4732
+ # remove unused images after saving the largest as 1st
4733
mv "$largest" "$WORK_DIR/pics/$i/000001.$IMG_FMT" 2>/dev/null
4734
rm -f "$WORK_DIR"/pics/$i/00000{2..9}.png
4735
fi
4736
4737
((numpics > ani_pics)) && ani_pics=$numpics
4738
# append ffmpeg output to the log
4739
echo -e \
4740
- "\n$ME Log from ffmpeg (processing transcode stream)\n" \
4741
+ "\n$ME Log from ${FFmpeg##*/} (processing video stream)\n" \
4742
>> "$LOG_FILE"
4743
- strings "$log_tmp" | sed '/time=10000000000.00/d' >> "$LOG_FILE"
4744
- rm -f "$log_tmp"
4745
+ cat "$ff_log_tmp" | sed '/time=10000000000.00/d' | pipe2log ${FFmpeg##*/}
4746
+ rm -f "$ff_log_tmp"
4747
echo
4748
- echo "Created $numpics images of $THUMB_FRAMES"
4749
+ echo -n "Created $numpics images of $THUMB_FRAMES"
4750
+ echo -ne "\r$(printf %60s)" # print spaces to overwrite previous line
4751
else
4752
runtime_error "Problem creating images from the video."
4753
fi
4754
4755
fi
4756
# copy 000001 image to 000000 as we use 0 based counting (transcode)
4757
# TODO transition to using "1" based' images as we use ffmpeg now
4758
- cp "$WORK_DIR/pics/$i/000001.$IMG_FMT" "$WORK_DIR/pics/$i/000000.$IMG_FMT"
4759
- last=$(find $WORK_DIR/pics/$i -maxdepth 1 -name \*.$IMG_FMT | \
4760
- sort | awk 'END{print}')
4761
- rm -f "$last"
4762
+ [[ -s "$WORK_DIR/pics/$i/000001.$IMG_FMT" ]] && cp \
4763
+ "$WORK_DIR/pics/$i/000001.$IMG_FMT" "$WORK_DIR/pics/$i/000000.$IMG_FMT"
4764
+ dir_cnt=$(find "$WORK_DIR/pics/$i" -maxdepth 1 -name "*.$IMG_FMT" |wc -l)
4765
+ if ((dir_cnt > 1)); then
4766
+ last=$(find $WORK_DIR/pics/$i -maxdepth 1 -name \*.$IMG_FMT | \
4767
+ sort | awk 'END{print}')
4768
+ rm -f "$last"
4769
+ fi
4770
done
4771
fi
4772
# create the pics for background image
4773
4774
if $SUB_MENU; then
4775
for ((s=0; s<=NUM_FILES; s++)); do
4776
if ! ${SLIDESHOW[s]}; then
4777
- echo
4778
- echo "Creating highlight and select PNGs for submenu $((s + 1))"
4779
+ print2log "Creating highlight and select PNGs for submenu $((s + 1))"
4780
C=$((${CHAPTERS[s]} - 1))
4781
MENU_BUTTON_SIZE=${GEO_ARRAY[C]}
4782
get_button_geo
4783
4784
echo
4785
for ((i=0; i<=NUM_FILES; i++)); do
4786
! ${SLIDESHOW[i]} && \
4787
- echo -e "Chapters for "${IN_FILES[i]}" are: \n"${CHAPT_ARRAY[i]}"\n"
4788
+ echo -e "Chapters for "${IN_FILES[i]}" are: \n"${CHAPT_ARRAY[i]}"\n" | \
4789
+ pipe2log
4790
done
4791
fi
4792
# get button coordinates if text-rect buttons (showcase menu only)
4793
4794
fi
4795
if ((i==NUM_FILES+2)); then # quick-nav assumes titlesets
4796
# VMGM_MENU means NOT -no-vmgm
4797
- if $VMGM_MENU && $PLAYALL && ! $VMGM_ONLY; then #DEBUG
4798
+ if $VMGM_MENU && $PLAYALL && ! $VMGM_ONLY; then
4799
echo -n " <button name=\"$i\" ${btn_geos[i-1]} "
4800
echo -e "up=\"$((i-1))\" down=\"$((i+1))\"/>"
4801
echo -e " <button name=\"$((i+1))\" ${btn_geos[i]} $down/>"
4802
4803
fi
4804
else
4805
for ((i=1; i<=NUM_BUTTONS; i++)); do
4806
- if $SHOWCASE && [[ $NUM_FILES -ge $SPLIT ]]; then
4807
+ if $SHOWCASE && ((NUM_FILES >= SPLIT)); then
4808
if ((i>SPLIT)) && ((i<NUM_BUTTONS)); then
4809
left="left=\"$((i-SPLIT))\""; right=""
4810
elif (( i<=SPLIT)) && (( (i+SPLIT) <= (NUM_FILES+1) )); then
4811
4812
if [[ -n $AUDIO_CHANNEL ]]; then
4813
echo "${VOB_PRE[i]}"
4814
fi
4815
- if [[ -n ${GROUP[i]} ]]; then
4816
+ if [[ -n ${GROUP_ARR[i]} ]]; then
4817
((MENU_NUM == 1 && ${CHAPTERS[i]} != 0)) && get_group_chapters $i format
4818
if ((${nochapt[i]})); then
4819
! ${SLIDESHOW[i]} && echo -e \
4820
" <vob file=\"$BASEDIR/${TSET_NUM}-$((i+1)).mpg\" $vid_pause/>"
4821
- for ((m=1; m<=$((${GROUP[i]})); m++)); do
4822
+ for ((m=1; m<=$((${GROUP_ARR[i]})); m++)); do
4823
mpg="$BASEDIR/${TSET_NUM}-group-$((i+1))-${m}.mpg"
4824
[[ -e $mpg ]] && \
4825
echo -e " <vob file=\"$mpg\" $grp_vid_pause/>"
4826
4827
else
4828
! ${SLIDESHOW[i]} && echo -e \
4829
" <vob file=\"$BASEDIR/${TSET_NUM}-$((i+1)).mpg\" $chpts0 $vid_pause/>"
4830
- for ((m=1; m<=$((${GROUP[i]})); m++)); do
4831
+ for ((m=1; m<=$((${GROUP_ARR[i]})); m++)); do
4832
mpg="$BASEDIR/${TSET_NUM}-group-$((i+1))-${m}.mpg"
4833
[[ -e $mpg ]] && echo -e \
4834
" <vob file=\"$mpg\" ${chpts[++j]} $grp_vid_pause/>"
4835
4836
4837
# make dummy VMGM mpeg
4838
if ! $TITLESET_MODE && ! $DO_TITLESETS; then
4839
+ yecho "Creating a blank mpeg for the vmgm menu"
4840
make_dummy
4841
fi
4842
# do submenu 1st for debug purposes
4843
4844
yecho
4845
yecho "Building submenus"
4846
yecho
4847
- yecho "Creating images for each chapter"
4848
+ print2log "Creating images for each chapter"
4849
if [ -z "$SM_TITLES" ]; then
4850
if $MULTILINE_TITLE; then
4851
for i in ${!TITLES[@]}; do
4852
4853
# Audio and no -submenu-length given: full length of the audio file
4854
if $SUBMENU_AUDIO; then
4855
if [[ -n $SM_AUDIO_FILE ]]; then
4856
- SM_AUDIOLEN=$(audio_length "$SM_AUDIO_FILE")
4857
+ SM_AUDIOLEN=$(stream_length "$SM_AUDIO_FILE" audio)
4858
fi
4859
for ((i=0; i<=NUM_FILES; i++)); do
4860
[[ -n $SM_AUDIO_FILE ]] && SUBMENU_AUDIOLEN[i]=$SM_AUDIOLEN
4861
4862
if ${SLIDESHOW[i]}; then
4863
yecho
4864
spin "getting length of ${SM_AUDIO[i]} "
4865
- SUBMENU_AUDIOLEN[i]=$(audio_length "${SM_AUDIO[i]}")
4866
+ SUBMENU_AUDIOLEN[i]=$(stream_length "${SM_AUDIO[i]}" audio)
4867
SUBMENU_LEN[i]=${SUBMENU_AUDIOLEN[i]}
4868
else
4869
SUBMENU_AUDIOLEN[i]=$( unformat_time ${SUBMENU_LEN[i]} )
4870
4871
smframes=${SUBMENU_FRAMES[i]}
4872
if ! ${SLIDESHOW[i]}; then
4873
C=$((${CHAPTERS[i]} - 1))
4874
+ VSIZE=${GEO_ARRAY[C]}
4875
SN_BTN_XY=${GEO_ARRAY[C]} # button dimensions
4876
NUM_CHAPTERS=${CHAPTERS[i]}
4877
- yecho "Creating a transparent title PNG"
4878
+ print2log "Creating a transparent title PNG"
4879
SMTITLE_CMD=(convert -size 620x300 xc:none -font "$SM_TITLE_FONT" \
4880
-pointsize $SUBMENU_FONTSIZE -fill "$SM_TITLE_CLR" \
4881
-draw "gravity center text 2,2 \"${SM_TITLES[i]}\"" \
4882
4883
TOTAL_IMGS=${CHAPTERS[i]}
4884
PREFIX=${i}-
4885
fi
4886
- if [[ -n ${GROUP[i]} ]]; then
4887
+ if [[ -n ${GROUP_ARR[i]} ]]; then
4888
unset x CUT c FILE_IN
4889
# this will also take care of grouped USER_CHAPTERS
4890
BASE=$WORK_DIR/${TSET_NUM}-group
4891
4892
if $USER_CHAPTERS; then
4893
# 1 second seek for 1st chapt (00:00:00), to avoid black frames
4894
cmd[0]=30-$(bc_math "30 + $CUT_TIME" int)
4895
- elif [[ -z ${GROUP[i]} ]]; then
4896
+ elif [[ -z ${GROUP_ARR[i]} ]]; then
4897
# auto chapters needs the last seek removed
4898
key=$((${#cmd[@]} - 1))
4899
unset cmd[key]
4900
fi
4901
- yecho
4902
- yecho "Creating $TOTAL_IMGS chapter images for ${IN_FILES[i]}"
4903
- yecho
4904
- unset cf frm
4905
- for t in "${cmd[@]}"; do
4906
+ print2log ""
4907
+ print2log "Creating $TOTAL_IMGS chapter images for ${IN_FILES[i]}"
4908
+ print2log ""
4909
+ unset cf f
4910
+ for t in "${!cmd[@]}"; do
4911
+ ! $use_transcode && break # don't run block if just using ffmpeg
4912
# warning to ignore transcode error messages
4913
print_tcode_info
4914
- if [[ -n ${GROUP[i]} ]]; then
4915
+ if [[ -n ${GROUP_ARR[i]} ]]; then
4916
CUR_FILE="${FILE_IN[cf++]}"
4917
else
4918
CUR_FILE="${IN_FILES[i]}"
4919
4920
else
4921
unset NAVSEEK NAVLOG
4922
fi
4923
- log_tmp="$PICS_OUT/log.tmp"
4924
+ ff_log_tmp="$PICS_OUT/ff_log.tmp"
4925
+ tc_log_tmp="$PICS_OUT/tc_log.tmp"
4926
yuv_fifo="$PICS_OUT/out.yuv"
4927
[[ ! -p "$yuv_fifo" ]] && mkfifo "$yuv_fifo"
4928
# resize using ffmpeg instead of transcode
4929
- FFMPEG_CMD=(ffmpeg $PIPE_FORMAT -i "$yuv_fifo" \
4930
- -f image2 -s ${GEO_ARRAY[C]} -y "$PICS_OUT/%06d.$SM_IMG_FMT")
4931
+ FFMPEG_CMD=($FFmpeg $PIPE_FORMAT -i "$yuv_fifo" \
4932
+ -f image2 $VF scale=${VSIZE%x*}:${VSIZE#*x} -y "$PICS_OUT/%06d.$SM_IMG_FMT")
4933
TCODE_CMD=(nice transcode --progress_rate 10 \
4934
--write_pid $WORK_DIR/tcode$i.pid -q 1 -i "$CUR_FILE" \
4935
$NAVSEEK "$NAVLOG" -o "$yuv_fifo" -f \
4936
- $FRAME_RATE -c $t $EXPORT)
4937
- yecho "Running ${TCODE_CMD[@]}" | fold -bs
4938
- yecho "Running ${FFMPEG_CMD[@]}" | fold -bs
4939
- "${TCODE_CMD[@]}" 2>&1 | strings >> "$LOG_FILE" &
4940
- "${FFMPEG_CMD[@]}" > "$log_tmp" 2>&1 &
4941
+ $FRAME_RATE -c ${cmd[t]} $EXPORT)
4942
+ print2log "Running ${TCODE_CMD[@]}"
4943
+ print2log "Running ${FFMPEG_CMD[@]}"
4944
+ "${TCODE_CMD[@]}" 2>&1 | pipe2log transcode &
4945
+ "${FFMPEG_CMD[@]}" > "$ff_log_tmp" 2>&1 &
4946
ffm_pid=$!
4947
wait_for "$WORK_DIR/tcode$i.pid"
4948
TCODE_PID=$(<$WORK_DIR/tcode$i.pid)
4949
tcode_pids="$tcode_pids $TCODE_PID"
4950
- if [[ -n "$TCODE_PID" ]]; then
4951
+ if [[ -n $TCODE_PID ]]; then
4952
while ps -p $ffm_pid >/dev/null; do
4953
wait_for "$IMG_DIR/000001.$SM_IMG_FMT"
4954
sleep 1 # spinner interval
4955
end=$(find "$IMG_DIR" -maxdepth 1 -name \*.$SM_IMG_FMT |
4956
sort | awk -F / '{ field = $NF }; END{ print field }')
4957
- spin "Seeking in video and creating images: $end"
4958
+ e=${end##*/}; e=${e%%.*}; e=${e##*0} # strip to digit
4959
+ spin \
4960
+ "Seeking and making $e images for chapter $((t+1)): $end"
4961
done
4962
- echo
4963
total_imgs=$(find "$IMG_DIR" -name "*.$SM_IMG_FMT" | wc -l)
4964
wait
4965
- echo "Created $total_imgs $sm_img_fmt of $TOTAL_IMGS"
4966
+ #yecho ""
4967
+ print2log "Created $total_imgs $sm_img_fmt of $TOTAL_IMGS"
4968
else
4969
runtime_error "Problem creating images from the video."
4970
fi
4971
- echo -e \
4972
- "\n$ME Log from ffmpeg (processing transcode stream)\n" \
4973
- >> "$LOG_FILE"
4974
- strings "$log_tmp" >> "$LOG_FILE"
4975
- rm -f "$log_tmp"
4976
- unset TCODE_CMD cmd run_transcode
4977
+ cat "$ff_log_tmp" | pipe2log ${FFmpeg##*/}
4978
+ rm -f "$ff_log_tmp"
4979
+ unset TCODE_CMD
4980
+ # transcode loops so each loop uses %06d, then moved to %08d
4981
if ! $ANI_SUB_MENU ; then
4982
- echo
4983
mv $WORK_DIR/submenu/000001.$SM_IMG_FMT \
4984
- $WORK_DIR/submenu/$(printf "%08d%s\n" $((frm++)) .$SM_IMG_FMT)
4985
- let frm+=1
4986
+ $WORK_DIR/submenu/$(printf "%08d%s\n" $((f++)) .$SM_IMG_FMT)
4987
+ let f+=1
4988
elif $ANI_SUB_MENU; then
4989
- echo "renaming images by frame number"
4990
- echo
4991
u=${t/*-}; v=${t/-*}
4992
# names now start with 000001. Rename starting at 000000.
4993
for ((n=1; n<smframes+1; n++)); do
4994
4995
lastimage=$WORK_DIR/animenu/$(printf \
4996
"%06d%s\n" $((n-1)) .$SM_IMG_FMT)
4997
nextimage=$WORK_DIR/animenu/$(printf \
4998
- "%08d%s\n" $((frm++ )) .$SM_IMG_FMT)
4999
+ "%08d%s\n" $((f++ )) .$SM_IMG_FMT)
5000
if [[ ! -e $curimage ]]; then
5001
cp "$lastimage" "$nextimage"
5002
else
5003
mv "$curimage" "$nextimage"
5004
fi
5005
- let frm+=1
5006
+ let f+=1
5007
done
5008
fi
5009
done
5010
- # make the chapter titles if called for. Shadow is hardcoded at #101010
5011
+ if ! $use_transcode; then # don't run block if using transcode
5012
+ if [[ -n ${GROUP_ARR[i]} ]]; then
5013
+ CUR_FILE="${FILE_IN[cf++]}"
5014
+ else
5015
+ CUR_FILE="${IN_FILES[i]}"
5016
+ fi
5017
+ ff_log_tmp="$PICS_OUT/ff_log.tmp"
5018
+ frames=$CUT_TIME
5019
+
5020
+ # avconv has no 'between' expr but keep commented code below
5021
+ #frames=$((CUT_TIME - 1))
5022
+ #[[ ${FFmpeg##*/} =~ avconv ]] && frames=$CUT_TIME
5023
+ # between filter is "inclusive" so between(300, 300) is 300
5024
+ #cur_frame=${cf%-*}
5025
+ #if [[ ${FFmpeg##*/} =~ avconv ]]; then
5026
+ #else # ffmpeg
5027
+ # "select using "between" expr
5028
+ # for fr in ${cmd[@]}; do
5029
+ # cur_frame=${fr%-*}
5030
+ # select1+="between(n,${cur_frame},$(( cur_frame + frames)))+"
5031
+ # done
5032
+ #fi
5033
+
5034
+ for fr in ${cmd[@]}; do
5035
+ cur_frame=${fr%-*}
5036
+ select1+="(gt(n,${cur_frame}))*lte(n,$(( cur_frame + frames)))+"
5037
+ done
5038
+
5039
+ # remove last '+' sign
5040
+ select1=${select1%+}
5041
+ select1="'${select1}'",setpts="'N/($ff_frame_rate*TB)'"
5042
+ scale1=scale=${VSIZE%x*}:${VSIZE#*x}
5043
+ ffm_cmd=($FFmpeg -i "$CUR_FILE" -vf select="${select1}",${scale1} \
5044
+ -y "$IMG_DIR/%08d.$SM_IMG_FMT")
5045
+ print2log "Running ${ffm_cmd[@]}"
5046
+ "${ffm_cmd[@]}" > "$ff_log_tmp" 2>&1 &
5047
+ ffm_pid=$!
5048
+ while ps -p $ffm_pid >/dev/null; do
5049
+ wait_for "$IMG_DIR/00000001.$SM_IMG_FMT"
5050
+ sleep 1 # spinner interval
5051
+ end=$(find "$IMG_DIR" -maxdepth 1 -name \*.$SM_IMG_FMT |
5052
+ sort | awk -F / '{ field = $NF }; END{ print field }')
5053
+ e=${end##*/}; e=${e%%.*}; e=${e##*0} # strip to digit
5054
+ spin \
5055
+ "Seeking and making $TOTAL_IMGS images for chapters: $end"
5056
+ done
5057
+ total_imgs=$(find "$IMG_DIR" -name "*.$SM_IMG_FMT" | wc -l)
5058
+ print2log "Created $total_imgs $sm_img_fmt of $TOTAL_IMGS"
5059
+ wait
5060
+ cat "$ff_log_tmp" | pipe2log ${FFmpeg##*/}
5061
+ unset select1 ffm_cmd
5062
+ fi
5063
+ # make the chapter titles if needed. Shadow is hardcoded at #101010
5064
if [[ -n ${CHAPTER_TITLES[@]} ]]; then
5065
echo "Making Chapter titles for Video $((i+1))"
5066
for ((a=0; a<${CHAPTERS[i]}; a++)); do
5067
5068
done
5069
fi
5070
if $ANI_SUB_MENU ; then
5071
- # move submenu images to each subdir: $WORK_DIR/animenu/{0,1,2,etc}
5072
+ # move submenu images to subdirs: $WORK_DIR/animenu/{0,1,2,etc}
5073
# or if making chapter titles, output to subdirs; rm original
5074
for ((a=0; a<${CHAPTERS[i]}; a++)); do
5075
unset num_procs smpids curimgs
5076
5077
5078
if $ANI_SUB_MENU; then
5079
$DEBUG && stime=$(date +%s)
5080
- TOYUV_CMD=(ppmtoy4m -v 0 -n $smframes -A $PIXEL_AR -F $YUV_FR -I p \
5081
- -S 420mpeg2 -r)
5082
- IMGENC_CMD=(ffmpeg -f yuv4mpegpipe -r $FRAME_RATE -i - -an \
5083
- -r $FRAME_RATE -s $VIDSIZE -tvstd $TV_STANDARD $FFMPEG_OPTS \
5084
+ TOYUV_CMD=(ppmtoy4m -v 0 -n $smframes -A $PIXEL_AR -F $YUV_FR \
5085
+ -I p -S 420mpeg2 -r)
5086
+ IMGENC_CMD=($FFmpeg -f yuv4mpegpipe -i - -an $FFMPEG_OPTS \
5087
+ -r $ff_frame_rate $VF scale=${VF_SCALE},${ASPECT} \
5088
-y "$WORK_DIR/menu$i.m2v")
5089
- echo
5090
- yecho "Running ${TOYUV_CMD[@]} < $WORK_DIR/ppm.fifo |
5091
- ${IMGENC_CMD[@]}" | fold -bs
5092
+ yecho ""
5093
+ print2log "Running ${TOYUV_CMD[@]} < $WORK_DIR/ppm.fifo |
5094
+ ${IMGENC_CMD[@]}"
5095
mkfifo "$WORK_DIR/ppm.fifo" 2>/dev/null
5096
mkfifo "$WORK_DIR/enc.fifo" 2>/dev/null
5097
"${TOYUV_CMD[@]}" < "$WORK_DIR/ppm.fifo" > \
5098
5099
"${IMGENC_CMD[@]}" < "$WORK_DIR/enc.fifo" 2>/dev/null &
5100
encpids="$encpids $!"
5101
echo
5102
- echo "Encoding $smframes frames for "${IN_FILES[i]}"" >&2
5103
+ v=${IN_FILES[i]}
5104
+ #echo "Encoding $smframes frames for "${IN_FILES[i]}"" >&2
5105
# make fifos for intermediary piping
5106
for ((f=1; f<=max_procs; f++)); do
5107
[[ ! -p "$WORK_DIR/temp-${f}.ppm" ]] && \
5108
5109
smpids="$smpids $!"
5110
ppm_fifos+=("$out_ppm") # all frames waiting to be processed
5111
if ((num_procs==max_procs || a == smframes-1 )); then
5112
- spin "\rProcessing frame $((a+1)) of $smframes " >&2
5113
+ spin "\r${v##*/}: Processing frame $((a+1)) of $smframes " >&2
5114
cat "${ppm_fifos[@]}"
5115
wait $smpids 2>/dev/null
5116
unset smpids num_procs ppm_fifos
5117
5118
5119
# wait for ppmtoy4m and ffmpeg to finish
5120
wait
5121
+ echo >&2
5122
5123
- unset IM_CMD IM_CMD2 d f P
5124
+ unset IM_CMD IM_CMD2 d f P v
5125
5126
else # not $ANI_SUB_MENU
5127
5128
- yecho
5129
+ yecho ""
5130
yecho "Making montage images for "${IN_FILES[i]}""
5131
# just use $CHAPTERS number of images
5132
imgs=( $(find $WORK_DIR/submenu -name \*.$SM_IMG_FMT |
5133
5134
fi
5135
if ! $ANI_SUB_MENU; then
5136
5137
- yecho
5138
+ yecho ""
5139
yecho "Converting chapter montage of ${IN_FILES[i]}
5140
to m2v video format"
5141
IMG_STREAM_CMD1=(convert "$PICS_IN" ppm:-)
5142
IMG_STREAM_CMD2=(ppmtoy4m -v 0 -n ${SM_LOOPS[i]} -A $PIXEL_AR -F $YUV_FR -I p \
5143
-S 420mpeg2 -r)
5144
- ENC_CMD1=(ffmpeg -f yuv4mpegpipe -r $FRAME_RATE -i - \
5145
- -r $FRAME_RATE -s $VIDSIZE -tvstd $TV_STANDARD $FFMPEG_OPTS \
5146
+ ENC_CMD1=($FFmpeg -f yuv4mpegpipe -i - \
5147
+ -r $ff_frame_rate $VF scale=${VF_SCALE},${ASPECT} $FFMPEG_OPTS \
5148
-y "$WORK_DIR/menu$i.m2v")
5149
- echo "Running ${IMG_STREAM_CMD1[@]} | ${IMG_STREAM_CMD2[@]} | \
5150
+ print2log "Running ${IMG_STREAM_CMD1[@]} | ${IMG_STREAM_CMD2[@]} | \
5151
${ENC_CMD1[@]}"| format_output | tee -a "$LOG_FILE" 2>&1
5152
- if ! "${IMG_STREAM_CMD1[@]}" | "${IMG_STREAM_CMD2[@]}" |
5153
- "${ENC_CMD1[@]}" 2>&1|strings >> "$LOG_FILE"; then
5154
- runtime_error
5155
- fi
5156
+ "${IMG_STREAM_CMD1[@]}" | "${IMG_STREAM_CMD2[@]}" |
5157
+ "${ENC_CMD1[@]}" 2>&1|strings >> "$LOG_FILE"
5158
fi
5159
5160
# check if m2v was created ok before proceeding
5161
- if mencoder -quiet -oac pcm -ovc copy -frames 0 \
5162
- "$WORK_DIR/menu$i.m2v" -o /dev/null &>/dev/null; then
5163
+ if is_video "$WORK_DIR/menu$i.m2v"; then
5164
:
5165
else
5166
echo
5167
5168
fi
5169
# clean out submenu dirs of images
5170
echo
5171
- echo "Cleaning up leftover pics in $REAL_WORK_DIR/animenu"
5172
+ print2log "Cleaning up leftover pics in $REAL_WORK_DIR/animenu"
5173
rm -f $WORK_DIR/submenu/*
5174
find $WORK_DIR/animenu/ -maxdepth 1 -type f -exec rm -f {} \;
5175
if $ANI_SUB_MENU; then
5176
5177
5178
# encode to m2v
5179
yecho "Encoding to compliant m2v video format"
5180
- PPM_CMD=(ppmtoy4m -v 0 -n ${SM_LOOPS[i]} -A $PIXEL_AR -I p -F $YUV_FR \
5181
- -S 420mpeg2 -r)
5182
- FFM_CMD=(ffmpeg $INSIZE -r $FRAME_RATE -pix_fmt yuv420p \
5183
- -f yuv4mpegpipe -i - -an -r $FRAME_RATE -s $VIDSIZE \
5184
- -tvstd $TV_STANDARD $FFMPEG_OPTS -y "$WORK_DIR/menu${i}.m2v")
5185
+ PPM_CMD=(ppmtoy4m -v 0 -n ${SM_LOOPS[i]} -A $PIXEL_AR -I p \
5186
+ -F $YUV_FR -S 420mpeg2 -r)
5187
+ FFM_CMD=($FFmpeg $PIPE_FORMAT -i - \
5188
+ -an -r $ff_frame_rate $VF scale=${VF_SCALE},${ASPECT} \
5189
+ $FFMPEG_OPTS -y "$WORK_DIR/menu${i}.m2v")
5190
yecho "Running ${PPM_CMD[@]} | ${FFM_CMD[@]}" | format_output
5191
cat "$WORK_DIR/polaroid_stack${i}.ppm" |
5192
"${PPM_CMD[@]}" | "${FFM_CMD[@]}" 2>&1 | strings >> "$LOG_FILE"
5193
5194
fi
5195
done
5196
unset IMG_STREAM_CMD1 ENC_CMD1 JPEG2YUV_OPTS
5197
+ yecho "Working on submenu audio"
5198
for ((s=0; s<=NUM_FILES; s++)); do
5199
# create audio background for either animated or plain submenus
5200
- yecho
5201
- yecho "Creating an audio background"
5202
- yecho "Working on submenu audio for "${IN_FILES[s]}""
5203
+ #yecho "Creating an audio background"
5204
+ #yecho "Working on submenu audio for "${IN_FILES[s]}""
5205
if $SUBMENU_AUDIO; then # user supplied audio file for ths video
5206
if [[ -n "$SM_AUDIO_FILE" ]]; then # user supplied "1" audio file
5207
COPY_AC3=(cp -v $WORK_DIR/submenu.$AUDIO_EXT \
5208
$WORK_DIR/menu$s.$AUDIO_EXT)
5209
- BGAUDIO_CMD=(ffmpeg -i "$SM_AUDIO_FILE" \
5210
+ BGAUDIO_CMD=($FFmpeg -i "$SM_AUDIO_FILE" \
5211
-t ${SUBMENU_AUDIOLEN[s]} -ar 48000 -acodec pcm_s16le \
5212
-y $WORK_DIR/submenu.wav)
5213
elif [[ "${SM_AUDIO[s]}" = "none" ]]; then # user asked for silence
5214
- SUBMENU_AUDIOLEN[s]=$(vid_length "$WORK_DIR/menu$s.m2v")
5215
- BGAUDIO_CMD=(ffmpeg -f s16le -ar 48000 -i /dev/zero $AUDIO_OPTS \
5216
+ SUBMENU_AUDIOLEN[s]=$(stream_length "$WORK_DIR/menu$s.m2v" m2v)
5217
+ BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero $AUDIO_OPTS \
5218
-t ${SUBMENU_AUDIOLEN[s]} -y $WORK_DIR/menu$s.$AUDIO_EXT)
5219
else
5220
# SM_AUDIO[s] is an audio file we will process it
5221
# do separate wavs for each supplied audio bg for each submenu
5222
- BGAUDIO_CMD=(ffmpeg -i "${SM_AUDIO[s]}" \
5223
+ # again using default or given submenu length
5224
+ BGAUDIO_CMD=($FFmpeg -i "${SM_AUDIO[s]}" \
5225
-t ${SUBMENU_AUDIOLEN[s]} -ar 48000 -acodec pcm_s16le \
5226
-y $WORK_DIR/menu$s.wav)
5227
- BGAUDIO_CMD2=(ffmpeg -i $WORK_DIR/menu$s.wav \
5228
+ BGAUDIO_CMD2=($FFmpeg -i $WORK_DIR/menu$s.wav \
5229
$AUDIO_OPTS -y $WORK_DIR/menu$s.$AUDIO_EXT)
5230
fi
5231
else # no supplied audio for submenu so create silence
5232
- SUBMENU_AUDIOLEN[s]=$(vid_length "$WORK_DIR/menu$s.m2v")
5233
- BGAUDIO_CMD=(ffmpeg -f s16le -ar 48000 -i /dev/zero $AUDIO_OPTS \
5234
+ SUBMENU_AUDIOLEN[s]=$(stream_length "$WORK_DIR/menu$s.m2v" m2v)
5235
+ BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero $AUDIO_OPTS \
5236
-t ${SUBMENU_AUDIOLEN[s]} -y $WORK_DIR/menu$s.$AUDIO_EXT)
5237
fi
5238
# run if wav doesn't exist, or its a slideshow
5239
if [[ ! -s $WORK_DIR/submenu.wav ]] || ${SLIDESHOW[s]}; then
5240
- yecho "Running ${BGAUDIO_CMD[@]}"
5241
+ print2log "Running ${BGAUDIO_CMD[@]}"
5242
# run command, error out if problem
5243
- ! "${BGAUDIO_CMD[@]}" 2>&1 |strings >> "$LOG_FILE" 2>&1 \
5244
+ ! "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/} \
5245
&& runtime_error "Problem getting audio for the submenu"
5246
fi
5247
# convert to DVD/SVCD format as long as not "none" or single audio file
5248
5249
&& [[ ! "${SM_AUDIO[s]}" = "none" && -z "$SM_AUDIO_FILE" ]]; then
5250
if $SM_AUDIO_FADE; then
5251
#TIME=$(audio_length "$WORK_DIR/menu$s.wav")
5252
- echo -e "Running:
5253
+ print2log "Running:
5254
sox $WORK_DIR/menu$s.wav $WORK_DIR/menu$s-processed.wav fade t
5255
- $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE" |
5256
- sed 's/ */ /g' | format_output
5257
+ $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE"
5258
sox -q $WORK_DIR/menu$s.wav $WORK_DIR/menu$s-processed.wav \
5259
fade t $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE
5260
rm $WORK_DIR/menu$s.wav
5261
mv $WORK_DIR/menu$s-processed.wav $WORK_DIR/menu$s.wav
5262
fi
5263
- echo "Running "${BGAUDIO_CMD2[@]}"" | fold -bs >> "$LOG_FILE"
5264
- ! "${BGAUDIO_CMD2[@]}" 2>&1 |strings >> "$LOG_FILE" \
5265
- && runtime_error "Problem getting audio for the submenu"
5266
+ print2log "Running ${BGAUDIO_CMD2[@]}"
5267
+ "${BGAUDIO_CMD2[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
5268
+ ((${PIPESTATUS[0]} != 0)) && runtime_error "Problem getting audio for the submenu"
5269
unset TIME
5270
fi
5271
# if "1" audio file, then convert it if it has not been done yet
5272
5273
&& ! -s $WORK_DIR/submenu-processed.wav ]]; then
5274
if $SM_AUDIO_FADE; then
5275
#TIME=$(audio_length "$WORK_DIR/submenu.wav")
5276
- echo -e "Running:
5277
+ print2log "Running:
5278
sox $WORK_DIR/submenu.wav $WORK_DIR/submenu-processed.wav \
5279
- fade t $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE" |
5280
- format_output >> "$LOG_FILE"
5281
+ fade t $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE"
5282
5283
sox -q $WORK_DIR/submenu.wav $WORK_DIR/submenu-processed.wav \
5284
fade t $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE
5285
rm -f $WORK_DIR/submenu.wav
5286
cp $WORK_DIR/submenu-processed.wav $WORK_DIR/submenu.wav
5287
fi
5288
- BGAUDIO_CMD3=(ffmpeg -i $WORK_DIR/submenu.wav \
5289
+ BGAUDIO_CMD3=($FFmpeg -i $WORK_DIR/submenu.wav \
5290
$AUDIO_OPTS -y $WORK_DIR/submenu.$AUDIO_EXT)
5291
if [ -s $WORK_DIR/submenu.$AUDIO_EXT ]; then # if exists do nothing
5292
:
5293
else
5294
- echo "Running "${BGAUDIO_CMD3[@]}"" >> "$LOG_FILE.tmp" 2>&1
5295
- ! "${BGAUDIO_CMD3[@]}" 2>&1 |strings >> "$LOG_FILE" \
5296
- && runtime_error
5297
+ print2log "Running ${BGAUDIO_CMD3[@]}"
5298
+ "${BGAUDIO_CMD3[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
5299
+ ((${PIPESTATUS[0]} != 0)) && runtime_error "Problem getting audio for the submenu"
5300
fi
5301
fi
5302
# copy the final file for each submenu if only 1 supplied
5303
"${COPY_AC3[@]}"
5304
- yecho
5305
- yecho "Multiplexing video and audio together"
5306
+ print2log "Multiplexing video and audio together"
5307
S=$((s + 1))
5308
MPLEX_CMD=(mplex -V -f $MPLEX_FORMAT -o $WORK_DIR/menu$S.mpg \
5309
$WORK_DIR/menu$s.$AUDIO_EXT $WORK_DIR/menu$s.m2v)
5310
- echo "Running: "${MPLEX_CMD[@]}"" | fold -bs >> "$LOG_FILE"
5311
- ! "${MPLEX_CMD[@]}" 2>&1 |strings >> "$LOG_FILE" && runtime_error
5312
+ print2log "Running: ${MPLEX_CMD[@]}"
5313
+ "${MPLEX_CMD[@]}" 2>&1 |pipe2log mplex
5314
+ ((${PIPESTATUS[0]} != 0)) && runtime_error \
5315
+ "Problem muxing audio and video with mplex"
5316
# remove wav to save space
5317
- rm -fv $WORK_DIR/menu$s.wav
5318
+ rm -f $WORK_DIR/menu$s.wav
5319
done
5320
- rm -fv $WORK_DIR/submenu.{wav,$AUDIO_EXT}
5321
+ rm -f $WORK_DIR/submenu.{wav,$AUDIO_EXT}
5322
rm -fr $WORK_DIR/animenu/*
5323
fi
5324
##############################################################################
5325
-# End of submenus #
5326
+# End of submenus #
5327
##############################################################################
5328
5329
##############################################################################
5330
-# Work on main menu #
5331
+# Work on main menu #
5332
##############################################################################
5333
if $DO_MENU; then
5334
yecho
5335
yecho "Building main menu"
5336
+ yecho
5337
fi
5338
if [[ -n "$BG_VIDEO" ]] && ! $QUICK_MENU; then
5339
if $FAST_SEEK; then
5340
5341
bg_post_seek="-ss $BG_SEEK" && unset bg_pre_seek
5342
fi
5343
yecho "Getting background video from $BG_VIDEO"
5344
- FFMPEG_CMD=(ffmpeg $bg_pre_seek -i "$BG_VIDEO" -an $bg_post_seek \
5345
- -vframes $BG_VIDEO_FRAMES -s $VIDSIZE -f image2 \
5346
- -y "$WORK_DIR/bg/%d.$IMG_FMT")
5347
- yecho "Extracting/resizing background images"
5348
- echo "Running: ${FFMPEG_CMD[@]}" | format_output >> "$LOG_FILE"
5349
+ FFMPEG_CMD=($FFmpeg $bg_pre_seek -i "$BG_VIDEO" -an $bg_post_seek \
5350
+ $VF scale=$VF_SCALE -f image2 \
5351
+ -vframes $BG_VIDEO_FRAMES -y "$WORK_DIR/bg/%d.$IMG_FMT")
5352
+ print2log "Extracting/resizing background images"
5353
+ print2log "Running: ${FFMPEG_CMD[@]}"
5354
# Run command and check for failure
5355
if ! "${FFMPEG_CMD[@]}" 2>&1 |strings >> "$LOG_FILE"; then
5356
runtime_error "Problem creating images from the background video"
5357
5358
#convert ${USER_PICS[MENU_NUM-1]} -resize $SHOWCASE_SIZE \
5359
cp "$WORK_DIR/showcase_img.png" "$WORK_DIR/showcase/000001.png"
5360
else
5361
- FFMPEG_CMD=(ffmpeg $ffm_pre_seek -i "$SHOWCASE_VIDEO" -s \
5362
- $SHOWCASE_SIZE -vframes $FRAMES -an $ffm_post_seek -f image2 \
5363
- -y "$WORK_DIR/showcase/%06d.png")
5364
- echo -e "\nRunning: "${FFMPEG_CMD[@]}"\n" | fold -bs >> "$LOG_FILE"
5365
+ FFMPEG_CMD=($FFmpeg $ffm_pre_seek -i "$SHOWCASE_VIDEO" \
5366
+ $VF scale=${SHOWCASE_SIZE%x*}:${SHOWCASE_SIZE#*x} -an -vframes \
5367
+ $FRAMES $ffm_post_seek -f image2 -y "$WORK_DIR/showcase/%06d.png")
5368
+ print2log "Running: ${FFMPEG_CMD[@]}"
5369
SED_VAR="frame="
5370
- "${FFMPEG_CMD[@]}" >> "$LOG_FILE.tmp" 2>&1 &
5371
+ #"${FFMPEG_CMD[@]}" >> "$LOG_FILE.tmp" 2>&1 &
5372
+ "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/} &
5373
ffm_pid=$!
5374
while ps -p $ffm_pid >/dev/null; do
5375
sleep 1
5376
5377
wait $ffm_pid
5378
(($?)) && runtime_error "Problem creating images from the video."
5379
5380
- strings "$LOG_FILE.tmp" >> "$LOG_FILE"
5381
- rm -f "$LOG_FILE.tmp"
5382
echo
5383
fi
5384
fi
5385
5386
else
5387
{ convert -size $SHOWCASE_SIZE "$pic" $SC_RAISE miff:- |
5388
convert - $SHOWCASE_FRAME -background none $ROTATE $WAVE miff:- |
5389
- convert - $QUALITY resize ${SHOWCASE_SIZE}! "$pic" ; } \
5390
+ convert - $QUALITY -resize ${SHOWCASE_SIZE}! "$pic" ; } \
5391
2>> "$LOG_FILE" &
5392
fi
5393
fi
5394
5395
((num_scpics > ani_pics)) && ani_pics=$num_scpics
5396
unset IMAGES last_pic next_pic FFMPEG_CMD pic
5397
5398
-yecho
5399
+yecho ""
5400
if [[ ! "$SC_FRAMESTYLE" = "glass" && ! $TEXTMENU ]]; then
5401
if $SHOWCASE; then
5402
yecho "Processing video images"
5403
5404
done
5405
fi
5406
if ! $QUICK_MENU && $DO_MENU; then
5407
- yecho
5408
- yecho "Making $FRAMES final montage frames and compositing onto \
5409
+ yecho ""
5410
+ yecho "Making $FRAMES final montage frame(s) and compositing onto \
5411
background with title"
5412
- yecho
5413
+ yecho ""
5414
fi
5415
if $STATIC; then
5416
# we have a value for MENU_AUDIOLEN AND BG_AUDIO
5417
- if [[ -n "$BG_AUDIO" && "$BG_AUDIO" != "none" ]]; then
5418
+ if [[ -n "$BG_AUDIO" && "$BG_AUDIO" != "none" ]] && ! $MENU_FADE; then
5419
LOOPS=$( bc <<< "$MENU_AUDIOLEN * $FRAME_RATE" 2>/dev/null)
5420
LOOPS=${LOOPS%.*}
5421
# switched menu: no bg audio or video and not menu fade
5422
5423
PPM_LOOPS=$LOOPS
5424
fi
5425
if ! $QUICK_MENU && $DO_MENU; then
5426
- $STATIC && INSIZE="-s $VIDSIZE"
5427
echo
5428
echo \
5429
"Converting images to video and encoding to $TARGET-compliant format" >&2
5430
5431
PPM_FRAMES=$((PPM_FRAMES+18))
5432
TOYUV_CMD=(ppmtoy4m -v 2 -n $PPM_FRAMES -A $PIXEL_AR -I p -F $YUV_FR \
5433
-S 420mpeg2 -r)
5434
- IMGENC_CMD=(ffmpeg $INSIZE -r $FRAME_RATE $PIPE_FORMAT -i - -an \
5435
- -r $FRAME_RATE -s $VIDSIZE -tvstd $TV_STANDARD $FFMPEG_OPTS \
5436
+ IMGENC_CMD=($FFmpeg $PIPE_FORMAT -i - -an \
5437
+ -r $ff_frame_rate $VF scale=${VF_SCALE},${ASPECT} $FFMPEG_OPTS \
5438
-y $WORK_DIR/intro.m2v)
5439
- yecho "Running ${TOYUV_CMD[@]} < $WORK_DIR/ppm.fifo | ${IMGENC_CMD[@]}" |
5440
- fold -bs
5441
+ #print2log "Running ${TOYUV_CMD[@]} < $WORK_DIR/ppm.fifo | ${IMGENC_CMD[@]}" |
5442
+ print2log "Running:"
5443
+ echo "${TOYUV_CMD[@]} < $WORK_DIR/ppm.fifo | ${IMGENC_CMD[@]}" | \
5444
+ while read -r line; do
5445
+ print2log "$line"
5446
+ done
5447
mkfifo "$WORK_DIR/ppm.fifo" 2>/dev/null
5448
mkfifo "$WORK_DIR/enc.fifo" 2>/dev/null
5449
"${TOYUV_CMD[@]}" < "$WORK_DIR/ppm.fifo" > "$WORK_DIR/enc.fifo" \
5450
- 2>> "$LOG_FILE" & #/dev/null &
5451
+ 2>> "${LOG_FILE}.1-tmp" & #/dev/null &
5452
encpids="$encpids $!"
5453
- "${IMGENC_CMD[@]}" < "$WORK_DIR/enc.fifo" 2>> "$LOG_FILE" & #/dev/null &
5454
+ "${IMGENC_CMD[@]}" < "$WORK_DIR/enc.fifo" 2>> "${LOG_FILE}.2-tmp" & #/dev/null &
5455
encpids="$encpids $!"
5456
fi
5457
# make intermediary fifos for images. They will get catted to ppm.fifo
5458
5459
# -menu-fade working with -static
5460
$SINGLE_SLIDESHOW && \
5461
IM_CMD1=(convert "$WORK_DIR/polaroid_stack.png" miff:- )
5462
-
5463
- $TEXTMENU && unset MONTAGE_CMD
5464
- $TEXTMENU && MONTAGE_CMD=( "${MONTAGE_CMD03[@]}" )
5465
+ # -text-menu can have showcase image so don't unset if it is present
5466
+ if $TEXTMENU && [[ -z "$SHOWCASE_IMG" ]]; then
5467
+ unset MONTAGE_CMD
5468
+ MONTAGE_CMD=( "${MONTAGE_CMD03[@]}" )
5469
+ fi
5470
# if doing less animated frames than the total # of frames
5471
# break from the loop and use ppmtoy4m to repeat last frame
5472
# if we are not doing a fadeout, or if doing fadeout, cat the last
5473
5474
2>> "$LOG_FILE" &
5475
else # not SHOWCASE_VIDEO (SHOWCASE_IMG)
5476
{ "${MONTAGE_CMD[@]}" miff:- | "${MONTAGE_CMD02[@]}" miff:- |
5477
- "${MONTAGE_CMD2c[@]}" miff:- |"${MONTAGE_CMD5[@]}" |
5478
+ "${MONTAGE_CMD2c[@]}" miff:- | "${MONTAGE_CMD5[@]}" |
5479
"${MONTAGE_CMD6[@]}" | "${MONTAGE_CMD3[@]}" miff:- |
5480
"${MONTAGE_CMD4[@]}" | "${MONTAGE_CMD7[@]}" ; } \
5481
2>> "$LOG_FILE" &
5482
5483
fi # end making final montages
5484
# wait for ppmtoy4m and ffmpeg to finish
5485
wait
5486
+# send formated ffmpeg output to log
5487
+if [[ -e "${LOG_FILE}.1-tmp" ]]; then
5488
+ cat "${LOG_FILE}.1-tmp" | pipe2log ppmtoy4m
5489
+ rm -f "${LOG_FILE}.1-tmp"
5490
+fi
5491
+if [[ -e "${LOG_FILE}.2-tmp" ]]; then
5492
+ cat "${LOG_FILE}.2-tmp" | pipe2log ${FFmpeg##*/}
5493
+ rm -f "${LOG_FILE}.2-tmp"
5494
+fi
5495
5496
if ! $QUICK_MENU && $DO_MENU; then
5497
echo
5498
- echo "Cleaning up montage images"
5499
+ print2log "Cleaning up montage images"
5500
rm -f $WORK_DIR/animenu/*.$IMG_FMT
5501
rm -f $WORK_DIR/animenu/*.png
5502
fi
5503
# check if m2v was created ok before proceeding
5504
if $DO_MENU; then
5505
- if ! mencoder -quiet -oac pcm -ovc copy -frames 0 \
5506
- "$WORK_DIR/intro.m2v" -o /dev/null &> /dev/null; then
5507
+ if ! is_video "$WORK_DIR/intro.m2v"; then
5508
echo
5509
runtime_error "The menu video file has not been created !"
5510
fi
5511
fi
5512
if $DO_MENU; then
5513
- MENU_ATIME=$(vid_length "$WORK_DIR/intro.m2v")
5514
+ MENU_ATIME=$(stream_length "$WORK_DIR/intro.m2v" m2v)
5515
$SWITCHED && MENU_ATIME=${MENU_LEN[MENU_NUM-1]}
5516
fi
5517
-
5518
# use mplayer to dump audio if mplayer used for video
5519
# but first check if audio same file as video and its not a static menu
5520
if [[ $SC_FRAMESTYLE = "glass" && $BG_AUDIO = $SHOWCASE_VIDEO ]]; then
5521
! $STATIC && USE_MPLAYER_4AUDIO=:
5522
fi
5523
BG_AUDIO_LENGTH="-t $MENU_ATIME"
5524
-# create audio background for the main menu
5525
+# audio background for main menu #
5526
if $DO_MENU; then
5527
- sample_size=$(get_sox_arg)
5528
if [[ -z "$BG_AUDIO" || "$BG_AUDIO" = "none" ]]; then # use silence
5529
! $SWITCHED && AUDIO_FADE=false # do not fade silence
5530
- echo "Running cat /dev/zero 2>/dev/null | nice -n 0 sox -t raw -c 2 -r 48000 \
5531
- $sample_size -s - $WORK_DIR/intro.wav trim 0 $MENU_ATIME" |fold -bs
5532
- cat /dev/zero 2>/dev/null | nice -n 0 sox -t raw -c 2 -r 48000 \
5533
- $sample_size -s - $WORK_DIR/intro.wav trim 0 $MENU_ATIME
5534
+ BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero -ar 48000 \
5535
+ -t $MENU_ATIME -ac 2 -acodec pcm_s16le -y $WORK_DIR/intro.wav)
5536
+ print2log "Running ${BGAUDIO_CMD[@]}"
5537
+ "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
5538
+ if [[ ! -s "$WORK_DIR/intro.wav" ]]; then
5539
+ runtime_error "There was a problem creating menu background silence"
5540
+ fi
5541
# Make sure file exists
5542
elif test ! -s "$BG_AUDIO"; then
5543
runtime_error "Cannot find background audio file: $BG_AUDIO"
5544
- else # audio supplied: convert to wav then later to dvd/svcd format
5545
+ else # audio supplied: convert to wav then later to dvd format
5546
# TODO if ! $BG_AUDIOVIDEO_FILE; then # check if same file and if so
5547
# decode the audio and jpegs in one step above, and skip this block
5548
if $USE_MPLAYER_4AUDIO; then
5549
- BGAUDIO_CMD=(mplayer -quiet -vc null -vo null -ss \
5550
+ pipe_prog=mplayer
5551
+ BGAUDIO_CMD=(mplayer -quiet -vc null -vo null -ss \
5552
$MPLAYER_SEEK_VAL -ao pcm:waveheader:file="$WORK_DIR/intro.wav" \
5553
-endpos $MENU_ATIME "$BG_AUDIO")
5554
else
5555
- BGAUDIO_CMD=(ffmpeg -y -async 1 -ss $BG_AUDIO_SEEK \
5556
- $BG_AUDIO_LENGTH -i "$BG_AUDIO" -r $FRAME_RATE -ar 48000 \
5557
+ pipe_prog=${FFmpeg##*/}
5558
+ BGAUDIO_CMD=($FFmpeg -y \
5559
+ -i "$BG_AUDIO" -vn -ss $BG_AUDIO_SEEK $BG_AUDIO_LENGTH -ar 48000 \
5560
-acodec pcm_s16le $WORK_DIR/intro.wav)
5561
fi
5562
- yecho
5563
- echo "Running ${BGAUDIO_CMD[@]}" |format_output|tee -a "$LOG_FILE" 2>&1
5564
- ! "${BGAUDIO_CMD[@]}" 2>&1 |strings >> "$LOG_FILE" && runtime_error
5565
+ print2log "Running ${BGAUDIO_CMD[@]}"
5566
+ "${BGAUDIO_CMD[@]}" 2>&1 |pipe2log $pipe_prog
5567
+ ((${PIPESTATUS[0]} != 0)) && runtime_error \
5568
+ "Problem creating wav file during background audio processing"
5569
5570
if $AUDIO_FADE; then # bgaudio supplied and audio fade selected
5571
- WAV_TIME=$(audio_length "$WORK_DIR/intro.wav")
5572
- echo "Running:
5573
+ WAV_TIME=$(stream_length "$WORK_DIR/intro.wav" audio)
5574
+ print2log "Running:
5575
sox $WORK_DIR/intro.wav $WORK_DIR/intro-processed.wav fade t
5576
- $FADE $WAV_TIME $FADE" |format_output
5577
+ $FADE $WAV_TIME $FADE"
5578
sox $WORK_DIR/intro.wav \
5579
- $WORK_DIR/intro-processed.wav fade t $FADE $WAV_TIME $FADE
5580
- rm $WORK_DIR/intro.wav
5581
+ $WORK_DIR/intro-processed.wav fade t $FADE $WAV_TIME $FADE 2>&1 | pipe2log sox
5582
+ $KEEP_FILES || rm $WORK_DIR/intro.wav
5583
mv $WORK_DIR/intro-processed.wav $WORK_DIR/intro.wav
5584
fi
5585
fi
5586
-fi
5587
-unset BGAUDIO_CMD TIME
5588
+ unset BGAUDIO_CMD TIME
5589
+
5590
+ # convert to proper audio format
5591
+ BGAUDIO_CMD=($FFmpeg -i $WORK_DIR/intro.wav \
5592
+ $AUDIO_OPTS -y $WORK_DIR/intro.$AUDIO_EXT)
5593
+ echo "Running "${BGAUDIO_CMD[@]}"" | pipe2log
5594
+ "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
5595
5596
-# convert to proper audio format
5597
-BGAUDIO_CMD=(ffmpeg -i $WORK_DIR/intro.wav \
5598
-$AUDIO_OPTS -y $WORK_DIR/intro.$AUDIO_EXT)
5599
-yecho "Running "${BGAUDIO_CMD[@]}"" | fold -bs >> "$LOG_FILE"
5600
-"${BGAUDIO_CMD[@]}" 2>&1 |strings >> "$LOG_FILE"
5601
-if $DO_MENU; then
5602
! [[ -s $WORK_DIR/intro.$AUDIO_EXT ]] && runtime_error
5603
unset BGAUDIO_CMD
5604
- rm -fv "$WORK_DIR/intro.wav"
5605
- echo
5606
- echo "Multiplexing main menu audio and video together"
5607
+ $KEEP_FILES || rm -f "$WORK_DIR/intro.wav"
5608
+ print2log "Multiplexing main menu audio and video together"
5609
# mplex main menu audio and video together
5610
INTRO_MPLEX_CMD="mplex -V -f $MPLEX_FORMAT -o $WORK_DIR/intro.mpg \
5611
$WORK_DIR/intro.$AUDIO_EXT $WORK_DIR/intro.m2v"
5612
- echo -e "\nRunning: $INTRO_MPLEX_CMD\n" |fold -bs >> "$LOG_FILE"
5613
- yecho
5614
- ! ${INTRO_MPLEX_CMD[@]} 2>&1 |strings >> "$LOG_FILE" && runtime_error
5615
+ print2log "Running: $INTRO_MPLEX_CMD"
5616
+ ${INTRO_MPLEX_CMD[@]} 2>&1 |pipe2log mplex
5617
+ ((${PIPESTATUS[0]} != 0)) && runtime_error \
5618
+ "Problem muxing the menu video and audio with mplex"
5619
5620
- yecho
5621
if $SWITCHED_MODE || $SWITCHED_MENUS; then
5622
- yecho "Copying the menu mpeg"
5623
+ echo "Copying the menu mpeg" |pipe2log
5624
if [[ $MENU_NUM -ne 1 ]]; then
5625
cp -v "$REAL_WORK_DIR/intro.mpg" \
5626
"$BASEDIR/${TSET_NUM}-${MENU_NUM}intro.mpg"
5627
5628
fi
5629
fi
5630
if $SWITCHED_MENUS; then
5631
+ print2log "Running spumux to create navigation buttons."
5632
for ((i=1; i<=${#FILES[@]}; i++)); do
5633
MENU_FILE="$BASEDIR/animenu${TSET_NUM}-${i}.mpg"
5634
- yecho "Running spumux "$SPUMUX_XML" \
5635
- < "$REAL_WORK_DIR/${TSET_NUM}-${i}intro.mpg" > "$MENU_FILE""
5636
+ print2log "Running spumux $SPUMUX_XML \
5637
+ < $REAL_WORK_DIR/${TSET_NUM}-${i}intro.mpg > $MENU_FILE"
5638
spumux "$SPUMUX_XML" < "$WORK_DIR/${TSET_NUM}-${i}intro.mpg" \
5639
- > "$MENU_FILE" 2>> "$LOG_FILE"
5640
+ > "$MENU_FILE" 2>> "${LOG_FILE}.tmp"
5641
+ wait
5642
+ [[ -e ${LOG_FILE}.tmp ]] && cat "${LOG_FILE}.tmp" | pipe2log spumux
5643
+ rm -f ${LOG_FILE}.tmp
5644
check_menufile
5645
done
5646
fi
5647
fi
5648
if ! $SWITCHED_MENUS && ! $SWITCHED_MODE; then
5649
- yecho "Running spumux "$SPUMUX_XML" < $WORK_DIR/intro.mpg > "$MENU_FILE""
5650
- spumux "$SPUMUX_XML" < $WORK_DIR/intro.mpg > "$MENU_FILE" 2>> "$LOG_FILE"
5651
+ print2log "Running spumux $SPUMUX_XML < $WORK_DIR/intro.mpg > $MENU_FILE"
5652
+ spumux "$SPUMUX_XML" < $WORK_DIR/intro.mpg > "$MENU_FILE" 2>> "${LOG_FILE}.tmp"
5653
+ wait
5654
+ [[ -e ${LOG_FILE}.tmp ]] && cat "${LOG_FILE}.tmp" | pipe2log spumux
5655
+ rm -f ${LOG_FILE}.tmp
5656
check_menufile
5657
fi
5658
if $SUB_MENU; then
5659
- echo "Creating submenus"
5660
+ echo "Creating submenus" | pipe2log
5661
+ print2log "Running spumux to create navigation buttons"
5662
for ((x=1; x<=V_TOTAL; x++)); do
5663
- yecho "Running spumux "$WORK_DIR/submenu${x}_spumux.xml" < \
5664
+ print2log "Running spumux "$WORK_DIR/submenu${x}_spumux.xml" < \
5665
$WORK_DIR/menu${x}.mpg > \
5666
$(sed 's/\(.*\)menu/\1Menu/' <<< $WORK_DIR/menu${x}.mpg)"|fold -bs
5667
spumux "$WORK_DIR/submenu${x}_spumux.xml" < \
5668
$WORK_DIR/menu${x}.mpg > \
5669
$(sed 's/\(.*\)menu/\1Menu/' <<< $BASEDIR/${TSET_NUM}-menu${x}.mpg) \
5670
- 2>> "$LOG_FILE"
5671
+ 2>> "${LOG_FILE}.tmp"
5672
+ wait
5673
+ [[ -e ${LOG_FILE}.tmp ]] && cat "${LOG_FILE}.tmp" | pipe2log spumux
5674
+ rm -f ${LOG_FILE}.tmp
5675
+
5676
done
5677
fi
5678
if $TITLESET_MODE; then
5679
5680
fi
5681
5682
if $AUTHOR && ! $VMGM_ONLY && ! $DO_TITLESETS && ! $SWITCHED_MODE; then
5683
- echo "Running dvdauthor to create the DVD filesystem"
5684
- dvdauthor -x "$DVDAUTHOR_XML" 2>&1 | tee -a "$LOG_FILE.tmp"
5685
+ yecho "Running dvdauthor to create the DVD filesystem"
5686
+ dvdauthor -x "$DVDAUTHOR_XML" 2>&1 | pipe2log dvdauthor
5687
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
5688
dvdauthor_error
5689
fi
5690
- strings "$LOG_FILE.tmp" >> "$LOG_FILE" && rm -f "$LOG_FILE.tmp"
5691
+ #strings "$LOG_FILE.tmp" >> "$LOG_FILE" && rm -f "$LOG_FILE.tmp"
5692
fi
5693
-echo "Cleaning up unwanted files in $REAL_WORK_DIR"
5694
+print2log "Cleaning up unwanted files in $REAL_WORK_DIR"
5695
find "$WORK_DIR"/ -name '*.$IMG_FMT' ! -name preview.$IMG_FMT -exec rm -f {} \; \
5696
> /dev/null 2>&1
5697
rm -fr "$WORK_DIR/animenu" "$WORK_DIR/pics" "$WORK_DIR/submenu"
5698
tovid-0.34.tar.bz2/src/todisc-fade-routine -> tovid-0.35.tar.gz/src/todisc-fade-routine
Changed
10
1
2
#
3
# Project homepage: http://tovid.wikia.com
4
#
5
-# Copyright (C) 2005-2010
6
+# Copyright (C) 2005-2015
7
#
8
# This program is free software; you can redistribute it and/or
9
# modify it under the terms of the GNU General Public License
10
tovid-0.34.tar.bz2/src/todiscgui -> tovid-0.35.tar.gz/src/todiscgui
Changed
23
1
2
import sys
3
from libtovid.guis import todisc
4
5
+command = []
6
+position = ''
7
+project = ''
8
if __name__ == '__main__':
9
- todisc.run(sys.argv[1:])
10
+ args = sys.argv[1:]
11
+ while args:
12
+ arg = args.pop(0)
13
+ # if passing --position pop next arg as well
14
+ if arg in ['--position', '-position']:
15
+ position = args.pop(0)
16
+ elif arg in ['--project', '-project']:
17
+ project = args.pop(0)
18
+ else:
19
+ # if --position or --project not passed, all args append to command
20
+ command.append(arg)
21
+ todisc.run(command, position=position, project=project)
22
23
tovid-0.34.tar.bz2/src/tovid -> tovid-0.35.tar.gz/src/tovid
Changed
136
1
2
-#! /usr/bin/env python
3
+#!/usr/bin/python
4
# tovid.py
5
6
"""Frontend to the tovid suite.
7
8
9
Where 'command' is one of the following:
10
11
- Command Description Formerly
12
- -----------------------------------------------------------------
13
- id Identify one or more video files idvid
14
- dvd Author and/or burn a DVD makedvd
15
- menu Create an MPEG menu makemenu
16
- vcd Author and/or burn a VCD makevcd
17
- xml Create (S)VCD or DVD .xml file makexml
18
- postproc Post-process an MPEG video file postproc
19
- disc Create a DVD with menus todisc
20
- gui Start the tovid GUI todiscgui
21
- mpg Encode videos to MPEG format tovid
22
- titlesets Start the titleset wizard (new)
23
- chapters Set video chapter points with mplayer (new)
24
+ Main commands (one step DVD creation)
25
+
26
+ Command Description Formerly
27
+ -----------------------------------------------------------------------
28
+ disc Options to encode, make menus, author and burn todisc
29
+ gui Start the tovid GUI todiscgui
30
+ titlesets Start the titleset wizard GUI (new)
31
+
32
+
33
+ Helper commands (used by 'Main commands' or run standalone)
34
+
35
+ Command Description Formerly
36
+ -----------------------------------------------------------------------
37
+ mpg Encode videos to MPEG format tovid
38
+ id Identify one or more video files idvid
39
+ dvd Author and/or burn a DVD makedvd
40
+ chapters A GUI to set chapter points with mplayer (new)
41
+
42
43
The following general options are also available:
44
--prefix | -prefix Return the tovid install prefix
45
46
import time
47
import shlex
48
import shutil
49
-from ConfigParser import ConfigParser
50
+# python 3 compatibility
51
+try:
52
+ from ConfigParser import ConfigParser
53
+except ImportError:
54
+ from configparser import ConfigParser
55
56
# Command names to script mappings
57
_scripts = {
58
'id': 'idvid',
59
'dvd': 'makedvd',
60
- 'menu': 'makemenu',
61
- 'vcd': 'makevcd',
62
- 'xml': 'makexml',
63
- 'postproc': 'postproc',
64
'disc': 'todisc',
65
'gui': 'todiscgui',
66
'mpg': 'makempg',
67
68
"""Return the tovid version string.
69
"""
70
tovid_init = self.script_dir + '/tovid-init'
71
- cmd = shlex.split("bash -c '. %s && printf $TOVID_VERSION'" % tovid_init)
72
- return subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
73
+ # can't just source tovid-init to get TOVID_VERSION - sourcing may fail
74
+ cmd = shlex.split("awk -F= '/^TOVID_VERSION/ {print $2}' %s" % tovid_init)
75
+ result = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
76
+ # Python 3 needs decode("utf-8") as it returns a byte string not str
77
+ return result.decode("utf-8").replace('"', '').strip()
78
79
80
def parse_options(self, args):
81
82
arg = args.pop(0)
83
84
if arg in ['-prefix', '--prefix']:
85
- print self.prefix
86
+ print(self.prefix)
87
sys.exit(0)
88
89
elif arg in ['-version', '--version']:
90
- print self.version
91
+ print(self.version)
92
sys.exit(0)
93
94
elif arg in ['-info', '--info']:
95
96
return
97
98
# Create ~/.tovid if it doesn't exist already
99
- user_tovid_dir = os.path.expanduser('~/.tovid')
100
- if not os.path.exists(user_tovid_dir):
101
- print("Creating '%s'" % user_tovid_dir)
102
- os.mkdir(user_tovid_dir)
103
-
104
+ # honour TOVID_HOME environment variable
105
+ self.user_tovid_dir = os.getenv('TOVID_HOME') or os.path.expanduser('~/.tovid')
106
+ #user_tovid_dir = os.path.expanduser('~/.tovid')
107
+
108
+ if not os.path.exists(self.user_tovid_dir):
109
+ try:
110
+ os.mkdir(self.user_tovid_dir)
111
+ print("Creating '%s'" % self.user_tovid_dir)
112
+ except OSError:
113
+ print("Cannot create %s, exiting ..." %self.user_tovid_dir)
114
+ sys.exit(1)
115
# Copy default tovid.ini to ~/.tovid if it doesn't exist already
116
- user_tovid_ini = os.path.join(user_tovid_dir, 'tovid.ini')
117
- if not os.path.exists(user_tovid_ini):
118
- print("Creating '%s'" % user_tovid_ini)
119
- shutil.copy(default_tovid_ini, user_tovid_ini)
120
+ self.user_tovid_ini = os.path.join(self.user_tovid_dir, 'tovid.ini')
121
+ if not os.path.exists(self.user_tovid_ini):
122
+ print("Creating '%s'" % self.user_tovid_ini)
123
+ shutil.copy(default_tovid_ini, self.user_tovid_ini)
124
125
126
def get_config_options(self, command):
127
"""Return any options found in ~/.tovid/tovid.ini for the given command.
128
"""
129
# Parse the user's tovid.ini file
130
- filename = os.path.expanduser('~/.tovid/tovid.ini')
131
+ #filename = os.path.expanduser('~/.tovid/tovid.ini')
132
+ filename = self.user_tovid_ini
133
config = ConfigParser()
134
config.read(filename)
135
# If no [command] section exists, or if there's no 'options' setting,
136
tovid-0.34.tar.bz2/src/tovid-init -> tovid-0.35.tar.gz/src/tovid-init
Changed
185
1
2
#
3
# Project homepage: http://tovid.wikia.com
4
#
5
-# Copyright (C) 2005-2010
6
+# Copyright (C) 2005-2014
7
#
8
# This program is free software; you can redistribute it and/or
9
# modify it under the terms of the GNU General Public License
10
11
#set -u
12
13
# Suite version
14
-TOVID_VERSION="0.34"
15
+TOVID_VERSION="0.35"
16
17
# String used to separate blocks of output
18
SEPARATOR="========================================================="
19
20
TOVID_HOME="$HOME/.tovid"
21
TOVID_HOME_PAGE="http://tovid.wikia.com"
22
TOVID_FORUMS="http://groups.google.com/group/tovid-users"
23
-
24
+TOVID_ISSUES="http://code.google.com/p/tovid/issues/list"
25
26
# ******************************************************************************
27
# ******************************************************************************
28
29
# ******************************************************************************
30
# Take a string containing a time (like "02:15:25.3") and
31
# format it as an integer number of seconds. Fractional seconds
32
-# are truncated. Result is echoed to stdout, so to use the output
33
-# as a "return value", call the function like this:
34
-# RETURN_VALUE=$(unformat_time $TIME_STRING)
35
+# are truncated. Result is echoed to stdout, so to use the output you can
36
+# call the function like this: var=$(unformat_time $TIME_STRING)
37
# ******************************************************************************
38
function unformat_time()
39
{
40
41
else
42
TOT_SECONDS=$1
43
fi
44
- echo $TOT_SECONDS
45
+ if [[ -n $2 && $2 = "int" ]]; then
46
+ echo ${TOT_SECONDS%%.*}
47
+ else
48
+ echo $TOT_SECONDS
49
+ fi
50
}
51
52
# *****************************************************************************
53
54
# Wait for input file to appear
55
# After a 30-second timeout, exit gracefully
56
CUR_TIME=30
57
- while test $CUR_TIME -gt 0; do
58
+ while test $CUR_TIME -gt 0; do
59
+ sleep 3
60
# If file exists, wait a few more seconds, then break out
61
if test -e "$FOP_OUTFILE"; then
62
- printf "Processing started. Please wait... "
63
- sleep 3s
64
+ $QUIET || printf "Processing started. Please wait... "
65
+ sleep 1
66
+ CUR_TIME=1
67
break
68
fi
69
printf "Waiting $CUR_TIME seconds for output file \"$FOP_BASENAME_NAME\" to appear...\r"
70
- sleep 1s
71
+ sleep 1
72
CUR_TIME=$(expr $CUR_TIME - 1)
73
done
74
75
76
77
# Doze a bit to let the file size increase
78
# (SLEEP_TIME defaults to 1s if unset)
79
- sleep ${SLEEP_TIME-"1s"}
80
+ sleep ${SLEEP_TIME-"1"}
81
82
FOP_LAST_SIZE=$FOP_CUR_SIZE
83
FOP_CUR_SIZE=$(du -b "$FOP_OUTFILE" | awk '{print $1}')
84
done
85
- printf "\n\n"
86
+ $QUIET && printf "\n" || printf "\n\n"
87
}
88
89
# ******************************************************************************
90
91
count=$(seq 1 $LAST)
92
for _CNTR in $(sort -nr <<< "$count")
93
do
94
- echo -n -e " in $_CNTR seconds...\r";
95
- sleep 1s;
96
+ echo -n -e " in $_CNTR seconds...or press <ENTER>\r";
97
+ read -t 1 && break;
98
done
99
}
100
101
102
done
103
return 0
104
}
105
-
106
+# *****************************************************************************
107
+# takes 1 arg: [name to prefix each line of output]
108
+# uses stdbuf (coreutils) if present so stdin is line buffered
109
+send_to_log()
110
+{
111
+ [[ $1 ]] && prog_name="[$1]: " || prog_name="[${0##*/}]: "
112
+ $std_buf tr "\015" "\n" < /dev/stdin | \
113
+ while read line; do
114
+ printf "%s %s\n" "$prog_name" "$line"
115
+ done
116
+ printf "\n"
117
+}
118
119
# ******************************************************************************
120
#
121
122
KERNEL=$(uname)
123
if test "$KERNEL" = "Linux"; then
124
# Linux should have /proc/cpuinfo
125
- CPU_MODEL=$(awk -F ":" '/model name/ {print $2}' /proc/cpuinfo | head -n 1)
126
+ CPU_MODEL=$(awk -F ":" '/model name/ {print $2}' \
127
+ /proc/cpuinfo | head -n 1 | sed 's/^ *//g')
128
CPU_SPEED=$(awk 'BEGIN { IGNORECASE = 1 } /MHz/ { print $4 }' /proc/cpuinfo | head -n 1)
129
# Test for multiple CPUs. If they are available, try to use them.
130
if test $(grep "^processor" /proc/cpuinfo | wc -l) -ge "2"; then
131
132
# tovid preferences
133
# Configures working directory for all scripts and
134
# output directory for the makempg script
135
+# also used for setting ffmpeg/avconv program
136
#WORKING_DIR=/tmp
137
#OUTPUT_DIR=/video/outfiles
138
+#TOVID_FFMPEG=ffmpeg
139
EOF`
140
printf "$PREFS_CONTENTS\n" > "$USER_PREFS"
141
fi
142
# if preferences vars are set in the environment, use those (takes precedence).
143
[[ $TOVID_WORKING_DIR ]] && WORKING_DIR="$TOVID_WORKING_DIR"
144
[[ $TOVID_OUTPUT_DIR ]] && OUTPUT_DIR="$TOVID_WORKING_DIR"
145
+[[ $TOVID_FFMPEG_CMD ]] && TOVID_FFMPEG="$TOVID_FFMPEG_CMD"
146
+# FFmpeg and FFprobe are vars used for ffmpeg by scripts needing ffmpeg/avconv
147
+# if avconv is installed, use that unless env var set
148
+hash avconv 2>/dev/null && TOVID_FFMPEG=${TOVID_FFMPEG:-avconv}
149
+hash avprobe 2>/dev/null && TOVID_FFPROBE=${TOVID_FFPROBE:=avprobe}
150
+# finally, default to ffmpeg if non of the above override it
151
+FFmpeg=${TOVID_FFMPEG:=ffmpeg}
152
+[[ $FFmpeg =~ ffmpeg ]] && TOVID_FFPROBE=ffprobe
153
+[[ $FFmpeg =~ avconv ]] && TOVID_FFPROBE=avprobe
154
+FFprobe=${TOVID_FFPROBE:=ffprobe}
155
+
156
+# stdbuf (coreutils>=7.5) is useful to todisc and makempg, use it if present
157
+hash stdbuf 2>/dev/null && std_buf="stdbuf -oL" || std_buf=""
158
159
# ******************************************************************************
160
# Check for run-time dependencies
161
162
# *************************************************************************
163
# Required Dependencies
164
# *************************************************************************
165
- core="grep sed md5sum mplayer mencoder mplex mpeg2enc yuvfps yuvdenoise ppmtoy4m mp2enc jpeg2yuv ffmpeg"
166
+ core="grep sed md5sum mplayer mplex mpeg2enc yuvfps yuvdenoise ppmtoy4m mp2enc jpeg2yuv"
167
168
# *************************************************************************
169
# Optional Dependencies
170
171
172
# -------------------------------------------------------------------------
173
# todisc dependencies
174
- todisc_deps="$magick mogrify spumux dvdauthor transcode sox"
175
+ todisc_deps="$magick mogrify spumux dvdauthor sox"
176
177
# Quit and complain if ANY core dependency is missing.
178
assert_dep "$core" "You are missing CORE tovid dependencies!"
179
+ # ffmpeg is also a part of core deps, but is taken care of here
180
+ ffmpeg_alts="Use either ffmpeg (ffmpeg.org) or avconv (libav.org)."
181
+ ffmpeg_pref="Set choice in ${USER_PREFS}. As in: TOVID_FFMPEG=ffmpeg"
182
+ assert_dep $FFmpeg "You are missing $FFmpeg ! $ffmpeg_alts ${ffmpeg_pref}."
183
184
# End tovid-init
185
tovid-0.34.tar.bz2/src/tovid-init.in -> tovid-0.35.tar.gz/src/tovid-init.in
Changed
176
1
2
#
3
# Project homepage: http://tovid.wikia.com
4
#
5
-# Copyright (C) 2005-2010
6
+# Copyright (C) 2005-2014
7
#
8
# This program is free software; you can redistribute it and/or
9
# modify it under the terms of the GNU General Public License
10
11
TOVID_HOME="$HOME/.tovid"
12
TOVID_HOME_PAGE="http://tovid.wikia.com"
13
TOVID_FORUMS="http://groups.google.com/group/tovid-users"
14
-
15
+TOVID_ISSUES="http://code.google.com/p/tovid/issues/list"
16
17
# ******************************************************************************
18
# ******************************************************************************
19
20
# ******************************************************************************
21
# Take a string containing a time (like "02:15:25.3") and
22
# format it as an integer number of seconds. Fractional seconds
23
-# are truncated. Result is echoed to stdout, so to use the output
24
-# as a "return value", call the function like this:
25
-# RETURN_VALUE=$(unformat_time $TIME_STRING)
26
+# are truncated. Result is echoed to stdout, so to use the output you can
27
+# call the function like this: var=$(unformat_time $TIME_STRING)
28
# ******************************************************************************
29
function unformat_time()
30
{
31
32
else
33
TOT_SECONDS=$1
34
fi
35
- echo $TOT_SECONDS
36
+ if [[ -n $2 && $2 = "int" ]]; then
37
+ echo ${TOT_SECONDS%%.*}
38
+ else
39
+ echo $TOT_SECONDS
40
+ fi
41
}
42
43
# *****************************************************************************
44
45
# Wait for input file to appear
46
# After a 30-second timeout, exit gracefully
47
CUR_TIME=30
48
- while test $CUR_TIME -gt 0; do
49
+ while test $CUR_TIME -gt 0; do
50
+ sleep 3
51
# If file exists, wait a few more seconds, then break out
52
if test -e "$FOP_OUTFILE"; then
53
- printf "Processing started. Please wait... "
54
- sleep 3s
55
+ $QUIET || printf "Processing started. Please wait... "
56
+ sleep 1
57
+ CUR_TIME=1
58
break
59
fi
60
printf "Waiting $CUR_TIME seconds for output file \"$FOP_BASENAME_NAME\" to appear...\r"
61
- sleep 1s
62
+ sleep 1
63
CUR_TIME=$(expr $CUR_TIME - 1)
64
done
65
66
67
68
# Doze a bit to let the file size increase
69
# (SLEEP_TIME defaults to 1s if unset)
70
- sleep ${SLEEP_TIME-"1s"}
71
+ sleep ${SLEEP_TIME-"1"}
72
73
FOP_LAST_SIZE=$FOP_CUR_SIZE
74
FOP_CUR_SIZE=$(du -b "$FOP_OUTFILE" | awk '{print $1}')
75
done
76
- printf "\n\n"
77
+ $QUIET && printf "\n" || printf "\n\n"
78
}
79
80
# ******************************************************************************
81
82
count=$(seq 1 $LAST)
83
for _CNTR in $(sort -nr <<< "$count")
84
do
85
- echo -n -e " in $_CNTR seconds...\r";
86
- sleep 1s;
87
+ echo -n -e " in $_CNTR seconds...or press <ENTER>\r";
88
+ read -t 1 && break;
89
done
90
}
91
92
93
done
94
return 0
95
}
96
-
97
+# *****************************************************************************
98
+# takes 1 arg: [name to prefix each line of output]
99
+# uses stdbuf (coreutils) if present so stdin is line buffered
100
+send_to_log()
101
+{
102
+ [[ $1 ]] && prog_name="[$1]: " || prog_name="[${0##*/}]: "
103
+ $std_buf tr "\015" "\n" < /dev/stdin | \
104
+ while read line; do
105
+ printf "%s %s\n" "$prog_name" "$line"
106
+ done
107
+ printf "\n"
108
+}
109
110
# ******************************************************************************
111
#
112
113
KERNEL=$(uname)
114
if test "$KERNEL" = "Linux"; then
115
# Linux should have /proc/cpuinfo
116
- CPU_MODEL=$(awk -F ":" '/model name/ {print $2}' /proc/cpuinfo | head -n 1)
117
+ CPU_MODEL=$(awk -F ":" '/model name/ {print $2}' \
118
+ /proc/cpuinfo | head -n 1 | sed 's/^ *//g')
119
CPU_SPEED=$(awk 'BEGIN { IGNORECASE = 1 } /MHz/ { print $4 }' /proc/cpuinfo | head -n 1)
120
# Test for multiple CPUs. If they are available, try to use them.
121
if test $(grep "^processor" /proc/cpuinfo | wc -l) -ge "2"; then
122
123
# tovid preferences
124
# Configures working directory for all scripts and
125
# output directory for the makempg script
126
+# also used for setting ffmpeg/avconv program
127
#WORKING_DIR=/tmp
128
#OUTPUT_DIR=/video/outfiles
129
+#TOVID_FFMPEG=ffmpeg
130
EOF`
131
printf "$PREFS_CONTENTS\n" > "$USER_PREFS"
132
fi
133
# if preferences vars are set in the environment, use those (takes precedence).
134
[[ $TOVID_WORKING_DIR ]] && WORKING_DIR="$TOVID_WORKING_DIR"
135
[[ $TOVID_OUTPUT_DIR ]] && OUTPUT_DIR="$TOVID_WORKING_DIR"
136
+[[ $TOVID_FFMPEG_CMD ]] && TOVID_FFMPEG="$TOVID_FFMPEG_CMD"
137
+# FFmpeg and FFprobe are vars used for ffmpeg by scripts needing ffmpeg/avconv
138
+# if avconv is installed, use that unless env var set
139
+hash avconv 2>/dev/null && TOVID_FFMPEG=${TOVID_FFMPEG:-avconv}
140
+hash avprobe 2>/dev/null && TOVID_FFPROBE=${TOVID_FFPROBE:=avprobe}
141
+# finally, default to ffmpeg if non of the above override it
142
+FFmpeg=${TOVID_FFMPEG:=ffmpeg}
143
+[[ $FFmpeg =~ ffmpeg ]] && TOVID_FFPROBE=ffprobe
144
+[[ $FFmpeg =~ avconv ]] && TOVID_FFPROBE=avprobe
145
+FFprobe=${TOVID_FFPROBE:=ffprobe}
146
+
147
+# stdbuf (coreutils>=7.5) is useful to todisc and makempg, use it if present
148
+hash stdbuf 2>/dev/null && std_buf="stdbuf -oL" || std_buf=""
149
150
# ******************************************************************************
151
# Check for run-time dependencies
152
153
# *************************************************************************
154
# Required Dependencies
155
# *************************************************************************
156
- core="grep sed md5sum mplayer mencoder mplex mpeg2enc yuvfps yuvdenoise ppmtoy4m mp2enc jpeg2yuv ffmpeg"
157
+ core="grep sed md5sum mplayer mplex mpeg2enc yuvfps yuvdenoise ppmtoy4m mp2enc jpeg2yuv"
158
159
# *************************************************************************
160
# Optional Dependencies
161
162
163
# -------------------------------------------------------------------------
164
# todisc dependencies
165
- todisc_deps="$magick mogrify spumux dvdauthor transcode sox"
166
+ todisc_deps="$magick mogrify spumux dvdauthor sox"
167
168
# Quit and complain if ANY core dependency is missing.
169
assert_dep "$core" "You are missing CORE tovid dependencies!"
170
+ # ffmpeg is also a part of core deps, but is taken care of here
171
+ ffmpeg_alts="Use either ffmpeg (ffmpeg.org) or avconv (libav.org)."
172
+ ffmpeg_pref="Set choice in ${USER_PREFS}. As in: TOVID_FFMPEG=ffmpeg"
173
+ assert_dep $FFmpeg "You are missing $FFmpeg ! $ffmpeg_alts ${ffmpeg_pref}."
174
175
# End tovid-init
176
tovid-0.34.tar.bz2/src/tovid.ini -> tovid-0.35.tar.gz/src/tovid.ini
Changed
54
1
2
; command, you can specify one or more "default" options that will always be
3
; passed to the 'tovid' script when used with that command.
4
;
5
+; Note that in the [gui] section you should use only boolean options as others
6
+; may have trouble loading, particularly options that 'optionally' take args or
7
+; optionally take one or many args
8
+;
9
; You can include all your desired default options on a single line, like this:
10
;
11
; [mpg]
12
13
; -device /dev/hdb
14
; -speed 8
15
16
-[menu]
17
-options =
18
-; -dvd
19
-; -align center
20
-; -textcolor #FF0000
21
-; -overwrite
22
-
23
-[vcd]
24
-options =
25
-; -device /dev/hdb
26
-; -speed 24
27
-; -quiet
28
-
29
-[xml]
30
-options =
31
-; -overwrite
32
-; -quiet
33
-; -nochapters
34
-
35
-[postproc]
36
-options =
37
-; -parallel
38
-; -normalize
39
-
40
[disc]
41
options =
42
; -thumb-shape plectrum
43
44
45
[gui]
46
options =
47
-
48
+; -no-ask
49
+; -no-warn
50
+; -no-confirm-backup
51
+; -ffmpeg
52
+; -static
53
54
tovid-0.34.tar.bz2/tovidgui.desktop -> tovid-0.35.tar.gz/tovidgui.desktop
Changed
16
1
2
Exec=tovid gui
3
Icon=tovid
4
Terminal=false
5
-GenericName=DVD creation with menus
6
-GenericName[en_US]=DVD creation with menus
7
-Comment=Author videos to DVD with menus
8
-Comment[en_US]=Author videos to DVD with menus
9
+GenericName=DVD creation with optional menus
10
+GenericName[en_US]=DVD creation with optional menus
11
+Comment=Author videos to DVD with optional menus
12
+Comment[en_US]=Author videos to DVD with optional menus
13
Categories=AudioVideo;Video;
14
StartupNotify=true
15
X-KDE-SubstituteUID=false
16