6
# Part of the tovid suite
7
# =======================
8
# This bash script generates XML output describing the structure of
9
# a VCD, SVCD, or DVD disc. The resulting output can be given as input
10
# to vcdxbuild or dvdauthor. Format, and a list of menus and
11
# video files in MPEG format, are specified on the command-line, and
12
# the resulting XML is written to the specified file. Currently
13
# supports an optional top-level menu, any number of optional sub-menus,
14
# and any number of videos reachable through those menus.
16
# Project homepage: http://www.tovid.org
19
# Copyright (C) 2005 tovid.org <http://www.tovid.org>
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
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.
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:
36
# http://www.gnu.org/licenses/gpl.txt
38
SCRIPTNAME=`cat << EOF
39
--------------------------------
41
A script to generate XML for authoring a VCD, SVCD, or DVD.
42
Part of the tovid suite, version $TOVID_VERSION
44
--------------------------------
48
Usage: makexml [OPTIONS] {video1.mpg video2.mpg ...} -out OUT_PREFIX
52
-dvd | -vcd | -svcd Specify the target disc format
53
-overwrite Overwrite any existing output files
55
Provide a list of .mpg video files, and they will be played back in
56
sequence. You may organize several lists of videos into menus by
57
providing the name of a menu .mpg:
59
makexml -menu menu1.mpg \\\\
60
video1.mpg video2.mpg video3.mpg \\\\
62
makexml -topmenu topmenu.mpg \\\\
63
-menu submenu1.mpg vid1.mpg vid2.mpg vid3.mpg \\\\
64
-menu submenu2.mpg vid4.mpg vid5.mpg vid6.mpg \\\\
67
See the makexml manual page ('man makexml') for additional documentation.
71
SEPARATOR="=========================================="
73
# Print script name, usage notes, and optional error message, then exit.
74
# Args: $1 == text string containing error message
84
# Currently-numbered titleset (must have at least 1 titleset)
86
# Currently-numbered video title under a titleset menu (0 for no titles)
88
# Do we have a top menu yet?
90
# Do we have any menus yet?
92
# Do not overwrite by default
94
# Use dvdauthor XML for DVD authoring
96
# No un-found files yet
98
# Not doing still titles
101
# Avoid some unbound variables
108
SEQUENCE_ITEMS_XML=""
114
FORCE_TITLESETS=false
122
# ==========================================================
123
# Backslash-escape the given special character (and any EOLs)
126
# echo $TEXT | sed "s/PATTERN/$(sedprep "$REPLACEMENT" /)/"
130
echo "$1" |sed -e 's/[\&'"$delim"']/\\&/g' -e '$!s,$,\\,';
133
# ==========================================================
134
# Check for the existence of a file and print an error if it
135
# does not exist in the current directory
136
# Args: $1 = file to look for
137
function checkExistence ()
139
if test -e "$1"; then :
141
echo "The file "$1" was not found. Exiting."
147
# ==========================================================
148
# Find a video's aspect ratio and set dvd behavior accordingly
149
# Args: $1 = video file to find aspect for
150
# Usage: noPanScan foo.avi
151
# Sets NOPANSCAN to either: widescreen="nopanscan"
153
function noPanScan ()
155
ASPECT=$(idvid -fast -terse "$1" | grep "ASPECT" | awk -F '=' '{print $2}')
156
$QUIET || echo -n " $1 has aspect $ASPECT "
157
if test $ASPECT -eq $WIDESCREEN; then
158
NOPANSCAN='widescreen="nopanscan"'
159
$QUIET || echo "(widescreen)."
162
$QUIET || echo "(standard)."
167
# ==========================================================
168
# Add a top-level VMGM menu to the DVD
169
# Args: $1 = video file to use for top menu
170
function addTopMenu ()
173
echo "Adding top-level menu using file: $1"
175
# --------------------------
177
if test $XML_FORMAT = "dvd"; then
181
# Generate XML for the top menu, with a placeholder for
182
# the titleset menu buttons (to be replaced later by sed)
183
TOP_MENU_XML=`cat << EOF
193
# --------------------------
197
# Generate XML for the segment-item
198
SEGMENT_ITEMS_XML=`cat << EOF
200
<segment-item src="$1" id="seg-top-menu"/>
203
# Generate XML for the selection to go in pbc
204
TOP_MENU_XML=`cat << EOF
205
<selection id="select-top-menu">
207
<loop jump-timing="immediate">0</loop>
208
<play-item ref="seg-top-menu"/>
216
# ==========================================================
217
# Add a menu to the disc.
218
# Args: $1 = video file to use for the menu
221
# --------------------------
223
if test $XML_FORMAT = "dvd"; then
224
echo "Adding a titleset-level menu using file: $1"
226
# Generate XML for the button linking to this titleset menu from the top menu
227
TOP_MENU_BUTTONS=`cat << EOF
229
<button>jump titleset $CUR_TS menu;</button>
235
# Generate XML for the menu header, with a placeholder for
236
# the video segment buttons (to be replaced later by sed)
247
# --------------------------
250
echo "Adding a menu using file: $1"
252
# Generate XML for the button linking to this menu from the top menu
253
TOP_MENU_BUTTONS=`cat << EOF
255
<select ref="select-menu-$CUR_TS"/>
258
# Generate XML for the segment item
259
SEGMENT_ITEMS_XML=`cat << EOF
261
<segment-item src="$1" id="seg-menu-$CUR_TS"/>
264
# Generate XML for the selection to go in pbc
265
# If there's a top menu, "return" goes back to it.
266
# Otherwise, don't use a "return" command.
267
if $HAVE_TOP_MENU; then
268
RETURN_CMD="<return ref=\"select-top-menu\"/>"
272
SELECTION_XML=`cat << EOF
273
<selection id="select-menu-$CUR_TS">
276
<loop jump-timing="immediate">0</loop>
277
<play-item ref="seg-menu-$CUR_TS"/>
285
# ==========================================================
286
# Add a video title to a titleset menu, or a still image to
288
# Args: $1 = video file to use for the title
291
if $FORCE_TITLESETS && test $CUR_VIDEO -eq 0; then
294
# Increment the current title number
295
if ! $MAKE_GROUP; then
298
# Grouping several videos within one title
299
if test $CUR_VIDEO -eq 0; then
304
# --------------------------
306
if test $XML_FORMAT = "dvd"; then
307
if ! $MAKE_GROUP; then
308
echo "Adding title: $1 as title number $CUR_TITLE of titleset $CUR_TS"
310
if test $CUR_VIDEO -eq 1; then
311
echo "Adding title number $CUR_TITLE of titleset $CUR_TS"
313
echo "Adding $1 as video $CUR_VIDEO of title $CUR_TITLE"
319
# Generate XML for the button linking to this title from the titleset menu
320
if ! $FORCE_TITLESETS; then
321
if test $CUR_VIDEO -lt 2; then
322
MENU_BUTTONS=`cat << EOF
324
<button>jump title $CUR_TITLE;</button>
328
# Add a button for the current titleset to the top menu
329
if test $CUR_VIDEO -le 1; then
330
TOP_MENU_BUTTONS=`cat << EOF
332
<button>jump titleset $CUR_TS menu;</button>
337
# Generate the chapters tag
338
# If file exists, get duration and add appropriate chapter breaks
339
if test -e "$1" && $MAKE_CHAPTERS; then
340
CMD="idvid -terse \"$1\""
341
echo " Calculating the duration of the video with:"
343
echo " This may take a few minutes, so please be patient..."
344
DURATION=$(eval $CMD | grep DURATION | awk -F '=' '{print $2}')
345
echo $DURATION | awk '{hh=int($1/3600);mm=int(($1-hh*3600)/60);ss=$1-hh*3600-mm*60;\
346
printf " The duration of the video is %02d:%02d:%02d\n",hh,mm,ss}'
348
CHAPTERS=`echo $DURATION $CHAPTER_INTERVAL | \
363
mm=int((cur-hh*3600)/60);\
364
ss=cur-hh*3600-mm*60;\
365
printf "%02d:%02d:%02d",hh,mm,ss;
369
# If file doesn't exist, or -nochapters was passed, use 0 chapters
374
# Generate the XML for the title itself, appending to existing titles
376
if test $CUR_VIDEO -eq 1; then
377
TS_TITLES=`cat << EOF
382
TS_TITLES=`cat << EOF
384
<vob file="$1" chapters="$CHAPTERS" />
387
TS_TITLES=`cat << EOF
390
<vob file="$1" chapters="$CHAPTERS" />
396
# --------------------------
400
# If there's a menu, "return" goes back to it; if not,
401
# do not generate a "return" command
403
RETURN_CMD="<return ref=\"select-menu-$CUR_TS\"/>"
407
# If this is the first title or slide in a series
408
if $FIRST_TITLE; then
409
# For the first titles, PREV stays on the current title
410
let "PREV_TITLE=$CUR_TITLE"
411
# For all other titles
413
# PREV goes to the previous slide
414
let "PREV_TITLE=$CUR_TITLE - 1"
417
# Fill in the NEXT command for the previous slide, if there was one
418
NEXT_TITLE="<next ref=\"play-title-$CUR_TITLE\"\/>"
419
SELECTION_XML=$( echo "$SELECTION_XML" | sed -e "s/__NEXT_TITLE__/$NEXT_TITLE/g" )
420
PLAYLIST_XML=$( echo "$PLAYLIST_XML" | sed -e "s/__NEXT_TITLE__/$NEXT_TITLE/g" )
422
# --------------------------
423
# If doing a still-image slideshow, use segment/selection
424
if $STILL_TITLES; then
425
echo "Adding title: $1 as number $CUR_TITLE in a slideshow"
427
# Generate XML for the selection (menu) "buttons" that will
428
# jump to this slideshow. Only the first slide gets a button.
429
if $FIRST_TITLE; then
430
MENU_BUTTONS=`cat << EOF
432
<select ref="play-title-$CUR_TITLE"/>
436
# Generate XML for the segment item
437
SEGMENT_ITEMS_XML=`cat << EOF
439
<segment-item src="$1" id="seg-slide-$CUR_TITLE"/>
442
# Generate XML for the selection to go in pbc
443
# The slide will play indefinitely until NEXT, PREV,
444
# or RETURN is pressed. __NEXT_TITLE__ is a placeholder
445
# until we're sure there is a next slide; it will be
446
# filled in on the next addition if there is.
447
SELECTION_XML=`cat << EOF
449
<playlist id="play-title-$CUR_TITLE">
450
<prev ref="play-title-$PREV_TITLE"/>
454
<play-item ref="seg-slide-$CUR_TITLE"/>
458
# --------------------------
459
# If doing normal video titles, use select/playlist
462
echo "Adding title: $1 as title number $CUR_TITLE"
464
# Generate XML for the selection (menu) "buttons" that will
465
# jump to this playlist (title)
466
MENU_BUTTONS=`cat << EOF
468
<select ref="play-title-$CUR_TITLE"/>
471
# Generate XML for the sequence item
472
SEQUENCE_ITEMS_XML=`cat << EOF
474
<sequence-item src="$1" id="seq-title-$CUR_TITLE"/>
477
# Generate XML for the playlist for this title
478
PLAYLIST_XML=`cat << EOF
480
<playlist id="play-title-$CUR_TITLE">
481
<prev ref="play-title-$PREV_TITLE"/>
485
<play-item ref="seq-title-$CUR_TITLE"/>
489
fi # (S)VCD slides or normal titles
496
# ==========================================================
497
# Finalize the XML for a titleset, containing a menu and titles
498
function closeTitleset ()
500
# Proceed only if there are titles in this titleset
501
if (( $CUR_TITLE > 0 )); then
503
# --------------------------
505
if test $XML_FORMAT = "dvd"; then
506
echo "Closing titleset $CUR_TS with $CUR_TITLE title(s)."
508
# Give each menu a button linking back to the top menu, if there is one
509
if $HAVE_TOP_MENU; then
510
MENU_BUTTONS=`cat << EOF
512
<button>jump vmgm menu;</button>
517
# Fill in titleset menu buttons
518
MENU_XML=$(echo "$MENU_XML" | \
519
sed -e "s/__MENU_BUTTONS__/$(sedprep "$MENU_BUTTONS" /)/g")
521
# Fill in the POST command. If there is a menu to jump back to, use that;
522
# otherwise, do not insert a POST command.
524
POST_CMD="<post>call menu;<\/post>"
525
elif $FORCE_TITLESETS && $HAVE_TOP_MENU; then
526
POST_CMD="<post>call vmgm menu;<\/post>"
530
TS_TITLES=$( echo "$TS_TITLES" | sed -e "s/__POST_CMD__/$POST_CMD/g" )
532
# Append titleset info to ALL_MENU_XML
533
if ! $FORCE_TITLESETS || ! $HAVE_TOP_MENU; then
534
ALL_MENU_XML=`cat << EOF
545
# One titleset for each title -> add a dummy menu to the titleset
546
ALL_MENU_XML=`cat << EOF
563
# Clear existing XML to prepare for next titleset
569
# --------------------------
573
# Fill in menu title selections ("buttons")
574
# and remove any remaining __NEXT_TITLE__s
575
SELECTION_XML=$(echo "$SELECTION_XML" | \
576
sed -e "s/__MENU_BUTTONS__/$(sedprep "$MENU_BUTTONS" /)/g" -e "s/__NEXT_TITLE__//g")
577
PLAYLIST_XML=$(echo "$PLAYLIST_XML" | sed -e "s/__NEXT_TITLE__//g")
579
# Append new PBC menus/playlists to PBC_XML
587
# Clear existing XML to prepare for next menu/titles
591
# Go back to doing normal video titles
595
# Increment the current titleset number
598
fi # End if there are titles
601
# ==========================================================
602
# EXECUTION BEGINS HERE
605
if test $# -lt 1; then
606
usage_error "Please provide at least one video to author, and the name of an output file to use."
609
while test $# -gt 0; do
618
# Format and overwriting options
619
"-dvd" ) XML_FORMAT="dvd" ;;
620
"-vcd" ) XML_FORMAT="vcd" ;;
621
"-svcd" ) XML_FORMAT="svcd" ;;
622
"-overwrite" ) OVERWRITE=: ;;
623
# Menus and video titles
626
if ! $HAVE_TOP_MENU; then
630
usage_error "Please specify only one -topmenu option. If you would like to have multiple menus, please use the -menu option."
634
if $FORCE_TITLESETS; then
635
usage_error "You can not use -titlesets with -menu. Please use -topmenu instead."
654
TS_TITLES=`cat << EOF
664
# Space-separated list of comma-separated chapter points
667
IFS=""; while test $# -gt 0 && test ${1:0:1} != "-"; do
668
CHAPTER_POINTS=("${CHAPTER_POINTS[@]}" "$1")
671
if test $# -gt 0 && test ${1:0:1} = "-"; then
677
# Fixed chapter intervals
681
if test "$CHAPTER_INTERVAL" -lt "0" || \
682
test "$CHAPTER_INTERVAL" -gt "9999";
684
usage_error "Please use a -chapters interval between 0 and 9999."
692
usage_error "You can not use -titlesets with -menu. Please use -topmenu instead."
695
echo "Creation of titlesets forced ..."
702
# Get the next argument
706
# Last argument should be the name of the output file
707
if test -z "$OUT_PREFIX"; then
708
usage_error "Please provide an output filename with -out."
711
# See if selected output file exists. If so, confirm for overwrite.
712
if test -e "$OUT_PREFIX.xml"; then
714
echo "*** The output file you specified: $OUT_PREFIX.xml already exists."
716
echo "Overwriting existing file."
718
echo "Please re-run the script with the -overwrite option to overwrite."
725
# Close current titleset
728
# Fill in top menu buttons
729
TOP_MENU_XML=$(echo "$TOP_MENU_XML" | \
730
sed -e "s/__TOP_MENU_BUTTONS__/$(sedprep "$TOP_MENU_BUTTONS" /)/g")
732
# If there is a top menu with no other menus, print an error and
733
# a suggestion that user specify -menu instead of -topmenu
734
if $HAVE_TOP_MENU && ! $HAVE_MENU && ! $FORCE_TITLESETS; then
735
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."
736
echo "Exiting without writing XML file."
740
# Assemble the final XML file
742
# dvdauthor format for a DVD
743
if test $XML_FORMAT = "dvd" ; then
744
FINAL_DISC_XML=`cat << EOF
745
<dvdauthor dest="$OUT_PREFIX">
746
<!-- makexml $TOVID_VERSION -->
754
# vcdxbuild (vcdimager) format for a VCD or SVCD
756
# Determine what version number to use
757
if test $XML_FORMAT = "vcd" ; then
763
OPTION_LINE='<option name="update scan offsets" value="true" />'
766
# Make sure there are segment-items and sequence-items
767
if test -n "$SEGMENT_ITEMS_XML" ; then
768
SEGMENT_ITEMS_XML=`cat << EOF
774
if test -n "$SEQUENCE_ITEMS_XML" ; then
775
SEQUENCE_ITEMS_XML=`cat << EOF
782
FINAL_DISC_XML=`cat << EOF
783
<?xml version="1.0"?>
784
<!DOCTYPE videocd PUBLIC "-//GNU/DTD VideoCD//EN"
785
"http://www.gnu.org/software/vcdimager/videocd.dtd">
786
<videocd xmlns="http://www.gnu.org/software/vcdimager/1.0/"
787
class="$XML_FORMAT" version="$VCD_VERSION">
790
<album-id>VIDEO_DISC</album-id>
791
<volume-count>1</volume-count>
792
<volume-number>1</volume-number>
793
<restriction>0</restriction>
797
<volume-id>VIDEO_DISC</volume-id>
798
<system-id>CD-RTOS CD-BRIDGE</system-id>
814
# Remove blank lines and write final result to output file
815
echo "$FINAL_DISC_XML" | sed -e '/^ *$/d' > "$OUT_PREFIX.xml"
817
if $FILE_NOT_FOUND; then
819
echo "Some of the video files you specified were not found."
820
echo "The XML file was written anyway, but you might want to"
821
echo "double-check to make sure you didn't make a typing mistake."
824
echo "Done. The resulting XML was written to $OUT_PREFIX.xml."
827
if test $XML_FORMAT = "dvd" ; then
828
echo "You can now author, image and/or burn the disc by running:"
829
echo " makedvd \"$OUT_PREFIX.xml\""
831
echo "You can create the (S)VCD .bin and .cue files by running the command:"
832
echo " makevcd \"$OUT_PREFIX.xml\""
834
echo "Thanks for using makexml!"