Distributed unter the GPL
*/
+#include <cstdlib>
#include <netinet/in.h>
#include <netdb.h>
+#include <msp/gl/immediate.h>
+#include <msp/gl/matrix.h>
+#include <msp/gl/meshbuilder.h>
+#include <msp/gl/texture.h>
#include <msp/strings/lexicalcast.h>
#include "port.h"
+#include "netvis.h"
-Port::Port(unsigned n, const Msp::GL::Color &c):
+using namespace std;
+using namespace Msp;
+
+Port::Port(NetVis &v, unsigned n):
+ netvis(v),
number(n),
- color(c)
+ registered(false),
+ mesh((GL::COLOR4_UBYTE, GL::VERTEX2))
{
char buf[128];
sockaddr_in addr;
addr.sin_addr.s_addr = 0;
int err = getnameinfo(reinterpret_cast<sockaddr *>(&addr), sizeof(sockaddr_in), 0, 0, buf, sizeof(buf), 0);
if(err==0)
+ {
name = buf;
+ registered = !isdigit(name[0]);
+ }
else
- name = Msp::lexical_cast(number);
+ name = Msp::lexical_cast<string>(number);
+
+ const map<unsigned, Port *> &ports = netvis.get_ports();
+ unsigned tries = 100;
+ if(ports.size()>100 && !registered)
+ tries = 10000/ports.size()+1;
+ float best_score = 0;
+ for(unsigned i=0; (i<tries && best_score<1); ++i)
+ {
+ GL::Color c;
+ c.r = rand()*1.0/RAND_MAX;
+ c.g = rand()*1.0/RAND_MAX;
+ c.b = rand()*1.0/RAND_MAX;
+ float high = max(max(c.r, c.g), c.b);
+ c = c*(1.0/high);
+ if(registered)
+ {
+ float low = min(min(c.r, c.g), c.b);
+ c = (c+-low)*(1/(1-low));
+ }
+ else
+ c = c*0.6+0.4;
+
+ float score = 2;
+ for(map<unsigned, Port *>::const_iterator j=ports.begin(); j!=ports.end(); ++j)
+ {
+ if(registered && !j->second->is_registered())
+ break;
+ const GL::Color &other = j->second->get_color();
+ float dr = c.r-other.r;
+ float dg = c.g-other.g;
+ float db = c.b-other.b;
+ score = min(score, dr*dr+dg*dg+db*db);
+ }
+ if(score>best_score)
+ {
+ best_score = score;
+ color = c;
+ }
+ }
+ color.a = 0.4f;
+
+ GL::MeshBuilder bld(mesh);
+ bld.begin(GL::QUADS);
+ bld.color(color.r, color.g, color.b, color.a);
+ for(unsigned x=0; x<=4; x+=2)
+ {
+ bld.vertex(x+0, 0);
+ bld.vertex(x+10, 0);
+ bld.vertex(x+10, 10);
+ bld.vertex(x+0, 10);
+ }
+ bld.end();
+}
+
+void Port::set_name(const string &n)
+{
+ name = n;
+}
+
+void Port::add_activity(unsigned bytes)
+{
+ activity.add_bytes(bytes);
+}
+
+void Port::tick(const Time::TimeDelta &dt)
+{
+ activity.tick(dt);
+}
+
+void Port::render() const
+{
+ GL::MatrixStack::Push push_(GL::MatrixStack::modelview());
+ mesh.draw();
+ {
+ GL::Immediate imm((GL::COLOR4_UBYTE, GL::VERTEX2));
+ imm.begin(GL::QUADS);
+ imm.color(color.r, color.g, color.b, color.a);
+ unsigned x = static_cast<unsigned>(activity.get_average()/4096);
+ imm.vertex(14, 0);
+ imm.vertex(14+x, 0);
+ imm.vertex(14+x, 10);
+ imm.vertex(14, 10);
+ imm.end();
+ }
+ GL::MatrixStack::modelview() *= GL::Matrix::translation(16, 1, 0);
+ GL::MatrixStack::modelview() *= GL::Matrix::scaling(10);
+ netvis.get_font().draw_string(name);
+ GL::Texture::unbind();
}