<commit_before>/*

 * code.cpp
 *
 *  Created on: Oct 30, 2015
 *      Author: (Bu)nn

 TODO

 * Background Subtration to get just the hand (binarized image)
 *

 */

#include <core/cvdef.h>
#include <core/cvstd.hpp>
#include <core/mat.hpp>
#include <core/mat.inl.hpp>
#include <core/matx.hpp>
#include <core/ptr.inl.hpp>
#include <core/types.hpp>
#include <highgui.hpp>
#include <imgproc/types_c.h>
#include <imgproc.hpp>
#include <video/background_segm.hpp>
#include <videoio.hpp>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <utility>
#include <vector>

#include "../../ImageAnalysis/helpers/helpers.cpp"

using namespace cv;
using namespace std;

Mat frame; //current frame
Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method
Ptr<BackgroundSubtractor> pMOG2; //MOG2 Background subtractor
vector<pair<Point, double>> palm_centers;

//This function returns the square of the euclidean distance between 2 points.
double dist(Point x, Point y) {
  return (x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y);
}

Mat pre_processing(Mat frame) {
  GaussianBlur(frame, frame, Size(7, 7), 1.5, 1.5);
//  blur(frame, frame, Size(10, 10));

  Mat gray_scale;
  cvtColor(frame, gray_scale, CV_BGR2GRAY);

  Mat element = (Mat_<uchar>(3, 3) << 0, 1, 0, 1, 1, 1, 0, 1, 0);
  morphologyEx(gray_scale, gray_scale, MORPH_OPEN, element);

  return gray_scale;
}

Mat bg_subtraction(VideoCapture cap, Mat frame) {
  //update the background model
  pMOG2->apply(frame, fgMaskMOG2);
  return fgMaskMOG2;
}

//This function returns the radius and the center of the circle given 3 points
//If a circle cannot be formed , it returns a zero radius circle centered at (0,0)
pair<Point, double> circleFromPoints(Point p1, Point p2, Point p3) {
  double offset = pow(p2.x, 2) + pow(p2.y, 2);
  double bc = (pow(p1.x, 2) + pow(p1.y, 2) - offset) / 2.0;
  double cd = (offset - pow(p3.x, 2) - pow(p3.y, 2)) / 2.0;
  double det = (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p2.y);
  double TOL = 0.0000001;
  if (abs(det) < TOL) {
    cout << "POINTS TOO CLOSE" << endl;
    return make_pair(Point(0, 0), 0);
  }

  double idet = 1 / det;
  double centerx = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) * idet;
  double centery = (cd * (p1.x - p2.x) - bc * (p2.x - p3.x)) * idet;
  double radius = sqrt(pow(p2.x - centerx, 2) + pow(p2.y - centery, 2));

  return make_pair(Point(centerx, centery), radius);
}

Mat contouring(Mat bg, Mat pre_processed) {
  vector<vector<Point>> contours;

  //Find the contours in the foreground
  Mat thr = bg.clone();
  thr = threshold(bg, bg, 130, 255, THRESH_BINARY);
  imshow("Binary", binarize(bg));
  findContours(binarize(bg), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

  for (int i = 0; i < contours.size(); i++)
    //Ignore all small insignificant areas
    if (contourArea(contours[i]) >= 5000) {
      //Draw contour
      vector<vector<Point>> tcontours;
      tcontours.push_back(contours[i]);
      drawContours(pre_processed, tcontours, -1, Scalar(0, 0, 255), 2);

      //Detect Hull in current contour
      vector<vector<Point> > hulls(1);
      vector<vector<int> > hullsI(1);
      convexHull(Mat(tcontours[0]), hulls[0], false);
      convexHull(Mat(tcontours[0]), hullsI[0], false);
      drawContours(pre_processed, hulls, -1, Scalar(0, 255, 0), 2);

      //Find minimum area rectangle to enclose hand
      RotatedRect rect = minAreaRect(Mat(tcontours[0]));

      //Find Convex Defects
      vector<Vec4i> defects;
      if (hullsI[0].size() > 0) {
        Point2f rect_points[4];
        rect.points(rect_points);
        for (int j = 0; j < 4; j++)
          line(pre_processed, rect_points[j], rect_points[(j + 1) % 4],
              Scalar(255, 0, 0), 1, 8);
        Point rough_palm_center;
        convexityDefects(tcontours[0], hullsI[0], defects);
        if (defects.size() >= 3) {
          vector<Point> palm_points;
          for (int j = 0; j < defects.size(); j++) {
            int startidx = defects[j][0];
            Point ptStart(tcontours[0][startidx]);
            int endidx = defects[j][1];
            Point ptEnd(tcontours[0][endidx]);
            int faridx = defects[j][2];
            Point ptFar(tcontours[0][faridx]);
            //Sum up all the hull and defect points to compute average
            rough_palm_center += ptFar + ptStart + ptEnd;
            palm_points.push_back(ptFar);
            palm_points.push_back(ptStart);
            palm_points.push_back(ptEnd);
          }

          //Get palm center by 1st getting the average of all defect points, this is the rough palm center,
          //Then U chose the closest 3 points ang get the circle radius and center formed from them which is the palm center.
          rough_palm_center.x /= defects.size() * 3;
          rough_palm_center.y /= defects.size() * 3;
          Point closest_pt = palm_points[0];
          vector<pair<double, int> > distvec;
          for (int i = 0; i < palm_points.size(); i++)
            distvec.push_back(
                make_pair(dist(rough_palm_center, palm_points[i]), i));
          sort(distvec.begin(), distvec.end());

          //Keep choosing 3 points till you find a circle with a valid radius
          //As there is a high chance that the closes points might be in a linear line or too close that it forms a very large circle
          pair<Point, double> soln_circle;
          for (int i = 0; i + 2 < distvec.size(); i++) {
            Point p1 = palm_points[distvec[i + 0].second];
            Point p2 = palm_points[distvec[i + 1].second];
            Point p3 = palm_points[distvec[i + 2].second];
            soln_circle = circleFromPoints(p1, p2, p3); //Final palm center,radius
            if (soln_circle.second != 0)
              break;
          }

          //Find avg palm centers for the last few frames to stabilize its centers, also find the avg radius
          palm_centers.push_back(soln_circle);
          if (palm_centers.size() > 10)
            palm_centers.erase(palm_centers.begin());

          Point palm_center;
          double radius = 0;
          for (int i = 0; i < palm_centers.size(); i++) {
            palm_center += palm_centers[i].first;
            radius += palm_centers[i].second;
          }
          palm_center.x /= palm_centers.size();
          palm_center.y /= palm_centers.size();
          radius /= palm_centers.size();

          //Draw the palm center and the palm circle
          //The size of the palm gives the depth of the hand
          circle(frame, palm_center, 5, Scalar(144, 144, 255), 3);
          circle(frame, palm_center, radius, Scalar(144, 144, 255), 2);

          //Detect fingers by finding points that form an almost isosceles triangle with certain thesholds
          int no_of_fingers = 0;
          for (int j = 0; j < defects.size(); j++) {
            int startidx = defects[j][0];
            Point ptStart(tcontours[0][startidx]);
            int endidx = defects[j][1];
            Point ptEnd(tcontours[0][endidx]);
            int faridx = defects[j][2];
            Point ptFar(tcontours[0][faridx]);
            //X o--------------------------o Y
            double Xdist = sqrt(dist(palm_center, ptFar));
            double Ydist = sqrt(dist(palm_center, ptStart));
            double length = sqrt(dist(ptFar, ptStart));

            double retLength = sqrt(dist(ptEnd, ptFar));
            //Play with these thresholds to improve performance
            if (length <= 3 * radius && Ydist >= 0.4 * radius && length >= 10
                && retLength >= 10
                && max(length, retLength) / min(length, retLength) >= 0.8)
              if (min(Xdist, Ydist) / max(Xdist, Ydist) <= 0.8) {
                if ((Xdist >= 0.1 * radius && Xdist <= 1.3 * radius
                    && Xdist < Ydist)
                    || (Ydist >= 0.1 * radius && Ydist <= 1.3 * radius
                        && Xdist > Ydist))
                  line(frame, ptEnd, ptFar, Scalar(0, 255, 0), 1), no_of_fingers++;
              }

          }

           no_of_fingers = min(5, no_of_fingers);
           cout << "NO OF FINGERS: " << no_of_fingers << endl;
//           mouseTo(palm_center.x, palm_center.y); //Move the cursor corresponding to the palm
//           if (no_of_fingers < 4) //If no of fingers is <4 , click , else release
//           mouseClick();
//           else
//           mouseRelease();

           }
      }

    }

  return pre_processed;
}

int process_video() {

  VideoCapture cap(0); // open the default camera
  if (!cap.isOpened())  // check if we succeeded
    return -1;

  for (;;) {

    //Capture the Frame and convert it to Grayscale
    cap >> frame; // get a new frame from camera

    Mat pre_processed;
    pre_processed = pre_processing(frame);

    Mat bg_sub = bg_subtraction(cap, pre_processed);

    pre_processed = contouring(bg_sub,frame);

    imshow("Frame", pre_processed);
    imshow("FG Mask MOG 2",bg_sub);
    if (waitKey(30) >= 0)
      break;
  }

  return 0;
}

int main(int, char**) {
  //create Background Subtractor objects
  pMOG2 = createBackgroundSubtractorMOG2(); //MOG2 approach
  int res = process_video();
  return 0;
}

<commit_msg>Finger tracking working<commit_after>/*

 * code.cpp
 *
 *  Created on: Oct 30, 2015
 *      Author: (Bu)nn

 TODO

 * Background Subtration to get just the hand (binarized image)
 *

 */

#include <core/cvdef.h>
#include <core/cvstd.hpp>
#include <core/cvstd.inl.hpp>
#include <core/mat.hpp>
#include <core/mat.inl.hpp>
#include <core/matx.hpp>
#include <core/ptr.inl.hpp>
#include <core/types.hpp>
#include <core.hpp>
#include <highgui.hpp>
#include <imgproc/types_c.h>
#include <imgproc.hpp>
#include <video/background_segm.hpp>
#include <videoio.hpp>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <utility>
#include <vector>

using namespace cv;
using namespace std;

Mat frame; //current frame
Mat fgMaskMOG2; //fg mask fg mask generated by MOG2 method
Mat back;
Ptr<BackgroundSubtractorMOG2> pMOG2; //MOG2 Background subtractor
vector<pair<Point, double>> palm_centers;

//This function returns the square of the euclidean distance between 2 points.
double dist(Point x, Point y) {
  return (x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y);
}

Mat pre_processing(Mat frame) {

  GaussianBlur(frame, frame, Size(7, 7), 10, 10);
  Mat gray_scale;
  cvtColor(frame, gray_scale, COLOR_BGR2GRAY, 1);

  Mat element = (Mat_<uchar>(3, 3) << 0, 1, 0, 1, 1, 1, 0, 1, 0);
  morphologyEx(gray_scale, gray_scale, MORPH_OPEN, element);

  return gray_scale;
}

Mat bg_subtraction(VideoCapture cap, Mat frame) {
  //update the background model
  pMOG2->apply(frame, fgMaskMOG2);

  //Get background image to display it
  pMOG2->getBackgroundImage(back);
  pMOG2->setDetectShadows(0);
  pMOG2->setNMixtures(3);
  return fgMaskMOG2;
}

//This function returns the radius and the center of the circle given 3 points
//If a circle cannot be formed , it returns a zero radius circle centered at (0,0)
pair<Point, double> circleFromPoints(Point p1, Point p2, Point p3) {
  double offset = pow(p2.x, 2) + pow(p2.y, 2);
  double bc = (pow(p1.x, 2) + pow(p1.y, 2) - offset) / 2.0;
  double cd = (offset - pow(p3.x, 2) - pow(p3.y, 2)) / 2.0;
  double det = (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p2.y);
  double TOL = 0.0000001;
  if (abs(det) < TOL) {
    cout << "POINTS TOO CLOSE" << endl;
    return make_pair(Point(0, 0), 0);
  }

  double idet = 1 / det;
  double centerx = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) * idet;
  double centery = (cd * (p1.x - p2.x) - bc * (p2.x - p3.x)) * idet;
  double radius = sqrt(pow(p2.x - centerx, 2) + pow(p2.y - centery, 2));

  return make_pair(Point(centerx, centery), radius);
}

