mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Merge remote-tracking branch
'origin/GP-2858_dragonmacher_PR-4755_agatti_refactor-audio-playable' (Closes #4755)
This commit is contained in:
@@ -4,9 +4,7 @@
|
|||||||
icon.content.handler.archive.dt = closedBookBlue.png
|
icon.content.handler.archive.dt = closedBookBlue.png
|
||||||
icon.content.handler.program = program_obj.png
|
icon.content.handler.program = program_obj.png
|
||||||
|
|
||||||
icon.data.type.aiff = audio-volume-medium.png
|
icon.data.type.audio.player = audio-volume-medium.png
|
||||||
icon.data.type.au = audio-volume-medium.png
|
|
||||||
icon.data.type.wave = audio-volume-medium.png
|
|
||||||
|
|
||||||
[Dark Defaults]
|
[Dark Defaults]
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,14 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.program.model.data;
|
package ghidra.program.model.data;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.sound.sampled.*;
|
|
||||||
import javax.swing.Icon;
|
|
||||||
|
|
||||||
import generic.theme.GIcon;
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
@@ -104,36 +96,6 @@ public class AIFFDataType extends BuiltIn implements Dynamic {
|
|||||||
return "<AIFF-Representation>";
|
return "<AIFF-Representation>";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AIFFData implements Playable {
|
|
||||||
|
|
||||||
private static final Icon AUDIO_ICON = new GIcon("icon.data.type.aiff");
|
|
||||||
private byte[] bytes;
|
|
||||||
|
|
||||||
public AIFFData(byte[] bytes) {
|
|
||||||
this.bytes = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clicked(MouseEvent event) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Clip clip = AudioSystem.getClip();
|
|
||||||
AudioInputStream ais =
|
|
||||||
AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes));
|
|
||||||
clip.open(ais);
|
|
||||||
clip.start();
|
|
||||||
}
|
|
||||||
catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
|
|
||||||
Msg.debug(this, "Unable to play audio", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Icon getImageIcon() {
|
|
||||||
return AUDIO_ICON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||||
byte[] data = new byte[length];
|
byte[] data = new byte[length];
|
||||||
@@ -141,12 +103,12 @@ public class AIFFDataType extends BuiltIn implements Dynamic {
|
|||||||
Msg.error(this, "AIFF-Sound error: Not enough bytes in memory");
|
Msg.error(this, "AIFF-Sound error: Not enough bytes in memory");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new AIFFData(data);
|
return new AudioPlayer(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getValueClass(Settings settings) {
|
public Class<?> getValueClass(Settings settings) {
|
||||||
return AIFFData.class;
|
return AudioPlayer.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -15,14 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.program.model.data;
|
package ghidra.program.model.data;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.sound.sampled.*;
|
|
||||||
import javax.swing.Icon;
|
|
||||||
|
|
||||||
import generic.theme.GIcon;
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
@@ -56,7 +48,7 @@ public class AUDataType extends BuiltIn implements Dynamic {
|
|||||||
Msg.debug(this, "Invalid AU magic number");
|
Msg.debug(this, "Invalid AU magic number");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
//Ints always stored as big endian in this format but can be in any kind of program so must get the ints as big endian even when in a little endian program
|
//Ints always stored as big endian in this format but can be in any kind of program so must get the ints as big endian even when in a little endian program
|
||||||
int dataOffset = GhidraBigEndianDataConverter.INSTANCE.getInt(buf, 4);
|
int dataOffset = GhidraBigEndianDataConverter.INSTANCE.getInt(buf, 4);
|
||||||
|
|
||||||
int dataSize = GhidraBigEndianDataConverter.INSTANCE.getInt(buf, 8);
|
int dataSize = GhidraBigEndianDataConverter.INSTANCE.getInt(buf, 8);
|
||||||
@@ -108,36 +100,6 @@ public class AUDataType extends BuiltIn implements Dynamic {
|
|||||||
return "<AU-Representation>";
|
return "<AU-Representation>";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class AUData implements Playable {
|
|
||||||
|
|
||||||
private static final Icon AUDIO_ICON = new GIcon("icon.data.type.au");
|
|
||||||
private byte[] bytes;
|
|
||||||
|
|
||||||
public AUData(byte[] bytes) {
|
|
||||||
this.bytes = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clicked(MouseEvent event) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Clip clip = AudioSystem.getClip();
|
|
||||||
AudioInputStream ais =
|
|
||||||
AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes));
|
|
||||||
clip.open(ais);
|
|
||||||
clip.start();
|
|
||||||
}
|
|
||||||
catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
|
|
||||||
Msg.debug(this, "Unable to play audio", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Icon getImageIcon() {
|
|
||||||
return AUDIO_ICON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||||
byte[] data = new byte[length];
|
byte[] data = new byte[length];
|
||||||
@@ -145,12 +107,12 @@ public class AUDataType extends BuiltIn implements Dynamic {
|
|||||||
Msg.error(this, "AU-DataTpe Error: Not enough bytes in memory");
|
Msg.error(this, "AU-DataTpe Error: Not enough bytes in memory");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new AUData(data);
|
return new AudioPlayer(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getValueClass(Settings settings) {
|
public Class<?> getValueClass(Settings settings) {
|
||||||
return AUData.class;
|
return AudioPlayer.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.program.model.data;
|
||||||
|
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.sound.sampled.*;
|
||||||
|
import javax.sound.sampled.LineEvent.Type;
|
||||||
|
import javax.swing.Icon;
|
||||||
|
|
||||||
|
import generic.theme.GIcon;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
|
public class AudioPlayer implements Playable, LineListener {
|
||||||
|
|
||||||
|
private static final Icon AUDIO_ICON = new GIcon("icon.data.type.audio.player");
|
||||||
|
|
||||||
|
private byte[] bytes;
|
||||||
|
|
||||||
|
public AudioPlayer(byte[] bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Icon getImageIcon() {
|
||||||
|
return AUDIO_ICON;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clicked(MouseEvent event) {
|
||||||
|
try (AudioInputStream stream =
|
||||||
|
AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes))) {
|
||||||
|
Clip clip = AudioSystem.getClip();
|
||||||
|
clip.addLineListener(this);
|
||||||
|
clip.open(stream);
|
||||||
|
clip.start();
|
||||||
|
}
|
||||||
|
catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
|
||||||
|
Msg.debug(this, "Unable to play audio", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(LineEvent event) {
|
||||||
|
LineEvent.Type eventType = event.getType();
|
||||||
|
|
||||||
|
if (eventType != Type.STOP && eventType != Type.CLOSE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.getSource() instanceof Clip clip) {
|
||||||
|
clip.removeLineListener(this);
|
||||||
|
clip.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
@@ -15,14 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.program.model.data;
|
package ghidra.program.model.data;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.sound.sampled.*;
|
|
||||||
import javax.swing.Icon;
|
|
||||||
|
|
||||||
import generic.theme.GIcon;
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.program.model.mem.MemoryAccessException;
|
import ghidra.program.model.mem.MemoryAccessException;
|
||||||
@@ -101,36 +93,6 @@ public class WAVEDataType extends BuiltIn implements Dynamic {
|
|||||||
return "<WAVE-Resource>";
|
return "<WAVE-Resource>";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class WAVEData implements Playable {
|
|
||||||
|
|
||||||
private static final Icon AUDIO_ICON = new GIcon("icon.data.type.wave");
|
|
||||||
private byte[] bytes;
|
|
||||||
|
|
||||||
public WAVEData(byte[] bytes) {
|
|
||||||
this.bytes = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clicked(MouseEvent event) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Clip clip = AudioSystem.getClip();
|
|
||||||
AudioInputStream ais =
|
|
||||||
AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes));
|
|
||||||
clip.open(ais);
|
|
||||||
clip.start();
|
|
||||||
}
|
|
||||||
catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
|
|
||||||
Msg.debug(this, "Unable to play audio", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Icon getImageIcon() {
|
|
||||||
return AUDIO_ICON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||||
byte[] data = new byte[length];
|
byte[] data = new byte[length];
|
||||||
@@ -138,13 +100,12 @@ public class WAVEDataType extends BuiltIn implements Dynamic {
|
|||||||
Msg.error(this, "WAVE-Sound error: " + "Not enough bytes!");
|
Msg.error(this, "WAVE-Sound error: " + "Not enough bytes!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
WAVEData waveData = new WAVEData(data);
|
return new AudioPlayer(data);
|
||||||
return waveData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<?> getValueClass(Settings settings) {
|
public Class<?> getValueClass(Settings settings) {
|
||||||
return WAVEData.class;
|
return AudioPlayer.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user