mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-24 18:50:48 +00:00
Added #2132 Show and export streamed sound (SoundStreamHead/SoundStreamBlock) in frame ranges
Fixed #1194 FLA Export - stream sound export
This commit is contained in:
+4
-1
@@ -25,6 +25,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- [#2131] Breakpoint list dialog
|
- [#2131] Breakpoint list dialog
|
||||||
- ExportAssets tag - show first item as description in the tree when there is only single item
|
- ExportAssets tag - show first item as description in the tree when there is only single item
|
||||||
- [#2134] FLA Export - split main timeline into scenes when DefineSceneAndFrameLabelData tag is present
|
- [#2134] FLA Export - split main timeline into scenes when DefineSceneAndFrameLabelData tag is present
|
||||||
|
- [#2132] Show and export streamed sound (SoundStreamHead/SoundStreamBlock) in frame ranges
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- [#2021], [#2000] Caret position in editors when using tabs and / or unicode
|
- [#2021], [#2000] Caret position in editors when using tabs and / or unicode
|
||||||
@@ -64,6 +65,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Wordrapping long words in DefineEditText
|
- Wordrapping long words in DefineEditText
|
||||||
- [#2133] Linux/Mac - ffdec.sh not correctly parsing java build number on javas without it
|
- [#2133] Linux/Mac - ffdec.sh not correctly parsing java build number on javas without it
|
||||||
- [#2135] FLA Export - framescripts handling when addFrameScript uses Multinames instead of QNames
|
- [#2135] FLA Export - framescripts handling when addFrameScript uses Multinames instead of QNames
|
||||||
|
- [#1194] FLA Export - stream sound export
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- [#2120] Exported assets no longer take names from assigned classes if there is more than 1 assigned class
|
- [#2120] Exported assets no longer take names from assigned classes if there is more than 1 assigned class
|
||||||
@@ -3324,6 +3326,7 @@ Major version of SWF to XML export changed to 2.
|
|||||||
[#2131]: https://www.free-decompiler.com/flash/issues/2131
|
[#2131]: https://www.free-decompiler.com/flash/issues/2131
|
||||||
[#2124]: https://www.free-decompiler.com/flash/issues/2124
|
[#2124]: https://www.free-decompiler.com/flash/issues/2124
|
||||||
[#2134]: https://www.free-decompiler.com/flash/issues/2134
|
[#2134]: https://www.free-decompiler.com/flash/issues/2134
|
||||||
|
[#2132]: https://www.free-decompiler.com/flash/issues/2132
|
||||||
[#2021]: https://www.free-decompiler.com/flash/issues/2021
|
[#2021]: https://www.free-decompiler.com/flash/issues/2021
|
||||||
[#2000]: https://www.free-decompiler.com/flash/issues/2000
|
[#2000]: https://www.free-decompiler.com/flash/issues/2000
|
||||||
[#2116]: https://www.free-decompiler.com/flash/issues/2116
|
[#2116]: https://www.free-decompiler.com/flash/issues/2116
|
||||||
@@ -3335,6 +3338,7 @@ Major version of SWF to XML export changed to 2.
|
|||||||
[#2053]: https://www.free-decompiler.com/flash/issues/2053
|
[#2053]: https://www.free-decompiler.com/flash/issues/2053
|
||||||
[#2133]: https://www.free-decompiler.com/flash/issues/2133
|
[#2133]: https://www.free-decompiler.com/flash/issues/2133
|
||||||
[#2135]: https://www.free-decompiler.com/flash/issues/2135
|
[#2135]: https://www.free-decompiler.com/flash/issues/2135
|
||||||
|
[#1194]: https://www.free-decompiler.com/flash/issues/1194
|
||||||
[#2120]: https://www.free-decompiler.com/flash/issues/2120
|
[#2120]: https://www.free-decompiler.com/flash/issues/2120
|
||||||
[#1130]: https://www.free-decompiler.com/flash/issues/1130
|
[#1130]: https://www.free-decompiler.com/flash/issues/1130
|
||||||
[#1220]: https://www.free-decompiler.com/flash/issues/1220
|
[#1220]: https://www.free-decompiler.com/flash/issues/1220
|
||||||
@@ -3765,7 +3769,6 @@ Major version of SWF to XML export changed to 2.
|
|||||||
[#1200]: https://www.free-decompiler.com/flash/issues/1200
|
[#1200]: https://www.free-decompiler.com/flash/issues/1200
|
||||||
[#1198]: https://www.free-decompiler.com/flash/issues/1198
|
[#1198]: https://www.free-decompiler.com/flash/issues/1198
|
||||||
[#1205]: https://www.free-decompiler.com/flash/issues/1205
|
[#1205]: https://www.free-decompiler.com/flash/issues/1205
|
||||||
[#1194]: https://www.free-decompiler.com/flash/issues/1194
|
|
||||||
[#1210]: https://www.free-decompiler.com/flash/issues/1210
|
[#1210]: https://www.free-decompiler.com/flash/issues/1210
|
||||||
[#1217]: https://www.free-decompiler.com/flash/issues/1217
|
[#1217]: https://www.free-decompiler.com/flash/issues/1217
|
||||||
[#1244]: https://www.free-decompiler.com/flash/issues/1244
|
[#1244]: https://www.free-decompiler.com/flash/issues/1244
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
|||||||
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
|
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
|
||||||
import com.jpexs.decompiler.flash.timeline.DepthState;
|
import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||||
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||||
import com.jpexs.decompiler.flash.types.BUTTONCONDACTION;
|
import com.jpexs.decompiler.flash.types.BUTTONCONDACTION;
|
||||||
@@ -261,7 +262,13 @@ public class PreviewExporter {
|
|||||||
|
|
||||||
List<SoundStreamBlockTag> soundFrames = new ArrayList<>();
|
List<SoundStreamBlockTag> soundFrames = new ArrayList<>();
|
||||||
if (treeItem instanceof SoundStreamHeadTypeTag) {
|
if (treeItem instanceof SoundStreamHeadTypeTag) {
|
||||||
soundFrames = ((SoundStreamHeadTypeTag) treeItem).getBlocks();
|
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) treeItem;
|
||||||
|
for (SoundStreamFrameRange range : head.getRanges()) {
|
||||||
|
soundFrames.addAll(range.blocks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (treeItem instanceof SoundStreamFrameRange) {
|
||||||
|
soundFrames = ((SoundStreamFrameRange) treeItem).blocks;
|
||||||
frameCount = soundFrames.size();
|
frameCount = soundFrames.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
|||||||
import com.jpexs.decompiler.flash.tags.base.SoundTag;
|
import com.jpexs.decompiler.flash.tags.base.SoundTag;
|
||||||
import com.jpexs.decompiler.flash.tags.gfx.DefineExternalSound;
|
import com.jpexs.decompiler.flash.tags.gfx.DefineExternalSound;
|
||||||
import com.jpexs.decompiler.flash.tags.gfx.DefineExternalStreamSound;
|
import com.jpexs.decompiler.flash.tags.gfx.DefineExternalStreamSound;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.types.sound.SoundExportFormat;
|
import com.jpexs.decompiler.flash.types.sound.SoundExportFormat;
|
||||||
import com.jpexs.decompiler.flash.types.sound.SoundFormat;
|
import com.jpexs.decompiler.flash.types.sound.SoundFormat;
|
||||||
import com.jpexs.helpers.ByteArrayRange;
|
import com.jpexs.helpers.ByteArrayRange;
|
||||||
@@ -58,8 +59,17 @@ import java.util.Set;
|
|||||||
* @author JPEXS
|
* @author JPEXS
|
||||||
*/
|
*/
|
||||||
public class SoundExporter {
|
public class SoundExporter {
|
||||||
|
|
||||||
public List<File> exportSounds(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final SoundExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
public List<File> exportSounds(AbortRetryIgnoreHandler handler, String outdir, ReadOnlyTagList tags, final SoundExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||||
|
List<SoundTag> sounds = new ArrayList<>();
|
||||||
|
for (Tag t : tags) {
|
||||||
|
if (t instanceof SoundTag) {
|
||||||
|
sounds.add((SoundTag) t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exportSounds(handler, outdir, sounds, settings, evl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<File> exportSounds(AbortRetryIgnoreHandler handler, String outdir, List<SoundTag> tags, final SoundExportSettings settings, EventListener evl) throws IOException, InterruptedException {
|
||||||
List<File> ret = new ArrayList<>();
|
List<File> ret = new ArrayList<>();
|
||||||
if (Thread.currentThread().isInterrupted()) {
|
if (Thread.currentThread().isInterrupted()) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -72,75 +82,64 @@ public class SoundExporter {
|
|||||||
File foutdir = new File(outdir);
|
File foutdir = new File(outdir);
|
||||||
Path.createDirectorySafe(foutdir);
|
Path.createDirectorySafe(foutdir);
|
||||||
|
|
||||||
int count = 0;
|
if (tags.isEmpty()) {
|
||||||
for (Tag t : tags) {
|
|
||||||
if (t instanceof SoundTag) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0) {
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentIndex = 1;
|
int currentIndex = 1;
|
||||||
for (Tag t : tags) {
|
for (SoundTag st : tags) {
|
||||||
if (t instanceof SoundTag) {
|
if (evl != null) {
|
||||||
if (evl != null) {
|
evl.handleExportingEvent("sound", currentIndex, tags.size(), st.getName());
|
||||||
evl.handleExportingEvent("sound", currentIndex, count, t.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
final SoundTag st = (SoundTag) t;
|
|
||||||
|
|
||||||
String ext = ".wav";
|
|
||||||
SoundFormat fmt = st.getSoundFormat();
|
|
||||||
switch (fmt.getNativeExportFormat()) {
|
|
||||||
case MP3:
|
|
||||||
if (settings.mode.hasMP3()) {
|
|
||||||
ext = ".mp3";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FLV:
|
|
||||||
if (settings.mode.hasFlv()) {
|
|
||||||
ext = ".flv";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (settings.mode == SoundExportMode.FLV) {
|
|
||||||
ext = ".flv";
|
|
||||||
}
|
|
||||||
|
|
||||||
final File file = new File(outdir + File.separator + Helper.makeFileName(st.getCharacterExportFileName()) + ext);
|
|
||||||
new RetryTask(() -> {
|
|
||||||
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) {
|
|
||||||
exportSound(os, st, settings.mode);
|
|
||||||
}
|
|
||||||
}, handler).run();
|
|
||||||
|
|
||||||
Set<String> classNames = (st instanceof CharacterTag) ? ((CharacterTag) st).getClassNames() : new HashSet<>();
|
|
||||||
if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) {
|
|
||||||
for (String className : classNames) {
|
|
||||||
File classFile = new File(outdir + File.separator + Helper.makeFileName(className + ext));
|
|
||||||
new RetryTask(() -> {
|
|
||||||
Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}, handler).run();
|
|
||||||
ret.add(classFile);
|
|
||||||
}
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
ret.add(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Thread.currentThread().isInterrupted()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evl != null) {
|
|
||||||
evl.handleExportedEvent("sound", currentIndex, count, t.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
currentIndex++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String ext = ".wav";
|
||||||
|
SoundFormat fmt = st.getSoundFormat();
|
||||||
|
switch (fmt.getNativeExportFormat()) {
|
||||||
|
case MP3:
|
||||||
|
if (settings.mode.hasMP3()) {
|
||||||
|
ext = ".mp3";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FLV:
|
||||||
|
if (settings.mode.hasFlv()) {
|
||||||
|
ext = ".flv";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (settings.mode == SoundExportMode.FLV) {
|
||||||
|
ext = ".flv";
|
||||||
|
}
|
||||||
|
|
||||||
|
final File file = new File(outdir + File.separator + Helper.makeFileName(st.getCharacterExportFileName()) + ext);
|
||||||
|
new RetryTask(() -> {
|
||||||
|
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) {
|
||||||
|
exportSound(os, st, settings.mode);
|
||||||
|
}
|
||||||
|
}, handler).run();
|
||||||
|
|
||||||
|
Set<String> classNames = (st instanceof CharacterTag) ? ((CharacterTag) st).getClassNames() : new HashSet<>();
|
||||||
|
if (Configuration.as3ExportNamesUseClassNamesOnly.get() && !classNames.isEmpty()) {
|
||||||
|
for (String className : classNames) {
|
||||||
|
File classFile = new File(outdir + File.separator + Helper.makeFileName(className + ext));
|
||||||
|
new RetryTask(() -> {
|
||||||
|
Files.copy(file.toPath(), classFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}, handler).run();
|
||||||
|
ret.add(classFile);
|
||||||
|
}
|
||||||
|
file.delete();
|
||||||
|
} else {
|
||||||
|
ret.add(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Thread.currentThread().isInterrupted()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evl != null) {
|
||||||
|
evl.handleExportedEvent("sound", currentIndex, tags.size(), st.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -168,12 +167,22 @@ public class SoundExporter {
|
|||||||
for (ByteArrayRange data : datas) {
|
for (ByteArrayRange data : datas) {
|
||||||
flv.writeTag(new FLVTAG(0, new AUDIODATA(st.getSoundFormatId(), st.getSoundRate(), st.getSoundSize(), st.getSoundType(), data.getRangeData())));
|
flv.writeTag(new FLVTAG(0, new AUDIODATA(st.getSoundFormatId(), st.getSoundRate(), st.getSoundSize(), st.getSoundType(), data.getRangeData())));
|
||||||
}
|
}
|
||||||
} else if (st instanceof SoundStreamHeadTypeTag) {
|
} else if ((st instanceof SoundStreamFrameRange) || (st instanceof SoundStreamHeadTypeTag)) {
|
||||||
SoundStreamHeadTypeTag sh = (SoundStreamHeadTypeTag) st;
|
List<SoundStreamBlockTag> blocks;
|
||||||
|
if (st instanceof SoundStreamHeadTypeTag) {
|
||||||
|
blocks = new ArrayList<>();
|
||||||
|
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) st;
|
||||||
|
for (SoundStreamFrameRange range : head.getRanges()) {
|
||||||
|
blocks.addAll(range.blocks);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
blocks = ((SoundStreamFrameRange) st).blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundStreamFrameRange sh = (SoundStreamFrameRange) st;
|
||||||
FLVOutputStream flv = new FLVOutputStream(fos);
|
FLVOutputStream flv = new FLVOutputStream(fos);
|
||||||
flv.writeHeader(true, false);
|
flv.writeHeader(true, false);
|
||||||
List<SoundStreamBlockTag> blocks = sh.getBlocks();
|
|
||||||
|
|
||||||
int ms = (int) (1000.0 / ((Tag) st).getSwf().frameRate);
|
int ms = (int) (1000.0 / ((Tag) st).getSwf().frameRate);
|
||||||
for (int b = 0; b < blocks.size(); b++) {
|
for (int b = 0; b < blocks.size(); b++) {
|
||||||
byte[] data = blocks.get(b).streamSoundData.getRangeData();
|
byte[] data = blocks.get(b).streamSoundData.getRangeData();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import com.jpexs.decompiler.flash.tags.base.SoundImportException;
|
|||||||
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
||||||
import com.jpexs.decompiler.flash.tags.base.SoundTag;
|
import com.jpexs.decompiler.flash.tags.base.SoundTag;
|
||||||
import com.jpexs.decompiler.flash.tags.base.UnsupportedSamplingRateException;
|
import com.jpexs.decompiler.flash.tags.base.UnsupportedSamplingRateException;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||||
import com.jpexs.decompiler.flash.types.sound.MP3FRAME;
|
import com.jpexs.decompiler.flash.types.sound.MP3FRAME;
|
||||||
import com.jpexs.decompiler.flash.types.sound.MP3SOUNDDATA;
|
import com.jpexs.decompiler.flash.types.sound.MP3SOUNDDATA;
|
||||||
@@ -329,7 +330,14 @@ public class SoundImporter {
|
|||||||
|
|
||||||
ByteArrayInputStream bais = uncompressedSoundData == null ? null : new ByteArrayInputStream(uncompressedSoundData);
|
ByteArrayInputStream bais = uncompressedSoundData == null ? null : new ByteArrayInputStream(uncompressedSoundData);
|
||||||
|
|
||||||
List<SoundStreamBlockTag> existingBlocks = streamHead.getBlocks();
|
List<SoundStreamFrameRange> ranges = streamHead.getRanges();
|
||||||
|
|
||||||
|
List<SoundStreamBlockTag> existingBlocks = new ArrayList<>();
|
||||||
|
for (SoundStreamFrameRange range : ranges) {
|
||||||
|
existingBlocks.addAll(range.blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int startFrame = 0;
|
int startFrame = 0;
|
||||||
Timelined timelined = streamHead.getTimelined();
|
Timelined timelined = streamHead.getTimelined();
|
||||||
if (!existingBlocks.isEmpty()) {
|
if (!existingBlocks.isEmpty()) {
|
||||||
|
|||||||
@@ -237,4 +237,9 @@ public class DefineSoundTag extends CharacterTag implements SoundTag {
|
|||||||
public void setSoundRate(int soundRate) {
|
public void setSoundRate(int soundRate) {
|
||||||
this.soundRate = soundRate;
|
this.soundRate = soundRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlaExportName() {
|
||||||
|
return "sound" + getCharacterId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF;
|
|||||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||||
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||||
import com.jpexs.decompiler.flash.types.BasicType;
|
import com.jpexs.decompiler.flash.types.BasicType;
|
||||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||||
@@ -191,9 +192,9 @@ public class SoundStreamHead2Tag extends SoundStreamHeadTypeTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SoundStreamBlockTag> getBlocks() {
|
public List<SoundStreamFrameRange> getRanges() {
|
||||||
Timeline timeline = swf.getTimeline();
|
Timeline timeline = swf.getTimeline();
|
||||||
List<SoundStreamBlockTag> ret = timeline.getSoundStreamBlocks(this);
|
List<SoundStreamFrameRange> ret = timeline.getSoundStreamBlocks(this);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -206,14 +207,16 @@ public class SoundStreamHead2Tag extends SoundStreamHeadTypeTag {
|
|||||||
@Override
|
@Override
|
||||||
public List<ByteArrayRange> getRawSoundData() {
|
public List<ByteArrayRange> getRawSoundData() {
|
||||||
List<ByteArrayRange> ret = new ArrayList<>();
|
List<ByteArrayRange> ret = new ArrayList<>();
|
||||||
List<SoundStreamBlockTag> blocks = getBlocks();
|
List<SoundStreamFrameRange> frameRanges = getRanges();
|
||||||
if (blocks != null) {
|
if (frameRanges != null) {
|
||||||
for (SoundStreamBlockTag block : blocks) {
|
for (SoundStreamFrameRange range : frameRanges) {
|
||||||
ByteArrayRange data = block.streamSoundData;
|
for (SoundStreamBlockTag block : range.blocks) {
|
||||||
if (streamSoundCompression == SoundFormat.FORMAT_MP3) {
|
ByteArrayRange data = block.streamSoundData;
|
||||||
ret.add(data.getSubRange(4, data.getLength() - 4));
|
if (streamSoundCompression == SoundFormat.FORMAT_MP3) {
|
||||||
} else {
|
ret.add(data.getSubRange(4, data.getLength() - 4));
|
||||||
ret.add(data);
|
} else {
|
||||||
|
ret.add(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,7 +225,11 @@ public class SoundStreamHead2Tag extends SoundStreamHeadTypeTag {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTotalSoundSampleCount() {
|
public long getTotalSoundSampleCount() {
|
||||||
return getBlocks().size() * streamSoundSampleCount;
|
int blockCount = 0;
|
||||||
|
for (SoundStreamFrameRange range : getRanges()) {
|
||||||
|
blockCount += range.blocks.size();
|
||||||
|
}
|
||||||
|
return blockCount * streamSoundSampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -278,4 +285,9 @@ public class SoundStreamHead2Tag extends SoundStreamHeadTypeTag {
|
|||||||
public void setSoundRate(int soundRate) {
|
public void setSoundRate(int soundRate) {
|
||||||
this.streamSoundRate = soundRate;
|
this.streamSoundRate = soundRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlaExportName() {
|
||||||
|
return "sound" + getCharacterId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF;
|
|||||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||||
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||||
import com.jpexs.decompiler.flash.types.BasicType;
|
import com.jpexs.decompiler.flash.types.BasicType;
|
||||||
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
import com.jpexs.decompiler.flash.types.annotations.Conditional;
|
||||||
@@ -201,11 +202,10 @@ public class SoundStreamHeadTag extends SoundStreamHeadTypeTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SoundStreamBlockTag> getBlocks() {
|
public List<SoundStreamFrameRange> getRanges() {
|
||||||
Timeline timeline = swf.getTimeline();
|
Timeline timeline = swf.getTimeline();
|
||||||
List<SoundStreamBlockTag> ret = timeline.getSoundStreamBlocks(this);
|
List<SoundStreamFrameRange> ret = timeline.getSoundStreamBlocks(this);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -216,14 +216,16 @@ public class SoundStreamHeadTag extends SoundStreamHeadTypeTag {
|
|||||||
@Override
|
@Override
|
||||||
public List<ByteArrayRange> getRawSoundData() {
|
public List<ByteArrayRange> getRawSoundData() {
|
||||||
List<ByteArrayRange> ret = new ArrayList<>();
|
List<ByteArrayRange> ret = new ArrayList<>();
|
||||||
List<SoundStreamBlockTag> blocks = getBlocks();
|
List<SoundStreamFrameRange> frameRanges = getRanges();
|
||||||
if (blocks != null) {
|
if (frameRanges != null) {
|
||||||
for (SoundStreamBlockTag block : blocks) {
|
for (SoundStreamFrameRange range : frameRanges) {
|
||||||
ByteArrayRange data = block.streamSoundData;
|
for (SoundStreamBlockTag block : range.blocks) {
|
||||||
if (streamSoundCompression == SoundFormat.FORMAT_MP3) {
|
ByteArrayRange data = block.streamSoundData;
|
||||||
ret.add(data.getSubRange(4, data.getLength() - 4));
|
if (streamSoundCompression == SoundFormat.FORMAT_MP3) {
|
||||||
} else {
|
ret.add(data.getSubRange(4, data.getLength() - 4));
|
||||||
ret.add(data);
|
} else {
|
||||||
|
ret.add(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,7 +234,11 @@ public class SoundStreamHeadTag extends SoundStreamHeadTypeTag {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTotalSoundSampleCount() {
|
public long getTotalSoundSampleCount() {
|
||||||
return getBlocks().size() * streamSoundSampleCount;
|
int blockCount = 0;
|
||||||
|
for (SoundStreamFrameRange range : getRanges()) {
|
||||||
|
blockCount += range.blocks.size();
|
||||||
|
}
|
||||||
|
return blockCount * streamSoundSampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -288,4 +294,9 @@ public class SoundStreamHeadTag extends SoundStreamHeadTypeTag {
|
|||||||
public void setSoundRate(int soundRate) {
|
public void setSoundRate(int soundRate) {
|
||||||
this.streamSoundRate = soundRate;
|
this.streamSoundRate = soundRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlaExportName() {
|
||||||
|
return "sound" + getCharacterId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.tags.base;
|
|||||||
import com.jpexs.decompiler.flash.SWF;
|
import com.jpexs.decompiler.flash.SWF;
|
||||||
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
|
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
|
||||||
import com.jpexs.decompiler.flash.tags.Tag;
|
import com.jpexs.decompiler.flash.tags.Tag;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.helpers.ByteArrayRange;
|
import com.jpexs.helpers.ByteArrayRange;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -37,6 +38,6 @@ public abstract class SoundStreamHeadTypeTag extends Tag implements CharacterIdT
|
|||||||
|
|
||||||
public abstract long getSoundSampleCount();
|
public abstract long getSoundSampleCount();
|
||||||
|
|
||||||
public abstract List<SoundStreamBlockTag> getBlocks();
|
public abstract List<SoundStreamFrameRange> getRanges();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,4 +59,10 @@ public interface SoundTag extends TreeItem {
|
|||||||
public void setSoundRate(int soundRate);
|
public void setSoundRate(int soundRate);
|
||||||
|
|
||||||
public int getCharacterId();
|
public int getCharacterId();
|
||||||
|
|
||||||
|
public boolean isReadOnly();
|
||||||
|
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
public String getFlaExportName();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,4 +243,9 @@ public class DefineExternalSound extends CharacterTag implements SoundTag {
|
|||||||
tagInfo.addInfo("general", "stereo", soundFormat.stereo);
|
tagInfo.addInfo("general", "stereo", soundFormat.stereo);
|
||||||
tagInfo.addInfo("general", "sampleCount", sampleCount);
|
tagInfo.addInfo("general", "sampleCount", sampleCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlaExportName() {
|
||||||
|
return "sound" + getCharacterId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -255,4 +255,9 @@ public class DefineExternalStreamSound extends Tag implements CharacterIdTag, So
|
|||||||
tagInfo.addInfo("general", "stereo", soundFormat.stereo);
|
tagInfo.addInfo("general", "stereo", soundFormat.stereo);
|
||||||
tagInfo.addInfo("general", "sampleCount", sampleCount);
|
tagInfo.addInfo("general", "sampleCount", sampleCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlaExportName() {
|
||||||
|
return "sound" + getCharacterId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2023 JPEXS, All rights reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3.0 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library.
|
||||||
|
*/
|
||||||
|
package com.jpexs.decompiler.flash.timeline;
|
||||||
|
|
||||||
|
import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.SoundTag;
|
||||||
|
import com.jpexs.decompiler.flash.treeitems.Openable;
|
||||||
|
import com.jpexs.decompiler.flash.treeitems.TreeItem;
|
||||||
|
import com.jpexs.decompiler.flash.types.sound.SoundExportFormat;
|
||||||
|
import com.jpexs.decompiler.flash.types.sound.SoundFormat;
|
||||||
|
import com.jpexs.helpers.ByteArrayRange;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author JPEXS
|
||||||
|
*/
|
||||||
|
public class SoundStreamFrameRange implements TreeItem, SoundTag {
|
||||||
|
public int startFrame;
|
||||||
|
public int endFrame;
|
||||||
|
public List<SoundStreamBlockTag> blocks = new ArrayList<>();
|
||||||
|
|
||||||
|
private final SoundStreamHeadTypeTag head;
|
||||||
|
|
||||||
|
public SoundStreamFrameRange(SoundStreamHeadTypeTag head) {
|
||||||
|
this.head = head;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Openable getOpenable() {
|
||||||
|
return head.getOpenable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isModified() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SoundExportFormat getExportFormat() {
|
||||||
|
return head.getExportFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean importSupported() {
|
||||||
|
return false; //??
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSoundRate() {
|
||||||
|
return head.getSoundRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getSoundType() {
|
||||||
|
return head.getSoundType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ByteArrayRange> getRawSoundData() {
|
||||||
|
List<ByteArrayRange> ret = new ArrayList<>();
|
||||||
|
for (SoundStreamBlockTag block : blocks) {
|
||||||
|
ByteArrayRange data = block.streamSoundData;
|
||||||
|
if (getSoundFormatId() == SoundFormat.FORMAT_MP3) {
|
||||||
|
ret.add(data.getSubRange(4, data.getLength() - 4));
|
||||||
|
} else {
|
||||||
|
ret.add(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSoundFormatId() {
|
||||||
|
return head.getSoundFormatId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTotalSoundSampleCount() {
|
||||||
|
return blocks.size() * head.getSoundSampleCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getSoundSize() {
|
||||||
|
return head.getSoundSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCharacterExportFileName() {
|
||||||
|
return head.getCharacterExportFileName() + "_" + (startFrame + 1) + "-" + (endFrame + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "SoundStreamBlocks";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SoundFormat getSoundFormat() {
|
||||||
|
return head.getSoundFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSoundSize(boolean soundSize) {
|
||||||
|
//?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSoundType(boolean soundType) {
|
||||||
|
//?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSoundSampleCount(long soundSampleCount) {
|
||||||
|
//?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSoundCompression(int soundCompression) {
|
||||||
|
//?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSoundRate(int soundRate) {
|
||||||
|
//?
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCharacterId() {
|
||||||
|
return head.getCharacterId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoundStreamHeadTypeTag getHead() {
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SoundStreamBlocks (frame " + (startFrame + 1) + " - " + (endFrame + 1) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReadOnly() {
|
||||||
|
return head.isReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFlaExportName() {
|
||||||
|
return head.getFlaExportName() + "_" + (startFrame + 1) + "-" + (endFrame + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -118,7 +118,7 @@ public class Timeline {
|
|||||||
|
|
||||||
private final Map<ASMSource, Integer> actionFrames = new HashMap<>();
|
private final Map<ASMSource, Integer> actionFrames = new HashMap<>();
|
||||||
|
|
||||||
private final Map<Integer, List<SoundStreamBlockTag>> soundStramBlocks = new LinkedHashMap<>();
|
private final Map<Integer, List<SoundStreamFrameRange>> soundStreamRanges = new LinkedHashMap<>();
|
||||||
|
|
||||||
private AS2Package as2RootPackage;
|
private AS2Package as2RootPackage;
|
||||||
|
|
||||||
@@ -174,9 +174,9 @@ public class Timeline {
|
|||||||
return depthMaxFrame;
|
return depthMaxFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SoundStreamBlockTag> getSoundStreamBlocks(SoundStreamHeadTypeTag head) {
|
public List<SoundStreamFrameRange> getSoundStreamBlocks(SoundStreamHeadTypeTag head) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
return soundStramBlocks.get(head.getCharacterId());
|
return soundStreamRanges.get(head.getCharacterId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tag getParentTag() {
|
public Tag getParentTag() {
|
||||||
@@ -194,7 +194,7 @@ public class Timeline {
|
|||||||
asmSources.clear();
|
asmSources.clear();
|
||||||
asmSourceContainers.clear();
|
asmSourceContainers.clear();
|
||||||
actionFrames.clear();
|
actionFrames.clear();
|
||||||
soundStramBlocks.clear();
|
soundStreamRanges.clear();
|
||||||
otherTags.clear();
|
otherTags.clear();
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.swf = swf;
|
this.swf = swf;
|
||||||
@@ -576,13 +576,23 @@ public class Timeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void populateSoundStreamBlocks(int containerId, Iterable<Tag> tags) {
|
private void populateSoundStreamBlocks(int containerId, Iterable<Tag> tags) {
|
||||||
List<SoundStreamBlockTag> blocks = null;
|
List<SoundStreamFrameRange> ranges = null;
|
||||||
|
SoundStreamFrameRange range = null;
|
||||||
|
final int MIN_NUM_FRAMES_NO_SOUND = 2;
|
||||||
|
int numFramesNoSound = MIN_NUM_FRAMES_NO_SOUND;
|
||||||
|
boolean frameHasSound = false;
|
||||||
|
int frame = 0;
|
||||||
|
SoundStreamHeadTypeTag head = null;
|
||||||
for (Tag t : tags) {
|
for (Tag t : tags) {
|
||||||
if (t instanceof SoundStreamHeadTypeTag) {
|
if (t instanceof SoundStreamHeadTypeTag) {
|
||||||
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) t;
|
head = (SoundStreamHeadTypeTag) t;
|
||||||
head.setCharacterId(containerId);
|
head.setCharacterId(containerId);
|
||||||
blocks = new ArrayList<>();
|
ranges = new ArrayList<>();
|
||||||
soundStramBlocks.put(containerId, blocks);
|
range = new SoundStreamFrameRange(head);
|
||||||
|
range.startFrame = -1;
|
||||||
|
range.endFrame = -1;
|
||||||
|
numFramesNoSound = MIN_NUM_FRAMES_NO_SOUND;
|
||||||
|
soundStreamRanges.put(containerId, ranges);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (t instanceof DefineExternalStreamSound) {
|
if (t instanceof DefineExternalStreamSound) {
|
||||||
@@ -595,14 +605,41 @@ public class Timeline {
|
|||||||
DefineSpriteTag sprite = (DefineSpriteTag) t;
|
DefineSpriteTag sprite = (DefineSpriteTag) t;
|
||||||
populateSoundStreamBlocks(sprite.getCharacterId(), sprite.getTags());
|
populateSoundStreamBlocks(sprite.getCharacterId(), sprite.getTags());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (t instanceof ShowFrameTag) {
|
||||||
|
frame++;
|
||||||
|
if (frameHasSound) {
|
||||||
|
numFramesNoSound = 0;
|
||||||
|
} else {
|
||||||
|
numFramesNoSound++;
|
||||||
|
}
|
||||||
|
frameHasSound = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (blocks == null) {
|
if (ranges == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (range == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t instanceof SoundStreamBlockTag) {
|
if (t instanceof SoundStreamBlockTag) {
|
||||||
blocks.add((SoundStreamBlockTag) t);
|
if (numFramesNoSound >= MIN_NUM_FRAMES_NO_SOUND && range.endFrame > -1) {
|
||||||
}
|
ranges.add(range);
|
||||||
|
range = new SoundStreamFrameRange(head);
|
||||||
|
range.startFrame = -1;
|
||||||
|
range.endFrame = -1;
|
||||||
|
}
|
||||||
|
range.blocks.add((SoundStreamBlockTag) t);
|
||||||
|
if (range.startFrame == -1) {
|
||||||
|
range.startFrame = frame;
|
||||||
|
}
|
||||||
|
range.endFrame = frame;
|
||||||
|
frameHasSound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (range != null && ranges != null && range.endFrame > -1) {
|
||||||
|
ranges.add(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ import com.jpexs.decompiler.flash.tags.base.SoundTag;
|
|||||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||||
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
||||||
import com.jpexs.decompiler.flash.tags.font.CharacterRanges;
|
import com.jpexs.decompiler.flash.tags.font.CharacterRanges;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||||
import com.jpexs.decompiler.flash.types.BUTTONCONDACTION;
|
import com.jpexs.decompiler.flash.types.BUTTONCONDACTION;
|
||||||
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
|
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
|
||||||
@@ -1949,6 +1950,158 @@ public class XFLConverter {
|
|||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void convertSoundMedia(SWF swf, ReadOnlyTagList tags, SoundTag symbol, XFLXmlWriter writer, HashMap<String, byte[]> files) throws XMLStreamException {
|
||||||
|
int soundFormat = 0;
|
||||||
|
int soundRate = 0;
|
||||||
|
boolean soundType = false;
|
||||||
|
boolean soundSize = false;
|
||||||
|
long soundSampleCount = 0;
|
||||||
|
byte[] soundData = SWFInputStream.BYTE_ARRAY_EMPTY;
|
||||||
|
int[] rateMap = {5, 11, 22, 44};
|
||||||
|
String exportFormat = "flv";
|
||||||
|
if (symbol instanceof SoundStreamFrameRange) {
|
||||||
|
SoundStreamHeadTypeTag head = ((SoundStreamFrameRange) symbol).getHead();
|
||||||
|
soundFormat = head.getSoundFormatId();
|
||||||
|
soundRate = head.getSoundRate();
|
||||||
|
soundType = head.getSoundType();
|
||||||
|
soundSize = head.getSoundSize();
|
||||||
|
soundSampleCount = head.getSoundSampleCount();
|
||||||
|
boolean found = false;
|
||||||
|
for (Tag t : tags) {
|
||||||
|
if (found && (t instanceof SoundStreamBlockTag)) {
|
||||||
|
SoundStreamBlockTag bl = (SoundStreamBlockTag) t;
|
||||||
|
soundData = bl.streamSoundData.getRangeData();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (t == head) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (symbol instanceof DefineSoundTag) {
|
||||||
|
DefineSoundTag sound = (DefineSoundTag) symbol;
|
||||||
|
soundFormat = sound.soundFormat;
|
||||||
|
soundRate = sound.soundRate;
|
||||||
|
soundType = sound.soundType;
|
||||||
|
soundData = sound.soundData.getRangeData();
|
||||||
|
soundSize = sound.soundSize;
|
||||||
|
soundSampleCount = sound.soundSampleCount;
|
||||||
|
}
|
||||||
|
int format = 0;
|
||||||
|
int bits = 0;
|
||||||
|
if ((soundFormat == SoundFormat.FORMAT_ADPCM)
|
||||||
|
|| (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN)
|
||||||
|
|| (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN)) {
|
||||||
|
exportFormat = "wav";
|
||||||
|
if (soundType) { //stereo
|
||||||
|
format += 1;
|
||||||
|
}
|
||||||
|
switch (soundRate) {
|
||||||
|
case 0:
|
||||||
|
format += 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
format += 6;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
format += 10;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
format += 14;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (soundFormat == SoundFormat.FORMAT_SPEEX) {
|
||||||
|
bits = 18;
|
||||||
|
}
|
||||||
|
if (soundFormat == SoundFormat.FORMAT_ADPCM) {
|
||||||
|
exportFormat = "wav";
|
||||||
|
try {
|
||||||
|
SWFInputStream sis = new SWFInputStream(swf, soundData);
|
||||||
|
int adpcmCodeSize = (int) sis.readUB(2, "adpcmCodeSize");
|
||||||
|
bits = 2 + adpcmCodeSize;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (soundFormat == SoundFormat.FORMAT_MP3) {
|
||||||
|
exportFormat = "mp3";
|
||||||
|
if (!soundType) { //mono
|
||||||
|
format += 1;
|
||||||
|
}
|
||||||
|
format += 4; //quality best
|
||||||
|
try {
|
||||||
|
SWFInputStream sis = new SWFInputStream(swf, soundData);
|
||||||
|
MP3SOUNDDATA s = new MP3SOUNDDATA(sis, false);
|
||||||
|
if (!s.frames.isEmpty()) {
|
||||||
|
MP3FRAME frame = s.frames.get(0);
|
||||||
|
int bitRate = frame.getBitRate();
|
||||||
|
|
||||||
|
switch (bitRate) {
|
||||||
|
case 8:
|
||||||
|
bits = 6;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
bits = 7;
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
bits = 8;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
bits = 9;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
bits = 10;
|
||||||
|
break;
|
||||||
|
case 48:
|
||||||
|
bits = 11;
|
||||||
|
break;
|
||||||
|
case 56:
|
||||||
|
bits = 12;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
bits = 13;
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
bits = 14;
|
||||||
|
break;
|
||||||
|
case 112:
|
||||||
|
bits = 15;
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
bits = 16;
|
||||||
|
break;
|
||||||
|
case 160:
|
||||||
|
bits = 17;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException | IndexOutOfBoundsException ex) {
|
||||||
|
logger.log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SoundTag st = (SoundTag) symbol;
|
||||||
|
SoundFormat fmt = st.getSoundFormat();
|
||||||
|
byte[] data = SWFInputStream.BYTE_ARRAY_EMPTY;
|
||||||
|
try {
|
||||||
|
data = new SoundExporter().exportSound(st, SoundExportMode.MP3_WAV);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
String symbolFile = symbol.getFlaExportName() + "." + exportFormat;
|
||||||
|
files.put(symbolFile, data);
|
||||||
|
writer.writeStartElement("DOMSoundItem", new String[]{
|
||||||
|
"name", symbolFile,
|
||||||
|
"sourceLastImported", Long.toString(getTimestamp(swf)),
|
||||||
|
"externalFileSize", Integer.toString(data.length)});
|
||||||
|
writer.writeAttribute("href", symbolFile);
|
||||||
|
writer.writeAttribute("format", rateMap[soundRate] + "kHz" + " " + (soundSize ? "16bit" : "8bit") + " " + (soundType ? "Stereo" : "Mono"));
|
||||||
|
writer.writeAttribute("exportFormat", format);
|
||||||
|
writer.writeAttribute("exportBits", bits);
|
||||||
|
writer.writeAttribute("sampleCount", soundSampleCount);
|
||||||
|
}
|
||||||
|
|
||||||
private void convertMedia(SWF swf, Map<Integer, String> characterVariables, Map<Integer, String> characterClasses, List<Integer> nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap<Integer, CharacterTag> characters, HashMap<String, byte[]> files, HashMap<String, byte[]> datfiles, FLAVersion flaVersion, XFLXmlWriter writer, StatusStack statusStack) throws XMLStreamException {
|
private void convertMedia(SWF swf, Map<Integer, String> characterVariables, Map<Integer, String> characterClasses, List<Integer> nonLibraryShapes, String backgroundColor, ReadOnlyTagList tags, HashMap<Integer, CharacterTag> characters, HashMap<String, byte[]> files, HashMap<String, byte[]> datfiles, FLAVersion flaVersion, XFLXmlWriter writer, StatusStack statusStack) throws XMLStreamException {
|
||||||
boolean hasMedia = false;
|
boolean hasMedia = false;
|
||||||
for (int ch : characters.keySet()) {
|
for (int ch : characters.keySet()) {
|
||||||
@@ -1967,7 +2120,8 @@ public class XFLConverter {
|
|||||||
|
|
||||||
int mediaCount = 0;
|
int mediaCount = 0;
|
||||||
writer.writeStartElement("media");
|
writer.writeStartElement("media");
|
||||||
|
|
||||||
|
|
||||||
for (int ch : characters.keySet()) {
|
for (int ch : characters.keySet()) {
|
||||||
CharacterTag symbol = characters.get(ch);
|
CharacterTag symbol = characters.get(ch);
|
||||||
if (symbol instanceof ImageTag) {
|
if (symbol instanceof ImageTag) {
|
||||||
@@ -2060,157 +2214,9 @@ public class XFLConverter {
|
|||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
mediaCount++;
|
mediaCount++;
|
||||||
statusStack.popStatus();
|
statusStack.popStatus();
|
||||||
} else if (/*(symbol instanceof SoundStreamHeadTypeTag) || FIXME */(symbol instanceof DefineSoundTag)) {
|
} else if (symbol instanceof DefineSoundTag) {
|
||||||
statusStack.pushStatus(symbol.toString());
|
statusStack.pushStatus(symbol.toString());
|
||||||
int soundFormat = 0;
|
convertSoundMedia(swf, tags, (DefineSoundTag) symbol, writer, files);
|
||||||
int soundRate = 0;
|
|
||||||
boolean soundType = false;
|
|
||||||
boolean soundSize = false;
|
|
||||||
long soundSampleCount = 0;
|
|
||||||
byte[] soundData = SWFInputStream.BYTE_ARRAY_EMPTY;
|
|
||||||
int[] rateMap = {5, 11, 22, 44};
|
|
||||||
String exportFormat = "flv";
|
|
||||||
if (false) { //FIXME symbol instanceof SoundStreamHeadTypeTag) {
|
|
||||||
SoundStreamHeadTypeTag sstream = null; //(SoundStreamHeadTypeTag) symbol;
|
|
||||||
soundFormat = sstream.getSoundFormatId();
|
|
||||||
soundRate = sstream.getSoundRate();
|
|
||||||
soundType = sstream.getSoundType();
|
|
||||||
soundSize = sstream.getSoundSize();
|
|
||||||
soundSampleCount = sstream.getSoundSampleCount();
|
|
||||||
boolean found = false;
|
|
||||||
for (Tag t : tags) {
|
|
||||||
if (found && (t instanceof SoundStreamBlockTag)) {
|
|
||||||
SoundStreamBlockTag bl = (SoundStreamBlockTag) t;
|
|
||||||
soundData = bl.streamSoundData.getRangeData();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (t == symbol) {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (symbol instanceof DefineSoundTag) {
|
|
||||||
DefineSoundTag sound = (DefineSoundTag) symbol;
|
|
||||||
soundFormat = sound.soundFormat;
|
|
||||||
soundRate = sound.soundRate;
|
|
||||||
soundType = sound.soundType;
|
|
||||||
soundData = sound.soundData.getRangeData();
|
|
||||||
soundSize = sound.soundSize;
|
|
||||||
soundSampleCount = sound.soundSampleCount;
|
|
||||||
}
|
|
||||||
int format = 0;
|
|
||||||
int bits = 0;
|
|
||||||
if ((soundFormat == SoundFormat.FORMAT_ADPCM)
|
|
||||||
|| (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_LITTLE_ENDIAN)
|
|
||||||
|| (soundFormat == SoundFormat.FORMAT_UNCOMPRESSED_NATIVE_ENDIAN)) {
|
|
||||||
exportFormat = "wav";
|
|
||||||
if (soundType) { //stereo
|
|
||||||
format += 1;
|
|
||||||
}
|
|
||||||
switch (soundRate) {
|
|
||||||
case 0:
|
|
||||||
format += 2;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
format += 6;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
format += 10;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
format += 14;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (soundFormat == SoundFormat.FORMAT_SPEEX) {
|
|
||||||
bits = 18;
|
|
||||||
}
|
|
||||||
if (soundFormat == SoundFormat.FORMAT_ADPCM) {
|
|
||||||
exportFormat = "wav";
|
|
||||||
try {
|
|
||||||
SWFInputStream sis = new SWFInputStream(swf, soundData);
|
|
||||||
int adpcmCodeSize = (int) sis.readUB(2, "adpcmCodeSize");
|
|
||||||
bits = 2 + adpcmCodeSize;
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (soundFormat == SoundFormat.FORMAT_MP3) {
|
|
||||||
exportFormat = "mp3";
|
|
||||||
if (!soundType) { //mono
|
|
||||||
format += 1;
|
|
||||||
}
|
|
||||||
format += 4; //quality best
|
|
||||||
try {
|
|
||||||
SWFInputStream sis = new SWFInputStream(swf, soundData);
|
|
||||||
MP3SOUNDDATA s = new MP3SOUNDDATA(sis, false);
|
|
||||||
if (!s.frames.isEmpty()) {
|
|
||||||
MP3FRAME frame = s.frames.get(0);
|
|
||||||
int bitRate = frame.getBitRate();
|
|
||||||
|
|
||||||
switch (bitRate) {
|
|
||||||
case 8:
|
|
||||||
bits = 6;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
bits = 7;
|
|
||||||
break;
|
|
||||||
case 20:
|
|
||||||
bits = 8;
|
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
bits = 9;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
bits = 10;
|
|
||||||
break;
|
|
||||||
case 48:
|
|
||||||
bits = 11;
|
|
||||||
break;
|
|
||||||
case 56:
|
|
||||||
bits = 12;
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
bits = 13;
|
|
||||||
break;
|
|
||||||
case 80:
|
|
||||||
bits = 14;
|
|
||||||
break;
|
|
||||||
case 112:
|
|
||||||
bits = 15;
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
bits = 16;
|
|
||||||
break;
|
|
||||||
case 160:
|
|
||||||
bits = 17;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException | IndexOutOfBoundsException ex) {
|
|
||||||
logger.log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SoundTag st = (SoundTag) symbol;
|
|
||||||
SoundFormat fmt = st.getSoundFormat();
|
|
||||||
byte[] data = SWFInputStream.BYTE_ARRAY_EMPTY;
|
|
||||||
try {
|
|
||||||
data = new SoundExporter().exportSound(st, SoundExportMode.MP3_WAV);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
String symbolFile = "sound" + symbol.getCharacterId() + "." + exportFormat;
|
|
||||||
files.put(symbolFile, data);
|
|
||||||
writer.writeStartElement("DOMSoundItem", new String[]{
|
|
||||||
"name", symbolFile,
|
|
||||||
"sourceLastImported", Long.toString(getTimestamp(swf)),
|
|
||||||
"externalFileSize", Integer.toString(data.length)});
|
|
||||||
writer.writeAttribute("href", symbolFile);
|
|
||||||
writer.writeAttribute("format", rateMap[soundRate] + "kHz" + " " + (soundSize ? "16bit" : "8bit") + " " + (soundType ? "Stereo" : "Mono"));
|
|
||||||
writer.writeAttribute("exportFormat", format);
|
|
||||||
writer.writeAttribute("exportBits", bits);
|
|
||||||
writer.writeAttribute("sampleCount", soundSampleCount);
|
|
||||||
|
|
||||||
boolean linkageExportForAS = false;
|
boolean linkageExportForAS = false;
|
||||||
if (characterClasses.containsKey(symbol.getCharacterId())) {
|
if (characterClasses.containsKey(symbol.getCharacterId())) {
|
||||||
@@ -2314,6 +2320,35 @@ public class XFLConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Tag t : tags) {
|
||||||
|
if (t instanceof SoundStreamHeadTypeTag) {
|
||||||
|
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) t;
|
||||||
|
for (SoundStreamFrameRange range : head.getRanges()) {
|
||||||
|
statusStack.pushStatus(range.toString());
|
||||||
|
convertSoundMedia(swf, tags, range, writer, files);
|
||||||
|
writer.writeEndElement();
|
||||||
|
mediaCount++;
|
||||||
|
statusStack.popStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t instanceof DefineSpriteTag) {
|
||||||
|
DefineSpriteTag sprite = (DefineSpriteTag) t;
|
||||||
|
for (Tag st : sprite.getTags()) {
|
||||||
|
if (st instanceof SoundStreamHeadTypeTag) {
|
||||||
|
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) st;
|
||||||
|
for (SoundStreamFrameRange range : head.getRanges()) {
|
||||||
|
statusStack.pushStatus(range.toString());
|
||||||
|
convertSoundMedia(swf, sprite.getTags(), range, writer, files);
|
||||||
|
writer.writeEndElement();
|
||||||
|
mediaCount++;
|
||||||
|
statusStack.popStatus();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2420,7 +2455,7 @@ public class XFLConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void convertFrame(boolean shapeTween, SoundStreamHeadTypeTag soundStreamHead, StartSoundTag startSound, int frame, int duration, String actionScript, String elements, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
private static void convertFrame(Scene scene, boolean shapeTween, SoundStreamFrameRange soundStreamRange, StartSoundTag startSound, int frame, int duration, String actionScript, String elements, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
||||||
DefineSoundTag sound = null;
|
DefineSoundTag sound = null;
|
||||||
if (startSound != null) {
|
if (startSound != null) {
|
||||||
SWF swf = startSound.getSwf();
|
SWF swf = startSound.getSwf();
|
||||||
@@ -2438,13 +2473,14 @@ public class XFLConverter {
|
|||||||
} else {
|
} else {
|
||||||
writer.writeAttribute("keyMode", KEY_MODE_NORMAL);
|
writer.writeAttribute("keyMode", KEY_MODE_NORMAL);
|
||||||
}
|
}
|
||||||
if (soundStreamHead != null && startSound == null) {
|
if (soundStreamRange != null && startSound == null) {
|
||||||
String soundName = "sound" + soundStreamHead.getCharacterId() + "." + soundStreamHead.getExportFormat().toString().toLowerCase();
|
String soundName = soundStreamRange.getFlaExportName() + "." + soundStreamRange.getExportFormat().toString().toLowerCase();
|
||||||
writer.writeAttribute("soundName", soundName);
|
writer.writeAttribute("soundName", soundName);
|
||||||
writer.writeAttribute("soundSync", "stream");
|
writer.writeAttribute("soundSync", "stream");
|
||||||
writer.writeStartElement("SoundEnvelope");
|
writer.writeStartElement("SoundEnvelope");
|
||||||
writer.writeEmptyElement("SoundEnvelopePoint", new String[]{"level0", "32768", "level1", "32768"});
|
writer.writeEmptyElement("SoundEnvelopePoint", new String[]{"level0", "32768", "level1", "32768"});
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
|
||||||
}
|
}
|
||||||
if (startSound != null && sound != null) {
|
if (startSound != null && sound != null) {
|
||||||
convertSoundUsage(writer, sound, startSound.soundInfo);
|
convertSoundUsage(writer, sound, startSound.soundInfo);
|
||||||
@@ -2497,7 +2533,7 @@ public class XFLConverter {
|
|||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void convertFrames(SWF swf, List<Integer> onlyFrames, int startFrame, int endFrame, String prevStr, String afterStr, List<Integer> nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap<Integer, CharacterTag> characters, int depth, FLAVersion flaVersion, HashMap<String, byte[]> files, XFLXmlWriter writer, List<Integer> multiUsageMorphShapes, StatusStack statusStack) throws XMLStreamException {
|
private static void convertFrames(Scene scene, SWF swf, List<Integer> onlyFrames, int startFrame, int endFrame, String prevStr, String afterStr, List<Integer> nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap<Integer, CharacterTag> characters, int depth, FLAVersion flaVersion, HashMap<String, byte[]> files, XFLXmlWriter writer, List<Integer> multiUsageMorphShapes, StatusStack statusStack) throws XMLStreamException {
|
||||||
boolean lastIn = true;
|
boolean lastIn = true;
|
||||||
XFLXmlWriter writer2 = new XFLXmlWriter();
|
XFLXmlWriter writer2 = new XFLXmlWriter();
|
||||||
prevStr += "<frames>";
|
prevStr += "<frames>";
|
||||||
@@ -2669,7 +2705,7 @@ public class XFLConverter {
|
|||||||
SHAPEWITHSTYLE endShape = m.getShapeAtRatio(65535); //lastTweenRatio);
|
SHAPEWITHSTYLE endShape = m.getShapeAtRatio(65535); //lastTweenRatio);
|
||||||
convertShape(swf, characters, matrix, m.getShapeNum() == 1 ? 3 : 4, endShape.shapeRecords, m.getFillStyles().getFillStylesAt(lastTweenRatio), m.getLineStyles().getLineStylesAt(m.getShapeNum(), lastTweenRatio), true, false, addLastWriter);
|
convertShape(swf, characters, matrix, m.getShapeNum() == 1 ? 3 : 4, endShape.shapeRecords, m.getFillStyles().getFillStylesAt(lastTweenRatio), m.getLineStyles().getLineStylesAt(m.getShapeNum(), lastTweenRatio), true, false, addLastWriter);
|
||||||
//duration--;
|
//duration--;
|
||||||
convertFrame(true, null, null, frame - duration, duration, "", lastElements, files, writer2);
|
convertFrame(scene, true, null, null, frame - duration, duration, "", lastElements, files, writer2);
|
||||||
duration = 1;
|
duration = 1;
|
||||||
lastElements = addLastWriter.toString();
|
lastElements = addLastWriter.toString();
|
||||||
lastCharacter = m;
|
lastCharacter = m;
|
||||||
@@ -2730,7 +2766,7 @@ public class XFLConverter {
|
|||||||
frame++;
|
frame++;
|
||||||
String elements = elementsWriter.toString();
|
String elements = elementsWriter.toString();
|
||||||
if (!elements.equals(lastElements) && frame > 0) {
|
if (!elements.equals(lastElements) && frame > 0) {
|
||||||
convertFrame(false, null, null, frame - duration, duration, "", lastElements, files, writer2);
|
convertFrame(scene, false, null, null, frame - duration, duration, "", lastElements, files, writer2);
|
||||||
duration = 1;
|
duration = 1;
|
||||||
} else if (frame == 0) {
|
} else if (frame == 0) {
|
||||||
duration = 1;
|
duration = 1;
|
||||||
@@ -2768,7 +2804,7 @@ public class XFLConverter {
|
|||||||
}
|
}
|
||||||
if (!lastElements.isEmpty() || writer2.length() > 0) {
|
if (!lastElements.isEmpty() || writer2.length() > 0) {
|
||||||
frame++;
|
frame++;
|
||||||
convertFrame(false, null, null, (frame - duration < 0 ? 0 : frame - duration), duration, "", lastElements, files, writer2);
|
convertFrame(scene, false, null, null, (frame - duration < 0 ? 0 : frame - duration), duration, "", lastElements, files, writer2);
|
||||||
}
|
}
|
||||||
afterStr = "</frames>" + afterStr;
|
afterStr = "</frames>" + afterStr;
|
||||||
|
|
||||||
@@ -3140,13 +3176,12 @@ public class XFLConverter {
|
|||||||
return hasLabel;
|
return hasLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void convertSoundLayer(ReadOnlyTagList timeLineTags, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
private void convertSoundLayer(Scene scene, ReadOnlyTagList timeLineTags, HashMap<String, byte[]> files, XFLXmlWriter writer) throws XMLStreamException {
|
||||||
int soundLayerIndex = 0;
|
int soundLayerIndex = 0;
|
||||||
XFLXmlWriter writer2 = new XFLXmlWriter();
|
XFLXmlWriter writer2 = new XFLXmlWriter();
|
||||||
List<StartSoundTag> startSounds = new ArrayList<>();
|
List<StartSoundTag> startSounds = new ArrayList<>();
|
||||||
List<Integer> startSoundFrameNumbers = new ArrayList<>();
|
List<Integer> startSoundFrameNumbers = new ArrayList<>();
|
||||||
List<SoundStreamHeadTypeTag> soundStreamHeads = new ArrayList<>();
|
List<SoundStreamFrameRange> soundStreamRanges = new ArrayList<>();
|
||||||
List<Integer> soundStreamHeadFrameNumbers = new ArrayList<>();
|
|
||||||
int frame = 0;
|
int frame = 0;
|
||||||
for (Tag t : timeLineTags) {
|
for (Tag t : timeLineTags) {
|
||||||
if (t instanceof StartSoundTag) {
|
if (t instanceof StartSoundTag) {
|
||||||
@@ -3168,32 +3203,30 @@ public class XFLConverter {
|
|||||||
}
|
}
|
||||||
} else if (t instanceof SoundStreamHeadTypeTag) {
|
} else if (t instanceof SoundStreamHeadTypeTag) {
|
||||||
SoundStreamHeadTypeTag soundStreamHead = (SoundStreamHeadTypeTag) t;
|
SoundStreamHeadTypeTag soundStreamHead = (SoundStreamHeadTypeTag) t;
|
||||||
if (!files.containsKey("sound" + soundStreamHead.getCharacterId() + "." + soundStreamHead.getExportFormat().toString().toLowerCase())) { //Sound was not exported
|
|
||||||
soundStreamHead = null; // ignore
|
for (SoundStreamFrameRange range : soundStreamHead.getRanges()) {
|
||||||
}
|
if (files.containsKey(range.getFlaExportName() + "." + soundStreamHead.getExportFormat().toString().toLowerCase())) { //Sound was really exported
|
||||||
|
soundStreamRanges.add(range);
|
||||||
if (soundStreamHead != null) {
|
}
|
||||||
soundStreamHeads.add(soundStreamHead);
|
|
||||||
soundStreamHeadFrameNumbers.add(frame);
|
|
||||||
}
|
}
|
||||||
} else if (t instanceof ShowFrameTag) {
|
} else if (t instanceof ShowFrameTag) {
|
||||||
frame++;
|
frame++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < soundStreamHeads.size(); i++) {
|
for (int i = 0; i < soundStreamRanges.size(); i++) {
|
||||||
writer.writeStartElement("DOMLayer", new String[]{"name", "Sound Layer " + (soundLayerIndex++), "color", randomOutlineColor()});
|
writer.writeStartElement("DOMLayer", new String[]{"name", "Sound Layer " + (soundLayerIndex++), "color", randomOutlineColor()});
|
||||||
writer.writeStartElement("frames");
|
writer.writeStartElement("frames");
|
||||||
|
|
||||||
int startFrame = soundStreamHeadFrameNumbers.get(i);
|
int startFrame = soundStreamRanges.get(i).startFrame - scene.startFrame;
|
||||||
int duration = frame - startFrame;
|
int duration = frame - startFrame;
|
||||||
|
|
||||||
if (startFrame != 0) {
|
if (startFrame != 0) {
|
||||||
// empty frames should be added
|
// empty frames should be added
|
||||||
convertFrame(false, null, null, 0, startFrame, "", "", files, writer);
|
convertFrame(scene, false, null, null, 0, startFrame, "", "", files, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
convertFrame(false, soundStreamHeads.get(i), null, startFrame, duration, "", "", files, writer);
|
convertFrame(scene, false, soundStreamRanges.get(i), null, startFrame, duration, "", "", files, writer);
|
||||||
|
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
@@ -3208,10 +3241,10 @@ public class XFLConverter {
|
|||||||
|
|
||||||
if (startFrame != 0) {
|
if (startFrame != 0) {
|
||||||
// empty frames should be added
|
// empty frames should be added
|
||||||
convertFrame(false, null, null, 0, startFrame, "", "", files, writer);
|
convertFrame(scene, false, null, null, 0, startFrame, "", "", files, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
convertFrame(false, null, startSounds.get(i), startFrame, duration, "", "", files, writer);
|
convertFrame(scene, false, null, startSounds.get(i), startFrame, duration, "", "", files, writer);
|
||||||
|
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
@@ -4076,7 +4109,7 @@ public class XFLConverter {
|
|||||||
"color", randomOutlineColor(),
|
"color", randomOutlineColor(),
|
||||||
"layerType", "mask",
|
"layerType", "mask",
|
||||||
"locked", "true"});
|
"locked", "true"});
|
||||||
convertFrames(swf, depthToFramesList.get(po.getDepth()), clipFrame, lastFrame, "", "", nonLibraryShapes, tags, sceneTimelineTags, characters, po.getDepth(), flaVersion, files, writer, multiUsageMorphShapes, statusStack);
|
convertFrames(scene, swf, depthToFramesList.get(po.getDepth()), clipFrame, lastFrame, "", "", nonLibraryShapes, tags, sceneTimelineTags, characters, po.getDepth(), flaVersion, files, writer, multiUsageMorphShapes, statusStack);
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
|
||||||
int parentIndex = index;
|
int parentIndex = index;
|
||||||
@@ -4165,7 +4198,7 @@ public class XFLConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int nd = po.getClipDepth() - 1; nd > po.getDepth(); nd--) {
|
for (int nd = po.getClipDepth() - 1; nd > po.getDepth(); nd--) {
|
||||||
boolean nonEmpty = writeLayer(swf, index, depthToFramesList.get(nd), nd, clipFrame, lastFrame, parentIndex, writer, nonLibraryShapes, tags, sceneTimelineTags, characters, flaVersion, files, multiUsageMorphShapes, statusStack);
|
boolean nonEmpty = writeLayer(scene, swf, index, depthToFramesList.get(nd), nd, clipFrame, lastFrame, parentIndex, writer, nonLibraryShapes, tags, sceneTimelineTags, characters, flaVersion, files, multiUsageMorphShapes, statusStack);
|
||||||
for (int i = clipFrame; i <= lastFrame; i++) {
|
for (int i = clipFrame; i <= lastFrame; i++) {
|
||||||
depthToFramesList.get(nd).remove((Integer) i);
|
depthToFramesList.get(nd).remove((Integer) i);
|
||||||
}
|
}
|
||||||
@@ -4179,7 +4212,7 @@ public class XFLConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean nonEmpty = writeLayer(swf, index, depthToFramesList.get(d), d, 0, Integer.MAX_VALUE, -1, writer, nonLibraryShapes, tags, sceneTimelineTags, characters, flaVersion, files, multiUsageMorphShapes, statusStack);
|
boolean nonEmpty = writeLayer(scene, swf, index, depthToFramesList.get(d), d, 0, Integer.MAX_VALUE, -1, writer, nonLibraryShapes, tags, sceneTimelineTags, characters, flaVersion, files, multiUsageMorphShapes, statusStack);
|
||||||
if (nonEmpty) {
|
if (nonEmpty) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -4190,7 +4223,7 @@ public class XFLConverter {
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
convertSoundLayer(sceneTimelineTags, files, writer);
|
convertSoundLayer(scene, sceneTimelineTags, files, writer);
|
||||||
writer.writeEndElement(); //layers
|
writer.writeEndElement(); //layers
|
||||||
writer.writeEndElement(); //DOMTimeline
|
writer.writeEndElement(); //DOMTimeline
|
||||||
}
|
}
|
||||||
@@ -4218,7 +4251,7 @@ public class XFLConverter {
|
|||||||
writer.writeEndElement(); //DOMLayer
|
writer.writeEndElement(); //DOMLayer
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean writeLayer(SWF swf, int index, List<Integer> onlyFrames, int d, int startFrame, int endFrame, int parentLayer, XFLXmlWriter writer, List<Integer> nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap<Integer, CharacterTag> characters, FLAVersion flaVersion, HashMap<String, byte[]> files, List<Integer> multiUsageMorphShapes, StatusStack statusStack) throws XMLStreamException {
|
private boolean writeLayer(Scene scene, SWF swf, int index, List<Integer> onlyFrames, int d, int startFrame, int endFrame, int parentLayer, XFLXmlWriter writer, List<Integer> nonLibraryShapes, ReadOnlyTagList tags, ReadOnlyTagList timelineTags, HashMap<Integer, CharacterTag> characters, FLAVersion flaVersion, HashMap<String, byte[]> files, List<Integer> multiUsageMorphShapes, StatusStack statusStack) throws XMLStreamException {
|
||||||
XFLXmlWriter layerPrev = new XFLXmlWriter();
|
XFLXmlWriter layerPrev = new XFLXmlWriter();
|
||||||
statusStack.pushStatus("layer " + (index + 1));
|
statusStack.pushStatus("layer " + (index + 1));
|
||||||
//System.err.println("- writing layer " + (index + 1) + (startFrame == 0 && endFrame == Integer.MAX_VALUE ? ", all frames": ", frame " + startFrame + " to " + endFrame));
|
//System.err.println("- writing layer " + (index + 1) + (startFrame == 0 && endFrame == Integer.MAX_VALUE ? ", all frames": ", frame " + startFrame + " to " + endFrame));
|
||||||
@@ -4237,7 +4270,7 @@ public class XFLConverter {
|
|||||||
layerPrev.writeCharacters(""); // todo honfika: hack to close start tag
|
layerPrev.writeCharacters(""); // todo honfika: hack to close start tag
|
||||||
String layerAfter = "</DOMLayer>";
|
String layerAfter = "</DOMLayer>";
|
||||||
int prevLength = writer.length();
|
int prevLength = writer.length();
|
||||||
convertFrames(swf, onlyFrames, startFrame, endFrame, layerPrev.toString(), layerAfter, nonLibraryShapes, tags, timelineTags, characters, d, flaVersion, files, writer, multiUsageMorphShapes, statusStack);
|
convertFrames(scene, swf, onlyFrames, startFrame, endFrame, layerPrev.toString(), layerAfter, nonLibraryShapes, tags, timelineTags, characters, d, flaVersion, files, writer, multiUsageMorphShapes, statusStack);
|
||||||
statusStack.popStatus();
|
statusStack.popStatus();
|
||||||
return writer.length() != prevLength;
|
return writer.length() != prevLength;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ import com.jpexs.decompiler.flash.tags.text.TextParseException;
|
|||||||
import com.jpexs.decompiler.flash.timeline.AS3Package;
|
import com.jpexs.decompiler.flash.timeline.AS3Package;
|
||||||
import com.jpexs.decompiler.flash.timeline.DepthState;
|
import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.timeline.TagScript;
|
import com.jpexs.decompiler.flash.timeline.TagScript;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||||
@@ -2038,7 +2039,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
List<Tag> sprites = new ArrayList<>();
|
List<Tag> sprites = new ArrayList<>();
|
||||||
List<Tag> buttons = new ArrayList<>();
|
List<Tag> buttons = new ArrayList<>();
|
||||||
List<Tag> movies = new ArrayList<>();
|
List<Tag> movies = new ArrayList<>();
|
||||||
List<Tag> sounds = new ArrayList<>();
|
List<SoundTag> sounds = new ArrayList<>();
|
||||||
List<Tag> texts = new ArrayList<>();
|
List<Tag> texts = new ArrayList<>();
|
||||||
List<TreeItem> as12scripts = new ArrayList<>();
|
List<TreeItem> as12scripts = new ArrayList<>();
|
||||||
List<BinaryDataInterface> binaryData = new ArrayList<>();
|
List<BinaryDataInterface> binaryData = new ArrayList<>();
|
||||||
@@ -2060,8 +2061,15 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
as12scripts.add(d);
|
as12scripts.add(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d instanceof SoundStreamHeadTypeTag) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (d instanceof Tag || d instanceof ASMSource || d instanceof BinaryDataInterface) {
|
if (d instanceof Tag
|
||||||
|
|| d instanceof ASMSource
|
||||||
|
|| d instanceof BinaryDataInterface
|
||||||
|
|| d instanceof SoundStreamFrameRange) {
|
||||||
TreeNodeType nodeType = TagTree.getTreeNodeType(d);
|
TreeNodeType nodeType = TagTree.getTreeNodeType(d);
|
||||||
if (nodeType == TreeNodeType.IMAGE) {
|
if (nodeType == TreeNodeType.IMAGE) {
|
||||||
images.add((Tag) d);
|
images.add((Tag) d);
|
||||||
@@ -2090,7 +2098,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
movies.add((Tag) d);
|
movies.add((Tag) d);
|
||||||
}
|
}
|
||||||
if (nodeType == TreeNodeType.SOUND) {
|
if (nodeType == TreeNodeType.SOUND) {
|
||||||
sounds.add((Tag) d);
|
sounds.add((SoundTag) d);
|
||||||
}
|
}
|
||||||
if (nodeType == TreeNodeType.BINARY_DATA) {
|
if (nodeType == TreeNodeType.BINARY_DATA) {
|
||||||
binaryData.add((BinaryDataInterface) d);
|
binaryData.add((BinaryDataInterface) d);
|
||||||
@@ -2183,7 +2191,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (export.isOptionEnabled(SoundExportMode.class)) {
|
if (export.isOptionEnabled(SoundExportMode.class)) {
|
||||||
ret.addAll(new SoundExporter().exportSounds(handler, selFile2 + File.separator + SoundExportSettings.EXPORT_FOLDER_NAME, new ReadOnlyTagList(sounds),
|
ret.addAll(new SoundExporter().exportSounds(handler, selFile2 + File.separator + SoundExportSettings.EXPORT_FOLDER_NAME, sounds,
|
||||||
new SoundExportSettings(export.getValue(SoundExportMode.class)), evl));
|
new SoundExportSettings(export.getValue(SoundExportMode.class)), evl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5554,15 +5562,17 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
|
|||||||
previewPanel.showImagePanel(timelinedContainer, swf, frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false);
|
previewPanel.showImagePanel(timelinedContainer, swf, frame, true, Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false);
|
||||||
} else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) {
|
} else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) {
|
||||||
previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32")));
|
previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32")));
|
||||||
previewPanel.setImageReplaceButtonVisible(false, false, false, !((Tag) treeItem).isReadOnly() && ((SoundTag) treeItem).importSupported(), false, false, false);
|
previewPanel.setImageReplaceButtonVisible(false, false, false, !((SoundTag) treeItem).isReadOnly() && ((SoundTag) treeItem).importSupported(), false, false, false);
|
||||||
try {
|
if (!(treeItem instanceof SoundStreamHeadTypeTag)) {
|
||||||
SoundTagPlayer soundThread = new SoundTagPlayer(null, (SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true);
|
try {
|
||||||
if (!Configuration.autoPlaySounds.get()) {
|
SoundTagPlayer soundThread = new SoundTagPlayer(null, (SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true);
|
||||||
soundThread.pause();
|
if (!Configuration.autoPlaySounds.get()) {
|
||||||
|
soundThread.pause();
|
||||||
|
}
|
||||||
|
previewPanel.setMedia(soundThread);
|
||||||
|
} catch (LineUnavailableException | IOException | UnsupportedAudioFileException ex) {
|
||||||
|
logger.log(Level.SEVERE, null, ex);
|
||||||
}
|
}
|
||||||
previewPanel.setMedia(soundThread);
|
|
||||||
} catch (LineUnavailableException | IOException | UnsupportedAudioFileException ex) {
|
|
||||||
logger.log(Level.SEVERE, null, ex);
|
|
||||||
}
|
}
|
||||||
} else if ((treeItem instanceof FontTag) && internalViewer) {
|
} else if ((treeItem instanceof FontTag) && internalViewer) {
|
||||||
previewPanel.showFontPanel((FontTag) treeItem);
|
previewPanel.showFontPanel((FontTag) treeItem);
|
||||||
|
|||||||
@@ -1529,6 +1529,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
|
|||||||
|
|
||||||
public void showImagePanel(SerializableImage image) {
|
public void showImagePanel(SerializableImage image) {
|
||||||
showCardLeft(DRAW_PREVIEW_CARD);
|
showCardLeft(DRAW_PREVIEW_CARD);
|
||||||
|
imageTransformButton.setVisible(false);
|
||||||
parametersPanel.setVisible(false);
|
parametersPanel.setVisible(false);
|
||||||
imagePlayControls.setMedia(imagePanel);
|
imagePlayControls.setMedia(imagePanel);
|
||||||
imagePanel.setImage(image);
|
imagePanel.setImage(image);
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ public class SoundTagPlayer implements MediaDisplay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void openSound(SOUNDINFO soundInfo, SoundTag tag) throws IOException, LineUnavailableException, UnsupportedAudioFileException {
|
private void openSound(SOUNDINFO soundInfo, SoundTag tag) throws IOException, LineUnavailableException, UnsupportedAudioFileException {
|
||||||
SWF swf = ((Tag) tag).getSwf();
|
SWF swf = (SWF) tag.getOpenable();
|
||||||
wavData = swf.getFromCache(soundInfo, tag);
|
wavData = swf.getFromCache(soundInfo, tag);
|
||||||
if (wavData == null) {
|
if (wavData == null) {
|
||||||
List<ByteArrayRange> soundData = tag.getRawSoundData();
|
List<ByteArrayRange> soundData = tag.getRawSoundData();
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
|
|||||||
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
|
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
|
||||||
import com.jpexs.decompiler.flash.tags.base.RemoveTag;
|
import com.jpexs.decompiler.flash.tags.base.RemoveTag;
|
||||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||||
|
import com.jpexs.decompiler.flash.tags.base.SoundStreamHeadTypeTag;
|
||||||
import com.jpexs.decompiler.flash.tags.base.SymbolClassTypeTag;
|
import com.jpexs.decompiler.flash.tags.base.SymbolClassTypeTag;
|
||||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||||
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
|
import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont;
|
||||||
@@ -89,6 +90,7 @@ import com.jpexs.decompiler.flash.timeline.AS2Package;
|
|||||||
import com.jpexs.decompiler.flash.timeline.AS3Package;
|
import com.jpexs.decompiler.flash.timeline.AS3Package;
|
||||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||||
import com.jpexs.decompiler.flash.timeline.FrameScript;
|
import com.jpexs.decompiler.flash.timeline.FrameScript;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.timeline.TagScript;
|
import com.jpexs.decompiler.flash.timeline.TagScript;
|
||||||
import com.jpexs.decompiler.flash.treeitems.FolderItem;
|
import com.jpexs.decompiler.flash.treeitems.FolderItem;
|
||||||
import com.jpexs.decompiler.flash.treeitems.HeaderItem;
|
import com.jpexs.decompiler.flash.treeitems.HeaderItem;
|
||||||
@@ -174,6 +176,11 @@ public abstract class AbstractTagTree extends JTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Icon getIconFor(TreeItem val, boolean folderExpanded) {
|
public static Icon getIconFor(TreeItem val, boolean folderExpanded) {
|
||||||
|
|
||||||
|
if (val instanceof SoundStreamHeadTypeTag) {
|
||||||
|
return View.getIcon("foldersounds16");
|
||||||
|
}
|
||||||
|
|
||||||
TreeNodeType type = getTreeNodeType(val);
|
TreeNodeType type = getTreeNodeType(val);
|
||||||
|
|
||||||
if (type == TreeNodeType.FOLDER && folderExpanded) {
|
if (type == TreeNodeType.FOLDER && folderExpanded) {
|
||||||
@@ -289,7 +296,8 @@ public abstract class AbstractTagTree extends JTree {
|
|||||||
|| (t instanceof SoundStreamHeadTag)
|
|| (t instanceof SoundStreamHeadTag)
|
||||||
|| (t instanceof SoundStreamHead2Tag)
|
|| (t instanceof SoundStreamHead2Tag)
|
||||||
|| (t instanceof DefineExternalSound)
|
|| (t instanceof DefineExternalSound)
|
||||||
|| (t instanceof DefineExternalStreamSound)) {
|
|| (t instanceof DefineExternalStreamSound)
|
||||||
|
|| (t instanceof SoundStreamFrameRange)) {
|
||||||
return TreeNodeType.SOUND;
|
return TreeNodeType.SOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,7 +603,11 @@ public abstract class AbstractTagTree extends JTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d instanceof Tag || d instanceof ASMSource || d instanceof BinaryDataInterface) {
|
if (d instanceof Tag
|
||||||
|
|| d instanceof ASMSource
|
||||||
|
|| d instanceof BinaryDataInterface
|
||||||
|
|| d instanceof SoundStreamFrameRange
|
||||||
|
) {
|
||||||
TreeNodeType nodeType = TagTree.getTreeNodeType(d);
|
TreeNodeType nodeType = TagTree.getTreeNodeType(d);
|
||||||
if (nodeType == TreeNodeType.IMAGE) {
|
if (nodeType == TreeNodeType.IMAGE) {
|
||||||
ret.add(d);
|
ret.add(d);
|
||||||
|
|||||||
@@ -1180,7 +1180,7 @@ public class TagTreeContextMenu extends JPopupMenu {
|
|||||||
replaceMenuItem.setVisible(true);
|
replaceMenuItem.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canReplace.test(it -> it instanceof SoundTag)) {
|
if (canReplace.test(it -> it instanceof SoundTag && ((SoundTag) it).importSupported())) {
|
||||||
replaceMenuItem.setVisible(true);
|
replaceMenuItem.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import com.jpexs.decompiler.flash.timeline.AS2Package;
|
|||||||
import com.jpexs.decompiler.flash.timeline.AS3Package;
|
import com.jpexs.decompiler.flash.timeline.AS3Package;
|
||||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||||
import com.jpexs.decompiler.flash.timeline.FrameScript;
|
import com.jpexs.decompiler.flash.timeline.FrameScript;
|
||||||
|
import com.jpexs.decompiler.flash.timeline.SoundStreamFrameRange;
|
||||||
import com.jpexs.decompiler.flash.timeline.TagScript;
|
import com.jpexs.decompiler.flash.timeline.TagScript;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||||
@@ -264,8 +265,8 @@ public class TagTreeModel extends AbstractTagTreeModel {
|
|||||||
for (int i = sounds.size() - 1; i >= 0; i--) {
|
for (int i = sounds.size() - 1; i >= 0; i--) {
|
||||||
TreeItem sound = sounds.get(i);
|
TreeItem sound = sounds.get(i);
|
||||||
if (sound instanceof SoundStreamHeadTypeTag) {
|
if (sound instanceof SoundStreamHeadTypeTag) {
|
||||||
List<SoundStreamBlockTag> blocks = ((SoundStreamHeadTypeTag) sound).getBlocks();
|
List<SoundStreamFrameRange> ranges = ((SoundStreamHeadTypeTag) sound).getRanges();
|
||||||
if (blocks == null || blocks.isEmpty()) {
|
if (ranges == null || ranges.isEmpty()) {
|
||||||
sounds.remove(i);
|
sounds.remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -580,6 +581,9 @@ public class TagTreeModel extends AbstractTagTreeModel {
|
|||||||
} else if (parentNode instanceof ABC) {
|
} else if (parentNode instanceof ABC) {
|
||||||
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
|
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
|
||||||
return classesTreeModel.getAllChildren(classesTreeModel.getRoot());
|
return classesTreeModel.getAllChildren(classesTreeModel.getRoot());
|
||||||
|
} else if (parentNode instanceof SoundStreamHeadTypeTag) {
|
||||||
|
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) parentNode;
|
||||||
|
return head.getRanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -662,7 +666,10 @@ public class TagTreeModel extends AbstractTagTreeModel {
|
|||||||
} else if (parentNode instanceof ABC) {
|
} else if (parentNode instanceof ABC) {
|
||||||
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
|
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
|
||||||
return classesTreeModel.getChild(classesTreeModel.getRoot(), index);
|
return classesTreeModel.getChild(classesTreeModel.getRoot(), index);
|
||||||
}
|
} else if (parentNode instanceof SoundStreamHeadTypeTag) {
|
||||||
|
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) parentNode;
|
||||||
|
return head.getRanges().get(index);
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error("Unsupported parent type: " + parentNode.getClass().getName());
|
throw new Error("Unsupported parent type: " + parentNode.getClass().getName());
|
||||||
}
|
}
|
||||||
@@ -713,6 +720,9 @@ public class TagTreeModel extends AbstractTagTreeModel {
|
|||||||
} else if (parentNode instanceof ABC) {
|
} else if (parentNode instanceof ABC) {
|
||||||
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
|
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
|
||||||
return classesTreeModel.getChildCount(classesTreeModel.getRoot());
|
return classesTreeModel.getChildCount(classesTreeModel.getRoot());
|
||||||
|
} else if (parentNode instanceof SoundStreamHeadTypeTag) {
|
||||||
|
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) parentNode;
|
||||||
|
return head.getRanges().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -787,6 +797,9 @@ public class TagTreeModel extends AbstractTagTreeModel {
|
|||||||
} else if (parentNode instanceof ABC) {
|
} else if (parentNode instanceof ABC) {
|
||||||
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
|
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
|
||||||
return indexOfAdd(baseIndex, classesTreeModel.getIndexOfChild(classesTreeModel.getRoot(), childNode));
|
return indexOfAdd(baseIndex, classesTreeModel.getIndexOfChild(classesTreeModel.getRoot(), childNode));
|
||||||
|
} else if (parentNode instanceof SoundStreamHeadTypeTag) {
|
||||||
|
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) parentNode;
|
||||||
|
return indexOfAdd(baseIndex, head.getRanges().indexOf(childNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
Reference in New Issue
Block a user