From 1aac5c557700015054685eec36f727199ba9c06c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20B=C3=B6hning?=
<1497707+bohning@users.noreply.github.com>
Date: Mon, 27 May 2024 21:50:54 +0200
Subject: [PATCH] Add UWebServer which serves the list of available songs on
localhost, port 8091.
---
Makefile.in | 1 +
game/resources/songlist_template.html | 88 ++++++++++
src/base/UMain.pas | 18 +-
src/base/UWebServer.pas | 149 ++++++++++++++++
src/ultrastardx-unix.lpi | 242 ++++++++++++++++++++++----
src/ultrastardx.dpr | 2 +
6 files changed, 463 insertions(+), 37 deletions(-)
create mode 100644 game/resources/songlist_template.html
create mode 100644 src/base/UWebServer.pas
diff --git a/Makefile.in b/Makefile.in
index f40b28dc6..bb8ae34e2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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)/
diff --git a/game/resources/songlist_template.html b/game/resources/songlist_template.html
new file mode 100644
index 000000000..10a0df268
--- /dev/null
+++ b/game/resources/songlist_template.html
@@ -0,0 +1,88 @@
+
+
+
+
+ Song List
+
+
+
+
+
Song List
+
+
+
+
Artist
+
Title
+
Edition
+
Genre
+
Year
+
+
+
+
+
diff --git a/src/base/UMain.pas b/src/base/UMain.pas
index 08ea4aae0..e9df5df96 100644
--- a/src/base/UMain.pas
+++ b/src/base/UMain.pas
@@ -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
@@ -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
//------------------------------
@@ -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;
diff --git a/src/base/UWebServer.pas b/src/base/UWebServer.pas
new file mode 100644
index 000000000..95564d1d0
--- /dev/null
+++ b/src/base/UWebServer.pas
@@ -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 := '
Method Not Allowed
';
+ 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 + '