Select Git revision
osdd-to-string.c
-
Jiří Kalvoda authoredJiří Kalvoda authored
osdd-to-string.c 7.59 KiB
/*
* On-screen Display
*
* (c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
*/
#include "osdd-to-string.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <getopt.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/extensions/shape.h>
#include <X11/extensions/render.h>
#include <X11/Xft/Xft.h>
char * expand_backslash(char * in)
{
char * out = xmalloc(strlen(in)+1);
int i=0;
for(;*in;i++,in++)
{
if(in[0]=='\\')
{
switch(in[1])
{
case 'n':
out[i]='\n';
break;
case 't':
out[i]='\t';
break;
case '0':
out[i]='\0';
break;
default:
out[i]='?';
break;
}
if(in[1]) in++;
}
else
out[i]=*in;
}
out[i]=0;
return out;
}
static void replace_no_text(char * in)
{
for(;*in;in++)
{
if(' '== *in) continue;
if('a'<= *in&& *in<='z') continue;
if('A'<= *in&& *in<='Z') continue;
if('0'<= *in&& *in<='9') continue;
//if(128 <= (unsigned char)*in) continue;
*in='?';
}
}
static void
colorToRGB(char * name, int *r, int *g, int *b)
{
Display *d = XOpenDisplay(NULL);
int s = XDefaultScreen(d);
Visual *v = XDefaultVisual(d,s);
Colormap cmap = DefaultColormap(d,s);
XftColor color;
if (XftColorAllocName(d, v, cmap, name, &color))
{
typeof(color.color) c = color.color;
*r = c.red;
*g = c.green;
*b = c.blue;
}
else *r=*g=*b=-1;
XftColorFree(d, v, cmap, &color);
XCloseDisplay(d);
}
bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg)
{
if(osd_to_strings_vector_parse_arg(state, arg)) return 1;
switch(arg)
{
case 'l':
free(state->line_separator);
state->line_separator = expand_backslash(optarg);
break;
case 'm':
free(state->msq_separator);
state->msq_separator = expand_backslash(optarg);
break;
case 'T':
free(state->time_separator);
state->time_separator = expand_backslash(optarg);
break;
default:
return 0;
}
return 1;
}
bool osd_to_strings_vector_parse_arg(struct osd_to_string_state *state, char arg)
{
switch(arg)
{
case 'c':
if(!strcmp(optarg,"no")) state->color_mode = FILE_COLOR_NO; else
if(!strcmp(optarg,"rgbDEC")) state->color_mode = FILE_COLOR_RGB_DEC; else
if(!strcmp(optarg,"rgbHEX")) state->color_mode = FILE_COLOR_RGB_HEX; else
if(!strcmp(optarg,"rgbHEXHASHTAG")) state->color_mode = FILE_COLOR_RGB_HASHTAG_HEX; else
if(!strcmp(optarg,"term")) state->color_mode = FILE_COLOR_TERM_RGB; else
if(!strcmp(optarg,"original")) state->color_mode = FILE_COLOR_ORIGINAL; else
{
fprintf(stderr,"Color mode %s not exist\n\n",optarg);
exit(0);
}
break;
case 'r':
state->replace_no_text = 1;
break;
case 't':
if(!strcmp(optarg,"no")) state->time_mode = FILE_TIME_NO; else
if(!strcmp(optarg,"unix")) state->time_mode = FILE_TIME_UNIX; else
if(!strcmp(optarg,"iso")) state->time_mode = FILE_TIME_ISO; else
{
fprintf(stderr,"Time mode %s not exist\n\n",optarg);
exit(0);
}
break;
case 'e':
if(state->end_of_mes_by) free(state->end_of_mes_by);
state->end_of_mes_by = expand_backslash(optarg);
break;
case 'E':
state->end_of_mes_time = 1;
break;
case 'a':
state->on_arrive = 1;
break;
case 'N':
state->no_msg_body = 1;
break;
case 'A':
state->on_arrive = 1;
state->do_not_insert_msg_to_que = 1;
break;
default:
return 0;
}
return 1;
}
static
VECTOR(char) osd_to_string_time(struct osd_to_string_state *state)
{
VECTOR(char) out=0;
switch(state->time_mode)
{
case FILE_TIME_NO:
break;
case FILE_TIME_UNIX:
vprint(&out,"%lld",(long long)time(0));
break;
case FILE_TIME_ISO:
{
time_t t = time(NULL);
struct tm tm = *localtime(&t);
vprint(&out,"%04d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
}
break;
}
return out;
}
VECTOR(VECTOR(char)) osd_to_strings_vector(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
{
VECTOR(VECTOR(char)) out = NULL;
VECTOR(char) t = osd_to_string_time(state);
if(t) VPB(out,t);
for(int i=0;i<num_lines;i++)
{
struct osd_line * line = lines+i;
//if(!(line->log & 1)) continue;
if(line->type!=OSD_TYPE_TEXT) continue;
int r,g,b;
VECTOR(char) text=0;
VRESERVE(text,strlen(line->u.text)+1);
char color[30];
color[0]=0;
char * end_color = "";
vprint(&text,"%s",line->u.text);
if(state->replace_no_text) replace_no_text(text);
switch(state->color_mode)
{
case FILE_COLOR_RGB_DEC:
case FILE_COLOR_RGB_HEX:
case FILE_COLOR_RGB_HASHTAG_HEX:
case FILE_COLOR_TERM_RGB:
colorToRGB(line->fg_color,&r,&g,&b);
break;
default:
break;
}
switch(state->color_mode)
{
case FILE_COLOR_RGB_DEC:
sprintf(color,"%d %d %d ",r/256,g/256,b/256);
break;
case FILE_COLOR_RGB_HEX:
sprintf(color,"%02x%02x%02x ",r/256,g/256,b/256);
break;
case FILE_COLOR_RGB_HASHTAG_HEX:
sprintf(color,"#%02x%02x%02x ",r/256,g/256,b/256);
break;
case FILE_COLOR_TERM_RGB:
sprintf(color,"\e[38;2;%d;%d;%dm",r/256,g/256,b/256);
end_color = "\e[0m";
break;
case FILE_COLOR_ORIGINAL:
sprintf(color,"%s ",line->fg_color);
break;
case FILE_COLOR_NO:
break;
}
VECTOR(char) l=0;
vprint(&l,"%s%s%s", color, state->no_msg_body?"":text, end_color);
VPB(out,l);
VFREE(text);
}
return out;
}
VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
{
VECTOR(char) out = NULL;
VRESERVE(out,256);
VECTOR(VECTOR(char)) in = osd_to_strings_vector(state, lines, num_lines);
for(int i=0; i<VSIZE(in); i++)
{
if(i==0 && state->time_mode != FILE_TIME_NO)
vprint(&out,"%s%s",in[i],state->time_separator);
else
vprint(&out,"%s%s",in[i],state->line_separator);
}
vprint(&out,"%s",state->msq_separator);
for(int i=0; i<VSIZE(in); i++)
VFREE(in[i]);
VFREE(in);
return out;
}
VECTOR(char) osd_to_string_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
{
if(!state->on_arrive) return 0;
return osd_to_string(state, lines, num_lines);
}
VECTOR(char) osd_to_string_show_msg(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
{
if(state->on_arrive) return 0;
return osd_to_string(state, lines, num_lines);
}
VECTOR(char) osd_to_string_clear_msg(struct osd_to_string_state *state)
{
if(state->on_arrive) return 0;
if(!state->end_of_mes_by) return 0;
VECTOR(char) out=0;
if(state->end_of_mes_time)
{
VECTOR(char) t = osd_to_string_time(state);
vprint(&out,"%s",t);
VFREE(t);
}
vprint(&out,"%s",state->end_of_mes_by);
return out;
}
VECTOR(VECTOR(char)) osd_to_strings_vector_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
{
if(!state->on_arrive) return 0;
return osd_to_strings_vector(state, lines, num_lines);
}
VECTOR(VECTOR(char)) osd_to_strings_vector_show_msg(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
{
if(state->on_arrive) return 0;
return osd_to_strings_vector(state, lines, num_lines);
}
VECTOR(VECTOR(char)) osd_to_strings_vector_clear_msg(struct osd_to_string_state *state)
{
if(state->on_arrive) return 0;
if(!state->end_of_mes_by) return 0;
VECTOR(VECTOR(char)) out=0;
if(state->end_of_mes_time)
{
VECTOR(char) t = osd_to_string_time(state);
VPB(out,t);
}
VADDSIZE(out,1);
vprint(&VLAST(out),"%s",state->end_of_mes_by);
return out;
}
void osd_to_string_state_init(struct osd_to_string_state * state)
{
state->line_separator = expand_backslash("\\n");
state->time_separator = expand_backslash("\\n");
state->msq_separator = expand_backslash("");
state->end_of_mes_by = 0;
}