Correct using VLCj - java

I try to use VLCj to get access to web-cameras. I am using this code:
public static void main(String[] args) {
// Create player.
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
DirectMediaPlayer mediaPlayer = mediaPlayerFactory.newDirectMediaPlayer(
320, 240,
new RenderCallback() {
#Override
public void display(Memory arg0) {
// Do nothing.
}
});
// Options setup.
String[] options = new String[]{};
String mrl = "v4l2:///dev/video0"; // Linux
// Start preocessing.
mediaPlayer.startMedia(mrl, options);
BufferedImage bufImg;
for (int i = 0; i < 1000; ++i) {
bufImg = mediaPlayer.getSnapshot();
// Do something with BufferedImage...
// ...
}
// Stop precessing.
mediaPlayer.stop();
mediaPlayer = null;
System.out.println("Finish!");
}
And this code partially works -- I can get and work with BufferedImage, but:
I got an error in to output: [0x7f0a4c001268] main vout display error: Failed to set on top
When main loop is finished and camera was disabled program don't finished! I see Finish! message, but program not return control into IDE or console.
UPD:
I am using openSUSE 12.2 x64, VLC 2.0.3 installed and working properly for all video files, library VLCj 2.1.0.

This code working properly:
public static void main(String[] args) {
// Configure player factory.
String[] VLC_ARGS = {
"--intf", "dummy", // no interface
"--vout", "dummy", // we don't want video (output)
"--no-audio", // we don't want audio (decoding)
"--no-video-title-show", // nor the filename displayed
"--no-stats", // no stats
"--no-sub-autodetect-file", // we don't want subtitles
"--no-inhibit", // we don't want interfaces
"--no-disable-screensaver", // we don't want interfaces
"--no-snapshot-preview", // no blending in dummy vout
};
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory(VLC_ARGS);
// Create player.
HeadlessMediaPlayer mediaPlayer = mediaPlayerFactory.newHeadlessMediaPlayer();
// Select input device.
String mrl = "v4l2:///dev/video0"; // Linux
// Start processing.
mediaPlayer.startMedia(mrl);
BufferedImage bufImg;
for (int i = 0; i < 1000; ++i) {
bufImg = mediaPlayer.getSnapshot();
// Do something with BufferedImage...
// ...
}
// Stop processing.
mediaPlayer.stop();
// Finish program.
mediaPlayer.release();
mediaPlayerFactory.release();
}

Re your native window: VLCj opens a shared instance to the VLC library.
A headless media palyer is NOT intended to have a video or audio output!
In fact, if you need anything to play (and not to stream to anywhere else) you need to create either an output window or use a direct media player (may be much more complicated)
So, if a headless player needs to play something it opens a native window to perform the playback!
Source: http://www.capricasoftware.co.uk/wiki/index.php?title=Vlcj_Media_Players
Re the error: the video display component MUST be the top component of the panel, window or whereever it is added to. Otherwise it will throw the error
main vout display error: Failed to set on top
Furthermore, if you put anything over the component it will destroy the video output which won't work anymore!
Anyway, I don't know how the DirectMediaPlayer works in detail but VLCj has some weird behaviour... Maybe getSnapshot() needs a video display component but I'm not sure.
Re your not finishing program: you join to finish your own thread. This can't work because your thread "sleeps" until the other thread who is waited for has been terminated but as this is your own thread it "sleeps" and won't terminate.
You can test this behaviour with this short code in a main method:
System.out.println("Test start");
Thread.currentThread().join();
System.out.println("Test stop");
You will NEVER reach the "Test stop" statement.

Related

How to let a sound play once in Processing?

import processing.serial.*;
import processing.sound.*;
SoundFile file;
Serial myPort; // Create object from Serial class
String val; // Data received from the serial port
//String antwoord = "A";
void setup()
{
size(300,300);
// I know that the first port in the serial list on my mac
// is Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if ( myPort.available() > 0)
{ // If data is available,
val = trim( myPort.readStringUntil(ENTER) );
// read it and store it in val
}
//println(val); //print it out in the console
file = new SoundFile(this,"Promise.mp3");
if ("A".equals(val) == true && file.isPlaying() == false) {
file.play();
file.amp(0.2);}
else{
ellipse(40,40,40,40);
}
}
I got this code, but I want the sound to keep playing as long as the signal 'A' is given. Now it starts playing constantly, which leads to a weird static noise. How can I make it just play steadidly?
You're creating a new SoundFile in every run of draw. So file.isPlaying() will always return false. Only create a new SoundFile if you haven't already. The simplest solution is probably to move file = new SoundFile(this,"Promise.mp3"); into setup
Or you check or remember if you already loaded the file.
I am sorry if it is a bit disconnected but I recommend using minim or a different sound library instead of the processing one, since it causes a lot of problems in exporting (at least it had done so consistently for me).

