/* * Copyright (C) 12 Jun 2003 Tomas Cermak * * This file is part of wmradio program. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "skin.h" #include <string.h> #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <locale.h> #include "stationnames.h" #define ACTION_COUNT 16 #ifndef SKIN_DIR #define SKIN_DIR "/usr/local/lib/wmradio/" #endif ButtonInfo buttons[ACTION_COUNT]; int button_count = 0; DigitsInfo digits; LettersInfo letters; XpmIcon RadioSkin; ButtonInfo StereoInfo; char radio_is_off = 0; int icon_width = DEFAULTICONSIZE; int icon_height = DEFAULTICONSIZE; int in_region(int x, int y, int btx,int bty,int btw,int bth) { if( (x>=btx) && (x < btx + btw) && (y>=bty) && (y<bty+bth) ) return 1; return 0; } int xor_string(char *s) { int a,r; r = 0; for(a=0; a<strlen(s); a++) { r = r << 1; if( r>0xFFFF ) r = (r & 0xFFFF) + 1; r ^= s[a]; } return r; } /* void add_action(char *name, region reg) */ /* { */ /* if( action_count < ACTION_COUNT ) { */ /* actions[action_count].action = xor_string(name); */ /* actions[action_count].r = reg; */ /* action_count++; */ /* } */ /* } */ int skin_read_num(char *p) { char *q; int res; q = strstr(p,","); if(q) { *q = '\000'; q++; } res = atoi(p); if(q) strcpy(p,q); return res; } void skin_def_line(char *line, Display *display, Drawable drawable, char *skin_desc_dir) { char *p,*w; int x,i; char buffer[256]; w = line; p = strstr(w,"="); if(!p) return; *p = '\000'; p++; x = xor_string(w); switch(x) { case 5829: /* preset1-6 */ buttons[button_count].status = BS_SELECTED; case 5830: case 5831: case 5824: case 5825: case 5826: case 1457: /* tune+ */ case 1463: /* tune- */ case 278: /* off */ case 696: /* scan */ case 4507: /* display */ buttons[button_count].action = x; buttons[button_count].destx = skin_read_num(p); buttons[button_count].desty = skin_read_num(p); buttons[button_count].srcx = skin_read_num(p); buttons[button_count].srcy = skin_read_num(p); buttons[button_count].width = skin_read_num(p); buttons[button_count].height = skin_read_num(p); button_count++; break; case 365: /* xpm */ buffer[0] = '\000'; if( ! strstr(p,"/") ) { strcpy(buffer,skin_desc_dir); } strcat(buffer,p); if(XpmReadFileToPixmap(display,drawable,buffer, &(RadioSkin.pixmap), &(RadioSkin.mask), &(RadioSkin.attributes)) != XpmSuccess) { printf("wmradio: can't load pixmap %s\n",buffer); } break; case 2071: /* digits */ digits.destx = skin_read_num(p); digits.desty = skin_read_num(p); digits.srcx = skin_read_num(p); digits.srcy = skin_read_num(p); for(i=0; i<12; i++) { digits.w[i] = skin_read_num(p); } digits.h = skin_read_num(p); break; case 4675: /* letters */ letters.destx = skin_read_num(p); letters.desty = skin_read_num(p); letters.srcx = skin_read_num(p); letters.srcy = skin_read_num(p); for(i=0; i<26; i++) { letters.w[i] = skin_read_num(p); } letters.h = skin_read_num(p); break; case 2917: /* stereo */ StereoInfo.destx = skin_read_num(p); StereoInfo.desty = skin_read_num(p); StereoInfo.srcx = skin_read_num(p); StereoInfo.srcy = skin_read_num(p); StereoInfo.width = skin_read_num(p); StereoInfo.height = skin_read_num(p); break; case 19368: /* iconwidth */ icon_width = atoi(p); case 37920: /* iconheight */ icon_height = atoi(p); } } void create_skin(char *skin_def_file, Display *display, Drawable drawable) { FILE *f; char buffer[256], *p, dir[256]; buffer[0] = '\000'; memset(&letters,0,sizeof(letters)); if(!strstr(skin_def_file,"/")) { strcpy(buffer,SKIN_DIR); } strcat(buffer,skin_def_file); strncpy(dir,buffer,sizeof(dir)); p = &dir[strlen(dir)-1]; while( *p != '/' ) p--; p[1] = '\000'; f = fopen(buffer,"r"); if(! f ){ printf("wmradio: Skin %s not found\n", skin_def_file); if( strcmp(skin_def_file,"default.skin") != 0 ) { create_skin("default.skin",display,drawable); } return; } while(!feof(f)) { fgets(buffer,sizeof(buffer),f); p = strstr(buffer,"#"); if(p) *p = '\000'; p = strstr(buffer,"\n"); if(p) *p = '\000'; while(buffer[0] == ' ') strcpy(buffer,&buffer[1]); skin_def_line(buffer,display,drawable,dir); } fclose(f); } int find_action(int x, int y) { int a; for(a=0; a< button_count; a++) { if( in_region(x,y, buttons[a].destx, buttons[a].desty, buttons[a].width, buttons[a].height ) ) return buttons[a].action; } return 0; } int skin_button_index(int x, int y) { int i; for(i=0; i< button_count; i++) { if( in_region(x,y, buttons[i].destx, buttons[i].desty, buttons[i].width, buttons[i].height) ) { return i; } } return -1; } void skin_unselect_button(void) { int a; for(a=0; a< ACTION_COUNT; a++) { if(buttons[a].status == BS_SELECTED) buttons[a].status = BS_RELEASED; } } int skin_mouse_event(int x, int y, int mousebutton, int press) { int i,r; static int last_press = -1; r=0; if(press) { last_press = skin_button_index(x,y); buttons[last_press].status = BS_PRESSED; } else { /* release */ if(last_press == skin_button_index(x,y)) { r = buttons[last_press].action; buttons[last_press].status = BS_RELEASED; if( r/100 == 58 ) { for(i = 0; i< button_count; i++) buttons[i].status = BS_RELEASED; buttons[last_press].status = BS_SELECTED; } } else { if(last_press >= 0) { buttons[last_press].status = BS_RELEASED; } last_press = -1; } } return r; } int digit_index(char digit) { int i = 10; if(isdigit(digit)) i = digit - '0'; if(digit == ' ') i = 10; if(digit == '.') i = 11; return i; } int digit_source_x(int index) { int i,x; x = digits.srcx; for(i=0; i<index; i++) { x += digits.w[i]; } return x; } int letter_index(char letter) { if(isalpha(letter) && isascii(letter)) return tolower(letter) - 'a'; return -1; } int letter_source_x(int index) { int i,x; x = letters.srcx; for(i=0; i<index; i++) { x += letters.w[i]; } return x; } int have_letters(void) { return letters.h != 0; } void char_to_window(Display *display, Window win, GC gc, char c, int *x, int y) { int idx, sourcex; if(isalpha(c)) { idx = letter_index(c); sourcex = letter_source_x(idx); XCopyArea(display,RadioSkin.pixmap,win, gc, letters.srcx + sourcex, letters.srcy, letters.w[idx], letters.h, *x, y); *x += letters.w[idx]; } else { idx = digit_index(c); sourcex = digit_source_x(idx); XCopyArea(display,RadioSkin.pixmap,win, gc, digits.srcx + sourcex, digits.srcy, digits.w[idx], digits.h, *x, y); *x += digits.w[idx]; } } void freq_to_window(Display *display, Window win, GC gc, int freq) { char freqs[10], temp[10], *stn_name; int x,i; stn_name = station_get_freq_name(freq); if(stn_name && have_letters()) { strncpy(freqs,stn_name,4); freqs[4] = 0; while(strlen(freqs)<3) strcat(freqs," "); strcat(freqs,". "); } else { snprintf(freqs,sizeof(freqs),"%i.%i",freq/100, (freq % 100) / 10); while(strlen(freqs)<5) { strcpy(temp," "); strcat(temp,freqs); strcpy(freqs,temp); } } /* freq now contain right text */ i = 0; x = digits.destx; while(freqs[i]) { char_to_window(display,win,gc,freqs[i],&x,digits.desty); i++; } } void skin_to_window(Display *display, Window win, GC gc, int freq, char stereo) { int i; int xs; char bs; setlocale(LC_ALL,"C"); XCopyArea(display,RadioSkin.pixmap,win, gc, 0, 0, skin_width(), skin_height(), 0, 0); for(i=0; i<button_count; i++) { xs = buttons[i].srcx; bs = buttons[i].status; if( radio_is_off ) bs = BS_PRESSED; switch(bs) { case BS_RELEASED: xs = buttons[i].srcx; break; case BS_PRESSED: xs = buttons[i].srcx + buttons[i].width; break; case BS_SELECTED: xs = buttons[i].srcx + buttons[i].width * 2; break; } if( buttons[i].action != 4507 ) { /* 4507 is display */ XCopyArea(display,RadioSkin.pixmap,win, gc, xs, buttons[i].srcy, buttons[i].width, buttons[i].height, buttons[i].destx, buttons[i].desty); } } /* digits */ if(!radio_is_off){ freq_to_window(display,win,gc,freq); /* stereo */ xs = StereoInfo.srcx; if(stereo) xs += StereoInfo.width; XCopyArea(display,RadioSkin.pixmap,win, gc, xs, StereoInfo.srcy, StereoInfo.width, StereoInfo.height, StereoInfo.destx, StereoInfo.desty); } } void skin_select_button(int action) { int a; for(a=0; a< ACTION_COUNT; a++) { if(buttons[a].action == action) buttons[a].status = BS_SELECTED; } } void skin_switch_radio(char status) { radio_is_off = status; } int skin_width(void) { return icon_width; } int skin_height(void) { return icon_height; } void skin_select_station(int station) { int i; for(i=0; i<ACTION_COUNT; i++) { switch(buttons[i].action) { case 5829: buttons[i].status = station == 0 ? BS_SELECTED : BS_RELEASED; break; case 5830: buttons[i].status = station == 1 ? BS_SELECTED : BS_RELEASED; break; case 5831: buttons[i].status = station == 2 ? BS_SELECTED : BS_RELEASED; break; case 5824: buttons[i].status = station == 3 ? BS_SELECTED : BS_RELEASED; break; case 5825: buttons[i].status = station == 4 ? BS_SELECTED : BS_RELEASED; break; case 5826: buttons[i].status = station == 5 ? BS_SELECTED : BS_RELEASED; break; } } }