initial player stuff

This commit is contained in:
Blue 2018-08-05 00:52:16 +03:00 committed by Gitea
parent 4b60ece582
commit 00f26c431e
38 changed files with 1107 additions and 93 deletions

View file

@ -276,3 +276,8 @@ bool C::Controller::isSubscribed()
{
return subscribed;
}
const W::Address & C::Controller::getAddress() const
{
return address;
}

View file

@ -40,6 +40,7 @@ namespace C {
void subscribe();
void unsubscribe();
bool isSubscribed();
const W::Address& getAddress() const;
void removeHandler(W::Handler* handler);
void removeController(C::Controller* ctrl);

View file

@ -215,7 +215,7 @@ void ResourceCache::h_subscribeMember(const W::Event& ev)
M::File* modelRecord = M::File::create(readFile(*record), address + lastHops >> 1);
delete record;
addModel(modelRecord);
passToHandler(ev);
passToLocalHandler(ev);
} catch (int err) {
if (err == 3) {
emit serviceMessage(QString("An attempt to create and subscribe record model in resourcecache, but it is not found. Event: ") + ev.toString().c_str());

View file

@ -14,6 +14,7 @@ set(HEADERS
attributes.h
icatalogue.h
catalogue.h
button.h
file/file.h
)
@ -25,12 +26,13 @@ set(SOURCES
attributes.cpp
icatalogue.cpp
catalogue.cpp
button.cpp
file/file.cpp
)
add_library(wModel STATIC ${HEADERS} ${SOURCES})
target_link_libraries(wModel Qt5::Core)
target_link_libraries(wModel wSocket)
target_link_libraries(wModel wDispatcher)
target_link_libraries(wModel wServerUtils)
target_link_libraries(wModel wType)
target_link_libraries(wModel wController)

113
lib/wModel/button.cpp Normal file
View file

@ -0,0 +1,113 @@
#include "button.h"
M::Button::Button(const W::Address& address, QObject* parent):
M::Model(address, parent),
enabled(true),
hasImage(false),
hasLabel(false),
imageName(0),
label(0)
{
W::Handler* get = W::Handler::create(address + W::Address({u"get"}), this, &M::Button::_h_get);
W::Handler* activate = W::Handler::create(address + W::Address({u"activate"}), this, &M::Button::_h_activate);
addHandler(get);
addHandler(activate);
}
M::Button::~Button()
{
if (hasImage) {
delete imageName;
}
}
void M::Button::setImage(const W::String& p_image)
{
if (hasImage) {
if (*imageName != p_image) {
imageName = static_cast<W::String*>(p_image.copy());
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"image", p_image);
broadcast(vc, W::Address{u"changeImage"});
}
} else {
imageName = static_cast<W::String*>(p_image.copy());
hasImage = true;
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"image", p_image);
broadcast(vc, W::Address{u"setImage"});
}
hasImage = true;
}
void M::Button::setEnabled(bool p_enabled)
{
if (enabled != p_enabled) {
enabled = p_enabled;
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"enable", new W::Boolean(enabled));
broadcast(vc, W::Address{u"setEnabled"});
}
}
void M::Button::setLabel(const W::String& p_label)
{
if (hasLabel) {
label->set(p_label);
} else {
label = new M::String(p_label, address + W::Address{u"label"});
addModel(label);
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"hasLabel", new W::Boolean(true));
vc->insert(u"label", label->getAddress());
broadcast(vc, W::Address{u"setLabel"});
hasLabel = true;
}
}
void M::Button::h_subscribe(const W::Event& ev)
{
M::Model::h_subscribe(ev);
h_get(ev);
}
void M::Button::h_get(const W::Event& ev)
{
W::Vocabulary* vc = new W::Vocabulary();
vc->insert(u"hasImage", new W::Boolean(hasImage));
if (hasImage) {
vc->insert(u"image", imageName->copy());
}
vc->insert(u"hasLabel", new W::Boolean(hasLabel));
if (hasLabel) {
vc->insert(u"label", label->getAddress());
}
vc->insert(u"enabled", new W::Boolean(enabled));
response(vc, W::Address({u"get"}), ev);
}
void M::Button::h_activate(const W::Event& ev)
{
if (enabled) {
emit activated();
}
}
M::Model::ModelType M::Button::getType() const
{
return M::Model::button;
}
void M::Button::set(const W::Object& value)
{
throw 14; //what do you expect here? not implemented, and not sure it ever would be
}
void M::Button::set(W::Object* value)
{
set(*value);
}

