Play mp3 with JavaFX 11 on Raspberry Pi 3 - javafx

I´d like to get Java 11 and JavaFX 11 running on a Raspberry Pi 3.
I followed the instructions given by Gluon here: http://docs.gluonhq.com/embedded/
(only differences: I´m running a full Stretch image, not Lite and meanwhile BellSoft released Liberica JDK version 11.0.1 also for ARM, so I used that.)
My application is super simple: a label and a button, when the button is pressed then an mp3 shall be played:
public class HelloFX extends Application
{
#Override
public void start(Stage stage) {
String version = System.getProperty("java.version");
String fxVersion = System.getProperty("javafx.runtime.version");
Label l = new Label ("Java version: " + version + "\nJavaFX version: " + fxVersion);
Button b = new Button("play");
Scene scene = new Scene(new VBox(l, b), 350, 200);
b.setOnAction(
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
PlayMp3();
}
});
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
Media media;
void PlayMp3()
{
String resource = "/resources/sound.mp3";
media = new Media(getClass().getResource(resource).toURI().toURL().toString());
MediaPlayer mp = new MediaPlayer(media);
mp.play();
}
On Windows / Eclipse this runs and plays the mp3. On the Raspberry Pi I can execute the application with this command:
sudo /opt/jdk-11.0.1/bin/java --module-path=/opt/armv6hf-sdk/lib/ --add-modules javafx.graphics,javafx.media -cp /home/pi/Java/HelloFX/ -Dprism.verbose=true -Dembedded=monocle -Dglass.platform=Monocle javafx11.HelloFX
The graphics is visible on the display but when I press the button then I get the following exception:
Exception in thread "JavaFX Application Thread" java.lang.UnsatisfiedLinkError: no jfxmedia in java.library.path: [/usr/java/packages/lib, /lib, /usr/lib]
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2660)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:829)
at java.base/java.lang.System.loadLibrary(System.java:1867)
at javafx.graphics/com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:150)
at javafx.graphics/com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:62)
at javafx.media/com.sun.media.jfxmediaimpl.NativeMediaManager.lambda$new$0(NativeMediaManager.java:136)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.media/com.sun.media.jfxmediaimpl.NativeMediaManager.<init>(NativeMediaManager.java:107)
at javafx.media/com.sun.media.jfxmediaimpl.NativeMediaManager$NativeMediaManagerInitializer.<clinit>(NativeMediaManager.java:78)
at javafx.media/com.sun.media.jfxmediaimpl.NativeMediaManager.getDefaultInstance(NativeMediaManager.java:90)
at javafx.media/com.sun.media.jfxmedia.MediaManager.canPlayProtocol(MediaManager.java:78)
at javafx.media/com.sun.media.jfxmedia.locator.Locator.<init>(Locator.java:239)
at javafx.media/javafx.scene.media.Media.<init>(Media.java:393)
at javafx11.HelloFX.PlayMp3(HelloFX.java:62)
I found some posts saying that this error message means that Java is looking for a library called "libjfxmedia.so" but I can´t find that file anywhere.
Did I make any mistake or miss anything?
Do I need to change something in the java command to execute the application? (I´m unsure about the --add-modules parameter, it runs the same without this option...)
Is it possible that JavaFX 11 still does not support Media on the Raspberry Pi (I read that v8 also provided by Gluon didn´t)? Whom to ask if it will be supported in the near future?

What José Pereda wrote is correct, javafx.media was not included and it also didn´t get included in 11 release.
But things changed meanwhile, BellSoft recently released their Liberica package (Java including JavaFX) in version 14.0.1 where playing mp3s now works:
https://bell-sw.com/pages/downloads/?version=java-14&release=14.0.1+8&os=Linux&bitness=32-bit&architecture=ARM&package=jdk-full
There are still some minor bugs (e. g. mp3 file names must not contain spaces, the length of any mp3 is always infinite) but the basics are working, it even allows to play videos, just see their blog:
https://bell-sw.com/announcements/2019/09/12/JDK-JavaFX-Video-Preview/
Please make sure to really use the 14.0.1 and not the first 14 release because several fixes esp. for the Raspberry Pi have been implemented there.
Thanks to the BellSoft team for their great work here!!

Related

WebView/WebEngine fails with GluonMobile, GraalVM22, JavaFX 17

