Yet another blog about WPF, Surface, SL, MVVM, NUI....

2008

 

Create your VideoPlayer with JavaFX, part three(Add a control bar).

22 December 2008

Let's continue pur story about creating our own media player.

You can find a demo of the resulting videoPlayer on this page: demo of the videoPlayer - part 3.

What will we do in our third part ? :

  1. Add a control bar to the videoPlayer
  2. Display the progess of the video in this bar
  3. Add a play/pause button in this bar
  4. Enjoy ourselves!



Add a control bar to the videoPlayer

The goal is to display a control bar when the mouse is hover the video or when the media is paused.

The control bar will look like this : Video player how-to: the control bar.

First we create the gray rectangle which is behind the meta-information and the two differents text. We will add them to a group to ease the use of trigger to show/hide them.

/** ###########################################
    * The control bar
    *   ########################################### */
 
var controlBarBackGroundRect : Rectangle = Rectangle{
        x:x
        y: vidHeight + y - 40
        width:vidWith
        height: 40
        opacity:0.5
        fill:Color.DARKGRAY
    }
 
    var playPauseGroupWidth = 20 ;
    var pauseGroup : Group = Group{content:[]};
    var playGroup : Group = Group{content:[]};
    var progressNode  = Group{content:[]};
 
 
    var groupControlBar: Group = Group{
        content: [controlBarBackGroundRect,progressNode, pauseGroup, playGroup]
        cursor: Cursor.DEFAULT
        opacity: 0.0
}


Don't forget to add it in the returned Group of our component:

return Group{
            content: [mediaView,groupVidMETA, groupControlBar]
        }


What you can notice is that we have already prepare the differents things which will be putted in : the playButton, the pauseButton, the progressNode and the grayRectangle which is the bacground ofthe controlbar.

Display the progess of the video in this bar

To display the progress of the media we will create a Progress's node. To create this progress Node we will uses the james weaver's how-to which is on this page : Progress Indicator: Creating a JavaFX Custom Node and Binding to a Model but we will customize it a little to fits our specifications.

Here is a summary of the changes :

  • No more polygon for the progression but a good old Rectangle,
  • Add left, right and center text.

And here is the code :

/*
 *  ProgressNode.fx -
 *  A custom node that functions as a progress bar
 *  TODO: Add the ability to have an "infinite progress" look as well
 *
 *  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
 *  to demonstrate how to create custom nodes in JavaFX
 *
 *  Used and changed 2008 by Jonathan ANTOINE to use in his videoPlayer
 */
 
package fr.antoinej.tools;
 
import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Paint;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextOrigin;
 
public class ProgressNode extends CustomNode {
 
    /*
    * A number from 0.0 to 1.0 that indicates the amount of progress
     */
    public var progress:Number;
 
    /*
    * The fill of the progress part of the progress bar.  Because
     * this is of type Paint, a Color or gradient may be used.
     */
    public-init var progressFill:Paint =   LinearGradient {
        startX: 0.0
        startY: 0.0
        endX: 0.0
        endY: 1.0
        stops: [
            Stop {
                offset: 0.0
                color: Color.rgb(0, 192, 255)
            },
            Stop {
                offset: 0.20
                color: Color.rgb(0, 172, 234)
            },
            Stop {
                offset: 1.0
                color: Color.rgb(0, 112, 174)
            },
        ]
    };
 
    /*
    * The fill of the bar part of the progress bar. Because
     * this is of type Paint, a Color or gradient may be used.
     */
    public-init  var barFill:Paint = LinearGradient {
        startX: 0.0
        startY: 0.0
        endX: 0.0
        endY: 1.0
        stops: [
            Stop {
                offset: 0.0
                color: Color.rgb(112, 112, 112)
            },
            Stop {
                offset: 1.0
                color: Color.rgb(88, 88, 88)
            },
        ]
    };
    /*
    * The color of the progress percent text on the progress bar
     */
    public-init var progressPercentColor:Color = Color.rgb(191, 223, 239);
 
    /*
    * The color of the progress text on the right side of the progress bar
     */
    public-init var progressTextColor:Color = Color.WHITE;
 
    /*
    * Determines the width, in pixels, of the progress bar
     */
    public-init var width:Integer = 200;
 
