Skip to content
Snippets Groups Projects
Select Git revision
  • b7eca513d6ac7cbadfa08abe61cb6305d90810b5
  • jk default protected
2 results

osdd-to-string.c

Blame
  • 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;
    }