Added #2132 Show and export streamed sound (SoundStreamHead/SoundStreamBlock) in frame ranges

Fixed #1194 FLA Export - stream sound export
This commit is contained in:
Jindra Petřík
2023-12-30 18:06:08 +01:00
parent 35dda78ffe
commit bd82522f16
20 changed files with 652 additions and 307 deletions
@@ -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.DepthState;
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.Timeline;
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> buttons = new ArrayList<>();
List<Tag> movies = new ArrayList<>();
List<Tag> sounds = new ArrayList<>();
List<SoundTag> sounds = new ArrayList<>();
List<Tag> texts = new ArrayList<>();
List<TreeItem> as12scripts = new ArrayList<>();
List<BinaryDataInterface> binaryData = new ArrayList<>();
@@ -2060,8 +2061,15 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
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);
if (nodeType == TreeNodeType.IMAGE) {
images.add((Tag) d);
@@ -2090,7 +2098,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
movies.add((Tag) d);
}
if (nodeType == TreeNodeType.SOUND) {
sounds.add((Tag) d);
sounds.add((SoundTag) d);
}
if (nodeType == TreeNodeType.BINARY_DATA) {
binaryData.add((BinaryDataInterface) d);
@@ -2183,7 +2191,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
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));
}
@@ -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);
} else if ((treeItem instanceof SoundTag)) { //&& isInternalFlashViewerSelected() && (Arrays.asList("mp3", "wav").contains(((SoundTag) tagObj).getExportFormat())))) {
previewPanel.showImagePanel(new SerializableImage(View.loadImage("sound32")));
previewPanel.setImageReplaceButtonVisible(false, false, false, !((Tag) treeItem).isReadOnly() && ((SoundTag) treeItem).importSupported(), false, false, false);
try {
SoundTagPlayer soundThread = new SoundTagPlayer(null, (SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true);
if (!Configuration.autoPlaySounds.get()) {
soundThread.pause();
previewPanel.setImageReplaceButtonVisible(false, false, false, !((SoundTag) treeItem).isReadOnly() && ((SoundTag) treeItem).importSupported(), false, false, false);
if (!(treeItem instanceof SoundStreamHeadTypeTag)) {
try {
SoundTagPlayer soundThread = new SoundTagPlayer(null, (SoundTag) treeItem, Configuration.loopMedia.get() ? Integer.MAX_VALUE : 1, true);
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) {
previewPanel.showFontPanel((FontTag) treeItem);
@@ -1529,6 +1529,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel
public void showImagePanel(SerializableImage image) {
showCardLeft(DRAW_PREVIEW_CARD);
imageTransformButton.setVisible(false);
parametersPanel.setVisible(false);
imagePlayControls.setMedia(imagePanel);
imagePanel.setImage(image);
@@ -187,7 +187,7 @@ public class SoundTagPlayer implements MediaDisplay {
}
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);
if (wavData == null) {
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.RemoveTag;
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.TextTag;
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.Frame;
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.treeitems.FolderItem;
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) {
if (val instanceof SoundStreamHeadTypeTag) {
return View.getIcon("foldersounds16");
}
TreeNodeType type = getTreeNodeType(val);
if (type == TreeNodeType.FOLDER && folderExpanded) {
@@ -289,7 +296,8 @@ public abstract class AbstractTagTree extends JTree {
|| (t instanceof SoundStreamHeadTag)
|| (t instanceof SoundStreamHead2Tag)
|| (t instanceof DefineExternalSound)
|| (t instanceof DefineExternalStreamSound)) {
|| (t instanceof DefineExternalStreamSound)
|| (t instanceof SoundStreamFrameRange)) {
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);
if (nodeType == TreeNodeType.IMAGE) {
ret.add(d);
@@ -1180,7 +1180,7 @@ public class TagTreeContextMenu extends JPopupMenu {
replaceMenuItem.setVisible(true);
}
if (canReplace.test(it -> it instanceof SoundTag)) {
if (canReplace.test(it -> it instanceof SoundTag && ((SoundTag) it).importSupported())) {
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.Frame;
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.Timeline;
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--) {
TreeItem sound = sounds.get(i);
if (sound instanceof SoundStreamHeadTypeTag) {
List<SoundStreamBlockTag> blocks = ((SoundStreamHeadTypeTag) sound).getBlocks();
if (blocks == null || blocks.isEmpty()) {
List<SoundStreamFrameRange> ranges = ((SoundStreamHeadTypeTag) sound).getRanges();
if (ranges == null || ranges.isEmpty()) {
sounds.remove(i);
}
}
@@ -580,6 +581,9 @@ public class TagTreeModel extends AbstractTagTreeModel {
} else if (parentNode instanceof ABC) {
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
return classesTreeModel.getAllChildren(classesTreeModel.getRoot());
} else if (parentNode instanceof SoundStreamHeadTypeTag) {
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) parentNode;
return head.getRanges();
}
return result;
@@ -662,7 +666,10 @@ public class TagTreeModel extends AbstractTagTreeModel {
} else if (parentNode instanceof ABC) {
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
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());
}
@@ -713,6 +720,9 @@ public class TagTreeModel extends AbstractTagTreeModel {
} else if (parentNode instanceof ABC) {
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
return classesTreeModel.getChildCount(classesTreeModel.getRoot());
} else if (parentNode instanceof SoundStreamHeadTypeTag) {
SoundStreamHeadTypeTag head = (SoundStreamHeadTypeTag) parentNode;
return head.getRanges().size();
}
return 0;
@@ -787,6 +797,9 @@ public class TagTreeModel extends AbstractTagTreeModel {
} else if (parentNode instanceof ABC) {
ClassesListTreeModel classesTreeModel = getClassesListTreeModel((ABC) parentNode);
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;