    public var leftStr : String = "";
    public var rightStr : String = "";
    public var centerStr : String = "";
 
    /*
    * Determines the height, in pixels, of the progress bar
     */
    public-init var height:Integer = 20;
 
    /**
    * Create the Node
     */
    public override function create():Node {
        var textRef:Text;
        var progBarFont =Font.font("Verdana", FontWeight.EXTRA_BOLD, 10);
        var leftAndRightFont =Font.font("Sans serif", FontWeight.EXTRA_BOLD, 10);
        return Group{
 
            content: [
                // The entire progress bar
                Rectangle {
                    x:0
                    y:0
                    width: bind width
                    height: bind height
                    fill: bind barFill
                },
                Rectangle {
                    x:0
                    y:0
                    width: bind progress * width
                    height: height
                    fill: bind progressFill
                }
              ,
                // The percent complete displayed on the progress bar
                textRef = Text {
                    translateX: width / 2 - 20
                    translateY: 5
                    textOrigin: TextOrigin.TOP
                    font: progBarFont
 
                    fill: bind progressPercentColor
                    content: bind "{centerStr}({progress * 100 as Integer}%)"
                },
                Text {
                    translateX: bind width  - rightStr.length() * 6
                    translateY: 5
                    textOrigin: TextOrigin.TOP
                    font: leftAndRightFont
                    fill: bind progressPercentColor
                    content: bind "{rightStr}"
                },
                Text {
                    translateX: 4
                    translateY: 5
                    textOrigin: TextOrigin.TOP
                    font: leftAndRightFont
                    fill: bind progressPercentColor
                    content: bind "{leftStr}"
                }
 
            ]
        }    
 
    }
 
 
}



Now we gonna add it to our videoPlayer changing the precedent progressNode declaration by this one :

var progressNode: ProgressNode =
    ProgressNode{
        translateX:controlBarBackGroundRect.x + 10 + playPauseGroupWidth
        translateY:controlBarBackGroundRect.y + 10
        progress: bind mediaPlayer.currentTime.toMillis() / media.duration.toMillis()
        centerStr: bind "{%tM mediaPlayer.currentTime.toDate()}:{%tS mediaPlayer.currentTime.toDate()}"
        height:20
        width: vidWith - 20 - playPauseGroupWidth
        leftStr:"0:00${media.duration}"
        rightStr: bind "{%tM media.duration.toDate()}:{%tS media.duration.toDate()}"
    };

Note that we bind the rightStr to fit the sun usages given on this page.



Add a play/pause button in this bar

Now we gonna add a play/pause button. To do this we are going to create two groups, a play group which will be visible when the video is paused and a pause group visible when the video is played.

To create this buttons we are using polygons whe re some may prefers image: that's our choice !


Here is the code :

