void SDeviceOutputLog::ExecuteConsoleCommand(const FString& ExecCommand)
{
	FTargetDeviceEntryPtr SelectedDeviceEntry = TargetDeviceComboBox->GetSelectedItem();
	if (SelectedDeviceEntry.IsValid())
	{
		ITargetDevicePtr PinnedPtr = SelectedDeviceEntry->DeviceWeakPtr.Pin();
		if (PinnedPtr.IsValid())
		{
			PinnedPtr->ExecuteConsoleCommand(ExecCommand);
		}
	}
}
void SDeviceOutputLog::OnDeviceSelectionChanged(FTargetDeviceEntryPtr DeviceEntry, ESelectInfo::Type SelectInfo)
{
	CurrentDeviceOutputPtr.Reset();
	OnClearLog();
	
	if (DeviceEntry.IsValid())
	{
		ITargetDevicePtr PinnedPtr = DeviceEntry->DeviceWeakPtr.Pin();
		if (PinnedPtr.IsValid() && PinnedPtr->IsConnected())
		{
			CurrentDeviceOutputPtr = PinnedPtr->CreateDeviceOutputRouter(this);
		}
	}
}
FText SDeviceOutputLog::GetTargetDeviceText(FTargetDeviceEntryPtr DeviceEntry) const
{
	if (DeviceEntry.IsValid())
	{
		ITargetDevicePtr PinnedPtr = DeviceEntry->DeviceWeakPtr.Pin();
		if (PinnedPtr.IsValid() && PinnedPtr->IsConnected())
		{
			return FText::FromString(DeviceEntry->DeviceName);
		}
		else
		{
			return FText::Format(NSLOCTEXT("OutputLog", "TargetDeviceOffline", "{0} (Offline)"), FText::FromString(DeviceEntry->DeviceName));
		}
	}
	else
	{
		return NSLOCTEXT("OutputLog", "UnknownTargetDevice", "<Unknown device>");
	}
}
void SDeviceDetails::HandleModelSelectedDeviceServiceChanged( )
{
	FeatureList.Empty();

	ITargetDeviceServicePtr DeviceService = Model->GetSelectedDeviceService();

	if (DeviceService.IsValid())
	{
		ITargetDevicePtr TargetDevice = DeviceService->GetDevice();

		if (TargetDevice.IsValid())
		{
			const ITargetPlatform& TargetPlatform = TargetDevice->GetTargetPlatform();

			// platform features
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("AudioStreaming"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::AudioStreaming))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("DistanceFieldShadows"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::DistanceFieldShadows))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("GrayscaleSRGB"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::GrayscaleSRGB))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("HighQualityLightmaps"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::HighQualityLightmaps))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("LowQualityLightmaps"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::LowQualityLightmaps))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("MultipleGameInstances"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::MultipleGameInstances))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("Packaging"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::Packaging))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("SdkConnectDisconnect"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::SdkConnectDisconnect))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("Tessellation"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::Tessellation))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("TextureStreaming"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::TextureStreaming))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("UserCredentials"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::UserCredentials))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("MobileRendering"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::MobileRendering))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("DeferredRendering"), TargetPlatform.SupportsFeature(ETargetPlatformFeatures::DeferredRendering))));

			// device features
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("MultiLaunch"), TargetDevice->SupportsFeature(ETargetDeviceFeatures::MultiLaunch))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("PowerOff"), TargetDevice->SupportsFeature(ETargetDeviceFeatures::PowerOff))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("PowerOn"), TargetDevice->SupportsFeature(ETargetDeviceFeatures::PowerOn))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("ProcessSnapshot"), TargetDevice->SupportsFeature(ETargetDeviceFeatures::ProcessSnapshot))));
			FeatureList.Add(MakeShareable(new FDeviceDetailsFeature(TEXT("Reboot"), TargetDevice->SupportsFeature(ETargetDeviceFeatures::Reboot))));
		}
	}

	FeatureListView->RequestListRefresh();
	QuickInfo->SetDeviceService(DeviceService);
}
bool FDeployCommand::Run( )
{
	bool bDeployed = false;

	// get the target device
	FString DevicesList;
	FParse::Value(FCommandLine::Get(), TEXT("-DEVICE="), DevicesList);

	// get the file manifest
	FString Manifest;
	FParse::Value(FCommandLine::Get(), TEXT("-MANIFEST="), Manifest);

	FString SourceDir;
	FParse::Value(FCommandLine::Get(), TEXT("-SOURCEDIR="), SourceDir);

	ITargetPlatformManagerModule* TPM = GetTargetPlatformManager();

	if (!TPM)
	{
		return false;
	}

	// Initialize the messaging subsystem so we can do device discovery.
	FModuleManager::Get().LoadModuleChecked("Messaging");

	// load plug-in modules
	// @todo: allow for better plug-in support in standalone Slate apps
	IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PreDefault);

	while (!DevicesList.IsEmpty())
	{
		FString Device;
		if (!DevicesList.Split(TEXT("+"), &Device, &DevicesList))
		{
			Device = DevicesList;
			DevicesList.Empty();
		}

		double DeltaTime = 0.0;
		double LastTime = FPlatformTime::Seconds();

		// We track the message sent time because we have to keep updating the loop until the message is *actually sent*. (ie all packets queued, sent, buffer flushed, etc.)
		double MessageSentTime = 0.0;
		bool bMessageSent = false;

		while (!GIsRequestingExit && ((MessageSentTime > LastTime + 1.0) || (MessageSentTime <= 0.1)))
		{
			FTaskGraphInterface::Get().ProcessThreadUntilIdle(ENamedThreads::GameThread);
			FTicker::GetCoreTicker().Tick(DeltaTime);
			FPlatformProcess::Sleep(0);

			DeltaTime = FPlatformTime::Seconds() - LastTime;
			LastTime = FPlatformTime::Seconds();

			if (!bMessageSent)
			{
				const TArray<ITargetPlatform*>& Platforms = TPM->GetActiveTargetPlatforms();

				FString Platform;
				FString DeviceName;

				Device.Split(TEXT("@"), &Platform, &DeviceName);

				FTargetDeviceId DeviceId(Platform, DeviceName);
				ITargetDevicePtr TargetDevice;

				for (int32 Index = 0; Index < Platforms.Num(); ++Index)
				{
					TargetDevice = Platforms[Index]->GetDevice(DeviceId);

					if (TargetDevice.IsValid())
					{
						FString OutId;

						if (Platforms[Index]->PackageBuild(SourceDir))
						{
							if (TargetDevice->Deploy(SourceDir, OutId))
							{
								bDeployed = true;
							}

							MessageSentTime = LastTime;
							bMessageSent = true;
						}
						else
						{
							MessageSentTime = LastTime;
							bMessageSent = true;
						}
					}
				}
			}
		}
	}

	return bDeployed;
}