From 0272175e0033387f1f2c51b551dfe593c16b99ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Tue, 27 Dec 2022 18:26:55 +0100 Subject: [PATCH] Added Bulk import sounds and sound streams --- CHANGELOG.md | 1 + .../flash/configuration/Configuration.java | 4 + .../flash/importers/SoundImporter.java | 100 +++++++++++++ .../decompiler/flash/tags/base/SoundTag.java | 2 + .../console/CommandLineArgumentParser.java | 141 ++++++++++++++---- .../decompiler/flash/gui/MainFrameMenu.java | 11 ++ .../jpexs/decompiler/flash/gui/MainPanel.java | 60 ++++++++ .../flash/gui/graphics/importsound16.png | Bin 0 -> 6600 bytes .../flash/gui/graphics/importsound32.png | Bin 0 -> 9807 bytes .../locales/AdvancedSettingsDialog.properties | 3 + .../AdvancedSettingsDialog_cs.properties | 3 + .../flash/gui/locales/MainFrame.properties | 9 ++ .../flash/gui/locales/MainFrame_cs.properties | 11 +- .../flash/gui/tagtree/TagTreeContextMenu.java | 14 ++ 14 files changed, 327 insertions(+), 32 deletions(-) create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/importsound16.png create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/importsound32.png diff --git a/CHANGELOG.md b/CHANGELOG.md index f710531ed..1547f267a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. - [#1827] Replacing and bulk import of DefineVideoStream - Movie FLV export - writing simple onMetadata tag - [#1424], [#1473], [#1473], [#1852] Replacing sound streams (SoundStreamHead, SoundStreamBlock) +- Bulk import sounds and sound streams ### Fixed - [#1914] DropShadow filter diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 571b6e6f9..0a83d945f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -875,6 +875,10 @@ public final class Configuration { @ConfigurationCategory("ui") public static ConfigurationItem showImportMovieInfo = null; + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("ui") + public static ConfigurationItem showImportSoundInfo = null; + private enum OSId { WINDOWS, OSX, UNIX } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SoundImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SoundImporter.java index a53568020..bb425d820 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SoundImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SoundImporter.java @@ -21,9 +21,11 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.tags.DefineSoundTag; +import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.SoundImportException; import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; import com.jpexs.decompiler.flash.tags.base.SoundTag; @@ -38,11 +40,17 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +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.List; +import java.util.Locale; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.sound.sampled.AudioFormat; @@ -460,4 +468,96 @@ public class SoundImporter { } return false; } + + public int bulkImport(File soundDir, SWF swf, boolean printOut) { + + Map characters = swf.getCharacters(); + int soundCount = 0; + List extensions = Arrays.asList("mp3", "wav"); + File allFiles[] = soundDir.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; + } + }); + + + List soundTags = new ArrayList<>(); + for (int characterId : characters.keySet()) { + CharacterTag tag = characters.get(characterId); + if (tag instanceof DefineSoundTag) { + soundTags.add((DefineSoundTag) tag); + } + if (tag instanceof DefineSpriteTag) { + DefineSpriteTag sprite = (DefineSpriteTag) tag; + for (Tag subTag : sprite.getTags()) { + if (subTag instanceof SoundStreamHeadTypeTag) { + soundTags.add((SoundStreamHeadTypeTag)subTag); + } + } + } + } + for (Tag tag:swf.getTags()) { + if (tag instanceof SoundStreamHeadTypeTag) { + soundTags.add((SoundStreamHeadTypeTag) tag); + } + } + + for (SoundTag tag : soundTags) { + int characterId = tag.getCharacterId(); + List existingFilesForSoundTag = new ArrayList<>(); + for (File f : allFiles) { + if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) { + existingFilesForSoundTag.add(f); + } + } + existingFilesForSoundTag.sort(new Comparator() { + @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 (existingFilesForSoundTag.isEmpty()) { + continue; + } + + if (existingFilesForSoundTag.size() > 1) { + Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Multiple matching files for sound tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForSoundTag.get(0).getName()}); + } + File sourceFile = existingFilesForSoundTag.get(0); + + try { + if (printOut) { + System.out.println("Importing character " + characterId + " from file " + sourceFile.getName()); + } + int soundFormat = SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN; + if (sourceFile.getAbsolutePath().toLowerCase(Locale.ENGLISH).endsWith(".mp3")) { + soundFormat = SoundFormat.FORMAT_MP3; + } + try (FileInputStream fis = new FileInputStream(sourceFile)){ + importSound(tag,fis, soundFormat); + soundCount++; + } + } catch (IOException|SoundImportException ex) { + Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Cannot import sound " + characterId + " from file " + sourceFile.getName(), ex); + } + if (Thread.currentThread().isInterrupted()) { + break; + } + } + return soundCount; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundTag.java index 64137b79a..12ccfe4d5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/SoundTag.java @@ -58,4 +58,6 @@ public interface SoundTag extends TreeItem { public void setSoundCompression(int soundCompression); public void setSoundRate(int soundRate); + + public int getCharacterId(); } diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index 2c947fe2f..3e188ef12 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -226,6 +226,7 @@ import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; import com.jpexs.decompiler.flash.tags.base.HasSeparateAlphaChannel; import com.jpexs.decompiler.flash.tags.base.RenderContext; import com.jpexs.decompiler.flash.tags.base.SoundImportException; +import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag; import com.jpexs.decompiler.flash.tags.base.UnsupportedSamplingRateException; import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.helpers.SerializableImage; @@ -598,7 +599,11 @@ public class CommandLineArgumentParser { out.println(" ...imports movies to and saves the result to "); } - + if (filter == null || filter.equals("importsounds")) { + out.println(" " + (cnt++) + ") -importSounds "); + out.println(" ...imports sounds to and saves the result to "); + } + if (filter == null || filter.equals("importshapes")) { out.println(" " + (cnt++) + ") -importShapes [nofill] "); out.println(" ...imports shapes to and saves the result to "); @@ -1067,6 +1072,9 @@ public class CommandLineArgumentParser { } else if (command.equals("importmovies")) { parseImportMovies(args, charset); System.exit(0); + } else if (command.equals("importsounds")) { + parseImportSounds(args, charset); + System.exit(0); } else if (command.equals("importshapes")) { parseImportShapes(args, charset); System.exit(0); @@ -1483,7 +1491,7 @@ public class CommandLineArgumentParser { } return false; } - }, charset); + }, charset); } private static void parseSetInstanceMetadata(Stack args, String charset) { @@ -1692,7 +1700,7 @@ public class CommandLineArgumentParser { } return false; } - }, charset); + }, charset); } private static void parseRemoveInstanceMetadata(Stack args, String charset) { @@ -1820,7 +1828,7 @@ public class CommandLineArgumentParser { } return false; } - }, charset); + }, charset); } private static class Range { @@ -2732,7 +2740,7 @@ public class CommandLineArgumentParser { } } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); - } + } } private static void parseXml2Swf(Stack args, String charset) { @@ -2751,7 +2759,7 @@ public class CommandLineArgumentParser { } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); } - + } private static void parseExtract(Stack args) { @@ -2836,7 +2844,7 @@ public class CommandLineArgumentParser { } catch (IOException ex) { logger.log(Level.SEVERE, null, ex); } - + } private static void parseMemorySearch(Stack args) { @@ -2921,7 +2929,7 @@ public class CommandLineArgumentParser { } else { System.err.println("Memory search is only available on Windows platform."); } - + } private static void parseRenameInvalidIdentifiers(Stack args) { @@ -3065,7 +3073,7 @@ public class CommandLineArgumentParser { int fframe = 0; final Graphics2D g = (Graphics2D) job.getGraphics(pf); - + SerializableImage image = new SerializableImage((int) w + 1, (int) h + 1, SerializableImage.TYPE_INT_ARGB_PRE) { private Graphics2D compositeGraphics; @@ -3103,7 +3111,7 @@ public class CommandLineArgumentParser { if (Thread.currentThread().isInterrupted()) { return; - } + } System.out.println("OK"); @@ -3169,16 +3177,56 @@ public class CommandLineArgumentParser { System.err.println("CharacterId should be integer"); badArguments("replace"); } - if (!swf.getCharacters().containsKey(characterId)) { + + SoundStreamHeadTypeTag soundStreamHead = null; + CharacterTag characterTag = null; + if (characterId == 0) { + //replacing soundstreamhead on main timeline + } else if (swf.getCharacters().containsKey(characterId)) { + characterTag = swf.getCharacter(characterId); + } else { System.err.println("CharacterId does not exist"); System.exit(1); } - CharacterTag characterTag = swf.getCharacter(characterId); String repFile = args.pop(); + byte[] data = Helper.readFile(repFile); String ext = Path.getExtension(repFile); - if (characterTag instanceof DefineBinaryDataTag) { + + int soundFormat = SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN; + if (".mp3".equals(ext)) { + soundFormat = SoundFormat.FORMAT_MP3; + } + + if ((characterTag == null || (characterTag instanceof DefineSpriteTag)) && (".wav".equals(ext) || ".mp3".equals(ext))) { + ReadOnlyTagList tags = (characterTag == null) ? swf.getTags() : ((DefineSpriteTag) characterTag).getTags(); + for (Tag t : tags) { + if (t instanceof SoundStreamHeadTypeTag) { + soundStreamHead = (SoundStreamHeadTypeTag) t; + break; + } + } + if (soundStreamHead == null) { + System.err.println((characterTag == null ? "Main timeline " : "DefineSprite(" + characterId + ")") + " does not contain any SoundStreamHead"); + System.exit(1); + } + boolean ok = false; + try { + ok = new SoundImporter().importSoundStream(soundStreamHead, new ByteArrayInputStream(data), soundFormat); + } catch (UnsupportedSamplingRateException usre) { + List supportedRatesStr = new ArrayList<>(); + for (int i : usre.getSupportedRates()) { + supportedRatesStr.add("" + i); + } + System.err.println("Import FAILED. Input file has unsupported sampling rate (" + usre.getSoundRate() + "). Supported rates for this sound format: " + String.join(", ", supportedRatesStr) + "."); + System.exit(2); + } + if (!ok) { + System.err.println("Import FAILED. Maybe unsuppoted media type? Only MP3 and uncompressed WAV are available."); + System.exit(1); + } + } else if (characterTag instanceof DefineBinaryDataTag) { DefineBinaryDataTag defineBinaryData = (DefineBinaryDataTag) characterTag; new BinaryDataImporter().importData(defineBinaryData, data); } else if (characterTag instanceof ImageTag) { @@ -3218,12 +3266,7 @@ public class CommandLineArgumentParser { } }).importText(textTag, new String(data, Utf8Helper.charset)); } else if (characterTag instanceof SoundTag) { - SoundTag st = (SoundTag) characterTag; - int soundFormat = SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN; - if (repFile.toLowerCase(Locale.ENGLISH).endsWith(".mp3")) { - soundFormat = SoundFormat.FORMAT_MP3; - } - + SoundTag st = (SoundTag) characterTag; boolean ok = false; SoundImporter soundImporter = new SoundImporter(); try { @@ -3233,7 +3276,7 @@ public class CommandLineArgumentParser { for (int i : usre.getSupportedRates()) { supportedRatesStr.add("" + i); } - System.err.println("Import FAILED. Input file has unsupported sampling rate ("+usre.getSoundRate()+"). Supported rates for this sound format: "+String.join(", ", supportedRatesStr)+"."); + System.err.println("Import FAILED. Input file has unsupported sampling rate (" + usre.getSoundRate() + "). Supported rates for this sound format: " + String.join(", ", supportedRatesStr) + "."); System.exit(2); } catch (SoundImportException sie) { ok = false; @@ -3243,11 +3286,11 @@ public class CommandLineArgumentParser { System.exit(1); } } else if (characterTag instanceof DefineVideoStreamTag) { - DefineVideoStreamTag movie = (DefineVideoStreamTag)characterTag; + DefineVideoStreamTag movie = (DefineVideoStreamTag) characterTag; try { - new MovieImporter().importMovie(movie, data); + new MovieImporter().importMovie(movie, data); } catch (IOException iex) { - System.err.println("Import FAILED: "+iex.getMessage()); + System.err.println("Import FAILED: " + iex.getMessage()); System.exit(1); } } else { @@ -3317,7 +3360,7 @@ public class CommandLineArgumentParser { try { try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) { swf.saveTo(fos); - } + } } catch (IOException e) { System.err.println("I/O error during writing"); System.exit(2); @@ -3824,7 +3867,7 @@ public class CommandLineArgumentParser { } ShapeImporter shapeImporter = new ShapeImporter(); int shapeCount = shapeImporter.bulkImport(shapesDir, swf, noFill, true); - + System.out.println("Writing outfile"); try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) { swf.saveTo(fos); @@ -3835,7 +3878,7 @@ public class CommandLineArgumentParser { System.exit(2); } } - + private static void parseImportMovies(Stack args, String charset) { if (args.size() < 3) { badArguments("importmovies"); @@ -3860,7 +3903,7 @@ public class CommandLineArgumentParser { System.exit(1); } MovieImporter movieImporter = new MovieImporter(); - int movieCount = movieImporter.bulkImport(moviesDir, swf, true); + int movieCount = movieImporter.bulkImport(moviesDir, swf, true); System.out.println("Writing outfile"); try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) { swf.saveTo(fos); @@ -3872,6 +3915,42 @@ public class CommandLineArgumentParser { } } + private static void parseImportSounds(Stack args, String charset) { + if (args.size() < 3) { + badArguments("importsounds"); + } + + 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 soundsDir = new File(Path.combine(selFile, SoundExportSettings.EXPORT_FOLDER_NAME)); + if (soundsDir.exists()) { + System.out.println("Using the directory: " + soundsDir.getAbsolutePath()); + } else { + soundsDir = new File(selFile); + } + if (!soundsDir.exists()) { + System.err.println("Sounds directory does not exist: " + soundsDir.getAbsolutePath()); + System.exit(1); + } + SoundImporter soundImporter = new SoundImporter(); + int soundCount = soundImporter.bulkImport(soundsDir, swf, true); + System.out.println("Writing outfile"); + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) { + swf.saveTo(fos); + } + System.out.println("" + soundCount + " sounds successfully imported"); + } catch (IOException | InterruptedException e) { + System.err.println("I/O error during writing"); + System.exit(2); + } + } + private static void parseImportImages(Stack args, String charset) { if (args.size() < 3) { badArguments("importimages"); @@ -3896,7 +3975,7 @@ public class CommandLineArgumentParser { System.exit(1); } ImageImporter imageImporter = new ImageImporter(); - int imageCount = imageImporter.bulkImport(imagesDir, swf, true); + int imageCount = imageImporter.bulkImport(imagesDir, swf, true); System.out.println("Writing outfile"); try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) { swf.saveTo(fos); @@ -4296,7 +4375,7 @@ public class CommandLineArgumentParser { } if (!found) { System.exit(1); - } + } } private static String doubleToString(double d) { @@ -4383,7 +4462,7 @@ public class CommandLineArgumentParser { } catch (Exception ex) { logger.log(Level.SEVERE, null, ex); System.exit(1); - } + } } private static void parseDumpAS2(Stack args, String charset) { @@ -4483,7 +4562,7 @@ public class CommandLineArgumentParser { System.exit(3); } - System.out.println("Finished"); + System.out.println("Finished"); } private static void parseDumpAS3(Stack args, String charset) { diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java index eae205afb..b72d9e96b 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/MainFrameMenu.java @@ -383,6 +383,16 @@ public abstract class MainFrameMenu implements MenuBuilder { mainFrame.getPanel().importMovie((SWF) openable); } + protected void importSoundsActionPerformed(ActionEvent evt) { + if (Main.isWorking()) { + return; + } + if (mainFrame.getPanel().checkEdited()) { + return; + } + mainFrame.getPanel().importSound((SWF) openable); + } + protected void importSymbolClassActionPerformed(ActionEvent evt) { if (Main.isWorking()) { return; @@ -1129,6 +1139,7 @@ public abstract class MainFrameMenu implements MenuBuilder { addMenuItem("/file/import/importOther/importShapes", translate("menu.file.import.shape"), "importshape32", this::importShapesActionPerformed, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/file/import/importOther/importShapesNoFill", translate("menu.file.import.shapeNoFill"), "importshape32", this::importShapesNoFillActionPerformed, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/file/import/importOther/importMovies", translate("menu.file.import.movie"), "importmovie32", this::importMoviesActionPerformed, PRIORITY_MEDIUM, null, true, null, false); + addMenuItem("/file/import/importOther/importSounds", translate("menu.file.import.sound"), "importsound32", this::importSoundsActionPerformed, PRIORITY_MEDIUM, null, true, null, false); addMenuItem("/file/import/importOther/importSymbolClass", translate("menu.file.import.symbolClass"), "importsymbolclass32", this::importSymbolClassActionPerformed, PRIORITY_MEDIUM, null, true, null, false); finishMenu("/file/import/importOther"); finishMenu("/file/import"); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index f9c1f0242..411d93544 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -3129,6 +3129,66 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se }.execute(); } } + + public void importSound(final SWF swf) { + ViewMessages.showMessageDialog(MainPanel.this, translate("message.info.importSounds2"), translate("message.info"), JOptionPane.INFORMATION_MESSAGE, Configuration.showImportSoundInfo); + 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) { + + previewPanel.clear(); + + String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath(); + File soundsDir = new File(Path.combine(selFile, SoundExportSettings.EXPORT_FOLDER_NAME)); + if (!soundsDir.exists()) { + soundsDir = new File(selFile); + } + final File fSoundsDir = soundsDir; + SoundImporter soundImporter = new SoundImporter(); + + final long timeBefore = System.currentTimeMillis(); + new CancellableWorker() { + + private int count = 0; + + @Override + public Void doInBackground() throws Exception { + try { + count = soundImporter.bulkImport(fSoundsDir, 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.sound.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); JFileChooser chooser = new JFileChooser(); diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/importsound16.png b/src/com/jpexs/decompiler/flash/gui/graphics/importsound16.png new file mode 100644 index 0000000000000000000000000000000000000000..4f2b6d23aed51a140a65f03e460af94f1f219755 GIT binary patch literal 6600 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 literal 0 HcmV?d00001 diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/importsound32.png b/src/com/jpexs/decompiler/flash/gui/graphics/importsound32.png new file mode 100644 index 0000000000000000000000000000000000000000..301afdea6700616c9354f4a9b0d48145dd46ce08 GIT binary patch literal 9807 zcmeHrc|6qJ+y7X{ntk8KP$**<>x_Nh_a(G2GiDguFf-O{6+(zeWS1<7kdR2JEJ-5! zS_x5hsR++d_kDN&p6~Db{JyW(@A>aGubKIr>%6b`bm=cpfP3ttlNjB9x!9I077KnNPo^M6@2>u}BFs78twwrFCnxAn>n&;Hfu&xBNm zbCr3K59Wn|5j~>0>xc+H*SO0^}`^>y6m5-M98-=H+)Gj@7`mSJg z>MnF{7#bRpH2sKq^9Fo0;qz%1sxQM@QW`GN!+@F5jJqve^N^Rjf?v=QOW%oG8RNs4 z{Y|I1JnlJTxn<6)^Xetvq(P%DB;2b02lZp`+Eb!8au`-D8{0TiT%LDDI$zsKez7C{ zV{Tj7$|k%@RVIuX8!i$VqMnW)cA;t#cyB3R`X%ps_m>}1kMb{iN6vc?=Rdm#iJjDO zcF7Jk?67F`huJl0Ry0Sqwmq0QIX@^k`Y`JB?t0oVgSwt8TolMGmQ%grAM>1@IKgIw zN<2|=u9Cv~%83x5#pv00ddBKF&$kUx%KnOvhS`^!cP$!p&?x2!KB|i`z`bw#A-jPE zMCn=G)g_@5LtGGgr&v+G2xGDNUUXscFUQulf^I>6x$XEB3E zD;^9Ezb-R=M_+k-tnSkYGR;JFrS?>eXUn~q*m=^_lbz}H*Snc=TGQ&zIc6Mkz=;QTBKz$Db<=VGYeK!kO>pTmJ3zawjNOT{?F4dY}nVGXlwLQEH`a9zW8> zwxexQ9WuH%0#J?s%F8ZOht*QYd?=oMN*Ap=T&}`CJa;ZZ!nT@a!@+*RF8`wLq5 zsOUrgsp@Y5KTJe0(D%fRTc`XK2jRmbrI3XX0nxOUbYS%}n6( z++2O$jALkGQWc%=Q5Ka=q{%w{L5R)TZpQe*TpQ@(<*ifA#YQJ0;vc_qzcBaUl#&X) zA!Dh%!tdj+61!Phngyzw;n7HPk#zGf@0-lf+?w-q

>_Dg{>~+@CU`XEm{Y$%=K{-zZO?>Qs=MQUC+ynt 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 literal 0 HcmV?d00001 diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index d9043dbda..39234ef58 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -662,3 +662,6 @@ config.description.warningRenameIdentifiers = Show warning when turning on auto config.name.showImportMovieInfo = Show information before importing movies config.description.showImportMovieInfo = Displays some info about how importing movies works after clicking Import movies in the menu. + +config.name.showImportSoundInfo = Show information before importing sounds +config.description.showImportSoundInfo = Displays some info about how importing sounds works after clicking Import sounds in the menu. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties index 92741a336..43cef3066 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties @@ -652,3 +652,6 @@ config.description.warningRenameIdentifiers = Zobrazovat varov\u00e1n\u00ed b\u0 config.name.showImportMovieInfo = Zobrazit informaci p\u0159ed importem vide\u00ed config.description.showImportMovieInfo = Zobraz\u00ed n\u011bjak\u00e9 informace o tom jak import vide\u00ed funguje po kliku na import vide\u00ed v menu. + +config.name.showImportSoundInfo = Zobrazit informaci p\u0159ed importem zvuk\u016f +config.description.showImportSoundInfo = Zobraz\u00ed n\u011bjak\u00e9 informace o tom jak import zvuk\u016f funguje po kliku na import zvuk\u016f v menu. diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index c1c51048a..c92268376 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -1099,3 +1099,12 @@ message.info.importMovies2 = During importing movies, you need to select a FOLDE The best way to get the structure right is to export images in current SWF file first. import.movie.result = %count% movies imported. + +menu.file.import.sound = Import sounds + +message.info.importSounds2 = During importing sounds, you need to select a FOLDER.\r\n \ + Filenames inside the folder must match existing sounds in current selected SWF.\r\n \ + If there exist "sounds" folder inside, it is selected instead.\r\n \ + The best way to get the structure right is to export sounds in current SWF file first. + +import.sound.result = %count% sounds imported. \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 0ae033f28..7c6c35b58 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -1083,4 +1083,13 @@ message.info.importMovies2 = B\u011bhem importu vide\u00ed mus\u00edte vybrat SL 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. \ No newline at end of file +import.movie.result = %count% vide\u00ed importov\u00e1no. + +menu.file.import.sound = Importovat zvuky + +message.info.importSounds2 = B\u011bhem importu zvuk\u016f mus\u00edte vybrat SLO\u017dKU.\r\n \ + N\u00e1zvy soubor\u016f uvnit\u0159 mus\u00ed souhlasit s existuj\u00edc\u00edmi zvuky v pr\u00e1v\u011b vybran\u00e9m SWF.\r\n \ + Pokud je uvnit\u0159 slo\u017eka "sounds", 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 zvuky v aktu\u00e1ln\u00edm SWF souboru. + +import.sound.result = %count% zvuk\u016f importov\u00e1no. \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index f3e35c753..ebccd43e4 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -173,6 +173,8 @@ public class TagTreeContextMenu extends JPopupMenu { private JMenuItem importMoviesMenuItem; + private JMenuItem importSoundsMenuItem; + private JMenuItem importSymbolClassMenuItem; private JMenuItem closeMenuItem; @@ -417,6 +419,11 @@ public class TagTreeContextMenu extends JPopupMenu { importMoviesMenuItem.addActionListener(this::importMoviesActionPerformed); importMoviesMenuItem.setIcon(View.getIcon("importmovie16")); add(importMoviesMenuItem); + + importSoundsMenuItem = new JMenuItem(mainPanel.translate("menu.file.import.sound")); + importSoundsMenuItem.addActionListener(this::importSoundsActionPerformed); + importSoundsMenuItem.setIcon(View.getIcon("importsound16")); + add(importSoundsMenuItem); importSymbolClassMenuItem = new JMenuItem(mainPanel.translate("menu.file.import.symbolClass")); importSymbolClassMenuItem.addActionListener(this::importSymbolClassActionPerformed); @@ -900,6 +907,7 @@ public class TagTreeContextMenu extends JPopupMenu { importShapesMenuItem.setVisible(false); importShapesNoFillMenuItem.setVisible(false); importMoviesMenuItem.setVisible(false); + importSoundsMenuItem.setVisible(false); importScriptsMenuItem.setVisible(false); importSymbolClassMenuItem.setVisible(false); importTextsMenuItem.setVisible(false); @@ -1119,6 +1127,7 @@ public class TagTreeContextMenu extends JPopupMenu { importShapesMenuItem.setVisible(true); importShapesNoFillMenuItem.setVisible(true); importMoviesMenuItem.setVisible(true); + importSoundsMenuItem.setVisible(true); importScriptsMenuItem.setVisible(true); importSymbolClassMenuItem.setVisible(true); importTextsMenuItem.setVisible(true); @@ -3271,6 +3280,11 @@ public class TagTreeContextMenu extends JPopupMenu { SWF swf = (SWF) getCurrentItem().getOpenable(); mainPanel.importMovie(swf); } + + public void importSoundsActionPerformed(ActionEvent evt) { + SWF swf = (SWF) getCurrentItem().getOpenable(); + mainPanel.importSound(swf); + } public void importSymbolClassActionPerformed(ActionEvent evt) { SWF swf = (SWF) getCurrentItem().getOpenable();