mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-14 10:36:43 +00:00
Refactor RemoteHost to be copyable with shared storage
* This allows RemoteHost handles to still be valid and usable (if returning empty data) when they are deleted/removed if the device is disconnected, as well as providing better multi-thread access (they lock internally)
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QMutexLocker>
|
||||
#include <QStandardPaths>
|
||||
#include "Code/QRDUtils.h"
|
||||
#include "Styles/StyleData.h"
|
||||
@@ -194,34 +195,78 @@ void PersistantConfig::applyValues(const QVariantMap &values)
|
||||
RENAMED_SETTING(QVariantList, SPIRVDisassemblers, ShaderProcessors);
|
||||
}
|
||||
|
||||
int PersistantConfig::RemoteHostCount()
|
||||
static QMutex RemoteHostLock;
|
||||
|
||||
rdcarray<RemoteHost> PersistantConfig::GetRemoteHosts()
|
||||
{
|
||||
return RemoteHosts.count();
|
||||
QMutexLocker autolock(&RemoteHostLock);
|
||||
return RemoteHostList;
|
||||
}
|
||||
|
||||
RemoteHost *PersistantConfig::GetRemoteHost(int index)
|
||||
RemoteHost PersistantConfig::GetRemoteHost(const rdcstr &hostname)
|
||||
{
|
||||
if(index < 0 || index >= RemoteHostCount())
|
||||
return NULL;
|
||||
return RemoteHosts[index];
|
||||
RemoteHost ret;
|
||||
|
||||
{
|
||||
QMutexLocker autolock(&RemoteHostLock);
|
||||
for(size_t i = 0; i < RemoteHostList.size(); i++)
|
||||
{
|
||||
if(RemoteHostList[i].Hostname() == hostname)
|
||||
{
|
||||
ret = RemoteHostList[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PersistantConfig::AddRemoteHost(RemoteHost host)
|
||||
{
|
||||
RemoteHosts.push_back(new RemoteHost(host));
|
||||
if(!host.IsValid())
|
||||
return;
|
||||
|
||||
QMutexLocker autolock(&RemoteHostLock);
|
||||
|
||||
// don't add duplicates
|
||||
for(size_t i = 0; i < RemoteHostList.size(); i++)
|
||||
{
|
||||
if(RemoteHostList[i] == host)
|
||||
{
|
||||
RemoteHostList[i] = host;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RemoteHostList.push_back(host);
|
||||
}
|
||||
|
||||
void PersistantConfig::RemoveRemoteHost(RemoteHost host)
|
||||
{
|
||||
if(!host.IsValid())
|
||||
return;
|
||||
|
||||
QMutexLocker autolock(&RemoteHostLock);
|
||||
|
||||
for(size_t i = 0; i < RemoteHostList.size(); i++)
|
||||
{
|
||||
if(RemoteHostList[i] == host)
|
||||
{
|
||||
RemoteHostList.takeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PersistantConfig::AddAndroidHosts()
|
||||
{
|
||||
QMap<rdcstr, RemoteHost *> oldHosts;
|
||||
for(int i = RemoteHosts.count() - 1; i >= 0; i--)
|
||||
{
|
||||
if(RemoteHosts[i]->IsADB())
|
||||
{
|
||||
RemoteHost *host = RemoteHosts.takeAt(i);
|
||||
oldHosts[host->hostname] = host;
|
||||
}
|
||||
}
|
||||
QMutexLocker autolock(&RemoteHostLock);
|
||||
|
||||
QMap<rdcstr, RemoteHost> oldHosts;
|
||||
for(int i = RemoteHostList.count() - 1; i >= 0; i--)
|
||||
if(RemoteHostList[i].IsADB())
|
||||
oldHosts[RemoteHostList[i].Hostname()] = RemoteHostList.takeAt(i);
|
||||
|
||||
QString androidSDKPath = (!Android_SDKPath.isEmpty() && QFile::exists(Android_SDKPath))
|
||||
? QString(Android_SDKPath)
|
||||
@@ -242,28 +287,25 @@ void PersistantConfig::AddAndroidHosts()
|
||||
for(const QString &hostName :
|
||||
QString(androidHosts).split(QLatin1Char(','), QString::SkipEmptyParts))
|
||||
{
|
||||
RemoteHost *host = NULL;
|
||||
RemoteHost host((rdcstr)hostName);
|
||||
|
||||
if(oldHosts.contains(hostName))
|
||||
host = oldHosts.take(hostName);
|
||||
else
|
||||
host = new RemoteHost();
|
||||
|
||||
host->hostname = hostName;
|
||||
rdcstr friendly;
|
||||
RENDERDOC_GetAndroidFriendlyName(hostName.toUtf8().data(), friendly);
|
||||
host->friendlyName = friendly;
|
||||
host.SetFriendlyName(friendly);
|
||||
// Just a command to display in the GUI and allow Launch() to be called.
|
||||
host->runCommand = lit("Automatically handled");
|
||||
RemoteHosts.push_back(host);
|
||||
host.SetRunCommand("Automatically handled");
|
||||
RemoteHostList.push_back(host);
|
||||
}
|
||||
|
||||
// delete any leftovers
|
||||
QMapIterator<rdcstr, RemoteHost *> i(oldHosts);
|
||||
QMutableMapIterator<rdcstr, RemoteHost> i(oldHosts);
|
||||
while(i.hasNext())
|
||||
{
|
||||
i.next();
|
||||
delete i.value();
|
||||
i.value().SetShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,8 +330,6 @@ bool PersistantConfig::SetStyle()
|
||||
|
||||
PersistantConfig::~PersistantConfig()
|
||||
{
|
||||
for(RemoteHost *h : RemoteHosts)
|
||||
delete h;
|
||||
}
|
||||
|
||||
bool PersistantConfig::Load(const rdcstr &filename)
|
||||
@@ -309,24 +349,32 @@ bool PersistantConfig::Load(const rdcstr &filename)
|
||||
RDDialog::DefaultBrowsePath = LastFileBrowsePath;
|
||||
|
||||
// localhost should always be available as a remote host
|
||||
bool foundLocalhost = false;
|
||||
|
||||
for(RemoteHost host : RemoteHostList)
|
||||
{
|
||||
if(host.hostname.isEmpty())
|
||||
continue;
|
||||
QMutexLocker autolock(&RemoteHostLock);
|
||||
|
||||
RemoteHosts.push_back(new RemoteHost(host));
|
||||
bool foundLocalhost = false;
|
||||
|
||||
if(host.IsLocalhost())
|
||||
foundLocalhost = true;
|
||||
}
|
||||
rdcarray<RemoteHost> hosts;
|
||||
hosts.swap(RemoteHostList);
|
||||
|
||||
if(!foundLocalhost)
|
||||
{
|
||||
RemoteHost *host = new RemoteHost();
|
||||
host->hostname = "localhost";
|
||||
RemoteHosts.insert(0, host);
|
||||
for(RemoteHost host : hosts)
|
||||
{
|
||||
// skip invalid hosts
|
||||
if(!host.IsValid())
|
||||
continue;
|
||||
|
||||
RemoteHostList.push_back(host);
|
||||
|
||||
if(host.IsLocalhost())
|
||||
foundLocalhost = true;
|
||||
}
|
||||
|
||||
if(!foundLocalhost)
|
||||
{
|
||||
RemoteHost host;
|
||||
host.m_hostname = "localhost";
|
||||
RemoteHostList.insert(0, host);
|
||||
}
|
||||
}
|
||||
|
||||
bool tools[arraydim<KnownShaderTool>()] = {};
|
||||
@@ -427,11 +475,6 @@ bool PersistantConfig::Save()
|
||||
if(m_Filename.isEmpty())
|
||||
return true;
|
||||
|
||||
// update serialize list
|
||||
RemoteHostList.clear();
|
||||
for(RemoteHost *host : RemoteHosts)
|
||||
RemoteHostList.push_back(*host);
|
||||
|
||||
RENDERDOC_SetConfigSetting("Disassembly_FriendlyNaming", ShaderViewer_FriendlyNaming ? "1" : "0");
|
||||
RENDERDOC_SetConfigSetting("ExternalTool_RGPIntegration", ExternalTool_RGPIntegration ? "1" : "0");
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "QRDInterface.h"
|
||||
#include "RemoteHost.h"
|
||||
|
||||
class QMutex;
|
||||
|
||||
DOCUMENT(R"(Identifies a particular known tool used for shader processing.
|
||||
|
||||
.. data:: Unknown
|
||||
@@ -766,38 +768,29 @@ For more information about some of these settings that are user-facing see
|
||||
class PersistantConfig
|
||||
{
|
||||
public:
|
||||
// don't allow SWIG direct access to the RemoteHosts since they're an array of references and our
|
||||
// bindings can't handle that properly
|
||||
#if !defined(SWIG)
|
||||
// Runtime list of dynamically allocated hosts.
|
||||
// Saved to/from private RemoteHostList in CONFIG_SETTINGS()
|
||||
// This is documented above in the docstring, similar to the values in CONFIG_SETTINGS()
|
||||
// This must only be accessed on the UI thread to prevent races. For access on other threads (e.g.
|
||||
// a background/asynchronous update), take a copy on the UI thread, update it in the background,
|
||||
// then apply the updates.
|
||||
DOCUMENT("");
|
||||
rdcarray<RemoteHost *> RemoteHosts;
|
||||
#endif
|
||||
DOCUMENT(R"(Returns a list of all remote hosts.
|
||||
|
||||
DOCUMENT(R"(Returns the number of remote hosts currently registered.
|
||||
|
||||
:return: The number of remote hosts.
|
||||
:rtype: ``int``
|
||||
:return: The remote host list
|
||||
:rtype: ``list`` of ``RemoteHost``
|
||||
)");
|
||||
int RemoteHostCount();
|
||||
DOCUMENT(R"(Returns a given remote host at an index.
|
||||
rdcarray<RemoteHost> GetRemoteHosts();
|
||||
DOCUMENT(R"(Look up a remote host by hostname.
|
||||
|
||||
:param int index: The index of the remote host to retrieve
|
||||
:return: The remote host specified, or ``None`` if an invalid index was passed
|
||||
:return: The remote host for the given hostname, or an invalid ``RemoteHost`` if no such exists.
|
||||
:rtype: ``RemoteHost``
|
||||
)");
|
||||
RemoteHost *GetRemoteHost(int index);
|
||||
RemoteHost GetRemoteHost(const rdcstr &hostname);
|
||||
|
||||
DOCUMENT(R"(Adds a new remote host.
|
||||
|
||||
:param RemoteHost host: The remote host to add.
|
||||
R)");
|
||||
void AddRemoteHost(RemoteHost host);
|
||||
DOCUMENT(R"(Removes an existing remote host.
|
||||
|
||||
:param RemoteHost host: The remote host to remove.
|
||||
R)");
|
||||
void RemoveRemoteHost(RemoteHost host);
|
||||
DOCUMENT("If configured, queries ``adb`` to add android hosts to :data:`RemoteHosts`.");
|
||||
void AddAndroidHosts();
|
||||
|
||||
|
||||
@@ -735,7 +735,7 @@ struct IReplayManager
|
||||
:return: Whether or not the connection was successful.
|
||||
:rtype: ~renderdoc.ReplayStatus
|
||||
)");
|
||||
virtual ReplayStatus ConnectToRemoteServer(RemoteHost *host) = 0;
|
||||
virtual ReplayStatus ConnectToRemoteServer(RemoteHost host) = 0;
|
||||
|
||||
DOCUMENT("Disconnect from the server the manager is currently connected to.");
|
||||
virtual void DisconnectFromRemoteServer() = 0;
|
||||
@@ -751,10 +751,10 @@ struct IReplayManager
|
||||
|
||||
DOCUMENT(R"(Retrieves the host that the manager is currently connected to.
|
||||
|
||||
:return: The host connected to, or ``None`` if no connection is active.
|
||||
:return: The host connected to, or an invalid RemoteHost if no connection is active.
|
||||
:rtype: RemoteHost
|
||||
)");
|
||||
virtual RemoteHost *CurrentRemote() = 0;
|
||||
virtual RemoteHost CurrentRemote() = 0;
|
||||
|
||||
DOCUMENT(R"(Retrieves the capture file handle for the currently open file.
|
||||
|
||||
|
||||
@@ -22,80 +22,158 @@
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <QAtomicInt>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QProcess>
|
||||
#include <QThread>
|
||||
#include "Code/QRDUtils.h"
|
||||
#include "QRDInterface.h"
|
||||
|
||||
RemoteHost::RemoteHost()
|
||||
struct RemoteHostData
|
||||
{
|
||||
serverRunning = connected = busy = versionMismatch = false;
|
||||
}
|
||||
QAtomicInt refcount;
|
||||
QMutex mutex;
|
||||
|
||||
void ref() { refcount.ref(); }
|
||||
void deref()
|
||||
{
|
||||
if(!refcount.deref())
|
||||
delete this;
|
||||
}
|
||||
|
||||
RemoteHostData() : refcount(1) {}
|
||||
rdcstr m_friendlyName, m_runCommand, m_lastCapturePath;
|
||||
bool m_serverRunning = false, m_connected = false, m_busy = false, m_versionMismatch = false;
|
||||
};
|
||||
|
||||
RemoteHost::RemoteHost(const QVariant &var)
|
||||
{
|
||||
m_data = new RemoteHostData();
|
||||
|
||||
QVariantMap map = var.toMap();
|
||||
if(map.contains(lit("hostname")))
|
||||
hostname = map[lit("hostname")].toString();
|
||||
m_hostname = map[lit("hostname")].toString();
|
||||
if(map.contains(lit("friendlyName")))
|
||||
friendlyName = map[lit("friendlyName")].toString();
|
||||
m_data->m_friendlyName = map[lit("friendlyName")].toString();
|
||||
if(map.contains(lit("runCommand")))
|
||||
runCommand = map[lit("runCommand")].toString();
|
||||
m_data->m_runCommand = map[lit("runCommand")].toString();
|
||||
if(map.contains(lit("lastCapturePath")))
|
||||
lastCapturePath = map[lit("lastCapturePath")].toString();
|
||||
m_data->m_lastCapturePath = map[lit("lastCapturePath")].toString();
|
||||
}
|
||||
|
||||
serverRunning = connected = busy = versionMismatch = false;
|
||||
RemoteHost::RemoteHost()
|
||||
{
|
||||
m_data = new RemoteHostData();
|
||||
}
|
||||
|
||||
RemoteHost::RemoteHost(const rdcstr &host)
|
||||
{
|
||||
// create a new host
|
||||
m_hostname = host;
|
||||
m_data = new RemoteHostData();
|
||||
}
|
||||
|
||||
RemoteHost::RemoteHost(const RemoteHost &o)
|
||||
{
|
||||
*this = o;
|
||||
}
|
||||
|
||||
RemoteHost &RemoteHost::operator=(const RemoteHost &o)
|
||||
{
|
||||
m_hostname = o.m_hostname;
|
||||
|
||||
// deref old data
|
||||
if(m_data)
|
||||
m_data->deref();
|
||||
// point to new data
|
||||
m_data = o.m_data;
|
||||
// get a ref on it
|
||||
m_data->ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RemoteHost::~RemoteHost()
|
||||
{
|
||||
m_data->deref();
|
||||
}
|
||||
|
||||
RemoteHost::operator QVariant() const
|
||||
{
|
||||
QVariantMap map;
|
||||
map[lit("hostname")] = hostname;
|
||||
map[lit("friendlyName")] = friendlyName;
|
||||
map[lit("runCommand")] = runCommand;
|
||||
map[lit("lastCapturePath")] = lastCapturePath;
|
||||
m_data->mutex.lock();
|
||||
map[lit("hostname")] = m_hostname;
|
||||
map[lit("friendlyName")] = m_data->m_friendlyName;
|
||||
map[lit("runCommand")] = m_data->m_runCommand;
|
||||
map[lit("lastCapturePath")] = m_data->m_lastCapturePath;
|
||||
m_data->mutex.unlock();
|
||||
return map;
|
||||
}
|
||||
|
||||
void RemoteHost::CheckStatus()
|
||||
{
|
||||
// special case - this is the local context
|
||||
if(hostname == "localhost")
|
||||
if(m_hostname == "localhost")
|
||||
{
|
||||
serverRunning = false;
|
||||
versionMismatch = busy = false;
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
m_data->m_serverRunning = m_data->m_versionMismatch = m_data->m_busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// to avoid doing complex work while holding the remote host lock, we check the status here then
|
||||
// call into the internal function that will propagate that data to the proper storage if needed.
|
||||
IRemoteServer *rend = NULL;
|
||||
ReplayStatus status = RENDERDOC_CreateRemoteServerConnection(hostname.c_str(), 0, &rend);
|
||||
|
||||
if(status == ReplayStatus::Succeeded)
|
||||
{
|
||||
serverRunning = true;
|
||||
versionMismatch = busy = false;
|
||||
}
|
||||
else if(status == ReplayStatus::NetworkRemoteBusy)
|
||||
{
|
||||
serverRunning = true;
|
||||
busy = true;
|
||||
versionMismatch = false;
|
||||
}
|
||||
else if(status == ReplayStatus::NetworkVersionMismatch)
|
||||
{
|
||||
serverRunning = true;
|
||||
busy = true;
|
||||
versionMismatch = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
serverRunning = false;
|
||||
versionMismatch = busy = false;
|
||||
}
|
||||
ReplayStatus status = RENDERDOC_CreateRemoteServerConnection(m_hostname.c_str(), 0, &rend);
|
||||
|
||||
if(rend)
|
||||
rend->ShutdownConnection();
|
||||
|
||||
UpdateStatus(status);
|
||||
}
|
||||
|
||||
void RemoteHost::SetConnected(bool connected)
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
m_data->m_connected = connected;
|
||||
}
|
||||
|
||||
void RemoteHost::SetShutdown()
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
m_data->m_connected = false;
|
||||
m_data->m_serverRunning = false;
|
||||
m_data->m_busy = false;
|
||||
}
|
||||
|
||||
void RemoteHost::UpdateStatus(ReplayStatus status)
|
||||
{
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
|
||||
if(status == ReplayStatus::Succeeded)
|
||||
{
|
||||
m_data->m_serverRunning = true;
|
||||
m_data->m_versionMismatch = m_data->m_busy = false;
|
||||
}
|
||||
else if(status == ReplayStatus::NetworkRemoteBusy)
|
||||
{
|
||||
m_data->m_serverRunning = true;
|
||||
m_data->m_busy = true;
|
||||
m_data->m_versionMismatch = false;
|
||||
}
|
||||
else if(status == ReplayStatus::NetworkVersionMismatch)
|
||||
{
|
||||
m_data->m_serverRunning = true;
|
||||
m_data->m_busy = true;
|
||||
m_data->m_versionMismatch = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_data->m_serverRunning = false;
|
||||
m_data->m_versionMismatch = m_data->m_busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
// since we can only have one active client at once on a remote server, we need
|
||||
// to avoid DDOS'ing by doing multiple CheckStatus() one after the other so fast
|
||||
// that the active client can't be properly shut down. Sleeping here for a short
|
||||
@@ -113,15 +191,82 @@ ReplayStatus RemoteHost::Launch()
|
||||
|
||||
if(IsADB())
|
||||
{
|
||||
status = RENDERDOC_StartAndroidRemoteServer(hostname.c_str());
|
||||
status = RENDERDOC_StartAndroidRemoteServer(m_hostname.c_str());
|
||||
QThread::msleep(WAIT_TIME);
|
||||
return status;
|
||||
}
|
||||
|
||||
rdcstr run;
|
||||
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
run = RunCommand();
|
||||
}
|
||||
|
||||
RDProcess process;
|
||||
process.start(runCommand);
|
||||
process.start(run);
|
||||
process.waitForFinished(WAIT_TIME);
|
||||
process.detach();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool RemoteHost::IsServerRunning() const
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
return m_data->m_serverRunning;
|
||||
}
|
||||
|
||||
bool RemoteHost::IsConnected() const
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
return m_data->m_connected;
|
||||
}
|
||||
|
||||
bool RemoteHost::IsBusy() const
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
return m_data->m_busy;
|
||||
}
|
||||
|
||||
bool RemoteHost::IsVersionMismatch() const
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
return m_data->m_versionMismatch;
|
||||
}
|
||||
|
||||
rdcstr RemoteHost::FriendlyName() const
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
return m_data->m_friendlyName;
|
||||
}
|
||||
|
||||
void RemoteHost::SetFriendlyName(const rdcstr &name)
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
m_data->m_friendlyName = name;
|
||||
}
|
||||
|
||||
rdcstr RemoteHost::RunCommand() const
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
return m_data->m_runCommand;
|
||||
}
|
||||
|
||||
void RemoteHost::SetRunCommand(const rdcstr &cmd)
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
m_data->m_runCommand = cmd;
|
||||
}
|
||||
|
||||
rdcstr RemoteHost::LastCapturePath() const
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
return m_data->m_lastCapturePath;
|
||||
}
|
||||
|
||||
void RemoteHost::SetLastCapturePath(const rdcstr &path)
|
||||
{
|
||||
QMutexLocker autolock(&m_data->mutex);
|
||||
m_data->m_lastCapturePath = path;
|
||||
}
|
||||
|
||||
@@ -29,22 +29,33 @@ class RemoteHost;
|
||||
// do not include any headers here, they must all be in QRDInterface.h
|
||||
#include "QRDInterface.h"
|
||||
|
||||
class PersistantConfig;
|
||||
class ReplayManager;
|
||||
|
||||
struct RemoteHostData;
|
||||
|
||||
// to enable easy copying around of these hosts as well as allowing graceful behaviour when hosts
|
||||
// are unexpectedly removed (such as disconnecting an auto-populated device) these structs are
|
||||
// copied around and they have a shared locked data pointer. All accessors then lock and look up the
|
||||
// data there to fetch or modify
|
||||
DOCUMENT("A handle for interacting with a remote server on a given host.");
|
||||
class RemoteHost
|
||||
{
|
||||
public:
|
||||
DOCUMENT("");
|
||||
RemoteHost();
|
||||
|
||||
RemoteHost(const rdcstr &host);
|
||||
RemoteHost(const RemoteHost &o);
|
||||
#if !defined(SWIG)
|
||||
RemoteHost &operator=(const RemoteHost &o);
|
||||
#endif
|
||||
~RemoteHost();
|
||||
VARIANT_CAST(RemoteHost);
|
||||
|
||||
DOCUMENT("");
|
||||
bool operator==(const RemoteHost &o) const
|
||||
{
|
||||
return hostname == o.hostname && friendlyName == o.friendlyName && runCommand == o.runCommand &&
|
||||
serverRunning == o.serverRunning && connected == o.connected && busy == o.busy &&
|
||||
versionMismatch == o.versionMismatch;
|
||||
}
|
||||
bool operator==(const RemoteHost &o) const { return m_hostname == o.m_hostname; }
|
||||
bool operator!=(const RemoteHost &o) const { return !(*this == o); }
|
||||
bool operator<(const RemoteHost &o) const { return m_hostname < o.m_hostname; }
|
||||
DOCUMENT(
|
||||
"Ping the host to check current status - if the server is running, connection status, etc.");
|
||||
void CheckStatus();
|
||||
@@ -54,36 +65,72 @@ public:
|
||||
ReplayStatus Launch();
|
||||
|
||||
DOCUMENT("``True`` if a remote server is currently running on this host.");
|
||||
bool serverRunning : 1;
|
||||
bool IsServerRunning() const;
|
||||
DOCUMENT("``True`` if an active connection exists to this remote server.");
|
||||
bool connected : 1;
|
||||
bool IsConnected() const;
|
||||
DOCUMENT("``True`` if someone else is currently connected to this server.");
|
||||
bool busy : 1;
|
||||
bool IsBusy() const;
|
||||
DOCUMENT("``True`` if there is a code version mismatch with this server.");
|
||||
bool versionMismatch : 1;
|
||||
bool IsVersionMismatch() const;
|
||||
|
||||
DOCUMENT("The hostname of this host.");
|
||||
rdcstr hostname;
|
||||
const rdcstr &Hostname() const { return m_hostname; }
|
||||
DOCUMENT("The friendly name for this host, if available (if empty, the Hostname is used).");
|
||||
rdcstr friendlyName;
|
||||
rdcstr FriendlyName() const;
|
||||
DOCUMENT("The command to run locally to try to launch the server remotely.");
|
||||
rdcstr runCommand;
|
||||
rdcstr RunCommand() const;
|
||||
DOCUMENT(R"(Sets the run command. See :meth:`RunCommand`.
|
||||
|
||||
DOCUMENT("The last folder browser to on this host, to provide a reasonable default path.");
|
||||
rdcstr lastCapturePath;
|
||||
:param str cmd: The new command to set.
|
||||
)");
|
||||
void SetRunCommand(const rdcstr &cmd);
|
||||
|
||||
DOCUMENT("The last folder browsed to on this host, to provide a reasonable default path.");
|
||||
rdcstr LastCapturePath() const;
|
||||
DOCUMENT(R"(Sets the last folder browsed to. See :meth:`LastCapturePath`.
|
||||
|
||||
:param str path: The new path to set.
|
||||
)");
|
||||
void SetLastCapturePath(const rdcstr &path);
|
||||
|
||||
DOCUMENT(R"(
|
||||
Returns the name to display for this host in the UI, either :data:`friendlyName` or :data:`hostname`
|
||||
Returns the name to display for this host in the UI, either :meth:`FriendlyName` if it is valid, or
|
||||
:meth:`Hostname` if not.
|
||||
)");
|
||||
const rdcstr &Name() const { return !friendlyName.isEmpty() ? friendlyName : hostname; }
|
||||
rdcstr Name() const
|
||||
{
|
||||
rdcstr friendlyName = FriendlyName();
|
||||
return !friendlyName.isEmpty() ? friendlyName : m_hostname;
|
||||
}
|
||||
DOCUMENT("Returns ``True`` if this host represents a connected ADB (Android) device.");
|
||||
bool IsADB() const
|
||||
{
|
||||
return hostname.count() > 4 && hostname[0] == 'a' && hostname[1] == 'd' && hostname[2] == 'b' &&
|
||||
hostname[3] == ':';
|
||||
return m_hostname.count() > 4 && m_hostname[0] == 'a' && m_hostname[1] == 'd' &&
|
||||
m_hostname[2] == 'b' && m_hostname[3] == ':';
|
||||
}
|
||||
DOCUMENT("Returns ``True`` if this host represents the special localhost device.");
|
||||
bool IsLocalhost() const { return hostname == "localhost"; }
|
||||
bool IsLocalhost() const { return m_hostname == "localhost"; }
|
||||
DOCUMENT("Returns ``True`` if this host represents a valid remote host.");
|
||||
bool IsValid() const { return m_data && !m_hostname.isEmpty(); }
|
||||
private:
|
||||
// this is immutable and is used as a key to look up data, it's always valid as RemoteHost objects
|
||||
// are created with it
|
||||
rdcstr m_hostname;
|
||||
|
||||
// self-deleting shared and locked data store
|
||||
RemoteHostData *m_data = NULL;
|
||||
|
||||
// allow config to set our data
|
||||
friend class PersistantConfig;
|
||||
void SetFriendlyName(const rdcstr &name);
|
||||
|
||||
// allow ReplayManager to call these functions to change the status. Otherwise they are read-only
|
||||
// except by calling CheckStatus()
|
||||
friend class ReplayManager;
|
||||
void SetConnected(bool connected);
|
||||
void SetShutdown();
|
||||
|
||||
void UpdateStatus(ReplayStatus status);
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(RemoteHost);
|
||||
@@ -305,11 +305,11 @@ void ReplayManager::CloseThread()
|
||||
m_Thread = NULL;
|
||||
}
|
||||
|
||||
ReplayStatus ReplayManager::ConnectToRemoteServer(RemoteHost *host)
|
||||
ReplayStatus ReplayManager::ConnectToRemoteServer(RemoteHost host)
|
||||
{
|
||||
ReplayStatus status = RENDERDOC_CreateRemoteServerConnection(host->hostname.c_str(), 0, &m_Remote);
|
||||
ReplayStatus status = RENDERDOC_CreateRemoteServerConnection(host.Hostname().c_str(), 0, &m_Remote);
|
||||
|
||||
if(host->IsADB())
|
||||
if(host.IsADB())
|
||||
{
|
||||
ANALYTIC_SET(UIFeatures.AndroidRemoteReplay, true);
|
||||
}
|
||||
@@ -322,7 +322,7 @@ ReplayStatus ReplayManager::ConnectToRemoteServer(RemoteHost *host)
|
||||
|
||||
if(status == ReplayStatus::Succeeded)
|
||||
{
|
||||
m_RemoteHost->connected = true;
|
||||
m_RemoteHost.SetConnected(true);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -331,8 +331,7 @@ ReplayStatus ReplayManager::ConnectToRemoteServer(RemoteHost *host)
|
||||
|
||||
void ReplayManager::DisconnectFromRemoteServer()
|
||||
{
|
||||
if(m_RemoteHost)
|
||||
m_RemoteHost->connected = false;
|
||||
m_RemoteHost.SetConnected(false);
|
||||
|
||||
if(m_Remote)
|
||||
{
|
||||
@@ -340,12 +339,14 @@ void ReplayManager::DisconnectFromRemoteServer()
|
||||
m_Remote->ShutdownConnection();
|
||||
}
|
||||
|
||||
m_RemoteHost = NULL;
|
||||
m_RemoteHost = RemoteHost();
|
||||
m_Remote = NULL;
|
||||
}
|
||||
|
||||
void ReplayManager::ShutdownServer()
|
||||
{
|
||||
m_RemoteHost.SetShutdown();
|
||||
|
||||
if(m_Remote)
|
||||
{
|
||||
QMutexLocker autolock(&m_RemoteLock);
|
||||
@@ -365,7 +366,7 @@ void ReplayManager::PingRemote()
|
||||
if(!IsRunning() || m_Thread->isCurrentThread())
|
||||
{
|
||||
if(!m_Remote->Ping())
|
||||
m_RemoteHost->serverRunning = false;
|
||||
m_RemoteHost.SetShutdown();
|
||||
}
|
||||
m_RemoteLock.unlock();
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
void CloseThread();
|
||||
|
||||
ReplayStatus ConnectToRemoteServer(RemoteHost *host);
|
||||
ReplayStatus ConnectToRemoteServer(RemoteHost host);
|
||||
void DisconnectFromRemoteServer();
|
||||
void ShutdownServer();
|
||||
void PingRemote();
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
// work whether local or remote.
|
||||
ICaptureFile *GetCaptureFile() { return m_CaptureFile; }
|
||||
void ReopenCaptureFile(const QString &path);
|
||||
RemoteHost *CurrentRemote() { return m_RemoteHost; }
|
||||
RemoteHost CurrentRemote() { return m_RemoteHost; }
|
||||
ExecuteResult ExecuteAndInject(const rdcstr &exe, const rdcstr &workingDir, const rdcstr &cmdLine,
|
||||
const rdcarray<EnvironmentModification> &env,
|
||||
const rdcstr &capturefile, CaptureOptions opts);
|
||||
@@ -128,7 +128,7 @@ private:
|
||||
void PushInvoke(InvokeHandle *cmd);
|
||||
|
||||
QMutex m_RemoteLock;
|
||||
RemoteHost *m_RemoteHost = NULL;
|
||||
RemoteHost m_RemoteHost;
|
||||
IRemoteServer *m_Remote = NULL;
|
||||
|
||||
volatile bool m_Running;
|
||||
|
||||
@@ -86,6 +86,7 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, rdcstrpair)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, BugReport)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ExtensionMetadata)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, DialogButton)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, RemoteHost)
|
||||
TEMPLATE_ARRAY_INSTANTIATE_PTR(rdcarray, ICaptureViewer)
|
||||
|
||||
// unignore the function from above
|
||||
|
||||
@@ -125,20 +125,24 @@ void PersistantConfig::Close()
|
||||
{
|
||||
}
|
||||
|
||||
int PersistantConfig::RemoteHostCount()
|
||||
rdcarray<RemoteHost> PersistantConfig::GetRemoteHosts()
|
||||
{
|
||||
return 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
RemoteHost *PersistantConfig::GetRemoteHost(int index)
|
||||
RemoteHost PersistantConfig::GetRemoteHost(const rdcstr &)
|
||||
{
|
||||
return NULL;
|
||||
return RemoteHost();
|
||||
}
|
||||
|
||||
void PersistantConfig::AddRemoteHost(RemoteHost host)
|
||||
{
|
||||
}
|
||||
|
||||
void PersistantConfig::RemoveRemoteHost(RemoteHost host)
|
||||
{
|
||||
}
|
||||
|
||||
void PersistantConfig::AddAndroidHosts()
|
||||
{
|
||||
}
|
||||
@@ -166,7 +170,23 @@ rdcstr PersistantConfig::GetConfigSetting(const rdcstr &name)
|
||||
|
||||
RemoteHost::RemoteHost()
|
||||
{
|
||||
serverRunning = connected = busy = versionMismatch = false;
|
||||
}
|
||||
|
||||
RemoteHost::RemoteHost(const rdcstr &host)
|
||||
{
|
||||
}
|
||||
|
||||
RemoteHost::RemoteHost(const RemoteHost &o)
|
||||
{
|
||||
}
|
||||
|
||||
RemoteHost &RemoteHost::operator=(const RemoteHost &o)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
RemoteHost::~RemoteHost()
|
||||
{
|
||||
}
|
||||
|
||||
void RemoteHost::CheckStatus()
|
||||
@@ -177,3 +197,58 @@ ReplayStatus RemoteHost::Launch()
|
||||
{
|
||||
return ReplayStatus::Succeeded;
|
||||
}
|
||||
|
||||
bool RemoteHost::IsServerRunning() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RemoteHost::IsConnected() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RemoteHost::IsBusy() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RemoteHost::IsVersionMismatch() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rdcstr RemoteHost::FriendlyName() const
|
||||
{
|
||||
return rdcstr();
|
||||
}
|
||||
|
||||
void RemoteHost::SetFriendlyName(const rdcstr &name)
|
||||
{
|
||||
}
|
||||
|
||||
rdcstr RemoteHost::RunCommand() const
|
||||
{
|
||||
return rdcstr();
|
||||
}
|
||||
|
||||
void RemoteHost::SetRunCommand(const rdcstr &cmd)
|
||||
{
|
||||
}
|
||||
|
||||
rdcstr RemoteHost::LastCapturePath() const
|
||||
{
|
||||
return rdcstr();
|
||||
}
|
||||
|
||||
void RemoteHost::SetLastCapturePath(const rdcstr &path)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoteHost::SetConnected(bool connected)
|
||||
{
|
||||
}
|
||||
|
||||
void RemoteHost::SetShutdown()
|
||||
{
|
||||
}
|
||||
@@ -312,10 +312,11 @@ int main(int argc, char *argv[])
|
||||
int replayHostIndex = -1;
|
||||
if(parser.isSet(replayhost))
|
||||
{
|
||||
QString replayHost = parser.value(replayhost);
|
||||
for(int i = 0; i < config.RemoteHosts.count(); i++)
|
||||
rdcstr replayHost = parser.value(replayhost);
|
||||
rdcarray<RemoteHost> hosts = config.GetRemoteHosts();
|
||||
for(int i = 0; i < hosts.count(); i++)
|
||||
{
|
||||
if(QString(config.RemoteHosts[i]->hostname) == replayHost)
|
||||
if(hosts[i].Hostname() == replayHost)
|
||||
{
|
||||
replayHostIndex = i;
|
||||
break;
|
||||
|
||||
@@ -300,7 +300,7 @@ void CaptureDialog::on_exePath_textChanged(const QString &text)
|
||||
{
|
||||
QString path = dir.absolutePath();
|
||||
|
||||
if(!m_Ctx.Replay().CurrentRemote())
|
||||
if(!m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
path = QDir::toNativeSeparators(path);
|
||||
|
||||
// match the path separators from the path
|
||||
@@ -503,7 +503,7 @@ void CaptureDialog::CheckAndroidSetup(QString &filename)
|
||||
|
||||
LambdaThread *scan = new LambdaThread([this, filename]() {
|
||||
|
||||
rdcstr host = m_Ctx.Replay().CurrentRemote()->hostname;
|
||||
rdcstr host = m_Ctx.Replay().CurrentRemote().Hostname();
|
||||
RENDERDOC_CheckAndroidPackage(host.c_str(), filename.toUtf8().data(), &m_AndroidFlags);
|
||||
|
||||
const bool debuggable = bool(m_AndroidFlags & AndroidFlags::Debuggable);
|
||||
@@ -535,9 +535,9 @@ void CaptureDialog::androidWarn_mouseClick()
|
||||
{
|
||||
QString exe = ui->exePath->text();
|
||||
|
||||
const RemoteHost *remote = m_Ctx.Replay().CurrentRemote();
|
||||
RemoteHost remote = m_Ctx.Replay().CurrentRemote();
|
||||
|
||||
if(!remote)
|
||||
if(!remote.IsValid())
|
||||
{
|
||||
RDDialog::critical(this, tr("Android server disconnected"),
|
||||
tr("You've been disconnected from the android server.\n\n"
|
||||
@@ -545,7 +545,7 @@ void CaptureDialog::androidWarn_mouseClick()
|
||||
return;
|
||||
}
|
||||
|
||||
rdcstr host = remote->hostname;
|
||||
rdcstr host = remote.Hostname();
|
||||
|
||||
QString caption = tr("Application is not debuggable");
|
||||
|
||||
@@ -650,9 +650,9 @@ void CaptureDialog::on_exePathBrowse_clicked()
|
||||
initDir = dir.absolutePath();
|
||||
initExe = f.fileName();
|
||||
}
|
||||
else if(m_Ctx.Replay().CurrentRemote())
|
||||
else if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
{
|
||||
initDir = m_Ctx.Replay().CurrentRemote()->lastCapturePath;
|
||||
initDir = m_Ctx.Replay().CurrentRemote().LastCapturePath();
|
||||
}
|
||||
else if(!m_Ctx.Config().LastCapturePath.isEmpty())
|
||||
{
|
||||
@@ -663,7 +663,7 @@ void CaptureDialog::on_exePathBrowse_clicked()
|
||||
|
||||
QString filename;
|
||||
|
||||
if(m_Ctx.Replay().CurrentRemote())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
{
|
||||
VirtualFileDialog vfd(m_Ctx, initDir, this);
|
||||
RDDialog::show(&vfd);
|
||||
@@ -678,7 +678,7 @@ void CaptureDialog::on_exePathBrowse_clicked()
|
||||
{
|
||||
SetExecutableFilename(filename);
|
||||
|
||||
if(m_Ctx.Replay().CurrentRemote() && m_Ctx.Replay().CurrentRemote()->IsADB())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsADB())
|
||||
{
|
||||
CheckAndroidSetup(filename);
|
||||
}
|
||||
@@ -691,9 +691,9 @@ void CaptureDialog::on_workDirBrowse_clicked()
|
||||
|
||||
if(initDir.isEmpty())
|
||||
{
|
||||
if(m_Ctx.Replay().CurrentRemote())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
{
|
||||
initDir = m_Ctx.Replay().CurrentRemote()->lastCapturePath;
|
||||
initDir = m_Ctx.Replay().CurrentRemote().LastCapturePath();
|
||||
}
|
||||
else if(!QDir(initDir).exists())
|
||||
{
|
||||
@@ -709,7 +709,7 @@ void CaptureDialog::on_workDirBrowse_clicked()
|
||||
|
||||
QString dir;
|
||||
|
||||
if(m_Ctx.Replay().CurrentRemote())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
{
|
||||
VirtualFileDialog vfd(m_Ctx, initDir, this);
|
||||
vfd.setDirBrowse();
|
||||
@@ -1021,12 +1021,12 @@ void CaptureDialog::SetExecutableFilename(const rdcstr &filename)
|
||||
{
|
||||
QString fn = filename;
|
||||
|
||||
if(!m_Ctx.Replay().CurrentRemote())
|
||||
if(!m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
fn = QDir::toNativeSeparators(QFileInfo(fn).absoluteFilePath());
|
||||
|
||||
ui->exePath->setText(fn);
|
||||
|
||||
if(m_Ctx.Replay().CurrentRemote())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
{
|
||||
// remove the filename itself before setting the last capture path. Try /, then \ as path
|
||||
// separator. If no separators are found, there is no path to set.
|
||||
@@ -1045,7 +1045,7 @@ void CaptureDialog::SetExecutableFilename(const rdcstr &filename)
|
||||
fn = QString();
|
||||
}
|
||||
|
||||
m_Ctx.Replay().CurrentRemote()->lastCapturePath = fn;
|
||||
m_Ctx.Replay().CurrentRemote().SetLastCapturePath(fn);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1122,9 +1122,7 @@ void CaptureDialog::UpdateGlobalHook()
|
||||
|
||||
void CaptureDialog::UpdateRemoteHost()
|
||||
{
|
||||
const RemoteHost *host = m_Ctx.Replay().CurrentRemote();
|
||||
|
||||
if(host && host->IsADB())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsADB())
|
||||
ui->cmdLineLabel->setText(tr("Intent Arguments"));
|
||||
else
|
||||
ui->cmdLineLabel->setText(tr("Command-line Arguments"));
|
||||
@@ -1188,7 +1186,7 @@ void CaptureDialog::TriggerCapture()
|
||||
}
|
||||
|
||||
// for non-remote captures, check the executable locally
|
||||
if(!m_Ctx.Replay().CurrentRemote())
|
||||
if(!m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
{
|
||||
if(!QFileInfo::exists(exe))
|
||||
{
|
||||
@@ -1201,7 +1199,7 @@ void CaptureDialog::TriggerCapture()
|
||||
QString workingDir;
|
||||
|
||||
// for non-remote captures, check the directory locally
|
||||
if(m_Ctx.Replay().CurrentRemote())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
{
|
||||
workingDir = ui->workDirPath->text();
|
||||
}
|
||||
|
||||
@@ -705,9 +705,7 @@ bool LiveCapture::checkAllowClose()
|
||||
// we either have to save or delete the capture. Make sure that if it's remote that we are able
|
||||
// to by having an active connection or replay context on that host.
|
||||
if(suppressRemoteWarning == false && (!m_Connection || !m_Connection->Connected()) &&
|
||||
!cap->local && (!m_Ctx.Replay().CurrentRemote() ||
|
||||
QString(m_Ctx.Replay().CurrentRemote()->hostname) != m_Hostname ||
|
||||
!m_Ctx.Replay().CurrentRemote()->connected))
|
||||
!cap->local && m_Ctx.Replay().CurrentRemote().Hostname() != rdcstr(m_Hostname))
|
||||
{
|
||||
QMessageBox::StandardButton res2 = RDDialog::question(
|
||||
this, tr("No active replay context"),
|
||||
@@ -752,9 +750,7 @@ void LiveCapture::openCapture(Capture *cap)
|
||||
{
|
||||
cap->opened = true;
|
||||
|
||||
if(!cap->local && (!m_Ctx.Replay().CurrentRemote() ||
|
||||
QString(m_Ctx.Replay().CurrentRemote()->hostname) != m_Hostname ||
|
||||
!m_Ctx.Replay().CurrentRemote()->connected))
|
||||
if(!cap->local && m_Ctx.Replay().CurrentRemote().Hostname() != rdcstr(m_Hostname))
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("No active replay context"),
|
||||
@@ -821,9 +817,7 @@ bool LiveCapture::saveCapture(Capture *cap, QString path)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!m_Ctx.Replay().CurrentRemote() ||
|
||||
QString(m_Ctx.Replay().CurrentRemote()->hostname) != m_Hostname ||
|
||||
!m_Ctx.Replay().CurrentRemote()->connected)
|
||||
if(m_Ctx.Replay().CurrentRemote().Hostname() != rdcstr(m_Hostname))
|
||||
{
|
||||
RDDialog::critical(this, tr("No active replay context"),
|
||||
tr("This capture is on remote host %1 and there is no active replay "
|
||||
@@ -1054,9 +1048,7 @@ void LiveCapture::connectionClosed()
|
||||
// to this machine as a remote context
|
||||
if(!cap->local)
|
||||
{
|
||||
if(!m_Ctx.Replay().CurrentRemote() ||
|
||||
QString(m_Ctx.Replay().CurrentRemote()->hostname) != m_Hostname ||
|
||||
!m_Ctx.Replay().CurrentRemote()->connected)
|
||||
if(m_Ctx.Replay().CurrentRemote().Hostname() != rdcstr(m_Hostname))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,25 +58,16 @@ static RemoteConnect getRemoteConnect(RDTreeWidgetItem *item)
|
||||
return item->tag().value<RemoteConnect>();
|
||||
}
|
||||
|
||||
static void setRemoteHost(RDTreeWidgetItem *item, RemoteHost *host)
|
||||
static void setRemoteHost(RDTreeWidgetItem *item, RemoteHost host)
|
||||
{
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
item->setTag(QVariant::fromValue((uintptr_t)host));
|
||||
}
|
||||
|
||||
static RemoteHost *getRemoteHost(RDTreeWidgetItem *item)
|
||||
{
|
||||
if(!item)
|
||||
return NULL;
|
||||
|
||||
return (RemoteHost *)item->tag().value<uintptr_t>();
|
||||
item->setTag(host.Hostname());
|
||||
}
|
||||
|
||||
void deleteItemAndHost(RDTreeWidgetItem *item)
|
||||
{
|
||||
delete getRemoteHost(item);
|
||||
delete item;
|
||||
}
|
||||
|
||||
@@ -116,7 +107,7 @@ RemoteManager::RemoteManager(ICaptureContext &ctx, MainWindow *main)
|
||||
|
||||
m_Ctx.Config().AddAndroidHosts();
|
||||
|
||||
for(RemoteHost *h : m_Ctx.Config().RemoteHosts)
|
||||
for(RemoteHost h : m_Ctx.Config().GetRemoteHosts())
|
||||
addHost(h);
|
||||
|
||||
on_hosts_itemSelectionChanged();
|
||||
@@ -125,10 +116,18 @@ RemoteManager::RemoteManager(ICaptureContext &ctx, MainWindow *main)
|
||||
RemoteManager::~RemoteManager()
|
||||
{
|
||||
for(RDTreeWidgetItem *item : m_QueuedDeletes)
|
||||
deleteItemAndHost(item);
|
||||
delete item;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
RemoteHost RemoteManager::getRemoteHost(RDTreeWidgetItem *item)
|
||||
{
|
||||
if(!item)
|
||||
return RemoteHost();
|
||||
|
||||
return m_Ctx.Config().GetRemoteHost(item->tag().toString());
|
||||
}
|
||||
|
||||
void RemoteManager::closeWhenFinished()
|
||||
{
|
||||
m_ExternalRef.acquire(1);
|
||||
@@ -137,15 +136,12 @@ void RemoteManager::closeWhenFinished()
|
||||
|
||||
void RemoteManager::setRemoteServerLive(RDTreeWidgetItem *node, bool live, bool busy)
|
||||
{
|
||||
RemoteHost *host = getRemoteHost(node);
|
||||
RemoteHost host = getRemoteHost(node);
|
||||
|
||||
if(!host)
|
||||
if(!host.IsValid())
|
||||
return;
|
||||
|
||||
host->serverRunning = live;
|
||||
host->busy = busy;
|
||||
|
||||
if(host->IsLocalhost())
|
||||
if(host.IsLocalhost())
|
||||
{
|
||||
node->setIcon(0, QIcon());
|
||||
node->setText(1, QString());
|
||||
@@ -154,11 +150,11 @@ void RemoteManager::setRemoteServerLive(RDTreeWidgetItem *node, bool live, bool
|
||||
{
|
||||
QString text = live ? tr("Remote server running") : tr("No remote server");
|
||||
|
||||
if(host->connected)
|
||||
if(host.IsConnected())
|
||||
text += tr(" (Active Context)");
|
||||
else if(host->versionMismatch)
|
||||
else if(host.IsVersionMismatch())
|
||||
text += tr(" (Version Mismatch)");
|
||||
else if(host->busy)
|
||||
else if(host.IsBusy())
|
||||
text += tr(" (Busy)");
|
||||
|
||||
node->setText(1, text);
|
||||
@@ -167,15 +163,9 @@ void RemoteManager::setRemoteServerLive(RDTreeWidgetItem *node, bool live, bool
|
||||
}
|
||||
}
|
||||
|
||||
bool RemoteManager::isRemoteServerLive(RDTreeWidgetItem *node)
|
||||
void RemoteManager::addHost(RemoteHost host)
|
||||
{
|
||||
RemoteHost *host = getRemoteHost(node);
|
||||
return host && host->serverRunning;
|
||||
}
|
||||
|
||||
void RemoteManager::addHost(RemoteHost *host)
|
||||
{
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem({host->Name(), lit("...")});
|
||||
RDTreeWidgetItem *node = new RDTreeWidgetItem({host.Name(), lit("...")});
|
||||
|
||||
node->setItalic(true);
|
||||
node->setIcon(0, Icons::hourglass());
|
||||
@@ -200,15 +190,15 @@ void RemoteManager::updateLookupsStatus()
|
||||
|
||||
void RemoteManager::runRemoteServer(RDTreeWidgetItem *node)
|
||||
{
|
||||
RemoteHost *host = getRemoteHost(node);
|
||||
RemoteHost host = getRemoteHost(node);
|
||||
|
||||
if(!host)
|
||||
if(!host.IsValid())
|
||||
{
|
||||
m_Lookups.acquire();
|
||||
return;
|
||||
}
|
||||
|
||||
host->Launch();
|
||||
host.Launch();
|
||||
|
||||
// now refresh this host
|
||||
refreshHost(node);
|
||||
@@ -218,22 +208,25 @@ void RemoteManager::runRemoteServer(RDTreeWidgetItem *node)
|
||||
|
||||
void RemoteManager::refreshHost(RDTreeWidgetItem *node)
|
||||
{
|
||||
RemoteHost *host = getRemoteHost(node);
|
||||
RemoteHost host = getRemoteHost(node);
|
||||
|
||||
if(!host)
|
||||
if(!host.IsValid())
|
||||
return;
|
||||
|
||||
m_Lookups.release();
|
||||
|
||||
// this function looks up the remote connections and for each one open
|
||||
// queries it for the API, target (usually executable name) and if any user is already connected
|
||||
LambdaThread *th = new LambdaThread([this, node, host]() {
|
||||
LambdaThread *th = new LambdaThread([ this, node, h = host ]() {
|
||||
QByteArray username = GetSystemUsername().toUtf8();
|
||||
|
||||
host->CheckStatus();
|
||||
// make a mutable copy and check the status
|
||||
RemoteHost host = h;
|
||||
host.CheckStatus();
|
||||
|
||||
GUIInvoke::call(
|
||||
this, [this, node, host]() { setRemoteServerLive(node, host->serverRunning, host->busy); });
|
||||
GUIInvoke::call(this, [this, node, host]() {
|
||||
setRemoteServerLive(node, host.IsServerRunning(), host.IsBusy());
|
||||
});
|
||||
|
||||
uint32_t nextIdent = 0;
|
||||
|
||||
@@ -242,13 +235,13 @@ void RemoteManager::refreshHost(RDTreeWidgetItem *node)
|
||||
// just a sanity check to make sure we don't hit some unexpected case and infinite loop
|
||||
uint32_t prevIdent = nextIdent;
|
||||
|
||||
nextIdent = RENDERDOC_EnumerateRemoteTargets(host->hostname.c_str(), nextIdent);
|
||||
nextIdent = RENDERDOC_EnumerateRemoteTargets(host.Hostname().c_str(), nextIdent);
|
||||
|
||||
if(nextIdent == 0 || prevIdent >= nextIdent)
|
||||
break;
|
||||
|
||||
ITargetControl *conn =
|
||||
RENDERDOC_CreateTargetControl(host->hostname.c_str(), nextIdent, username.data(), false);
|
||||
RENDERDOC_CreateTargetControl(host.Hostname().c_str(), nextIdent, username.data(), false);
|
||||
|
||||
if(conn)
|
||||
{
|
||||
@@ -263,7 +256,7 @@ void RemoteManager::refreshHost(RDTreeWidgetItem *node)
|
||||
else
|
||||
running = tr("Running %1").arg(api);
|
||||
|
||||
RemoteConnect tag(host->hostname, host->Name(), nextIdent);
|
||||
RemoteConnect tag(host.Hostname(), host.Name(), nextIdent);
|
||||
|
||||
GUIInvoke::call(this, [this, node, target, running, tag]() {
|
||||
RDTreeWidgetItem *child = new RDTreeWidgetItem({target, running});
|
||||
@@ -297,7 +290,7 @@ void RemoteManager::updateStatus()
|
||||
ui->refreshAll->setEnabled(true);
|
||||
|
||||
for(RDTreeWidgetItem *item : m_QueuedDeletes)
|
||||
deleteItemAndHost(item);
|
||||
delete item;
|
||||
m_QueuedDeletes.clear();
|
||||
|
||||
// if the external ref is gone now, we can delete ourselves
|
||||
@@ -337,27 +330,27 @@ void RemoteManager::updateConnectButton()
|
||||
ui->connect->setEnabled(true);
|
||||
ui->connect->setText(tr("Connect to App"));
|
||||
|
||||
RemoteHost *host = getRemoteHost(item);
|
||||
RemoteHost host = getRemoteHost(item);
|
||||
|
||||
if(host)
|
||||
if(host.IsValid())
|
||||
{
|
||||
if(host->IsLocalhost())
|
||||
if(host.IsLocalhost())
|
||||
{
|
||||
ui->connect->setText(tr("Run Server"));
|
||||
ui->connect->setEnabled(false);
|
||||
}
|
||||
else if(host->serverRunning)
|
||||
else if(host.IsServerRunning())
|
||||
{
|
||||
ui->connect->setText(tr("Shutdown"));
|
||||
|
||||
if(host->busy && !host->connected)
|
||||
if(host.IsBusy() && !host.IsConnected())
|
||||
ui->connect->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->connect->setText(tr("Run Server"));
|
||||
|
||||
if(host->runCommand.isEmpty())
|
||||
if(host.RunCommand().isEmpty())
|
||||
ui->connect->setEnabled(false);
|
||||
}
|
||||
}
|
||||
@@ -375,23 +368,14 @@ void RemoteManager::addNewHost()
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
for(int i = 0; i < m_Ctx.Config().RemoteHosts.count(); i++)
|
||||
{
|
||||
QString hostname = m_Ctx.Config().RemoteHosts[i]->hostname;
|
||||
if(hostname.compare(host, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RemoteHost h = m_Ctx.Config().GetRemoteHost(host);
|
||||
|
||||
if(!found)
|
||||
if(!h.IsValid())
|
||||
{
|
||||
RemoteHost *h = new RemoteHost();
|
||||
h->hostname = host;
|
||||
h->runCommand = ui->runCommand->text().trimmed();
|
||||
h = RemoteHost((rdcstr)host);
|
||||
h.SetRunCommand(ui->runCommand->text().trimmed());
|
||||
|
||||
m_Ctx.Config().RemoteHosts.push_back(h);
|
||||
m_Ctx.Config().AddRemoteHost(h);
|
||||
m_Ctx.Config().Save();
|
||||
|
||||
addHost(h);
|
||||
@@ -408,11 +392,11 @@ void RemoteManager::setRunCommand()
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
RemoteHost *h = getRemoteHost(item);
|
||||
RemoteHost h = getRemoteHost(item);
|
||||
|
||||
if(h)
|
||||
if(h.IsValid())
|
||||
{
|
||||
h->runCommand = ui->runCommand->text().trimmed();
|
||||
h.SetRunCommand(ui->runCommand->text().trimmed());
|
||||
m_Ctx.Config().Save();
|
||||
}
|
||||
}
|
||||
@@ -426,7 +410,7 @@ void RemoteManager::queueDelete(RDTreeWidgetItem *item)
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteItemAndHost(item);
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,21 +432,21 @@ void RemoteManager::on_hosts_itemSelectionChanged()
|
||||
|
||||
RDTreeWidgetItem *item = ui->hosts->selectedItem();
|
||||
|
||||
RemoteHost *host = item ? getRemoteHost(item) : NULL;
|
||||
RemoteHost host = getRemoteHost(item);
|
||||
|
||||
ui->runCommand->setText(QString());
|
||||
|
||||
if(host)
|
||||
if(host.IsValid())
|
||||
{
|
||||
if(ui->refreshAll->isEnabled())
|
||||
ui->refreshOne->setEnabled(true);
|
||||
|
||||
ui->runCommand->setText(host->runCommand);
|
||||
ui->hostname->setText(host->Name());
|
||||
ui->runCommand->setText(host.RunCommand());
|
||||
ui->hostname->setText(host.Name());
|
||||
|
||||
ui->addUpdateHost->setText(tr("Update"));
|
||||
|
||||
if(host->IsLocalhost() || host->IsADB())
|
||||
if(host.IsLocalhost() || host.IsADB())
|
||||
{
|
||||
// localhost and android hosts cannot be updated or have their run command changed
|
||||
ui->addUpdateHost->setEnabled(false);
|
||||
@@ -532,7 +516,7 @@ void RemoteManager::on_runCommand_keyPress(QKeyEvent *event)
|
||||
void RemoteManager::on_addUpdateHost_clicked()
|
||||
{
|
||||
RDTreeWidgetItem *item = ui->hosts->selectedItem();
|
||||
if(item && getRemoteHost(item))
|
||||
if(getRemoteHost(item).IsValid())
|
||||
setRunCommand();
|
||||
else
|
||||
addNewHost();
|
||||
@@ -589,26 +573,26 @@ void RemoteManager::on_connect_clicked()
|
||||
return;
|
||||
|
||||
RemoteConnect connect = getRemoteConnect(node);
|
||||
RemoteHost *host = getRemoteHost(node);
|
||||
RemoteHost host = getRemoteHost(node);
|
||||
|
||||
if(connect.ident > 0)
|
||||
{
|
||||
connectToApp(node);
|
||||
}
|
||||
else if(host)
|
||||
else if(host.IsValid())
|
||||
{
|
||||
if(host->serverRunning)
|
||||
if(host.IsServerRunning())
|
||||
{
|
||||
QMessageBox::StandardButton res = RDDialog::question(
|
||||
this, tr("Remote server shutdown"),
|
||||
tr("Are you sure you wish to shut down running remote server on %1?").arg(host->Name()),
|
||||
tr("Are you sure you wish to shut down running remote server on %1?").arg(host.Name()),
|
||||
RDDialog::YesNoCancel);
|
||||
|
||||
if(res == QMessageBox::Cancel || res == QMessageBox::No)
|
||||
return;
|
||||
|
||||
// shut down
|
||||
if(host->connected)
|
||||
if(host.IsConnected())
|
||||
{
|
||||
m_Ctx.Replay().ShutdownServer();
|
||||
setRemoteServerLive(node, false, false);
|
||||
@@ -617,7 +601,7 @@ void RemoteManager::on_connect_clicked()
|
||||
{
|
||||
IRemoteServer *server = NULL;
|
||||
ReplayStatus status =
|
||||
RENDERDOC_CreateRemoteServerConnection(host->hostname.c_str(), 0, &server);
|
||||
RENDERDOC_CreateRemoteServerConnection(host.Hostname().c_str(), 0, &server);
|
||||
if(server)
|
||||
server->ShutdownServerAndConnection();
|
||||
setRemoteServerLive(node, false, false);
|
||||
@@ -627,6 +611,14 @@ void RemoteManager::on_connect_clicked()
|
||||
tr("Error shutting down remote server: %1").arg(ToQStr(status)));
|
||||
}
|
||||
|
||||
// kick off a thread to check the status
|
||||
LambdaThread *th = new LambdaThread([ this, h = host ]() {
|
||||
RemoteHost host = h;
|
||||
host.CheckStatus();
|
||||
});
|
||||
th->selfDelete(true);
|
||||
th->start();
|
||||
|
||||
updateConnectButton();
|
||||
}
|
||||
else
|
||||
@@ -654,12 +646,12 @@ void RemoteManager::on_deleteHost_clicked()
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
RemoteHost *host = getRemoteHost(item);
|
||||
RemoteHost host = getRemoteHost(item);
|
||||
|
||||
int itemIdx = ui->hosts->indexOfTopLevelItem(item);
|
||||
|
||||
// don't delete running instances on a host
|
||||
if(item->parent() != ui->hosts->invisibleRootItem() || itemIdx < 0 || !host)
|
||||
if(item->parent() != ui->hosts->invisibleRootItem() || itemIdx < 0 || !host.IsValid())
|
||||
return;
|
||||
|
||||
QString hostname = item->text(0);
|
||||
@@ -676,12 +668,12 @@ void RemoteManager::on_deleteHost_clicked()
|
||||
|
||||
if(res == QMessageBox::Yes)
|
||||
{
|
||||
int32_t idx = m_Ctx.Config().RemoteHosts.indexOf(host);
|
||||
if(idx < 0)
|
||||
RemoteHost h = m_Ctx.Config().GetRemoteHost(host.Hostname());
|
||||
if(!h.IsValid())
|
||||
return;
|
||||
|
||||
// the host will be removed in queueDelete.
|
||||
m_Ctx.Config().RemoteHosts.erase(idx);
|
||||
m_Ctx.Config().RemoveRemoteHost(h);
|
||||
m_Ctx.Config().Save();
|
||||
|
||||
item->clear();
|
||||
|
||||
@@ -77,12 +77,12 @@ private:
|
||||
|
||||
QList<RDTreeWidgetItem *> m_QueuedDeletes;
|
||||
|
||||
RemoteHost getRemoteHost(RDTreeWidgetItem *item);
|
||||
void queueDelete(RDTreeWidgetItem *item);
|
||||
|
||||
bool isRemoteServerLive(RDTreeWidgetItem *node);
|
||||
void setRemoteServerLive(RDTreeWidgetItem *node, bool live, bool busy);
|
||||
|
||||
void addHost(RemoteHost *host);
|
||||
void addHost(RemoteHost host);
|
||||
void updateLookupsStatus();
|
||||
void runRemoteServer(RDTreeWidgetItem *node);
|
||||
|
||||
|
||||
@@ -552,9 +552,10 @@ void MainWindow::OnCaptureTrigger(const QString &exe, const QString &workingDir,
|
||||
}
|
||||
|
||||
LiveCapture *live = new LiveCapture(
|
||||
m_Ctx, m_Ctx.Replay().CurrentRemote() ? m_Ctx.Replay().CurrentRemote()->hostname : "",
|
||||
m_Ctx.Replay().CurrentRemote() ? m_Ctx.Replay().CurrentRemote()->Name() : "", ret.ident,
|
||||
this, this);
|
||||
m_Ctx,
|
||||
m_Ctx.Replay().CurrentRemote().IsValid() ? m_Ctx.Replay().CurrentRemote().Hostname() : "",
|
||||
m_Ctx.Replay().CurrentRemote().IsValid() ? m_Ctx.Replay().CurrentRemote().Name() : "",
|
||||
ret.ident, this, this);
|
||||
ShowLiveCapture(live);
|
||||
callback(live);
|
||||
});
|
||||
@@ -639,8 +640,7 @@ void MainWindow::LoadCapture(const QString &filename, bool temporary, bool local
|
||||
QString machineIdent;
|
||||
ReplaySupport support = ReplaySupport::Unsupported;
|
||||
|
||||
bool remoteReplay =
|
||||
!local || (m_Ctx.Replay().CurrentRemote() && m_Ctx.Replay().CurrentRemote()->connected);
|
||||
bool remoteReplay = !local || m_Ctx.Replay().CurrentRemote().IsConnected();
|
||||
|
||||
if(local)
|
||||
{
|
||||
@@ -701,8 +701,7 @@ void MainWindow::LoadCapture(const QString &filename, bool temporary, bool local
|
||||
[this]() { return contextChooser->isEnabled(); });
|
||||
}
|
||||
|
||||
remoteReplay =
|
||||
(m_Ctx.Replay().CurrentRemote() && m_Ctx.Replay().CurrentRemote()->connected);
|
||||
remoteReplay = m_Ctx.Replay().CurrentRemote().IsConnected();
|
||||
|
||||
if(!remoteReplay)
|
||||
{
|
||||
@@ -753,7 +752,7 @@ void MainWindow::LoadCapture(const QString &filename, bool temporary, bool local
|
||||
QString remoteMessage =
|
||||
tr("This capture was captured with %1 and cannot be replayed on %2.\n\n")
|
||||
.arg(driver)
|
||||
.arg(m_Ctx.Replay().CurrentRemote()->Name());
|
||||
.arg(m_Ctx.Replay().CurrentRemote().Name());
|
||||
|
||||
remoteMessage += tr("Try selecting a different remote context in the status bar.");
|
||||
|
||||
@@ -1005,8 +1004,8 @@ void MainWindow::SetTitle(const QString &filename)
|
||||
prefix += lit(" - ");
|
||||
}
|
||||
|
||||
if(m_Ctx.Replay().CurrentRemote())
|
||||
prefix += tr("Remote: %1 - ").arg(m_Ctx.Replay().CurrentRemote()->Name());
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
prefix += tr("Remote: %1 - ").arg(m_Ctx.Replay().CurrentRemote().Name());
|
||||
|
||||
QString text = prefix + lit("RenderDoc ");
|
||||
|
||||
@@ -1592,8 +1591,8 @@ void MainWindow::remoteProbe()
|
||||
{
|
||||
QMutexLocker lock(&m_ProbeRemoteHostsLock);
|
||||
m_ProbeRemoteHosts.clear();
|
||||
for(RemoteHost *host : m_Ctx.Config().RemoteHosts)
|
||||
m_ProbeRemoteHosts.push_back(*host);
|
||||
for(RemoteHost host : m_Ctx.Config().GetRemoteHosts())
|
||||
m_ProbeRemoteHosts.push_back(host);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1604,41 +1603,20 @@ void MainWindow::remoteProbe()
|
||||
hosts = m_ProbeRemoteHosts;
|
||||
}
|
||||
|
||||
QList<QPair<RemoteHost, RemoteHost>> updates;
|
||||
|
||||
for(RemoteHost &host : hosts)
|
||||
{
|
||||
// don't mess with a host we're connected to - this is handled anyway
|
||||
if(host.connected)
|
||||
if(host.IsConnected())
|
||||
continue;
|
||||
|
||||
RemoteHost updated = host;
|
||||
|
||||
updated.CheckStatus();
|
||||
// this will do the bulk of the status checking on this thread without holding any lock, then
|
||||
// grab the remote host lock and update the config's host (if it's still there)
|
||||
host.CheckStatus();
|
||||
|
||||
// bail as soon as we notice that we're done
|
||||
if(!m_RemoteProbeSemaphore.available())
|
||||
return;
|
||||
|
||||
if(updated != host)
|
||||
updates.push_back(qMakePair(host, updated));
|
||||
}
|
||||
|
||||
GUIInvoke::call(this, [this, updates] {
|
||||
// this is a bit naive - it suffers from the A-B-A problem where the host could be updated
|
||||
// then restored to its original state before we notice. In this case though we don't care
|
||||
// about that, we just don't want to trash some important changes like the connected status
|
||||
// changing or something.
|
||||
|
||||
for(const QPair<RemoteHost, RemoteHost> &u : updates)
|
||||
{
|
||||
for(RemoteHost *host : m_Ctx.Config().RemoteHosts)
|
||||
{
|
||||
if(*host == u.first)
|
||||
*host = u.second;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1661,13 +1639,13 @@ void MainWindow::messageCheck()
|
||||
|
||||
bool disconnected = false;
|
||||
|
||||
if(m_Ctx.Replay().CurrentRemote())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
{
|
||||
bool wasRunning = m_Ctx.Replay().CurrentRemote()->serverRunning;
|
||||
bool wasRunning = m_Ctx.Replay().CurrentRemote().IsServerRunning();
|
||||
|
||||
m_Ctx.Replay().PingRemote();
|
||||
|
||||
if(wasRunning != m_Ctx.Replay().CurrentRemote()->serverRunning)
|
||||
if(wasRunning != m_Ctx.Replay().CurrentRemote().IsServerRunning())
|
||||
{
|
||||
qCritical() << "Remote server disconnected";
|
||||
disconnected = true;
|
||||
@@ -1692,7 +1670,8 @@ void MainWindow::messageCheck()
|
||||
"RenderDoc to reconnect and load the capture again"));
|
||||
}
|
||||
|
||||
if(m_Ctx.Replay().CurrentRemote() && !m_Ctx.Replay().CurrentRemote()->serverRunning)
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid() &&
|
||||
!m_Ctx.Replay().CurrentRemote().IsServerRunning())
|
||||
contextChooser->setIcon(Icons::cross());
|
||||
|
||||
if(!msgs.empty())
|
||||
@@ -1711,11 +1690,11 @@ void MainWindow::messageCheck()
|
||||
}
|
||||
else if(!m_Ctx.IsCaptureLoaded() && !m_Ctx.IsCaptureLoading())
|
||||
{
|
||||
if(m_Ctx.Replay().CurrentRemote())
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid())
|
||||
m_Ctx.Replay().PingRemote();
|
||||
|
||||
GUIInvoke::call(this, [this]() {
|
||||
if(m_Ctx.Replay().CurrentRemote() && !m_Ctx.Replay().CurrentRemote()->serverRunning)
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid() && !m_Ctx.Replay().CurrentRemote().IsServerRunning())
|
||||
{
|
||||
contextChooser->setIcon(Icons::cross());
|
||||
contextChooser->setText(tr("Replay Context: %1").arg(tr("Local")));
|
||||
@@ -1735,32 +1714,35 @@ void MainWindow::FillRemotesMenu(QMenu *menu, bool includeLocalhost)
|
||||
{
|
||||
menu->clear();
|
||||
|
||||
for(int i = 0; i < m_Ctx.Config().RemoteHosts.count(); i++)
|
||||
{
|
||||
RemoteHost *host = m_Ctx.Config().RemoteHosts[i];
|
||||
rdcarray<RemoteHost> hosts = m_Ctx.Config().GetRemoteHosts();
|
||||
|
||||
// add localhost at the end
|
||||
if(host->IsLocalhost())
|
||||
for(int i = 0; i < hosts.count(); i++)
|
||||
{
|
||||
RemoteHost host = hosts[i];
|
||||
|
||||
// add localhost at the end, skip invalid hosts
|
||||
if(host.IsLocalhost() || !host.IsValid())
|
||||
continue;
|
||||
|
||||
QAction *action = new QAction(menu);
|
||||
|
||||
action->setIcon(host->serverRunning && !host->versionMismatch ? Icons::tick() : Icons::cross());
|
||||
if(host->connected)
|
||||
action->setText(tr("%1 (Connected)").arg(host->Name()));
|
||||
else if(host->serverRunning && host->versionMismatch)
|
||||
action->setText(tr("%1 (Bad Version)").arg(host->Name()));
|
||||
else if(host->serverRunning && host->busy)
|
||||
action->setText(tr("%1 (Busy)").arg(host->Name()));
|
||||
else if(host->serverRunning)
|
||||
action->setText(tr("%1 (Online)").arg(host->Name()));
|
||||
action->setIcon(host.IsServerRunning() && !host.IsVersionMismatch() ? Icons::tick()
|
||||
: Icons::cross());
|
||||
if(host.IsConnected())
|
||||
action->setText(tr("%1 (Connected)").arg(host.Name()));
|
||||
else if(host.IsServerRunning() && host.IsVersionMismatch())
|
||||
action->setText(tr("%1 (Bad Version)").arg(host.Name()));
|
||||
else if(host.IsServerRunning() && host.IsBusy())
|
||||
action->setText(tr("%1 (Busy)").arg(host.Name()));
|
||||
else if(host.IsServerRunning())
|
||||
action->setText(tr("%1 (Online)").arg(host.Name()));
|
||||
else
|
||||
action->setText(tr("%1 (Offline)").arg(host->Name()));
|
||||
action->setText(tr("%1 (Offline)").arg(host.Name()));
|
||||
QObject::connect(action, &QAction::triggered, this, &MainWindow::switchContext);
|
||||
action->setData(i);
|
||||
|
||||
// don't allow switching to the connected host
|
||||
if(host->connected)
|
||||
if(host.IsConnected())
|
||||
action->setEnabled(false);
|
||||
|
||||
menu->addAction(action);
|
||||
@@ -1782,18 +1764,18 @@ void MainWindow::FillRemotesMenu(QMenu *menu, bool includeLocalhost)
|
||||
|
||||
void MainWindow::setRemoteHost(int hostIdx)
|
||||
{
|
||||
RemoteHost *host = NULL;
|
||||
if(hostIdx >= 0 && hostIdx < m_Ctx.Config().RemoteHosts.count())
|
||||
{
|
||||
host = m_Ctx.Config().RemoteHosts[hostIdx];
|
||||
}
|
||||
rdcarray<RemoteHost> hosts = m_Ctx.Config().GetRemoteHosts();
|
||||
|
||||
RemoteHost host;
|
||||
if(hostIdx >= 0 && hostIdx < hosts.count())
|
||||
host = hosts[hostIdx];
|
||||
|
||||
for(LiveCapture *live : m_LiveCaptures)
|
||||
{
|
||||
// allow live captures to this host to stay open, that way
|
||||
// we can connect to a live capture, then switch into that
|
||||
// context
|
||||
if(host && live->hostname() == host->hostname)
|
||||
if(host.IsValid() && live->hostname() == host.Hostname())
|
||||
continue;
|
||||
|
||||
if(!live->checkAllowClose())
|
||||
@@ -1808,7 +1790,7 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
// allow live captures to this host to stay open, that way
|
||||
// we can connect to a live capture, then switch into that
|
||||
// context
|
||||
if(host && live->hostname() == host->hostname)
|
||||
if(host.IsValid() && live->hostname() == host.Hostname())
|
||||
continue;
|
||||
|
||||
live->cleanItems();
|
||||
@@ -1817,7 +1799,7 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
|
||||
m_Ctx.Replay().DisconnectFromRemoteServer();
|
||||
|
||||
if(!host)
|
||||
if(!host.IsValid())
|
||||
{
|
||||
contextChooser->setIcon(Icons::house());
|
||||
contextChooser->setText(tr("Replay Context: %1").arg(tr("Local")));
|
||||
@@ -1833,8 +1815,8 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
}
|
||||
else
|
||||
{
|
||||
contextChooser->setText(tr("Replay Context: %1").arg(host->Name()));
|
||||
contextChooser->setIcon(host->serverRunning ? Icons::connect() : Icons::disconnect());
|
||||
contextChooser->setText(tr("Replay Context: %1").arg(host.Name()));
|
||||
contextChooser->setIcon(host.IsServerRunning() ? Icons::connect() : Icons::disconnect());
|
||||
|
||||
// disable until checking is done
|
||||
contextChooser->setEnabled(false);
|
||||
@@ -1845,11 +1827,12 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
|
||||
statusText->setText(tr("Checking remote server status..."));
|
||||
|
||||
LambdaThread *th = new LambdaThread([this, host]() {
|
||||
// see if the server is up
|
||||
host->CheckStatus();
|
||||
LambdaThread *th = new LambdaThread([ this, h = host ]() {
|
||||
// make a mutable copy and see if the server is up
|
||||
RemoteHost host = h;
|
||||
host.CheckStatus();
|
||||
|
||||
if(host->IsADB() && !RENDERDOC_IsAndroidSupported(host->hostname.c_str()))
|
||||
if(host.IsADB() && !RENDERDOC_IsAndroidSupported(host.Hostname().c_str()))
|
||||
{
|
||||
// check to see if we should warn the user about this unsupported android version.
|
||||
GUIInvoke::call(this, [this]() {
|
||||
@@ -1869,7 +1852,7 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
});
|
||||
}
|
||||
|
||||
if(!host->serverRunning && !host->runCommand.isEmpty())
|
||||
if(!host.IsServerRunning() && !host.RunCommand().isEmpty())
|
||||
{
|
||||
GUIInvoke::call(this, [this]() {
|
||||
statusText->setText(tr("Running remote server command..."));
|
||||
@@ -1877,28 +1860,28 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
statusProgress->setMaximum(0);
|
||||
});
|
||||
|
||||
ReplayStatus launchStatus = host->Launch();
|
||||
ReplayStatus launchStatus = host.Launch();
|
||||
if(launchStatus != ReplayStatus::Succeeded)
|
||||
{
|
||||
showLaunchError(launchStatus);
|
||||
}
|
||||
|
||||
// check if it's running now
|
||||
host->CheckStatus();
|
||||
host.CheckStatus();
|
||||
|
||||
GUIInvoke::call(this, [this]() { statusProgress->setVisible(false); });
|
||||
}
|
||||
|
||||
ReplayStatus status = ReplayStatus::Succeeded;
|
||||
|
||||
if(host->serverRunning && !host->busy)
|
||||
if(host.IsServerRunning() && !host.IsBusy())
|
||||
{
|
||||
status = m_Ctx.Replay().ConnectToRemoteServer(host);
|
||||
}
|
||||
|
||||
GUIInvoke::call(this, [this, host, status]() {
|
||||
contextChooser->setIcon(host->serverRunning && !host->busy ? Icons::connect()
|
||||
: Icons::disconnect());
|
||||
contextChooser->setIcon(host.IsServerRunning() && !host.IsBusy() ? Icons::connect()
|
||||
: Icons::disconnect());
|
||||
|
||||
if(status != ReplayStatus::Succeeded)
|
||||
{
|
||||
@@ -1906,22 +1889,22 @@ void MainWindow::setRemoteHost(int hostIdx)
|
||||
contextChooser->setText(tr("Replay Context: %1").arg(tr("Local")));
|
||||
statusText->setText(tr("Connection failed: %1").arg(ToQStr(status)));
|
||||
}
|
||||
else if(host->versionMismatch)
|
||||
else if(host.IsVersionMismatch())
|
||||
{
|
||||
statusText->setText(
|
||||
tr("Remote server is not running RenderDoc %1").arg(lit(FULL_VERSION_STRING)));
|
||||
}
|
||||
else if(host->busy)
|
||||
else if(host.IsBusy())
|
||||
{
|
||||
statusText->setText(tr("Remote server in use elsewhere"));
|
||||
}
|
||||
else if(host->serverRunning)
|
||||
else if(host.IsServerRunning())
|
||||
{
|
||||
statusText->setText(tr("Remote server ready"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!host->runCommand.isEmpty())
|
||||
if(!host.RunCommand().isEmpty())
|
||||
statusText->setText(tr("Remote server not running or failed to start"));
|
||||
else
|
||||
statusText->setText(tr("Remote server not running - no start command configured"));
|
||||
@@ -2030,7 +2013,7 @@ void MainWindow::OnCaptureClosed()
|
||||
SetTitle();
|
||||
|
||||
// if the remote sever disconnected during capture replay, resort back to a 'disconnected' state
|
||||
if(m_Ctx.Replay().CurrentRemote() && !m_Ctx.Replay().CurrentRemote()->serverRunning)
|
||||
if(m_Ctx.Replay().CurrentRemote().IsValid() && !m_Ctx.Replay().CurrentRemote().IsServerRunning())
|
||||
{
|
||||
statusText->setText(
|
||||
tr("Remote server disconnected. To attempt to reconnect please select it again."));
|
||||
@@ -2914,10 +2897,10 @@ void MainWindow::showLaunchError(ReplayStatus status)
|
||||
|
||||
bool MainWindow::isCapturableAppRunningOnAndroid()
|
||||
{
|
||||
if(!m_Ctx.Replay().CurrentRemote() || !m_Ctx.Replay().CurrentRemote()->IsADB())
|
||||
if(!m_Ctx.Replay().CurrentRemote().IsADB())
|
||||
return false;
|
||||
|
||||
rdcstr host = m_Ctx.Replay().CurrentRemote()->hostname;
|
||||
rdcstr host = m_Ctx.Replay().CurrentRemote().Hostname();
|
||||
uint32_t ident = RENDERDOC_EnumerateRemoteTargets(host.c_str(), 0);
|
||||
return ident != 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user