Alright so I'm using Eclipse Oxygen here (I think that's important since it looks like this is an Eclipse-generated error). I've seen several other posts on this specific error, but none of them worked for me/weren't things I had already tried. So my goal is to have a while loop and have it get the db sound level every second and update a label.
Unfortunately, that didn't work like 5 times in a row. The first, the window didn't open, and I realized it was because the while loop was keeping the window from opening, so I put it into a thread. And then like 5 attempts to fix it later, I'm still getting a "Widget is disposed" error in my code. Here's the code for opening the window (that's the only code I've changed since I made the project):
public void open() throws InterruptedException, LineUnavailableException {
Display display = Display.getDefault();
shlAudioAdjuster = new Shell();
shlAudioAdjuster.setSize(450, 300);
shlAudioAdjuster.setText("Audio Adjuster");
Label lblCurrentDecibelLevel = new Label(shlAudioAdjuster, SWT.NONE);
lblCurrentDecibelLevel.setFont(SWTResourceManager.getFont("Muli", 14, SWT.NORMAL));
ProgressBar progressBar = new ProgressBar(shlAudioAdjuster, SWT.NONE);
progressBar.setSelection(30);
progressBar.setBounds(143, 168, 170, 17);
shlAudioAdjuster.open();
shlAudioAdjuster.layout();
while (!shlAudioAdjuster.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
AudioFormat audioFormat = getAudioFormat();
TargetDataLine targetDataLine;
try {
targetDataLine = (TargetDataLine) AudioSystem.getTargetDataLine(audioFormat);
targetDataLine.open();
targetDataLine.start();
byte [] buffer = new byte[2000];
while (true) {
int bytesRead = targetDataLine.read(buffer,0,buffer.length);
int max;
if (bytesRead >=0) {
max = (short) (buffer[0] + (buffer[1] << 8));
for (int p=2;p<bytesRead-1;p+=2) {
short thisValue = (short) (buffer[p] + (buffer[p+1] << 8));
if (thisValue>max) max=thisValue;
}
progressBar.setSelection((int)(20 * Math.log10(max)));
}
}
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
And the error confirms there is a problem with progressBar.setSelection((int)(20 * Math.log10(max)));. Here's the full error:
org.eclipse.swt.SWTException: Widget is disposed
at org.eclipse.swt.SWT.error(SWT.java:4533)
at org.eclipse.swt.SWT.error(SWT.java:4448)
at org.eclipse.swt.SWT.error(SWT.java:4419)
at org.eclipse.swt.widgets.Widget.error(Widget.java:482)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:354)
at org.eclipse.swt.widgets.ProgressBar.setSelection(ProgressBar.java:322)
at MainWindow.open(MainWindow.java:90)
at MainWindow.main(MainWindow.java:34)
P.S The last line of error saying 34 is the caller for that function, the first is the progress-bar-change line. Any ideas?
The Shell window is only displayed while the while (!shlAudioAdjuster.isDisposed()) loop is running. Once that loop has exited all the controls in the shell are disposed and cannot be used anymore. So you can't put your code after that while loop.
You will have to put the code playing the sound in a separate thread which you start when you open the shell. But you can't update the progress bar directly in a background thread, instead you need to use Display.asyncExec to run the progress bar update in the UI thread:
Display.getDefault().asyncExec(() -> progressBar.setSelection((int)(20 * Math.log10(max))));
You might also want to check if the progress bar has been disposed and stop the thread:
if (progressBar.isDisposed()) {
// TODO exit the thread
}
Related
I have struggled with playing aac encoded audio files with Java a while now.
We had a group project at the end of our first semester and wanted to have a background music and few soundeffects in there.
At the end we used WAV files, as we couldn't get the AAC's to play.
This weekend I gave it another try and searched along again, and have got a working code searched together from different sites, but nowhere was a complete working solution.
For a more comfortable usage in future projects I made me a small library for aac playback.
As it was hard to find the working solution, I wanted to share it with you, in the hope some one having the same problem in the future will have it a bit easier.
The following code is a snippet from the lib I wrote. You can have a look onto the whole lib on GitLab at
Java AAC-Player.
This lib/solution uses the aac decoder JAAD.
The player I wrote around the JAAD library is available as Maven artifact:
<dependency>
<groupId>com.gitlab.9lukas5</groupId>
<artifactId>jaad</artifactId>
<!--
check latest version on https://search.maven.org
or try the latest tag you find in git
-->
</dependency>
public static void play(File[] files)
{
// local vars
byte[] b; // array for the actual audio Data during the playback
AudioTrack track; // track we are playing atm
AudioFormat af; // the track's format
SourceDataLine line; // the line we'll use the get our audio to the speaker's
Decoder dec; // decoder to get the audio bytes
Frame frame; //
SampleBuffer buf; //
int currentTrack; // index of current track from playlist
MP4Container cont; // container to open the current track with
Movie movie; // and get the content from the container
try
{
// for-next loop to play each titel from the playlist once
for (currentTrack = 0; currentTrack < files.length; currentTrack++)
{
cont = new MP4Container(new RandomAccessFile(files[currentTrack], "r")); // open titel with random access
movie = cont.getMovie(); // get content from container,
List<Track> content = movie.getTracks();
if (content.isEmpty()) // check if container HAS content
throw new Exception ("insert error message here"); // if so,
track = (AudioTrack) movie.getTracks().get(0); // grab first track and set the audioformat
af = new AudioFormat(track.getSampleRate(), track.getSampleSize(), track.getChannelCount(), true, true);
line = AudioSystem.getSourceDataLine(af); // get a DataLine from the AudioSystem
line.open(); // open and
line.start(); // start it
dec = new Decoder(track.getDecoderSpecificInfo());
buf = new SampleBuffer();
while(track.hasMoreFrames()) // while we have frames left
{
frame = track.readNextFrame(); // read next frame,
dec.decodeFrame(frame.getData(), buf); // decode it and put into the buffer
b = buf.getData(); // write the frame data from the buffer to our byte-array
line.write(b, 0, b.length); // and from there write the byte array into our open AudioSystem DataLine
while (paused) // check if we should pause
{
Thread.sleep(500); // if yes, stay half a second
if (Thread.interrupted()) // check if we should stop possibly
{
line.close(); // if yes, close line and
return; // exit thread
}
}
if (Thread.interrupted()) // if not in pause, still check on each frame if we should
{ // stop. If so
line.close(); // close line and
return; // exit thread
}
}
line.close(); // after titel is over, close line
if (loop) // if we should loop current titel, set currentTrack -1,
currentTrack--; // as on bottom of for-next it get's +1 and so the same titel get's played again
else if (repeat && (currentTrack == files.length -1)) // else check if we are at the end of the playlist
currentTrack = -1; // and should repeat the whole list. If so, set currentTrack -1, so it get's 0 on for-next bottom
}
}
catch (LineUnavailableException | IOException | InterruptedException e)
{
e.printStackTrace();
}
}
I know this question is asked many times.But i didnt get what i want.
I need to automate quick3270 which is used to connect to mainframe using java.
First let me tell you what i want.
I need my code to open quick3270.exe then open my saved session:---this is done.
Now, I have to send commands to the quick3270.Here comes the problem, I dont know how to send command to that software.
Third is I am using robot class.So that i can input:TAB,ENTER,F3 etc. inputs.
So, the whole thing is I want to send commands to quick3270. I need interval also.Like send one command then delay of 1 second then other and so on.
public static void main(String[] args) throws IOException, AWTException {
String exeloc = "C:\\Program Files\\Quick3270\\Quick3270.exe ";
// my saved session
String directory = "C:\\Users\\c111128\\Desktop\\Project\\xyz.ecf";
ProcessBuilder builder = new ProcessBuilder(new String[] { exeloc, directory });
// Starting the process
Process p = builder.start();
// For handling keyboard events
Robot robot = new Robot();
try {
robot.delay(2000);
// Passing enter key to top screen
robot.keyPress(KeyEvent.VK_ENTER);
robot.delay(4000);
// Here I want to write the command
//Command like:"teleview" which is used in mainframe
robot.delay(1000);
}
catch (Exception e) {
System.out.println("Second:" + e);
e.printStackTrace();
}
}
did you manage the Problem?
Via VBA you can send commands to Quick3270 this way:
Set Session = .ActiveSession
Set Screen = Session.Screen
Screen.SendKeys ("<Enter>")
Result = Screen.WaitForKbdUnlock
Screen.SendKeys ("<PF12>")
Screen.SendKeys ("<Enter>")
Result = Screen.WaitForKbdUnlock
Screen.SendKeys ("<PF12>")
Result = Screen.WaitForKbdUnlock
Result = Screen.WaitForCursor(4, 15)
QuickPutstring "1", 10, 2
Private Function QuickPutstring(ByVal PutstringText As String, Row As Long, Col As Long)
Screen.MoveTo Row, Col
Screen.Putstring PutstringText
End Function
Hope that helps...
I am having trouble with creating a very small music player following the HeadFirstJava recipe. I followed the code in the book but it still has some bugs... When I first compiled it it gave me this error:
Dez 15, 2013 4:13:02 PM java.util.prefs.WindowsPreferences
WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
After googling the error I found out that I should create HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefs and also give full permision for JavaSoft on regedit. That did solve the problem but only partially. The code compliles, the sound is made by the computer but the program will not close util I hit CTRL + C. Here is the code:
import javax.sound.midi.*;//importam pachetul sound.mini
public class MiniMiniMusicApp {
public static void main (String [] args) {
MiniMiniMusicApp mini = new MiniMiniMusicApp();
mini.play();
} //inchidem main
public void play() {
try {
Sequencer player = MidiSystem.getSequencer();
player.open();
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack();
//ShortMessage first = new ShortMessage();
//first.setMessage(192, 1, 102, 0);
//MidiEvent noteOn1 = new MidiEvent(first, 1);
//track.add(noteOn1);
ShortMessage a = new ShortMessage();
a.setMessage(144, 1, 44, 100);
MidiEvent noteOn = new MidiEvent(a, 1);
track.add(noteOn);
ShortMessage b = new ShortMessage();
b.setMessage(128, 1, 44, 100);
MidiEvent noteOff = new MidiEvent(b, 16);
track.add(noteOff);
player.setSequence(seq);
player.start();
} catch (Exception ex) {
ex.printStackTrace();
}
} //inchidem play
}
I would like to mention that I am not using any GUI and that I am a total novice. Any help would be appreciated. Thank you.
The MIDI sequencer is a special thread that runs in the background. As long as it is active (or, in fact, any non-daemon thread is active), Java will not exit on its own.
Try adding this after the player.start(); line:
Thread.sleep(5000);
player.close();
Command Prompt doesn't support the multi-programming. So when you run the above program, the program is in the running state, after it's play() method and wait for the some event to occur(like another Framed based program in java).
you can write System.exit() after putting some delay(so that your voice would come). Currently you are killing the process from the DOS.
The docs [MidiDevice.open()] for player.open() says:
An application opening a device explicitly with this call has to close the device by calling close. This is necessary to release system resources and allow applications to exit cleanly.
So you may use a try-with-resource-statement (Java 7+) to close it safely and wait gracefully (at the end of your try-block) for your track to finish:
try (Sequencer player = MidiSystem.getSequencer()) {
...
while (player.isRunning()) {
Thread.sleep(100);
}
} catch (Exception ex) {
ex.printStackTrace();
}
Prior to Java 7 you would have called player.close(); in a finally-block attached to your try-catch-statement.
Note: The access warning for the root users Preferences could have been suppressed by:
PlatformLogger.getLogger("java.util.prefs")
.setLevel(PlatformLogger.Level.SEVERE);
To solve the first error, just run your compiler as administrator.
I have a program which can print screenshot in every 1 second, But during the screen capture, when the screen contains dark pictures then, the stored image contains huge amount of noise. Can anyone please tell me that how to reduce noise contents from these snapshot images.
Following code I am using for screen capture.
public class Beginning implements Runnable {
private Thread thread;
private static long counter = 0;
private final int FRAME_CAPTURE_RATE = 1000;
private Robot robot;
public Beginning() throws Exception {
robot = new Robot();
thread = new Thread(this);
thread.start();
}
public static void main(String[] args) throws Exception {
Beginning beginning = new Beginning();
}
public void run() {
for (;;) {
try {
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage bufferedImage = robot.createScreenCapture(screenRect);
ImageIO.write(bufferedImage, "png", new File("D:\\CapturedFrame\\toolImage" + counter + ".png"));
counter++;
thread.sleep(FRAME_CAPTURE_RATE);
} catch (Exception e) {
System.err.println("Something fishy is going on...");
}
}
}
}
Also tell me that how can I do this without playing the video in the screen, means I have to just give location of video and then my program will capture frames from it and the remove noise from it and then save it in specified location.
If you don't need to do this programatically VLC player has an option to create images of frames see:
http://www.isimonbrown.co.uk/vlc-export-frames
If you need to run from a program and don't want to have the videos play - I'd recommend using command line tool such as ffmpeg and calling it from java via Runtime exec i.e.
Runtime.getRuntime().exec("INSERT FFMPEG COMMAND HERE");
Some sample commands for ffmpeg can be found here:
http://trac.ffmpeg.org/wiki/Create%20a%20thumbnail%20image%20every%20X%20seconds%20of%20the%20video
e.g. 1 frame per second:
ffmpeg -i input.flv -f image2 -vf fps=fps=1 out%d.png
I am using Java function to download file from internet.
public void getLatestRelease()
{
try
{
// Function called
long startTime = System.currentTimeMillis();
// Open connection
System.out.println("Connecting...");
URL url = new URL(latestReleaseUrl);
url.openConnection();
// Download routine
InputStream reader = url.openStream();
FileOutputStream writer = new FileOutputStream("release.zip");
byte[] buffer = new byte[153600];
int totalBytesRead = 0;
int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) > 0)
{
writer.write(buffer, 0, bytesRead);
buffer = new byte[153600];
totalBytesRead += bytesRead;
}
// Download finished
long endTime = System.currentTimeMillis();
// Output download information
System.out.println("Done.");
System.out.println((new Integer(totalBytesRead).toString()) + " bytes read.");
System.out.println("It took " + (new Long(endTime - startTime).toString()) + " milliseconds.");
// Close input and output streams
writer.close();
reader.close();
}
// Here I catch MalformedURLException and IOException :)
}
And I have JProgressBar component in my JPanel, which is supposed to visualize download progress:
private static void createProgressBar(JPanel panel)
{
JProgressBar progressBar = new JProgressBar(0, 100);
progressBar.setValue(0);
progressBar.setStringPainted(true);
panel.add(progressBar, BorderLayout.SOUTH);
}
I'd like to separate "back-end" functions from "front-end" views, presented to users, by analogy with MVC in web applications.
So, function getLatestRelease() lies in the package framework in class MyFramework.
Everything, connected with Swing interface generation, including event listeners, is in the package frontend.
In the main Controller class I create an instance of MyFramework and an instance of ApplicationFrontend, which is the main class of frontend package.
The questions is how to update progressBar value, depending on download progress?
when you want to do MVC in swing, the SwingWorker class comes to mind.
SwingWorker comes with a property called "progress", that you can listen to using a PropertyChangeListener.
Progress events can be fired from the swingworker using its setProgress(int 0-100) method. So here it is for loading the file in the background with a notion of progress (note that you will need to have an idea of the size of the file to be able to compute a progress percentage).
Showing the progress can be done using two options : a JProgressBar for complete control, or a ProgressMonitor to show an almost self-managed popup with a progress bar in it. See the tutorial to see the differences.
Solution 1
As they say, if you go for a ProgressMonitor and your background task is reading from an InputStream, you can use the ProgressMonitorInputStream class to do the reading and displaying progress without bothering with calling setProgress or listening to the "progress" property.
Solution 2
If you want to do it manually, create your SwingWorker loading task that calls setProgress as it goes, instanciate a ProgressMonitor (or a JProgressBar) as needed, register a PropertyChangeListener on your SwingWorker that checks for "progress" changes and updates the monitor/bar accordingly.
Note: It is important to go through a PropertyChangeListener because it decouples the model (the task) from the view (the swing progress component) and abide by the EDT usage rules.