mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-13 02:08:13 +00:00
Bulk import movies
This commit is contained in:
@@ -26,30 +26,101 @@ import com.jpexs.decompiler.flash.tags.PlaceObject2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class MovieImporter {
|
||||
public void importMovie(DefineVideoStreamTag movie, InputStream fis) throws IOException {
|
||||
|
||||
public int bulkImport(File moviesDir, SWF swf, boolean printOut) {
|
||||
Map<Integer, CharacterTag> characters = swf.getCharacters();
|
||||
int movieCount = 0;
|
||||
List<String> extensions = Arrays.asList("flv");
|
||||
File allFiles[] = moviesDir.listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
String nameLower = name.toLowerCase();
|
||||
for (String ext : extensions) {
|
||||
if (nameLower.endsWith("." + ext)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
for (int characterId : characters.keySet()) {
|
||||
CharacterTag tag = characters.get(characterId);
|
||||
if (tag instanceof DefineVideoStreamTag) {
|
||||
DefineVideoStreamTag movieTag = (DefineVideoStreamTag) tag;
|
||||
List<File> existingFilesForMovieTag = new ArrayList<>();
|
||||
for (File f : allFiles) {
|
||||
if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) {
|
||||
existingFilesForMovieTag.add(f);
|
||||
}
|
||||
}
|
||||
existingFilesForMovieTag.sort(new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File o1, File o2) {
|
||||
String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1);
|
||||
String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1);
|
||||
int ret = extensions.indexOf(ext1) - extensions.indexOf(ext2);
|
||||
if (ret == 0) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
});
|
||||
|
||||
if (existingFilesForMovieTag.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (existingFilesForMovieTag.size() > 1) {
|
||||
Logger.getLogger(MovieImporter.class.getName()).log(Level.WARNING, "Multiple matching files for movie tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForMovieTag.get(0).getName()});
|
||||
}
|
||||
File sourceFile = existingFilesForMovieTag.get(0);
|
||||
|
||||
try {
|
||||
if (printOut) {
|
||||
System.out.println("Importing character " + characterId + " from file " + sourceFile.getName());
|
||||
}
|
||||
importMovie(movieTag, Helper.readFile(sourceFile.getAbsolutePath()));
|
||||
movieCount++;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Cannot import movie " + characterId + " from file " + sourceFile.getName(), ex);
|
||||
}
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return movieCount;
|
||||
}
|
||||
|
||||
public void importMovie(DefineVideoStreamTag movie, byte[] data) throws IOException {
|
||||
List<FLVTAG> videoTags = new ArrayList<>();
|
||||
|
||||
FLVInputStream flvIs = new FLVInputStream(fis);
|
||||
FLVInputStream flvIs = new FLVInputStream(new ByteArrayInputStream(data));
|
||||
Reference<Boolean> audioPresent = new Reference<>(false);
|
||||
Reference<Boolean> videoPresent = new Reference<>(false);
|
||||
flvIs.readHeader(audioPresent, videoPresent);
|
||||
|
||||
@@ -592,6 +592,12 @@ public class CommandLineArgumentParser {
|
||||
out.println(" ...imports Symbol-Class mapping to <infile> and saves the result to <outfile>");
|
||||
}
|
||||
|
||||
if (filter == null || filter.equals("importmovies")) {
|
||||
out.println(" " + (cnt++) + ") -importMovies <infile> <outfile> <moviesfolder>");
|
||||
out.println(" ...imports movies to <infile> and saves the result to <outfile>");
|
||||
}
|
||||
|
||||
|
||||
if (filter == null || filter.equals("importshapes")) {
|
||||
out.println(" " + (cnt++) + ") -importShapes <infile> <outfile> [nofill] <shapesfolder>");
|
||||
out.println(" ...imports shapes to <infile> and saves the result to <outfile>");
|
||||
@@ -1031,6 +1037,8 @@ public class CommandLineArgumentParser {
|
||||
parseDoc(args);
|
||||
} else if (command.equals("importsymbolclass")) {
|
||||
parseImportSymbolClass(args, charset);
|
||||
} else if (command.equals("importmovies")) {
|
||||
parseImportMovies(args, charset);
|
||||
} else if (command.equals("importshapes")) {
|
||||
parseImportShapes(args, charset);
|
||||
} else if (command.equals("importimages")) {
|
||||
@@ -3215,7 +3223,7 @@ public class CommandLineArgumentParser {
|
||||
} else if (characterTag instanceof DefineVideoStreamTag) {
|
||||
DefineVideoStreamTag movie = (DefineVideoStreamTag)characterTag;
|
||||
try {
|
||||
new MovieImporter().importMovie(movie, new ByteArrayInputStream(data));
|
||||
new MovieImporter().importMovie(movie, data);
|
||||
} catch (IOException iex) {
|
||||
System.err.println("Import FAILED: "+iex.getMessage());
|
||||
System.exit(1);
|
||||
@@ -3805,6 +3813,42 @@ public class CommandLineArgumentParser {
|
||||
System.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseImportMovies(Stack<String> args, String charset) {
|
||||
if (args.size() < 3) {
|
||||
badArguments("importmovies");
|
||||
}
|
||||
|
||||
File inFile = new File(args.pop());
|
||||
File outFile = new File(args.pop());
|
||||
|
||||
try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) {
|
||||
SWF swf = new SWF(is, Configuration.parallelSpeedUp.get(), charset);
|
||||
System.out.println("Source file opened");
|
||||
String selFile = args.pop();
|
||||
|
||||
File moviesDir = new File(Path.combine(selFile, MovieExportSettings.EXPORT_FOLDER_NAME));
|
||||
if (moviesDir.exists()) {
|
||||
System.out.println("Using the directory: " + moviesDir.getAbsolutePath());
|
||||
} else {
|
||||
moviesDir = new File(selFile);
|
||||
}
|
||||
if (!moviesDir.exists()) {
|
||||
System.err.println("Movies directory does not exist: " + moviesDir.getAbsolutePath());
|
||||
System.exit(1);
|
||||
}
|
||||
MovieImporter movieImporter = new MovieImporter();
|
||||
int movieCount = movieImporter.bulkImport(moviesDir, swf, true);
|
||||
System.out.println("Writing outfile");
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) {
|
||||
swf.saveTo(fos);
|
||||
}
|
||||
System.out.println("" + movieCount + " movies successfully imported");
|
||||
} catch (IOException | InterruptedException e) {
|
||||
System.err.println("I/O error during writing");
|
||||
System.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseImportImages(Stack<String> args, String charset) {
|
||||
if (args.size() < 3) {
|
||||
|
||||
@@ -3067,7 +3067,60 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
}
|
||||
|
||||
public void importMovie(final SWF swf) {
|
||||
|
||||
ViewMessages.showMessageDialog(MainPanel.this, translate("message.info.importMovies2"), translate("message.info"), JOptionPane.INFORMATION_MESSAGE, Configuration.showImportShapeInfo);
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get()));
|
||||
chooser.setDialogTitle(translate("import.select.directory"));
|
||||
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
chooser.setAcceptAllFileFilterUsed(false);
|
||||
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||||
String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath();
|
||||
File moviesDir = new File(Path.combine(selFile, MovieExportSettings.EXPORT_FOLDER_NAME));
|
||||
if (!moviesDir.exists()) {
|
||||
moviesDir = new File(selFile);
|
||||
}
|
||||
final File fMoviesDir = moviesDir;
|
||||
MovieImporter movieImporter = new MovieImporter();
|
||||
|
||||
final long timeBefore = System.currentTimeMillis();
|
||||
new CancellableWorker<Void>() {
|
||||
|
||||
private int count = 0;
|
||||
|
||||
@Override
|
||||
public Void doInBackground() throws Exception {
|
||||
try {
|
||||
count = movieImporter.bulkImport(fMoviesDir, swf, false);
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Error during import", ex);
|
||||
ViewMessages.showMessageDialog(null, translate("error.import") + ": " + ex.getClass().getName() + " " + ex.getLocalizedMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
Main.startWork(translate("work.importing") + "...", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
Main.stopWork();
|
||||
long timeAfter = System.currentTimeMillis();
|
||||
final long timeMs = timeAfter - timeBefore;
|
||||
|
||||
View.execInEventDispatch(() -> {
|
||||
refreshTree(swf);
|
||||
setStatus(translate("import.finishedin").replace("%time%", Helper.formatTimeSec(timeMs)));
|
||||
|
||||
ViewMessages.showMessageDialog(MainPanel.this, translate("import.movie.result").replace("%count%", Integer.toString(count)));
|
||||
if (count != 0) {
|
||||
reload(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
public void importShape(final SWF swf, boolean noFill) {
|
||||
ViewMessages.showMessageDialog(MainPanel.this, translate("message.info.importShapes2"), translate("message.info"), JOptionPane.INFORMATION_MESSAGE, Configuration.showImportShapeInfo);
|
||||
@@ -4105,8 +4158,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
||||
previewPanel.clear();
|
||||
DefineVideoStreamTag movie = (DefineVideoStreamTag) item;
|
||||
File selfile = Helper.fixDialogFile(selectedFile);
|
||||
try (FileInputStream fis = new FileInputStream(selfile)) {
|
||||
new MovieImporter().importMovie(movie, fis);
|
||||
try {
|
||||
new MovieImporter().importMovie(movie, Helper.readFile(selfile.getAbsolutePath()));
|
||||
refreshTree();
|
||||
} catch (IOException ex) {
|
||||
ViewMessages.showMessageDialog(MainPanel.this, translate("error.movie.invalid") + ": "+ex.getMessage(), translate("error"), JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
@@ -1091,4 +1091,11 @@ error.sound.rate = The input sound has unsupported sampling rate: %saplingRate%.
|
||||
filter.movies = Supported movie formats (%extensions%)
|
||||
error.movie.invalid = Invalid movie.
|
||||
|
||||
menu.file.import.movie = Import movies
|
||||
menu.file.import.movie = Import movies
|
||||
|
||||
message.info.importMovies2 = During importing movies, you need to select a FOLDER.\r\n \
|
||||
Filenames inside the folder must match existing movies in current selected SWF.\r\n \
|
||||
If there exist "movies" folder inside, it is selected instead.\r\n \
|
||||
The best way to get the structure right is to export images in current SWF file first.
|
||||
|
||||
import.movie.result = %count% movies imported.
|
||||
|
||||
@@ -1071,4 +1071,16 @@ status.editing.autosave = Jste v EDITA\u010cN\u00cdM re\u017eimu. Prove\u010fte
|
||||
|
||||
error.sound.rate = Vstupn\u00ed zvuk m\u00e1 nepodporovanou vzorkovac\u00ed frekvenci: %saplingRate%.\r\n\
|
||||
P\u0159ed importem je t\u0159eba zvuk zkonvertovat n\u011bjak\u00fdm editorem zvuku\r\n\
|
||||
do jedn\u00e9 z podporovan\u00fdch frekvenc\u00ed (%supportedRates%).
|
||||
do jedn\u00e9 z podporovan\u00fdch frekvenc\u00ed (%supportedRates%).
|
||||
|
||||
filter.movies = Podporovan\u00e9 form\u00e1ty videa (%extensions%)
|
||||
error.movie.invalid = Neplatn\u00e9 video.
|
||||
|
||||
menu.file.import.movie = Importovat videa
|
||||
|
||||
message.info.importMovies2 = B\u011bhem importu vide\u00ed mus\u00edte vybrat SLO\u017dKU.\r\n \
|
||||
N\u00e1zvy soubor\u016f uvnit\u0159 mus\u00ed souhlasit s existuj\u00edc\u00edmi videi v pr\u00e1v\u011b vybran\u00e9m SWF.\r\n \
|
||||
Pokud je uvnit\u0159 slo\u017eka "movies", pak je vybr\u00e1na m\u00edsto n\u00ed.\r\n \
|
||||
Nejlep\u0161\u00ed zp\u016fsob jak m\u00edt tuto strukturu spr\u00e1vn\u011b je nejprve exportovat videa v aktu\u00e1ln\u00edm SWF souboru.
|
||||
|
||||
import.movie.result = %count% vide\u00ed importov\u00e1no.
|
||||
Reference in New Issue
Block a user