Mat contouring(Mat binarized, Mat pre_processed) {
  vector<vector<Point>> contours;

  //Find the contours in the foreground

  findContours(binarized, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
  imshow("Binary", binarized);

  for (int i = 0; i < contours.size(); i++)
    //Ignore all small insignificant areas
    if (contourArea(contours[i]) >= 5000) {
      //Draw contour
      vector<vector<Point>> tcontours;
      tcontours.push_back(contours[i]);
      drawContours(pre_processed, tcontours, -1, Scalar(0, 0, 255), 2);

      //Detect Hull in current contour
      vector<vector<Point> > hulls(1);
      vector<vector<int> > hullsI(1);
      convexHull(Mat(tcontours[0]), hulls[0], false);
      convexHull(Mat(tcontours[0]), hullsI[0], false);
      drawContours(pre_processed, hulls, -1, Scalar(0, 255, 0), 2);

      //Find minimum area rectangle to enclose hand
      RotatedRect rect = minAreaRect(Mat(tcontours[0]));

      //Find Convex Defects
      vector<Vec4i> defects;
      if (hullsI[0].size() > 0) {
        Point2f rect_points[4];
        rect.points(rect_points);
        for (int j = 0; j < 4; j++)
          line(pre_processed, rect_points[j], rect_points[(j + 1) % 4],
              Scalar(255, 0, 0), 1, 8);
        Point rough_palm_center;
        convexityDefects(tcontours[0], hullsI[0], defects);
        if (defects.size() >= 3) {
          vector<Point> palm_points;
          for (int j = 0; j < defects.size(); j++) {
            int startidx = defects[j][0];
            Point ptStart(tcontours[0][startidx]);
            int endidx = defects[j][1];
            Point ptEnd(tcontours[0][endidx]);
            int faridx = defects[j][2];
            Point ptFar(tcontours[0][faridx]);
            //Sum up all the hull and defect points to compute average
            rough_palm_center += ptFar + ptStart + ptEnd;
            palm_points.push_back(ptFar);
            palm_points.push_back(ptStart);
            palm_points.push_back(ptEnd);
          }

          //Get palm center by 1st getting the average of all defect points, this is the rough palm center,
          //Then U chose the closest 3 points ang get the circle radius and center formed from them which is the palm center.
          rough_palm_center.x /= defects.size() * 3;
          rough_palm_center.y /= defects.size() * 3;
          Point closest_pt = palm_points[0];
          vector<pair<double, int> > distvec;
          for (int i = 0; i < palm_points.size(); i++)
            distvec.push_back(
                make_pair(dist(rough_palm_center, palm_points[i]), i));
          sort(distvec.begin(), distvec.end());

          //Keep choosing 3 points till you find a circle with a valid radius
          //As there is a high chance that the closes points might be in a linear line or too close that it forms a very large circle
          pair<Point, double> soln_circle;
          for (int i = 0; i + 2 < distvec.size(); i++) {
            Point p1 = palm_points[distvec[i + 0].second];
            Point p2 = palm_points[distvec[i + 1].second];
            Point p3 = palm_points[distvec[i + 2].second];
            soln_circle = circleFromPoints(p1, p2, p3); //Final palm center,radius
            if (soln_circle.second != 0)
              break;
          }

          //Find avg palm centers for the last few frames to stabilize its centers, also find the avg radius
          palm_centers.push_back(soln_circle);
          if (palm_centers.size() > 10)
            palm_centers.erase(palm_centers.begin());

          Point palm_center;
          double radius = 0;
          for (int i = 0; i < palm_centers.size(); i++) {
            palm_center += palm_centers[i].first;
            radius += palm_centers[i].second;
          }
          palm_center.x /= palm_centers.size();
          palm_center.y /= palm_centers.size();
          radius /= palm_centers.size();

          //Draw the palm center and the palm circle
          //The size of the palm gives the depth of the hand
          circle(frame, palm_center, 5, Scalar(144, 144, 255), 3);
          circle(frame, palm_center, radius, Scalar(144, 144, 255), 2);

          //Detect fingers by finding points that form an almost isosceles triangle with certain thesholds
          int no_of_fingers = 0;
          for (int j = 0; j < defects.size(); j++) {
            int startidx = defects[j][0];
            Point ptStart(tcontours[0][startidx]);
            int endidx = defects[j][1];
            Point ptEnd(tcontours[0][endidx]);
            int faridx = defects[j][2];
            Point ptFar(tcontours[0][faridx]);
            //X o--------------------------o Y
            double Xdist = sqrt(dist(palm_center, ptFar));
            double Ydist = sqrt(dist(palm_center, ptStart));
            double length = sqrt(dist(ptFar, ptStart));

            double retLength = sqrt(dist(ptEnd, ptFar));
            //Play with these thresholds to improve performance
            if (length <= 3 * radius && Ydist >= 0.4 * radius && length >= 10
                && retLength >= 10
                && max(length, retLength) / min(length, retLength) >= 0.8)
              if (min(Xdist, Ydist) / max(Xdist, Ydist) <= 0.8) {
                if ((Xdist >= 0.1 * radius && Xdist <= 1.3 * radius
                    && Xdist < Ydist)
                    || (Ydist >= 0.1 * radius && Ydist <= 1.3 * radius
                        && Xdist > Ydist))
                  line(frame, ptEnd, ptFar, Scalar(0, 255, 0), 1), no_of_fingers++;
              }
          }
           no_of_fingers = min(5, no_of_fingers);
           cout << "NO OF FINGERS: " << no_of_fingers << endl;
           }
      }

    }

  return pre_processed;
}

int process_video() {

  VideoCapture cap(0); // open the default camera
  if (!cap.isOpened())  // check if we succeeded
    return -1;

  for (;;) {

    //Capture the Frame and convert it to Grayscale
    cap >> frame; // get a new frame from camera

    Mat foreground;
    Mat i1 = pre_processing(frame);
    Mat bg_sub = bg_subtraction(cap, i1);
    absdiff(i1, back, foreground);

    Mat fg_binarized;
    threshold(foreground, fg_binarized, 0, 255, THRESH_BINARY | THRESH_OTSU);

    Mat contour = contouring(fg_binarized,frame);

    imshow("Frame", contour);
    imshow("FG Mask MOG 2",bg_sub);
    imshow("Background",back);
    if (waitKey(30) >= 0)
      break;
  }

  return 0;
}

int main(int, char**) {
  //create Background Subtractor objects
  pMOG2 = createBackgroundSubtractorMOG2(); //MOG2 approach
  int res = process_video();
  return 0;
}

<|endoftext|>


<commit_before>// Copyright (c) 2011 Baidu, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: Ge,Jun (gejun@baidu.com)
// Date: Mon. Nov 7 14:47:36 CST 2011

#include "butil/build_config.h"                // OS_MACOSX
#include <arpa/inet.h>                         // inet_pton, inet_ntop
#include <netdb.h>                             // gethostbyname_r
#include <unistd.h>                            // gethostname
#include <errno.h>                             // errno
#include <string.h>                            // strcpy
#include <stdio.h>                             // snprintf
#include <stdlib.h>                            // strtol
#include "butil/fd_guard.h"                    // fd_guard
#include "butil/endpoint.h"                    // ip_t
#include "butil/logging.h"
#include "butil/memory/singleton_on_pthread_once.h"
#include "butil/strings/string_piece.h"

__BEGIN_DECLS
int BAIDU_WEAK bthread_connect(
    int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) {
    return connect(sockfd, serv_addr, addrlen);
}
__END_DECLS

namespace butil {

int str2ip(const char* ip_str, ip_t* ip) {
    // ip_str can be NULL when called by EndPoint(0, ...)
    if (ip_str != NULL) {
        for (; isspace(*ip_str); ++ip_str);
        int rc = inet_pton(AF_INET, ip_str, ip);
        if (rc > 0) {
            return 0;
        }
    }
    return -1;
}

IPStr ip2str(ip_t ip) {
    IPStr str;
    if (inet_ntop(AF_INET, &ip, str._buf, INET_ADDRSTRLEN) == NULL) {
        return ip2str(IP_NONE);
    }
    return str;
}

int ip2hostname(ip_t ip, char* host, size_t host_len) {
    if (host == NULL || host_len == 0) {
        errno = EINVAL;
        return -1;
    }
    sockaddr_in sa;
    bzero((char*)&sa, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = 0;    // useless since we don't need server_name
    sa.sin_addr = ip;
    if (getnameinfo((const sockaddr*)&sa, sizeof(sa),
                    host, host_len, NULL, 0, NI_NAMEREQD) != 0) {
        return -1;
    }
    // remove baidu-specific domain name (that every name has)
    butil::StringPiece str(host);
    if (str.ends_with(".baidu.com")) {
        host[str.size() - 10] = '\0';
    }
    return 0;
}

int ip2hostname(ip_t ip, std::string* host) {
    char buf[128];
    if (ip2hostname(ip, buf, sizeof(buf)) == 0) {
        host->assign(buf);
        return 0;
    }
    return -1;
}

EndPointStr endpoint2str(const EndPoint& point) {
    EndPointStr str;
    if (inet_ntop(AF_INET, &point.ip, str._buf, INET_ADDRSTRLEN) == NULL) {
        return endpoint2str(EndPoint(IP_NONE, 0));
    }
    char* buf = str._buf + strlen(str._buf);
    *buf++ = ':';
    snprintf(buf, 16, "%d", point.port);
    return str;
}

int hostname2ip(const char* hostname, ip_t* ip) {
    char buf[256];
    if (NULL == hostname) {
        if (gethostname(buf, sizeof(buf)) < 0) {
            return -1;
        }
        hostname = buf;
    } else {
        // skip heading space
        for (; isspace(*hostname); ++hostname);
    }

#if defined(OS_MACOSX)
    // gethostbyname on MAC is thread-safe (with current usage) since the
    // returned hostent is TLS. Check following link for the ref:
    // https://lists.apple.com/archives/darwin-dev/2006/May/msg00008.html
    struct hostent* result = gethostbyname(hostname);
    if (result == NULL) {
        return -1;
    }
#else
    char aux_buf[1024];
    int error = 0;
    struct hostent ent;
    struct hostent* result = NULL;
    if (gethostbyname_r(hostname, &ent, aux_buf, sizeof(aux_buf),
                        &result, &error) != 0 || result == NULL) {
        return -1;
    }
#endif // defined(OS_MACOSX)
    // Only fetch the first address here
    bcopy((char*)result->h_addr, (char*)ip, result->h_length);
    return 0;
}

struct MyAddressInfo {
    char my_hostname[256];
    ip_t my_ip;
    IPStr my_ip_str;

    MyAddressInfo() {
        my_ip = IP_ANY;
        if (gethostname(my_hostname, sizeof(my_hostname)) < 0) {
            my_hostname[0] = '\0';
        } else if (hostname2ip(my_hostname, &my_ip) != 0) {
            my_ip = IP_ANY;
        }
        my_ip_str = ip2str(my_ip);
    }
};

ip_t my_ip() {
    return get_leaky_singleton<MyAddressInfo>()->my_ip;
}

const char* my_ip_cstr() {
    return get_leaky_singleton<MyAddressInfo>()->my_ip_str.c_str();
}

const char* my_hostname() {
    return get_leaky_singleton<MyAddressInfo>()->my_hostname;
}

int str2endpoint(const char* str, EndPoint* point) {
    // Should be enough to hold ip address
    char buf[64];
    size_t i = 0;
    for (; i < sizeof(buf) && str[i] != '\0' && str[i] != ':'; ++i) {
        buf[i] = str[i];
    }
    if (i >= sizeof(buf) || str[i] != ':') {
        return -1;
    }
    buf[i] = '\0';
    if (str2ip(buf, &point->ip) != 0) {
        return -1;
    }
    ++i;
    char* end = NULL;
    point->port = strtol(str + i, &end, 10);
    if (end == str + i) {
        return -1;
    } else if (*end) {
        for (++end; isspace(*end); ++end);
        if (*end) {
            return -1;
        }
    }
    if (point->port < 0 || point->port > 65535) {
        return -1;
    }
    return 0;
}

int str2endpoint(const char* ip_str, int port, EndPoint* point) {
    if (str2ip(ip_str, &point->ip) != 0) {
        return -1;
    }
    if (port < 0 || port > 65535) {
        return -1;
    }
    point->port = port;
    return 0;
}

int hostname2endpoint(const char* str, EndPoint* point) {
    // Should be enough to hold ip address
    char buf[64];
    size_t i = 0;
    for (; i < sizeof(buf) - 1 && str[i] != '\0' && str[i] != ':'; ++i) {
        buf[i] = str[i];
    }
    if (i == sizeof(buf) - 1) {
        return -1;
    }

    buf[i] = '\0';
    if (hostname2ip(buf, &point->ip) != 0) {
        return -1;
    }
    if (str[i] == ':') {
        ++i;
    }
    char* end = NULL;
    point->port = strtol(str + i, &end, 10);
    if (end == str + i) {
        return -1;
    } else if (*end) {
        for (; isspace(*end); ++end);
        if (*end) {
            return -1;
        }
    }
    if (point->port < 0 || point->port > 65535) {
        return -1;
    }
    return 0;
}

int hostname2endpoint(const char* name_str, int port, EndPoint* point) {
    if (hostname2ip(name_str, &point->ip) != 0) {
        return -1;
    }
    if (port < 0 || port > 65535) {
        return -1;
    }
    point->port = port;
    return 0;
}

int endpoint2hostname(const EndPoint& point, char* host, size_t host_len) {
    if (ip2hostname(point.ip, host, host_len) == 0) {
        size_t len = strlen(host);
        if (len + 1 < host_len) {
            snprintf(host + len, host_len - len, ":%d", point.port);
        }
        return 0;
    }
    return -1;
}

int endpoint2hostname(const EndPoint& point, std::string* host) {
    char buf[128];
    if (endpoint2hostname(point, buf, sizeof(buf)) == 0) {
        host->assign(buf);
        return 0;
    }
    return -1;
}

int tcp_connect(EndPoint point, int* self_port) {
    fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
    if (sockfd < 0) {
        return -1;
    }
    struct sockaddr_in serv_addr;
    bzero((char*)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr = point.ip;
    serv_addr.sin_port = htons(point.port);
    int rc = 0;
    if (bthread_connect != NULL) {
        rc = bthread_connect(sockfd, (struct sockaddr*)&serv_addr,
                             sizeof(serv_addr));
    } else {
        rc = ::connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    }
    if (rc < 0) {
        return -1;
    }
    if (self_port != NULL) {
        EndPoint pt;
        if (get_local_side(sockfd, &pt) == 0) {
            *self_port = pt.port;
        } else {
            CHECK(false) << "Fail to get the local port of sockfd=" << sockfd;
        }
    }
    return sockfd.release();
}

int tcp_listen(EndPoint point, bool reuse_addr) {
    fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
    if (sockfd < 0) {
        return -1;
    }
    if (reuse_addr) {
        const int on = 1;
        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
                       &on, sizeof(on)) != 0) {
            return -1;
        }
    }
    struct sockaddr_in serv_addr;
    bzero((char*)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr = point.ip;
    serv_addr.sin_port = htons(point.port);
    if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0) {
        return -1;
    }
    if (listen(sockfd, INT_MAX) != 0) {
        //             ^^^ kernel would silently truncate backlog to the value
        //             defined in /proc/sys/net/core/somaxconn
        return -1;
    }
    return sockfd.release();
}

int get_local_side(int fd, EndPoint *out) {
    struct sockaddr addr;
    socklen_t socklen = sizeof(addr);
    const int rc = getsockname(fd, &addr, &socklen);
    if (rc != 0) {
        return rc;
    }
    if (out) {
        *out = butil::EndPoint(*(sockaddr_in*)&addr);
    }
    return 0;
}

int get_remote_side(int fd, EndPoint *out) {
    struct sockaddr addr;
    socklen_t socklen = sizeof(addr);
    const int rc = getpeername(fd, &addr, &socklen);
    if (rc != 0) {
        return rc;
    }
    if (out) {
        *out = butil::EndPoint(*(sockaddr_in*)&addr);
    }
    return 0;
}

}  // namespace butil
<commit_msg>support for SO_REUSEPORT socket option<commit_after>// Copyright (c) 2011 Baidu, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: Ge,Jun (gejun@baidu.com)
// Date: Mon. Nov 7 14:47:36 CST 2011

#include "butil/build_config.h"                // OS_MACOSX
#include <arpa/inet.h>                         // inet_pton, inet_ntop
#include <netdb.h>                             // gethostbyname_r
#include <unistd.h>                            // gethostname
#include <errno.h>                             // errno
#include <string.h>                            // strcpy
#include <stdio.h>                             // snprintf
#include <stdlib.h>                            // strtol
#include <gflags/gflags.h>
#include "butil/fd_guard.h"                    // fd_guard
#include "butil/endpoint.h"                    // ip_t
#include "butil/logging.h"
#include "butil/memory/singleton_on_pthread_once.h"
#include "butil/strings/string_piece.h"

#ifndef SO_REUSEPORT
#define SO_REUSEPORT    15
#endif
//This option is supported since Linux 3.9.
DEFINE_bool(reuse_port, false, "turn on support for SO_REUSEPORT socket option.");

__BEGIN_DECLS
int BAIDU_WEAK bthread_connect(
    int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) {
    return connect(sockfd, serv_addr, addrlen);
}
__END_DECLS

namespace butil {

int str2ip(const char* ip_str, ip_t* ip) {
    // ip_str can be NULL when called by EndPoint(0, ...)
    if (ip_str != NULL) {
        for (; isspace(*ip_str); ++ip_str);
        int rc = inet_pton(AF_INET, ip_str, ip);
        if (rc > 0) {
            return 0;
        }
    }
    return -1;
}

IPStr ip2str(ip_t ip) {
    IPStr str;
    if (inet_ntop(AF_INET, &ip, str._buf, INET_ADDRSTRLEN) == NULL) {
        return ip2str(IP_NONE);
    }
    return str;
}

int ip2hostname(ip_t ip, char* host, size_t host_len) {
    if (host == NULL || host_len == 0) {
        errno = EINVAL;
        return -1;
    }
    sockaddr_in sa;
    bzero((char*)&sa, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = 0;    // useless since we don't need server_name
    sa.sin_addr = ip;
    if (getnameinfo((const sockaddr*)&sa, sizeof(sa),
                    host, host_len, NULL, 0, NI_NAMEREQD) != 0) {
        return -1;
    }
    // remove baidu-specific domain name (that every name has)
    butil::StringPiece str(host);
    if (str.ends_with(".baidu.com")) {
        host[str.size() - 10] = '\0';
    }
    return 0;
}

int ip2hostname(ip_t ip, std::string* host) {
    char buf[128];
    if (ip2hostname(ip, buf, sizeof(buf)) == 0) {
        host->assign(buf);
        return 0;
    }
    return -1;
}

EndPointStr endpoint2str(const EndPoint& point) {
    EndPointStr str;
    if (inet_ntop(AF_INET, &point.ip, str._buf, INET_ADDRSTRLEN) == NULL) {
        return endpoint2str(EndPoint(IP_NONE, 0));
    }
    char* buf = str._buf + strlen(str._buf);
    *buf++ = ':';
    snprintf(buf, 16, "%d", point.port);
    return str;
}

int hostname2ip(const char* hostname, ip_t* ip) {
    char buf[256];
    if (NULL == hostname) {
        if (gethostname(buf, sizeof(buf)) < 0) {
            return -1;
        }
        hostname = buf;
    } else {
        // skip heading space
        for (; isspace(*hostname); ++hostname);
    }

#if defined(OS_MACOSX)
    // gethostbyname on MAC is thread-safe (with current usage) since the
    // returned hostent is TLS. Check following link for the ref:
    // https://lists.apple.com/archives/darwin-dev/2006/May/msg00008.html
    struct hostent* result = gethostbyname(hostname);
    if (result == NULL) {
        return -1;
    }
#else
    char aux_buf[1024];
    int error = 0;
    struct hostent ent;
    struct hostent* result = NULL;
    if (gethostbyname_r(hostname, &ent, aux_buf, sizeof(aux_buf),
                        &result, &error) != 0 || result == NULL) {
        return -1;
    }
#endif // defined(OS_MACOSX)
    // Only fetch the first address here
    bcopy((char*)result->h_addr, (char*)ip, result->h_length);
    return 0;
}

struct MyAddressInfo {
    char my_hostname[256];
    ip_t my_ip;
    IPStr my_ip_str;

    MyAddressInfo() {
        my_ip = IP_ANY;
        if (gethostname(my_hostname, sizeof(my_hostname)) < 0) {
            my_hostname[0] = '\0';
        } else if (hostname2ip(my_hostname, &my_ip) != 0) {
            my_ip = IP_ANY;
        }
        my_ip_str = ip2str(my_ip);
    }
};

ip_t my_ip() {
    return get_leaky_singleton<MyAddressInfo>()->my_ip;
}

const char* my_ip_cstr() {
    return get_leaky_singleton<MyAddressInfo>()->my_ip_str.c_str();
}

const char* my_hostname() {
    return get_leaky_singleton<MyAddressInfo>()->my_hostname;
}

int str2endpoint(const char* str, EndPoint* point) {
    // Should be enough to hold ip address
    char buf[64];
    size_t i = 0;
    for (; i < sizeof(buf) && str[i] != '\0' && str[i] != ':'; ++i) {
        buf[i] = str[i];
    }
    if (i >= sizeof(buf) || str[i] != ':') {
        return -1;
    }
    buf[i] = '\0';
    if (str2ip(buf, &point->ip) != 0) {
        return -1;
    }
    ++i;
    char* end = NULL;
    point->port = strtol(str + i, &end, 10);
    if (end == str + i) {
        return -1;
    } else if (*end) {
        for (++end; isspace(*end); ++end);
        if (*end) {
            return -1;
        }
    }
    if (point->port < 0 || point->port > 65535) {
        return -1;
    }
    return 0;
}

int str2endpoint(const char* ip_str, int port, EndPoint* point) {
    if (str2ip(ip_str, &point->ip) != 0) {
        return -1;
    }
    if (port < 0 || port > 65535) {
        return -1;
    }
    point->port = port;
    return 0;
}

int hostname2endpoint(const char* str, EndPoint* point) {
    // Should be enough to hold ip address
    char buf[64];
    size_t i = 0;
    for (; i < sizeof(buf) - 1 && str[i] != '\0' && str[i] != ':'; ++i) {
        buf[i] = str[i];
    }
    if (i == sizeof(buf) - 1) {
        return -1;
    }

    buf[i] = '\0';
    if (hostname2ip(buf, &point->ip) != 0) {
        return -1;
    }
    if (str[i] == ':') {
        ++i;
    }
    char* end = NULL;
    point->port = strtol(str + i, &end, 10);
    if (end == str + i) {
        return -1;
    } else if (*end) {
        for (; isspace(*end); ++end);
        if (*end) {
            return -1;
        }
    }
    if (point->port < 0 || point->port > 65535) {
        return -1;
    }
    return 0;
}

int hostname2endpoint(const char* name_str, int port, EndPoint* point) {
    if (hostname2ip(name_str, &point->ip) != 0) {
        return -1;
    }
    if (port < 0 || port > 65535) {
        return -1;
    }
    point->port = port;
    return 0;
}

int endpoint2hostname(const EndPoint& point, char* host, size_t host_len) {
    if (ip2hostname(point.ip, host, host_len) == 0) {
        size_t len = strlen(host);
        if (len + 1 < host_len) {
            snprintf(host + len, host_len - len, ":%d", point.port);
        }
        return 0;
    }
    return -1;
}

int endpoint2hostname(const EndPoint& point, std::string* host) {
    char buf[128];
    if (endpoint2hostname(point, buf, sizeof(buf)) == 0) {
        host->assign(buf);
        return 0;
    }
    return -1;
}

int tcp_connect(EndPoint point, int* self_port) {
    fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
    if (sockfd < 0) {
        return -1;
    }
    struct sockaddr_in serv_addr;
    bzero((char*)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr = point.ip;
    serv_addr.sin_port = htons(point.port);
    int rc = 0;
    if (bthread_connect != NULL) {
        rc = bthread_connect(sockfd, (struct sockaddr*)&serv_addr,
                             sizeof(serv_addr));
    } else {
        rc = ::connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    }
    if (rc < 0) {
        return -1;
    }
    if (self_port != NULL) {
        EndPoint pt;
        if (get_local_side(sockfd, &pt) == 0) {
            *self_port = pt.port;
        } else {
            CHECK(false) << "Fail to get the local port of sockfd=" << sockfd;
        }
    }
    return sockfd.release();
}

int tcp_listen(EndPoint point, bool reuse_addr) {
    fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
    if (sockfd < 0) {
        return -1;
    }
    if (reuse_addr) {
        const int on = 1;
        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
                       &on, sizeof(on)) != 0) {
            return -1;
        }
    }

    if (FLAGS_reuse_port) {
        const int on = 1;
        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
                       &on, sizeof(on)) != 0) {
            LOG(WARNING) << "Fail to setsockopt SO_REUSEPORT of sockfd=" << sockfd;
        }
    }

    struct sockaddr_in serv_addr;
    bzero((char*)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr = point.ip;
    serv_addr.sin_port = htons(point.port);
    if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0) {
        return -1;
    }
    if (listen(sockfd, INT_MAX) != 0) {
        //             ^^^ kernel would silently truncate backlog to the value
        //             defined in /proc/sys/net/core/somaxconn
        return -1;
    }
    return sockfd.release();
}

