JavaFX is *officially* dead!

Hence the importance of project jigsaw. Better start up time and even smaller kernel JVM with more fine grained modules for install. But I agree that until Java starts under 500 ms or so in applets, user perception will stay bad. This includes the Java logo animation (this seems to appear on applet install only) and white box too, which should just doesn’t exist.

I went to javaforum a couple of months ago. Some oracle devs explained (or rather tried to impress us) with the grand future of java. :slight_smile:
One of the key things they pressed lots and lots and lots was javaFX. Larry was determined to see javaFX a success. And as the sales guy said: “what Larry wants, he usually gets”.
Even when filtering with my bullshit filter, it seems that javaFX will get real attention with oracle.

Hopefully Oracle focuses on the “last inch”.

Java is a great platform, specially the VM! Getting it to the end user is a pain.

Applet would be great in theory; apps embedded int he browser! Look at flash, that works out well.
But something about the last inch, mainly the user experience with applets - just isn’t/wasn’t there.
If they could get applets running like flash they would dominate the flash market. Most any one would rather write for the Java VM then for adobes yucky one.
With a good deployment of the VM you could write in most anything: java, javascript, jpython, jruby, etc. That would attract a lot of developers.

It’s not that flash is better, it ain’t. The only reason it “won” is because it had a better user experience in terms of deployment.
If Oracle was to focus on that (Sun sure didn’t) then they might have something.

The go tell them! :wink:

modularization is important.

I wonder why Sun never hired a team of spiky teenagers exclusively for end user experience on the desktop

As long as it is possible to mix JavaFX with Swing, it is fine for the interoperability between 2D UIs and hardware accelerated 3D. The problem is that if the whole GUI of JavaFX becomes hardware accelerated on Windows through Direct3D, there will be a driver conflict with OpenGL. I hope that there will be a mean to disable this hardware acceleration as it is already possible now. Personally I don’t want to be forced to use Java3D with JavaFX. If it is still possible to use existing 3D engines with JavaFX, it will avoid us to rewrite full UI APIs rendered through OpenGL.

Exposing the JavaFX API directly in Java is a nice move on my view. It is no more possible to mix JavaFX with AWT which prevents the use of heavyweight canvas (that are more reliable especially on very low end hardwares).

The low latency audio might be great if Oracle fixes some old existing and impacting bugs and limitations of the Java Sound Audio Engine (JSAE gets sometimes attached to a wrong audio device, the bad support of very short samples, the same for big in-memory samples, etc…).

Well, actually that’s a good thing. I didn’t like the development effort being split as it was rather than feeding effort into the existing framework. Video in Swing is awesome, as you say

I found a test application from the internet, its using JavaFX jmc.jar and jmc.dll libraries. Running on Windows it can play any file supported by DirectX filters. Test application draws a simple overlay graphics. It works but what makes it almost unusable is a very very bad video rendering quality. Maybe am spoiled by EVRRenderer filter quality but this specific issue is where JavaFX video support must do better.

Flash is able to blend sprites, transparent drawings and h264 video rendering with decent rendering quality. I am looking for what Oracle does here.


[ testvideo.bat script ]
  set file=c:/test/testvideo.mp4
  java.exe -cp ./lib/test.jar;./lib/jmc.jar -Djava.library.path=./lib   XMP2   %file%



[ XMP2.java ]

// XMP2 (eXperimental Media Player #2).java
// javajeff.mb.ca

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.geom.Rectangle2D;

import java.net.URI;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.sun.media.jmc.MediaProvider;

import com.sun.media.jmc.control.AudioControl;
import com.sun.media.jmc.control.VideoRenderControl;

import com.sun.media.jmc.event.VideoRendererEvent;
import com.sun.media.jmc.event.VideoRendererListener;

public class XMP2 extends JFrame
{
  MediaProvider mp;

  public XMP2 (String mediaURI)
  {
   super ("XMP2: "+mediaURI);
   setDefaultCloseOperation (EXIT_ON_CLOSE);

   try {
     mp = new MediaProvider(new URI(mediaURI));
   } catch (Exception e) {
     System.out.println("Error opening media: "+e.toString ());
     System.exit (1);
   }

   JPanel panel = new JPanel ();
   panel.setLayout (new BorderLayout ());
   panel.add (new MediaPanelXMP2(mp), BorderLayout.CENTER);
   panel.add (createControlPanel (), BorderLayout.SOUTH);

   setContentPane (panel);

   pack ();
   setVisible (true);
  }

