Talk:Development plans
From Tovid Wiki
Edit this page to leave a comment. For thread-like discussion, use one or more colons to indent your comments, and please use four tildes ~~~~ to sign your name at the end, like so:
: Spam :: And eggs ~~~~
Contents |
[edit] Top-down
I've hastily outlined a top-level libtovid interface for version 0.30. For a while, I've been thinking mostly top-up: what building blocks are needed for doing all the stuff tovid (as a suite) needs to do? But Python is good for top-down development too, and I'd like to try to work downwards another layer:
$ python >>> from libtovid import DVD
Here, I'm assuming that DVD is some kind of encapsulation of what a DVD video disc is, with an interface that makes creating one easy. Most likely, DVD is a class; classes have constructors:
>>> mydvd = DVD("Movie trailers", 'ntsc')
From this we can infer that mydvd is now a representation of a DVD disc called "Movie trailers", and that it's NTSC format. Other than that, it's a blank disc. It needs some videos:
>>> mydvd.add_videos('/pub/video/trailers')
Added 12 videos to DVD disc "Movie trailers".
OK, this allows you to add a directory full of videos, and prints a helpful confirmation message. The DVD object (mydvd) presumably searches that directory and stores a list of filenames. It's also safe to assume that there are other ways of adding videos (by individual filename, by reading a text file with a list of filenames, etc.) but this one just happens to be the most convenient. We can also assume that there are equally simple approaches to specifying the title of each video.
DVDs gotta allow some kind of control over video quality, right? Something simple like:
>>> mydvd.quality('medium')
Using medium quality video encoding.
Of course, this implies that you could configure other attributes about the disc--whether to use widescreen, subtitles, or multiple audio tracks, or what the maximum video bitrate should be. And of course, controlling those things on a per-video basis is a must, too. But that stuff is for advanced users, right?
With 12 videos on the disc, it'll be a hassle to press "next" for each one, so it might be good to have a menu to choose them from. Like so:
>>> mydvd.thumb_menu(background="/pub/images/sky.png") Creating a thumbnail menu with a background image.
Hey presto, the DVD will now have a main menu showing thumbnail animations of each video, and will have "sky.png" in the background. We could most likely display some kind of a preview at this point, but we're confident in libtovid's abilities and sail on into transcoding:
>>> mydvd.transcode(author=True) Encoding videos: 25%..50%..75%..100% Done! Generating menus: 25%..50%..75%..100% Done! Authoring disc: 25%..50%..75%..100% Done! DVD "Movie trailers" is done authoring.
This stuff takes a long time, which is why regular updates are shown on handy progress-meters, as all the videos are encoded to compliant MPEG formats, our nice thumbnail menu is created, and the dvdauthor XML is written to author the disc. In fact, we planned on leaving this to work for several hours, so might as well author the disc too, while we're gone. Once it finishes, you can preview the DVD in a program of your choice (gxine default, say):
>>> mydvd.preview() Showing preview of disc in gxine... (press ESC to exit)
Looks good, so it's time to burn it:
>>> mydvd.burn(speed=2) Burning DVD "Movie trailers" to /dev/dvdrw...
At the very least, this should provide us with some direction towards what needs work. -- Wapcaplet 05:29, 8 November 2006 (UTC)
- I've implemented some "fake" classes and functions that implement the above behavior. Install from SVN to try it out, and read the comments in libtovid/__init__.py (under "Target interface for version 0.30") for the rationale. -- Wapcaplet 23:45, 8 November 2006 (UTC)
[edit] Easier said than done
Here's how I've been approaching the implementation of this desired interface:
[edit] Axioms
- Say it, don't do it, unless doing it is actually easier than saying it.
- If it takes several sentences to fully say it, invent a function for each sentence, and call those functions.
- If there are lots of functions, put related ones into classes, and use the class's interface.
- If there are lots of classes, put related ones into modules, and import those modules.
[edit] Example
Here's an initial implementation of the DVD class that is used in the Python examples above:
class DVD:
def add_videos(self, directory):
print "Adding videos in %s" % directory
def thumb_menu(self, background):
print "Creating a thumbnail menu with a background image."
All I'm doing is defining the functions I want to be able to use, and printing out what they do. These take arguments, which can be used in the print message to help say what the function is doing. self makes it object-oriented, so I can have several DVDs going at once.
Creating a thumbnail menu is a pretty complex task, so let's assume it's all handled by a Menu class (which we'll define later). Pretend it has functions for adding a list of videos, and for defining a background image, and that you can configure what kind and format of menu it is by passing arguments to the Menu() constructor function. Here's the new thumb_menu function using it:
def thumb_menu(self, background):
print "Creating a thumbnail menu with a background image."
self.menu = Menu('DVD', 'thumbnail')
self.menu.add_videos(self.videos)
self.menu.set_background(background)
The video titles added to the menu should be the same ones that were given to the add_videos function, which implies that the DVD class somehow stores that list. Above, I'm assuming it's in self.videos.
It would be nice if add_videos actually added some videos to that list. I'm hoping to read some in from a directory, but am too lazy to look up how to do that right now, so I just write a little example; I can come back and do it the right way later:
def add_videos(self, directory):
print "Adding videos in %s" % directory
for filename in ["First.mpg", "Second.mpg", "Third.mpg"]:
title = filename.rstrip('.mpg')
self.videos.append(Video(filename, title))
In the middle of writing this function, it occurs to me that there ought to be a Video class, to make it easy to pass around filenames and titles. So I treat self.videos as a list of Video objects, and append to it.
Don't worry about leaving stuff half-implemented or missing; Python will warn you if you forget to implement Video:
>>> mydvd = DVD()
>>> mydvd.add_videos('/foo')
DVD: Adding videos in /foo
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "libtovid/__init__.py", line 92, in add_videos
self.videos.append(Video(filename, title))
NameError: global name 'Video' is not defined
Not a problem; at this point, the Video class has just about written itself:
class Video:
def __init__(self, filename, title):
print "Creating a Video from file %s entitled %s" %\
(filename, title)
I can then build on this later if necessary. This is a quick and easy way to work out a desired program structure; think of it as a program outline, where all the details can be filled in later.
-- Wapcaplet 07:16, 9 November 2006 (UTC)