int get_local_side(int fd, EndPoint *out) {
    struct sockaddr addr;
    socklen_t socklen = sizeof(addr);
    const int rc = getsockname(fd, &addr, &socklen);
    if (rc != 0) {
        return rc;
    }
    if (out) {
        *out = butil::EndPoint(*(sockaddr_in*)&addr);
    }
    return 0;
}

int get_remote_side(int fd, EndPoint *out) {
    struct sockaddr addr;
    socklen_t socklen = sizeof(addr);
    const int rc = getpeername(fd, &addr, &socklen);
    if (rc != 0) {
        return rc;
    }
    if (out) {
        *out = butil::EndPoint(*(sockaddr_in*)&addr);
    }
    return 0;
}

}  // namespace butil
<|endoftext|>


<commit_before>//===-- WinEHPrepare - Prepare exception handling for code generation ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass lowers LLVM IR exception handling into something closer to what the
// backend wants. It snifs the personality function to see which kind of
// preparation is necessary. If the personality function uses the Itanium LSDA,
// this pass delegates to the DWARF EH preparation pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
using namespace llvm;

#define DEBUG_TYPE "winehprepare"

namespace {
class WinEHPrepare : public FunctionPass {
  FunctionPass *DwarfPrepare;

public:
  static char ID; // Pass identification, replacement for typeid.
  WinEHPrepare(const TargetMachine *TM = nullptr)
      : FunctionPass(ID), DwarfPrepare(createDwarfEHPass(TM)) {}

