LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C - Gtk + timer + sockets + cairo (https://www.linuxquestions.org/questions/programming-9/c-gtk-timer-sockets-cairo-931809/)

Dr_Lion 02-28-2012 05:02 PM

C - Gtk + timer + sockets + cairo
 
My ideia is to draw a circle with a radius "radius" and i'm thinking about using a gtk window for it. I need to redraw it from time to time or everytime that comes a new value from a socket message. My problem is i don't know where to put the socket code, to be constantly reading the socket messages.

I thought puting the code after the gtk function but the program hang on, and only jump to the socket piece of code after closing the gtk window.


Does anyone knows where to paste the code? i had another ideia and it would be to create two threads and put gtk window in one thread and the socket receiver code in another, what you think?



Code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <cairo.h>
#include <gtk/gtk.h>
#include <time.h>


#define M_PI 3.1415
#define MYPORT "4950"    // the port users will be connecting to
#define MAX_EST 70
#define MAXBUFLEN 100

double radius1 = 100.0;

static char buffer[256];

static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
        double xc1 = 300.0;
        double yc1 = 225.0;


        double angle1 = 0.0  * (M_PI/180.0);  /* angles are specified */
        double angle2 = 360.0 * (M_PI/180.0);  /* in radians          */

        cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 500, 500);
        //cairo_t *cr = cairo_create (surface);

        cairo_t *cr;
        cr = gdk_cairo_create(widget->window);
                       
        //circ 1
        cairo_set_line_width (cr, 10.0);
        cairo_arc (cr, xc1, yc1, radius1, angle1, angle2);
        cairo_stroke (cr);
               
        cairo_destroy(cr);

  return FALSE;
}


static gboolean time_handler(GtkWidget *widget)
{
  if (widget->window == NULL) return FALSE;

  time_t curtime;
  struct tm *loctime;

  curtime = time(NULL);
  loctime = localtime(&curtime);
  strftime(buffer, 256, "%T", loctime);
 
        //printf("\n %f", radius1);
  gtk_widget_queue_draw(widget);
  return TRUE;
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }
 
    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main (int argc, char *argv[])
{
       
        int sockfd;
    struct addrinfo hints, *servinfo, *p;
    int rv;
    int numbytes;
    struct sockaddr_storage their_addr;
    char buf[MAXBUFLEN];
    socklen_t addr_len;
    char s[INET6_ADDRSTRLEN];
   
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE; // use my IP
 
    if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }
 
    // loop through all the results and bind to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("listener: socket");
            continue;
        }
 
        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("listener: bind");
            continue;
        }
 
        break;
    }
   
    if (p == NULL) {
        fprintf(stderr, "listener: failed to bind socket\n");
        return 2;
    }
 
    freeaddrinfo(servinfo);

  GtkWidget *window;
  GtkWidget *darea;

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  darea = gtk_drawing_area_new();
  gtk_container_add(GTK_CONTAINER (window), darea);

  g_signal_connect(darea, "expose-event",
      G_CALLBACK(on_expose_event), NULL);
  g_signal_connect(window, "destroy",
      G_CALLBACK(gtk_main_quit), NULL);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 600, 600);

  gtk_window_set_title(GTK_WINDOW(window), "timer");
  g_timeout_add(1000, (GSourceFunc) time_handler, (gpointer) window);
  gtk_widget_show_all(window);
  time_handler(window);

  gtk_main();
 
  //codigo socket
 
  printf("listener: waiting to recvfrom...\n");
       
        while (1) {       
                printf("dentro do while\n");
                addr_len = sizeof their_addr;
                if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, (struct sockaddr *) &their_addr, &addr_len)) == -1) {
                        perror("recvfrom");
                        exit(1);
                }
       
       
                printf("listener: got packet from %s\n", inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *) &their_addr), s, sizeof s));

                printf("listener: packet is %d bytes long\n", numbytes);
                buf[numbytes] = '\0';
                printf("RECEBIDO: \"%s\"\n", buf);

                radius1 = atoi(buf);
       
                printf("\n %f", radius1);
       
        }
 
  //fim do codigo socket

  return 0;
}

Thanks in advance, and sorry my bad english.

skoona 02-29-2012 06:19 PM

GIOChannels is a facility the fully supports the GTK environment. You can research more example using "GIOChannel
as the keyword.

Hope that gets you started.


All times are GMT -5. The time now is 07:15 AM.