1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 xskin_i.c
21
22 Oct.06.1998 Daisuke Nagano
23 */
24
25 #include "xskin.h"
26
27 #include "timidity.h"
28 #include "common.h"
29 #include "instrum.h"
30 #include "playmidi.h"
31 #include "output.h"
32 #include "controls.h"
33 #include "miditrace.h"
34
35 extern void xskin_pipe_write(char *);
36 extern int xskin_pipe_read(char *,int);
37
38 /* text positions */
39
40 static int text_posx[] = {
41 /* ! "" # $ % & ' ( ) * + , - . / */
42 30, 17, 26, 30, 29, 26, 25, 16, 13, 14, 4, 19, 10, 15, 10, 21,
43 /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
44 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 12, 30, 28, 30, 3,
45 27, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
46 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 22, 20, 23, 24, 18
47 };
48 static int text_posy[] = {
49 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1,
50 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 2,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1
53 };
54
55 static char local_buf[300];
56
57 static int load_skins( void );
58 static void xskin_jobs( int );
59 static void repaint( void );
60
61 static void install_sighandler( void );
62 static void signal_vector( int );
63 static void delete_shm( void );
64
65 static int fshuf,frep,fequ,fpll;
66 static int fplay,fpause;
67 static int fremain;
68 static int play_val, vol_val;
69 static char last_text[1024];
70 static int last_current_time;
71 static int total_time;
72
73 static int shmid;
74 static unsigned char *speana_buf;
75
76 Visual *xskin_vis;
77 unsigned int xskin_depth;
78
79 Display *xskin_d;
80 Window xskin_r,xskin_w;
81 GC xskin_gc;
82
83 Pixmap xskin_back,xskin_titlebar,xskin_playpaus,xskin_numbers,xskin_cbuttons;
84 Pixmap xskin_monoster,xskin_posbar,xskin_shufrep,xskin_text,xskin_volume;
85
86 /* text */
87
ts_puttext(int x0,int y0,char * message)88 void ts_puttext( int x0, int y0, char *message ) {
89 int i,l;
90 int c;
91 int x,px,py;
92
93 if ( x0 == MESSAGE_X ) {
94 px=text_posx[0]*TEXT_W;
95 py=text_posy[0]*TEXT_H;
96 for ( i=0 ; i<31 ; i++ ) {
97 x = x0+i*TEXT_W;
98 XCopyArea( xskin_d, xskin_text, xskin_w, xskin_gc,
99 px, py, TEXT_W, TEXT_H, x, y0 );
100 }
101 } else if ( x0 == BITRATE_X ) {
102 XCopyArea( xskin_d, xskin_back, xskin_w, xskin_gc,
103 111, 43, 15, 6, 111, 43 );
104 } else if ( x0 == SAMPLE_X ) {
105 XCopyArea( xskin_d, xskin_back, xskin_w, xskin_gc,
106 156, 43, 10, 6, 156, 43 );
107 }
108
109 l = strlen( message );
110 if ( l<=0 ) return;
111 for ( i=0 ; i<l ; i++ ) {
112 c = (int)(message[i]);
113 if ( (c>='a') && (c<='z') ) c = c-'a'+'A';
114 if ( c<' ' ) c = '.';
115 if ( c>'_' ) c = '.';
116
117 c-=' ';
118 if ( c>=64 ) c=0;
119 px = text_posx[c]*TEXT_W;
120 py = text_posy[c]*TEXT_H;
121 x = x0+i*TEXT_W;
122 if (( x0 == MESSAGE_X && i<31 ) ||
123 ( x0 == BITRATE_X && i<3 ) ||
124 ( x0 == SAMPLE_X && i<2 )) {
125 XCopyArea( xskin_d, xskin_text, xskin_w, xskin_gc,
126 px, py, TEXT_W, TEXT_H, x, y0 );
127 }
128 }
129 XSync( xskin_d, True ); /* discards any events in the queue */
130
131 if ( x0 == MESSAGE_X )
132 strncpy( last_text, message, sizeof(last_text) );
133
134 return;
135 }
136
137 /* numbers */
138
ts_putnum(int x,int y,int val)139 void ts_putnum( int x, int y, int val ) {
140
141 int x0,y0;
142
143 if ( (val>9) || (val<0 ) ) return;
144 x0=val*9;
145 y0=0;
146
147 XCopyArea( xskin_d, xskin_numbers, xskin_w, xskin_gc,
148 x0, y0, NUM_W, NUM_H, x, y );
149
150 return ;
151 }
152
153 /* cbuttons */
154
ts_prev(int i)155 void ts_prev( int i ) {
156
157 XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc,
158 PREV_SX(i), PREV_SY(i), PREV_W, PREV_H, PREV_DX, PREV_DY );
159
160 return;
161 }
162
ts_play(int i)163 void ts_play( int i ) {
164
165 XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc,
166 PLAY_SX(i), PLAY_SY(i), PLAY_W, PLAY_H, PLAY_DX, PLAY_DY );
167
168 return;
169 }
170
ts_pause(int i)171 void ts_pause( int i ) {
172
173 XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc,
174 PAUSE_SX(i), PAUSE_SY(i), PAUSE_W, PAUSE_H, PAUSE_DX, PAUSE_DY);
175
176 return;
177 }
178
ts_stop(int i)179 void ts_stop ( int i ) {
180
181 XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc,
182 STOP_SX(i), STOP_SY(i), STOP_W, STOP_H, STOP_DX, STOP_DY );
183
184 return;
185 }
186
ts_next(int i)187 void ts_next( int i ) {
188
189 XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc,
190 NEXT_SX(i), NEXT_SY(i), NEXT_W, NEXT_H, NEXT_DX, NEXT_DY );
191
192 return;
193 }
194
ts_eject(int i)195 void ts_eject( int i ) {
196
197 XCopyArea( xskin_d, xskin_cbuttons, xskin_w, xskin_gc,
198 EJECT_SX(i), EJECT_SY(i), EJECT_W, EJECT_H, EJECT_DX, EJECT_DY );
199 return;
200 }
201
202 /* titlebar */
203
ts_titlebar(int i)204 void ts_titlebar( int i ) {
205
206 XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc,
207 TITLEBAR_SX(i), TITLEBAR_SY(i),
208 TITLEBAR_W, TITLEBAR_H, TITLEBAR_DX, TITLEBAR_DY );
209 return;
210 }
211
ts_exitbutton(int i)212 void ts_exitbutton( int i ) {
213
214 XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc,
215 EXITBUTTON_SX(i), EXITBUTTON_SY(i),
216 EXITBUTTON_W, EXITBUTTON_H, EXITBUTTON_DX, EXITBUTTON_DY );
217
218 return;
219 }
220
ts_menubutton(int i)221 void ts_menubutton( int i ) {
222
223 XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc,
224 MENUBUTTON_SX(i), MENUBUTTON_SY(i),
225 MENUBUTTON_W, MENUBUTTON_H, MENUBUTTON_DX, MENUBUTTON_DY );
226 return;
227 }
228
ts_iconbutton(int i)229 void ts_iconbutton( int i ) {
230
231 XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc,
232 ICONBUTTON_SX(i), ICONBUTTON_SY(i),
233 ICONBUTTON_W, ICONBUTTON_H, ICONBUTTON_DX, ICONBUTTON_DY );
234 return;
235 }
236
ts_minibutton(int i)237 void ts_minibutton( int i ) {
238
239 XCopyArea( xskin_d, xskin_titlebar, xskin_w, xskin_gc,
240 MINIBUTTON_SX(i), MINIBUTTON_SY(i),
241 MINIBUTTON_W, MINIBUTTON_H, MINIBUTTON_DX, MINIBUTTON_DY );
242 return;
243 }
244
245 /* monoster */
246
ts_mono(int i)247 void ts_mono( int i ) {
248
249 XCopyArea( xskin_d, xskin_monoster, xskin_w, xskin_gc,
250 MONO_SX(i), MONO_SY(i),
251 MONO_W, MONO_H, MONO_DX, MONO_DY );
252 return;
253 }
254
ts_stereo(int i)255 void ts_stereo( int i ) {
256
257 XCopyArea( xskin_d, xskin_monoster, xskin_w, xskin_gc,
258 STEREO_SX(i), STEREO_SY(i),
259 STEREO_W, STEREO_H, STEREO_DX, STEREO_DY );
260 return;
261 }
262
263 /* playpaus */
264
ts_pstate(int i)265 void ts_pstate( int i ) {
266
267 XCopyArea( xskin_d, xskin_playpaus, xskin_w, xskin_gc,
268 PSTATE1_SX(i), PSTATE1_SY(i),
269 PSTATE1_W, PSTATE1_H, PSTATE1_DX, PSTATE1_DY );
270 XCopyArea( xskin_d, xskin_playpaus, xskin_w, xskin_gc,
271 PSTATE2_SX(i), PSTATE2_SY(i),
272 PSTATE2_W, PSTATE2_H, PSTATE2_DX, PSTATE2_DY );
273 return;
274 }
275
276 /* shufrep */
277
ts_shuf(int i)278 void ts_shuf( int i ) {
279
280 XCopyArea( xskin_d, xskin_shufrep, xskin_w, xskin_gc,
281 SHUF_SX(i), SHUF_SY(i),
282 SHUF_W, SHUF_H, SHUF_DX, SHUF_DY );
283
284 return;
285 }
286
ts_rep(int i)287 void ts_rep( int i ) {
288
289 XCopyArea( xskin_d, xskin_shufrep, xskin_w, xskin_gc,
290 REP_SX(i), REP_SY(i),
291 REP_W, REP_H, REP_DX, REP_DY );
292
293 return;
294 }
295
ts_equ(int i)296 void ts_equ( int i ) {
297
298 XCopyArea( xskin_d, xskin_shufrep, xskin_w, xskin_gc,
299 EQU_SX(i), EQU_SY(i),
300 EQU_W, EQU_H, EQU_DX, EQU_DY );
301 return;
302 }
303
ts_plist(int i)304 void ts_plist( int i ) {
305
306 XCopyArea( xskin_d, xskin_shufrep, xskin_w, xskin_gc,
307 PLIST_SX(i), PLIST_SY(i),
308 PLIST_W, PLIST_H, PLIST_DX, PLIST_DY );
309 return;
310 }
311
312 /* posbar */
313
ts_pos(int i,int j)314 int ts_pos( int i, int j ) {
315
316 int x,y;
317 int p;
318
319 if ( j<0 ) p=-j;
320 else {
321 if (j<POS_MIN_DX) j=POS_MIN_DX;
322 if (j>POS_MAX_DX) j=POS_MAX_DX;
323 p = 100*(j-POS_MIN_DX)/(POS_MAX_DX-POS_MIN_DX);
324 }
325
326 x = POS_MIN_DX + (POS_MAX_DX-POS_MIN_DX)*p/100;
327 y = POS_DY;
328
329 XCopyArea( xskin_d, xskin_posbar, xskin_w, xskin_gc,
330 BAR_SX, BAR_SY, BAR_W, BAR_H, BAR_DX, BAR_DY );
331 XCopyArea( xskin_d, xskin_posbar, xskin_w, xskin_gc,
332 POS_SX(i), POS_SY(i), POS_W, POS_H, x, y );
333 return p;
334 }
335
ts_volume(int i,int j)336 int ts_volume( int i, int j ) {
337
338 int x,y;
339 int t,p;
340
341 if ( j<0 ) p=-j;
342 else {
343 if (j<VOL_MIN_DX) j=VOL_MIN_DX;
344 if (j>VOL_MAX_DX) j=VOL_MAX_DX;
345 p = 100*(j-VOL_MIN_DX)/(VOL_MAX_DX-VOL_MIN_DX);
346 }
347
348 x = VOL_MIN_DX + (VOL_MAX_DX-VOL_MIN_DX)*p/100;
349 y = VOL_DY;
350 t=27*(int)p/100;
351 XCopyArea( xskin_d, xskin_volume, xskin_w, xskin_gc,
352 VOLUME_SX, t*VOLUME_H,
353 VOLUME_W, VOLUME_H-2, VOLUME_DX, VOLUME_DY );
354 XCopyArea( xskin_d, xskin_volume, xskin_w, xskin_gc,
355 VOL_SX(i), VOL_SY(i), VOL_W, VOL_H, x, y );
356 return p;
357 }
358
ts_pan(int i,int j)359 int ts_pan( int i, int j ) {
360
361 int x,y;
362 int t,p;
363
364 if ( j<0 ) p=-j;
365 else {
366 if (j<PAN_MIN_DX) j=PAN_MIN_DX;
367 if (j>PAN_MAX_DX) j=PAN_MAX_DX;
368 p = 100*(j-PAN_MIN_DX)/(PAN_MAX_DX-PAN_MIN_DX);
369 }
370
371 x = PAN_MIN_DX + (PAN_MAX_DX-PAN_MIN_DX)*p/100;
372 y = PAN_DY;
373 t=27*((p>50)?((float)p-50)/50:(50-(float)p)/50);
374 if ( t<2 ) t=0;
375 XCopyArea( xskin_d, xskin_volume, xskin_w, xskin_gc,
376 PANPOT_SX, t*PANPOT_H,
377 PANPOT_W, PANPOT_H-2, PANPOT_DX, PANPOT_DY );
378 XCopyArea( xskin_d, xskin_volume, xskin_w, xskin_gc,
379 PAN_SX(i), PAN_SY(i),
380 PAN_W, PAN_H, x, y );
381 return p;
382 }
383
pauseOn()384 static void pauseOn()
385 {
386 if(!fpause) {
387 fpause = 1;
388 xskin_pipe_write("U");
389 }
390 }
391
pauseOff()392 static void pauseOff()
393 {
394 if(fpause) {
395 fpause = 0;
396 xskin_pipe_write("U");
397 }
398 }
399
400 /* main loop */
401
402 #define ISIN(x,y,x0,y0,w,h) ( (x>=x0)&&(x<x0+w)&&(y>=y0)&&(y<y0+h) )?1:0
403
xskin_start_interface(int pipe_in)404 void xskin_start_interface( int pipe_in ) {
405
406 int xskin_sc;
407 XEvent xskin_e;
408 XSetWindowAttributes xskin_attr;
409
410 XSizeHints xskin_hint;
411 XClassHint xskin_chint;
412 XTextProperty ct;
413 char *namlist[2];
414
415
416 /* setup window */
417
418 xskin_d = XOpenDisplay( NULL );
419 xskin_sc = DefaultScreen( xskin_d );
420 xskin_r = RootWindow( xskin_d, xskin_sc );
421 xskin_gc = DefaultGC( xskin_d, xskin_sc );
422 xskin_vis = DefaultVisual( xskin_d, xskin_sc );
423 xskin_depth = DefaultDepth( xskin_d, xskin_sc );
424
425 xskin_w = XCreateSimpleWindow( xskin_d, xskin_r, 0, 0,
426 skin_width, skin_height, 0,
427 WhitePixel( xskin_d, xskin_sc ),
428 BlackPixel( xskin_d, xskin_sc ) );
429
430 xskin_attr.backing_store = True;
431 xskin_attr.override_redirect = False;
432 XChangeWindowAttributes( xskin_d, xskin_w,
433 CWBackingStore|CWOverrideRedirect, &xskin_attr );
434
435 XSelectInput( xskin_d, xskin_w,
436 KeyPressMask|ExposureMask|
437 EnterWindowMask|LeaveWindowMask|
438 ButtonPressMask|ButtonReleaseMask|
439 Button1MotionMask );
440
441 xskin_hint.flags = USSize | PMinSize | PMaxSize | USPosition;
442 xskin_hint.width = xskin_hint.min_width = xskin_hint.max_width
443 = skin_width;
444 xskin_hint.height = xskin_hint.min_height = xskin_hint.max_height
445 = skin_height;
446 XSetNormalHints( xskin_d, xskin_w, &xskin_hint );
447
448 xskin_chint.res_name = XSKIN_RES_NAME;
449 xskin_chint.res_class = XSKIN_RES_CLASS;
450 XSetClassHint( xskin_d, xskin_w, &xskin_chint );
451
452 namlist[0]=(char *)safe_malloc(strlen(XSKIN_WINDOW_NAME)+1);
453 strcpy( namlist[0], XSKIN_WINDOW_NAME );
454 XmbTextListToTextProperty( xskin_d, namlist, 1, XCompoundTextStyle, &ct );
455 XSetWMName( xskin_d, xskin_w, &ct );
456 XSetWMIconName( xskin_d, xskin_w, &ct );
457 free(namlist[0]);
458
459
460 /* setup pixmaps */
461
462 if ( load_skins()!=0 ) goto finish;
463
464 XSetWindowBackgroundPixmap( xskin_d, xskin_w, xskin_back );
465 XClearWindow( xskin_d, xskin_w );
466
467 XMapWindow( xskin_d, xskin_w );
468 while( 1 ) {
469 XNextEvent( xskin_d, &xskin_e );
470 if ( xskin_e.type == Expose ) break;
471 }
472
473 fshuf=0;
474 frep=0;
475 fequ=1;
476 fpll=1;
477 fplay=0;
478 fpause=0;
479 fremain=0;
480 play_val=1;
481 vol_val=50;
482 last_current_time=0;
483 total_time=0;
484 speana_buf = NULL;
485 strcpy( last_text, "welcome to timidity" );
486
487 install_sighandler();
488
489 repaint();
490 ts_spectrum( -1, speana_buf );
491
492 XFlush(xskin_d);
493
494 xskin_jobs( pipe_in ); /* tskin main jobs */
495
496 finish:
497 signal_vector(0); /* finish */
498 }
499
500 #define ISIN(x,y,x0,y0,w,h) ( (x>=x0)&&(x<x0+w)&&(y>=y0)&&(y<y0+h) )?1:0
501
xskin_jobs(int pipe_in)502 static void xskin_jobs( int pipe_in ) {
503 XEvent e;
504 int x,y;
505 int window_x,window_y;
506 int fspe=0;
507 int pr=-1;
508 int z;
509 int p;
510 int master_volume=0;
511 char file_name[1024], tmp[1024];
512
513 int last_puttext_time;
514 int last_window_x=-1, last_window_y=-1;
515
516 int max_files;
517 int i;
518 fd_set fds;
519 static struct timeval tv;
520
521 Window t_w;
522 unsigned int t_width, t_height, t_border, t_depth;
523
524 xskin_pipe_write( "READY" );
525
526 shmid = shmget( IPC_PRIVATE, sizeof(char)*SPE_W, IPC_CREAT|0600 );
527 if ( shmid<0 ) xskin_pipe_write( "ERROR" );
528 else {
529 sprintf( local_buf, "%d", shmid );
530 xskin_pipe_write( local_buf );
531 speana_buf = (unsigned char *)shmat( shmid, 0, 0 );
532 }
533
534 xskin_pipe_read( local_buf, sizeof(local_buf) );
535 max_files = atoi( local_buf );
536 for ( i=0 ; i<max_files ; i++ ) {
537 xskin_pipe_read( local_buf, sizeof(local_buf) );
538 }
539
540 z=1;
541 last_puttext_time=0;
542 last_current_time=0;
543
544 XGetGeometry( xskin_d, xskin_w, &t_w,
545 &window_x, &window_y,
546 &t_width, &t_height, &t_border, &t_depth );
547
548 while( z ) {
549
550 XFlush( xskin_d );
551
552 FD_ZERO( &fds );
553 FD_SET( pipe_in, &fds );
554 tv.tv_sec=0;
555 tv.tv_usec=20000L; /* 20 msec */
556 i=select( pipe_in+1, &fds, NULL, NULL, &tv );
557
558 if ( i!=0 ) {
559 xskin_pipe_read( local_buf, sizeof(local_buf) );
560 switch (local_buf[0]) {
561
562 case 'A': /* total time */
563 total_time=atoi( local_buf+2 );
564 last_current_time=0;
565 last_puttext_time=0;
566 break;
567
568 case 'T': /* current time */
569 {
570 int min,sec;
571 sscanf( local_buf+2, "%02d:%02d", &min, &sec );
572 i=min*60+sec;
573 if ( fremain==1 ) {
574 sec =total_time-i;
575 min =sec/60;
576 sec-=min*60;
577 }
578 if ( i != last_current_time ) {
579 ts_putnum( MIN_H_X, MIN_H_Y, min/10 );
580 ts_putnum( MIN_L_X, MIN_L_Y, min%10 );
581 ts_putnum( SEC_H_X, SEC_H_Y, sec/10 );
582 ts_putnum( SEC_L_X, SEC_L_Y, sec%10 );
583 p=100*i/total_time;
584 play_val=ts_pos( OFF, -p );
585 last_current_time=i;
586
587 if ( last_current_time - last_puttext_time == 3 ) { /* 3 sec */
588 sprintf( tmp, "%s [%02d:%02d]",
589 file_name, total_time/60, total_time%60 );
590 ts_puttext( MESSAGE_X, MESSAGE_Y, tmp );
591 }
592 }
593 }
594 break;
595
596 case 'L': /* lylics/message */
597 ts_puttext( MESSAGE_X, MESSAGE_Y, local_buf+2 );
598 last_puttext_time=last_current_time;
599 break;
600
601 case 'F': /* filename */
602 strncpy( file_name, local_buf+2, 1023 );
603 file_name[1023]=0;
604 break;
605
606 case 'O': /* off the play button */
607 fplay=0;
608 ts_play(OFF);
609 ts_spectrum(fspe, NULL); /* erase spectrums */
610 break;
611
612 case 'V': /* master volume */
613 master_volume=atoi( local_buf+2 );
614 p=100*((master_volume<200)?master_volume:200)/200; /* max:200% */
615 vol_val=ts_volume( OFF, -p );
616 break;
617
618 case 'Q': /* quit */
619 z=1;
620 break;
621
622 case 'W': /* wave form */
623 ts_spectrum(fspe, speana_buf);
624 break;
625
626 default:
627 break;
628 }
629 }
630
631 if ( XPending( xskin_d )==0 ) continue;
632 XNextEvent( xskin_d, &e );
633
634 switch ( e.type ) {
635 /*
636 case KeyPress:
637 z=0;
638 break;
639 */
640
641 case Expose:
642 repaint();
643 break;
644
645 case EnterNotify:
646 {
647 Cursor cs;
648 ts_titlebar(ON);
649 cs = XCreateFontCursor( xskin_d, XC_top_left_arrow );
650 XDefineCursor( xskin_d, xskin_w, cs );
651 }
652 break;
653
654 case LeaveNotify:
655 ts_titlebar(OFF);
656 XUndefineCursor( xskin_d, xskin_w );
657 break;
658
659 case MotionNotify:
660 while( XCheckMaskEvent( xskin_d, Button1MotionMask, &e ) ) {
661 XNextEvent( xskin_d, &e );
662 }
663 x = e.xbutton.x;
664 y = e.xbutton.y;
665 switch( pr ) {
666
667 /*
668 case TS_POS:
669 play_val=ts_pos( ON, x );break;
670 */
671 case TS_VOLUME:
672 vol_val=ts_volume( ON, x );
673 i=master_volume;
674 master_volume=200*vol_val/100;
675 sprintf( local_buf, "V %d", master_volume-i );
676 xskin_pipe_write( local_buf );
677
678 sprintf( tmp, " volume: %d%%", vol_val );
679 ts_puttext( MESSAGE_X, MESSAGE_Y, tmp );
680 last_puttext_time=last_current_time;
681 break;
682 /*
683 case TS_PAN:
684 pan_val=ts_pan( ON, x );break;
685 */
686
687 default:
688 if ( x != last_window_x || y != last_window_y ) {
689 window_x += x-last_window_x;
690 window_y += y-last_window_y;
691 XMoveWindow( xskin_d, xskin_w,
692 window_x, window_y );
693 }
694 break;
695 }
696 break;
697
698 case ButtonPress:
699 x = e.xbutton.x;
700 y = e.xbutton.y;
701 last_window_x=x;
702 last_window_y=y;
703
704 if ( ISIN( x, y,EXITBUTTON_DX,EXITBUTTON_DY,
705 EXITBUTTON_W,EXITBUTTON_H ) ) {
706 ts_exitbutton(ON);pr=TS_EXITBUTTON;
707
708 } else if ( ISIN( x, y, PREV_DX, PREV_DY, PREV_W, PREV_H ) ) {
709 ts_prev(ON);pr=TS_PREV;
710 } else if ( ISIN( x, y, PLAY_DX, PLAY_DY, PLAY_W, PLAY_H ) ) {
711 ts_play(ON);pr=TS_PLAY;
712 } else if ( ISIN( x, y, PAUSE_DX, PAUSE_DY, PAUSE_W, PAUSE_H ) ) {
713 ts_pause(ON);pr=TS_PAUSE;
714 } else if ( ISIN( x, y, STOP_DX, STOP_DY, STOP_W, STOP_H ) ) {
715 ts_stop(ON);pr=TS_STOP;
716 } else if ( ISIN( x, y, NEXT_DX, NEXT_DY, NEXT_W, NEXT_H ) ) {
717 ts_next(ON);pr=TS_NEXT;
718 } else if ( ISIN( x, y, EJECT_DX, EJECT_DY, EJECT_W, EJECT_H ) ) {
719 ts_eject(ON);pr=TS_EJECT;
720
721 } else if ( ISIN( x, y,164, 89, 47, 15 ) ) { /* shuffle */
722 if ( fshuf==0 ) {
723 ts_shuf(OFFON);pr=TS_SHUFON;
724 } else {
725 ts_shuf(ONOFF);pr=TS_SHUFOFF;
726 }
727 } else if ( ISIN( x, y,210, 89, 28, 15 ) ) { /* repeat */
728 if ( frep==0 ) {
729 ts_rep(OFFON);pr=TS_REPON;
730 } else {
731 ts_rep(ONOFF);pr=TS_REPOFF;
732 }
733 } else if ( ISIN( x, y,219, 58, 23, 12 ) ) { /* equalizer */
734 if ( fequ==0 ) {
735 ts_equ(OFFON);pr=TS_EQUON;
736 } else {
737 ts_equ(ONOFF);pr=TS_EQUOFF;
738 }
739 } else if ( ISIN( x, y,242, 58, 23, 12 ) ) { /* playlist */
740 if ( fpll==0 ) {
741 ts_plist(OFFON);pr=TS_PLISTON;
742 } else {
743 ts_plist(ONOFF);pr=TS_PLISTOFF;
744 }
745
746 } else if ( ISIN( x, y, MENUBUTTON_DX, MENUBUTTON_DY,
747 MENUBUTTON_W, MENUBUTTON_H ) ) {
748 ts_menubutton(ON);pr=TS_MENUBUTTON;
749 } else if ( ISIN( x, y, ICONBUTTON_DX, ICONBUTTON_DY,
750 ICONBUTTON_W, ICONBUTTON_H ) ) {
751 ts_iconbutton(ON);pr=TS_ICONBUTTON;
752 } else if ( ISIN( x, y, MINIBUTTON_DX, MINIBUTTON_DY,
753 MINIBUTTON_W, MINIBUTTON_H ) ) {
754 ts_minibutton(ON);pr=TS_MINIBUTTON;
755
756 /*
757 } else if ( ISIN( x, y,POS_MIN_DX+(POS_MAX_DX-POS_MIN_DX)*play_val/100,
758 POS_DY, POS_W, POS_H ) ) {
759 ts_pos( ON, -play_val );pr=TS_POS;
760 */
761 } else if ( ISIN( x, y,VOL_MIN_DX+(VOL_MAX_DX-VOL_MIN_DX)*vol_val/100,
762 VOL_DY, VOL_W, VOL_H ) ) {
763 ts_volume( ON, -vol_val );pr=TS_VOLUME;
764 sprintf( tmp, " volume: %d%%", vol_val );
765 ts_puttext( MESSAGE_X, MESSAGE_Y, tmp );
766 last_puttext_time=last_current_time;
767
768 /*
769 } else if ( ISIN( x, y,PAN_MIN_DX+(PAN_MAX_DX-PAN_MIN_DX)*pan_val/100,
770 PAN_DY, PAN_W, PAN_H ) ) {
771 ts_pan( ON, -pan_val );pr=TS_PAN;
772 */
773
774 } else if ( ISIN( x, y, MIN_H_X, MIN_H_Y,
775 SEC_L_X+NUM_W-MIN_H_X, NUM_H ) ) {
776 int min,sec;
777 fremain=(fremain==0)?1:0;
778 sec=(fremain==0)?last_current_time:total_time-last_current_time;
779 min =sec/60;
780 sec-=min*60;
781 ts_putnum( MIN_H_X, MIN_H_Y, min/10 );
782 ts_putnum( MIN_L_X, MIN_L_Y, min%10 );
783 ts_putnum( SEC_H_X, SEC_H_Y, sec/10 );
784 ts_putnum( SEC_L_X, SEC_L_Y, sec%10 );
785
786 } else if ( ISIN( x, y, SPE_SX, SPE_SY, SPE_W, SPE_H ) ) {
787 pr=TS_SPECTRUM;
788 } else {
789 XRaiseWindow( xskin_d, xskin_w );
790 }
791 break;
792
793 case ButtonRelease:
794
795 last_window_x = -1;
796 last_window_y = -1;
797
798 switch( pr ) {
799
800 case TS_EXITBUTTON:
801 ts_exitbutton(OFF);
802 xskin_pipe_write("Q");
803 z=0;break;
804
805 case TS_PREV:
806 ts_prev(OFF);
807 ts_spectrum( fspe, NULL );
808 xskin_pipe_write("B");
809 break;
810 case TS_PLAY:
811 xskin_pipe_write("P");
812 fplay=1;
813 pauseOff();
814 ts_play(OFF);ts_pause(OFF);
815 ts_pstate( PSTATE_PLAY );
816 break;
817 case TS_PAUSE:
818 ts_pause(OFF);
819 if ( fplay ==1 ) {
820 if ( fpause==0 ) {
821 ts_pstate( PSTATE_PAUSE );
822 ts_spectrum( fspe, NULL );
823 pauseOn();
824 } else {
825 ts_pstate( PSTATE_PLAY );
826 pauseOff();
827 }
828 }
829 break;
830 case TS_STOP:
831 pauseOff();
832 fplay=0;
833 ts_pause(OFF);ts_play(OFF);ts_stop(OFF);
834 ts_pstate( PSTATE_STOP );
835 ts_spectrum( fspe, NULL );
836 xskin_pipe_write("S");
837 break;
838 case TS_NEXT:
839 ts_next(OFF);
840 ts_spectrum( fspe, NULL );
841 xskin_pipe_write("N");
842 break;
843 case TS_EJECT:
844 ts_eject(OFF);break;
845
846 case TS_SHUFON:
847 ts_shuf(ON);fshuf=1;
848 fplay=1;
849 pauseOff();
850 ts_pstate( PSTATE_PLAY );
851 xskin_pipe_write("D 1");
852 break;
853 case TS_SHUFOFF:
854 ts_shuf(OFF);fshuf=0;
855 fplay=0;
856 pauseOff();
857 ts_pstate( PSTATE_STOP );
858 ts_spectrum( fspe, NULL );
859 xskin_pipe_write("D 2");
860 break;
861 case TS_REPON:
862 ts_rep(ON);frep=1;
863 xskin_pipe_write("R 1");
864 break;
865 case TS_REPOFF:
866 ts_rep(OFF);frep=0;
867 xskin_pipe_write("R 0");
868 break;
869
870 case TS_EQUON:
871 ts_equ(ON);fequ=1;break;
872 case TS_EQUOFF:
873 ts_equ(OFF);fequ=0;break;
874
875 case TS_PLISTON:
876 ts_plist(ON);fpll=1;break;
877 case TS_PLISTOFF:
878 ts_plist(OFF);fpll=0;break;
879
880 case TS_MENUBUTTON:
881 ts_menubutton(OFF);break;
882 case TS_ICONBUTTON:
883 ts_iconbutton(OFF);break;
884 case TS_MINIBUTTON:
885 ts_minibutton(OFF);break;
886
887 /*
888 case TS_POS:
889 ts_pos( OFF, -play_val );break;
890 */
891 case TS_VOLUME:
892 ts_volume( OFF, -vol_val );break;
893 /*
894 case TS_PAN:
895 ts_pan( OFF, -pan_val );break;
896 */
897
898 case TS_SPECTRUM:
899 #ifdef SUPPORT_SOUNDSPEC
900 fspe = (fspe+1)%3;
901 if ( fspe==1 ) xskin_pipe_write("W"); /* on */
902 else if ( fspe==0 ) {
903 xskin_pipe_write("W"); /* off */
904 ts_spectrum(0,speana_buf);
905 }
906 #endif /* SUPPORT_SOUNDSPEC */
907 break;
908
909 default:
910 break;
911 }
912 pr=-1;
913 break;
914
915 default:
916 break;
917 }
918 }
919
920 return;
921 }
922
load_skins(void)923 static int load_skins( void ) {
924
925 char **files;
926 char *tmp[2];
927 int nfiles;
928 int i,pixmaps;
929 char *p,*p0;
930 char *skin_name;
931 int width, height;
932
933 skin_name = getenv( "TIMIDITY_SKIN" );
934 if ( skin_name == NULL ) {
935 skin_name = getenv( "timidity_skin" );
936 if ( skin_name == NULL ) {
937 #ifdef DEFAULT_SKIN
938 skin_name = DEFAULT_SKIN;
939 #else
940 fprintf(stderr, "Undefined environment `timidity_skin'\n");
941 return -1;
942 #endif
943 }
944 }
945
946 tmp[0]=skin_name;
947 files=tmp;
948 nfiles=1;
949 files = expand_file_archives( files, &nfiles );
950
951 pixmaps=0;
952
953 xskin_loadviscolor( xskin_d, xskin_w, NULL );
954
955 for ( i=0 ; i<nfiles ; i++ ) {
956
957 /*printf("%s\n",files[i]);fflush(stdout);*/
958 p0=strrchr( files[i], '#' );
959 if ( p0==NULL ) p0=files[i];
960 else p0++;
961 p=strrchr( p0, PATH_SEP );
962 if ( p==NULL ) p=p0;
963 else p++;
964
965 if ( strcasecmp( p, "viscolor.txt" )==0 ) {
966 xskin_loadviscolor( xskin_d, xskin_w, files[i] );
967
968 } else if ( strcasecmp( p, "main.bmp" )==0 ) {
969 xskin_back =
970 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
971 pixmaps++;
972
973 } else if ( strcasecmp( p, "titlebar.bmp" )==0 ) {
974 xskin_titlebar =
975 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
976 pixmaps++;
977
978 } else if ( strcasecmp( p, "playpaus.bmp" )==0 ) {
979 xskin_playpaus =
980 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
981 pixmaps++;
982
983 } else if ( strcasecmp( p, "cbuttons.bmp" )==0 ) {
984 xskin_cbuttons =
985 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
986 pixmaps++;
987
988 } else if ( strcasecmp( p, "monoster.bmp" )==0 ) {
989 xskin_monoster =
990 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
991 pixmaps++;
992
993 } else if ( strcasecmp( p, "posbar.bmp" )==0 ) {
994 xskin_posbar =
995 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
996 pixmaps++;
997
998 } else if ( strcasecmp( p, "shufrep.bmp" )==0 ) {
999 xskin_shufrep =
1000 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
1001 pixmaps++;
1002
1003 } else if ( strcasecmp( p, "text.bmp" )==0 ) {
1004 xskin_text =
1005 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
1006 pixmaps++;
1007
1008 } else if ( strcasecmp( p, "volume.bmp" )==0 ) {
1009 xskin_volume =
1010 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
1011 pixmaps++;
1012
1013 } else if ( strcasecmp( p, "numbers.bmp" )==0 ) {
1014 xskin_numbers =
1015 xskin_loadBMP( xskin_d, xskin_w, files[i], &width, &height );
1016 pixmaps++;
1017
1018 } else {
1019 width=1;
1020 }
1021 if ( width<0 ) return -1;
1022 }
1023
1024 if(files != tmp)
1025 free(files);
1026
1027 if ( pixmaps<10 ) {
1028 fprintf(stderr, "some of bmp file might be missed.\n");
1029 return -1;
1030 }
1031
1032 return 0;
1033 }
1034
repaint(void)1035 static void repaint( void ) {
1036
1037 char tmp[64];
1038 int min,sec;
1039
1040 /* static values */
1041
1042 XClearWindow( xskin_d, xskin_w );
1043
1044 ts_titlebar(OFF);
1045
1046 ts_prev(OFF);
1047 ts_play(OFF);
1048 ts_pause(OFF);
1049 ts_stop(OFF);
1050 ts_next(OFF);
1051 ts_eject(OFF);
1052
1053 if ( (play_mode->encoding & PE_MONO)==0 ) {
1054 ts_mono(OFF);
1055 ts_stereo(ON);
1056 } else {
1057 ts_mono(ON);
1058 ts_stereo(OFF);
1059 }
1060
1061 ts_pan(OFF,-50);
1062 ts_puttext( BITRATE_X, BITRATE_Y, "---" ); /* bit-rate */
1063
1064 sprintf( tmp, "%d", (int)play_mode->rate/1000 );
1065 ts_puttext( SAMPLE_X, SAMPLE_Y, tmp ); /* sample-rate */
1066
1067 /* volatile values */
1068
1069 if ( fshuf==0 ) ts_shuf(OFF);
1070 else ts_shuf(ON);
1071
1072 if ( frep==0 ) ts_rep(OFF);
1073 else ts_rep(ON);
1074
1075 if ( fequ==0 ) ts_equ(OFF);
1076 else ts_equ(ON);
1077
1078 if ( fpll==0 ) ts_plist(OFF);
1079 else ts_plist(ON);
1080
1081 if ( fplay==1 ) {
1082 if ( fpause==0 ) ts_pstate( PSTATE_PLAY );
1083 else ts_pstate( PSTATE_PAUSE );
1084 } else ts_pstate( PSTATE_STOP );
1085
1086 ts_volume( OFF, -vol_val );
1087 ts_pos( OFF, -play_val );
1088
1089 ts_puttext( MESSAGE_X, MESSAGE_Y, last_text );
1090
1091 if ( fremain==0 ) {
1092 sec=last_current_time;
1093 } else {
1094 sec=total_time-last_current_time;
1095 }
1096 min =sec/60;
1097 sec-=min*60;
1098
1099 ts_putnum( MIN_H_X, MIN_H_Y, min/10 );
1100 ts_putnum( MIN_L_X, MIN_L_Y, min%10 );
1101 ts_putnum( SEC_H_X, SEC_H_Y, sec/10 );
1102 ts_putnum( SEC_L_X, SEC_L_Y, sec%10 );
1103
1104 XFlush(xskin_d);
1105 return;
1106 }
1107
1108 /* signal handler calls are ported from xmasl
1109 and thanks to takawata@shidahara1.planet.kobe-u.ac.jp */
1110
delete_shm(void)1111 void delete_shm( void ) {
1112
1113 if ( speana_buf != NULL ) {
1114 shmdt( (char *)speana_buf );
1115 shmctl( shmid, IPC_RMID, 0 );
1116 }
1117 return;
1118 }
1119
1120 static const int signals[]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGABRT,SIGFPE,
1121 SIGBUS,SIGSEGV,SIGPIPE,SIGALRM,SIGTERM,0};
1122
install_sighandler(void)1123 void install_sighandler( void ) {
1124 int i;
1125 for ( i=0 ; signals[i]!=0 ; i++ ) {
1126 signal( signals[i], signal_vector );
1127 }
1128 }
1129
signal_vector(int sig)1130 void signal_vector( int sig ) {
1131
1132 delete_shm();
1133
1134 XUnmapWindow( xskin_d, xskin_w );
1135 XFlush(xskin_d);
1136 XDestroyWindow( xskin_d, xskin_w );
1137
1138 XCloseDisplay( xskin_d );
1139 exit (0);
1140 }
1141