  bool runOnFunction(Function &Fn) override;

  bool doFinalization(Module &M) override;

  void getAnalysisUsage(AnalysisUsage &AU) const override;

  const char *getPassName() const override {
    return "Windows exception handling preparation";
  }
};
} // end anonymous namespace

char WinEHPrepare::ID = 0;
INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare",
                   "Prepare Windows exceptions", false, false)

FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
  return new WinEHPrepare(TM);
}

static bool isMSVCPersonality(EHPersonality Pers) {
  return Pers == EHPersonality::MSVC_Win64SEH ||
         Pers == EHPersonality::MSVC_CXX;
}

bool WinEHPrepare::runOnFunction(Function &Fn) {
  SmallVector<LandingPadInst *, 4> LPads;
  SmallVector<ResumeInst *, 4> Resumes;
  for (BasicBlock &BB : Fn) {
    if (auto *LP = BB.getLandingPadInst())
      LPads.push_back(LP);
    if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
      Resumes.push_back(Resume);
  }

  // No need to prepare functions that lack landing pads.
  if (LPads.empty())
    return false;

  // Classify the personality to see what kind of preparation we need.
  EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn());

  // Delegate through to the DWARF pass if this is unrecognized.
  if (!isMSVCPersonality(Pers))
    return DwarfPrepare->runOnFunction(Fn);

  // FIXME: Cleanups are unimplemented. Replace them with calls to @llvm.trap.
  if (Resumes.empty())
    return false;

  for (ResumeInst *Resume : Resumes) {
    IRBuilder<>(Resume).CreateUnreachable();
    Resume->eraseFromParent();
  }

  return true;
}

bool WinEHPrepare::doFinalization(Module &M) {
  return DwarfPrepare->doFinalization(M);
}

void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
  DwarfPrepare->getAnalysisUsage(AU);
}
<commit_msg>Update comments to use unreachable instead of llvm.trap, as implemented now<commit_after>//===-- WinEHPrepare - Prepare exception handling for code generation ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass lowers LLVM IR exception handling into something closer to what the
// backend wants. It snifs the personality function to see which kind of
// preparation is necessary. If the personality function uses the Itanium LSDA,
// this pass delegates to the DWARF EH preparation pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Pass.h"
using namespace llvm;

#define DEBUG_TYPE "winehprepare"

namespace {
class WinEHPrepare : public FunctionPass {
  FunctionPass *DwarfPrepare;

public:
  static char ID; // Pass identification, replacement for typeid.
  WinEHPrepare(const TargetMachine *TM = nullptr)
      : FunctionPass(ID), DwarfPrepare(createDwarfEHPass(TM)) {}

  bool runOnFunction(Function &Fn) override;

  bool doFinalization(Module &M) override;

  void getAnalysisUsage(AnalysisUsage &AU) const override;

  const char *getPassName() const override {
    return "Windows exception handling preparation";
  }
};
} // end anonymous namespace

char WinEHPrepare::ID = 0;
INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare",
                   "Prepare Windows exceptions", false, false)

FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
  return new WinEHPrepare(TM);
}

static bool isMSVCPersonality(EHPersonality Pers) {
  return Pers == EHPersonality::MSVC_Win64SEH ||
         Pers == EHPersonality::MSVC_CXX;
}

bool WinEHPrepare::runOnFunction(Function &Fn) {
  SmallVector<LandingPadInst *, 4> LPads;
  SmallVector<ResumeInst *, 4> Resumes;
  for (BasicBlock &BB : Fn) {
    if (auto *LP = BB.getLandingPadInst())
      LPads.push_back(LP);
    if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
      Resumes.push_back(Resume);
  }

  // No need to prepare functions that lack landing pads.
  if (LPads.empty())
    return false;

  // Classify the personality to see what kind of preparation we need.
  EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn());

  // Delegate through to the DWARF pass if this is unrecognized.
  if (!isMSVCPersonality(Pers))
    return DwarfPrepare->runOnFunction(Fn);

  // FIXME: Cleanups are unimplemented. Replace them with unreachable.
  if (Resumes.empty())
    return false;

  for (ResumeInst *Resume : Resumes) {
    IRBuilder<>(Resume).CreateUnreachable();
    Resume->eraseFromParent();
  }

  return true;
}

bool WinEHPrepare::doFinalization(Module &M) {
  return DwarfPrepare->doFinalization(M);
}

void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
  DwarfPrepare->getAnalysisUsage(AU);
}
<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

// Disable "'this': used in base member initializer list"
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning(disable: 4355)
#endif

#include "remoteobject_p.hpp"
#include <qimessaging/message.hpp>
#include <qimessaging/transportsocket.hpp>
#include <qimessaging/binarydecoder.hpp>
#include <qi/log.hpp>
#include <boost/thread/mutex.hpp>
#include <qi/eventloop.hpp>

namespace qi {