var pauseGroup : Group = Group{
        var rect1 =Rectangle {
            x: controlBarBackGroundRect.x + 7
            y: controlBarBackGroundRect.y + 13
            width: 4
            height: 13
            fill: Color.WHITE
            } ;
        var rect2 = Rectangle {
            x: controlBarBackGroundRect.x + 14
            y: controlBarBackGroundRect.y + 13
            width: 4
            height: 13
            fill: Color.WHITE
            };
        content: [rect1,rect2 ,
            Rectangle {
                x: controlBarBackGroundRect.x + 4
                y: controlBarBackGroundRect.y + 11
                width: 17
                height: 16
                fill: Color.TRANSPARENT
            }
        ]
        cursor:Cursor.HAND
        //On left click, play or pause the video
        onMouseClicked: function(me: MouseEvent){
            //Only a left click play/pause the video
            if(me.button == MouseButton.PRIMARY) {
                mediaPlayer.pause();
            }
        }
        onMouseEntered: function(me: MouseEvent){
            Timeline {
                keyFrames: [
               at(0s) {
                    rect1.fill => rect1.fill  tween Interpolator.LINEAR;
                    rect2.fill => rect1.fill  tween Interpolator.LINEAR;
              }
                  at(800ms) {
                    rect1.fill => Color.RED  tween Interpolator.LINEAR;
                    rect2.fill => Color.RED tween Interpolator.LINEAR;
            }
                ]
            }.play();
 
        }
        onMouseExited: function(me: MouseEvent){
            Timeline {
                keyFrames: [
               at(0s) {
                    rect1.fill => rect1.fill  tween Interpolator.LINEAR;
                    rect2.fill => rect1.fill  tween Interpolator.LINEAR;
              }
                  at(800ms) {
                    rect1.fill => Color.WHITE  tween Interpolator.LINEAR;
                    rect2.fill => Color.WHITE  tween Interpolator.LINEAR;
            }
                ]
            }.play();
 
        }
 
        visible: bind (mediaPlayer.status == mediaPlayer.PLAYING)
}
 
    var playGroup : Group = Group{
        var polygon = Polygon {
            points: [
                    controlBarBackGroundRect.x + 7,controlBarBackGroundRect.y + 14 ,
                    controlBarBackGroundRect.x + 7,controlBarBackGroundRect.y + 27,
                    controlBarBackGroundRect.x + 20,controlBarBackGroundRect.y + 20 ]
            fill: Color.WHITE
           };
        content: [polygon ,
            Rectangle {
                x: controlBarBackGroundRect.x + 4
                y: controlBarBackGroundRect.y + 11
                width: 17
                height: 16
                fill: Color.TRANSPARENT
            }
        ]
        cursor:Cursor.HAND
        //On left click, play or pause the video
        onMouseClicked: function(me: MouseEvent){
            //Only a left click play/pause the video
            if(me.button == MouseButton.PRIMARY) {
                mediaPlayer.play();
            }
        }
        onMouseEntered: function(me: MouseEvent){
            Timeline {
                keyFrames: [
               at(0s) {
                    polygon.fill => polygon.fill  tween Interpolator.LINEAR;
                             }
                  at(800ms) {
                    polygon.fill => Color.RED  tween Interpolator.LINEAR;
                             }
                ]
            }.play();
 
        }
        onMouseExited: function(me: MouseEvent){
            Timeline {
                keyFrames: [
               at(0s) {
                    polygon.fill => polygon.fill  tween Interpolator.LINEAR;
                              }
                  at(800ms) {
                    polygon.fill => Color.WHITE  tween Interpolator.LINEAR;
                           }
                ]
            }.play();
 
        }
 
        visible: bind (mediaPlayer.status == mediaPlayer.PAUSED)
}



You can find our component source in this post and view a demo on this page: demo of the videoPlayer - part 3.

 

how do I detect double clic in JavaFX ?

14 December 2008

I am currently confronted to this problem: detect double clic in JavaFX.

What I want to do :

When you make a double click, you click twice, so this is what will occurs:

  • The first click will be catch and the simpleClickAction will be done (because clickCount != 2) ---> I don't want it : this is a double click and I want the simpleClick action to be perform only on single click !,
  • The second click will be catch and the double clickAction will be done --> This is what I want.


So what I want is :

  • To perform a simpleClick action on single click only (and not those which are part of a double click),
  • To perform a double click action on doubleClick only.


How I did it

In swing this is done by using timer. So why not do the same with a Timeline in JavaFX.


This is how I solve the problem (the code is also linked to this post) :

/*
 * Main.fx
 *
 * Created on 14 déc. 2008, 15:10:59
 */
 
package fr.antoinj.detectdoubleclick;
 
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.Group;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
 
/**
 * @author Jonathan
 */
 
var textContent = "Nothing detected";
var clickInTheLastFewMoments: Boolean = false;
var lastLauchedTimeLine:Timeline ;
var clickedTimeLine: Timeline= Timeline {
    keyFrames: [KeyFrame {
            time: 0s
            action:function(){
                lastLauchedTimeLine.stop();
                clickInTheLastFewMoments=true;
            }
        }
        ,
        KeyFrame {
            time: 200ms
            action:function(){
                clickInTheLastFewMoments=false;
                simpleClick();
            }
        }
    ]
}
 
