Skip to content

Commit

Permalink
Add UWebServer which serves the list of available songs on localhost,…
Browse files Browse the repository at this point in the history
… port 8091.
  • Loading branch information
bohning committed May 27, 2024
1 parent 80adde2 commit 1aac5c5
Show file tree
Hide file tree
Showing 6 changed files with 463 additions and 37 deletions.
1 change: 1 addition & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ macosx-app: all
# Must be done BEFORE info.plist is created.
$(MKDIR) $(macosx_bundle_path)/resources
$(INSTALL_DATA) icons/ultrastardx.icns $(macosx_bundle_path)/resources/
$(INSTALL_DATA) game/resources/songlist_template.html $(macosx_bundle_path)/resources/

# the info.plist file
$(INSTALL_DATA) $(USDX_SRC_DIR)/macosx/Info.plist $(macosx_bundle_path)/
Expand Down
88 changes: 88 additions & 0 deletions game/resources/songlist_template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Song List</title>
<style>
body { font-family: Arial, sans-serif; background-color: #f0f8ff; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
th { background-color: #add8e6; cursor: pointer; }
tr:hover { background-color: #d1e7f3; }
input { margin-bottom: 12px; padding: 8px; width: 100%; }
</style>
<script>
function filterSongs() {
var input, filter, table, tr, td, i, j, txtValue;
input = document.getElementById("songFilter");
filter = input.value.toUpperCase();
table = document.getElementById("songTable");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
tr[i].style.display = "none";
td = tr[i].getElementsByTagName("td");
for (j = 0; j < td.length; j++) {
if (td[j]) {
txtValue = td[j].textContent || td[j].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
break;
}
}
}
}
}

function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("songTable");
switching = true;
dir = "asc";
while (switching) {
switching = false;
rows = table.rows;
for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i+1].getElementsByTagName("TD")[n];
if (dir == "asc") {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
} else if (dir == "desc") {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
switchcount ++;
} else {
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}
}
}
}
</script>
</head>
<body>
<h1>Song List</h1>
<input type="text" id="songFilter" onkeyup="filterSongs()" placeholder="Search for songs...">
<table id="songTable">
<tr>
<th onclick="sortTable(0)">Artist</th>
<th onclick="sortTable(1)">Title</th>
<th onclick="sortTable(2)">Edition</th>
<th onclick="sortTable(3)">Genre</th>
<th onclick="sortTable(4)">Year</th>
</tr>
<!--SONG_ROWS-->
</table>
</body>
</html>
18 changes: 17 additions & 1 deletion src/base/UMain.pas
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,16 @@ implementation
ULuaParty,
ULuaScreenSing,
UTime,
UWebcam;
UWebcam,
UWebServer;
//UVideoAcinerella;

procedure Main;
var
WindowTitle: string;
BadPlayer: integer;
Server: TWebServer;

begin
{$IFNDEF Debug}
try
Expand Down Expand Up @@ -262,6 +265,14 @@ procedure Main;
Display.CurrentScreen^.FadeTo( @ScreenOptionsRecord );
end;

//------------------------------
// Start Webserver
//------------------------------
Log.LogStatus('Webserver', 'Initialization');
// Create and start the web server
Server := TWebServer.Create(8091);
Server.Start;

//------------------------------
// Start Mainloop
//------------------------------
Expand Down Expand Up @@ -296,6 +307,11 @@ procedure Main;
Log.LogStatus('Finalize SDL', 'Finalization');
SDL_Quit();

Log.LogStatus('Finalize Webserver', 'Finalization');
//Server.Terminate; // Terminate the thread
//Server.WaitFor;
//Server.Free;

Log.LogStatus('Finalize Log', 'Finalization');
{$IFNDEF Debug}
end;
Expand Down
149 changes: 149 additions & 0 deletions src/base/UWebServer.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
{* UltraStar Deluxe - Karaoke Game
*
* UltraStar Deluxe is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*}

unit UWebServer;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, fphttpserver, HTTPDefs, USongs, USong, UPlatform, UPath;

type
TWebServer = class(TThread)
private
FServer: TFPHTTPServer;
FPort: Integer;
protected
procedure Execute; override;
procedure HandleRequest(Sender: TObject; var ARequest: TFPHTTPConnectionRequest;
var AResponse: TFPHTTPConnectionResponse);
function GenerateHTMLWithSongs: string;
function LoadTemplate: string;
public
constructor Create(APort: Integer);
destructor Destroy; override;
end;

implementation

constructor TWebServer.Create(APort: Integer);
begin
inherited Create(True); // Create suspended
FPort := APort;
FreeOnTerminate := True;
end;

destructor TWebServer.Destroy;
begin
inherited Destroy;
end;

procedure TWebServer.Execute;
begin
FServer := TFPHTTPServer.Create(nil);
try
FServer.OnRequest := @HandleRequest;
FServer.Port := FPort;
FServer.Active := True;
WriteLn('Server is running on port ', FPort);
while not Terminated do
Sleep(100);
finally
FServer.Free;
end;
end;

procedure TWebServer.HandleRequest(Sender: TObject; var ARequest: TFPHTTPConnectionRequest;
var AResponse: TFPHTTPConnectionResponse);
var
ResponseHTML: string;
begin
if ARequest.Method = 'GET' then
begin
// Serve the HTML page with the list of songs
AResponse.ContentType := 'text/html; charset=UTF-8';
ResponseHTML := GenerateHTMLWithSongs;
AResponse.Content := ResponseHTML;
AResponse.Code := 200;
end
else
begin
// Method not allowed
AResponse.Content := '<h1>Method Not Allowed</h1>';
AResponse.ContentType := 'text/html; charset=UTF-8';
AResponse.Code := 405;
end;
end;

function TWebServer.LoadTemplate: string;
var
TemplateFilePath: IPath;
TemplateFile: TStringList;
begin
TemplateFile := TStringList.Create;
try
TemplateFilePath := Platform.GetGameUserPath.Append('resources\songlist_template.html');
TemplateFile.LoadFromFile(TemplateFilePath.toNative);
Result := TemplateFile.Text;
finally
TemplateFile.Free;
end;
end;

function TWebServer.GenerateHTMLWithSongs: string;
var
I: Integer;
SongRows: string;
Edition, Genre, Year: string;
begin
SongRows := '';
for I := 0 to Songs.SongList.Count - 1 do
begin
Edition := UTF8Encode(TSong(Songs.SongList[I]).Edition);
Genre := UTF8Encode(TSong(Songs.SongList[I]).Genre);
Year := IntToStr(TSong(Songs.SongList[I]).Year);

if Edition = 'Unknown' then
Edition := '';
if Genre = 'Unknown' then
Genre := '';
if Year = '0' then
Year := '';

SongRows := SongRows + '<tr>' + sLineBreak +
'<td>' + UTF8Encode(TSong(Songs.SongList[I]).Artist) + '</td>' + sLineBreak +
'<td>' + UTF8Encode(TSong(Songs.SongList[I]).Title) + '</td>' + sLineBreak +
'<td>' + Edition + '</td>' + sLineBreak +
'<td>' + Genre + '</td>' + sLineBreak +
'<td>' + Year + '</td>' + sLineBreak +
'</tr>' + sLineBreak;
end;

Result := LoadTemplate;
Result := StringReplace(Result, '<!--SONG_ROWS-->', SongRows, []);
end;

end.

Loading

0 comments on commit 1aac5c5

Please sign in to comment.