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