function simpleClick(){
    textContent="Simple click detected";
}
function doubleClick(){
    textContent="Double click detected";
}
Stage {
 
 
    title: "How I detect doubleClick in JavaFX"
    width: 400
    height: 80
    scene: Scene {
        content: Group{
            content: [Rectangle {
                    x: 75,
                    y: 0
                    width: 400,
                    height: 50
                    fill: Color.BLACK
                    onMouseClicked: function(me:MouseEvent){
                        if(clickInTheLastFewMoments){
                            clickInTheLastFewMoments=false;
                            clickedTimeLine.stop();
                            doubleClick();
                        }else {
                            clickedTimeLine.playFromStart();
                        }
                    }
                },
 
                Rectangle {
                    x: 0,
                    y: 0
                    width: 75
                    height: 50
                    fill: Color.ORANGERED
                    onMouseClicked: function(me:MouseEvent){
                        textContent="Nothing detected";
                    }
 
                },
                Text {
                    font: Font.font("Verdana",FontWeight.BOLD,12)
                    fill: Color.BLACK
                    x: 8
                    y: 25
                    content: "REFRESH"
                }
                ,
                Text {
                    font: Font.font("Verdana",FontWeight.MEDIUM,24)
                    fill:Color.PINK
                    x: 80
                    y: 30
                    content: bind textContent;
                }]
 
        }
 
    }
}

You can also see a demo of this javaFx apps here : link to the demo page or launch this JNLP : link to the JNLP



My question is : Do you have a better way to do this ?

 

Create your VideoPlayer with JavaFX, part two.

Let's continue pur story about creating our own media player

What will we do in our second part ? :

  1. Display the meta-information of our video.
  2. Create animation and triggers to show it in a non-disturbing way.
  3. Add some triggers to our video : play/pause on click.
  4. Double-clic to resume the video
  5. Enjoy ourselves!



Display the meta-informations in a non-disturbing way

We already have all the informations to display because we gived them to our component.
Now we will display them in an header: Videoplayer's metainformation header

First we create the gray rectangle which is behind the meta-information and the two differents text. We will add them to a group to ease the use of trigger to show/hide them.

/** ###########################################
    * The Top Rectangle of description
     *   ########################################### */
    var topRDescription : Rectangle = Rectangle{
        x:x
        y:y
        width:vidWith
        height: 40
        opacity:0.5
        fill:Color.DARKGRAY
}
 
    var titleText: Text =  Text{
        x:topRDescription.x + 10
        y: topRDescription.y + 25
        textOrigin: TextOrigin.BOTTOM
        content: bind vidTitle
        fill:Color.ORANGE
        font: Font.font("Verdana", FontWeight.EXTRA_BOLD, 18)
}
 
    var descriptionText: Text =  Text{
        x:topRDescription.x + 10
        y: topRDescription.y + 35
        content: bind vidDescription
        fill:Color.WHITE
        font: Font.font("Verdana", FontWeight.MEDIUM, 10)
}
 
    var groupVidMETA : Group = Group{
        content: [topRDescription,titleText,descriptionText]
        cursor: Cursor.DEFAULT
        opacity: 0.0
        visible: bind showInfoBar
}


Don't forget to add it in the returned Group of our component:

return Group{
            content: [mediaView,groupVidMETA]
        }


You can see that the visibility of our meta-information's bar is bind to a var showInfoBar. This is on this var that we will act to show/hide the bar. Sets this var to true and the informations will be displayed all the time... this is cool but quite boring when you want watch the movie which is behind. We will so add some animations to display it in a non disturbing way.

Create animation and triggers to show it in a non-disturbing way.

We will now display the bar only when the mouse is hover the video or when the video is paused.
To do this we will use the opacity of the bar and add animation in the MediaView's node triggers. Remember the MediaView is the node in which the media is displayed.
Resume of the things to do :

  • Add the onMouseEntered trigger to the MediaView,
  • Creates and play an animation in it which will set the groupVidMETA'opacity from it's current state to 1 in 500ms.
  • Add the onMouseExited trigger to the MediaView and add an animation to hide the meta's info only if the video is not paused.


The resulting mediaView var is then :