  static qi::MetaObject &createRemoteObjectSpecialMetaObject() {
    static qi::MetaObject *mo = 0;

    if (!mo) {

      mo = new qi::MetaObject;
      qi::MetaObjectBuilder mob;
      mob.addMethod("I", "registerEvent::(III)", qi::Message::BoundObjectFunction_RegisterEvent);
      mob.addMethod("v", "unregisterEvent::(III)", qi::Message::BoundObjectFunction_UnregisterEvent);
      mob.addMethod("({I(ssI)}{I(Is)})", "metaObject::(I)", qi::Message::BoundObjectFunction_MetaObject);
      *mo = mob.metaObject();

      assert(mo->methodId("registerEvent::(III)") == qi::Message::BoundObjectFunction_RegisterEvent);
      assert(mo->methodId("unregisterEvent::(III)") == qi::Message::BoundObjectFunction_UnregisterEvent);
      assert(mo->methodId("metaObject::(I)") == qi::Message::BoundObjectFunction_MetaObject);
    }
    return *mo;
  }

  RemoteObject::RemoteObject(unsigned int service, qi::TransportSocketPtr socket)
    : _socket()
    , _service(service)
    , _linkMessageDispatcher(0)
    , _self(makeDynamicObjectPtr(this, false))
  {
    //simple metaObject with only special methods. (<10)
    setMetaObject(createRemoteObjectSpecialMetaObject());
    setTransportSocket(socket);
    //fetchMetaObject should be called to make sure the metaObject is valid.
  }

  RemoteObject::RemoteObject(unsigned int service, qi::MetaObject metaObject, TransportSocketPtr socket)
    : _socket()
    , _service(service)
    , _linkMessageDispatcher(0)
    , _self(makeDynamicObjectPtr(this, false))
  {
    setMetaObject(metaObject);
    setTransportSocket(socket);
  }

  RemoteObject::~RemoteObject()
  {
    //close may already have been called. (by Session_Service.close)
    close();
  }

  //### RemoteObject

  void RemoteObject::setTransportSocket(qi::TransportSocketPtr socket) {
    if (socket == _socket)
      return;
    if (_socket) {
      _socket->messagePendingDisconnect(_service, _linkMessageDispatcher);
      _socket->disconnected.disconnect(_linkDisconnected);
    }
    _socket = socket;
    //do not set the socket on the remote object
    if (socket) {
      _linkMessageDispatcher = _socket->messagePendingConnect(_service, boost::bind<void>(&RemoteObject::onMessagePending, this, _1));
      _linkDisconnected      = _socket->disconnected.connect (boost::bind<void>(&RemoteObject::onSocketDisconnected, this, _1));
    }
  }

  //should be done in the object thread
  void RemoteObject::onSocketDisconnected(int error)
  {
    {
      boost::mutex::scoped_lock lock(_mutex);
      std::map<int, qi::Promise<GenericValuePtr> >::iterator it = _promises.begin();
      while (it != _promises.end()) {
        qiLogVerbose("RemoteObject") << "Reporting error for request " << it->first << "(socket disconnected)";
        it->second.setError("Socket disconnected");
        _promises.erase(it);
        it = _promises.begin();
      }
    }
  }

  void RemoteObject::onMetaObject(qi::Future<qi::MetaObject> fut, qi::Promise<void> prom) {
    if (fut.hasError()) {
      prom.setError(fut.error());
      return;
    }
    setMetaObject(fut.value());
    prom.setValue(0);
  }

  //retrieve the metaObject from the network
  qi::Future<void> RemoteObject::fetchMetaObject() {
    qi::Promise<void> prom;
    qi::Future<qi::MetaObject> fut = _self->call<qi::MetaObject>("metaObject", 0U);
    fut.connect(boost::bind<void>(&RemoteObject::onMetaObject, this, _1, prom));
    return prom.future();
  }

  //should be done in the object thread
  void RemoteObject::onMessagePending(const qi::Message &msg)
  {
    qi::Promise<GenericValuePtr> promise;
    bool found = false;
    std::map<int, qi::Promise<GenericValuePtr> >::iterator it;

    // qiLogDebug("RemoteObject") << this << " msg " << msg.type() << " " << msg.buffer().size();
    {
      boost::mutex::scoped_lock lock(_mutex);
      it = _promises.find(msg.id());
      if (it != _promises.end()) {
        promise = _promises[msg.id()];
        _promises.erase(it);
        found = true;
      }
    }

    switch (msg.type()) {
      case qi::Message::Type_Reply:
      {
        if (!found) {
          qiLogError("remoteobject") << "no promise found for req id:" << msg.id()
          << "  obj: " << msg.service() << "  func: " << msg.function();
          return;
        }
        // Get call signature
        MetaMethod* mm =  metaObject().method(msg.function());
        if (!mm)
        {
          qiLogError("remoteobject") << "Result for unknown function "
           << msg.function();
           promise.setError("Result for unknown function");
           return;
        }
        Type* type = Type::fromSignature(mm->sigreturn());
        if (!type)
        {
          promise.setError("Unable to find a type for signature " + mm->sigreturn());
          return;
        }
        BinaryDecoder in(msg.buffer());
        promise.setValue(qi::details::deserialize(type, in));
        return;
      }
      case qi::Message::Type_Error: {
        qi::BinaryDecoder ds(msg.buffer());
        std::string    err;
        std::string    sig;
        ds.read(sig);
        if (sig != "s") {
          qiLogError("qi.RemoteObject") << "Invalid error signature: " << sig;
          //houston we have an error about the error..
          promise.setError("unknown error");
          return;
        }
        ds.read(err);
        qiLogVerbose("remoteobject") << "Received error message"  << msg.address() << ":" << err;
        promise.setError(err);
        return;
      }
      case qi::Message::Type_Event: {
        SignalBase* sb = signalBase(msg.event());
        if (sb)
        {
          try {
            std::string sig = sb->signature();
            // Remove top-level tuple
            sig = sig.substr(1, sig.length()-2);
            GenericFunctionParameters args = msg.parameters(sig);
            sb->trigger(args);
            args.destroy();
          }
          catch (const std::exception& e)
          {
            qiLogWarning("remoteobject") << "Deserialize error on event: " << e.what();
          }
        }
        else
        {
          qiLogWarning("remoteobject") << "Event message on unknown signal " << msg.event();
          qiLogDebug("remoteobject") << metaObject().signalMap().size();
        }
        return;
      }
      default:
        qiLogError("remoteobject") << "Message " << msg.address() << " type not handled: " << msg.type();
        return;
    }
  }

  qi::Future<GenericValuePtr> RemoteObject::metaCall(unsigned int method, const qi::GenericFunctionParameters &in, MetaCallType callType)
  {
    qi::Promise<GenericValuePtr> out;
    qi::Message msg;
    msg.setParameters(in);
#ifndef NDEBUG
    std::string sig = metaObject().method(method)->signature();
    sig = signatureSplit(sig)[2];
    // Remove extra tuple layer
    sig = sig.substr(1, sig.length()-2);
    if (sig != msg.signature())
    {
      qiLogWarning("remoteobject") << "call signature mismatch '"
                                   << sig << "' (internal) vs '"
                                   << msg.signature() << "' (message) for:" << metaObject().method(method)->signature();
    }
#endif
    msg.setType(qi::Message::Type_Call);
    msg.setService(_service);
    msg.setObject(qi::Message::GenericObject_Main);
    msg.setFunction(method);
    // qiLogDebug("remoteobject") << this << " metacall " << msg.service() << " " << msg.function() <<" " << msg.id();
    {
      boost::mutex::scoped_lock lock(_mutex);
      if (_promises.find(msg.id()) != _promises.end())
      {
        qiLogError("remoteobject") << "There is already a pending promise with id "
                                   << msg.id();
      }
      _promises[msg.id()] = out;
    }

    //error will come back as a error message
    if (!_socket || !_socket->isConnected() || !_socket->send(msg)) {
      qi::MetaMethod*   meth = metaObject().method(method);
      std::stringstream ss;
      if (meth) {
        ss << "Network error while sending data to method: '";
        ss << meth->signature();;
        ss << "'.";
      } else {
        ss << "Network error while sending data an unknown method (id=" << method << ").";
      }
      if (!_socket->isConnected()) {
        ss << " Socket is not connected.";
        qiLogVerbose("remoteobject") << ss.str();
      } else {
        qiLogError("remoteobject") << ss.str();
      }
      out.setError(ss.str());

      {
        boost::mutex::scoped_lock lock(_mutex);
        _promises.erase(msg.id());
      }
    }
    return out.future();
  }

  void RemoteObject::metaPost(unsigned int event, const qi::GenericFunctionParameters &args)
  {
    // Bounce the emit request to server
    // TODO: one optimisation that could be done is to trigger the local
    // subscribers immediately.
    // But it is a bit complex, because the server will bounce the
    // event back to us.
    qi::Message msg;
    msg.setParameters(args);
    msg.setType(Message::Type_Post);
    msg.setService(_service);
    msg.setObject(qi::Message::GenericObject_Main);
    msg.setFunction(event);
    if (!_socket->send(msg)) {
      qiLogError("remoteobject") << "error while emiting event";
    }
  }

  static void onEventConnected(qi::Future<unsigned int> fut, qi::Promise<unsigned int> prom, unsigned int id) {
    if (fut.hasError()) {
      prom.setError(fut.error());
      return;
    }
    prom.setValue(id);
  }

  qi::Future<unsigned int> RemoteObject::metaConnect(unsigned int event, const SignalSubscriber& sub)
  {
    qi::Promise<unsigned int> prom;

    // Bind the subscriber locally.
    unsigned int uid = DynamicObject::metaConnect(event, sub);

    qiLogDebug("remoteobject") <<"connect() to " << event <<" gave " << uid;
    qi::Future<unsigned int> fut = _self->call<unsigned int>("registerEvent", _service, event, uid);
    fut.connect(boost::bind<void>(&onEventConnected, _1, prom, uid));
    return prom.future();
  }

  qi::Future<void> RemoteObject::metaDisconnect(unsigned int linkId)
  {
    unsigned int event = linkId >> 16;
    //disconnect locally
    qi::Future<void> fut = DynamicObject::metaDisconnect(linkId);
    if (fut.hasError())
    {
      std::stringstream ss;
      ss << "Disconnection failure for " << linkId << ", error:" << fut.error();
      qiLogWarning("qi.object") << ss.str();
      return qi::makeFutureError<void>(ss.str());
    }
    return _self->call<void>("unregisterEvent", _service, event, linkId);
  }

  void RemoteObject::close() {
    if (_socket) {
      _socket->messagePendingDisconnect(_service, _linkMessageDispatcher);
      _socket->disconnected.disconnect(_linkDisconnected);
    }
  }

}

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<commit_msg>remoteobject: do not remoteunregister events when disconnected<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

// Disable "'this': used in base member initializer list"
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning(disable: 4355)
#endif

#include "remoteobject_p.hpp"
#include <qimessaging/message.hpp>
#include <qimessaging/transportsocket.hpp>
#include <qimessaging/binarydecoder.hpp>
#include <qi/log.hpp>
#include <boost/thread/mutex.hpp>
#include <qi/eventloop.hpp>

namespace qi {

