* Player demo

This commit is contained in:
Michaël Van Canneyt 2022-01-13 21:42:30 +01:00
parent e4b569110d
commit 49b0ae4bec
6 changed files with 553 additions and 0 deletions

BIN
demo/player/headset.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

54
demo/player/index.html Normal file
View File

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Media player demo</title>
<link rel="stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css">
<link rel="stylesheet" type="text/css" href="style.css">
<script src="tracks.js"></script>
<script src="main.js"></script>
</head>
<body>
<div class="player">
<div class="details">
<div class="display-text"></div>
<div class="now-playing">PLAYING x OF y</div>
<div class="track-art"></div>
<div class="track-name">Track Name</div>
<div class="track-artist">Track Artist</div>
</div>
<div class="buttons">
<div class="prev-track" >
<i class="fa fa-step-backward fa-2x"></i>
</div>
<div class="playpause-track">
<i class="fa fa-play-circle fa-5x"></i>
</div>
<div class="next-track" >
<i class="fa fa-step-forward fa-2x"></i>
</div>
</div>
<div class="slider_container">
<div class="current-time">00:00</div>
<input type="range" min="1" max="100"
value="0" class="seek_slider" >
<div class="total-duration">00:00</div>
</div>
<div class="slider_container">
<i class="fa fa-volume-down"></i>
<input type="range" min="1" max="100"
value="99" class="volume_slider">
<i class="fa fa-volume-up"></i>
</div>
</div>
<hr>
<a href="main.pas">Program sources</a> &nbsp; <a
href="https://www.bensound.com/royalty-free-music/">Royalty-free music from Bensound</a>
<script>
window.addEventListener("load",rtl.run)
</script>
</body>
</html>

81
demo/player/main.lpi Normal file
View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
<Runnable Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="main"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<CustomData Count="2">
<Item0 Name="PasJSPort" Value="0"/>
<Item1 Name="PasJSWebBrowserProject" Value="1"/>
</CustomData>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<Units>
<Unit>
<Filename Value="main.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target FileExt=".js">
<Filename Value="main"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="js"/>
</SearchPaths>
<Parsing>
<SyntaxOptions>
<AllowLabel Value="False"/>
<CPPInline Value="False"/>
<UseAnsiStrings Value="False"/>
</SyntaxOptions>
</Parsing>
<CodeGeneration>
<TargetOS Value="browser"/>
</CodeGeneration>
<Linking>
<Debugging>
<GenerateDebugInfo Value="False"/>
<UseLineInfoUnit Value="False"/>
</Debugging>
</Linking>
<Other>
<CustomOptions Value="-Jeutf-8 -Jirtl.js -Jc -Jminclude"/>
<CompilerPath Value="$(pas2js)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions>
<Item>
<Name Value="EAbort"/>
</Item>
<Item>
<Name Value="ECodetoolError"/>
</Item>
<Item>
<Name Value="EFOpenError"/>
</Item>
</Exceptions>
</Debugging>
</CONFIG>

229
demo/player/main.pas Normal file
View File

@ -0,0 +1,229 @@
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 := '<i class="fa fa-pause-circle fa-5x"></i>';
end;
procedure TMyApplication.PauseTrack;
begin
curr_track.pause();
isPlaying:=false;
playpause_btn.innerHTML := '<i class="fa fa-play-circle fa-5x"></i>';
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.

143
demo/player/style.css Normal file
View File

@ -0,0 +1,143 @@
body {
background-color: lightgreen;
/* Smoothly transition the background color */
transition: background-color .5s;
}
/* Using flex with the column direction to
align items in a vertical direction */
.player {
height: 95vh;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
.details {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
margin-top: 25px;
}
.track-art {
margin: 25px;
height: 250px;
width: 250px;
background-image: URL("headset.jpeg");
background-size: cover;
background-position: center;
border-radius: 15%;
}
/* Changing the font sizes to suitable ones */
.now-playing {
font-size: 1rem;
}
.track-name {
font-size: 3rem;
}
.display-text {
font-size: 3rem;
}
.track-artist {
font-size: 1.5rem;
}
/* Using flex with the row direction to
align items in a horizontal direction */
.buttons {
display: flex;
flex-direction: row;
align-items: center;
}
.playpause-track,
.prev-track,
.next-track {
padding: 25px;
opacity: 0.8;
/* Smoothly transition the opacity */
transition: opacity .2s;
}
/* Change the opacity when mouse is hovered */
.playpause-track:hover,
.prev-track:hover,
.next-track:hover {
opacity: 1.0;
}
/* Define the slider width so that it scales properly */
.slider_container {
width: 75%;
max-width: 400px;
display: flex;
justify-content: center;
align-items: center;
}
/* Modify the appearance of the slider */
.seek_slider, .volume_slider {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
height: 5px;
background: black;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
/* Modify the appearance of the slider thumb */
.seek_slider::-webkit-slider-thumb,
.volume_slider::-webkit-slider-thumb {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 15px;
height: 15px;
background: white;
cursor: pointer;
border-radius: 50%;
}
/* Change the opacity when mouse is hovered */
.seek_slider:hover,
.volume_slider:hover {
opacity: 1.0;
}
.seek_slider {
width: 60%;
}
.volume_slider {
width: 30%;
}
.current-time,
.total-duration {
padding: 10px;
}
i.fa-volume-down,
i.fa-volume-up {
padding: 10px;
}
/* Change the mouse cursor to a pointer
when hovered over */
i.fa-play-circle,
i.fa-pause-circle,
i.fa-step-forward,
i.fa-step-backward {
cursor: pointer;
}

46
demo/player/tracks.js Normal file
View File

@ -0,0 +1,46 @@
var track_list = [
{
display: "here we go with our demo!",
name: "Epic music",
artist: "Bensound epic",
image: "https://www.freepascal.org/~michael/pas2js-demos/player/epic.jpg",
path: "https://www.freepascal.org/~michael/pas2js-demos/player/bensound-epic.mp3",
},
{
display: "Now for something less hard...",
name: "Rumble rock",
artist: "Bensound rumble",
image: "https://www.freepascal.org/~michael/pas2js-demos/player/rumble.jpg",
path: "https://www.freepascal.org/~michael/pas2js-demos/player/bensound-rumble.mp3"
},
{
display: "We even have dubstep",
name: "Dubstep for the fans",
artist: "Bensound dubstep",
image: "https://www.freepascal.org/~michael/pas2js-demos/player/dubstep.jpg",
path: "https://www.freepascal.org/~michael/pas2js-demos/player/bensound-dubstep.mp3"
},
{
display: "We also have some pop tunes",
name: "Pop tune beyond the line",
artist: "Bensound pop tune ",
image: "https://www.freepascal.org/~michael/pas2js-demos/player/beyondtheline.jpg",
path: "https://www.freepascal.org/~michael/pas2js-demos/player/bensound-beyondtheline.mp3"
},
{
display: "Something soundtrack-like.",
name: "Once again",
artist: "Bensound once again",
image: "https://www.freepascal.org/~michael/pas2js-demos/player/onceagain.jpg",
path: "https://www.freepascal.org/~michael/pas2js-demos/player/bensound-onceagain.mp3",
},
{
display: "And going home with some jazzy tune!",
name: "Jazzy lounge",
artist: "Bensound the lounge",
image: "https://www.freepascal.org/~michael/pas2js-demos/player/thelounge.jpg",
path: "https://www.freepascal.org/~michael/pas2js-demos/player/bensound-thelounge.mp3",
}
];