52
lib/wModel/button.h Normal file
View file

@ -0,0 +1,52 @@
#ifndef BUTTON_H
#define BUTTON_H
#include <wModel/model.h>
#include <wModel/modelstring.h>
#include <wDispatcher/handler.h>
#include <wType/address.h>
#include <wType/event.h>
#include <wType/vocabulary.h>
#include <wType/boolean.h>
/**
* @todo write docs
*/
namespace M {
class Button : public Model {
Q_OBJECT
public:
Button(const W::Address& address, QObject* parent = 0);
~Button();
void setImage(const W::String& p_image);
void setLabel(const W::String& p_label);
void setEnabled(bool p_enabled);
M::Model::ModelType getType() const override;
void set(const W::Object & value) override;
void set(W::Object * value) override;
signals:
void activated() const;
protected:
void h_subscribe(const W::Event & ev) override;
handler(get);
handler(activate);
protected:
bool enabled;
bool hasImage;
bool hasLabel;
W::String* imageName;
M::String* label;
};
}
#endif // BUTTON_H

View file

@ -5,12 +5,12 @@ M::Model::Model(const W::Address p_address, QObject* parent):
address(p_address),
registered(false),
subscribers(new Map()),
dispatcher(0),
server(0),
connector(0),
subscribersCount(0),
handlers(new HList()),
properties(new W::Vector()),
models(new MList())
models(new MList()),
controllers(new Controllers())
{
W::Handler* subscribe = W::Handler::create(address + W::Address({u"subscribe"}), this, &M::Model::_h_subscribe);
W::Handler* unsubscribe = W::Handler::create(address + W::Address({u"unsubscribe"}), this, &M::Model::_h_unsubscribe);
@ -21,7 +21,7 @@ M::Model::Model(const W::Address p_address, QObject* parent):
M::Model::~Model()
{
if (registered) {
unregisterModel();
getUnregistered();
}
MList::iterator itr = models->begin();
@ -37,11 +37,19 @@ M::Model::~Model()
for (; hItr != hEnd; ++hItr) {
delete *hItr;
}
Controllers::iterator cItr = controllers->begin();
Controllers::iterator cEnd = controllers->end();
for (; cItr != cEnd; ++cItr) {
delete cItr->first;
}
delete subscribers;
delete properties;
delete handlers;
delete models;
delete controllers;
}
void M::Model::addModel(M::Model* model)
@ -49,7 +57,7 @@ void M::Model::addModel(M::Model* model)
models->push_back(model);
connect(model, SIGNAL(serviceMessage(const QString&)), SIGNAL(serviceMessage(const QString&)));
if (registered) {
model->registerModel(dispatcher, server);
model->getRegistered(connector);
}
}
@ -57,7 +65,7 @@ void M::Model::addHandler(W::Handler* handler)
{
handlers->push_back(handler);
if (registered) {
dispatcher->registerHandler(handler);
connector->registerHandler(handler);
}
}
@ -83,21 +91,20 @@ W::Address M::Model::getAddress() const
}
void M::Model::registerModel(W::Dispatcher* dp, W::Server* srv)
void M::Model::getRegistered(U::Connector* cn)
{
if (registered) {
emit serviceMessage(QString("Model ") + address.toString().c_str() + " is already registered");
throw 1;
} else {
dispatcher = dp;
server = srv;
connector = cn;
MList::iterator itr = models->begin();
MList::iterator end = models->end();
for (; itr != end; ++itr) {
M::Model* model = *itr;
model->registerModel(dispatcher, server);
model->getRegistered(connector);
}
HList::iterator hItr = handlers->begin();
@ -105,14 +112,21 @@ void M::Model::registerModel(W::Dispatcher* dp, W::Server* srv)
for (; hItr != hEnd; ++hItr) {
W::Handler* handler = *hItr;
dispatcher->registerHandler(handler);
connector->registerHandler(handler);
}
Controllers::iterator cItr = controllers->begin();
Controllers::iterator cEnd = controllers->end();
for (; cItr != cEnd; ++cItr) {
connector->registerController(cItr->first, cItr->second);
}
registered = true;
}
}
void M::Model::unregisterModel()
void M::Model::getUnregistered()
{
if (!registered) {
emit serviceMessage(QString("Model ") + address.toString().c_str() + " is not registered");
@ -123,7 +137,7 @@ void M::Model::unregisterModel()
for (; itr != end; ++itr) {
Model* model = *itr;
model->unregisterModel();
model->getUnregistered();
}
HList::iterator hItr = handlers->begin();
@ -131,21 +145,27 @@ void M::Model::unregisterModel()
for (; hItr != hEnd; ++hItr) {
W::Handler* handler = *hItr;
dispatcher->unregisterHandler(handler);
connector->unregisterHandler(handler);
}
Map::iterator sItr = subscribers->begin();
Map::iterator sEnd = subscribers->end();
for (; sItr != sEnd; ++sItr) {
const W::Socket& socket = server->getConnection(sItr->first);
disconnect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
const W::Socket* socket = connector->getConnection(sItr->first);
disconnect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
}
subscribers->clear();
subscribersCount = 0;
dispatcher = 0;
server = 0;
Controllers::iterator cItr = controllers->begin();
Controllers::iterator cEnd = controllers->end();
for (; cItr != cEnd; ++cItr) {
connector->unregisterController(cItr->first, cItr->second);
}
connector = 0;
registered = false;
}
@ -162,7 +182,6 @@ void M::Model::h_subscribe(const W::Event& ev)
params = static_cast<const W::Vocabulary&>(vc.at(u"params"));
}
Map::iterator sItr = subscribers->find(id);
if (sItr == subscribers->end()) {
@ -171,8 +190,8 @@ void M::Model::h_subscribe(const W::Event& ev)
emit serviceMessage(QString("Model ") + address.toString().c_str() + ": something completely wrong happened");
throw 3;
}
const W::Socket& socket = server->getConnection(id);
connect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
const W::Socket* socket = connector->getConnection(id);
connect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
sItr = pair.first;
}
SMap::const_iterator oItr = sItr->second.find(source);
@ -238,8 +257,8 @@ void M::Model::h_unsubscribe(const W::Event& ev)
smap.erase(sItr);
if (smap.size() == 0) {
const W::Socket& socket = server->getConnection(itr->first);
disconnect(&socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
const W::Socket* socket = connector->getConnection(itr->first);
disconnect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
subscribers->erase(itr);
}
--subscribersCount;
@ -256,7 +275,7 @@ void M::Model::send(W::Vocabulary* vc, const W::Address& destination, uint64_t c
}
W::Event ev(destination, vc);
ev.setSenderId(connectionId);
server->getConnection(connectionId).send(ev);
connector->getConnection(connectionId)->send(ev);
}
void M::Model::response(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Event& src)
@ -272,7 +291,7 @@ void M::Model::response(W::Vocabulary* vc, const W::Address& handlerAddress, con
W::Event ev(source + handlerAddress, vc);
ev.setSenderId(id);
server->getConnection(id).send(ev);
connector->getConnection(id)->send(ev);
}
void M::Model::fakeResponse(W::Vocabulary* vc, const W::Address& handlerAddress, const W::Address& sourceAddress, const W::Event& src)
@ -288,7 +307,7 @@ void M::Model::fakeResponse(W::Vocabulary* vc, const W::Address& handlerAddress,
W::Event ev(source + handlerAddress, vc);
ev.setSenderId(id);
server->getConnection(id).send(ev);
connector->getConnection(id)->send(ev);
}
void M::Model::broadcast(W::Vocabulary* vc, const W::Address& handlerAddress)
@ -307,7 +326,7 @@ void M::Model::broadcast(W::Vocabulary* vc, const W::Address& handlerAddress)
for (;oItr != oEnd; ++oItr) {
W::Event ev(oItr->first + handlerAddress, vc->copy());
ev.setSenderId(itr->first);
server->getConnection(itr->first).send(ev);
connector->getConnection(itr->first)->send(ev);
}
}
delete vc;
@ -317,23 +336,54 @@ void M::Model::removeHandler(W::Handler* handler)
{
handlers->erase(handler);
if (registered) {
dispatcher->unregisterHandler(handler);
connector->unregisterHandler(handler);
}
}
void M::Model::removeModel(M::Model* model)
{
models->erase(model);
disconnect(model, SIGNAL(serviceMessage(const QString&)), this, SIGNAL(serviceMessage(const QString&)));
if (registered) {
model->unregisterModel();
model->getUnregistered();
}
}
void M::Model::passToHandler(const W::Event& event) const
void M::Model::passToLocalHandler(const W::Event& event) const
{
if (registered) {
dispatcher->pass(event);
connector->passThroughDispatcher(event);
} else {
emit serviceMessage(QString("An attempt to pass event to dispatcher from unregistered model\nModel address ") + address.toString().c_str());
}
}
void M::Model::addController(C::Controller* ctrl, const W::String& nodeName)
{
Controllers::const_iterator itr = controllers->find(ctrl);
if (itr != controllers->end()) {
emit serviceMessage(QString("An attempt to add controller ") + ctrl->getAddress().toString().c_str() + QString(" for the second time in model ") + address.toString().c_str());
throw 9;
}
controllers->insert(std::make_pair(ctrl, nodeName));
connect(ctrl, SIGNAL(serviceMessage(const QString&)), SIGNAL(serviceMessage(const QString&)));
if (registered) {
connector->registerController(ctrl, nodeName);;
}
}
void M::Model::removeController(C::Controller* ctrl)
{
Controllers::const_iterator itr = controllers->find(ctrl);
if (itr == controllers->end()) {
emit serviceMessage(QString("An attempt to remove absent controller ") + ctrl->getAddress().toString().c_str() + QString(" from the model ") + address.toString().c_str());
throw 10;
}
disconnect(ctrl, SIGNAL(serviceMessage(const QString&)), this, SIGNAL(serviceMessage(const QString&)));
if (registered) {
connector->unregisterController(itr->first, itr->second);
}
controllers->erase(itr);
}