How to input data into external GUI using Java runtime exec

I am trying to write java code to access and use the DullRazor software.
Please refer to this image of the DullRazor application:
I had an idea of creating a Java runtime program that could loop through all images I need to process(the software only allows 1 image at a time) and complete the necessary steps required for the DullRazor software to successfully alter an image for every image I have.
The DullRazor software works as follows:
-Source File: Requires the path to an image(jpg in my case) to be altered i.e c://Isic-Images//image0000.jpg.
-Target File: Requires the location for the new image with a new image name i.e c://finalLocation//newImage.jpg
-Start: Run the program after giving the inputs in the correct format as described above.
My thinking is iterating through all my images, creating new ones and incrementing the name(img00, img001 etc..).
I have never attempted anything like this in Java and I have had some trouble accessing the Input fields of the software as well as the application's start button.
The code below is just very basic for opening the application, but I am unsure how to access the various items in the DullRazor application and being able to input Strings in those aforementioned fields(again, refer to the DullRazor picture).
private String trainingPath = "C:\\Users\\user\\AppData\\Local\\Temp\\ISIC-Images\\Training\\0";
private String finalPath = "C:\\Users\\user\\finalLocation\\";
public static void main(String[] args) {
try {
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec("C:\\Users\\user\\Desktop\\dullrazor.exe");
System.out.println("Opening DullRazor");
OutputStream output = process.getOutputStream();
InputStream input = process.getInputStream();
Thread.sleep(2000);
process.destroy();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException s) {
s.printStackTrace();
} finally {
System.out.println("Closing Dullrazor");
}
}
I have just been testing a bit with the code above, but I am unsure on how to proceed.
Tell me if there is anything that needs clarifying.
Any help is greatly appreciated, thanks.
You can use Java's java.awt.Robot class to control mouse and keyboard on the screen.
This is a simple example entering "test1" and "test2" into two input fields:
Robot r = new Robot();
r.mouseMove(22, 125);
r.mousePress(InputEvent.BUTTON1_DOWN_MASK);
r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
r.keyPress('T');
r.keyRelease('T');
r.keyPress('E');
r.keyRelease('E');
r.keyPress('S');
r.keyRelease('S');
r.keyPress('T');
r.keyRelease('T');
r.keyPress('1');
r.keyRelease('1');
r.mouseMove(200, 125);
r.mousePress(InputEvent.BUTTON1_DOWN_MASK);
r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
r.keyPress('T');
r.keyRelease('T');
r.keyPress('E');
r.keyRelease('E');
r.keyPress('S');
r.keyRelease('S');
r.keyPress('T');
r.keyRelease('T');
r.keyPress('2');
r.keyRelease('2');
The above code in action:
If the position of the new application window does not change with each start, and the tool is not about to be deployed to users, this might already suffice. However, if it changes the position with each start, the challenge is to find the window position to add the relative input element positions from there. There are Windows (platform) specific approaches facilitating the Win32 API through JNA, though I'm not familiar with it and whether it is still available in current Microsoft Windows versions.
See these related questions on determining other windows positions:
Windows: how to get a list of all visible windows?
How to get the x and y of a program window in Java?
Using robot works perfectly in order to input into the targeted fields and clicking start/clear button on the application.
In order to find the x & y positions of the application I used runtime exec to open dullrazor and then take a screenshot of the screen with the application up where mouse clicks reveals the x and y position of the current click. Below is the code for finding x & y which I found at this Stackoverflow thread:
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().
getScreenSize();
final BufferedImage screen = robot.createScreenCapture(
new Rectangle(screenSize));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JLabel screenLabel = new JLabel(new ImageIcon(screen));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension(
(int)(screenSize.getWidth()/2),
(int)(screenSize.getHeight()/2)));
final Point pointOfInterest = new Point();
JPanel panel = new JPanel(new BorderLayout());
panel.add(screenScroll, BorderLayout.CENTER);
final JLabel pointLabel = new JLabel(
"Click on any point in the screen shot!");
panel.add(pointLabel, BorderLayout.SOUTH);
screenLabel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
pointOfInterest.setLocation(me.getPoint());
pointLabel.setText(
"Point: " +
pointOfInterest.getX() +
"x" +
pointOfInterest.getY());
}
});
JOptionPane.showMessageDialog(null, panel);
System.out.println("Point of interest: " + pointOfInterest);
}
});
Thank you try-catch-finally for a great answer.