  static qi::MetaObject &createRemoteObjectSpecialMetaObject() {
    static qi::MetaObject *mo = 0;

    if (!mo) {

      mo = new qi::MetaObject;
      qi::MetaObjectBuilder mob;
      mob.addMethod("I", "registerEvent::(III)", qi::Message::BoundObjectFunction_RegisterEvent);
      mob.addMethod("v", "unregisterEvent::(III)", qi::Message::BoundObjectFunction_UnregisterEvent);
      mob.addMethod("({I(ssI)}{I(Is)})", "metaObject::(I)", qi::Message::BoundObjectFunction_MetaObject);
      *mo = mob.metaObject();

      assert(mo->methodId("registerEvent::(III)") == qi::Message::BoundObjectFunction_RegisterEvent);
      assert(mo->methodId("unregisterEvent::(III)") == qi::Message::BoundObjectFunction_UnregisterEvent);
      assert(mo->methodId("metaObject::(I)") == qi::Message::BoundObjectFunction_MetaObject);
    }
    return *mo;
  }

  RemoteObject::RemoteObject(unsigned int service, qi::TransportSocketPtr socket)
    : _socket()
    , _service(service)
    , _linkMessageDispatcher(0)
    , _self(makeDynamicObjectPtr(this, false))
  {
    //simple metaObject with only special methods. (<10)
    setMetaObject(createRemoteObjectSpecialMetaObject());
    setTransportSocket(socket);
    //fetchMetaObject should be called to make sure the metaObject is valid.
  }

  RemoteObject::RemoteObject(unsigned int service, qi::MetaObject metaObject, TransportSocketPtr socket)
    : _socket()
    , _service(service)
    , _linkMessageDispatcher(0)
    , _self(makeDynamicObjectPtr(this, false))
  {
    setMetaObject(metaObject);
    setTransportSocket(socket);
  }

  RemoteObject::~RemoteObject()
  {
    //close may already have been called. (by Session_Service.close)
    close();
  }

  //### RemoteObject

  void RemoteObject::setTransportSocket(qi::TransportSocketPtr socket) {
    if (socket == _socket)
      return;
    if (_socket) {
      _socket->messagePendingDisconnect(_service, _linkMessageDispatcher);
      _socket->disconnected.disconnect(_linkDisconnected);
    }
    _socket = socket;
    //do not set the socket on the remote object
    if (socket) {
      _linkMessageDispatcher = _socket->messagePendingConnect(_service, boost::bind<void>(&RemoteObject::onMessagePending, this, _1));
      _linkDisconnected      = _socket->disconnected.connect (boost::bind<void>(&RemoteObject::onSocketDisconnected, this, _1));
    }
  }

  //should be done in the object thread
  void RemoteObject::onSocketDisconnected(int error)
  {
    {
      boost::mutex::scoped_lock lock(_mutex);
      std::map<int, qi::Promise<GenericValuePtr> >::iterator it = _promises.begin();
      while (it != _promises.end()) {
        qiLogVerbose("RemoteObject") << "Reporting error for request " << it->first << "(socket disconnected)";
        it->second.setError("Socket disconnected");
        _promises.erase(it);
        it = _promises.begin();
      }
    }
  }

  void RemoteObject::onMetaObject(qi::Future<qi::MetaObject> fut, qi::Promise<void> prom) {
    if (fut.hasError()) {
      prom.setError(fut.error());
      return;
    }
    setMetaObject(fut.value());
    prom.setValue(0);
  }

  //retrieve the metaObject from the network
  qi::Future<void> RemoteObject::fetchMetaObject() {
    qi::Promise<void> prom;
    qi::Future<qi::MetaObject> fut = _self->call<qi::MetaObject>("metaObject", 0U);
    fut.connect(boost::bind<void>(&RemoteObject::onMetaObject, this, _1, prom));
    return prom.future();
  }

  //should be done in the object thread
  void RemoteObject::onMessagePending(const qi::Message &msg)
  {
    qi::Promise<GenericValuePtr> promise;
    bool found = false;
    std::map<int, qi::Promise<GenericValuePtr> >::iterator it;

    // qiLogDebug("RemoteObject") << this << " msg " << msg.type() << " " << msg.buffer().size();
    {
      boost::mutex::scoped_lock lock(_mutex);
      it = _promises.find(msg.id());
      if (it != _promises.end()) {
        promise = _promises[msg.id()];
        _promises.erase(it);
        found = true;
      }
    }

    switch (msg.type()) {
      case qi::Message::Type_Reply:
      {
        if (!found) {
          qiLogError("remoteobject") << "no promise found for req id:" << msg.id()
          << "  obj: " << msg.service() << "  func: " << msg.function();
          return;
        }
        // Get call signature
        MetaMethod* mm =  metaObject().method(msg.function());
        if (!mm)
        {
          qiLogError("remoteobject") << "Result for unknown function "
           << msg.function();
           promise.setError("Result for unknown function");
           return;
        }
        Type* type = Type::fromSignature(mm->sigreturn());
        if (!type)
        {
          promise.setError("Unable to find a type for signature " + mm->sigreturn());
          return;
        }
        BinaryDecoder in(msg.buffer());
        promise.setValue(qi::details::deserialize(type, in));
        return;
      }
      case qi::Message::Type_Error: {
        qi::BinaryDecoder ds(msg.buffer());
        std::string    err;
        std::string    sig;
        ds.read(sig);
        if (sig != "s") {
          qiLogError("qi.RemoteObject") << "Invalid error signature: " << sig;
          //houston we have an error about the error..
          promise.setError("unknown error");
          return;
        }
        ds.read(err);
        qiLogVerbose("remoteobject") << "Received error message"  << msg.address() << ":" << err;
        promise.setError(err);
        return;
      }
      case qi::Message::Type_Event: {
        SignalBase* sb = signalBase(msg.event());
        if (sb)
        {
          try {
            std::string sig = sb->signature();
            // Remove top-level tuple
            sig = sig.substr(1, sig.length()-2);
            GenericFunctionParameters args = msg.parameters(sig);
            sb->trigger(args);
            args.destroy();
          }
          catch (const std::exception& e)
          {
            qiLogWarning("remoteobject") << "Deserialize error on event: " << e.what();
          }
        }
        else
        {
          qiLogWarning("remoteobject") << "Event message on unknown signal " << msg.event();
          qiLogDebug("remoteobject") << metaObject().signalMap().size();
        }
        return;
      }
      default:
        qiLogError("remoteobject") << "Message " << msg.address() << " type not handled: " << msg.type();
        return;
    }
  }

  qi::Future<GenericValuePtr> RemoteObject::metaCall(unsigned int method, const qi::GenericFunctionParameters &in, MetaCallType callType)
  {
    qi::Promise<GenericValuePtr> out;
    qi::Message msg;
    msg.setParameters(in);
#ifndef NDEBUG
    std::string sig = metaObject().method(method)->signature();
    sig = signatureSplit(sig)[2];
    // Remove extra tuple layer
    sig = sig.substr(1, sig.length()-2);
    if (sig != msg.signature())
    {
      qiLogWarning("remoteobject") << "call signature mismatch '"
                                   << sig << "' (internal) vs '"
                                   << msg.signature() << "' (message) for:" << metaObject().method(method)->signature();
    }
#endif
    msg.setType(qi::Message::Type_Call);
    msg.setService(_service);
    msg.setObject(qi::Message::GenericObject_Main);
    msg.setFunction(method);
    // qiLogDebug("remoteobject") << this << " metacall " << msg.service() << " " << msg.function() <<" " << msg.id();
    {
      boost::mutex::scoped_lock lock(_mutex);
      if (_promises.find(msg.id()) != _promises.end())
      {
        qiLogError("remoteobject") << "There is already a pending promise with id "
                                   << msg.id();
      }
      _promises[msg.id()] = out;
    }

    //error will come back as a error message
    if (!_socket || !_socket->isConnected() || !_socket->send(msg)) {
      qi::MetaMethod*   meth = metaObject().method(method);
      std::stringstream ss;
      if (meth) {
        ss << "Network error while sending data to method: '";
        ss << meth->signature();;
        ss << "'.";
      } else {
        ss << "Network error while sending data an unknown method (id=" << method << ").";
      }
      if (!_socket->isConnected()) {
        ss << " Socket is not connected.";
        qiLogVerbose("remoteobject") << ss.str();
      } else {
        qiLogError("remoteobject") << ss.str();
      }
      out.setError(ss.str());

      {
        boost::mutex::scoped_lock lock(_mutex);
        _promises.erase(msg.id());
      }
    }
    return out.future();
  }

  void RemoteObject::metaPost(unsigned int event, const qi::GenericFunctionParameters &args)
  {
    // Bounce the emit request to server
    // TODO: one optimisation that could be done is to trigger the local
    // subscribers immediately.
    // But it is a bit complex, because the server will bounce the
    // event back to us.
    qi::Message msg;
    msg.setParameters(args);
    msg.setType(Message::Type_Post);
    msg.setService(_service);
    msg.setObject(qi::Message::GenericObject_Main);
    msg.setFunction(event);
    if (!_socket->send(msg)) {
      qiLogError("remoteobject") << "error while emiting event";
    }
  }

  static void onEventConnected(qi::Future<unsigned int> fut, qi::Promise<unsigned int> prom, unsigned int id) {
    if (fut.hasError()) {
      prom.setError(fut.error());
      return;
    }
    prom.setValue(id);
  }

  qi::Future<unsigned int> RemoteObject::metaConnect(unsigned int event, const SignalSubscriber& sub)
  {
    qi::Promise<unsigned int> prom;

    // Bind the subscriber locally.
    unsigned int uid = DynamicObject::metaConnect(event, sub);

    qiLogDebug("remoteobject") <<"connect() to " << event <<" gave " << uid;
    qi::Future<unsigned int> fut = _self->call<unsigned int>("registerEvent", _service, event, uid);
    fut.connect(boost::bind<void>(&onEventConnected, _1, prom, uid));
    return prom.future();
  }

  qi::Future<void> RemoteObject::metaDisconnect(unsigned int linkId)
  {
    unsigned int event = linkId >> 16;
    //disconnect locally
    qi::Future<void> fut = DynamicObject::metaDisconnect(linkId);
    if (fut.hasError())
    {
      std::stringstream ss;
      ss << "Disconnection failure for " << linkId << ", error:" << fut.error();
      qiLogWarning("qi.object") << ss.str();
      return qi::makeFutureError<void>(ss.str());
    }
    if (_socket->isConnected())
      return _self->call<void>("unregisterEvent", _service, event, linkId);
    return qi::makeFutureError<void>("No remote unregister: socket disconnected");
  }

  void RemoteObject::close() {
    if (_socket) {
      _socket->messagePendingDisconnect(_service, _linkMessageDispatcher);
      _socket->disconnected.disconnect(_linkDisconnected);
    }
  }

}

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<|endoftext|>


<commit_before>/*
    This file is part of the KDE alarm daemon.
    Copyright (c) 1997-1999 Preston Brown
    Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
    Copyright (c) 2001 David Jarvie <software@astrojar.org.uk>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

// $Id$

#include <qstring.h>

#include <kcmdlineargs.h>
#include <kdebug.h>

#include "alarmdaemon.h"

#include "alarmapp.h"
#include "alarmapp.moc"

AlarmApp::AlarmApp() :
  KUniqueApplication(/*false,false*/),
  mAd(0L)
{
}

