ppsspp/UI/RemoteISOScreen.cpp

150 lines
4.5 KiB
C++
Raw Normal View History

// Copyright (c) 2014- PPSSPP Project.
// 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, version 2.0 or later versions.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "i18n/i18n.h"
#include "net/http_server.h"
#include "net/resolve.h"
#include "net/sinks.h"
#include "thread/thread.h"
#include "thread/threadutil.h"
#include "Common/Common.h"
#include "Common/FileUtil.h"
#include "Core/Config.h"
#include "UI/RemoteISOScreen.h"
using namespace UI;
enum class ServerStatus {
STOPPED,
STARTING,
RUNNING,
STOPPING,
};
static std::thread *serverThread = nullptr;
static ServerStatus serverStatus;
static recursive_mutex serverStatusLock;
static condition_variable serverStatusCond;
static void UpdateStatus(ServerStatus s) {
lock_guard guard(serverStatusLock);
serverStatus = s;
serverStatusCond.notify_one();
}
static ServerStatus RetrieveStatus() {
lock_guard guard(serverStatusLock);
return serverStatus;
}
static void ExecuteServer() {
setCurrentThreadName("HTTPServer");
net::Init();
auto http = new http::Server(new threading::SameThreadExecutor());
http->Listen(0);
// TODO: Report local IP and port.
UpdateStatus(ServerStatus::RUNNING);
while (RetrieveStatus() == ServerStatus::RUNNING) {
http->RunSlice(5.0);
}
net::Shutdown();
UpdateStatus(ServerStatus::STOPPED);
}
RemoteISOScreen::RemoteISOScreen() : serverRunning_(false) {
}
void RemoteISOScreen::update(InputState &input) {
UIScreenWithBackground::update(input);
bool nowRunning = RetrieveStatus() != ServerStatus::STOPPED;
if (serverRunning_ && !nowRunning) {
// Server stopped, delete the thread.
delete serverThread;
serverThread = nullptr;
}
if (serverRunning_ != nowRunning) {
RecreateViews();
}
serverRunning_ = nowRunning;
}
void RemoteISOScreen::CreateViews() {
I18NCategory *rp = GetI18NCategory("Reporting");
I18NCategory *di = GetI18NCategory("Dialog");
I18NCategory *sy = GetI18NCategory("System");
Margins actionMenuMargins(0, 20, 15, 0);
Margins contentMargins(0, 20, 5, 5);
ViewGroup *leftColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, FILL_PARENT, 0.4f, contentMargins));
LinearLayout *leftColumnItems = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(WRAP_CONTENT, FILL_PARENT));
ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins));
LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL);
leftColumnItems->Add(new TextView(sy->T("RemoteISOWifi", "Note: Connect both devices to the same wifi"), new LinearLayoutParams(Margins(12, 5, 0, 5))));
rightColumnItems->SetSpacing(0.0f);
rightColumnItems->Add(new Choice(rp->T("Browse Games")));
if (RetrieveStatus() != ServerStatus::STOPPED) {
rightColumnItems->Add(new Choice(rp->T("Stop Sharing")))->OnClick.Handle(this, &RemoteISOScreen::HandleStopServer);
} else {
rightColumnItems->Add(new Choice(rp->T("Share Games (Server)")))->OnClick.Handle(this, &RemoteISOScreen::HandleStartServer);
}
rightColumnItems->Add(new Spacer(25.0));
rightColumnItems->Add(new Choice(di->T("Back"), "", false, new AnchorLayoutParams(150, WRAP_CONTENT, 10, NONE, NONE, 10)))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
root_ = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f));
root_->Add(leftColumn);
root_->Add(rightColumn);
leftColumn->Add(leftColumnItems);
rightColumn->Add(rightColumnItems);
}
UI::EventReturn RemoteISOScreen::HandleStartServer(UI::EventParams &e) {
lock_guard guard(serverStatusLock);
if (serverStatus != ServerStatus::STOPPED) {
return EVENT_SKIPPED;
}
serverStatus = ServerStatus::STARTING;
serverThread = new std::thread(&ExecuteServer);
serverThread->detach();
return EVENT_DONE;
}
UI::EventReturn RemoteISOScreen::HandleStopServer(UI::EventParams &e) {
lock_guard guard(serverStatusLock);
if (serverStatus != ServerStatus::RUNNING) {
return EVENT_SKIPPED;
}
serverStatus = ServerStatus::STOPPING;
return EVENT_DONE;
}