471 lines
11 KiB
C
471 lines
11 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|
||
|
}
|
||
|
}
|