package draggablemp3player;
import javafx.animation.*;
import javafx.stage.*;
import javafx.scene.input.*;
import javafx.scene.*;
import javafx.scene.shape.*;
import javafx.scene.paint.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.text.*;
import javafx.scene.media.*;
import javafx.scene.effect.*;
var stage:Stage;
var isApplet = "true".equals(FX.getArgument("isApplet") as String);
var inBrowser = isApplet;
var draggable = AppletStageExtension.appletDragSupported;
var dragTextVisible = bind inBrowser and draggable and dragRect.hover;
var homePage = "http:;
var baseURL = "http:;
var artist = "La Bonne Soupe";
var album = "lbs album";
var edmonton_cover = Image { url: "{__DIR__}covers/edmonton.jpg" backgroundLoading: true};
var forward_cover = Image { url: "{__DIR__}covers/forward.png" backgroundLoading: true};
var scottish_cover = Image { url: "{__DIR__}covers/scottish.jpg" backgroundLoading: true};
var literary_cover = Image { url: "{__DIR__}covers/literary.png" backgroundLoading: true};
var playlist:Playlist = Playlist {
songs: [
Song {
filename: "09_oaf_king__again.mp3"
name: "Oaf King, Again" album: "Literary Gentlemen"
artist: artist baseURL: baseURL cover: literary_cover
}
Song {
filename: "10_fool_conditioning_our_grannie_liu.mp3"
name: "Fool Conditioning (Our Grannie Liu)" album: "Literary Gentlemen"
artist: artist baseURL: baseURL cover: literary_cover
}
Song {
filename: "13_delusion.mp3"
name: "Delusion" album: "Literary Gentlemen"
artist: artist baseURL: baseURL cover: literary_cover
}
Song {
filename: "01_nana__girl_from_hungary.mp3"
name: "Nana, Girl From Hungary" album: "Scottish Insufficiency"
artist: artist baseURL: baseURL cover: scottish_cover
}
Song {
filename: "04_im_cold_and_i_want_to_go_home.mp3"
name: "I'm Cold And I Want To Go Home" album: "Scottish Insufficiency"
artist: artist baseURL: baseURL cover: scottish_cover
}
Song {
filename: "01_good_day_things_can_change.mp3"
name: "Good Day Things Can Change" album: "Edmonton Tussle"
artist: artist baseURL: baseURL cover: edmonton_cover
}
Song {
filename: "02_i_guess__amen.mp3"
name: "I Guess, Amen" album: "Edmonton Tussle"
artist: artist baseURL: baseURL cover: edmonton_cover
}
Song {
filename: "04_flash_flood_participant.mp3"
name: "Flash Flood Participant" album: "Forward To The Forward People"
artist: artist baseURL: baseURL cover: forward_cover
}
Song {
filename: "09_ellowen_deeowen.mp3"
name: "Ellowen Deeowen" album: "Forward To The Forward People"
artist: artist baseURL: baseURL cover: forward_cover
}
]
};
function stopCurrentSong():Void {
mediaPlayer.stop();
mediaPlayer.media = null;
if (playlist.currentPlayingSong != null) {
playlist.currentPlayingSong.closeMedia();
}
}
function playCurrentSong():Void {
playlist.currentPlayingSong = playlist.songs[playlist.currentSong];
mediaPlayer.media = playlist.currentPlayingSong.getMedia();
mediaPlayer.play();
}
FX.addShutdownAction(function() { stopCurrentSong(); });
var mediaPlayer:MediaPlayer = MediaPlayer {
volume: 0.5
autoPlay: false
onError: function(e:MediaError) {
println("got a MediaPlayer error : {e.cause} {e}");
stopCurrentSong();
}
onEndOfMedia: function() {
println("reached end of media");
stopCurrentSong();
playlist.currentSong++;
playCurrentSong();
}
};
var playlist_bg = ImageView { id: "playlist_bg" opacity: 1.0 visible: true
translateX: 198
translateY: 120
image: Image { url: "{__DIR__}images/MP3_handoff_playlist.png" }
};
var song_info_current_song:Song = null;
var song_info_popup:Group = Group {
visible: false
translateX: 250
translateY: 40
blocksMouse: true
content: [
Rectangle {
width: 220 height: 290
fill: Color.BLACK
arcWidth: 20
arcHeight: 20
stroke: Color.rgb(50,50,50)
},
ImageView { x: 5 y: 5 image: Image { url: "{__DIR__}images/MP3_handoff_drag_close.png" }
onMousePressed: function(e) {
song_info_popup.visible = false;
}
},
ImageView { x: 10 y: 46 image: bind song_info_current_song.cover },
Text { x: 10 y: 40 content: bind song_info_current_song.artist fill: Color.WHITE },
Text { x: 10 y: 260 content: bind song_info_current_song.album fill: Color.WHITE },
Text { x: 10 y: 275 content: bind song_info_current_song.name fill: Color.WHITE },
]
}
var playlist_text = Group {
content: for(song in playlist.songs) {
var i_image = ImageView { x: 357 image: Image { url: "{__DIR__}images/MP3_handoff_i.png" } };
var i_overlay_image = ImageView { x: 353 y:-2 opacity: 0.0 image: Image { url: "{__DIR__}images/MP3_handoff_Group_1_copy_2.png" }
onMouseClicked: function(e) {
song_info_current_song = song;
song_info_popup.visible = true;
}
};
RolloverBehavior { target: i_overlay_image };
Group {
translateX: 210
translateY: 15 * indexof song + 190
content: [
ImageView {
x: 0
visible: bind (playlist.currentSong == indexof song)
image: Image { url: "{__DIR__}images/MP3_handoff_playlist_volume.png" }
},
Text {
x: 20
y: 8
fill: Color.WHITE
content: "{1 + indexof song} {song.album} - {song.name}"
font: Font { size: 11 name: "Arial" }
},
i_image,
i_overlay_image,
]
}
}
};
var playlist_innerGroup = Group {
translateY: -230
content: [playlist_bg, playlist_text]
};
var playlist_group = Group {
content: playlist_innerGroup
clip: Rectangle { x: 200 y: 100 width: 400 height: 300 }
};
var playlist_reveal = Timeline {
rate: -1.0
keyFrames: [
at (0s) { playlist_innerGroup.translateY => -230 },
at (0.4s) { playlist_innerGroup.translateY => 0 }
]
};
var player_normal = ImageView { id: "player_normal"
opacity: 1.0 visible: true
x: 83 y: 29
image: Image { url: "{__DIR__}images/MP3_handoff_player_normal.png" },
};
var fx_rollover:ImageView = ImageView { id: "fx_rollover"
opacity: 0.0 visible: true
x: 196 y: 91
image: Image { url: "{__DIR__}images/MP3_handoff_fx_rollover.png" },
onMouseClicked: function(e) {
println("going to the fx homepage");
AppletStageExtension.showDocument(homePage);
}
};
RolloverBehavior { target: fx_rollover };
var playlist_rollover:ImageView = ImageView { id: "playlist_rollover"
opacity: 0.0 visible: true
x: 115 y: 157
blocksMouse:true
image: Image { url: "{__DIR__}images/MP3_handoff_playlist_rollover.png" },
onMousePressed: function(e) {
playlist_reveal.rate *= -1.0;
playlist_reveal.play();
}
};
RolloverBehavior { target: playlist_rollover };
var playBack = ImageView { id: "playBack"
opacity: 0.0 visible: true
x: 99 y: 104
image: Image { url: "{__DIR__}images/MP3_handoff_playBack.png" },
onMousePressed: function(e) {
var paused = mediaPlayer.paused;
if (not paused) {
stopCurrentSong();
playlist.currentSong--;
playCurrentSong();
} else {
playlist.currentSong--;
}
}
};
RolloverBehavior { target: playBack };
var playForward = ImageView { id: "playFoward"
opacity: 0.0 visible: true
x: 165 y: 107
image: Image { url: "{__DIR__}images/MP3_handoff_playFoward.png" },
onMousePressed: function(e) {
var paused = mediaPlayer.paused;
if (not paused) {
stopCurrentSong();
playlist.currentSong++;
playCurrentSong();
} else {
playlist.currentSong++;
}
}
};
RolloverBehavior { target: playForward };
var stop = ImageView { id: "stop"
opacity: 0.0 visible: true
x: 116 y: 88
image: Image { url: "{__DIR__}images/MP3_handoff_stop.png" },
onMousePressed: function(e) {
mediaPlayer.stop();
}
};
RolloverBehavior { target: stop };
var play_normal_image = Image { url: "{__DIR__}images/play.png" };
var play_rollover_image = Image { url: "{__DIR__}images/play_selected.png" };
var pause_normal_image = Image { url: "{__DIR__}images/pause.png" };
var pause_rollover_image = Image { url: "{__DIR__}images/pause_selected.png" };
var play_rollover:ImageView = ImageView { id: "play_rollover"
opacity: 1.0 visible: true
x: 122 y: 114
image: bind if (not mediaPlayer.paused) {
if (play_rollover.hover) { pause_rollover_image } else { pause_normal_image }
} else {
if (play_rollover.hover) { play_rollover_image } else { play_normal_image }
}
onMousePressed: function(e) {
if (playlist.currentPlayingSong != playlist.songs[playlist.currentSong]) {
stopCurrentSong();
playCurrentSong();
} else {
if (mediaPlayer.paused) {
mediaPlayer.play();
} else {
mediaPlayer.pause();
}
}
}
};
var drag_opacity = 0.0;
var drag_close_rollover = Image { url: "{__DIR__}images/close_rollover.png" };
var drag_close_normal = Image { url: "{__DIR__}images/close.png" };
var drag_out_rollover = Image { url: "{__DIR__}images/dragOut_rollover.png" };
var drag_out_normal = Image { url: "{__DIR__}images/dragOut.png" };
var drag_closers = Group {
opacity: bind drag_opacity;
content:[
ImageView { x: 541 y: 44 image: drag_close_normal visible: bind not inBrowser },
ImageView { x: 541 y: 44 image: drag_out_normal visible: bind inBrowser and draggable },
Rectangle { x: 541 y: 44 width: 10 height: 10 fill: Color.TRANSPARENT
onMouseClicked: function(e:MouseEvent):Void { stage.close(); }
}
]
};
var dragAreaFader = Timeline {
keyFrames: [
at (0s) { drag_opacity => 0.0 },
at (0.2s) { drag_opacity => 1.0 },
]
};
var dragRect:Rectangle = Rectangle {
x: 155 y: 30 width: 420 height: 40 fill: Color.TRANSPARENT
onMouseEntered: function(e) {
dragAreaFader.rate = 1.0;
dragAreaFader.play();
}
onMouseExited: function(e) {
dragAreaFader.rate = -1.0;
dragAreaFader.play();
}
};
var can_drag_me:ImageView = ImageView { id: "can_drag_me"
opacity: bind drag_opacity
visible: true
x: 83 y: 29
image: Image { url: "{__DIR__}images/MP3_handoff_can_drag_me.png" },
onMouseDragged: function(e) {
stage.x += e.dragX;
stage.y += e.dragY;
}
};
var can_drag_me_text:Text = Text { content: "You can drag me out of the browser"
fill: Color.WHITE
font: Font { size: 12 embolden: true name: "Arial"}
effect: DropShadow { offsetX: 0 offsetY: 1 color:Color.BLACK spread: 0.5 radius: 14}
opacity: bind drag_opacity
visible: bind dragTextVisible
y: 60
x: 165
};
var time_control_length = 240.0;
var time_control_xoff = 210;
var currentTime = bind
if (mediaPlayer.media != null and
mediaPlayer.media.duration != null and
mediaPlayer.media.duration.toMillis() > 0 and
mediaPlayer.currentTime.toMillis() > 0)
{
time_control_length * mediaPlayer.currentTime.toMillis() / mediaPlayer.media.duration.toMillis()
} else {
0.0
};
var bufferedTime = bind
if (mediaPlayer.media != null and
mediaPlayer.media.duration != null and
mediaPlayer.media.duration.toMillis() > 0 and
mediaPlayer.bufferProgressTime.toMillis() > 0)
{
time_control_length * mediaPlayer.bufferProgressTime.toMillis() / mediaPlayer.media.duration.toMillis()
} else {
0.0
};
var time_control:ImageView = ImageView { id: "time_control"
cursor: Cursor.HAND
opacity: 1.0 visible: true
x: bind currentTime + time_control_xoff y: 143
image: Image { url: "{__DIR__}images/MP3_handoff_time_control.png" },
blocksMouse: true
onMouseDragged: function(e) {
if (mediaPlayer.media != null and mediaPlayer.media.duration > 0s) {
var x = e.x;
var available = mediaPlayer.bufferProgressTime.toMillis() / mediaPlayer.media.duration.toMillis();
var xmin = time_control_xoff;
var xmax = xmin + (available*time_control_length);
if (x > xmin and x < xmax) {
var t = (x - xmin) / time_control_length * mediaPlayer.media.duration.toMillis();
mediaPlayer.currentTime = Duration.valueOf(t);
}
}
}
};
var current_time_indicator = ImageView { id: "current_time_indicator"
opacity: 1.0 visible: true
translateX: 214
translateY: 154
image: Image { url: "{__DIR__}images/MP3_handoff_blue_play_fill.png" }
clip: Rectangle { x: 0 y: 0 width: bind currentTime height: 20}
};
var buffering_indicator = Rectangle {
fill: LinearGradient {
startX: 0 startY: 0
endX: 1 endY: 0
stops: [
Stop { offset: 0.9 color: Color.rgb(255, 255, 255, 0.1) }
Stop { offset: 1.0 color: Color.TRANSPARENT }
]
}
translateX: 216
translateY: 157
width: bind bufferedTime
height: 2
};
function getTimeString(dur:Duration):String {
if (dur == null or dur < 0s) {
return "0:00";
} else {
var minutes = dur.toMinutes() as Integer;
var seconds = dur.toSeconds() mod 60 as Integer;
return "{minutes}:{%02d seconds}";
}
}
var current_time = Text {
fill: Color.web("#0d9c0d")
x: 465 y: 160 font: Font { size: 9 }
content: bind getTimeString(mediaPlayer.currentTime)
};
var total_time = Text {
fill: Color.web("#c5c5c5")
x: 490 y: 160 font: Font { size: 9 }
content: bind "/ {getTimeString(mediaPlayer.media.duration)}"
};
var volume_icon = ImageView {
id: "volume_icon"
opacity: 1.0
x: 542
y: 150
image: Image {
url: "{__DIR__}images/MP3_handoff_volume_icon.png"
},
};
var volume_group:Group = Group {
translateY: 110
content: [
ImageView { image: Image { url: "{__DIR__}images/MP3_handoff_bkg.png" }
blocksMouse: true
onMouseDragged:function(e) {
var v = (e.y-14)/65;
if(v < 0) { v = 0; }
if(v > 1.0) { v = 1.0; }
v = 1-v;
mediaPlayer.volume = v;
}
},
Rectangle { x: 22 y: 16 width: 12 height: 68
fill: bind LinearGradient {
startX:0 endX: 0 startY: 0 endY: 1 proportional: true
stops: [
Stop { color: Color.BLACK offset: 0.0 },
Stop { color: Color.GREEN offset: 0.99-(mediaPlayer.volume*0.98) },
Stop { color: Color.GREEN offset: 1.0 },
]
}
},
ImageView { image: Image { url: "{__DIR__}images/MP3_handoff_outline_inner_shadow.png" } x: 21 y: 15},
ImageView { image: Image { url: "{__DIR__}images/MP3_handoff_slider.png" }
x: 13
y: bind (1-mediaPlayer.volume) * 65 + 14
},
]
};
var volume_group_wrapper = Group {
blocksMouse: true
translateX: 523
translateY: 30
content: volume_group
clip: Rectangle { width: 100 height: 130 }
};
var reveal_volume = Timeline {
keyFrames: [
at (0s) { volume_group.translateY => 110 },
at (0.3s) { volume_group.translateY => 0 },
]
}
var volume_rollover = ImageView {
id: "volume_rollover"
opacity: 0.0
x: 542
y: 150
blocksMouse: true
image: Image {
url: "{__DIR__}images/MP3_handoff_volume_rollover.png"
},
effect: Glow { }
onMousePressed: function(e) {
reveal_volume.rate *= -1.0;
reveal_volume.play();
}
};
RolloverBehavior { target: volume_rollover };
function createGradient(color:Color) {
return LinearGradient {
proportional: false
startX: 0 startY: 0 endX: 275 endY: 0
stops: [
Stop { offset: 0.0 color: color }
Stop { offset: 0.8 color: color }
Stop { offset: 1.0 color: Color.TRANSPARENT }
]
}
}
var songInfo = Group {
translateX: 300
translateY: 100
content: [
Text {
content: bind "{playlist.songs[playlist.currentSong].name}"
x: 0 y: 0 fill: createGradient(Color.WHITE);
}
Text {
content: bind "{playlist.songs[playlist.currentSong].artist}"
" - {playlist.songs[playlist.currentSong].album}"
x: 0 y: 18 fill: createGradient(Color.color(0.7, 0.7, 0.7));
}
]
};
stage = Stage {
title: "MP3 Player"
visible: true
width: 510
height: 345
style:StageStyle.TRANSPARENT
scene: Scene {
fill: bind if (inBrowser) Color.WHITE else Color.TRANSPARENT
content: Group {
translateX: -75
translateY: -25
content: [
can_drag_me,
playlist_group,
player_normal,
fx_rollover,
playlist_rollover,
playBack,
playForward,
stop,
play_rollover,
buffering_indicator,
current_time_indicator,
time_control,
current_time,
total_time,
dragRect,
can_drag_me_text,
drag_closers,
volume_group_wrapper,
ImageView { image: Image { url: "{__DIR__}images/MP3_handoff_volume_bkg.png" } x: 491 y: 130 },
volume_icon,
volume_rollover,
songInfo,
song_info_popup,
]
}
}
extensions: [
AppletStageExtension {
shouldDragStart: function(e): Boolean {
return inBrowser and e.primaryButtonDown and dragRect.hover;
}
onDragStarted: function(): Void {
inBrowser = false;
}
onAppletRestored: function(): Void {
inBrowser = true;
}
useDefaultClose: false
}
]
}