I built a simple app using WebView/WebEngine using Gluon Mobile but the WebView fails with a unsatisfiedlink error. It works fine with gluonfx:run and so I then ran gluonfx:runagent to get all the reflection stuff etc. I then run gluonfx:build but the app fails on gluonfx:nativerun. I have a simple fxml starting with <View fx:id="web"...> (with controller being WebPresenter) and containing a containing a <VBox...> containing a <WebView fx:id="wv"...>. The code is:
public class WebPresenter {
#FXML View web;
#FXML WebView wv;
public void initialize() {
WebEngine we = wv.getEngine();
we.loadContent("<html><body><h1>WebEngine!</h1></body></html>");
}
}
I run the build with NetBeans on Ubuntu 20.04 64bit, JavaFX v17.0.2, Charm v6.1.0, Java 17, graalvm-svm-java17-linux-gluon-22.0.0.3-Final. The reflect-json seems to have all the Web stuff necessary: com.sun.javafx.fxml.builder.web.WebViewBuilder, javafx.scene.web.WebView and WebPresenter.
The error occurs at load from the fxml <WebView...> and culminates in:
Caused by: java.lang.UnsatisfiedLinkError: com.sun.webkit.WebPage.twkInitWebCore(ZZZ)V [symbol: Java_com_sun_webkit_WebPage_twkInitWebCore or Java_com_sun_webkit_WebPage_twkInitWebCore__ZZZ]
:
at javafx.scene.web.WebView.<init>(WebView.java:275)
at com.sun.javafx.fxml.builder.web.WebViewBuilder.build(WebViewBuilder.java:66)
I had WebView/WebEngine working under slightly earlier versions (GraalVM11 and javafx-web 17.0.0.1). Am I missing something here?

Vimeo Networking Library Crash for Android 10 platform (api29)