//The node displaying the video   
    var mediaView : MediaView = MediaView{
        x:x
        y:y
        mediaPlayer: bind mediaPlayer
        fitHeight:vidHeight
        fitWidth:vidWith
          //Show the informations in an animation.
        onMouseEntered: function(me: MouseEvent){
            Timeline {
                keyFrames: [
               at(0s) {
                    groupVidMETA.opacity =>    groupVidMETA.opacity tween Interpolator.LINEAR;
                    groupControlBar.opacity => groupControlBar.opacity  tween Interpolator.LINEAR;
                }
                  at(500ms) {
                    groupVidMETA.opacity => 1.0 tween Interpolator.LINEAR;
                    groupControlBar.opacity => 1.0 tween Interpolator.LINEAR;
            }
                ]
            }.play()
 
        }
        //Hide the informations in an animation if the video is not paused.
        onMouseExited: function(me: MouseEvent){
            if(mediaPlayer.status != MediaPlayer.PAUSED){
                Timeline {
                    keyFrames: [
               at(0s) {
                        groupVidMETA.opacity => groupVidMETA.opacity  tween Interpolator.LINEAR;
              }
                  at(500ms) {
                        groupVidMETA.opacity => 0.0 tween Interpolator.LINEAR;
            }
                    ]
                }.play();
 
            }
        }
};


We are abble to know if the video is paused by accessing the mediaPlayer's status and comparing it to it's PAUSED def.
Now that informations are displayed, we will add triggers to play or pause the video.

Add some triggers to our video : play/pause on click.

This is done by adding a onMouseClicked trigger to our mediaView Component. We will also check that it's the left button that is clicked to perform the play/pause and reserve the right button to maybe future functionnality.
Also we will set the cursor to the HAND def: tell our watcher that they can do something by clicking the video.
This is what we add to our mediaView component:

cursor:Cursor.HAND
 
        onMouseClicked: function(me: MouseEvent){
            //Only a left click play/pause the video
            if(me.button == MouseButton.PRIMARY ) {
 
                if(mediaPlayer.status == mediaPlayer.PAUSED){
                    mediaPlayer.play();
                }else {
                    mediaPlayer.pause();
                }
            }
        }


Enjoy ourselfs

You can find our component source in this post and view a demo on this page: demo of the videoPlayer - part 2.
It can be long to load... My server fault ...

 

How I resolve my "MediaUnavailableException"'s problem in JavaFX...

10 December 2008

hey,

In my first try to create a videoPlayer I always get an exception trying to play a media which are on my local hard disk.

The problem

I was trying to execute this media :

var mediaURL : String = "file://C:/tchou.flv";

But it generates me logs like this one :

FX Media Object caught Exception com.sun.media.jmc.MediaUnavailableException: Media unavailable:


I search on the web and I notice that I was not alone facing this problem : look at this post.
But nobody seems to find the answer to this problem...

The solution

Actually I finally manage to get ride of this exception and it was quite simple : we should use '/' instead of '//' when using the "file" protocol. You just have to use the code below and it will work :

/*
* Do not use this :
* var mediaURL : String = "file://C:/tchou.flv";
*/
var mediaURL : String = "file:/C:/tchou.flv";

Quite easy in fact !

 

Create your VideoPlayer with JavaFX, part one.

9 December 2008

I noticed in this post that the mediaComponent pointed out in the JavaFX demos was not still available and that we will so make our own...

Lets start !

What will we do in our first part ? :

  1. Create our custom node MyMediaComponent
  2. Add the video in our component
  3. Enjoy ourselfs!



Create our custom node: MyMediaComponent

The first thing to do is quite easy : create a new JavaFX class in Nebeans and make it extends the CustomNode class from the javafx.scene package. This class is provided to enable you making your own nodes.

You will then have to ovveride the "create():Node" method :

public override function create():Node{
        return Group{
            content: []
        }
    }

We will add more things in the content when we will build them.
First we will add some var to our class, They will contains some informations about our component :

/** X attribute of our component. */
 public var x : Integer = 0 ;
 /** Y attribute of our component. */
 public var y : Integer = 0 ;
 
/** A description of the video. */
public var vidDescription : String = "" ;
/** The title of the video. */
public var vidTitle : String = "" ;
/** Start volume of the video. */
public var startVolume : Number = 0.5;
/** Do where display the meta informations on the video */
public var showInfoBar : Boolean = true;
/** The url of the video. */
public var mediaURL : String ="" ;
/** The Width in wich where will make the video fit. */
public var vidWith : Integer = 384;
/** The height in wich where will make the video fit. */
public var vidHeight : Integer = 288 ;



Add the video in our component

