package org.jcodec.movtool;
import java.io.File;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.jcodec.containers.mp4.MP4Util;
import org.jcodec.containers.mp4.boxes.MovieBox;
import org.jcodec.movtool.Flattern.ProgressListener;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* @author The JCodec project
*
*/
public class QTEdit {
protected final CommandFactory[] factories;
private final List<ProgressListener> listeners = new ArrayList<ProgressListener>();
public static interface CommandFactory {
String getName();
Command parseArgs(List<String> args);
String getHelp();
}
public static interface Command {
/**
* Performs changes on movie header
*
* @param movie
*/
void apply(MovieBox movie);
}
public static abstract class BaseCommand implements Command {
public void apply(MovieBox movie, FileChannel[][] refs) {
apply(movie);
}
public abstract void apply(MovieBox movie);
}
public QTEdit(CommandFactory... factories) {
this.factories = factories;
}
public void addProgressListener(ProgressListener listener) {
listeners.add(listener);
}
public void execute(String[] args) throws Exception {
LinkedList<String> aa = new LinkedList<String>(Arrays.asList(args));
final List<Command> commands = new LinkedList<Command>();
while (aa.size() > 0) {
int i;
for (i = 0; i < factories.length; i++) {
if (aa.get(0).equals(factories[i].getName())) {
aa.remove(0);
try {
commands.add(factories[i].parseArgs(aa));
} catch (Exception e) {
System.err.println("ERROR: " + e.getMessage());
return;
}
break;
}
}
if (i == factories.length)
break;
}
if (aa.size() == 0) {
System.err.println("ERROR: A movie file should be specified");
help();
}
if (commands.size() == 0) {
System.err
.println("ERROR: At least one command should be specified");
help();
}
File input = new File(aa.remove(0));
if (!input.exists()) {
System.err.println("ERROR: Input file '" + input.getAbsolutePath()
+ "' doesn't exist");
help();
}
boolean inplace = new InplaceEdit() {
protected void apply(MovieBox mov) {
applyCommands(mov, commands);
}
}.save(input);
if (!inplace) {
final MovieBox movie = MP4Util.createRefMovie(input);
applyCommands(movie, commands);
File out = new File(input.getParentFile(), "." + input.getName());
Flattern fl = new Flattern();
for (ProgressListener pl : this.listeners)
fl.addProgressListener(pl);
fl.flattern(movie, out);
out.renameTo(input);
}
}
private static void applyCommands(MovieBox mov, List<Command> commands) {
for (Command command : commands) {
command.apply(mov);
}
}
protected void help() {
System.out.println("Quicktime movie editor");
System.out
.println("Syntax: qtedit <command1> <options> ... <commandN> <options> <movie>");
System.out.println("Where options:");
for (CommandFactory commandFactory : factories) {
System.out.println("\t" + commandFactory.getHelp());
}
System.exit(-1);
}
}