Java picam preview

I am currently trying to incorporate a temporary stream in my card panel layed out like this.
Layout
Where it says scan your QRCode im trying to get a stream from the picam. Here is the issue.
I dont know how i can buffer that into the Java application
I got the command i want --> "raspistill -w 200 -h 200 -q 100 -t 5", but i just dont know how this would work. This is the first time im dealing with any video stream.
As for the second part. I need that "preview" to take a picture whenever it is able to grab the QRCode. I checked both apis for the raspberry pi camera but im still lost as in for direction. I also need this buffered so i can instantly parse it into my decodeQRCode method. What component do i need to accomplish this?
I decided to go with sarxos webcam api.
class VideoFeed extends Thread {
public void run() {
webcam.open();
boolean bool = true;
while (bool) {
try {
BufferedImage image = webcam.getImage();
var = BackEnd.refund(image,type[0]);
lblCamera.setIcon(new ImageIcon(image));
if (var[0] != null) {
bool = false;
webcam.close();
btnScan.doClick();
} else {
Thread.sleep(10);
}
} catch (InterruptedException ex) {
System.out.println("Error: " + ex);
}
}
}
}
started it by doing
new VideoFeed().start();
With this i opted for a more general driver.

disable other sounds in java

I wrote a program in Java using the pi4j lib to make sound whenever a (physical) button is clicked. This program works, but it now plays all the sounds interchangeably. I want that when you click on 2,3,4 or more buttons you only hear one sound.
This is the code I hope you can help.
public class ButtonSoundsProject{
public static void main(String args[]) throws InterruptedException {
System.out.println("Toy has been started!");
// create gpio controller
final GpioController gpio = GpioFactory.getInstance();
// provision gpio pin #02 as an input pin with its internal pull down resistor enabled
GpioPinDigitalInput[] pins = {
gpio.provisionDigitalInputPin(RaspiPin.GPIO_00, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_01, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_03, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_04, PinPullResistance.PULL_DOWN),
gpio.provisionDigitalInputPin(RaspiPin.GPIO_05, PinPullResistance.PULL_DOWN),};
final ArrayList<String> soundList = new ArrayList<String>();
soundList.add("/home/pi/Sounds/Sound1.wav");
soundList.add("/home/pi/Sounds/Sound2.wav");
soundList.add("/home/pi/Sounds/Sound3.wav");
soundList.add("/home/pi/Sounds/Sound4.wav");
soundList.add("/home/pi/Sounds/Sound5.wav");
soundList.add("/home/pi/Sounds/Sound6.wav");
soundList.add("/home/pi/Sounds/Sound7.wav");
soundList.add("/home/pi/Sounds/Sound8.wav");
soundList.add("/home/pi/Sounds/Sound9.wav");
soundList.add("/home/pi/Sounds/Sound10.wav");
soundList.add("/home/pi/Sounds/Sound11.wav");
soundList.add("/home/pi/Sounds/Sound12.wav");
// create and register gpio pin listener
GpioPinListenerDigital listener = new GpioPinListenerDigital() {
#Override
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
// display pin state on console
final int randomNum = 0 + (int) (Math.random() * 12);
System.out.println(randomNum);
System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
InputStream in;
try {
System.out.println(soundList.get(randomNum).toString());
String filepath = soundList.get(randomNum).toString();
in = new FileInputStream(new File(filepath));
AudioStream as = new AudioStream(in);
AudioPlayer.player.start(as);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
gpio.addListener(listener, pins);
for (;;) {
Thread.sleep(500);
}
}
}
As stated in the comments, I can't give you advise regarding the AudioStream and AudioPlayer classes because I don't seem to have those in my JDK. Since my method is similar, I'll give you what I have, and you can hopefully take it from there.
Basically, the solution is to stop and/or "mute" that audio clip. This is how I accomplish it using the javax.sound package.:
private Clip currentAudioClip; // Keep a reference to the current clip being played
public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
// Call this every time regardless.
// If nothing is playing, this will do nothing.
stopAudio();
String filepath = soundList.get(randomNum)
URL soundFileUrl = new File(filePath).toURI().toURL();
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(soundFileUrl);
Line.Info lineInfo = new Line.Info(Clip.class);
Line line = AudioSystem.getLine(lineInfo);
currentAudioClip = (Clip) line;
currentAudioClip.open(audioInputStream);
audioClip.start();
// Alternative if you want to loop continuously. Comment out the `.start` line to use this.
// audioClip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void stopAudio(){
if(audioClip != null){
muteLine(); // A gotcha I discovered (see explanation below)
audioClip.stop();
// audioClip.loop(0); // if you chose to loop, use this instead of `.stop()`
audioClip.flush();
audioClip = null;
}
}
public void muteLine(){
BooleanControl muteControl = (BooleanControl) audioClip.getControl(BooleanControl.Type.MUTE);
if(muteControl != null){
muteControl.setValue(true); // True to mute the line, false to unmute
}
}
In short, every time a pin state change event is fired, the previous audio clip will be ceased, and a new one should play. You shouldn't get any sound overlapping with this.
Also note that this is a slight modification of my original code, so let me know if there are any issues
Note about the GOTCHA
I wrote a question over on the Raspberry PI Stackexchange about an odd problem I encountered. The problem was that I discovered my audio clip would not cease playing on command. It would continue playing for a seemingly arbitrary amount of time. The stranger thing is that I only observed this while testing the app on the raspberry; it worked perfectly fine on my local machine (and even on several other machines).
It is possible my issue is related to the "looping" of my clip; if that is the case, and you simply want the clip to play for its length and no further, you may not encounter that issue, and you can probably dispense with the "muting" code I included. However, if you do observe the same issue, at least you have a solution.
Hope this helps, let me know if you have any questions.

Java VLCJ player, set audio track is not working

I am currently working on java media player that can play mkv format. I am using VLCJ, everything is working except when I try to change audio track which is not working.
here is the code
public class mediaplayer {
private static JFileChooser filechooser = new JFileChooser();
public mediaplayer() {
}
public static void main(String[] args) {
String vlcPath = "", mediaPath = "";
File ourfile;
filechooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
filechooser.showSaveDialog(null);
ourfile = filechooser.getSelectedFile();
mediaPath = ourfile.getAbsolutePath();
EmbeddedMediaPlayerComponent mediacom = new EmbeddedMediaPlayerComponent();
JFrame frame = new JFrame();
frame.setContentPane(mediacom);
frame.add(canvas);
frame.setLocation(100, 100);
frame.setSize(1050, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
MediaPlayer mplayer = mediacom.getMediaPlayer();
mplayer.playMedia(mediaPath);
mplayer.setAudioTrack(1);
}
}
In libVLC versions before vlc 2.0.5 the native API call to set the audio track was bugged.
With the fix in libVLC 2.0.5, setting the audio track works reliably but you can not just assume a simple index from 0..N and you can not assume sequential track numbers - you must enumerate the audio tracks by calling mediaPlayer.getAudioDescriptions(). The returned TrackDescription objects contain an audio track identifier that should be used with mediaPlayer.setAudioTrack().
To disable audio, you can select the audio track identifier of the track with a a description of "Disable".
Also be aware that you might not be able to set the audio track immediately after calling mediaPlayer.playMedia(). Media is started asynchronously and you may need to wait until the media has actually started and/or has been parsed before the track information is available.
6 years later
The API have grown a lot
If you want to stop or choose an audio track you can use this code snippet and adapt it, the idea is to wait for the player to start using a process then switching to what you need, in my case is the audio disabling
new Thread(
() -> {
try {
while(!empc.mediaPlayer().status().isPlaying())Thread.sleep(500);
empc.mediaPlayer().audio().trackDescriptions().stream()
.filter(td -> td.description().equals("Disable"))
.forEach(t -> empc.mediaPlayer().audio().setTrack(t.id()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
).start();
empc is my media player instance {the embed one for more precision in the player component}

Categories