I implemented vimeo networking using vimeo networking library(https://github.com/vimeo/vimeo-networking-java), exoplayer and explained in this post https://stackoverflow.com/a/65737556/8814924
Now the problem is when I was checking with API 30 it was getting error
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.emergingit.emergingstudy/com.emergingit.emergingstudy.activities.course.ExoPlayerActivity}: java.lang.IllegalStateException: Unable to extract the trust manager on Android10Platform, sslSocketFactory is class com.android.org.conscrypt.OpenSSLSocketFactoryImpl
Caused by: java.lang.IllegalStateException: Unable to extract the trust manager on Android10Platform, sslSocketFactory is class com.android.org.conscrypt.OpenSSLSocketFactoryImpl
which indicates the error on
VimeoClient.initialize(configuration);
which issue is dicscussed here : https://github.com/square/okhttp/issues/5878 , issue discussion :
I assume you are calling the deprecated form of sslSocketFactory, which is broken on newer Android versions. https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/OkHttpClient.kt#L719
/**
* Sets the socket factory used to secure HTTPS connections. If unset, the system default will
* be used.
*
* #deprecated [SSLSocketFactory] does not expose its [X509TrustManager], which is a field that
* OkHttp needs to build a clean certificate chain. This method instead must use reflection
* to extract the trust manager. Applications should prefer to call
* `sslSocketFactory(SSLSocketFactory, X509TrustManager)`, which avoids such reflection.
*/
#Deprecated(
message = "Use the sslSocketFactory overload that accepts a X509TrustManager.",
level = DeprecationLevel.ERROR
)
fun sslSocketFactory(sslSocketFactory: SSLSocketFactory) = apply {
if (sslSocketFactory != this.sslSocketFactoryOrNull) {
this.routeDatabase = null
}
this.sslSocketFactoryOrNull = sslSocketFactory
this.certificateChainCleaner = Platform.get().buildCertificateChainCleaner(sslSocketFactory)
}
is there any solution possible with using the current version "1.1.3" of networking library for this or I have to wait till the library update ?
I primarily Solved the problem for Vimeo video streaming on the Android 10 platform using the Vimeo-Networking library (v1.1.3).
as the main problem is in the OkHttpClient build method
builder.sslSocketFactory(sSLSocketFactory);
//RetrofitClientBuilder.java#186
where with 1 parameter version is depricated and I needed to pass X509TTrustManager as 2nd parameter like this :
builder.sslSocketFactory(sSLSocketFactory, new X509TrustManager() {
#Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
});
So it solved my problem till this update comes in the stable version of this library. How I implemented this is described below :
Error was showing on VimeoClient.initialize(accessToken); line and I searched about the error and find out that it is caused because of this OkHttpClient method deprecation (with 1 parameter).
So I went into VimeoClient.java and saw in its constructor private Retrofit createRetrofit() was called and inside it private OkHttpClient createOkHttpClient() was called. and there public class RetrofitClientBuilder object was created and it's problemetic method was public OkHttpClient build() in which : if (sSLSocketFactory != null) { builder.sslSocketFactory(sSLSocketFactory); }
this deprecated method was called.
So I just had to create 2 new java file with name VimeoClientUpdated.java and RetrofitClientBuilderUpdated.java which is just a renamed copy of VimeoClient.java and RetrofitClientBuilder.java and now my RetrofitClientBuilderUpdated.java has no deprecated method rather the correct and VimeoClientUpdated.java is calling RetrofitClientBuilderUpdated.java
(I couldn't extend because of the final class and couldn't even wrap the class as to the gateway to that solution, I had to face the private method which wasn't possible to alter in wrapper class)
and finally just instead of calling VimeoClient.initialize(accessToken) I am calling my newly created VimeoClientUpdated(accessToken) which won't crash while playing Vimeo video on Android 10.
Suggest me if there is a better way of serving my purpose (solving deprecated library method calling from the android activity).
Cheers..!!

Retrieved Audio Capture Device Names Differ When Queried in JavaFX Thread vs 'Plain' Java Thread

I've come across an odd behaviour when querying the names of audio capture devices in a JavaFX thread vs a 'plain' Java thread.
Normally I probably would not have noticed, except that I have some non-JavaFX applications which share a common configuration pool with a JavaFX application, and this caused some issues when programmatically setting a capture audio device to use.
In a nutshell, the same query main in a plain Java thread returns capture device names truncated to 31 characters, whereas in a JavaFX thread the capture device names are 'full'.
For example, truncated results...
Primary Sound Capture Driver
Microphone (HD Pro Webcam C910)
Microphone (Realtek(R) Audio)
Headset (Bose QuietComfort 35 H
Headset Microphone (Oculus Virt
...vs 'full' results:
Primary Sound Capture Driver
Microphone (HD Pro Webcam C910)
Microphone (Realtek(R) Audio)
Headset (Bose QuietComfort 35 Hands-Free)
Headset Microphone (Oculus Virtual Audio Device)
The minimal JavaFX application code below demonstrates the issue, and in my testing it happens in both 32 bit and 64 bit versions of the Java8 JDK on Windows 10. I have not tested non-Windows platforms, so I am not sure if the behaviour occurs outside this environment.
The showCaptureDeviceNames() method does the query and printout of the device names. If called from the main method, truncated devices names are shown. If commented out of main and triggered by the button press in the JavaFX thread, 'full' device names are shown.
Interestingly, if called in main first, and later in the JavaFX thread, truncated names are shown, indicating that there is some sort of caching going on (which luckily provides a workaround for my problem). Simply calling AudioSystem.getMixerInfo(); all by itself is sufficient to induce the 'caching' effect
Also, this only happens for capture devices; if the TargetDataLine.class is switched to SourceDataLine.class to filter for playback devices, the device name is always 'full'.
Can anyone offer any hints as to why this might be happening?
My current workaround is to ensure that the JavaFX application queries all audio devices before the JavaFX thread kicks off by calling AudioSystem.getMixerInfo(); in main(...). This works, but... as a "fix" it looks more like a mistake sitting there on its own for no apparent reason (although adequate commenting will help future developers who come across it).
I'd love for someone to tell me I'm doing something wrong and there's a better way.
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.Mixer.Info;
import javax.sound.sampled.TargetDataLine;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class CaptureDeviceListTest extends Application
{
#Override
public void start( Stage primaryStage )
throws Exception
{
primaryStage.setTitle( "Test Capture Device Queries" );
Button btn = new Button( "Get capture device names" );
btn.setOnAction( event -> showCaptureDeviceNames() );
StackPane root = new StackPane();
root.getChildren().add( btn );
primaryStage.setScene( new Scene( root, 200, 200 ) );
primaryStage.show();
}
private static void showCaptureDeviceNames()
{
// filter for capture devices - change to `SourceTargetData.class` for playback devices
Line.Info captureLine = new Line.Info( TargetDataLine.class );
for( Info mixerInfo : AudioSystem.getMixerInfo() )
{
Mixer mixer = AudioSystem.getMixer( mixerInfo );
if( mixer.isLineSupported( captureLine ) )
System.out.println( mixerInfo.getName() );
}
}
public static void main( String[] args )
{
// COMMENT / UNCOMMENT THE NEXT LINE
// showCaptureDeviceNames();
launch( args );
}
}

.NET Core Error 1053 the service did not respond to the start or control request in a timely fashion

I created a Windows Service starting from my .NET Core project following this
After this, I installed correctly it on my working machine and started it.
This is my service class:
using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading.Tasks;
namespace xxx
{
public class WindowsService
{
static void Main(string[] args)
{
System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
using (var service = new Service())
{
ServiceBase.Run(service);
}
}
}
internal class Service : ServiceBase
{
public Service()
{
ServiceName = "...";
}
protected override void OnStart(string[] args)
{
try
{
base.OnStart(args);
Task.Run(() => xxxx);
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
protected override void OnStop()
{
base.OnStop();
}
protected override void OnPause()
{
base.OnPause();
}
}
}
So, I copied the file and installed it also on a server. Here, when I try to start it, I get:
After this, I start a lot of googling... for example, I tried the following steps :
Go to Start > Run > and type regedit
Navigate to: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
With the control folder selected, right click in the pane on the right and - select new DWORD Value
Name the new DWORD: ServicesPipeTimeout
Right-click ServicesPipeTimeout, and then click Modify
Click Decimal, type '180000', and then click OK
Restart the computer
The weird point here is that the voice ServicesPipeTimeout didn't exist and I created it. Comparing the server with my working machine, there are also other value not present in the server. They are:
ServicesPipeTimeout
OsBootstatPath
Here the screenshot of regedit from the server:
Are these relevant?
I also tried to reinstall the service, recompile my files... how can I fix this problem? The error appears immediatly, it doesn't wait any timeout!
I had this problem when I switched my project to another location.
When I moved the project, I had copied the files in bin/debug folder too. The issue was resolved after I cleared the debug folder and created a new build.
See if this works!
It's a bit old question but someone may find this useful.
So I had the following code in Program.cs:
builder.SetBasePath(Environment.CurrentDirectory).AddJsonFile("appsettings.json")
Changed it to:
builder.SetBasePath(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).AddJsonFile("appsettings.json")
This seemed to fix the problem for me.
The problem with this error is that it is super generic.
Hopefully MS will give us some log in the future.
if you check the windows event viewer under applications it tells you what exactly is the exception that causes this error.
in my case the problem was i published the service in net6 and tried to run it on a pc with net7 installed. apparently it requires the exact major version that was used to publish the app.

Sonar and Flex plugin - Dollars ($) are not accepted in java class names

In reference to this bug from Sonar:
http://jira.codehaus.org/browse/SONAR-1865
and this one (which cross references the one above):
http://jira.codehaus.org/browse/SONAR-1637
I am still seeing this issue.
I am using Sonar server version 2.12.
I am using Hudson, version 2.2.0.
I have installed the Sonar plugin in Hudson, version 1.7.2.
and, most importantly, I have the Flex plugin installed in the Sonar server. Flex plugin version is 0.4.
When I run mvn sonar:sonar -Pflex on a flex project, i get this error in the stack trace:
Caused by: java.lang.IllegalArgumentException: Java inner classes are not supported : EntityEnums$ReportParameterName
at org.sonar.plugins.flex.FlexFile.<init>(FlexFile.java:79)
at org.sonar.plugins.flex.FlexFile.fromIOFile(FlexFile.java:165)
at org.sonar.plugins.flex.FlexSourceImporter.createResource(FlexSourceImporter.java:37)
at org.sonar.api.batch.AbstractSourceImporter.parseDirs(AbstractSourceImporter.java:75)
at org.sonar.api.batch.AbstractSourceImporter.analyse(AbstractSourceImporter.java:69)
at org.sonar.api.batch.AbstractSourceImporter.analyse(AbstractSourceImporter.java:60)
at org.sonar.batch.phases.SensorsExecutor.execute(SensorsExecutor.java:64)
Here is what my class looks like, that it is complaining about:
This is an Actionscript class, file name: EntityEnums$ReportParameterName.as. It was auto-generated from java to Actionscript using GraniteDS.
package com.digabit.core.db.entity.util {
[Bindable]
public class EntityEnums$ReportParameterName {
public static const tnid:String = "tnid";
public static const uname:String = "uname";
public static const lc:String = "lc";
public static const tnkey:String = "tnkey";
public static const oid:String = "oid";
public function EntityEnums$ReportParameterName()
{
super();
}
}
}
So, according the bug reports, this has been fixed in an earlier version of Sonar that I have; but I'm still seeing it in version 2.12. And why would the error show "java inner classes..." when this is a flex/actionscript class? Is anyone still seeing this bug behavior?
Issue has been created on Sonar Flex Plugin side ( http://jira.codehaus.org/browse/SONARPLUGINS-1623 ) and most probably would be fixed in next release.

Resources