o_textgraph.cpp 3 KB
#include "blc_core.h"
#include "blc_channel.h"
#include "blc_program.h"
#include <unistd.h>
#include <termios.h>
#include <libgen.h> //basename
#include <pthread.h>

static int width_max, height_max;
static int current_pos=0, size_change=0;
static blc_channel channel;
static blc_mem history;
static int  period, drawn=0;

static pthread_mutex_t resize_mutex;

void resize_cb(int width, int height, void*){
    width_max=width;
    height_max=height;
    size_change=1;
}

int fprint_spikes_uchars(blc_mem *history, FILE *file, const char *title){
    char c;
    int i, j;
    
    int last_col=current_pos;
    
    fprintf(file, "[%s]\n", title);
    FOR(j, 8){
        FOR(i, last_col){
            c=((1<<j) & history->uchars[i])? '.': ' ';
            fputc(c, file);
        }
        eprintf_escape_command("K");
        fprintf( file, "\n");
    }
    return 9;
}


void *record_thread(void*){
    while(1){
        if (size_change){ //Terminal resizing
            pthread_mutex_lock(&resize_mutex);
            history.reallocate(width_max);
            if (current_pos >= history.size) current_pos=current_pos%history.size;
            size_change=0;
            pthread_mutex_unlock(&resize_mutex);
            
        }
        history.uchars[current_pos]=channel.uchars[0];
        current_pos++;
        usleep(period/history.size);
        if (current_pos==history.size || drawn) {
            if (drawn==0) fprintf(stderr, "You do not draw fast enough\n");
            else drawn=0;
            
            current_pos=0;
        }
    }
    return NULL;
}

int main(int argc, char** argv){
    
    char const  *period_str;
    char const *channel_name, *filename, *time_str;
    char const *number_str;
    char const *ext;
    FILE *file;
    int height=0;
    int width;
    int number;
    struct timeval timer;
    pthread_t thread;
    
    blc_program_set_description("Display a text graph of blc_channel in the terminal");
    blc_program_add_option(&period_str, 'p', "period", "integer", "Period in ms to refresh the graph", "100");
    blc_program_add_parameter(&channel_name, "blc_channel-in", 1, "channel to graph", NULL);
    blc_program_init(&argc, &argv, blc_quit);
    blc_command_forward_blc_channels();
    
    period=strtol(period_str, NULL,10)*1000;
    
    channel.open(channel_name, BLC_CHANNEL_READ);
    blc_loop_try_add_waiting_semaphore(channel.sem_new_data);
    blc_loop_try_add_posting_semaphore(channel.sem_ack_data);
    
    blc_terminal_get_size(&width_max, &height_max);
    blc_terminal_set_resize_callback(resize_cb, NULL);
    
    history.allocate(width_max);
    BLC_PTHREAD_CHECK(pthread_mutex_init(&resize_mutex, NULL), "");
    BLC_PTHREAD_CHECK(pthread_create(&thread, NULL, record_thread, NULL), "Creating thread");
    
    BLC_COMMAND_LOOP(period){
        if (height) blc_eprint_cursor_up(height);
        pthread_mutex_lock(&resize_mutex);
        height=fprint_spikes_uchars(&history, stderr, channel_name);
        pthread_mutex_unlock(&resize_mutex);
        drawn=1;
    }
    return EXIT_SUCCESS;
}