AlarmApp::~AlarmApp()
{
}

int AlarmApp::newInstance()
{
  kdDebug(5900) << "kalarmd:AlarmApp::newInstance()" << endl;

  // Check if we already have a running alarm daemon widget
  if (mAd) return 0;

  // Check if we are starting up at session startup
  static bool restored = false;
  if (!restored  &&  isRestored()) {
    mStartedAtLogin = true;
    restored = true;       // make sure we restore only once
  }
  else {
    KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
    mStartedAtLogin = args->isSet("login");
    args->clear();      // free up memory
  }

  mAd = new AlarmDaemon(0L, "ad");

  return 0;
}
<commit_msg>+  KStartupInfo::appStarted();<commit_after>/*
    This file is part of the KDE alarm daemon.
    Copyright (c) 1997-1999 Preston Brown
    Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
    Copyright (c) 2001 David Jarvie <software@astrojar.org.uk>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

// $Id$

#include <qstring.h>

#include <kcmdlineargs.h>
#include <kdebug.h>
#include <kstartupinfo.h>

#include "alarmdaemon.h"

#include "alarmapp.h"
#include "alarmapp.moc"

AlarmApp::AlarmApp() :
  KUniqueApplication(/*false,false*/),
  mAd(0L)
{
}

AlarmApp::~AlarmApp()
{
}

int AlarmApp::newInstance()
{
  kdDebug(5900) << "kalarmd:AlarmApp::newInstance()" << endl;

  KStartupInfo::appStarted();

  // Check if we already have a running alarm daemon widget
  if (mAd) return 0;

  // Check if we are starting up at session startup
  static bool restored = false;
  if (!restored  &&  isRestored()) {
    mStartedAtLogin = true;
    restored = true;       // make sure we restore only once
  }
  else {
    KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
    mStartedAtLogin = args->isSet("login");
    args->clear();      // free up memory
  }

  mAd = new AlarmDaemon(0L, "ad");

  return 0;
}
<|endoftext|>


<commit_before>#include "application.h"
#include <elapsedMillis.h>
#include <math.h>
//#define DEBUGME
#ifdef DEBUGME
    #define DEBUGp(message)     Serial.print(message)
    #define DEBUGpln(message)   Serial.println(message)
#else
    #define DEBUGp(message)
    #define DEBUGpln(message)
#endif

int led = D7; // This one is the built-in tiny one to the right of the USB jack

//pins for decimal point and each segment
const int numberofSegments=8;

//A, B, C, D, E, F, G, dp
const int segmentPins[]= { A0, D4, D2, D1, D0, A1, D3, A2};

const int numberofDigits=4;

const int digitPins[numberofDigits] = { A3, A4, D5, D6}; //digits 1, 2, 3, 4

int outputSegmentValues[] = {0b00000010, 0b00000010, 0b00000010, 0b00000010}; // Initial values for Digits

// delay in milliseconds between Weather requests (10 minutes)
const unsigned long intervalAfterFirstUpdate = 10 * 60 * 1000;   // Set interval here

unsigned long interval = 20 * 1000;      // Actual value changes after first update
// Elapsed time since update
elapsedMillis timeElapsed;

//ABCDEFG,dp
const int numeral[10]= {
    0b11111100, //0
    0b01100000, //1
    0b11011010, //2
    0b11110010, //3
    0b01100110, //4
    0b10110110, //5
    0b10111110, //6
    0b11100000, //7
    0b11111110, //8
    0b11110110, //9
};
const int statusCode[10]= {
    0b01111100, //U
    0b00011110, //t
    0b10011100, //C
    0b00111010, //o
    0b11111100, //O
    0b01111010, //d
    0b00001010, //r
    0b10110110, //S
    0b10001110, //F
    0b10011110, //E
};

void selectDigit(int segment) {
    for (int i = 0; i < numberofSegments; i++) {
        if (segment == i) {
            digitalWrite(digitPins[i], HIGH);
        }
        else {
            digitalWrite(digitPins[i], LOW);
        }
    }
}

void clearDigit(int segment) {
    int segmentCounter = numberofSegments;
    while (segmentCounter) {
        digitalWrite(segmentPins[--segmentCounter],HIGH);
    }
}

void outputDigit(int segment, int value) {
    delay(segment == 0? 0: 4);              // Loop is taking some time causing visible brightness difference. Hence, Compensation.
    clearDigit(segment);                    // Clear the digit before moving. Overwriting is causing fade effect.
    selectDigit(segment);
    int segmentCounter = numberofSegments;
    if (value > 0)                          // only if there is something to turn on.
    {
        while (segmentCounter) {
            digitalWrite(segmentPins[--segmentCounter], (int)(value & 1) ? LOW: HIGH);  // Display LSB
            value >>= 1;                                                                // Set LSB
        }
    }
}

void displayWeather() {
   for (int i = 0; i < numberofDigits; i++) {                               // Display Each Segment
         outputDigit(i, outputSegmentValues[i]);
   }
}
void setSegmentValues(bool minus, int temp, int status) {
    DEBUGpln(minus);
    DEBUGpln(temp);
    DEBUGpln(status);
    outputSegmentValues[0] = minus? 0b00000010: 0b00000000;                 // Set G segment for minus
    int digitCounter = (temp < 10 || (temp < 100 && !minus))? 1: 2;                                  // To format  || (temp < 100 && !minus)
    outputSegmentValues[2] = 0b00000000;                                    // To clear the 2nd digit in case of single digit Weather
    do {                                                                    // Run once to display 0
      outputSegmentValues[digitCounter] = numeral[temp%10];
      temp /= 10;
      digitCounter--;
    } while (temp);
    outputSegmentValues[3] = statusCode[status];
}

void processValues(const char *temperature, const char *id) {
    //Sample:  temperature: -4.81  id: 800
    DEBUGpln(temperature);
    DEBUGpln(id);
    int intemperature =(int)(roundf(strtod(temperature,NULL))); // Round the temperature
    int intid = atoi(id);
    int status=0;  // U unknown
    if((int)(intid/100) == 2)
    {
        status = 1; //thunders t
    }else if (intid == 800)
    {
        status = 2;  //Clear Sky C
    }else if (intid == 801 || intid == 802)
    {
        status = 3;  //Partly Overcast o
    }else if (intid == 804 || intid == 803)
    {
        status = 4;   //Overcast O
    }else if ((int)(intid / 100)  == 3)
    {
        status = 5;   //Drizzle d
    }else if ((int)(intid / 100) == 5)
    {
        status = 6;   //Rain r
    }else if ((int)(intid / 100) == 6)
    {
        status = 7;   //Snow s
    }else if ((int)(intid / 100) == 7)
    {
        status = 8;   //Fog F
    }else if (intid >= 900 && intid < 910)
    {
        status = 9;   //Extreme E
    }

    setSegmentValues(intemperature < 0, intemperature < 0 ? intemperature * -1: intemperature, status);
}

void processWeather(const char *event, const char *data) {
    //Sample data: 800~-4.81
    DEBUGpln("Handling Weather: ");
    // Handle the webhook response
    int stringPos = strlen(data);
    char w_temp[7] = {""};
    char w_id[4] = {""};
    int itemCounter = 0;
    int tempStringLoc = 0;
    memset(w_temp, 0, sizeof(w_temp));
    memset(w_id, 0, sizeof(w_id));
    for (int i = 0; i < stringPos; i++){
        if(data[i] == '~'){
                    itemCounter++;
                    tempStringLoc = 0;
        }else
        {
            switch(itemCounter){
                case 0:
                    if(tempStringLoc < sizeof(w_id)-1) {      //Takes 3 digits: Sometimes there's error in the data received
                        w_id[tempStringLoc++] = data[i];
                    }
                    break;
                case 1:
                    w_temp[tempStringLoc++] = data[i];
                    break;
            }
        }
    }
    processValues(w_temp,w_id);
    digitalWrite(led, LOW);                             // Turn off when the response is received
    if (interval < intervalAfterFirstUpdate) {          // Changes the actual interval value
        interval = intervalAfterFirstUpdate;
        // removing this for block (or moving this if block to the top of this function)
        // is causing unwanted segments to turn on. I don't know why.
        for (int i = 0; i < numberofDigits; i++) {
            Serial.println();
        }
    }

}
void setupPins() {
    pinMode(led, OUTPUT);
    for (int i = 0; i < numberofDigits; i++) {
        pinMode( digitPins[i], OUTPUT);
    }
    for (int i = 0; i < numberofSegments; i++) {
        pinMode( segmentPins[i], OUTPUT);
    }
}

void setup() {
    setupPins();
    #if defined (DEBUGME)
        Serial.begin(115200);
    #endif
    DEBUGp("Started: ");
    // Subscribe to the webhook response event
    Particle.subscribe("hook-response/weather_hook", processWeather , MY_DEVICES);
}

void loop() {
    if (timeElapsed > interval)
    {
        // Get some data
        String data = String(10);
        digitalWrite(led, HIGH);    // Turn on when the request is sent
        // Trigger the webhook
        Particle.publish("weather_hook", data, PRIVATE);
        timeElapsed = 0;            // reset the counter to 0 so the counting starts over...
    }
    displayWeather();
}<commit_msg>Overflow Fix<commit_after>#include "application.h"
#include <elapsedMillis.h>
#include <math.h>
//#define DEBUGME
#ifdef DEBUGME
    #define DEBUGp(message)     Serial.print(message)
    #define DEBUGpln(message)   Serial.println(message)
#else
    #define DEBUGp(message)
    #define DEBUGpln(message)
#endif

int led = D7; // This one is the built-in tiny one to the right of the USB jack

//pins for decimal point and each segment
const int numberofSegments=8;

//A, B, C, D, E, F, G, dp
const int segmentPins[]= { A0, D4, D2, D1, D0, A1, D3, A2};

const int numberofDigits=4;

const int digitPins[numberofDigits] = { A3, A4, D5, D6}; //digits 1, 2, 3, 4

int outputSegmentValues[] = {0b00000010, 0b00000010, 0b00000010, 0b00000010}; // Initial values for Digits

// delay in milliseconds between Weather requests (10 minutes)
const unsigned long intervalAfterFirstUpdate = 10 * 60 * 1000;   // Set interval here

unsigned long interval = 20 * 1000;      // Actual value changes after first update
// Elapsed time since update
elapsedMillis timeElapsed;

//ABCDEFG,dp
const int numeral[10]= {
    0b11111100, //0
    0b01100000, //1
    0b11011010, //2
    0b11110010, //3
    0b01100110, //4
    0b10110110, //5
    0b10111110, //6
    0b11100000, //7
    0b11111110, //8
    0b11110110, //9
};
const int statusCode[10]= {
    0b01111100, //U
    0b00011110, //t
    0b10011100, //C
    0b00111010, //o
    0b11111100, //O
    0b01111010, //d
    0b00001010, //r
    0b10110110, //S
    0b10001110, //F
    0b10011110, //E
};

