Skip to content

Commit f793474

Browse files
committed
Refactor controller descriptors.
1 parent a2e25b9 commit f793474

14 files changed

+146
-108
lines changed

SerialPrograms/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,8 +635,8 @@ file(GLOB MAIN_SOURCES
635635
Source/Controllers/SerialPABotBase/SerialPABotBase.h
636636
Source/Controllers/SerialPABotBase/SerialPABotBase_Connection.cpp
637637
Source/Controllers/SerialPABotBase/SerialPABotBase_Connection.h
638-
Source/Controllers/SerialPABotBase/SerialPABotBase_Interface.cpp
639-
Source/Controllers/SerialPABotBase/SerialPABotBase_Interface.h
638+
Source/Controllers/SerialPABotBase/SerialPABotBase_Descriptor.cpp
639+
Source/Controllers/SerialPABotBase/SerialPABotBase_Descriptor.h
640640
Source/Integrations/DiscordIntegrationSettings.cpp
641641
Source/Integrations/DiscordIntegrationSettings.h
642642
Source/Integrations/DiscordIntegrationTable.cpp

SerialPrograms/SerialPrograms.pro

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ SOURCES += \
321321
Source/Controllers/NullController.cpp \
322322
Source/Controllers/SerialPABotBase/SerialPABotBase.cpp \
323323
Source/Controllers/SerialPABotBase/SerialPABotBase_Connection.cpp \
324-
Source/Controllers/SerialPABotBase/SerialPABotBase_Interface.cpp \
324+
Source/Controllers/SerialPABotBase/SerialPABotBase_Descriptor.cpp \
325325
Source/Controllers/SuperscalarScheduler.cpp \
326326
Source/Integrations/DiscordIntegrationSettings.cpp \
327327
Source/Integrations/DiscordIntegrationTable.cpp \
@@ -1457,7 +1457,7 @@ HEADERS += \
14571457
Source/Controllers/NullController.h \
14581458
Source/Controllers/SerialPABotBase/SerialPABotBase.h \
14591459
Source/Controllers/SerialPABotBase/SerialPABotBase_Connection.h \
1460-
Source/Controllers/SerialPABotBase/SerialPABotBase_Interface.h \
1460+
Source/Controllers/SerialPABotBase/SerialPABotBase_Descriptor.h \
14611461
Source/Controllers/SuperscalarScheduler.h \
14621462
Source/Integrations/DiscordIntegrationSettings.h \
14631463
Source/Integrations/DiscordIntegrationTable.h \

SerialPrograms/Source/CommonFramework/Panels/UI/PanelListWidget.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ void PanelListWidget::handle_panel_clicked(const std::string& text){
8686
}
8787
try{
8888
std::unique_ptr<PanelInstance> panel = descriptor->make_panel();
89-
panel->from_json(PERSISTENT_SETTINGS().panels[descriptor->identifier()]);
89+
// try{
90+
panel->from_json(PERSISTENT_SETTINGS().panels[descriptor->identifier()]);
91+
// }catch (ParseException&){}
9092
m_panel_holder.load_panel(descriptor, std::move(panel));
9193

9294
PERSISTENT_SETTINGS().panels[JSON_PROGRAM_PANEL] = iter->first;

SerialPrograms/Source/Controllers/ControllerCapability.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace PokemonAutomation{
1111

1212

1313
const EnumStringMap<ControllerInterface> CONTROLLER_INTERFACE_STRINGS{
14+
{ControllerInterface::None, "None"},
1415
{ControllerInterface::SerialPABotBase, "SerialPABotBase"},
1516
};
1617

SerialPrograms/Source/Controllers/ControllerCapability.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ namespace PokemonAutomation{
3232

3333

3434

35-
3635
enum class ControllerInterface{
36+
None,
3737
SerialPABotBase,
3838
};
3939
extern const EnumStringMap<ControllerInterface> CONTROLLER_INTERFACE_STRINGS;
@@ -61,6 +61,8 @@ extern const EnumStringMap<ControllerFeature> CONTROLLER_FEATURE_STRINGS;
6161

6262

6363

64+
65+
6466
class ControllerRequirements{
6567
public:
6668
ControllerRequirements(std::initializer_list<ControllerFeature> args);

SerialPrograms/Source/Controllers/ControllerDescriptor.cpp

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,19 @@ namespace PokemonAutomation{
2222
//
2323
// Here we store a map of all controller types in the program.
2424
//
25-
std::map<std::string, std::unique_ptr<AbstractControllerType>> CONTROLLER_TYPES;
25+
std::map<ControllerInterface, std::unique_ptr<InterfaceType>> ALL_CONTROLLER_INTERFACES;
2626

2727

28-
void AbstractControllerType::register_factory(
29-
const std::string& name,
30-
std::unique_ptr<AbstractControllerType> factory
28+
void InterfaceType::register_factory(
29+
ControllerInterface controller_interface,
30+
std::unique_ptr<InterfaceType> factory
3131
){
32-
auto ret = CONTROLLER_TYPES.emplace(name, std::move(factory));
32+
auto ret = ALL_CONTROLLER_INTERFACES.emplace(controller_interface, std::move(factory));
3333
if (!ret.second){
34-
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Duplicate Factory Name: " + name);
34+
throw InternalProgramError(
35+
nullptr, PA_CURRENT_FUNCTION,
36+
"Duplicate Factory Name: " + CONTROLLER_INTERFACE_STRINGS.get_string(controller_interface)
37+
);
3538
}
3639
}
3740

@@ -45,8 +48,8 @@ get_compatible_descriptors(const ControllerRequirements& requirements){
4548
ret.emplace_back(new NullControllerDescriptor());
4649

4750
// Add all other controllers. We don't filter them at this time.
48-
for (const auto& controller_interface : CONTROLLER_TYPES){
49-
if (controller_interface.first == NullControllerDescriptor::TYPENAME){
51+
for (const auto& controller_interface : ALL_CONTROLLER_INTERFACES){
52+
if (controller_interface.first == ControllerInterface::None){
5053
continue;
5154
}
5255
std::vector<std::shared_ptr<const ControllerDescriptor>> list = controller_interface.second->list();
@@ -58,8 +61,8 @@ get_compatible_descriptors(const ControllerRequirements& requirements){
5861
// required list. For each of those, enumerate all the descriptors and
5962
// combine them into a single list.
6063
for (const auto& device : requirements.map()){
61-
auto iter = CONTROLLER_TYPES.find(device.first);
62-
if (iter != CONTROLLER_TYPES.end()){
64+
auto iter = ALL_CONTROLLER_INTERFACES.find(device.first);
65+
if (iter != ALL_CONTROLLER_INTERFACES.end()){
6366
std::vector<std::shared_ptr<const ControllerDescriptor>> list = iter->second->list();
6467
std::move(list.begin(), list.end(), std::back_inserter(ret));
6568
}
@@ -76,32 +79,60 @@ get_compatible_descriptors(const ControllerRequirements& requirements){
7679

7780

7881
ControllerOption::ControllerOption()
79-
: m_current(new NullControllerDescriptor())
82+
: m_descriptor(new NullControllerDescriptor())
83+
, m_controller_type(ControllerType::None)
8084
{}
8185

8286
void ControllerOption::load_json(const JsonValue& json){
83-
if (json.is_null()){
84-
m_current.reset(new NullControllerDescriptor());
85-
}
86-
const JsonObject& obj = json.to_object_throw();
87-
const std::string& type = obj.get_string_throw("DeviceType");
88-
const JsonValue& params = obj.get_value_throw("Parameters");
89-
90-
auto iter = CONTROLLER_TYPES.find(type);
91-
if (iter == CONTROLLER_TYPES.end()){
92-
m_current.reset(new NullControllerDescriptor());
93-
return;
87+
std::unique_ptr<const ControllerDescriptor> descriptor;
88+
ControllerType controller_type = ControllerType::None;
89+
do{
90+
if (json.is_null()){
91+
break;
92+
}
93+
94+
const JsonObject* obj = json.to_object();
95+
if (obj == nullptr){
96+
break;
97+
}
98+
const std::string* type = obj->get_string("Interface");
99+
if (type == nullptr){
100+
break;
101+
}
102+
const std::string* controller = obj->get_string("Controller");
103+
if (controller != nullptr){
104+
controller_type = CONTROLLER_TYPE_STRINGS.get_enum(*controller);
105+
}
106+
const JsonValue* params = obj->get_value("Parameters");
107+
if (params == nullptr){
108+
break;
109+
}
110+
111+
auto iter = ALL_CONTROLLER_INTERFACES.find(CONTROLLER_INTERFACE_STRINGS.get_enum(*type, ControllerInterface::None));
112+
if (iter == ALL_CONTROLLER_INTERFACES.end()){
113+
break;
114+
}
115+
116+
descriptor = iter->second->make(*params);
117+
118+
}while (false);
119+
120+
if (descriptor == nullptr){
121+
descriptor.reset(new NullControllerDescriptor());
94122
}
95123

96-
m_current = iter->second->make(params);
124+
m_descriptor = std::move(descriptor);
125+
m_controller_type = controller_type;
97126
}
98127
JsonValue ControllerOption::to_json() const{
99-
if (!m_current){
128+
if (!m_descriptor){
100129
return JsonValue();
101130
}
131+
102132
JsonObject obj;
103-
obj["DeviceType"] = m_current->type_name();
104-
obj["Parameters"] = m_current->to_json();
133+
obj["Interface"] = CONTROLLER_INTERFACE_STRINGS.get_string(m_descriptor->interface_type);
134+
obj["Controller"] = CONTROLLER_TYPE_STRINGS.get_string(m_controller_type);
135+
obj["Parameters"] = m_descriptor->to_json();
105136
return obj;
106137
}
107138

SerialPrograms/Source/Controllers/ControllerDescriptor.h

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,35 @@
1616
namespace PokemonAutomation{
1717

1818
class JsonValue;
19-
class AbstractControllerType;
19+
class InterfaceType;
2020
class ControllerDescriptor;
2121
class ControllerConnection;
2222

2323

2424
//
25-
// Represents an entire type of controller.
25+
// Represents an entire controller interface.
2626
//
2727
// For example:
28-
// - "Nintendo Switch via Serial PABotBase" is a type of controller.
29-
// - "Nintendo Switch via Joycon Emulation" is a type of controller. (hypothetical)
30-
// - "Xbox One via whatever..." ...
28+
// - Serial PABotBase
29+
// - Direct USB to X (hypothetical)
30+
// - Emulator IPC (hypothetical)
3131
//
32-
// One instance of this class exists for each type of controller.
32+
// One instance of this class exists for each interface.
3333
//
34-
class AbstractControllerType{
34+
class InterfaceType{
3535
public:
36-
virtual ~AbstractControllerType() = default;
36+
virtual ~InterfaceType() = default;
3737

38-
// Returns a list of all available instances for this controller type.
38+
// Returns a list of all available descriptors for this interface type.
3939
virtual std::vector<std::shared_ptr<const ControllerDescriptor>> list() const = 0;
4040

4141
// Construct a descriptor from a JSON config. (reloading saved controller settings)
4242
virtual std::unique_ptr<ControllerDescriptor> make(const JsonValue& json) const = 0;
4343

4444
protected:
4545
static void register_factory(
46-
const std::string& name,
47-
std::unique_ptr<AbstractControllerType> factory
46+
ControllerInterface controller_interface,
47+
std::unique_ptr<InterfaceType> factory
4848
);
4949
};
5050

@@ -53,7 +53,7 @@ class AbstractControllerType{
5353
// Subclass helper for ControllerType.
5454
//
5555
template <typename DescriptorType>
56-
class ControllerType_t : public AbstractControllerType{
56+
class InterfaceType_t : public InterfaceType{
5757
public:
5858
// Subclasses must implement this function.
5959
virtual std::vector<std::shared_ptr<const ControllerDescriptor>> list() const override;
@@ -67,16 +67,16 @@ class ControllerType_t : public AbstractControllerType{
6767

6868
private:
6969
static int register_class(){
70-
AbstractControllerType::register_factory(
71-
DescriptorType::TYPENAME,
72-
std::make_unique<ControllerType_t<DescriptorType>>()
70+
InterfaceType::register_factory(
71+
DescriptorType::INTERFACE_NAME,
72+
std::make_unique<InterfaceType_t<DescriptorType>>()
7373
);
7474
return 0;
7575
}
7676
static int initializer;
7777
};
7878
template <typename DescriptorType>
79-
int ControllerType_t<DescriptorType>::initializer = register_class();
79+
int InterfaceType_t<DescriptorType>::initializer = register_class();
8080

8181

8282

@@ -88,10 +88,14 @@ int ControllerType_t<DescriptorType>::initializer = register_class();
8888
//
8989
class ControllerDescriptor{
9090
public:
91+
const ControllerInterface interface_type;
92+
93+
ControllerDescriptor(ControllerInterface p_interface_type)
94+
: interface_type(p_interface_type)
95+
{}
9196
virtual ~ControllerDescriptor() = default;
9297
virtual bool operator==(const ControllerDescriptor& x) const = 0;
9398

94-
virtual const char* type_name() const = 0;
9599
virtual std::string display_name() const = 0;
96100

97101
virtual void load_json(const JsonValue& json) = 0;
@@ -108,6 +112,7 @@ class ControllerDescriptor{
108112
) const{
109113
return nullptr;
110114
}
115+
111116
};
112117

113118

@@ -128,16 +133,17 @@ class ControllerOption{
128133
public:
129134
ControllerOption();
130135

131-
std::shared_ptr<const ControllerDescriptor> current() const{
132-
return m_current;
136+
std::shared_ptr<const ControllerDescriptor> descriptor() const{
137+
return m_descriptor;
133138
}
134139

135140
void load_json(const JsonValue& json);
136141
JsonValue to_json() const;
137142

138143
private:
139144
friend class ControllerSession;
140-
std::shared_ptr<const ControllerDescriptor> m_current;
145+
std::shared_ptr<const ControllerDescriptor> m_descriptor;
146+
ControllerType m_controller_type;
141147
};
142148

143149

SerialPrograms/Source/Controllers/ControllerSession.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
#include "Common/Cpp/Exceptions.h"
88
#include "ControllerSession.h"
99

10-
// REMOVE
11-
#include <iostream>
12-
using std::cout;
13-
using std::endl;
10+
//#include <iostream>
11+
//using std::cout;
12+
//using std::endl;
1413

1514
namespace PokemonAutomation{
1615

@@ -42,7 +41,7 @@ ControllerSession::ControllerSession(
4241
, m_requirements(requirements)
4342
, m_option(option)
4443
, m_options_locked(false)
45-
, m_descriptor(option.current())
44+
, m_descriptor(option.descriptor())
4645
, m_connection(m_descriptor->open_connection(logger))
4746
{
4847
// cout << "ControllerSession:ControllerSession(): " << m_descriptor->display_name() << endl;
@@ -58,7 +57,7 @@ void ControllerSession::get(ControllerOption& option){
5857
option = m_option;
5958
}
6059
void ControllerSession::set(const ControllerOption& option){
61-
set_device(option.current());
60+
set_device(option.descriptor());
6261
}
6362

6463

@@ -155,7 +154,7 @@ bool ControllerSession::set_device(const std::shared_ptr<const ControllerDescrip
155154
m_connection->add_status_listener(*this);
156155
}
157156

158-
m_option.m_current = device;
157+
m_option.m_descriptor = device;
159158
m_descriptor = device;
160159
}
161160
signal_controller_changed(device);
@@ -191,21 +190,32 @@ void ControllerSession::pre_not_ready(){
191190
m_listeners.run_method_unique(&Listener::pre_not_ready);
192191
}
193192
void ControllerSession::post_ready(const std::map<ControllerType, std::set<ControllerFeature>>& controllers){
194-
#if 1
195193
if (controllers.empty()){
196194
return;
197195
}
198196

199-
// REMOVE: TODO: Pick the first controller for now.
200197
auto iter = controllers.begin();
201198

199+
if (controllers.size() == 1){
200+
// Only one controller available. Force the option to it.
201+
m_option.m_controller_type = iter->first;
202+
}else{
203+
// Otherwise, try to use the option setting. If it's not valid,
204+
// clear it.
205+
iter = controllers.find(m_option.m_controller_type);
206+
if (iter == controllers.end()){
207+
m_option.m_controller_type = ControllerType::None;
208+
m_controller.reset();
209+
return;
210+
}
211+
}
212+
202213
// cout << "post_ready()" << endl;
203214

204215
m_controller.reset();
205216
m_controller = m_descriptor->make_controller(m_logger, *m_connection, iter->first, m_requirements);
206217
m_listeners.run_method_unique(&Listener::post_ready, controllers);
207218
signal_ready_changed(m_controller->is_ready());
208-
#endif
209219
}
210220
void ControllerSession::post_status_text_changed(const std::string& text){
211221
do{

0 commit comments

Comments
 (0)