We will add the video in our component. To add this features we will use three differents Object in the JavaFX API:

  • Media : contains the basic informations about our media, Note that it can be a video or an audio media...
  • MediaPlayer: this object is used to perform the differents actions on our video; play/pause. This component also contains the informations about the status of the current video: playing/paused/buffering, etc ... We give it the media.
  • MediaView: this object is the node in which the video is displayed. We give it the mediaPlayer.



Lets add it in our class and use the differents var we created just before :

var media:Media = Media{
        source: mediaURL
    };
    var mediaPlayer: MediaPlayer = MediaPlayer{
        media:media
        autoPlay:true
    };
 
    var mediaView : MediaView = MediaView{
        x:x
        y:y
        mediaPlayer: bind mediaPlayer
        fitHeight:vidHeight
        fitWidth:vidWith
      };

The autoPlay attribute tells that the video is played as soon as it can be by the player (when enough data is available when buffered).


Now that we have created the different component we will add the mediaView in the group returned by our create() function:

public override function create():Node{
        return Group{
            content: [mediaView ]
        }
    }


Now by adding our component in your application you will display the video and play it. This is a first step in the birth of our videoComponent: Video player, results of part one.


In the next part you will learn how to display the informations on the video currently played when hovering the video and how to add some triggers (play/pause the video by clicking on it).

+++

 

You could use the JavaFX Media Component.... Yes but where is it ?

8 December 2008

Have you been trying all the wonderful demo on on the JavaFX web site ? Yes ? Me too !

You can try the "Simple Video Player" for example :

Simple Video Player sample

It's great but when I tried to reproduce the video player i meet a little problem.

It tells "You could use the JavaFX Media Component, a prefabricated video player in the com.sun.fxmediacomponent package."... But where is it ? I Just cannot find it on the web...

You then have two solutions:

  1. Download the source code and use the jar file present in the lib folder,
  2. Reproduce this package by your own implementations...

I really prefere the second solutions and I will make a little How-To in a future posts to tell you how to do...

++

 

Deploy a JavaFX app as an applet with the Java Deployement Toolkit... (Updated twice)

Yesterday I tried to write my first JavaFX... I Found it quite easy.... It's name was "VideoPlayer".

But when I tried to put it on a web page and deploy it as an java Applet it became a Nightmare !

First I tried to use the code Netbeans give me in my 'dist' folder... It worked well on my computer but not when I putted it on my web site...

I notice then that it was trying to load the JNLP from this host: "http://localhost:8093/servlet/org.netbeans.modules.javafx.project.JnlpDownloadServlet/"... It was the problem !

So I change my "VideoPlayer_browser.jnlp" and change the host by the one of my webSite : "http://www.lexique-du-net.com/javafx/videoPlayer/". It then look like this :

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="http://www.lexique-du-net.com/javafx/videoPlayer/" href="VideoPlayer_browser.jnlp">
    <information>
        <title>VideoPlayer</title>
        <vendor>Jonathan ANTOINE</vendor>
        <homepage href="http://www.lexique-du-net.com/javafx/videoPlayer/"/>
        <description>VideoPlayer</description>
        <offline-allowed/>
        <shortcut>
            <desktop/>
        </shortcut>
    </information>
    <security>
        <all-permissions/>
    </security>
    <resources>
        <j2se version="1.5+"/>
        <extension name="JavaFX Runtime" href="http://dl.javafx.com/javafx-rt.jnlp"/>
        <jar href="VideoPlayer.jar" main="true"/>
    </resources>
    <applet-desc name="VideoPlayer" main-class="com.sun.javafx.runtime.adapter.Applet" width="384" height="288">
        <param name="MainJavaFXScript" value="videoplayer.Main">
    </applet-desc>
</jnlp>

It then worked well !

I also give you what to put in your HTML page :

javafx(
        {
              archive: "VideoPlayer.jar",
              draggable: true,
              width: 384,
              height: 306,
              code: "fr.antoinej.videoplayer.Main",
              name: "VideoPlayer"
        },
        {
	      isApplet: true
	 }
    );

I some params (isApplet: true) to tell my apps that it is an applet....

An other interesting thing you can add on you HTML page is to add thie next snippet in the header part. It will reload you JNLP files and do not use the cache each time you will load the page... Better when adding frequently features to you application...

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="0">

Update (21/12/2008): You can now find a tutorials on the JavaFx webSite : here !

+++