void selectDigit(int segment) {
    for (int i = 0; i < numberofSegments; i++) {
        if (segment == i) {
            digitalWrite(digitPins[i], HIGH);
        }
        else {
            digitalWrite(digitPins[i], LOW);
        }
    }
}

void clearDigit(int segment) {
    int segmentCounter = numberofSegments;
    while (segmentCounter) {
        digitalWrite(segmentPins[--segmentCounter],HIGH);
    }
}

void outputDigit(int segment, int value) {
    delay(segment == 0? 0: 4);              // Loop is taking some time causing visible brightness difference. Hence, Compensation.
    clearDigit(segment);                    // Clear the digit before moving. Overwriting is causing fade effect.
    selectDigit(segment);
    int segmentCounter = numberofSegments;
    if (value > 0)                          // only if there is something to turn on.
    {
        while (segmentCounter) {
            digitalWrite(segmentPins[--segmentCounter], (int)(value & 1) ? LOW: HIGH);  // Display LSB
            value >>= 1;                                                                // Set LSB
        }
    }
}

void displayWeather() {
   for (int i = 0; i < numberofDigits; i++) {                               // Display Each Segment
         outputDigit(i, outputSegmentValues[i]);
   }
}
void setSegmentValues(bool minus, int temp, int status) {
    DEBUGpln(minus);
    DEBUGpln(temp);
    DEBUGpln(status);
    outputSegmentValues[0] = minus? 0b00000010: 0b00000000;                 // Set G segment for minus
    int digitCounter = (temp < 10 || (temp < 100 && !minus))? 1: 2;                                  // To format  || (temp < 100 && !minus)
    outputSegmentValues[2] = 0b00000000;                                    // To clear the 2nd digit in case of single digit Weather
    do {                                                                    // Run once to display 0
      outputSegmentValues[digitCounter] = numeral[temp%10];
      temp /= 10;
      digitCounter--;
    } while (temp);
    outputSegmentValues[3] = statusCode[status];
}

void processValues(const char *temperature, const char *id) {
    //Sample:  temperature: -4.81  id: 800
    DEBUGpln(temperature);
    DEBUGpln(id);
    int intemperature =(int)(roundf(strtod(temperature,NULL))); // Round the temperature
    int intid = atoi(id);
    int status=0;  // U unknown
    if((int)(intid/100) == 2)
    {
        status = 1; //thunders t
    }else if (intid == 800)
    {
        status = 2;  //Clear Sky C
    }else if (intid == 801 || intid == 802)
    {
        status = 3;  //Partly Overcast o
    }else if (intid == 804 || intid == 803)
    {
        status = 4;   //Overcast O
    }else if ((int)(intid / 100)  == 3)
    {
        status = 5;   //Drizzle d
    }else if ((int)(intid / 100) == 5)
    {
        status = 6;   //Rain r
    }else if ((int)(intid / 100) == 6)
    {
        status = 7;   //Snow s
    }else if ((int)(intid / 100) == 7)
    {
        status = 8;   //Fog F
    }else if (intid >= 900 && intid < 910)
    {
        status = 9;   //Extreme E
    }

    setSegmentValues(intemperature < 0, intemperature < 0 ? intemperature * -1: intemperature, status);
}

void processWeather(const char *event, const char *data) {
    //Sample data: 800~-4.81
    DEBUGpln("Handling Weather: ");
    // Handle the webhook response
    int stringPos = strlen(data);
    char w_temp[8] = {""};  // can accomodate: -100.46
    char w_id[4] = {""};
    int itemCounter = 0;
    int tempStringLoc = 0;
    memset(w_temp, 0, sizeof(w_temp));
    memset(w_id, 0, sizeof(w_id));
    for (int i = 0; i < stringPos; i++){
        if(data[i] == '~'){
                    itemCounter++;
                    tempStringLoc = 0;
        }else
        {
            switch(itemCounter){
                case 0:
                    if(tempStringLoc < sizeof(w_id)-1) {      //Takes 3 digits: Sometimes there's error in the data received
                        w_id[tempStringLoc++] = data[i];
                    }
                    break;
                case 1:
                    w_temp[tempStringLoc++] = data[i];
                    break;
            }
        }
    }
    processValues(w_temp,w_id);
    digitalWrite(led, LOW);                             // Turn off when the response is received
    if (interval < intervalAfterFirstUpdate) {          // Changes the actual interval value
        interval = intervalAfterFirstUpdate;
        // removing this for block (or moving this if block to the top of this function)
        // is causing unwanted segments to turn on. I don't know why.
        for (int i = 0; i < numberofDigits; i++) {
            Serial.println();
        }
    }

}
void setupPins() {
    pinMode(led, OUTPUT);
    for (int i = 0; i < numberofDigits; i++) {
        pinMode( digitPins[i], OUTPUT);
    }
    for (int i = 0; i < numberofSegments; i++) {
        pinMode( segmentPins[i], OUTPUT);
    }
}

void setup() {
    setupPins();
    #if defined (DEBUGME)
        Serial.begin(115200);
    #endif
    DEBUGp("Started: ");
    // Subscribe to the webhook response event
    Particle.subscribe("hook-response/weather_hook", processWeather , MY_DEVICES);
}

void loop() {
    if (timeElapsed > interval)
    {
        // Get some data
        String data = String(10);
        digitalWrite(led, HIGH);    // Turn on when the request is sent
        // Trigger the webhook
        Particle.publish("weather_hook", data, PRIVATE);
        timeElapsed = 0;            // reset the counter to 0 so the counting starts over...
    }
    displayWeather();
}<|endoftext|>


<commit_before>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2016, Itseez, Inc, all rights reserved.

#include "test_precomp.hpp"
#include <vector>
#include <cmath>

using namespace cv;
using namespace std;

// return true if point lies inside ellipse
static bool check_pt_in_ellipse(const Point2f& pt, const RotatedRect& el) {
    Point2f to_pt = pt - el.center;
    double pt_angle = atan2(to_pt.y, to_pt.x);
    double el_angle = el.angle * CV_PI / 180;
    double x_dist = 0.5 * el.size.width * cos(pt_angle + el_angle);
    double y_dist = 0.5 * el.size.height * sin(pt_angle + el_angle);
    double el_dist = sqrt(x_dist * x_dist + y_dist * y_dist);
    return norm(to_pt) < el_dist;
}

// Return true if mass center of fitted points lies inside ellipse
static bool fit_and_check_ellipse(const vector<Point2f>& pts) {
    RotatedRect ellipse = fitEllipse(pts);

    Point2f mass_center;
    for (size_t i = 0; i < pts.size(); i++) {
        mass_center += pts[i];
    }
    mass_center /= (float)pts.size();

    return check_pt_in_ellipse(mass_center, ellipse);
}

TEST(Imgproc_FitEllipse_Issue_4515, DISABLED_accuracy) {
    vector<Point2f> pts;
    pts.push_back(Point2f(327, 317));
    pts.push_back(Point2f(328, 316));
    pts.push_back(Point2f(329, 315));
    pts.push_back(Point2f(330, 314));
    pts.push_back(Point2f(331, 314));
    pts.push_back(Point2f(332, 314));
    pts.push_back(Point2f(333, 315));
    pts.push_back(Point2f(333, 316));
    pts.push_back(Point2f(333, 317));
    pts.push_back(Point2f(333, 318));
    pts.push_back(Point2f(333, 319));
    pts.push_back(Point2f(333, 320));

    EXPECT_TRUE(fit_and_check_ellipse(pts));
}

TEST(Imgproc_FitEllipse_Issue_6544, DISABLED_accuracy) {
    vector<Point2f> pts;
    pts.push_back(Point2f(924.784f, 764.160f));
    pts.push_back(Point2f(928.388f, 615.903f));
    pts.push_back(Point2f(847.4f,   888.014f));
    pts.push_back(Point2f(929.406f, 741.675f));
    pts.push_back(Point2f(904.564f, 825.605f));
    pts.push_back(Point2f(926.742f, 760.746f));
    pts.push_back(Point2f(863.479f, 873.406f));
    pts.push_back(Point2f(910.987f, 808.863f));
    pts.push_back(Point2f(929.145f, 744.976f));
    pts.push_back(Point2f(917.474f, 791.823f));

    EXPECT_TRUE(fit_and_check_ellipse(pts));
}
<commit_msg>enabled tests for fitEllipse since the issue is fixed<commit_after>// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Copyright (C) 2016, Itseez, Inc, all rights reserved.

#include "test_precomp.hpp"
#include <vector>
#include <cmath>

using namespace cv;
using namespace std;

// return true if point lies inside ellipse
static bool check_pt_in_ellipse(const Point2f& pt, const RotatedRect& el) {
    Point2f to_pt = pt - el.center;
    double pt_angle = atan2(to_pt.y, to_pt.x);
    double el_angle = el.angle * CV_PI / 180;
    double x_dist = 0.5 * el.size.width * cos(pt_angle + el_angle);
    double y_dist = 0.5 * el.size.height * sin(pt_angle + el_angle);
    double el_dist = sqrt(x_dist * x_dist + y_dist * y_dist);
    return norm(to_pt) < el_dist;
}

// Return true if mass center of fitted points lies inside ellipse
static bool fit_and_check_ellipse(const vector<Point2f>& pts) {
    RotatedRect ellipse = fitEllipseDirect(pts); // fitEllipseAMS() also works fine

    Point2f mass_center;
    for (size_t i = 0; i < pts.size(); i++) {
        mass_center += pts[i];
    }
    mass_center /= (float)pts.size();

    return check_pt_in_ellipse(mass_center, ellipse);
}

TEST(Imgproc_FitEllipse_Issue_4515, accuracy) {
    vector<Point2f> pts;
    pts.push_back(Point2f(327, 317));
    pts.push_back(Point2f(328, 316));
    pts.push_back(Point2f(329, 315));
    pts.push_back(Point2f(330, 314));
    pts.push_back(Point2f(331, 314));
    pts.push_back(Point2f(332, 314));
    pts.push_back(Point2f(333, 315));
    pts.push_back(Point2f(333, 316));
    pts.push_back(Point2f(333, 317));
    pts.push_back(Point2f(333, 318));
    pts.push_back(Point2f(333, 319));
    pts.push_back(Point2f(333, 320));

    EXPECT_TRUE(fit_and_check_ellipse(pts));
}

TEST(Imgproc_FitEllipse_Issue_6544, accuracy) {
    vector<Point2f> pts;
    pts.push_back(Point2f(924.784f, 764.160f));
    pts.push_back(Point2f(928.388f, 615.903f));
    pts.push_back(Point2f(847.4f,   888.014f));
    pts.push_back(Point2f(929.406f, 741.675f));
    pts.push_back(Point2f(904.564f, 825.605f));
    pts.push_back(Point2f(926.742f, 760.746f));
    pts.push_back(Point2f(863.479f, 873.406f));
    pts.push_back(Point2f(910.987f, 808.863f));
    pts.push_back(Point2f(929.145f, 744.976f));
    pts.push_back(Point2f(917.474f, 791.823f));

    EXPECT_TRUE(fit_and_check_ellipse(pts));
}
<|endoftext|>