--- /dev/null
+#include <msp/strings/format.h>
+#include "bindings.h"
+#include "controlscheme.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Input {
+
+vector<Device *> Bindings::resolve_devices(Device &dev) const
+{
+ vector<Device *> resolved_devs;
+ resolved_devs.reserve(devices.size());
+ for(vector<DeviceRef>::const_iterator i=devices.begin(); i!=devices.end(); ++i)
+ {
+ if(i->type!=UNSPECIFIED)
+ resolved_devs.push_back(dev.find_subdevice(i->type));
+ else if(!i->name.empty())
+ resolved_devs.push_back(dev.find_subdevice(i->name));
+ else
+ resolved_devs.push_back(0);
+ }
+ return resolved_devs;
+}
+
+bool Bindings::is_compatible(Device &dev) const
+{
+ vector<Device *> resolved_devs = resolve_devices(dev);
+ for(vector<Device *>::const_iterator i=resolved_devs.begin(); i!=resolved_devs.end(); ++i)
+ if(!*i)
+ return false;
+ return true;
+}
+
+bool Bindings::apply_to(ControlScheme &control_scheme, Device &dev)
+{
+ vector<Device *> resolved_devs = resolve_devices(dev);
+ bool applied = false;
+ for(vector<Binding>::const_iterator i=bindings.begin(); i!=bindings.end(); ++i)
+ {
+ Control *ctrl = control_scheme.find(i->control);
+ Device *bdev = (i->device<resolved_devs.size() ? resolved_devs[i->device] : 0);
+ if(ctrl && bdev)
+ {
+ ctrl->set_source(*bdev, i->type, i->index);
+ applied = true;
+ }
+ }
+
+ return applied;
+}
+
+
+DataFile::Loader::ActionMap Bindings::Loader::shared_actions;
+
+Bindings::Loader::Loader(Bindings &b):
+ ObjectLoader<Bindings>(b)
+{
+ set_actions(shared_actions);
+}
+
+void Bindings::Loader::init_actions()
+{
+ add("binding", &Loader::binding);
+ add("device", &Loader::device_type);
+ add("device", &Loader::device_name);
+}
+
+void Bindings::Loader::binding(const string &c)
+{
+ Binding bind;
+ bind.control = c;
+ load_sub(bind);
+ obj.bindings.push_back(bind);
+}
+
+void Bindings::Loader::device_type(DeviceType t)
+{
+ DeviceRef dev;
+ dev.type = t;
+ obj.devices.push_back(dev);
+}
+
+void Bindings::Loader::device_name(const string &n)
+{
+ DeviceRef dev;
+ dev.name = n;
+ obj.devices.push_back(dev);
+}
+
+
+DataFile::Loader::ActionMap Bindings::Binding::Loader::shared_actions;
+
+Bindings::Binding::Loader::Loader(Binding &b):
+ ObjectLoader<Binding>(b)
+{
+ set_actions(shared_actions);
+}
+
+void Bindings::Binding::Loader::init_actions()
+{
+ add("axis", &Loader::axis);
+ add("button", &Loader::button);
+ add("device", &Binding::device);
+ add("key", &Loader::key);
+}
+
+void Bindings::Binding::Loader::axis(unsigned a, AxisSide s)
+{
+ obj.type = (s==NEGATIVE ? AXIS_NEG : AXIS_POS);
+ obj.index = a;
+}
+
+void Bindings::Binding::Loader::button(unsigned b)
+{
+ obj.type = BUTTON;
+ obj.index = b;
+}
+
+
+void operator>>(const LexicalConverter &conv, Bindings::AxisSide &side)
+{
+ if(conv.get()=="POSITIVE")
+ side = Bindings::POSITIVE;
+ else if(conv.get()=="NEGATIVE")
+ side = Bindings::NEGATIVE;
+ else
+ throw lexical_error(format("conversion of '%s' to AxisSide", conv.get()));
+}
+
+void operator<<(LexicalConverter &conv, Bindings::AxisSide side)
+{
+ switch(side)
+ {
+ case Bindings::POSITIVE: conv.result("POSITIVE"); break;
+ case Bindings::NEGATIVE: conv.result("NEGATIVE"); break;
+ default: conv.result(format("AxisSide(%#x)", static_cast<int>(side)));
+ }
+}
+
+} // namespace Input
+} // namespace Msp;