-
Notifications
You must be signed in to change notification settings - Fork 263
Target Manager Programming Discussion
The ATF Target Manager Sample uses TargetEnumerationService
and related components to manage targets. Targets are created by applications and are network endpoints, such as IP addresses, PS3™ and PS4™ DevKits, and PlayStation®Vita DevKits.
Target providers, such as TcpIpTargetProvider
, discover and report targets of their specific type and these targets' parameters. Once found, you can edit and, in some cases, add and remove, targets, of that type with the provider. TargetEnumerationService
enumerates all available target providers, combining the targets' information into a list view for displaying and editing.
TargetManager has very little code of its own, and relies on interfaces and classes in the Sce.Atf.Applications.NetworkTargetServices
namespace for its operation. However, TargetManager does not use all of the interfaces and classes in this namespace. This namespace also supports creating and servicing targets, which TargetManager does not do. This article focuses on the items used by TargetManager in this namespace.
Several applications based on ATF create their own target managers similar to the TargetManager sample. These applications include the StateMachine and Scream tools.
TargetManager simply imports target related components to build the application. These components reside in the Sce.Atf.Applications.NetworkTargetServices
namespace, which also contains an interface and classes that serve building targets.
Targets are classified by the type of the communication protocol used to communicate with the target. There are two protocols: TCP for x86, PS3™, and PS4™ targets, and Deci4p for PlayStation®Vita DevKits, and these describe the two types.
The classes and interfaces used can be divided into consumers and providers. Consumers use information from the providers, which compile a list of targets of each type. ITargetConsumer
handles updating the target list user interface and provides a target list for the consumer. ITargetProvider
enumerates targets for the particular provider and adds and removes targets.
The consumer is TargetEnumerationService
, implementing ITargetConsumer
. This component creates a ListView
control for the targets and their information, embodied in the TargetInfo
class.
The providers are TcpIpTargetProvider
and Deci4pTargetProvider
, both implementing ITargetProvider
. These manage the list of targets: editing, and for TcpIpTargetProvider
, adding, and removing them. TCP targets are added by users; Deci4p are discovered by the provider. These classes inform the user when changes occur so the target display list can be updated.
TargetCommands
creates the context menu commands on the ListView
control and is their command client.
There is one interface for target consumers, another for providers.
ITargetConsumer
is for classes that consume network target information, such as TargetEnumerationService
, which implements this interface. Such classes usually provide a user interface to view and edit targets. ITargetConsumer
consists of the following:
-
TargetsChanged()
: Updates changed targets for a given provider. -
SelectedTargets
: Gets or sets an enumeration of the selected targets in the consumer, if any, as anIEnumerable<TargetInfo>
. TheTargetInfo
class describes target information. For details, see TargetInfo Class. -
AllTargets
: Gets all targets in the consumer as anIEnumerable<TargetInfo>
ITargetProvider
provides information about a particular kind of target available on the network, such as a TCP accessible device. Its methods and properties access the providers of this type:
-
Name
: Get the provider name. -
GetTargets()
: Get an enumeration of theTargetInfo
for all the targets. -
CanCreateNew
: Get whether a new target can be created. -
CreateNew()
: Create a new target, returning itsTargetInfo
. -
AddTarget()
: Add a new target with the givenTargetInfo
. -
Remove()
: Remove the target with the givenTargetInfo
.
TargetEnumerationService
is a MEF component that does the following:
- Imports the available target providers created by the host application.
- Creates a
ListView
with target information. - Acts as control host client for this
ListView
control. For details, see Control Host Client. - Implements
ITargetConsumer
.
TargetEnumerationService
imports all components implementing ITargetProvider
, so that it can display their information:
[ImportMany]
private IEnumerable<ITargetProvider> m_targetProviders= null;
The field m_targetProviders
is get or set in the TargetProviders
property.
Providers implemented in the ATF framework include the Deci4pTargetProvider
and TcpIpTargetProvider
components. More such providers could be added. For the discussion of target providers, see Target Provider Classes.
The component's IInitializable.Initialize()
method calls SetUpTargetsView()
to create a targets display control, which can be used as a docked control or a stand alone dialog:
void IInitializable.Initialize()
{
// force creation of the window handles on the GUI thread
// see http://forums.msdn.microsoft.com/en-US/clr/thread/fa033425-0149-4b9a-9c8b-bcd2196d5471/
var handle = MainForm.Handle;
var control = SetUpTargetsView();
if (!ShowAsDialog)
{
m_controlHostService.RegisterControl(
control,
new ControlInfo(
"Targets".Localize(),
"Controls for managing targets.".Localize(),
StandardControlGroup.Bottom),
this);
}
if (m_settingsService != null)
{
m_settingsService.RegisterSettings(this,
new BoundPropertyDescriptor(this, () => PersistedUISettings, "UI Settings".Localize(), null, null));
m_settingsService.RegisterSettings(this,
new BoundPropertyDescriptor(this, () => PersistedSelectedTargets, "Selected Targets".Localize(), null, null));
}
}
SetUpTargetsView()
creates and configures a DataBoundListView
, which extends ListView
with data binding and cell editing functionality. If the control is not a dialog, it's registered with the Control Host Service. Settings in the control that persist between sessions are registered with the Settings Service. The properties PersistedUISettings
and PersistedSelectedTargets
get and set persistent values.
TargetEnumerationService
also imports context menu providers for its context menu:
[ImportMany]
private IEnumerable<Lazy<IContextMenuCommandProvider>> m_contextMenuCommandProviders;
Menu items for the control are provided by the TargetCommands
component, which implements IContextMenuCommandProvider
. For details, see TargetCommands Component.
The bulk of the code in TargetEnumerationService
creates the DataBoundListView
control and handles its events. For example, the CellValidating
event is raised when one of the cells of the DataBoundListView
changes; the listView_CellValidating()
event handler validates the change.
This client is very simple. The only method that does anything is Activate()
, which brings focus to the DataBoundListView
control to interactively select and edit targets.
The ITargetConsumer.TargetsChanged()
method updates the target view in the DataBoundListView
control. All target providers call TargetsChanged()
when a target is added, removed, or changed so the target display stays current.
The properties SelectedTargets
and AllTargets
get known targets as an IEnumerable<TargetInfo>
. SelectedTargets
can also set the target selection.
Target providers manage targets that are using a given type of communications protocol. Deci4p is a proprietary protocol handling the PlayStation®Vita DevKit. Everything else, x86, PS3™, and PS4™, is handled by TCP.
This section discusses the target provider components and their auxiliary classes.
TargetInfo
encapsulates target information in its gettable and settable properties, which are all string
values except for Scope
:
-
Name
: Target name. -
Platform
: Type of platform the target can run on, such as as "Ps3" or "Vita". -
Endpoint
: Network endpoint in string format; an IP address for TCP. -
Protocol
: Type of protocol the target can use. Currently, this is either "Tcp" or "Deci4p". -
Scope
:TargetScope
enumeration indicating how the target is persisted for applications that use TargetManager:-
PerApp
: Save target data for the current application. All users on this computer see this target when they run this application. Other applications that use TargetManager do not see this target. This is the default value for TCP targets. -
PerUser
: Save target data for the current user. Other applications that use the TargetManager can see this target for this user; other users won't see this target in any application. -
AllUsers
: Save the target data for all users and applications, so this target is visible for all users in any application that uses the TargetManager framework.
-
TargetInfo
implements INotifyPropertyChanged
, which contains one event, PropertyChanged
. It has the method OnPropertyChanged()
that simply raises this event.
TargetInfo
has two ATF classes that derive from it, described in the next sections.
TcpIpTargetInfo
describes TCP target information, and is used by TcpIpTargetProvider
. TcpIpTargetInfo
contains methods to verify that the IP address provided is valid. Its Validate()
method checks this, as well as the other properties, and is called by TargetEnumerationService
when any properties change in a TCP target listed.
TcpIpTargetInfo
also has derived classes:
-
X86TargetInfo
: X86 target information. -
Ps3TargetInfo
: PS3™ target information. -
Ps4TargetInfo
: PS4™ target information.
Ps3TargetInfo
:
public Ps3TargetInfo()
: base()
{
Name = "Ps3Host";
Platform = PlatformName;
Endpoint = "10.89.0.0:1338";
}
Deci4pTargetInfo
holds information about a Deci4p target and is used by Deci4pTargetProvider
in its process of finding active targets of this type.
TargetManager imports the TcpIpTargetProvider
component, which is one of the two providers implementing ITargetProvider
.
TCP targets are not found; they are added by users. The list of targets is persisted using the Setting Service to save the list between sessions. This requires using the Setting Service to set the saved values when a target changes and to read the saved values when the application starts. The PersistedTargets
property gets and sets the persisted targets list.
The ITargetProvider
implementation manipulates the target list. For instance, GetTargets()
retrieves objects from the targets list in m_targets
:
public IEnumerable<TargetInfo> GetTargets(ITargetConsumer targetConsumer)
{
foreach (var target in m_targets)
yield return target;
}
CreateNew()
returns a new TcpIpTargetInfo
:
public virtual TargetInfo CreateNew()
{
var newTarget = new TcpIpTargetInfo();
return newTarget;
}
AddTarget()
adds the given target to the list and calls TargetsChanged()
to inform each target consumer so its lists can be updated:
public bool AddTarget(TargetInfo target)
{
if (target is TcpIpTargetInfo && !m_targets.Contains(target))
{
m_targets.Add(target);
foreach (var targetConsumer in TargetConsumers)
targetConsumer.TargetsChanged(this, m_targets);
return true;
}
return false;
}
TcpIpTargetProvider
imports as many ITargetConsumer
implementers as it can find to populate its TargetConsumers
property, which is used in AddTarget()
:
[ImportMany]
protected IEnumerable<ITargetConsumer> TargetConsumers { get; set; }
Finally, TcpIpTargetProvider
has its own derived classes to match up with TcpIpTargetInfo
's derived classes:
-
X86TargetProvider
: X86 target provider. -
Ps3TargetProvider
: PS3™ target provider. -
Ps4TargetProvider
: PS4™ target provider.
Ps3TargetProvider
has two gettable string
properties and a CreateNew()
method that constructs and returns a Ps3TargetInfo
:
public class Ps3TargetProvider : TcpIpTargetProvider
{
/// <summary>
/// Gets the provider's user-readable name</summary>
public override string Name { get { return "PS3 Target".Localize(); } }
/// <summary>
/// Gets the the identifier of the provider</summary>
/// <returns>A string that contains the identifier.</returns>
public override string Id { get { return @"Sce.Atf.Ps3TcpIpTargetProvider"; } }
/// <summary>
/// Creates a new target</summary>
/// <remarks>Creates and returns a TargetInfo, but does not add it to the watched list</remarks>
/// <returns>TargetInfo for new target</returns>
public override TargetInfo CreateNew()
{
var newTarget = new Ps3TargetInfo();
return newTarget;
}
}
TargetManager also imports the Deci4pTargetProvider
component, one of the two providers implementing ITargetProvider
. This supports only the PlayStation®Vita platform.
Unlike TCP targets, you can't create targets — PlayStation®Vita targets can only be discovered. Its IInitializable.Initialize()
method starts a background task in another thread to attempt to find these targets with its FindTargets()
method, adding them to a list as they are found. FindTargets()
only works if you have installed the PlayStation®Vita SDK on your local computer.
This limitation makes ITargetProvider
's implementation rudimentary. Name
always gets "Vita Target". CanCreateNew
gets false
. CreateNew()
throws an exception. Both AddTarget()
and Remove()
do nothing but return false
. GetTargets()
does return the list of targets found.
Deci4pTargetProvider
also imports as many ITargetConsumer
implementers as it can find to update the target display of each consumer:
[ImportMany(typeof(ITargetConsumer))]
protected IEnumerable<ITargetConsumer> TargetConsumers { get; set; }
TargetCommands
adds the context menu commands for the targets list control, providing the command client for these commands, so it implements ICommandClient
:
public class TargetCommands : ICommandClient, IContextMenuCommandProvider, IInitializable
To create the right commands, TargetCommands
needs to know which target providers are available. It does so by importing all exported ITargetProvider
and accessing them with TargetProviders
:
[ImportMany]
private IEnumerable<ITargetProvider> m_targetProviders = null;
/// <summary>
/// Gets or sets the target providers</summary>
public IEnumerable<ITargetProvider> TargetProviders
{
get { return m_targetProviders; }
set { m_targetProviders = value; }
}
TargetCommands
's IInitializable.Initialize()
creates the commands, based on available targets:
void IInitializable.Initialize()
{
if (CommandService == null)
return;
if (Deci4pTargetProvider.SdkInstalled)
{
var cmdInfo = new CommandInfo(
CommandTag.VitaNeighborhood,
null,
null,
"Edit Vita Target in Neighborhood".Localize(),
"Edit Vita Target in Neighborhood".Localize());
cmdInfo.ShortcutsEditable = false;
CommandService.RegisterCommand(cmdInfo, this);
}
foreach (var targetProvider in TargetProviders)
{
if (targetProvider.CanCreateNew)
{
string addCmdTag = AddNewString.Localize() + targetProvider.Name;
CommandService.RegisterCommand(
new CommandInfo(
addCmdTag,
null,
null,
addCmdTag,
"Creates a new target".Localize()),
this);
m_addTargetsCmdTags.Add(addCmdTag);
string remCmdTag = "Remove ".Localize() + targetProvider.Name;
CommandService.RegisterCommand(
new CommandInfo(
remCmdTag,
null,
null,
remCmdTag,
"Remove selected target".Localize()),
this);
m_removeTargetsCmdTags.Add(remCmdTag);
}
}
}
Deci4p target providers are treated differently than TCP target providers. First, the method checks that a PlayStation®Vita SDK is installed with the Deci4pTargetProvider.SdkInstalled
property. If present, it adds a command to edit PlayStation®Vita targets.
Next, Initialize()
iterates through TargetProviders
to create commands to add and remove targets for each provider. It first checks the CanCreateNew
for the provider to make sure that new targets can be created; they can't for PlayStation®Vita, because Deci4pTargetProvider
's property is this:
public bool CanCreateNew { get { return false; } }
As a result, Add and Remove commands are created only for TcpIpTargetProvider
. The general loop is used, so other types of providers can be added easily.
This interface provides a method to get commands that apply to a given context:
IEnumerable<object> IContextMenuCommandProvider.GetCommands(object context, object selectedTargets)
{
m_selectedTargets = null;
if (context.Is<ITargetConsumer>())
{
m_targetConsumer = context.Cast<ITargetConsumer>();
m_selectedTargets = selectedTargets as IEnumerable<TargetInfo>;
foreach (var cmdTag in m_addTargetsCmdTags)
yield return cmdTag;
if (m_selectedTargets != null && m_selectedTargets.Any())
foreach (var cmdTag in m_removeTargetsCmdTags)
yield return cmdTag;
yield return CommandTag.VitaNeighborhood;
}
}
The commands are available only for the target list control provided by TargetEnumerationService
, the only implementer of ITargetConsumer
, so the method first checks that the given context can be adapted to ITargetConsumer
. If so, it proceeds and saves this context adapted to ITargetConsumer
in m_targetConsumer
, where it is used later to test whether a command can be performed.
Next, the selected objects are adapted to IEnumerable<TargetInfo>
and saved in the field m_selectedTargets
, which is used to test whether commands can be performed and to perform commands. Targets are treated as TargetInfo
objects in TargetManager, so this adaptation works.
Finally, GetCommands()
iterates through the lists m_addTargetsCmdTags
and m_removeTargetsCmdTags
of commands created in Initialize()
. Remove commands are only returned when there are targets selected, hence the m_selectedTargets \!= null && m_selectedTargets.Any()
test.
The ICommandClient
implementation uses the TargetProviders
property and field values like m_addTargetsCmdTags
, already set up by Initialize()
and IContextMenuCommandProvider.GetCommands()
. For example, here's DoCommand()
:
void ICommandClient.DoCommand(object commandTag)
{
if (CommandTag.VitaNeighborhood.Equals(commandTag))
{
// Invoke "Edit Vita Target in Neighborhood" command merely launches the PSP2 Neighborhood app that comes with Vita SDK installer,
// as if you double click "Neighborhood for PlayStation(R)Vita" on your desktop icon.
// This is intended just for a convenience helper to allow users directly bring up the PSP2 app without a detour to desktop first,
// as PSP2 Neighborhood app can reboot, power off, and do much more for the Vita kit.
// {BA414141-28C6-7F3C-45FF-14C28C11EE88} is the registered Neighborhood for PlayStation(R)Vita Shell extension
System.Diagnostics.Process.Start("Explorer.exe", @"/e,/root,::{BA414141-28C6-7F3C-45FF-14C28C11EE88}");
}
else if (m_addTargetsCmdTags.Contains(commandTag))
{
foreach (var targetProvider in TargetProviders)
{
string addCmdTag = AddNewString.Localize() + targetProvider.Name;
if (addCmdTag.Equals(commandTag))
{
targetProvider.AddTarget(targetProvider.CreateNew());
break;
}
}
}
else if (m_removeTargetsCmdTags.Contains(commandTag))
{
foreach (var item in m_selectedTargets)
foreach (var provider in TargetProviders)
provider.Remove(item);
}
}
The commandTag
parameter is matched against existing commands in the command lists, and if a match is found, the corresponding command is executed. The Add command logic does additional processing to find the right target provider for the command and uses the target provider's AddTarget()
method to add the target. The Remove processing tries to remove each selected target with each target provider's Remove()
method, relying on it to do the right thing. Deci4pTargetProvider.Remove()
does nothing — PlayStation®Vita targets can't be added or removed, only discovered — so that's not a problem. And TcpIpTargetProvider.Remove()
checks that the target is one of the TCP targets, so that works also.
- Circuit Editor Programming Discussion: Learn how ATF handles graphs, and provides editors for kinds of graphs, such as circuits.
- Code Editor Programming Discussion: Shows how to interface third party software to an ATF application: the ActiproSoftware SyntaxEditor.
- Diagram Editor Programming Discussion: Very simply combines components from the CircuitEditor, FsmEditor, and StateChartEditor samples into one application, with the abilities of all three, showing the power of components.
-
DOM Property Editor Programming Discussion: Shows how to use the ATF DOM with an XML Schema to define application data with a large variety of attribute types, whose values can be viewed and edited using the ATF
PropertyEditor
component, using various value editors to view and edit attributes. - DOM Tree Editor Programming Discussion: Shows how to edit DOM data using a tree control and display properties in a variety of value editors.
- File Explorer Programming Discussion: Discusses the ATF File Explorer Sample using list and tree controls with adapters.
- FSM Editor Programming Discussion: Tells you about how the ATF FSM Editor Sample edits simple graphs for state machines, using DOM adapters for contexts and validation.
-
Model Viewer Programming Discussion: Shows how the ATF Model Viewer Sample is written, discussing how ATGI and Collada model data is handled, using rendering components, and using a
DesignControl
as a canvas for rendering. -
Simple DOM Editor Programming Discussion: Programming the ATF Simple DOM Editor Sample, creating a palette, using DOM adapters and contexts, editing application data, and searching
DomNode
s. - Simple DOM Editor WPF Programming Discussion: Programming the ATF Simple DOM Editor WPF Sample, which is similar to ATF Simple DOM Editor Sample, but implemented using ATF's WPF framework.
- Simple DOM No XML Editor Programming Discussion: Programming the ATF Simple DOM No XML Editor Sample, which is very similar to ATF Simple DOM Editor Sample, except that it doesn't use XML for either its data model or persisting application data.
- State Chart Editor Programming Discussion: Shows using ATF graph and other classes to create a statechart editor, using DOM adapters, documents, contexts, and validators.
- Target Manager Programming Discussion: Description of how a target manager is implemented using ATF components to manage target devices, such as PlayStation®Vita or PS3™ consoles. A target manager is used in other tools, such as the StateMachine tool.
- Timeline Editor Programming Discussion: Discusses how to create a fairly full-featured timeline editor using the ATF timeline facilities, such as the timeline renderer and the timeline control and its manipulators.
-
Tree List Control Programming Discussion: Demonstrates using the
TreeListControl
andTreeListItemRenderer
classes to display and edit hierarchical data in a tree view with details in columns. -
Tree List Editor Programming Discussion: Demonstrates how to use the ATF tree controls
TreeListView
and its enhancement,TreeListViewEditor
.TreeListView
usesTreeListViewAdapter
, which adaptsTreeListView
to display data in a tree. - Using Dom Programming Discussion: Shows how to use the various parts of the ATF DOM: an XML Schema, a schema metadata class file generated by DomGen, DOM adapters for the data types, a schema loader, and saving application data to an XML file.
- Home
- Getting Started
- Features & Benefits
- Requirements & Dependencies
- Gallery
- Technology & Samples
- Adoption
- News
- Release Notes
- ATF Community
- Searching Documentation
- Using Documentation
- Videos
- Tutorials
- How To
- Programmer's Guide
- Reference
- Code Samples
- Documentation Files
© 2014-2015, Sony Computer Entertainment America LLC