program main;
{$mode objfpc}
uses
browserapp, JS, Classes, SysUtils, Web;
type
TTrack = Record
name,
artist,
image,
path,
display,
url : String;
end;
TMyApplication = class(TBrowserApplication)
now_playing,
track_art,
track_name,
track_artist,
display_text,
playpause_btn,
next_btn,
prev_btn,
curr_time,
total_duration : TJSHTMLElement;
curr_track : TJSHTMLAudioElement;
volume_slider,
seek_slider : TJSHTMLinputElement;
isPlaying : Boolean;
track_index : Integer;
updateTimer: Integer;
Procedure BindElements;
Procedure seekTo(Event: TJSEvent);
Procedure SetVolume(Event: TJSEvent);
Procedure DoPlayPause(Event: TJSEvent);
Procedure NextTrack(Event: TJSEvent);
Procedure PrevTrack(Event: TJSEvent);
Procedure PlayTrack;
Procedure PauseTrack;
procedure LoadTrack(aIndex : Integer);
procedure random_bg_color;
procedure resetValues;
procedure seekUpdate;
procedure doRun; override;
private
end;
var
track_list : Array of TTrack; external name 'track_list';
procedure TMyApplication.seekUpdate;
Var
seekPosition : Double;
currentMinutes,
currentSeconds,
durationMinutes,
durationSeconds : Integer;
begin
if jsIsNan(curr_track.duration) then exit;
seekPosition:=curr_track.currentTime * (100 / curr_track.duration);
seek_slider.value :=FloatToStr(seekPosition);
currentMinutes:=Round(curr_track.currentTime / 60);
currentSeconds:=Round(curr_track.currentTime - currentMinutes * 60);
durationMinutes:=Round(curr_track.duration / 60);
durationSeconds:=Round(curr_track.duration - durationMinutes * 60);
curr_time.innerText:= Format('%.2:%d2',[currentMinutes,currentSeconds]);
total_duration.innerText:=Format('%.2:%d2',[durationMinutes,durationSeconds]);
end;
procedure TMyApplication.BindElements;
Function GetElement (aClass : String) : TJSHTMLELement;
begin
Result:=TJSHTMLELement(Document.querySelector('.'+aClass));
Writeln('Looking for ',aClass,' : ',assigned(Result));
end;
begin
now_playing :=GetElement('now-playing');
track_art :=GetElement('track-art');
track_name :=GetElement('track-name');
track_artist :=GetElement('track-artist');
display_text :=GetElement('display-text');
playpause_btn :=GetElement('playpause-track');
playpause_btn.AddEventListener('click',@DoPlayPause);
next_btn :=GetElement('next-track');
next_btn.AddEventListener('click',@NextTrack);
prev_btn :=GetElement('prev-track');
prev_btn.AddEventListener('click',@PrevTrack);
seek_slider :=TJSHTMLInputElement(GetElement('seek_slider'));
seek_slider.AddEventListener('change',@SeekTo);
volume_slider :=TJSHTMLInputElement(GetElement('volume_slider'));
volume_slider.AddEventListener('change',@SetVolume);
curr_time :=GetElement('current-time');
total_duration :=GetElement('total-duration');
end;
procedure TMyApplication.seekTo(Event: TJSEvent);
Var
dSeekTo : Double;
begin
dSeekTo := curr_track.duration * (StrToFloatDef(seek_slider.value,50) / 100);
curr_track.currentTime := dSeekTo;
end;
procedure TMyApplication.SetVolume(Event: TJSEvent);
begin
curr_track.volume := StrToFloatDef(volume_slider.value,50) / 100;
end;
procedure TMyApplication.DoPlayPause(Event: TJSEvent);
begin
if isPlaying then
pauseTrack
else
playTrack;
end;
procedure TMyApplication.NextTrack(Event: TJSEvent);
begin
// Go back to the first track if the
// current one is the last in the track list
if (track_index < (Length(track_list) - 1)) then
Inc(track_index)
else
track_index:=0;
// Load and play the new track
loadTrack(track_index);
playTrack();
end;
procedure TMyApplication.PrevTrack(Event: TJSEvent);
begin
if (track_index > 0) then
Dec(track_index)
else
track_index := Length(track_list)- 1;
loadTrack(track_index);
playTrack();
end;
procedure TMyApplication.PlayTrack;
begin
curr_track.play();
isPlaying:=true;
playpause_btn.innerHTML := '';
end;
procedure TMyApplication.PauseTrack;
begin
curr_track.pause();
isPlaying:=false;
playpause_btn.innerHTML := '';
end;
procedure TMyApplication.LoadTrack(aIndex: Integer);
begin
// Clear the previous seek timer
window.clearInterval(updateTimer);
resetValues();
curr_track.src :=track_list[track_index].path;
curr_track.load();
track_art.style.SetProperty('background-image','url("' + track_list[track_index].image+ '")');
track_art.style.SetProperty('background-image','url("' + track_list[track_index].image+ '")');
track_artist.InnerHTML := track_list[track_index].artist;
track_name.InnerHTML := track_list[track_index].name;
display_text.InnerHTML:=String(track_list[track_index].display);
now_playing.InnerHTML := Format('PLAYING %d OF %d',[track_index + 1,Length(track_list)]);
updateTimer :=Window.setInterval(@seekUpdate, 1000);
curr_track.addEventListener('ended', @nextTrack);
random_bg_color();
end;
procedure TMyApplication.random_bg_color;
Const
Lim = 256 - 64;
Var
red,Green,blue : Integer;
col : string;
begin
red:=Round(random(Lim) + 64);
green:=Round(random(lim) + 64);
blue:=Round(random(lim)+64);
col:= Format('rgb(%d,%d,%d)',[red, green ,blue]);
TJSHTMLELement(document.body).style.SetProperty('background',col);
end;
procedure TMyApplication.resetValues;
begin
curr_time.InnerHTML:= '00:00';
total_duration.InnerHTML:= '00:00';
seek_slider.value:='0';
end;
procedure TMyApplication.doRun;
begin
Terminate;
BindElements;
curr_track:=TJSHTMLAudioElement(document.createElement('audio'));
curr_track.autoplay:=true;
ResetValues;
Window.SetInterval(@seekUpdate,1000);
LoadTrack(0);
end;
var
Application : TMyApplication;
begin
Application:=TMyApplication.Create(nil);
Application.Initialize;
Application.Run;
end.