Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UWebServer which serves the list of available songs on localhost,… #852

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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