2016-07-03 17:24:33 +00:00
// 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/.
2017-02-27 19:51:36 +00:00
# include <algorithm>
# include <thread>
2017-12-20 09:22:15 +00:00
# include <mutex>
2017-02-27 19:51:36 +00:00
2016-07-04 00:38:29 +00:00
# include "base/timeutil.h"
# include "i18n/i18n.h"
2018-04-15 18:24:10 +00:00
# include "json/json_reader.h"
2016-07-03 19:38:55 +00:00
# include "net/http_client.h"
2016-07-03 17:24:33 +00:00
# include "net/resolve.h"
# include "Common/Common.h"
# include "Core/Config.h"
2018-04-21 20:51:18 +00:00
# include "Core/WebServer.h"
2016-07-03 17:24:33 +00:00
# include "UI/RemoteISOScreen.h"
using namespace UI ;
2016-07-04 00:38:29 +00:00
static const char * REPORT_HOSTNAME = " report.ppsspp.org " ;
static const int REPORT_PORT = 80 ;
2016-07-04 14:32:49 +00:00
static bool scanCancelled = false ;
2017-03-22 07:00:52 +00:00
static bool scanAborted = false ;
2016-07-04 14:32:49 +00:00
2016-07-04 03:48:27 +00:00
static bool FindServer ( std : : string & resultHost , int & resultPort ) {
2016-07-04 00:38:29 +00:00
http : : Client http ;
Buffer result ;
int code = 500 ;
2017-03-22 07:00:52 +00:00
auto TryServer = [ & ] ( const std : : string & host , int port ) {
// Don't wait as long for a connect - we need a good connection for smooth streaming anyway.
// This way if it's down, we'll find the right one faster.
if ( http . Resolve ( host . c_str ( ) , port ) & & http . Connect ( 1 , 10.0 , & scanCancelled ) ) {
http . Disconnect ( ) ;
resultHost = host ;
resultPort = port ;
return true ;
}
return false ;
} ;
2017-02-14 02:18:14 +00:00
// Try last server first, if it is set
2017-03-22 07:00:52 +00:00
if ( g_Config . iLastRemoteISOPort & & g_Config . sLastRemoteISOServer ! = " " ) {
if ( TryServer ( g_Config . sLastRemoteISOServer . c_str ( ) , g_Config . iLastRemoteISOPort ) ) {
return true ;
}
2017-02-14 02:18:14 +00:00
}
2017-03-22 07:06:02 +00:00
// Don't scan if in manual mode.
if ( g_Config . bRemoteISOManual | | scanCancelled ) {
2017-03-06 04:26:53 +00:00
return false ;
}
2016-07-04 00:38:29 +00:00
2017-03-06 04:26:53 +00:00
// Start by requesting a list of recent local ips for this network.
if ( http . Resolve ( REPORT_HOSTNAME , REPORT_PORT ) ) {
2017-03-22 07:00:52 +00:00
if ( http . Connect ( 2 , 20.0 , & scanCancelled ) ) {
2017-03-06 04:26:53 +00:00
code = http . GET ( " /match/list " , & result ) ;
http . Disconnect ( ) ;
2017-02-22 01:45:58 +00:00
}
2017-03-06 04:26:53 +00:00
}
if ( code ! = 200 | | scanCancelled ) {
return false ;
}
2016-07-04 00:38:29 +00:00
2017-03-06 04:26:53 +00:00
std : : string json ;
result . TakeAll ( & json ) ;
2016-07-04 00:38:29 +00:00
2018-08-12 22:05:00 +00:00
using namespace json ;
2017-03-06 04:26:53 +00:00
JsonReader reader ( json . c_str ( ) , json . size ( ) ) ;
if ( ! reader . ok ( ) ) {
return false ;
}
2016-07-04 00:38:29 +00:00
2018-04-15 18:24:10 +00:00
const JsonValue entries = reader . rootArray ( ) ;
if ( entries . getTag ( ) ! = JSON_ARRAY ) {
2017-03-06 04:26:53 +00:00
return false ;
}
2016-07-04 00:38:29 +00:00
2017-03-06 04:26:53 +00:00
std : : vector < std : : string > servers ;
2018-04-15 18:24:10 +00:00
for ( const auto pentry : entries ) {
JsonGet entry = pentry - > value ;
if ( scanCancelled )
return false ;
const char * host = entry . getString ( " ip " , " " ) ;
int port = entry . getInt ( " p " , 0 ) ;
2017-03-06 04:26:53 +00:00
char url [ 1024 ] = { } ;
snprintf ( url , sizeof ( url ) , " http://%s:%d " , host , port ) ;
servers . push_back ( url ) ;
2016-07-04 00:38:29 +00:00
2017-03-22 07:00:52 +00:00
if ( TryServer ( host , port ) ) {
2017-03-06 04:26:53 +00:00
return true ;
2016-07-04 00:38:29 +00:00
}
}
2017-03-06 04:26:53 +00:00
2016-07-04 00:38:29 +00:00
// None of the local IPs were reachable.
2016-07-04 03:48:27 +00:00
return false ;
}
static bool LoadGameList ( const std : : string & host , int port , std : : vector < std : : string > & games ) {
http : : Client http ;
Buffer result ;
int code = 500 ;
2017-03-11 05:23:49 +00:00
std : : vector < std : : string > responseHeaders ;
2017-02-22 01:45:58 +00:00
std : : string subdir = " / " ;
2017-03-10 04:51:44 +00:00
size_t offset ;
2017-02-22 01:45:58 +00:00
if ( g_Config . bRemoteISOManual ) {
subdir = g_Config . sRemoteISOSubdir ;
2017-03-10 04:51:44 +00:00
offset = subdir . find_last_of ( " / " ) ;
2017-03-11 06:53:16 +00:00
if ( offset ! = subdir . length ( ) - 1 & & offset ! = subdir . npos ) {
2017-03-10 04:51:44 +00:00
//truncate everything after last /
subdir . erase ( offset + 1 ) ;
}
2017-02-22 01:45:58 +00:00
}
2016-07-04 03:48:27 +00:00
2017-02-22 01:45:58 +00:00
// Start by requesting the list of games from the server.
2016-07-04 03:48:27 +00:00
if ( http . Resolve ( host . c_str ( ) , port ) ) {
2017-03-22 07:00:52 +00:00
if ( http . Connect ( 2 , 20.0 , & scanCancelled ) ) {
2017-03-11 06:53:16 +00:00
code = http . GET ( subdir . c_str ( ) , & result , responseHeaders ) ;
2016-07-04 14:34:40 +00:00
http . Disconnect ( ) ;
}
2016-07-04 03:48:27 +00:00
}
2016-07-04 14:32:49 +00:00
if ( code ! = 200 | | scanCancelled ) {
2016-07-04 03:48:27 +00:00
return false ;
}
std : : string listing ;
std : : vector < std : : string > items ;
result . TakeAll ( & listing ) ;
2017-03-12 06:15:40 +00:00
std : : string contentType ;
for ( const std : : string & header : responseHeaders ) {
if ( startsWithNoCase ( header , " Content-Type: " ) ) {
contentType = header . substr ( strlen ( " Content-Type: " ) ) ;
// Strip any whitespace (TODO: maybe move this to stringutil?)
contentType . erase ( 0 , contentType . find_first_not_of ( " \t \r \n " ) ) ;
contentType . erase ( contentType . find_last_not_of ( " \t \r \n " ) + 1 ) ;
}
}
// TODO: Technically, "TExt/hTml ; chaRSet = Utf8" should pass, but "text/htmlese" should not.
// But unlikely that'll be an issue.
bool parseHtml = startsWithNoCase ( contentType , " text/html " ) ;
bool parseText = startsWithNoCase ( contentType , " text/plain " ) ;
if ( parseText ) {
2017-03-11 05:23:49 +00:00
//ppsspp server
SplitString ( listing , ' \n ' , items ) ;
for ( const std : : string & item : items ) {
if ( ! endsWithNoCase ( item , " .cso " ) & & ! endsWithNoCase ( item , " .iso " ) & & ! endsWithNoCase ( item , " .pbp " ) ) {
continue ;
}
char temp [ 1024 ] = { } ;
snprintf ( temp , sizeof ( temp ) - 1 , " http://%s:%d%s " , host . c_str ( ) , port , item . c_str ( ) ) ;
games . push_back ( temp ) ;
2016-07-04 03:48:27 +00:00
}
2017-03-12 06:15:40 +00:00
} else if ( parseHtml ) {
2017-03-11 05:23:49 +00:00
//other webserver
2017-03-06 04:26:53 +00:00
GetQuotedStrings ( listing , items ) ;
2017-03-11 05:23:49 +00:00
for ( const std : : string & item : items ) {
if ( ! endsWithNoCase ( item , " .cso " ) & & ! endsWithNoCase ( item , " .iso " ) & & ! endsWithNoCase ( item , " .pbp " ) ) {
continue ;
}
2016-07-04 03:48:27 +00:00
2017-03-11 05:23:49 +00:00
char temp [ 1024 ] = { } ;
2017-02-22 01:45:58 +00:00
snprintf ( temp , sizeof ( temp ) - 1 , " http://%s:%d%s%s " , host . c_str ( ) , port , subdir . c_str ( ) , item . c_str ( ) ) ;
2017-03-11 05:23:49 +00:00
games . push_back ( temp ) ;
}
2017-03-12 06:15:40 +00:00
} else {
ERROR_LOG ( FILESYS , " Unsupported Content-Type: %s " , contentType . c_str ( ) ) ;
return false ;
2016-07-04 03:48:27 +00:00
}
2017-03-12 06:15:40 +00:00
2017-02-22 01:45:58 +00:00
//save for next time unless manual is true
if ( ! games . empty ( ) & & ! g_Config . bRemoteISOManual ) {
2017-02-14 02:18:14 +00:00
g_Config . sLastRemoteISOServer = host ;
g_Config . iLastRemoteISOPort = port ;
}
2016-07-04 03:48:27 +00:00
return ! games . empty ( ) ;
2016-07-04 00:38:29 +00:00
}
2016-07-03 18:41:27 +00:00
RemoteISOScreen : : RemoteISOScreen ( ) : serverRunning_ ( false ) , serverStopping_ ( false ) {
2016-07-03 17:43:35 +00:00
}
2017-03-15 05:01:18 +00:00
void RemoteISOScreen : : update ( ) {
UIScreenWithBackground : : update ( ) ;
2016-07-03 17:43:35 +00:00
2018-04-21 20:51:18 +00:00
bool nowRunning = ! WebServerStopped ( WebServerFlags : : DISCS ) ;
2016-07-03 18:41:27 +00:00
if ( serverStopping_ & & ! nowRunning ) {
serverStopping_ = false ;
2016-07-03 17:43:35 +00:00
}
2016-07-03 18:41:27 +00:00
2016-07-03 17:43:35 +00:00
if ( serverRunning_ ! = nowRunning ) {
RecreateViews ( ) ;
}
serverRunning_ = nowRunning ;
2016-07-03 17:24:33 +00:00
}
void RemoteISOScreen : : CreateViews ( ) {
I18NCategory * di = GetI18NCategory ( " Dialog " ) ;
2017-08-16 21:39:30 +00:00
I18NCategory * ri = GetI18NCategory ( " RemoteISO " ) ;
2016-07-03 17:24:33 +00:00
Margins actionMenuMargins ( 0 , 20 , 15 , 0 ) ;
Margins contentMargins ( 0 , 20 , 5 , 5 ) ;
2017-03-22 07:03:45 +00:00
ViewGroup * leftColumn = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , FILL_PARENT , 0.4f , contentMargins ) ) ;
2016-07-03 17:24:33 +00:00
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 ) ;
2017-08-16 21:39:30 +00:00
leftColumnItems - > Add ( new TextView ( ri - > T ( " RemoteISODesc " , " Games in your recent list will be shared " ) , new LinearLayoutParams ( Margins ( 12 , 5 , 0 , 5 ) ) ) ) ;
leftColumnItems - > Add ( new TextView ( ri - > T ( " RemoteISOWifi " , " Note: Connect both devices to the same wifi " ) , new LinearLayoutParams ( Margins ( 12 , 5 , 0 , 5 ) ) ) ) ;
2016-07-03 17:24:33 +00:00
rightColumnItems - > SetSpacing ( 0.0f ) ;
2017-08-16 21:39:30 +00:00
Choice * browseChoice = new Choice ( ri - > T ( " Browse Games " ) ) ;
2016-07-04 03:46:06 +00:00
rightColumnItems - > Add ( browseChoice ) - > OnClick . Handle ( this , & RemoteISOScreen : : HandleBrowse ) ;
2018-04-21 20:51:18 +00:00
if ( WebServerStopping ( WebServerFlags : : DISCS ) ) {
2017-08-16 21:39:30 +00:00
rightColumnItems - > Add ( new Choice ( ri - > T ( " Stopping.. " ) ) ) - > SetDisabledPtr ( & serverStopping_ ) ;
2016-07-04 03:46:06 +00:00
browseChoice - > SetEnabled ( false ) ;
2018-04-21 20:51:18 +00:00
} else if ( ! WebServerStopped ( WebServerFlags : : DISCS ) ) {
2017-08-16 21:39:30 +00:00
rightColumnItems - > Add ( new Choice ( ri - > T ( " Stop Sharing " ) ) ) - > OnClick . Handle ( this , & RemoteISOScreen : : HandleStopServer ) ;
2016-07-04 03:46:06 +00:00
browseChoice - > SetEnabled ( false ) ;
2016-07-03 17:24:33 +00:00
} else {
2017-08-16 21:39:30 +00:00
rightColumnItems - > Add ( new Choice ( ri - > T ( " Share Games (Server) " ) ) ) - > OnClick . Handle ( this , & RemoteISOScreen : : HandleStartServer ) ;
2016-07-04 03:46:06 +00:00
browseChoice - > SetEnabled ( true ) ;
2016-07-03 17:24:33 +00:00
}
2017-08-16 21:39:30 +00:00
Choice * settingsChoice = new Choice ( ri - > T ( " Settings " ) ) ;
2017-03-11 04:05:56 +00:00
rightColumnItems - > Add ( settingsChoice ) - > OnClick . Handle ( this , & RemoteISOScreen : : HandleSettings ) ;
2016-07-03 17:24:33 +00:00
2017-03-22 07:03:45 +00:00
LinearLayout * beforeBack = new LinearLayout ( ORIENT_HORIZONTAL , new AnchorLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
beforeBack - > Add ( leftColumn ) ;
beforeBack - > Add ( rightColumn ) ;
root_ = new AnchorLayout ( new LayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
root_ - > Add ( beforeBack ) ;
root_ - > Add ( new Choice ( di - > T ( " Back " ) , " " , false , new AnchorLayoutParams ( 150 , WRAP_CONTENT , 10 , NONE , NONE , 10 ) ) ) - > OnClick . Handle < UIScreen > ( this , & UIScreen : : OnBack ) ;
2016-07-03 17:24:33 +00:00
leftColumn - > Add ( leftColumnItems ) ;
rightColumn - > Add ( rightColumnItems ) ;
}
UI : : EventReturn RemoteISOScreen : : HandleStartServer ( UI : : EventParams & e ) {
2018-04-21 20:51:18 +00:00
if ( ! StartWebServer ( WebServerFlags : : DISCS ) ) {
2016-07-03 17:24:33 +00:00
return EVENT_SKIPPED ;
}
return EVENT_DONE ;
}
UI : : EventReturn RemoteISOScreen : : HandleStopServer ( UI : : EventParams & e ) {
2018-04-21 20:51:18 +00:00
if ( ! StopWebServer ( WebServerFlags : : DISCS ) ) {
2016-07-03 17:24:33 +00:00
return EVENT_SKIPPED ;
}
2016-07-03 18:41:27 +00:00
serverStopping_ = true ;
RecreateViews ( ) ;
2016-07-03 17:24:33 +00:00
return EVENT_DONE ;
}
2016-07-04 00:38:29 +00:00
UI : : EventReturn RemoteISOScreen : : HandleBrowse ( UI : : EventParams & e ) {
screenManager ( ) - > push ( new RemoteISOConnectScreen ( ) ) ;
return EVENT_DONE ;
}
2017-03-11 04:05:56 +00:00
UI : : EventReturn RemoteISOScreen : : HandleSettings ( UI : : EventParams & e ) {
screenManager ( ) - > push ( new RemoteISOSettingsScreen ( ) ) ;
return EVENT_DONE ;
}
2016-07-04 03:48:27 +00:00
RemoteISOConnectScreen : : RemoteISOConnectScreen ( ) : status_ ( ScanStatus : : SCANNING ) , nextRetry_ ( 0.0 ) {
2016-07-04 14:32:49 +00:00
scanCancelled = false ;
2017-03-22 07:00:52 +00:00
scanAborted = false ;
2016-07-04 00:38:29 +00:00
scanThread_ = new std : : thread ( [ ] ( RemoteISOConnectScreen * thiz ) {
thiz - > ExecuteScan ( ) ;
} , this ) ;
scanThread_ - > detach ( ) ;
}
RemoteISOConnectScreen : : ~ RemoteISOConnectScreen ( ) {
2016-07-04 14:32:49 +00:00
int maxWait = 5000 ;
scanCancelled = true ;
2016-07-04 03:48:27 +00:00
while ( GetStatus ( ) = = ScanStatus : : SCANNING | | GetStatus ( ) = = ScanStatus : : LOADING ) {
2016-07-04 00:38:29 +00:00
sleep_ms ( 1 ) ;
2016-07-04 14:32:49 +00:00
if ( - - maxWait < 0 ) {
// If it does ever wake up, it may crash... but better than hanging?
2017-03-22 07:00:52 +00:00
scanAborted = true ;
2016-07-04 14:32:49 +00:00
break ;
}
2016-07-04 00:38:29 +00:00
}
delete scanThread_ ;
}
void RemoteISOConnectScreen : : CreateViews ( ) {
2017-08-14 10:08:03 +00:00
I18NCategory * di = GetI18NCategory ( " Dialog " ) ;
2017-08-16 21:39:30 +00:00
I18NCategory * ri = GetI18NCategory ( " RemoteISO " ) ;
2016-07-04 00:38:29 +00:00
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 ) ;
2017-08-16 21:39:30 +00:00
statusView_ = leftColumnItems - > Add ( new TextView ( ri - > T ( " RemoteISOScanning " , " Scanning... click Share Games on your desktop " ) , new LinearLayoutParams ( Margins ( 12 , 5 , 0 , 5 ) ) ) ) ;
2016-07-04 00:38:29 +00:00
rightColumnItems - > SetSpacing ( 0.0f ) ;
2017-08-14 10:08:03 +00:00
rightColumnItems - > Add ( new Choice ( di - > T ( " Cancel " ) , " " , false , new AnchorLayoutParams ( 150 , WRAP_CONTENT , 10 , NONE , NONE , 10 ) ) ) - > OnClick . Handle < UIScreen > ( this , & UIScreen : : OnBack ) ;
2016-07-04 00:38:29 +00:00
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 ) ;
}
2017-03-15 05:01:18 +00:00
void RemoteISOConnectScreen : : update ( ) {
2017-08-16 21:39:30 +00:00
I18NCategory * ri = GetI18NCategory ( " RemoteISO " ) ;
2016-07-04 03:48:27 +00:00
2017-03-15 05:01:18 +00:00
UIScreenWithBackground : : update ( ) ;
2016-07-04 00:38:29 +00:00
2016-07-04 03:48:27 +00:00
ScanStatus s = GetStatus ( ) ;
switch ( s ) {
case ScanStatus : : SCANNING :
case ScanStatus : : LOADING :
break ;
case ScanStatus : : FOUND :
2017-08-16 21:39:30 +00:00
statusView_ - > SetText ( ri - > T ( " RemoteISOLoading " , " Connected - loading game list " ) ) ;
2016-07-04 03:48:27 +00:00
status_ = ScanStatus : : LOADING ;
// Let's reuse scanThread_.
delete scanThread_ ;
scanThread_ = new std : : thread ( [ ] ( RemoteISOConnectScreen * thiz ) {
thiz - > ExecuteLoad ( ) ;
} , this ) ;
scanThread_ - > detach ( ) ;
break ;
case ScanStatus : : FAILED :
nextRetry_ = real_time_now ( ) + 30.0 ;
status_ = ScanStatus : : RETRY_SCAN ;
break ;
case ScanStatus : : RETRY_SCAN :
if ( nextRetry_ < real_time_now ( ) ) {
status_ = ScanStatus : : SCANNING ;
2016-07-04 00:38:29 +00:00
nextRetry_ = 0.0 ;
delete scanThread_ ;
scanThread_ = new std : : thread ( [ ] ( RemoteISOConnectScreen * thiz ) {
thiz - > ExecuteScan ( ) ;
} , this ) ;
scanThread_ - > detach ( ) ;
}
2016-07-04 03:48:27 +00:00
break ;
case ScanStatus : : LOADED :
2017-03-20 00:43:03 +00:00
TriggerFinish ( DR_OK ) ;
2016-07-04 03:48:27 +00:00
screenManager ( ) - > push ( new RemoteISOBrowseScreen ( games_ ) ) ;
break ;
2016-07-04 00:38:29 +00:00
}
}
void RemoteISOConnectScreen : : ExecuteScan ( ) {
2016-07-04 03:48:27 +00:00
FindServer ( host_ , port_ ) ;
2017-03-22 07:00:52 +00:00
if ( scanAborted ) {
2016-07-04 14:32:49 +00:00
return ;
}
2016-07-04 00:38:29 +00:00
2017-02-27 20:57:46 +00:00
std : : lock_guard < std : : mutex > guard ( statusLock_ ) ;
2016-07-04 03:48:27 +00:00
status_ = host_ . empty ( ) ? ScanStatus : : FAILED : ScanStatus : : FOUND ;
2016-07-04 00:38:29 +00:00
}
2016-07-04 03:48:27 +00:00
ScanStatus RemoteISOConnectScreen : : GetStatus ( ) {
2017-02-27 20:57:46 +00:00
std : : lock_guard < std : : mutex > guard ( statusLock_ ) ;
2016-07-04 03:48:27 +00:00
return status_ ;
2016-07-04 00:38:29 +00:00
}
2016-07-04 03:48:27 +00:00
void RemoteISOConnectScreen : : ExecuteLoad ( ) {
bool result = LoadGameList ( host_ , port_ , games_ ) ;
2017-03-22 07:00:52 +00:00
if ( scanAborted ) {
2016-07-04 14:32:49 +00:00
return ;
}
2016-07-04 03:48:27 +00:00
2017-02-27 20:57:46 +00:00
std : : lock_guard < std : : mutex > guard ( statusLock_ ) ;
2016-07-04 03:48:27 +00:00
status_ = result ? ScanStatus : : LOADED : ScanStatus : : FAILED ;
2016-07-04 00:38:29 +00:00
}
2016-07-04 03:48:27 +00:00
class RemoteGameBrowser : public GameBrowser {
public :
RemoteGameBrowser ( const std : : vector < std : : string > & games , bool allowBrowsing , bool * gridStyle_ , std : : string lastText , std : : string lastLink , int flags = 0 , UI : : LayoutParams * layoutParams = 0 )
: GameBrowser ( " !REMOTE " , allowBrowsing , gridStyle_ , lastText , lastLink , flags , layoutParams ) {
games_ = games ;
Refresh ( ) ;
}
protected :
bool DisplayTopBar ( ) override {
return false ;
}
bool HasSpecialFiles ( std : : vector < std : : string > & filenames ) override ;
std : : vector < std : : string > games_ ;
} ;
bool RemoteGameBrowser : : HasSpecialFiles ( std : : vector < std : : string > & filenames ) {
filenames = games_ ;
return true ;
}
RemoteISOBrowseScreen : : RemoteISOBrowseScreen ( const std : : vector < std : : string > & games ) : games_ ( games ) {
2016-07-04 00:38:29 +00:00
}
void RemoteISOBrowseScreen : : CreateViews ( ) {
2016-07-04 03:48:27 +00:00
bool vertical = UseVerticalLayout ( ) ;
I18NCategory * di = GetI18NCategory ( " Dialog " ) ;
2017-08-16 21:39:30 +00:00
I18NCategory * ri = GetI18NCategory ( " RemoteISO " ) ;
2016-07-04 03:48:27 +00:00
Margins actionMenuMargins ( 0 , 10 , 10 , 0 ) ;
TabHolder * leftColumn = new TabHolder ( ORIENT_HORIZONTAL , 64 , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
tabHolder_ = leftColumn ;
tabHolder_ - > SetTag ( " RemoteGames " ) ;
gameBrowsers_ . clear ( ) ;
leftColumn - > SetClip ( true ) ;
ScrollView * scrollRecentGames = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
scrollRecentGames - > SetTag ( " RemoteGamesTab " ) ;
RemoteGameBrowser * tabRemoteGames = new RemoteGameBrowser (
games_ , false , & g_Config . bGridView1 , " " , " " , 0 ,
new LinearLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
scrollRecentGames - > Add ( tabRemoteGames ) ;
gameBrowsers_ . push_back ( tabRemoteGames ) ;
2017-08-16 21:39:30 +00:00
leftColumn - > AddTab ( ri - > T ( " Remote Server " ) , scrollRecentGames ) ;
2016-07-04 03:48:27 +00:00
tabRemoteGames - > OnChoice . Handle < MainScreen > ( this , & MainScreen : : OnGameSelectedInstant ) ;
tabRemoteGames - > OnHoldChoice . Handle < MainScreen > ( this , & MainScreen : : OnGameSelected ) ;
tabRemoteGames - > OnHighlight . Handle < MainScreen > ( this , & MainScreen : : OnGameHighlight ) ;
ViewGroup * rightColumn = new ScrollView ( ORIENT_VERTICAL ) ;
LinearLayout * rightColumnItems = new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
rightColumnItems - > SetSpacing ( 0.0f ) ;
rightColumn - > Add ( rightColumnItems ) ;
rightColumnItems - > Add ( new Choice ( di - > T ( " Back " ) , " " , false , new AnchorLayoutParams ( 150 , WRAP_CONTENT , 10 , NONE , NONE , 10 ) ) ) - > OnClick . Handle < UIScreen > ( this , & UIScreen : : OnBack ) ;
if ( vertical ) {
root_ = new LinearLayout ( ORIENT_VERTICAL ) ;
rightColumn - > ReplaceLayoutParams ( new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
leftColumn - > ReplaceLayoutParams ( new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT , 1.0 ) ) ;
root_ - > Add ( rightColumn ) ;
root_ - > Add ( leftColumn ) ;
} else {
root_ = new LinearLayout ( ORIENT_HORIZONTAL ) ;
leftColumn - > ReplaceLayoutParams ( new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT , 1.0 ) ) ;
rightColumn - > ReplaceLayoutParams ( new LinearLayoutParams ( 300 , FILL_PARENT , actionMenuMargins ) ) ;
root_ - > Add ( leftColumn ) ;
root_ - > Add ( rightColumn ) ;
}
root_ - > SetDefaultFocusView ( tabHolder_ ) ;
upgradeBar_ = 0 ;
2016-07-04 00:38:29 +00:00
}
2017-03-11 04:05:56 +00:00
2017-03-22 07:03:45 +00:00
RemoteISOSettingsScreen : : RemoteISOSettingsScreen ( ) {
2018-04-21 20:51:18 +00:00
serverRunning_ = ! WebServerStopped ( WebServerFlags : : DISCS ) ;
2017-03-22 07:03:45 +00:00
}
void RemoteISOSettingsScreen : : update ( ) {
UIDialogScreenWithBackground : : update ( ) ;
2018-04-21 20:51:18 +00:00
bool nowRunning = ! WebServerStopped ( WebServerFlags : : DISCS ) ;
2017-03-22 07:03:45 +00:00
if ( serverRunning_ ! = nowRunning ) {
RecreateViews ( ) ;
}
serverRunning_ = nowRunning ;
}
2017-03-11 04:05:56 +00:00
void RemoteISOSettingsScreen : : CreateViews ( ) {
2017-08-16 21:39:30 +00:00
I18NCategory * ri = GetI18NCategory ( " RemoteISO " ) ;
2017-03-11 04:05:56 +00:00
2017-03-22 07:03:45 +00:00
ViewGroup * remoteisoSettingsScroll = new ScrollView ( ORIENT_VERTICAL , new LayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
remoteisoSettingsScroll - > SetTag ( " RemoteISOSettings " ) ;
2017-03-11 04:05:56 +00:00
LinearLayout * remoteisoSettings = new LinearLayout ( ORIENT_VERTICAL ) ;
remoteisoSettings - > SetSpacing ( 0 ) ;
remoteisoSettingsScroll - > Add ( remoteisoSettings ) ;
2017-08-16 21:39:30 +00:00
remoteisoSettings - > Add ( new ItemHeader ( ri - > T ( " Remote disc streaming " ) ) ) ;
2017-12-11 02:30:28 +00:00
remoteisoSettings - > Add ( new CheckBox ( & g_Config . bRemoteShareOnStartup , ri - > T ( " Share on PPSSPP startup " ) ) ) ;
remoteisoSettings - > Add ( new CheckBox ( & g_Config . bRemoteISOManual , ri - > T ( " Manual Mode Client " , " Manually configure client " ) ) ) ;
2017-11-16 12:33:10 +00:00
# if !defined(MOBILE_DEVICE)
2017-08-16 21:39:30 +00:00
PopupTextInputChoice * remoteServer = remoteisoSettings - > Add ( new PopupTextInputChoice ( & g_Config . sLastRemoteISOServer , ri - > T ( " Remote Server " ) , " " , 255 , screenManager ( ) ) ) ;
2017-11-16 12:33:10 +00:00
# else
2018-03-25 12:26:44 +00:00
ChoiceWithValueDisplay * remoteServer = new ChoiceWithValueDisplay ( & g_Config . sLastRemoteISOServer , ri - > T ( " Remote Server " ) , ( const char * ) nullptr ) ;
2017-11-16 12:33:10 +00:00
remoteisoSettings - > Add ( remoteServer ) ;
remoteServer - > OnClick . Handle ( this , & RemoteISOSettingsScreen : : OnClickRemoteServer ) ;
# endif
2017-03-11 04:05:56 +00:00
remoteServer - > SetEnabledPtr ( & g_Config . bRemoteISOManual ) ;
2017-08-16 21:39:30 +00:00
PopupSliderChoice * remotePort = remoteisoSettings - > Add ( new PopupSliderChoice ( & g_Config . iLastRemoteISOPort , 0 , 65535 , ri - > T ( " Remote Port " , " Remote Port " ) , 100 , screenManager ( ) ) ) ;
2017-03-11 04:05:56 +00:00
remotePort - > SetEnabledPtr ( & g_Config . bRemoteISOManual ) ;
2017-11-16 12:33:10 +00:00
# if !defined(MOBILE_DEVICE)
2017-08-16 21:39:30 +00:00
PopupTextInputChoice * remoteSubdir = remoteisoSettings - > Add ( new PopupTextInputChoice ( & g_Config . sRemoteISOSubdir , ri - > T ( " Remote Subdirectory " ) , " " , 255 , screenManager ( ) ) ) ;
2017-03-11 04:05:56 +00:00
remoteSubdir - > OnChange . Handle ( this , & RemoteISOSettingsScreen : : OnChangeRemoteISOSubdir ) ;
2017-11-16 12:33:10 +00:00
# else
ChoiceWithValueDisplay * remoteSubdir = remoteisoSettings - > Add (
2018-03-25 12:26:44 +00:00
new ChoiceWithValueDisplay ( & g_Config . sRemoteISOSubdir , ri - > T ( " Remote Subdirectory " ) , ( const char * ) nullptr ) ) ;
2017-11-16 12:33:10 +00:00
remoteSubdir - > OnClick . Handle ( this , & RemoteISOSettingsScreen : : OnClickRemoteISOSubdir ) ;
# endif
remoteSubdir - > SetEnabledPtr ( & g_Config . bRemoteISOManual ) ;
2017-03-22 07:03:45 +00:00
2017-08-16 21:39:30 +00:00
PopupSliderChoice * portChoice = new PopupSliderChoice ( & g_Config . iRemoteISOPort , 0 , 65535 , ri - > T ( " Local Server Port " , " Local Server Port " ) , 100 , screenManager ( ) ) ;
2017-03-22 07:03:45 +00:00
remoteisoSettings - > Add ( portChoice ) ;
portChoice - > SetDisabledPtr ( & serverRunning_ ) ;
2017-03-11 04:05:56 +00:00
remoteisoSettings - > Add ( new Spacer ( 25.0 ) ) ;
root_ = new AnchorLayout ( new LayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
2017-03-22 07:03:45 +00:00
root_ - > Add ( remoteisoSettingsScroll ) ;
AddStandardBack ( root_ ) ;
2017-03-11 04:05:56 +00:00
}
2017-11-16 12:33:10 +00:00
UI : : EventReturn RemoteISOSettingsScreen : : OnClickRemoteServer ( UI : : EventParams & e ) {
System_SendMessage ( " inputbox " , ( " remoteiso_server: " + g_Config . sLastRemoteISOServer ) . c_str ( ) ) ;
return UI : : EVENT_DONE ;
}
UI : : EventReturn RemoteISOSettingsScreen : : OnClickRemoteISOSubdir ( UI : : EventParams & e ) {
System_SendMessage ( " inputbox " , ( " remoteiso_subdir: " + g_Config . sRemoteISOSubdir ) . c_str ( ) ) ;
return UI : : EVENT_DONE ;
}
2017-03-11 04:05:56 +00:00
UI : : EventReturn RemoteISOSettingsScreen : : OnChangeRemoteISOSubdir ( UI : : EventParams & e ) {
//Conform to HTTP standards
2017-03-11 06:53:16 +00:00
ReplaceAll ( g_Config . sRemoteISOSubdir , " " , " %20 " ) ;
ReplaceAll ( g_Config . sRemoteISOSubdir , " \\ " , " / " ) ;
//Make sure it begins with /
2017-03-11 04:05:56 +00:00
if ( g_Config . sRemoteISOSubdir [ 0 ] ! = ' / ' )
g_Config . sRemoteISOSubdir = " / " + g_Config . sRemoteISOSubdir ;
2017-03-11 06:53:16 +00:00
2017-03-11 04:05:56 +00:00
return UI : : EVENT_DONE ;
}