Ticket #2968: mytharchive-label-print

File mytharchive-label-print, 7.5 KB (added by schachte@…, 14 years ago)
Line 
1#!/usr/bin/env python
2#
3#  Copyright 2007 by Peter Schachte
4#
5# This script is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public
7# License as published by the Free Software Foundation; either
8# version 2 of the License, or (at your option) any later version.
9#
10# This script is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public
16# License along with this library; if not, write to the
17# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18# Boston, MA 02111-1307, USA.
19
20
21################################################################
22# Generate nice printed labels for standard DVD boxes holding up to 4
23# mytharchive native archive format DVDs.  This relies on cdlabelgen
24# (http://www.aczoom.com/tools/cdinsert/) to do the actual postscript
25# formatting.  It examines the DVD(s), reading the relevant information
26# from the xml file stored on the disc itself to construct a suitable
27# label listing the videos included on each disc in the box.
28#
29# Currently, this script supports only native format archives, and only
30# mythvideo files.  I'd like to support DVD format archives as well,
31# but they do not contain the necessary information.  This script
32# should be able to support recordings, but I have not implemented this
33# yet.
34#
35# This code supports naming all discs with a common prefix (by
36# default "MythArchive Disc ").  As each disc is inserted, you will
37# be prompted for its number; the full name of the disc is the prefix
38# followed by the entered text.  The prefix can be set to anything on
39# the command line, including the empty string, and any text can be
40# entered for the disc "number."
41################################################################
42
43
44import sys, os, glob
45from optparse import OptionParser
46from elementtree.ElementTree import ElementTree
47
48################################################################
49# Command line parsing and help text
50
51def parse_command_line():
52    """Handle parsing of command line."""
53    parser = OptionParser(version="0.1")
54    parser.add_option("-o", "--outfile", metavar="FILE", default="-",
55                      help="write postscript output to FILE [default: stdout]")
56    parser.add_option("-q", "--quiet", action="store_false",
57                      dest="verbose", default=True,
58                      help="don't print status messages to stderr")
59    parser.add_option("-m", "--mountpoint", metavar="DIR",
60                      help="mount DVD on DIR [default /media/cdrom]",
61                      default="/media/cdrom")
62    parser.add_option("-p", "--prefix", metavar="TEXT",
63                      help="common prefix for discs " +
64                           "[default 'MythArchive Disc ']",
65                      default="MythArchive Disc ")
66    (options,args) = parser.parse_args()
67    return options
68
69
70################################################################
71# Main code
72
73def main():
74    options = parse_command_line()
75    discs = []
76    while True:
77        added = get_titles(options)
78        if added is None: break
79        discs.append(added)
80
81    if discs:
82        generate_cover(discs, options)
83    else:
84        sys.stderr.write("No titles found; no label generated.\n")
85        sys.exit(1)
86
87
88################################################################
89# Read one DVD to see what's on it
90
91def get_titles(options):
92    """Ask user to insert one DVD, and return list of items it contains."""
93    while True:
94        sys.stderr.write("Insert DVD to include in DVD label now, " +
95                         "then enter the MythArchive\n")
96        sys.stderr.write("disc number, or just hit enter if there are " +
97                         "no more DVDs to include\n")
98        sys.stderr.write("Disc number, or enter to quit:  ")
99        discnum = sys.stdin.readline().strip()
100        if discnum == "": return None
101        if 0 != os.system("mount -r " + options.mountpoint):
102            sys.stderr.write("Error:  couldn't mount DVD on " +
103                             options.mountpoint + "\n")
104            continue
105        items = []
106        for dirname in os.listdir(options.mountpoint):
107            if options.verbose:
108                sys.stderr.write("    " + dirname + "\n")
109            for filename in glob.glob(options.mountpoint + "/" +
110                                      dirname + "/*.xml"):
111                # there should only be one xml file in each directory
112                items.append(ElementTree(file=filename).getroot())
113               
114        os.system("eject " + options.mountpoint)
115        return (discnum, items)
116
117################################################################
118# Finally generate the cover Postscript file
119
120def generate_cover(discs, options):
121    """Generate the DVD cover postscript output for the specified titles."""
122    lines = []
123    if len(discs) > 1:
124        names = [name for (name,content) in discs]
125        title = options.prefix + ", ".join(names[0:-1]) + " and " + names[-1]
126        for (name,content) in discs:
127            lines.append("")
128            lines.append("{#BI}     ----- " +
129                           options.prefix + name + " -----")
130            lines.append("")
131            lines += text_for_one_disc(content, options)
132            lines.append("")
133    else:
134        title = options.prefix + discs[0][0]
135        lines += text_for_one_disc(discs[0][1], options)
136
137   
138    if options.verbose:
139        sys.stderr.write(
140            ("cdlabelgen --create-dvd-outside -c '%s' " +
141             "-w -o '%s' -v 40 -i '%s'\n") % \
142            (quote(title), quote(options.outfile), quote("%".join(lines))))
143    sys.exit(os.system(
144        "cdlabelgen --create-dvd-outside -c '%s' -w -o '%s' -v 40 -i '%s'" % \
145        (quote(title), quote(options.outfile), quote("%".join(lines)))))
146
147
148################################################################
149# Generate the output for one disc
150
151def text_for_one_disc(content, options):       
152    lines = []
153    for item in content:
154        meta = item.find("videometadata")
155        if item.get("type") == "video" and meta:
156            title = meta.findtext("title")
157            if title:
158                text = "{#B}" + title
159                year     = meta.findtext("year")
160                if year: text += " (" + year + ")"
161                lines.append(text)
162               
163                line = []
164                gens     = item.find("genres")
165                if gens:
166                    line.append(", ".join([g.get("genre") for g in gens]))
167                length   = meta.findtext("length")
168                if length and length != "0":
169                    line.append("Running time: %s minutes" % length)
170                if line: lines.append("; ".join(line))
171
172                line = []
173                rating   = meta.findtext("rating")
174                if rating: line.append(rating)
175                imdb     = meta.findtext("userrating")
176                if imdb: line.append("IMDB rating: %s / 10" % imdb)
177                if line: lines.append("; ".join(line))
178                lines.append("")
179    return lines
180
181################################################################
182# Protect single quote characters from the shell
183
184def quote(str):
185    """Return the input string with single quotes escaped."""
186    return str.replace("'", "'\"'\"'")
187
188################################################################
189
190if __name__ == "__main__":
191    main()