/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp> Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi> 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 xskin_i.c Oct.06.1998 Daisuke Nagano */ #include "xskin.h" #include "timidity.h" #include "common.h" #include "instrum.h" #include "playmidi.h" #include "output.h" #include "controls.h" #include "miditrace.h" extern void xskin_pipe_write(char *); extern int xskin_pipe_read(char *,int); /* text positions */ static int text_posx[] = { /* ! "" # $ % & ' ( ) * + , - . / */ 30, 17, 26, 30, 29, 26, 25, 16, 13, 14, 4, 19, 10, 15, 10, 21, /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 12, 30, 28, 30, 3, 27, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 22, 20, 23, 24, 18 }; static int text_posy[] = { 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 }; static char local_buf[300]; static int load_skins( void ); static void xskin_jobs( int ); static void repaint( void ); static void install_sighandler( void ); static void signal_vector( int ); static void delete_shm( void ); static int fshuf,frep,fequ,fpll; static int fplay,fpause; static int fremain; static int play_val, vol_val; static char last_text[1024]; static int last_current_time; static int total_time; static int shmid; static unsigned char *speana_buf; Visual *xskin_vis; unsigned int xskin_depth; Display *xskin_d; Window xskin_r,xskin_w; GC xskin_gc; Pixmap xskin_back,xskin_titlebar,xskin_playpaus,xskin_numbers,xskin_cbuttons; Pixmap xskin_monoster,xskin_posbar,xskin_shufrep,xskin_text,xskin_volume; /* text */ void ts_puttext( int x0, int y0, char *message ) { int i,l; int c; int x,px,py; if ( x0 == MESSAGE_X ) { px=text_posx[0]*TEXT_W; py=text_posy[0]*TEXT_H; for ( i=0 ; i<31 ; i++ ) { x = x0+i*TEXT_W; XCopyArea( xskin_d, xskin_text, xskin_w, xskin_gc, px, py, TEXT_W, TEXT_H, x, y0 ); } } else if ( x0 == BITRATE_X ) { XCopyArea( xskin_d, xskin_back, xskin_w, xskin_gc, 111, 43, 15, 6, 111, 43 ); } else if ( x0 == SAMPLE_X ) { XCopyArea( xskin_d, xskin_back, xskin_w, xskin_gc, 156, 43, 10, 6, 156, 43 ); } l = strlen( message ); if ( l<=0 ) return; for ( i=0 ; i<l ; i++ ) { c = (int)(message[i]); if ( (c>='a') && (c<='z') ) c = c-'a'+'A'; if ( c<' ' ) c = '.'; if ( c>'_' ) c = '.'; c-=' '; if ( c>=64 ) c=0; px = text_posx[c]*TEXT_W; py = text_posy[c]*TEXT_H; x = x0+i*TEXT_W; if (( x0 == MESSAGE_X && i<31 ) || ( x0 == BITRATE_X && i<3 ) || ( x0 == SAMPLE_X && i<2 )) { XCopyArea( xskin_d, xskin_text, xskin_w, xskin_gc, px, py, TEXT_W, TEXT_H, x, y0 ); } } XSync( xskin_d, True ); /* discards any events in the queue */ if ( x0 == MESSAGE_X ) strncpy( last_text, message, sizeof(last_text) ); return; } /* numbers */ void ts_putnum( int x, int y, int val ) { int x0,y0; if ( (val>9) || (val<0 ) ) return; x0=val*9; y0=0; XCopyArea( xskin_d, xskin_numbers, xskin_w, xskin_gc, x0, y0, NUM_W, NUM_H, x, y ); return ; } /* cbuttons */ void ts_prev( int i ) { XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc, PREV_SX(i), PREV_SY(i), PREV_W, PREV_H, PREV_DX, PREV_DY ); return; } void ts_play( int i ) { XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc, PLAY_SX(i), PLAY_SY(i), PLAY_W, PLAY_H, PLAY_DX, PLAY_DY ); return; } void ts_pause( int i ) { XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc, PAUSE_SX(i), PAUSE_SY(i), PAUSE_W, PAUSE_H, PAUSE_DX, PAUSE_DY); return; } void ts_stop ( int i ) { XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc, STOP_SX(i), STOP_SY(i), STOP_W, STOP_H, STOP_DX, STOP_DY ); return; } void ts_next( int i ) { XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc, NEXT_SX(i), NEXT_SY(i), NEXT_W, NEXT_H, NEXT_DX, NEXT_DY ); return; } void ts_eject( int i ) { XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc, EJECT_SX(i), EJECT_SY(i), EJECT_W, EJECT_H, EJECT_DX, EJECT_DY ); return; } /* titlebar */ void ts_titlebar( int i ) { XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc, TITLEBAR_SX(i), TITLEBAR_SY(i), TITLEBAR_W, TITLEBAR_H, TITLEBAR_DX, TITLEBAR_DY ); return; } void ts_exitbutton( int i ) { XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc, EXITBUTTON_SX(i), EXITBUTTON_SY(i), EXITBUTTON_W, EXITBUTTON_H, EXITBUTTON_DX, EXITBUTTON_DY ); return; } void ts_menubutton( int i ) { XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc, MENUBUTTON_SX(i), MENUBUTTON_SY(i), MENUBUTTON_W, MENUBUTTON_H, MENUBUTTON_DX, MENUBUTTON_DY ); return; } void ts_iconbutton( int i ) { XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc, ICONBUTTON_SX(i), ICONBUTTON_SY(i), ICONBUTTON_W, ICONBUTTON_H, ICONBUTTON_DX, ICONBUTTON_DY ); return; } void ts_minibutton( int i ) { XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc, MINIBUTTON_SX(i), MINIBUTTON_SY(i), MINIBUTTON_W, MINIBUTTON_H, MINIBUTTON_DX, MINIBUTTON_DY ); return; } /* monoster */ void ts_mono( int i ) { XCopyArea( xskin_d, xskin_monoster, xskin_w, xskin_gc, MONO_SX(i), MONO_SY(i), MONO_W, MONO_H, MONO_DX, MONO_DY ); return; } void ts_stereo( int i ) { XCopyArea( xskin_d, xskin_monoster, xskin_w, xskin_gc, STEREO_SX(i), STEREO_SY(i), STEREO_W, STEREO_H, STEREO_DX, STEREO_DY ); return; } /* playpaus */ void ts_pstate( int i ) { XCopyArea( xskin_d, xskin_playpaus, xskin_w, xskin_gc, PSTATE1_SX(i), PSTATE1_SY(i), PSTATE1_W, PSTATE1_H, PSTATE1_DX, PSTATE1_DY ); XCopyArea( xskin_d, xskin_playpaus, xskin_w, xskin_gc, PSTATE2_SX(i), PSTATE2_SY(i), PSTATE2_W, PSTATE2_H, PSTATE2_DX, PSTATE2_DY ); return; } /* shufrep */ void ts_shuf( int i ) { XCopyArea( xskin_d, xskin_shufrep, xskin_w, xskin_gc, SHUF_SX(i), SHUF_SY(i), SHUF_W, SHUF_H, SHUF_DX, SHUF_DY ); return; } void ts_rep( int i ) { XCopyArea( xskin_d, xskin_shufrep, xskin_w, xskin_gc, REP_SX(i), REP_SY(i), REP_W, REP_H, REP_DX, REP_DY ); return; } void ts_equ( int i ) { XCopyArea( xskin_d, xskin_shufrep, xskin_w, xskin_gc, EQU_SX(i), EQU_SY(i), EQU_W, EQU_H, EQU_DX, EQU_DY ); return; } void ts_plist( int i ) { XCopyArea( xskin_d, xskin_shufrep, xskin_w, xskin_gc, PLIST_SX(i), PLIST_SY(i), PLIST_W, PLIST_H, PLIST_DX, PLIST_DY ); return; } /* posbar */ int ts_pos( int i, int j ) { int x,y; int p; if ( j<0 ) p=-j; else { if (j<POS_MIN_DX) j=POS_MIN_DX; if (j>POS_MAX_DX) j=POS_MAX_DX; p = 100*(j-POS_MIN_DX)/(POS_MAX_DX-POS_MIN_DX); } x = POS_MIN_DX + (POS_MAX_DX-POS_MIN_DX)*p/100; y = POS_DY; XCopyArea( xskin_d, xskin_posbar, xskin_w, xskin_gc, BAR_SX, BAR_SY, BAR_W, BAR_H, BAR_DX, BAR_DY ); XCopyArea( xskin_d, xskin_posbar, xskin_w, xskin_gc, POS_SX(i), POS_SY(i), POS_W, POS_H, x, y ); return p; } int ts_volume( int i, int j ) { int x,y; int t,p; if ( j<0 ) p=-j; else { if (j<VOL_MIN_DX) j=VOL_MIN_DX; if (j>VOL_MAX_DX) j=VOL_MAX_DX; p = 100*(j-VOL_MIN_DX)/(VOL_MAX_DX-VOL_MIN_DX); } x = VOL_MIN_DX + (VOL_MAX_DX-VOL_MIN_DX)*p/100; y = VOL_DY; t=27*(int)p/100; XCopyArea( xskin_d, xskin_volume, xskin_w, xskin_gc, VOLUME_SX, t*VOLUME_H, VOLUME_W, VOLUME_H-2, VOLUME_DX, VOLUME_DY ); XCopyArea( xskin_d, xskin_volume, xskin_w, xskin_gc, VOL_SX(i), VOL_SY(i), VOL_W, VOL_H, x, y ); return p; } int ts_pan( int i, int j ) { int x,y; int t,p; if ( j<0 ) p=-j; else { if (j<PAN_MIN_DX) j=PAN_MIN_DX; if (j>PAN_MAX_DX) j=PAN_MAX_DX; p = 100*(j-PAN_MIN_DX)/(PAN_MAX_DX-PAN_MIN_DX); } x = PAN_MIN_DX + (PAN_MAX_DX-PAN_MIN_DX)*p/100; y = PAN_DY; t=27*((p>50)?((float)p-50)/50:(50-(float)p)/50); if ( t<2 ) t=0; XCopyArea( xskin_d, xskin_volume, xskin_w, xskin_gc, PANPOT_SX, t*PANPOT_H, PANPOT_W, PANPOT_H-2, PANPOT_DX, PANPOT_DY ); XCopyArea( xskin_d, xskin_volume, xskin_w, xskin_gc, PAN_SX(i), PAN_SY(i), PAN_W, PAN_H, x, y ); return p; } static void pauseOn() { if(!fpause) { fpause = 1; xskin_pipe_write("U"); } } static void pauseOff() { if(fpause) { fpause = 0; xskin_pipe_write("U"); } } /* main loop */ #define ISIN(x,y,x0,y0,w,h) ( (x>=x0)&&(x<x0+w)&&(y>=y0)&&(y<y0+h) )?1:0 void xskin_start_interface( int pipe_in ) { int xskin_sc; XEvent xskin_e; XSetWindowAttributes xskin_attr; XSizeHints xskin_hint; XClassHint xskin_chint; XTextProperty ct; char *namlist[2]; /* setup window */ xskin_d = XOpenDisplay( NULL ); xskin_sc = DefaultScreen( xskin_d ); xskin_r = RootWindow( xskin_d, xskin_sc ); xskin_gc = DefaultGC( xskin_d, xskin_sc ); xskin_vis = DefaultVisual( xskin_d, xskin_sc ); xskin_depth = DefaultDepth( xskin_d, xskin_sc ); xskin_w = XCreateSimpleWindow( xskin_d, xskin_r, 0, 0, skin_width, skin_height, 0, WhitePixel( xskin_d, xskin_sc ), BlackPixel( xskin_d, xskin_sc ) ); xskin_attr.backing_store = True; xskin_attr.override_redirect = False; XChangeWindowAttributes( xskin_d, xskin_w, CWBackingStore|CWOverrideRedirect, &xskin_attr ); XSelectInput( xskin_d, xskin_w, KeyPressMask|ExposureMask| EnterWindowMask|LeaveWindowMask| ButtonPressMask|ButtonReleaseMask| Button1MotionMask ); xskin_hint.flags = USSize | PMinSize | PMaxSize | USPosition; xskin_hint.width = xskin_hint.min_width = xskin_hint.max_width = skin_width; xskin_hint.height = xskin_hint.min_height = xskin_hint.max_height = skin_height; XSetNormalHints( xskin_d, xskin_w, &xskin_hint ); xskin_chint.res_name = XSKIN_RES_NAME; xskin_chint.res_class = XSKIN_RES_CLASS; XSetClassHint( xskin_d, xskin_w, &xskin_chint ); namlist[0]=(char *)safe_malloc(strlen(XSKIN_WINDOW_NAME)+1); strcpy( namlist[0], XSKIN_WINDOW_NAME ); XmbTextListToTextProperty( xskin_d, namlist, 1, XCompoundTextStyle, &ct ); XSetWMName( xskin_d, xskin_w, &ct ); XSetWMIconName( xskin_d, xskin_w, &ct ); free(namlist[0]); /* setup pixmaps */ if ( load_skins()!=0 ) goto finish; XSetWindowBackgroundPixmap( xskin_d, xskin_w, xskin_back ); XClearWindow( xskin_d, xskin_w ); XMapWindow( xskin_d, xskin_w ); while( 1 ) { XNextEvent( xskin_d, &xskin_e ); if ( xskin_e.type == Expose ) break; } fshuf=0; frep=0; fequ=1; fpll=1; fplay=0; fpause=0; fremain=0; play_val=1; vol_val=50; last_current_time=0; total_time=0; speana_buf = NULL; strcpy( last_text, "welcome to timidity" ); install_sighandler(); repaint(); ts_spectrum( -1, speana_buf ); XFlush(xskin_d); xskin_jobs( pipe_in ); /* tskin main jobs */ finish: signal_vector(0); /* finish */ } #define ISIN(x,y,x0,y0,w,h) ( (x>=x0)&&(x<x0+w)&&(y>=y0)&&(y<y0+h) )?1:0 static void xskin_jobs( int pipe_in ) { XEvent e; int x,y; int window_x,window_y; int fspe=0; int pr=-1; int z; int p; int master_volume=0; char file_name[1024], tmp[1024]; int last_puttext_time; int last_window_x=-1, last_window_y=-1; int max_files; int i; fd_set fds; static struct timeval tv; Window t_w; unsigned int t_width, t_height, t_border, t_depth; xskin_pipe_write( "READY" ); shmid = shmget( IPC_PRIVATE, sizeof(char)*SPE_W, IPC_CREAT|0600 ); if ( shmid<0 ) xskin_pipe_write( "ERROR" ); else { sprintf( local_buf, "%d", shmid ); xskin_pipe_write( local_buf ); speana_buf = (unsigned char *)shmat( shmid, 0, 0 ); } xskin_pipe_read( local_buf, sizeof(local_buf) ); max_files = atoi( local_buf ); for ( i=0 ; i<max_files ; i++ ) { xskin_pipe_read( local_buf, sizeof(local_buf) ); } z=1; last_puttext_time=0; last_current_time=0; XGetGeometry( xskin_d, xskin_w, &t_w, &window_x, &window_y, &t_width, &t_height, &t_border, &t_depth ); while( z ) { XFlush( xskin_d ); FD_ZERO( &fds ); FD_SET( pipe_in, &fds ); tv.tv_sec=0; tv.tv_usec=20000L; /* 20 msec */ i=select( pipe_in+1, &fds, NULL, NULL, &tv ); if ( i!=0 ) { xskin_pipe_read( local_buf, sizeof(local_buf) ); switch (local_buf[0]) { case 'A': /* total time */ total_time=atoi( local_buf+2 ); last_current_time=0; last_puttext_time=0; break; case 'T': /* current time */ { int min,sec; sscanf( local_buf+2, "%02d:%02d", &min, &sec ); i=min*60+sec; if ( fremain==1 ) { sec =total_time-i; min =sec/60; sec-=min*60; } if ( i != last_current_time ) { ts_putnum( MIN_H_X, MIN_H_Y, min/10 ); ts_putnum( MIN_L_X, MIN_L_Y, min%10 ); ts_putnum( SEC_H_X, SEC_H_Y, sec/10 ); ts_putnum( SEC_L_X, SEC_L_Y, sec%10 ); p=100*i/total_time; play_val=ts_pos( OFF, -p ); last_current_time=i; if ( last_current_time - last_puttext_time == 3 ) { /* 3 sec */ sprintf( tmp, "%s [%02d:%02d]", file_name, total_time/60, total_time%60 ); ts_puttext( MESSAGE_X, MESSAGE_Y, tmp ); } } } break; case 'L': /* lylics/message */ ts_puttext( MESSAGE_X, MESSAGE_Y, local_buf+2 ); last_puttext_time=last_current_time; break; case 'F': /* filename */ strncpy( file_name, local_buf+2, 1023 ); file_name[1023]=0; break; case 'O': /* off the play button */ fplay=0; ts_play(OFF); ts_spectrum(fspe, NULL); /* erase spectrums */ break; case 'V': /* master volume */ master_volume=atoi( local_buf+2 ); p=100*((master_volume<200)?master_volume:200)/200; /* max:200% */ vol_val=ts_volume( OFF, -p ); break; case 'Q': /* quit */ z=1; break; case 'W': /* wave form */ ts_spectrum(fspe, speana_buf); break; default: break; } } if ( XPending( xskin_d )==0 ) continue; XNextEvent( xskin_d, &e ); switch ( e.type ) { /* case KeyPress: z=0; break; */ case Expose: repaint(); break; case EnterNotify: { Cursor cs; ts_titlebar(ON); cs = XCreateFontCursor( xskin_d, XC_top_left_arrow ); XDefineCursor( xskin_d, xskin_w, cs ); } break; case LeaveNotify: ts_titlebar(OFF); XUndefineCursor( xskin_d, xskin_w ); break; case MotionNotify: while( XCheckMaskEvent( xskin_d, Button1MotionMask, &e ) ) { XNextEvent( xskin_d, &e ); } x = e.xbutton.x; y = e.xbutton.y; switch( pr ) { /* case TS_POS: play_val=ts_pos( ON, x );break; */ case TS_VOLUME: vol_val=ts_volume( ON, x ); i=master_volume; master_volume=200*vol_val/100; sprintf( local_buf, "V %d", master_volume-i ); xskin_pipe_write( local_buf ); sprintf( tmp, " volume: %d%%", vol_val ); ts_puttext( MESSAGE_X, MESSAGE_Y, tmp ); last_puttext_time=last_current_time; break; /* case TS_PAN: pan_val=ts_pan( ON, x );break; */ default: if ( x != last_window_x || y != last_window_y ) { window_x += x-last_window_x; window_y += y-last_window_y; XMoveWindow( xskin_d, xskin_w, window_x, window_y ); } break; } break; case ButtonPress: x = e.xbutton.x; y = e.xbutton.y; last_window_x=x; last_window_y=y; if ( ISIN( x, y,EXITBUTTON_DX,EXITBUTTON_DY, EXITBUTTON_W,EXITBUTTON_H ) ) { ts_exitbutton(ON);pr=TS_EXITBUTTON; } else if ( ISIN( x, y, PREV_DX, PREV_DY, PREV_W, PREV_H ) ) { ts_prev(ON);pr=TS_PREV; } else if ( ISIN( x, y, PLAY_DX, PLAY_DY, PLAY_W, PLAY_H ) ) { ts_play(ON);pr=TS_PLAY; } else if ( ISIN( x, y, PAUSE_DX, PAUSE_DY, PAUSE_W, PAUSE_H ) ) { ts_pause(ON);pr=TS_PAUSE; } else if ( ISIN( x, y, STOP_DX, STOP_DY, STOP_W, STOP_H ) ) { ts_stop(ON);pr=TS_STOP; } else if ( ISIN( x, y, NEXT_DX, NEXT_DY, NEXT_W, NEXT_H ) ) { ts_next(ON);pr=TS_NEXT; } else if ( ISIN( x, y, EJECT_DX, EJECT_DY, EJECT_W, EJECT_H ) ) { ts_eject(ON);pr=TS_EJECT; } else if ( ISIN( x, y,164, 89, 47, 15 ) ) { /* shuffle */ if ( fshuf==0 ) { ts_shuf(OFFON);pr=TS_SHUFON; } else { ts_shuf(ONOFF);pr=TS_SHUFOFF; } } else if ( ISIN( x, y,210, 89, 28, 15 ) ) { /* repeat */ if ( frep==0 ) { ts_rep(OFFON);pr=TS_REPON; } else { ts_rep(ONOFF);pr=TS_REPOFF; } } else if ( ISIN( x, y,219, 58, 23, 12 ) ) { /* equalizer */ if ( fequ==0 ) { ts_equ(OFFON);pr=TS_EQUON; } else { ts_equ(ONOFF);pr=TS_EQUOFF; } } else if ( ISIN( x, y,242, 58, 23, 12 ) ) { /* playlist */ if ( fpll==0 ) { ts_plist(OFFON);pr=TS_PLISTON; } else { ts_plist(ONOFF);pr=TS_PLISTOFF; } } else if ( ISIN( x, y, MENUBUTTON_DX, MENUBUTTON_DY, MENUBUTTON_W, MENUBUTTON_H ) ) { ts_menubutton(ON);pr=TS_MENUBUTTON; } else if ( ISIN( x, y, ICONBUTTON_DX, ICONBUTTON_DY, ICONBUTTON_W, ICONBUTTON_H ) ) { ts_iconbutton(ON);pr=TS_ICONBUTTON; } else if ( ISIN( x, y, MINIBUTTON_DX, MINIBUTTON_DY, MINIBUTTON_W, MINIBUTTON_H ) ) { ts_minibutton(ON);pr=TS_MINIBUTTON; /* } else if ( ISIN( x, y,POS_MIN_DX+(POS_MAX_DX-POS_MIN_DX)*play_val/100, POS_DY, POS_W, POS_H ) ) { ts_pos( ON, -play_val );pr=TS_POS; */ } else if ( ISIN( x, y,VOL_MIN_DX+(VOL_MAX_DX-VOL_MIN_DX)*vol_val/100, VOL_DY, VOL_W, VOL_H ) ) { ts_volume( ON, -vol_val );pr=TS_VOLUME; sprintf( tmp, " volume: %d%%", vol_val ); ts_puttext( MESSAGE_X, MESSAGE_Y, tmp ); last_puttext_time=last_current_time; /* } else if ( ISIN( x, y,PAN_MIN_DX+(PAN_MAX_DX-PAN_MIN_DX)*pan_val/100, PAN_DY, PAN_W, PAN_H ) ) { ts_pan( ON, -pan_val );pr=TS_PAN; */ } else if ( ISIN( x, y, MIN_H_X, MIN_H_Y, SEC_L_X+NUM_W-MIN_H_X, NUM_H ) ) { int min,sec; fremain=(fremain==0)?1:0; sec=(fremain==0)?last_current_time:total_time-last_current_time; min =sec/60; sec-=min*60; ts_putnum( MIN_H_X, MIN_H_Y, min/10 ); ts_putnum( MIN_L_X, MIN_L_Y, min%10 ); ts_putnum( SEC_H_X, SEC_H_Y, sec/10 ); ts_putnum( SEC_L_X, SEC_L_Y, sec%10 ); } else if ( ISIN( x, y, SPE_SX, SPE_SY, SPE_W, SPE_H ) ) { pr=TS_SPECTRUM; } else { XRaiseWindow( xskin_d, xskin_w ); } break; case ButtonRelease: last_window_x = -1; last_window_y = -1; switch( pr ) { case TS_EXITBUTTON: ts_exitbutton(OFF); xskin_pipe_write("Q"); z=0;break; case TS_PREV: ts_prev(OFF); ts_spectrum( fspe, NULL ); xskin_pipe_write("B"); break; case TS_PLAY: xskin_pipe_write("P"); fplay=1; pauseOff(); ts_play(OFF);ts_pause(OFF); ts_pstate( PSTATE_PLAY ); break; case TS_PAUSE: ts_pause(OFF); if ( fplay ==1 ) { if ( fpause==0 ) { ts_pstate( PSTATE_PAUSE ); ts_spectrum( fspe, NULL ); pauseOn(); } else { ts_pstate( PSTATE_PLAY ); pauseOff(); } } break; case TS_STOP: pauseOff(); fplay=0; ts_pause(OFF);ts_play(OFF);ts_stop(OFF); ts_pstate( PSTATE_STOP ); ts_spectrum( fspe, NULL ); xskin_pipe_write("S"); break; case TS_NEXT: ts_next(OFF); ts_spectrum( fspe, NULL ); xskin_pipe_write("N"); break; case TS_EJECT: ts_eject(OFF);break; case TS_SHUFON: ts_shuf(ON);fshuf=1; fplay=1; pauseOff(); ts_pstate( PSTATE_PLAY ); xskin_pipe_write("D 1"); break; case TS_SHUFOFF: ts_shuf(OFF);fshuf=0; fplay=0; pauseOff(); ts_pstate( PSTATE_STOP ); ts_spectrum( fspe, NULL ); xskin_pipe_write("D 2"); break; case TS_REPON: ts_rep(ON);frep=1; xskin_pipe_write("R 1"); break; case TS_REPOFF: ts_rep(OFF);frep=0; xskin_pipe_write("R 0"); break; case TS_EQUON: ts_equ(ON);fequ=1;break; case TS_EQUOFF: ts_equ(OFF);fequ=0;break; case TS_PLISTON: ts_plist(ON);fpll=1;break; case TS_PLISTOFF: ts_plist(OFF);fpll=0;break; case TS_MENUBUTTON: ts_menubutton(OFF);break; case TS_ICONBUTTON: ts_iconbutton(OFF);break; case TS_MINIBUTTON: ts_minibutton(OFF);break; /* case TS_POS: ts_pos( OFF, -play_val );break; */ case TS_VOLUME: ts_volume( OFF, -vol_val );break; /* case TS_PAN: ts_pan( OFF, -pan_val );break; */ case TS_SPECTRUM: #ifdef SUPPORT_SOUNDSPEC fspe = (fspe+1)%3; if ( fspe==1 ) xskin_pipe_write("W"); /* on */ else if ( fspe==0 ) { xskin_pipe_write("W"); /* off */ ts_spectrum(0,speana_buf); } #endif /* SUPPORT_SOUNDSPEC */ break; default: break; } pr=-1; break; default: break; } } return; } static int load_skins( void ) { char **files; char *tmp[2]; int nfiles; int i,pixmaps; char *p,*p0; char *skin_name; int width, height; skin_name = getenv( "TIMIDITY_SKIN" ); if ( skin_name == NULL ) { skin_name = getenv( "timidity_skin" ); if ( skin_name == NULL ) { #ifdef DEFAULT_SKIN skin_name = DEFAULT_SKIN; #else fprintf(stderr, "Undefined environment `timidity_skin'\n"); return -1; #endif } } tmp[0]=skin_name; files=tmp; nfiles=1; files = expand_file_archives( files, &nfiles ); pixmaps=0; xskin_loadviscolor( xskin_d, xskin_w, NULL ); for ( i=0 ; i<nfiles ; i++ ) { /*printf("%s\n",files[i]);fflush(stdout);*/ p0=strrchr( files[i], '#' ); if ( p0==NULL ) p0=files[i]; else p0++; p=strrchr( p0, PATH_SEP ); if ( p==NULL ) p=p0; else p++; if ( strcasecmp( p, "viscolor.txt" )==0 ) { xskin_loadviscolor( xskin_d, xskin_w, files[i] ); } else if ( strcasecmp( p, "main.bmp" )==0 ) { xskin_back = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "titlebar.bmp" )==0 ) { xskin_titlebar = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "playpaus.bmp" )==0 ) { xskin_playpaus = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "cbuttons.bmp" )==0 ) { xskin_cbuttons = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "monoster.bmp" )==0 ) { xskin_monoster = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "posbar.bmp" )==0 ) { xskin_posbar = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "shufrep.bmp" )==0 ) { xskin_shufrep = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "text.bmp" )==0 ) { xskin_text = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "volume.bmp" )==0 ) { xskin_volume = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else if ( strcasecmp( p, "numbers.bmp" )==0 ) { xskin_numbers = xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height ); pixmaps++; } else { width=1; } if ( width<0 ) return -1; } if(files != tmp) free(files); if ( pixmaps<10 ) { fprintf(stderr, "some of bmp file might be missed.\n"); return -1; } return 0; } static void repaint( void ) { char tmp[64]; int min,sec; /* static values */ XClearWindow( xskin_d, xskin_w ); ts_titlebar(OFF); ts_prev(OFF); ts_play(OFF); ts_pause(OFF); ts_stop(OFF); ts_next(OFF); ts_eject(OFF); if ( (play_mode->encoding & PE_MONO)==0 ) { ts_mono(OFF); ts_stereo(ON); } else { ts_mono(ON); ts_stereo(OFF); } ts_pan(OFF,-50); ts_puttext( BITRATE_X, BITRATE_Y, "---" ); /* bit-rate */ sprintf( tmp, "%d", (int)play_mode->rate/1000 ); ts_puttext( SAMPLE_X, SAMPLE_Y, tmp ); /* sample-rate */ /* volatile values */ if ( fshuf==0 ) ts_shuf(OFF); else ts_shuf(ON); if ( frep==0 ) ts_rep(OFF); else ts_rep(ON); if ( fequ==0 ) ts_equ(OFF); else ts_equ(ON); if ( fpll==0 ) ts_plist(OFF); else ts_plist(ON); if ( fplay==1 ) { if ( fpause==0 ) ts_pstate( PSTATE_PLAY ); else ts_pstate( PSTATE_PAUSE ); } else ts_pstate( PSTATE_STOP ); ts_volume( OFF, -vol_val ); ts_pos( OFF, -play_val ); ts_puttext( MESSAGE_X, MESSAGE_Y, last_text ); if ( fremain==0 ) { sec=last_current_time; } else { sec=total_time-last_current_time; } min =sec/60; sec-=min*60; ts_putnum( MIN_H_X, MIN_H_Y, min/10 ); ts_putnum( MIN_L_X, MIN_L_Y, min%10 ); ts_putnum( SEC_H_X, SEC_H_Y, sec/10 ); ts_putnum( SEC_L_X, SEC_L_Y, sec%10 ); XFlush(xskin_d); return; } /* signal handler calls are ported from xmasl and thanks to takawata@shidahara1.planet.kobe-u.ac.jp */ void delete_shm( void ) { if ( speana_buf != NULL ) { shmdt( (char *)speana_buf ); shmctl( shmid, IPC_RMID, 0 ); } return; } static const int signals[]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGABRT,SIGFPE, SIGBUS,SIGSEGV,SIGPIPE,SIGALRM,SIGTERM,0}; void install_sighandler( void ) { int i; for ( i=0 ; signals[i]!=0 ; i++ ) { signal( signals[i], signal_vector ); } } void signal_vector( int sig ) { delete_shm(); XUnmapWindow( xskin_d, xskin_w ); XFlush(xskin_d); XDestroyWindow( xskin_d, xskin_w ); XCloseDisplay( xskin_d ); exit (0); }