1 /* $Id: hmiplay.c,v 1.2 2003/03/13 00:20:21 btb Exp $ */
2 /*
3  * HMI midi playing routines by Jani Frilander
4  *
5  * External device support by Patrick McCarthy
6  *
7  * Ported to d1x/sdl_threads by Matthew Mueller
8  *
9  */
10 
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <signal.h>
17 #include <linux/soundcard.h>
18 #include <sys/ioctl.h>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/ipc.h>
22 #include <sys/msg.h>
23 #include "music.h"
24 #include "cfile.h"
25 
26 #include <SDL_thread.h>
27 
28 //#define WANT_AWE32 1
29 
30 #ifdef WANT_AWE32
31 #include <linux/awe_voice.h>
32 #endif
33 
34 //#define WANT_MPU401 1
35 
36 #ifdef WANT_MPU401
37 #define MIDI_MESSAGE2(a,b) {		\
38 	SEQ_MIDIOUT(synth_dev,a);	\
39 	SEQ_MIDIOUT(synth_dev,b);	\
40 }
41 
42 #define MIDI_MESSAGE3(a,b,c) {		\
43 	SEQ_MIDIOUT(synth_dev,a);	\
44 	SEQ_MIDIOUT(synth_dev,b);	\
45 	SEQ_MIDIOUT(synth_dev,c);	\
46 }
47 #endif
48 
49 SEQ_DEFINEBUF(1024);
50 
51 int drumflag = 1<<9;
52 int seqfd;
53 int synth_dev;
54 int program[16];
55 int stop;
56 double volume=1;
57 
58 int ipc_queue_id = -1;
59 struct msgbuf *snd;
60 
61 SDL_Thread *player_thread=NULL;
62 
63 Voice_info *voices;
64 unsigned char *data=NULL;
65 
66 struct synth_info card_info;
67 
seqbuf_dump()68 void seqbuf_dump()
69 {
70 	if (_seqbufptr)
71 	{
72 		if (write(seqfd, _seqbuf, _seqbufptr) == -1)
73 		{
74 			perror ("Error writing sequencer device");
75 			SDL_KillThread(player_thread);
76 		}
77 	}
78 	_seqbufptr = 0;
79 }
80 
my_quit()81 void my_quit()
82 {
83 //	printf("goodbye\n");//#####
84 //	exit(0);
85 }
86 
seq_init()87 int seq_init()
88 {
89 	int nrmidis,nrsynths,i;
90 
91 	if ((seqfd = open(SEQ_DEV, O_WRONLY, 0)) < 0)
92 	{
93 		perror ("Error opening sequencer device");
94 		return (-1);
95 	}
96 
97 	if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1)
98 	{
99 		perror ("There is no soundcard");
100 		return (-1);
101 	}
102 
103 	if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1)
104 	{
105 		perror ("There is no soundcard");
106 		return (-1);
107 	}
108 
109 
110 	if(nrsynths < 1 && nrmidis < 1)
111 	{
112 		printf("No synth or midi device!\n");
113 		return -1;
114 	}
115 
116 	synth_dev = 0;
117 
118 	//Check if we have wavetable synth device
119 	for (i=0; i < nrsynths; i++)
120 	{
121 		card_info.device = i;
122 		if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
123 		{
124 			perror("cannot get info on soundcard");
125 			return (-1);
126 		}
127 
128 		if (card_info.synth_type == SYNTH_TYPE_SAMPLE)
129 		{
130 			synth_dev = i;
131 			break;
132 		}
133 	}
134 
135 #ifdef WANT_AWE32
136 	for (i=0; i < nrsynths; i++)
137 	{
138 		card_info.device = i;
139 		if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
140 		{
141 			perror("cannot get info on soundcard");
142 			return (-1);
143 		}
144 
145 		if (card_info.synth_type==SYNTH_TYPE_SAMPLE
146 		    &&card_info.synth_subtype==SAMPLE_TYPE_AWE32) {
147 			synth_dev = i;
148 			break;
149 		}
150 	}
151 #endif
152 
153 #ifdef WANT_MPU401
154 	for (i=0; i < nrmidis; i++)
155 	{
156 		struct midi_info cinfo;
157 		cinfo.device = i;
158 		if (ioctl(seqfd, SNDCTL_MIDI_INFO, &cinfo) == -1)
159 		{
160 			perror("cannot get info on soundcard");
161 			return (-1);
162 		}
163 
164 		// Just take first available for now.
165 		card_info.synth_type=SYNTH_TYPE_MIDI;
166 		card_info.device=i;
167 		synth_dev=i;
168 		break;
169 	}
170 
171 	if (card_info.synth_type!=SYNTH_TYPE_MIDI) {
172 #endif
173 
174 		card_info.device = synth_dev;
175 		if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
176 		{
177 			perror("cannot get info on soundcard");
178 			return (-1);
179 		}
180 
181 #ifdef WANT_MPU401
182 	}
183 
184 	if (card_info.synth_type==SYNTH_TYPE_MIDI) {
185 		// Insert some sort of midi reset here later.
186 	} else
187 #endif
188 #ifdef WANT_AWE32
189 	  if (card_info.synth_type == SYNTH_TYPE_SAMPLE
190 	      && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
191 	{
192 		AWE_SET_CHANNEL_MODE(synth_dev,1);
193 		AWE_DRUM_CHANNELS(synth_dev,drumflag);
194 	}
195 	else
196 #endif
197 	{
198 		voices = malloc(sizeof(Voice_info)*card_info.nr_voices);
199 		for (i=0;i<card_info.nr_voices;i++)
200 		{
201 			voices[i].note = -1;
202 			voices[i].channel = -1;
203 		}
204 	}
205 
206 	return(0);
207 }
208 
seq_close()209 void seq_close()
210 {
211 	SEQ_DUMPBUF();
212 	ioctl(seqfd,SNDCTL_SEQ_SYNC);
213 	close(seqfd);
214 	free(voices);
215 }
216 
set_program(int channel,int pgm)217 void set_program(int channel, int pgm)
218 {
219 #ifdef WANT_AWE32
220 	if (card_info.synth_type == SYNTH_TYPE_SAMPLE
221 	    && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
222 	{
223 		SEQ_SET_PATCH(synth_dev,channel,pgm);
224 	}
225 	else
226 #endif
227 	  program[channel]=pgm;
228 }
229 
start_note(int channel,int note,int vel)230 void start_note(int channel, int note, int vel)
231 {
232 	int i;
233 
234 #ifdef WANT_AWE32
235 	if (card_info.synth_type == SYNTH_TYPE_SAMPLE
236 	    && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
237 	{
238 		SEQ_START_NOTE(synth_dev,channel,note,vel);
239 	}
240 	else
241 #endif
242 	{
243 		for (i=0; i<card_info.nr_voices;i++)
244 		  if ((voices[i].note == -1) && (voices[i].channel == -1))
245 		    break;
246 		if (i != card_info.nr_voices)
247 		{
248 			voices[i].note = note;
249 			voices[i].channel = channel;
250 			if (((1<<channel) & drumflag))         /* drum note */
251 			{
252 				SEQ_SET_PATCH(synth_dev, i, note + 128);
253 			}
254 			else
255 			{
256 				SEQ_SET_PATCH(synth_dev, i, program[channel]);
257 			}
258 			SEQ_START_NOTE(synth_dev, i, note, vel);
259 		}
260 	}
261 }
262 
stop_note(int channel,int note,int vel)263 void stop_note(int channel, int note, int vel)
264 {
265 	int i;
266 
267 #ifdef WANT_AWE32
268 	if (card_info.synth_type == SYNTH_TYPE_SAMPLE
269 	    && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
270 	{
271 		SEQ_STOP_NOTE(synth_dev,channel,note,vel);
272 	}
273 	else
274 #endif
275 	{
276 		for (i=0; i<card_info.nr_voices;i++)
277 		  if ((voices[i].note == note) && (voices[i].channel == channel))
278 		    break;
279 		if (i != card_info.nr_voices)
280 		{
281 			voices[i].note = -1;
282 			voices[i].channel = -1;
283 			SEQ_STOP_NOTE(synth_dev,i,note,vel);
284 		}
285 	}
286 }
287 
set_control(int channel,int ctrl,int value)288 void set_control(int channel,int ctrl,int value)
289 {
290 	int i;
291 
292 #ifdef WANT_AWE32
293 	if (card_info.synth_type == SYNTH_TYPE_SAMPLE
294 	    && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
295 	{
296 		SEQ_CONTROL(synth_dev,channel,ctrl,value);
297 	}
298 	else
299 #endif
300 	{
301 		for (i=0; i<card_info.nr_voices;i++)
302 		  if (voices[i].channel == channel)
303 		    if (ctrl == CTL_MAIN_VOLUME)
304 		      SEQ_MAIN_VOLUME(synth_dev,i,value);
305 	}
306 }
307 
set_pitchbend(int channel,int bend)308 void set_pitchbend(int channel, int bend)
309 {
310 	int i;
311 
312 #ifdef WANT_AWE32
313 	if (card_info.synth_type == SYNTH_TYPE_SAMPLE
314 	    && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
315 	{
316 		SEQ_BENDER(synth_dev,channel,bend);
317 	}
318 	else
319 #endif
320 	{
321 		for (i=0; i<card_info.nr_voices;i++)
322 		  if (voices[i].channel == channel)
323 		{
324 			/*SEQ_BENDER_RANGE(synth_dev, i, 200);*/
325 			SEQ_BENDER(synth_dev, i, bend);
326 		}
327 	}
328 }
329 
set_key_pressure(int channel,int note,int vel)330 void set_key_pressure(int channel, int note, int vel)
331 {
332 	int i;
333 
334 #ifdef WANT_AWE32
335 	if (card_info.synth_type == SYNTH_TYPE_SAMPLE
336 	    && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
337 	{
338 		AWE_KEY_PRESSURE(synth_dev,channel,note,vel);
339 	}
340 	else
341 #endif
342 	{
343 		for (i=0; i<card_info.nr_voices;i++)
344 		  if ((voices[i].note == note) && (voices[i].channel == channel))
345 		    SEQ_KEY_PRESSURE(synth_dev,i,note,vel);
346 	}
347 }
348 
set_chn_pressure(int channel,int vel)349 void set_chn_pressure(int channel, int vel)
350 {
351 	int i;
352 
353 #ifdef WANT_AWE32
354 	if (card_info.synth_type == SYNTH_TYPE_SAMPLE
355 	    && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
356 	{
357 		AWE_CHN_PRESSURE(synth_dev,channel,vel);
358 	}
359 	else
360 #endif
361 	{
362 		for (i=0; i<card_info.nr_voices;i++)
363 		  if (voices[i].channel == channel)
364 		    SEQ_CHN_PRESSURE(synth_dev,i,vel);
365 	}
366 }
367 
stop_all()368 void stop_all()
369 {
370 	int i;
371 
372 #ifdef WANT_AWE32
373 	int j;
374 	if (card_info.synth_type == SYNTH_TYPE_SAMPLE
375 	    && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
376 	{
377 		for (i=0; i<16;i++)
378 		  for (j=0;j<128;j++)
379 		    SEQ_STOP_NOTE(synth_dev,i,j,0);
380 	}
381 	else
382 #endif
383 #ifdef WANT_MPU401
384 	  if (card_info.synth_type==SYNTH_TYPE_MIDI) {
385 	  } else
386 #endif
387 	{
388 		for (i=0; i<card_info.nr_voices;i++)
389 		  SEQ_STOP_NOTE(synth_dev,i,voices[i].note,0);
390 	}
391 }
392 
get_dtime(unsigned char * data,int * pos)393 int get_dtime(unsigned char *data, int *pos)
394 {
395 	char buf;
396 	int result;
397 	result =0;
398 
399 	buf = data[*pos];
400 	*pos +=1;
401 	result = (0x7f & buf);
402 
403 	if (!(buf & 0x80))
404 	{
405 		buf = data[*pos];
406 		*pos +=1;
407 		result |=(int) (((int) 0x7f & (int) buf)<<7);
408 		if (!(buf & 0x80))
409 		{
410 			buf = data[*pos];
411 			*pos +=1;
412 			result |=(int) (((int) 0x7f & (int) buf)<<14);
413 			if (!(buf & 0x80))
414 			{
415 				buf = data[*pos];
416 				*pos +=1;
417 				result |=(int) (((int) 0x7f & (int) buf)<<21);
418 			}
419 		}
420 	}
421 
422 	return result;
423 }
424 
do_track_event(unsigned char * data,int * pos)425 int do_track_event(unsigned char *data, int *pos)
426 {
427 	char channel;
428 	unsigned char buf[5];
429 
430 	buf[0]=data[*pos];
431 	*pos +=1;
432 	channel = buf[0] & 0xf;
433 #ifdef WANT_MPU401
434 	if (card_info.synth_type==SYNTH_TYPE_MIDI) {
435 		switch((buf[0]&0xf0)) {
436 		 case 0x80:
437 		 case 0x90:
438 		 case 0xa0:
439 		 case 0xb0:
440 		 case 0xe0:
441 			buf[1]=data[*pos]; *pos+=1;
442 			buf[2]=data[*pos]; *pos+=1;
443 			MIDI_MESSAGE3(buf[0],buf[1],buf[2]);
444 			break;
445 		 case 0xc0:
446 		 case 0xd0:
447 			buf[1]=data[*pos]; *pos+=1;
448 			MIDI_MESSAGE3(buf[0],0,buf[1]);
449 			break;
450 		 case 0xf0:
451 			return 1;
452 		 default:
453 			return 3;
454 		}
455 		seqbuf_dump();
456 		return 0;
457 	}
458 #endif
459 
460 	switch((buf[0] & 0xf0))
461 	{
462 	 case 0x80:
463 		buf[1]=data[*pos];
464 		*pos +=1;
465 		buf[2]=data[*pos];
466 		*pos +=1;
467 		stop_note((int) channel, (int) buf[1], (int) buf[2]);
468 		break;
469 	 case 0x90:
470 		buf[1]=data[*pos];
471 		*pos +=1;
472 		buf[2]=data[*pos];
473 		*pos +=1;
474 		if(buf[2] == 0)
475 		{
476 			stop_note((int) channel, (int) buf[1], (int) buf[2]);
477 		}
478 		else
479 		{
480 			start_note((int) channel, (int) buf[1], (int) buf[2]);
481 		}
482 		break;
483 	 case 0xa0:
484 		buf[1]=data[*pos];
485 		*pos +=1;
486 		buf[2]=data[*pos];
487 		*pos +=1;
488 		set_key_pressure((int) channel, (int) buf[1], (int) buf[2]);
489 		break;
490 	 case 0xb0:
491 		buf[1]=data[*pos];
492 		*pos +=1;
493 		buf[2]=data[*pos];
494 		*pos +=1;
495 		set_control((int) channel, (int) buf[1], (int) buf[2]);
496 		break;
497 	 case 0xe0:
498 		buf[1]=data[*pos];
499 		*pos +=1;
500 		buf[2]=data[*pos];
501 		*pos +=1;
502 		set_pitchbend((int) channel, (int) ((buf[2] << 7) + buf[1]));
503 		break;
504 	 case 0xc0:
505 		buf[1]=data[*pos];
506 		*pos +=1;
507 		set_program((int) channel, (int) buf[1] );
508 		break;
509 	 case 0xd0:
510 		buf[1]=data[*pos];
511 		*pos +=1;
512 		set_chn_pressure((int) channel, (int) buf[1]);
513 		break;
514 	 case 0xf0:
515 		return 1;
516 	 default:
517 		return 3;
518 	}
519 	seqbuf_dump();
520 	return 0;
521 }
522 
send_ipc(char * message)523 void send_ipc(char *message)
524 {
525 	printf ("sendipc %s\n", message);//##########3
526 	if (ipc_queue_id<0)
527 	{
528 		ipc_queue_id=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's',
529 				     IPC_CREAT | 0660);
530 		snd=malloc(sizeof(long) + 32);
531 		snd->mtype=1;
532 		player_thread=SDL_CreateThread(play_hmi, NULL);
533 //		player_pid = play_hmi();
534 	}
535 	if (strlen(message) < 16)
536 	{
537 		sprintf(snd->mtext,"%s",message);
538 		msgsnd(ipc_queue_id,snd,16,0);
539 	}
540 }
541 
kill_ipc()542 void kill_ipc()
543 {
544 //	send_ipc("q");
545 //	kill(player_pid,SIGTERM);
546 	msgctl( ipc_queue_id, IPC_RMID, 0);
547 	free(snd);
548 	ipc_queue_id = -1;
549 //	player_pid = 0;
550 }
551 
do_ipc(int qid,struct msgbuf * buf,int flags)552 int do_ipc(int qid, struct msgbuf *buf, int flags)
553 {
554 	int ipc_read;
555 	CFILE *fptr;
556 	int l=0;
557 
558 	ipc_read = msgrcv(qid,buf,16,0,flags | MSG_NOERROR);
559 
560 	switch (ipc_read)
561 	{
562 	 case -1:
563 		if (errno == ENOMSG)
564 		  break;
565 		perror("IPC trouble");
566 		break;
567 	 case 0:
568 		break;
569 	 default:
570 		printf ("do_ipc %s\n", buf->mtext);//##########3
571 		switch (buf->mtext[0])
572 		{
573 		 case 'v':
574 			volume=(double) ((double) buf->mtext[0]/127.0);
575 			break;
576 		 case 'p':
577 			fptr=cfopen((buf->mtext+1),"rb");
578 			if(fptr != NULL)
579 			{
580 				l = cfilelength(fptr);
581 				data=realloc(data,(size_t) l);
582 				cfread(data, l, 1, fptr);
583 				cfclose(fptr);
584 				printf ("good. fpr=%p l=%i data=%p\n", fptr, l, data);//##########3
585 			}
586 			stop = 0;
587 			break;
588 		 case 's':
589 			stop = 2;
590 			break;
591 		 case 'q':
592 //			SDL_KillThread(player_thread);
593 			break;
594 		}
595 	}
596 
597 	return ipc_read;
598 }
599 
play_hmi(void * arg)600 void play_hmi (void * arg)
601 {
602 	int i;
603 	int pos = 0x308;
604 	int n_chunks = 0;
605 	int low_dtime;
606 	int low_chunk;
607 	int csec;
608 //	pid_t loc_pid;
609 	int qid;
610 	int ipc_read = 0;
611 	int k=0;
612 
613 	struct msgbuf *rcv;
614 
615 	Track_info *t_info;
616 
617 	printf ("play_hmi\n");//#########
618 
619 	stop = 0;
620 	ipc_read=0;
621 //	loc_pid=fork();
622 
623 /*	switch (loc_pid)
624 	{
625 	 case 0:
626 		break;
627 	 case -1:
628 		return -1;
629 	 default:
630 		atexit(kill_ipc);
631 		return loc_pid;
632 	}*/
633 
634 //	signal(SIGTERM, my_quit);
635 	rcv=malloc(sizeof(long) + 16);
636 
637 	rcv->mtype=1;
638 	rcv->mtext[0]='0';
639 
640 	sleep(2);
641 
642 	qid=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's', 0660);
643 	if(qid == -1)
644 	{
645 		return;
646 	}
647 
648 	do
649 	{
650 		ipc_read=do_ipc(qid,rcv,0);
651 	}
652 	while(rcv->mtext[0] != 'p');
653 
654 	stop=0;
655 	rcv->mtext[0] = '0';
656 
657 	seq_init();
658 
659 	n_chunks=data[0x30];
660 
661 	t_info = malloc(sizeof(Track_info)*n_chunks);
662 
663 	while(1)
664 	{
665 
666 		for(i=0;i<n_chunks;i++)
667 		{
668 			t_info[i].position = pos + 12;
669 			t_info[i].status = PLAYING;
670 			t_info[i].time = get_dtime(data,&t_info[i].position);
671 			pos += (( (0xff & data[pos + 5]) << 8 ) + (0xff & data[pos + 4]));
672 		}
673 
674 		SEQ_START_TIMER();
675 		do
676 		{
677 			low_chunk = -1;
678 			k++;
679 			i=0;
680 			do
681 			{
682 				if (t_info[i].status == PLAYING)
683 				  low_chunk = i;
684 				i++;
685 			}
686 			while((low_chunk <=0) && (i<n_chunks));
687 
688 			if (low_chunk == -1)
689 			  break;
690 
691 			low_dtime = t_info[low_chunk].time;
692 
693 			for(i=1;i<n_chunks;i++)
694 			{
695 				if ((t_info[i].time < low_dtime) &&
696 				    (t_info[i].status == PLAYING))
697 				{
698 					low_dtime = t_info[i].time;
699 					low_chunk = i;
700 				}
701 			}
702 
703 			if (low_dtime < 0)
704 			  printf("Serious warning: d_time negative!!!!!!\n");
705 
706 			csec = 0.86 * low_dtime;
707 
708 			//flush sequencer buffer after 20 events
709 			if (k == 20)
710 			{
711 				ioctl(seqfd, SNDCTL_SEQ_SYNC);
712 				k = 0;
713 			}
714 
715 			SEQ_WAIT_TIME(csec);
716 
717 			t_info[low_chunk].status = do_track_event(data,&t_info[low_chunk].position);
718 
719 			if (t_info[low_chunk].status == 3)
720 			{
721 				printf("Error playing data in chunk %d\n",low_chunk);
722 				t_info[low_chunk].status = STOPPED;
723 			}
724 
725 			if (t_info[low_chunk].status == PLAYING)
726 			  t_info[low_chunk].time += get_dtime(data,&t_info[low_chunk].position);
727 
728 			//Check if the song has reached the end
729 			stop = t_info[0].status;
730 			for(i=1;i<n_chunks;i++)
731 			  stop &= t_info[i].status;
732 
733 			if((do_ipc(qid,rcv,IPC_NOWAIT) > 0) && (rcv->mtext[0]=='p'))
734 			{
735 				n_chunks=data[0x30];
736 				t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
737 				stop = 1;
738 				rcv->mtext[0] = '0';
739 				stop_all();
740 			}
741 		}
742 		while(!stop);
743 		SEQ_STOP_TIMER();
744 		if( stop == 2)
745 		{
746 			stop_all();
747 			do
748 			{
749 				ipc_read=do_ipc(qid,rcv,0);
750 			}
751 			while(rcv->mtext[0] != 'p');
752 			rcv->mtext[0] = '0';
753 			n_chunks=data[0x30];
754 			t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
755 			stop = 0;
756 		}
757 		pos=0x308;
758 	}
759 	free(data);
760 	free(t_info);
761 	free(rcv);
762 
763 }
764 
digi_play_midi_song(char * filename,char * melodic_bank,char * drum_bank,int loop)765 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {
766         char buf[128];
767 
768         sprintf(buf,"p%s",filename);
769         send_ipc(buf);
770 }
digi_set_midi_volume(int mvolume)771 void digi_set_midi_volume( int mvolume ) {
772         char buf[128];
773 
774         sprintf(buf,"v%i",mvolume);
775         send_ipc(buf);
776 }
777