  public JPanel createControlPanel ()
  {
   JPanel panel = new JPanel ();

   JButton btnPlay = new JButton ("Play");
   ActionListener alPlay = new ActionListener ()
               {
                 public void actionPerformed (ActionEvent ae)
                 {
                   mp.play ();
                 }
               };
   btnPlay.addActionListener (alPlay);
   panel.add (btnPlay);

   JButton btnPause = new JButton ("Pause");
   ActionListener alPause = new ActionListener ()
                {
                  public void actionPerformed (ActionEvent ae)
                  {
                   mp.pause ();
                  }
                };
   btnPause.addActionListener (alPause);
   panel.add (btnPause);

   JButton btnStop = new JButton ("Stop");
   ActionListener alStop = new ActionListener ()
               {
                 public void actionPerformed (ActionEvent ae)
                 {
                   mp.pause ();
                   mp.setMediaTime (0.0);
                 }
               };
   btnStop.addActionListener (alStop);
   panel.add (btnStop);

   JCheckBox cbMute = new JCheckBox ("Mute");
   ChangeListener clMute = new ChangeListener ()
               {
                 public void stateChanged (ChangeEvent ce)
                 {
                   JCheckBox cb;
                   cb = (JCheckBox) ce.getSource ();
                   AudioControl ac;
                   ac = mp.getControl (AudioControl.class);
                   ac.setMute (cb.isSelected ());
                 }
               };
   cbMute.addChangeListener (clMute);
   panel.add (cbMute);

   panel.add (new JLabel ("Duration: "+mp.getDuration ()));

   return panel;
  }

  public static void main (final String [] args) throws Exception {
   if (args.length != 1)
   {
     System.err.println ("usage: java XMP2 mediaURI");
     return;
   }

   final String file = args[0].trim().replace('\\', '/');

   Runnable r = new Runnable ()
          {
            public void run ()
            {
             new XMP2(file);
            }
          };
   EventQueue.invokeLater (r);
  }
}

class MediaPanelXMP2 extends JPanel
{
  private AlphaComposite ac1 =
   AlphaComposite.getInstance (AlphaComposite.SRC_OVER, 0.1f);

  private AlphaComposite ac2 =
   AlphaComposite.getInstance (AlphaComposite.SRC_OVER, 0.3f);

  private AlphaComposite ac3 =
   AlphaComposite.getInstance (AlphaComposite.SRC_OVER, 0.6f);

  private Dimension frameSize;

  private Font font = new Font ("Arial", Font.BOLD, 16);

  private Rectangle frame = new Rectangle (0, 0, 0, 0);

  private Rectangle2D r2d = new Rectangle2D.Double (0.0, 0.0, 0.0, 0.0);

  private VideoRenderControl vrc;

  MediaPanelXMP2(MediaProvider mp) {
   vrc = mp.getControl(VideoRenderControl.class);
   if (vrc == null) {
     System.err.println ("no video renderer control");
     System.exit (-1);
   }
   frameSize = vrc.getFrameSize ();
   VideoRendererListener vrl;
   vrl = new VideoRendererListener ()
      {
        public void videoFrameUpdated (VideoRendererEvent vre)
        {
          repaint ();
        }
      };
   vrc.addVideoRendererListener (vrl);
   setPreferredSize (new Dimension (frameSize.width/2, frameSize.height/2));
  }

  protected void paintComponent(Graphics g)
  {
   frame.width = getWidth();
   frame.height = getHeight();
   vrc.paintVideoFrame(g, frame);

   double ar1 = frame.width/(double) frameSize.width;
   double ar2 = frame.height/(double) frameSize.height;

   double x, y;

   if (ar1 < ar2)
   {
     x = (frame.width-frameSize.width*ar1)/2+10.0;
     y = (frame.height-frameSize.height*ar1)/2+10.0;
   }
   else
   {
     x = (frame.width-frameSize.width*ar2)/2+10.0;
     y = (frame.height-frameSize.height*ar2)/2+10.0;
   }
   
   //x = y = 10;

   Graphics2D g2d = (Graphics2D) g;
   g2d.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
              RenderingHints.VALUE_ANTIALIAS_ON);

   g2d.setComposite (ac2);
   g2d.setPaint (Color.black);
   r2d.setFrame(x, y, 125.0, 50.0);
   g2d.fill(r2d);

   g2d.setComposite(ac3);
   g2d.setPaint (Color.blue);
   r2d.setFrame( (frame.width/2)-(125/2), (frame.height/2)-(50/2), 125.0, 50.0);
   g2d.fill(r2d);

   g2d.setComposite (ac2);
   g2d.setFont (font);
   g2d.setPaint (Color.yellow);
   g2d.drawString ("javajeff.mb.ca", (int) x+10, (int) y+30);
  }
}