file_main.c
author Tero Marttila <terom@fixme.fi>
Wed, 27 Aug 2008 21:30:32 +0300
changeset 41 540737bf6bac
parent 12 43297144f196
permissions -rw-r--r--
sending requests, and partial support for receiving -- incomplete, not tested
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include "common.h"
#include "render.h"
#include "render_local.h"

static int verbose;

int render_file_local (struct render *ctx, FILE *fh) {
    double duration;

    if (render_io_stream(ctx, fh))
        ERROR("render_io_stream");

    if (render_local(ctx, &duration))
        ERROR("render_local");

    if (verbose) {
        u_int32_t img_w, img_h;

        if (render_get_size(ctx, &img_w, &img_h))
            ERROR("render_get_size");

        fprintf(stdout, "rendered %dx%d mandelbrot in %f seconds\n", img_w, img_h, duration);
    }
    
    return 0;
    
error:
    return -1;
}

int main (int argc, char **argv) {
    int error = 1;

    struct render *ctx = NULL;

    // parse arguments
    int opt;
    FILE *output = NULL;
    int img_w = 256, img_h = 256;

    while ((opt = getopt(argc, argv, "w:h:o:v")) != -1) {
        switch(opt) {
            case 'w' :
                img_w = atoi(optarg);
                break;

            case 'h' :
                img_h = atoi(optarg);
                break;

            case 'o' :
                if (output)
                    err_exit("Only use -o once");

                output = fopen(optarg, "w");

                if (!output)
                    PFATAL("fopen: %s", optarg);

                break;

            case 'v' :
                verbose = 1;
                break;


            default :
                err_exit("Usage: %s [-w img_w] [-h img_h] [-o output_file] [-v]", argv[0]);
        }
    }

    if (!output)
        output = stdout;
    
    // setup the struct render
    if (!(ctx = render_alloc()))
        ERROR("render_alloc");

    if (render_set_mode(ctx, RENDER_PNG))
        ERROR("render_set_mode");

    if (render_set_size(ctx, img_w, img_h))
        ERROR("render_set_size");

    if (render_region_full(ctx))
        ERROR("render_region_full");
    
    // do the render!
    if (verbose)
        fprintf(stderr, "Render [%dx%d] mandelbrot locally...\n", img_w, img_h);
    
    if (render_file_local(ctx, output))
        ERROR("render_local");
    
    // success
    error = 0;

error:
    if (output)
        fclose(output);

    free(ctx);

    return error;
}

#if 0
void render_remote (int img_w, int img_h, FILE *output, FILE *remote) {
    render_t ctx;
    struct render_cmd cmd;

    render_init(&ctx, RENDER_PNG);
    render_set_size(&ctx, img_w, img_h);
    render_region_full(&ctx);

    if (render_cmd_build(&ctx, &cmd))
        err_exit("mandelbrot_render_remote failed");

    int ret = fwrite((void *) &cmd, sizeof(cmd), 1, remote);
    
    if (ret != 1)
        perr_exit("fwrite(remote)");
        
    if (verbose)
        printf("sent render command of %zu bytes\n", sizeof(cmd));

    // shuffle data around
    while (!feof(remote)) {
        char buf[1024];

        int bytes = fread(buf, 1, sizeof(buf), remote);

        if (bytes)
            if (fwrite(buf, bytes, 1, output) != 1)
                perr_exit("fwrite(output)");
    }
    
    if (verbose)
        printf("got PNG data\n");

    if (ferror(remote))
        perr_exit("fread(remote)");
}

FILE *open_remote (char *remote) {
    char *addr_str, *port_str = NULL;

    addr_str = strsep(&remote, ":");

    if (remote)
        port_str = remote;
    
    struct sockaddr_in addr;

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port_str ? atoi(port_str) : RENDER_PORT);
    
    if (inet_aton(addr_str, &addr.sin_addr) == 0)
        err_exit("invalid address: %s", addr_str);

    int sock;
    
    if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
        perr_exit("socket");

    if (verbose)
        printf("connect(%s, %d)\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    
    if (connect(sock, (const struct sockaddr *) &addr, sizeof(addr)) == -1)
        perr_exit("connect(%s, %d)", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
    
    FILE *fh = fdopen(sock, "w+");

    if (!fh || ferror(fh))
        perr_exit("fdopen");

    setbuffer(fh, NULL, 0);

    return fh;
}
#endif