View file

@ -13,10 +13,10 @@
#include <wType/event.h>
#include <wType/string.h>
#include <wSocket/socket.h>
#include <wSocket/server.h>
#include <wDispatcher/dispatcher.h>
#include <wDispatcher/handler.h>
#include <wContainer/order.h>
#include <wServerUtils/connector.h>
#include <wController/controller.h>
namespace M {
@ -29,10 +29,15 @@ namespace M {
list,
vocabulary,
catalogue,
image,
button,
model,
attributes = 50,
file,
resourceCache
resourceCache,
player = 107
};
Model(const W::Address p_address, QObject* parent = 0);
@ -46,13 +51,15 @@ namespace M {
void addModel(M::Model* model);
void addHandler(W::Handler* handler);
void addProperty(const W::String& value, const W::String& name);
void addController(C::Controller* ctrl, const W::String& nodeName);
W::Address getAddress() const;
void registerModel(W::Dispatcher* dp, W::Server* srv);
void unregisterModel();
void getRegistered(U::Connector* connector);
void getUnregistered();
void removeHandler(W::Handler* handler);
void removeModel(M::Model* model);
void passToHandler(const W::Event& event) const;
void removeController(C::Controller* ctrl);
void passToLocalHandler(const W::Event& event) const;
signals:
void serviceMessage(const QString& msg) const;
@ -76,13 +83,14 @@ namespace M {
private:
typedef W::Order<W::Handler*> HList;
typedef W::Order<M::Model*> MList;
typedef std::map<C::Controller*, W::String> Controllers;
W::Dispatcher* dispatcher;
W::Server* server;
U::Connector* connector;
uint64_t subscribersCount;
HList* handlers;
W::Vector* properties;
MList* models;
Controllers* controllers;
private slots:
void onSocketDisconnected();

View file

@ -12,8 +12,7 @@
namespace M {
class ICatalogue;
class Vocabulary : public M::Model
{
class Vocabulary : public M::Model {
friend class ICatalogue;
public:
Vocabulary(const W::Address p_address, QObject* parent = 0);

View file

@ -1,4 +1,5 @@
#include "connector.h"
#include "commands.h"
U::Connector::Connector(W::Dispatcher* dp, W::Server* srv, U::Commands* cmds, QObject* parent):
QObject(parent),
@ -6,7 +7,8 @@ U::Connector::Connector(W::Dispatcher* dp, W::Server* srv, U::Commands* cmds, QO
server(srv),
commands(cmds),
nodes(),
ignoredNodes()
ignoredNodes(),
controllers()
{
connect(server, SIGNAL(newConnection(const W::Socket&)), SLOT(onNewConnection(const W::Socket&)));
connect(server, SIGNAL(closedConnection(const W::Socket&)), SLOT(onClosedConnection(const W::Socket&)));
@ -30,6 +32,17 @@ U::Connector::~Connector()
for (; itr != end; ++itr) {
commands->removeCommand(dc + itr->first);
}
std::multimap<W::String, C::Controller*>::const_iterator cbeg = controllers.begin();
std::multimap<W::String, C::Controller*>::const_iterator cend = controllers.end();
for (; cbeg != cend; ++cbeg) {
C::Controller* ctrl = cbeg->second;
if (ctrl->isSubscribed()) {
ctrl->unsubscribe();
ctrl->unregisterController();
}
}
}
void U::Connector::addIgnoredNode(const W::String& name)
@ -43,7 +56,7 @@ void U::Connector::sendTo(const W::String& name, const W::Event& event)
if (itr != nodes.end()) {
throw new NodeAccessError(name);
} else {
server->getConnection(itr->second).send(event);
server->getConnection(itr->second)->send(event);
}
}
@ -69,6 +82,14 @@ void U::Connector::onNewConnection(const W::Socket& socket)
emit serviceMessage(QString("New connection, id: ") + socket.getId().toString().c_str());
connect(&socket, SIGNAL(message(const W::Event&)), dispatcher, SLOT(pass(const W::Event&)));
std::multimap<W::String, C::Controller*>::const_iterator beg = controllers.lower_bound(name);
std::multimap<W::String, C::Controller*>::const_iterator end = controllers.upper_bound(name);
for (; beg != end; ++beg) {
beg->second->registerController(dispatcher, &socket);
beg->second->subscribe();
}
emit nodeConnected(name);
}
} else {
@ -90,6 +111,14 @@ void U::Connector::onClosedConnection(const W::Socket& socket)
if (ign == ignoredNodes.end()) {
Map::const_iterator itr = nodes.find(name);
if (itr != nodes.end()) {
std::multimap<W::String, C::Controller*>::const_iterator beg = controllers.lower_bound(name);
std::multimap<W::String, C::Controller*>::const_iterator end = controllers.upper_bound(name);
for (; beg != end; ++beg) {
beg->second->unsubscribe();
beg->second->unregisterController();
}
emit nodeDisconnected(name);
commands->removeCommand(W::String(u"disconnect") + name);
nodes.erase(itr);
@ -114,7 +143,7 @@ void U::Connector::h_disconnect(const W::Event& ev)
server->closeConnection(itr->second);
}
const W::Socket& U::Connector::getNodeSocket(const W::String& name)
const W::Socket* U::Connector::getNodeSocket(const W::String& name)
{
Map::const_iterator itr = nodes.find(name);
if (itr == nodes.end()) {
@ -122,3 +151,62 @@ const W::Socket& U::Connector::getNodeSocket(const W::String& name)
}
return server->getConnection(itr->second);
}
void U::Connector::registerHandler(W::Handler* handler)
{
dispatcher->registerHandler(handler);
}
void U::Connector::unregisterHandler(W::Handler* handler)
{
dispatcher->unregisterHandler(handler);
}
const W::Socket * U::Connector::getConnection(uint64_t p_id) const
{
return server->getConnection(p_id);
}
void U::Connector::passThroughDispatcher(const W::Event& ev) const
{
dispatcher->pass(ev);
}
void U::Connector::registerController(C::Controller* ctrl, const W::String& node)
{
std::set<W::String>::const_iterator iitr = ignoredNodes.find(node);
if (iitr != ignoredNodes.end()) {
throw 3; //this means you're trying to receive something from one of ignored nodes, which never going to be handled in connector, most probably it's a mistake
}
controllers.insert(std::make_pair(node, ctrl));
Map::const_iterator itr = nodes.find(node);
if (itr != nodes.end()) {
ctrl->registerController(dispatcher, server->getConnection(itr->second));
ctrl->subscribe(); //let's say I always need them subscribed, for now at least
}
}
void U::Connector::unregisterController(C::Controller* ctrl, const W::String& node)
{
bool found = false;
std::multimap<W::String, C::Controller*>::const_iterator beg = controllers.lower_bound(node);
std::multimap<W::String, C::Controller*>::const_iterator end = controllers.upper_bound(node);
for (; beg != end; ++beg) {
if (beg->second == ctrl) {
found = true; //TODO make a proper way to store 'em
break;
}
}
if (!found) {
throw 4;
}
if (ctrl->isSubscribed()) {
ctrl->unsubscribe();
ctrl->unregisterController();
}
controllers.erase(beg);
}

View file

@ -1,11 +1,14 @@
#ifndef CONNECTOR_H
#define CONNECTOR_H
#include <utils/defines.h>
#include <QtCore/QObject>
#include <map>
#include <set>
#include <wDispatcher/dispatcher.h>
#include <wDispatcher/handler.h>
#include <wSocket/socket.h>
#include <wSocket/server.h>
@ -16,9 +19,11 @@
#include <utils/exception.h>
#include "commands.h"
#include <wController/controller.h>
namespace U {
class Commands;
class Connector : public QObject
{
Q_OBJECT
@ -29,7 +34,13 @@ namespace U {
void addIgnoredNode(const W::String& name);
void sendTo(const W::String& name, const W::Event& event);
const W::Socket& getNodeSocket(const W::String& name);
const W::Socket* getNodeSocket(const W::String& name);
void registerHandler(W::Handler* handler);
void unregisterHandler(W::Handler* handler);
const W::Socket* getConnection(uint64_t p_id) const;
void passThroughDispatcher(const W::Event& ev) const;
void registerController(C::Controller* ctrl, const W::String& node);
void unregisterController(C::Controller* ctrl, const W::String& node);
signals:
void serviceMessage(const QString& msg);
@ -42,6 +53,7 @@ namespace U {
U::Commands* commands;
Map nodes;
std::set<W::String> ignoredNodes;
std::multimap<W::String, C::Controller*> controllers;
protected:
handler(connect);

View file

@ -44,14 +44,14 @@ void W::Server::stop()
}
}
const W::Socket& W::Server::getConnection(uint64_t p_id) const
const W::Socket* W::Server::getConnection(uint64_t p_id) const
{
std::map<uint64_t, Socket*>::const_iterator itr = connections.find(p_id);
if (itr == connections.end()) {
throw new SocketAccessError();
}
return *(itr->second);
return itr->second;
}
uint64_t W::Server::getConnectionsCount() const

View file

@ -27,7 +27,7 @@ namespace W
void listen(uint16_t port);
void stop();
const Socket& getConnection(uint64_t p_id) const;
const Socket* getConnection(uint64_t p_id) const;
uint64_t getConnectionsCount() const;
void closeConnection(uint64_t p_id);
void openConnection(const String& addr, const Uint64& port);

View file

@ -102,5 +102,7 @@ W::Object::StdStr W::Object::getTypeName(W::Object::objectType type)
case blob:
return "Blob";
}
throw 5;
}