I made a simple programm to let java play some .mp3 files.
Using JLayer to get this right.
The problem is that i can't interrupt my player after pushing a button.
my code in actionperformed:
class MyThread extends Thread {
#Override
public void run() {
try {
File file = new File(source);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
try {
Thread.sleep(1);
try {
Player player = new Player(bis);
player.play();
} catch (JavaLayerException ex) {
}
} catch (InterruptedException e) {
System.out.println("Came");
}
} catch (IOException e) {
lab2.setText("error, is the pathway correct?");
}
}
}
MyThread mythread = new MyThread();
if (event.getSource() == input) {
source = input.getText();
source = source.replace("\\", "\\\\");
lab1.setText(source);
}
if (event.getSource() == but1) {
mythread.start();
}
if (event.getSource() == but2) {
but2.setLabel("stop");
mythread.interrupt();
but2.setLabel("stopped");
}
}
}
When I add the mythread.interrupt(); directly behind the interrupt works and my system gives me the "came" output.
But if I use my button called input, it wont work.
Seems that player class doesnt have a stop method, but you can try with AdvancedPlayer:
http://www.javazoom.net/javalayer/docs/docs1.0/javazoom/jl/player/advanced/AdvancedPlayer.html
and the stop() method.
Related
I have a JFrame with 2 buttons: Turn On and Turn Off
My problem is when a song has ended, I can't check that it ended and to play it again
How can I check it? Thank you so much
Below is the way that I play sound on Swing
class MP3 {
private Player player;
private String filename;
public MP3(String filename) {
this.filename = filename;
}
public void stop() {
if (player != null)
player.close();
}
public void play() {
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename));
player = new Player(bis);
} catch (FileNotFoundException | JavaLayerException ex) {
System.out.println(ex);
}
new Thread(new Runnable() {
#Override
public void run() {
try {
player.play();
} catch (Exception ex) {
System.out.println(ex);
}
}
}).start();
}
}
And Event when I click buttons
private void btnPlayActionPerformed(java.awt.event.ActionEvent evt) {
sound = new MP3("src/Sound/02 - Cold Pizza.mp3");
sound.play();
btnPlay.setVisible(false);
btnStop.setVisible(true);
}
private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {
sound.stop();
btnStop.setVisible(false);
btnPlay.setVisible(true);
}
sound is a instance of MP3 class in main class
I did it this way. I made the mp3 file a wav file. Then I made two objects
AudioInputStream songReader;
Clip song;
try{
songReader =
AudioSystem.getAudioInputStream(
getClass().getResource("wally.wav"));
song = AudioSystem.getClip();
song.open(songReader);
}catch (Exception e){
System.out.println("won't work");
}
try{
song.stop();
song.setFramePosition(0);
}catch(Exception e){
System.out.println("Error playing your music");
}
try{
song.start();
song.loop(song.LOOP_CONTINUOUSLY);
}catch(Exception e){
System.out.println("Won't work");
}
This makes it play infinitely, but if you need you can stop it at any point with song.stop(). Hopefully, that will work for you.
Good evening, please someone could tell me how the audio files are executed in a .jar
I have tried to call them using getClass (). GetResource () but I can not use it since an error appears.
This is my implementation for playing sounds:
public class Sonido extends Thread {
private Clip sonido;
private boolean seguir;
public Sonido(String rutaArchivo){
try {
sonido = AudioSystem.getClip();
sonido.open(AudioSystem.getAudioInputStream(new File(rutaArchivo)));
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException ex) {
Logger.getLogger(PanelBotones.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
#SuppressWarnings("SleepWhileInLoop")
public void run() {
seguir = true;
do {
sonido.loop(0);
try {
Thread.sleep(1000);
} catch (InterruptedException interruptedException) {
Logger.getLogger(PanelBotones.class.getName()).log(Level.SEVERE, null,
interruptedException);
}
} while (seguir == true && sonido.isActive());
// Se cierra el clip.
sonido.close();
}
public void parar() {
seguir = false;
}
}
And this is the event method where you created the new clip
#Override
public void actionPerformed(ActionEvent e) {
String cadena = e.getActionCommand();
if (cadena.equalsIgnoreCase(ROJO)) {
interfazPrincipal.imagenUno();
sonido = new Sonido("./recursos/sonido/rojo.wav");
Thread cancionFondo;
cancionFondo = new Thread(sonido);
cancionFondo.start();
}
I would be appreciated for your help, thank you.
Try this instead:
sonido.open(AudioSystem.getAudioInputStream(Sonido.class.getClassLoader().getResource(rutaArchivo)));
sonido = new Sonido("my/package/rojo.wav");
I am having trouble stopping one thread and starting another one. I have created two threads. One of them is first run from the main method. It then takes user input and if the desired input is provided, thread one (sound) is supposed to stop and start thread two (sound2). From the code below, thread two does start playing after the correct input is provided during thread one. But thread one does not stop. I can hear audio files from both thread one and thread two playing. Please help.
public class crytask {
public static void main(String args[]) throws InterruptedException {
Runnable sound = new sound();
final Thread soundthread = new Thread(sound);
soundthread.start();
int count = 0;
System.out.println("Enter");
Scanner reader = new Scanner(System.in);
int a = reader.nextInt();
if (a==12)
soundthread.interrupt();
System.out.println("this thread is cancelled");
Runnable sound2 = new sound2();
final Thread soundthread2 = new Thread(sound2);
soundthread2.start();
int count2 = 0;
System.out.println("Enter");
Scanner reader2 = new Scanner(System.in);
int b = reader2.nextInt();
if (b==12)
soundthread2.interrupt();
}}
class sound implements Runnable {
#Override
public void run() {
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("/Users/babe/Desktop/Con1.wav").getAbsoluteFile());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
Thread.sleep(clip.getMicrosecondLength() / 1000);
} catch(InterruptedException ex) {
System.out.println("Cancelled 1!");
} catch (Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}
}
class sound2 implements Runnable {
#Override
public void run() {
try {
AudioInputStream audioInputStream2 = AudioSystem.getAudioInputStream(new File("/Users/babe/Desktop/Con1.wav").getAbsoluteFile());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream2);
clip.start();
Thread.sleep(clip.getMicrosecondLength() / 1000);
} catch(InterruptedException ex) {
System.out.println("Cancelled 2!");
} catch (Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}
}
Try stopping the clip when the thread is interrupted, adding clip.close() to the catch clause that catches the interruptedException, like this:
class sound implements Runnable {
#Override
public void run() {
Clip clip = null; // take the declaration of the clip variable out of the try - catch
try {
AudioInputStream audioInputStream =
AudioSystem.getAudioInputStream(new File("/Users/babe/Desktop/Con1.wav").getAbsoluteFile());
clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
Thread.sleep(clip.getMicrosecondLength() / 1000);
} catch(InterruptedException ex) {
clip.stop(); // <--- ADD THIS LINE
System.out.println("Cancelled 1!");
} catch (Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}
}
I have to change the icon of a label every 2 seconds. I have 3 pictures in src folder. To change them i use a thread. The code i wrote:
private Thread t;
private int indexIcon;
public ImageIcon[] icons = {new ImageIcon(this.getClass().getResource("orange.jpg")),
new
ImageIcon(this.getClass().getResource("cosmote.jpg")), new
ImageIcon(this.getClass().getResource("vodafone.jpg"))};
public void run() {
while (true) {
try {
Thread.sleep(2000);
if (Thread.interrupted()) {
return;
}
indexIcon++;
if (indexIcon > 2) {
indexIcon = 0;
}
jLabel8.setIcon(icons[indexIcon]);
} catch (InterruptedException ex) {
Logger.getLogger(CarteDeTelefonGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
And in the class constructor:
t = new Thread(this);
t.start();
It works fine, but the problem is that when i run the program on a different computer it doesn't read the images, i get a nullpointer exception.
How could i solve this problem?
I have a class Automator that can automate a user. I am specifically having problems setting the system clipboard in windows. The Automator class makes use of the ClipSetThread class, which is a thread that sets the system clipboard. A instance of ClipSetThread takes as input a thread, that if null, it joins with (waits for it to complete).
I feel that I am not calling ClipSetThread right because I still have the errors I have had before in its reliability; prior to the ClipSetThread. This code does not throw any errors when it runs, it works about 2/3 of the time though. Other times it will print 1134, _234, or etc. It seems that the threads are not joining (waiting for) each other, or get skipped.
Code:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;
public class Automator extends Thread implements NativeMouseInputListener
{
Robot rob = null;
TheAppClass theApp = null;
ClipSetThread lastClipSet = null;
boolean doit = false;
boolean settingClip = false;
public void run()
{
try // to make the Global hook
{
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex){theApp.updateOutput("No Global Keyboard or Mouse Hook");return;}
try // to create a robot (can simulate user input such as mouse and keyboard input)
{
rob = new Robot();
}
catch (AWTException e1) {theApp.updateOutput("The Robot could not be created");return;}
while(true) {}
}
public void setApp(TheAppClass app)
{
theApp = app;
theApp.updateOutput("Succesfully started automator");
}
public void setClip(String arg)
{
ClipSetThread set = new ClipSetThread(theApp, lastClipSet);
lastClipSet = set;
set.setClip(arg);
}
public void DOit()
{
theApp.updateOutput("Starting");
pasteAtCursorLocation("1");
tab(1);
pasteAtCursorLocation("2");
tab(1);
pasteAtCursorLocation("3");
tab(1);
pasteAtCursorLocation("4");
tab(1);
theApp.updateOutput("Complete");
}
public void nativeMouseReleased(NativeMouseEvent e)
{
//System.out.println("Mouse Released: " + e.getButton());
if(doit)
{
DOit();
doit = false;
}
}
public void pasteAtCursorLocation(String text)
{
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
}
public void tab(int numTimes)
{
while(numTimes > 0)
{
rob.keyPress(KeyEvent.VK_TAB);
rob.keyRelease(KeyEvent.VK_TAB);
numTimes--;
theApp.updateOutput("Simulated Tab");
}
}
// Unimplemented
public void nativeMouseClicked(NativeMouseEvent arg0) {}
public void nativeMousePressed(NativeMouseEvent arg0) {}
public void nativeMouseDragged(NativeMouseEvent arg0) {}
public void nativeMouseMoved(NativeMouseEvent arg0) {}
}
ClipSetThread:
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
public class ClipSetThread extends Thread
{
Clipboard sysClip = null;
TheAppClass theApp = null;
public ClipSetThread(TheAppClass app, Thread waitFor)
{
theApp = app;
sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
if(waitFor != null)
{try {waitFor.join();}catch (InterruptedException e) {}}
}
public void setClip(String arg)
{
// Two strings that will hopefully never be on the clipboard
String checkStr1 = "9999999999999";
String checkStr2 = "99999999999999";
// When we read in the clipboard we want to see if we change these strings from the ones they
// will never be, if they do change we read the clipboard successfully
String clipBoardTextBefore = checkStr1;
String clipBoardTextAfter = checkStr2;
// First get a copy of the current system clipboard text
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// If we failed to change the string it means we failed to read the text
if(clipBoardTextBefore.equals(checkStr1))
theApp.updateOutput("Could NOT get sysClip text");
else
{
// If we didn't failed to get the current text try to change it
while(true)
{
try{sysClip.setContents(new StringSelection(arg), null);}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// Now again check to see the clipboard text
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextAfter = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// If we failed to read the clipboard text
if(clipBoardTextAfter.equals(checkStr2))
theApp.updateOutput("Could NOT check if sysClip update was successful");
else
{ // We re-read the clipboard text, see if it changed from the original clipboard text
if(clipBoardTextAfter.equals(checkStr1))
theApp.updateOutput("Could NOT successfully set clipboard text");
else
theApp.updateOutput("Set Clipboard Text:" + arg + "\n");
}
}
}
}
So, firstly, you never call start on the ClipSetThread. You should also check to see if the thread is still alive before joining it.
public class ClipSetThread extends Thread {
Clipboard sysClip = null;
TheAppClass theApp = null;
private String toClipboard;
public ClipSetThread(TheAppClass app, Thread waitFor, String toClipBoard) {
theApp = app;
sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
this.toClipboard = toClipBoard;
// !! Check to see if the thread is also alive before trying to join with it...
if (waitFor != null && waitFor.isAlive()) {
try {
waitFor.join();
} catch (InterruptedException e) {
}
}
}
// You should really put your logic into the `run` method in order to allow
// the code to actually run in a separate thread...otherwise there is no
// point in using a thread....
#Override
public void run() {
// Two strings that will hopefully never be on the clipboard
String checkStr1 = "9999999999999";
String checkStr2 = "99999999999999";
// When we read in the clipboard we want to see if we change these strings from the ones they
// will never be, if they do change we read the clipboard successfully
String clipBoardTextBefore = checkStr1;
String clipBoardTextAfter = checkStr2;
// First get a copy of the current system clipboard text
while (true) {
try {
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// If we failed to change the string it means we failed to read the text
if (clipBoardTextBefore.equals(checkStr1)) {
theApp.updateOutput("Could NOT get sysClip text");
} else {
// If we didn't failed to get the current text try to change it
while (true) {
try {
sysClip.setContents(new StringSelection(toClipboard), null);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// Now again check to see the clipboard text
while (true) {
try {
Transferable contents = sysClip.getContents(null);
clipBoardTextAfter = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// If we failed to read the clipboard text
if (clipBoardTextAfter.equals(checkStr2)) {
theApp.updateOutput("Could NOT check if sysClip update was successful");
} else { // We re-read the clipboard text, see if it changed from the original clipboard text
if (clipBoardTextAfter.equals(checkStr1)) {
theApp.updateOutput("Could NOT successfully set clipboard text");
} else {
theApp.updateOutput("Set Clipboard Text:" + toClipboard + "\n");
}
}
}
}
}
As per our previous converstaion, it's dangerous to use while (true) {}, it's also wasteful, as it will consume CPU cycles unnecessarily...
public class Automator extends Thread implements NativeMouseInputListener {
// A "locking" object...
private static final Object WAIT_LOCK = new Object();
Robot rob = null;
TheAppClass theApp = null;
ClipSetThread lastClipSet = null;
boolean doit = false;
boolean settingClip = false;
public void run() {
try // to make the Global hook
{
GlobalScreen.registerNativeHook();
} catch (NativeHookException ex) {
theApp.updateOutput("No Global Keyboard or Mouse Hook");
return;
}
try // to create a robot (can simulate user input such as mouse and keyboard input)
{
rob = new Robot();
} catch (AWTException e1) {
theApp.updateOutput("The Robot could not be created");
return;
}
// This is wasteful...
// while (true) {
// }
// Locks do not consume CPU cycles while in the wait state...
synchronized (WAIT_LOCK) {
try {
WAIT_LOCK.wait();
} catch (Exception exp) {
}
}
}
public void dispose() {
// Tell the thread it can terminate...
synchronized (WAIT_LOCK) {
WAIT_LOCK.notify();
}
// This will STOP the current thread (which called this method)
// while the lastClipSet finishes...
if (lastClipSet != null && lastClipSet.isAlive()) {
lastClipSet.join();
}
}
public void setClip(String arg) {
ClipSetThread set = new ClipSetThread(theApp, lastClipSet, arg);
lastClipSet = set;
// You MUST START the thread...
set.start();
}
/*...*/
}
Updated
This code could produce a infinite loop. What happens if the clipboard does not contain a String value??
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
You tend to do this a lot. I might suggest that you provide some kind of "escape" mechanism to allow it to fail after a number of retries...
boolean successful = false;
int retries = 0;
while (!successful && retries < 20) {
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
successful = true;
}
catch(Exception e)
{
retries++;
try {Thread.sleep(20);} catch (InterruptedException e1) {}
}
}
Updated with working example
Okay, that was fun. I've put together a (simple) working example. You will want to open a text editor of some kind. When you run the program, you have 5 seconds to make it active ;)
The only basic change I've made is I set added a auto delay between events of 250 milliseconds (see rob.setAutoDelay(250).
Now, you could also place a delay between each key event as well, using Robot#delay, but that's up to you
public class Engine extends Thread {
private Robot rob = null;
private PasteThread lastClipSet = null;
public void setClip(String arg) {
if (lastClipSet != null && lastClipSet.isAlive()) {
try {
lastClipSet.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
PasteThread set = new PasteThread(arg);
lastClipSet = set;
lastClipSet.start();
}
public void pasteAtCursorLocation(String text) {
System.out.println("Paste " + text);
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
}
public Engine() throws AWTException {
rob = new Robot();
rob.setAutoDelay(250);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
}
pasteAtCursorLocation("This is a simple test, thanks for watching!");
}
public static void main(String[] args) {
try {
new Engine();
} catch (AWTException ex) {
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, null, ex);
}
}
public class PasteThread extends Thread {
private String toPaste;
public PasteThread(String value) {
toPaste = value;
}
#Override
public void run() {
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
System.out.println("Current clipboard contents = " + getClipboardContents(sysClip));
sysClip.setContents(new StringSelection(toPaste), null);
System.out.println("New clipboard contents = " + getClipboardContents(sysClip));
}
public String getClipboardContents(Clipboard clipboard) {
String value = null;
boolean successful = false;
int retries = 0;
while (!successful && retries < 20) {
Transferable contents = clipboard.getContents(null);
if (contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
value = (String) contents.getTransferData(DataFlavor.stringFlavor);
successful = true;
} catch (Exception exp) {
retries++;
exp.printStackTrace();
}
} else {
retries++;
}
}
System.out.println(successful + "/" + retries);
return value;
}
}
}
Could you please try to repeat the Paste action with a sleep 1 second in between
public void pasteAtCursorLocation(String text)
{
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
// put in a sleep 1 second here
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
}
It could be that pasting 2x is giving different results. The reason for this strange behavior could the way Windows manages the clipboard. If pasting 2x the clipboard is giving different result then you know that the root cause for this strange behavior is not to find in your code but how Java and Windows work together.