1 /* $Id: hmiplay.c,v 1.9 2004-05-19 19:20:16 btb Exp $ */
3 * HMI midi playing routines by Jani Frilander
5 * External device support by Patrick McCarthy
7 * Ported to d1x/sdl_threads by Matthew Mueller
17 #include <linux/soundcard.h>
18 #include <sys/ioctl.h>
20 #include <sys/types.h>
22 #define __USE_GNU //in recent glibc versions msgbuf is only defined if you have __USE_GNU defined
28 #include <SDL/SDL_thread.h>
30 //#define WANT_AWE32 1
33 #include <linux/awe_voice.h>
36 //#define WANT_MPU401 1
40 unsigned char reset_genmidi[5] =
41 { 0x7e, 0x7f, 0x09, 0x01, 0xf7 };
43 #define MIDI_RESET { \
44 SEQ_MIDIOUT(synth_dev,MIDI_SYSTEM_PREFIX); \
45 SEQ_MIDIOUT(synth_dev,reset_genmidi[0]); \
46 SEQ_MIDIOUT(synth_dev,reset_genmidi[1]); \
47 SEQ_MIDIOUT(synth_dev,reset_genmidi[2]); \
48 SEQ_MIDIOUT(synth_dev,reset_genmidi[3]); \
49 SEQ_MIDIOUT(synth_dev,reset_genmidi[4]); \
52 #define MIDI_MESSAGE2(a,b) { \
53 SEQ_MIDIOUT(synth_dev,a); \
54 SEQ_MIDIOUT(synth_dev,b); \
57 #define MIDI_MESSAGE3(a,b,c) { \
58 SEQ_MIDIOUT(synth_dev,a); \
59 SEQ_MIDIOUT(synth_dev,b); \
60 SEQ_MIDIOUT(synth_dev,c); \
73 int ipc_queue_id = -1;
76 SDL_Thread *player_thread=NULL;
79 unsigned char *data=NULL;
80 char digi_last_midi_song[16] = "";
82 struct synth_info card_info;
88 if (write(seqfd, _seqbuf, _seqbufptr) == -1)
90 perror ("Error writing sequencer device");
91 SDL_KillThread(player_thread);
99 // printf("goodbye\n");//#####
105 int nrmidis,nrsynths,i;
107 if ((seqfd = open(SEQ_DEV, O_WRONLY, 0)) < 0)
109 perror ("Error opening sequencer device");
113 if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1)
115 perror ("There is no soundcard");
119 if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1)
121 perror ("There is no soundcard");
126 if(nrsynths < 1 && nrmidis < 1)
128 printf("No synth or midi device!\n");
134 //Check if we have wavetable synth device
135 for (i=0; i < nrsynths; i++)
137 card_info.device = i;
138 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
140 perror("cannot get info on soundcard");
144 if (card_info.synth_type == SYNTH_TYPE_SAMPLE)
152 for (i=0; i < nrsynths; i++)
154 card_info.device = i;
155 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
157 perror("cannot get info on soundcard");
161 if (card_info.synth_type==SYNTH_TYPE_SAMPLE
162 &&card_info.synth_subtype==SAMPLE_TYPE_AWE32) {
170 for (i=0; i < nrmidis; i++)
172 struct midi_info cinfo;
174 if (ioctl(seqfd, SNDCTL_MIDI_INFO, &cinfo) == -1)
176 perror("cannot get info on soundcard");
180 // Just take first available for now.
181 card_info.synth_type=SYNTH_TYPE_MIDI;
187 if (card_info.synth_type!=SYNTH_TYPE_MIDI) {
190 card_info.device = synth_dev;
191 if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1)
193 perror("cannot get info on soundcard");
200 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
206 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
207 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
209 AWE_SET_CHANNEL_MODE(synth_dev,1);
210 AWE_DRUM_CHANNELS(synth_dev,drumflag);
215 voices = malloc(sizeof(Voice_info)*card_info.nr_voices);
216 for (i=0;i<card_info.nr_voices;i++)
219 voices[i].channel = -1;
229 ioctl(seqfd,SNDCTL_SEQ_SYNC);
234 void set_program(int channel, int pgm)
237 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
238 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
240 SEQ_SET_PATCH(synth_dev,channel,pgm);
244 program[channel]=pgm;
247 void start_note(int channel, int note, int vel)
252 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
253 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
255 SEQ_START_NOTE(synth_dev,channel,note,vel);
260 for (i=0; i<card_info.nr_voices;i++)
261 if ((voices[i].note == -1) && (voices[i].channel == -1))
263 if (i != card_info.nr_voices)
265 voices[i].note = note;
266 voices[i].channel = channel;
267 if (((1<<channel) & drumflag)) /* drum note */
269 SEQ_SET_PATCH(synth_dev, i, note + 128);
273 SEQ_SET_PATCH(synth_dev, i, program[channel]);
275 SEQ_START_NOTE(synth_dev, i, note, vel);
280 void stop_note(int channel, int note, int vel)
285 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
286 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
288 SEQ_STOP_NOTE(synth_dev,channel,note,vel);
293 for (i=0; i<card_info.nr_voices;i++)
294 if ((voices[i].note == note) && (voices[i].channel == channel))
296 if (i != card_info.nr_voices)
299 voices[i].channel = -1;
300 SEQ_STOP_NOTE(synth_dev,i,note,vel);
305 void set_control(int channel,int ctrl,int value)
310 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
311 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
313 SEQ_CONTROL(synth_dev,channel,ctrl,value);
318 for (i=0; i<card_info.nr_voices;i++)
319 if (voices[i].channel == channel)
320 if (ctrl == CTL_MAIN_VOLUME)
321 SEQ_MAIN_VOLUME(synth_dev,i,value);
325 void set_pitchbend(int channel, int bend)
330 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
331 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
333 SEQ_BENDER(synth_dev,channel,bend);
338 for (i=0; i<card_info.nr_voices;i++)
339 if (voices[i].channel == channel)
341 /*SEQ_BENDER_RANGE(synth_dev, i, 200);*/
342 SEQ_BENDER(synth_dev, i, bend);
347 void set_key_pressure(int channel, int note, int vel)
352 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
353 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
355 AWE_KEY_PRESSURE(synth_dev,channel,note,vel);
360 for (i=0; i<card_info.nr_voices;i++)
361 if ((voices[i].note == note) && (voices[i].channel == channel))
362 SEQ_KEY_PRESSURE(synth_dev,i,note,vel);
366 void set_chn_pressure(int channel, int vel)
371 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
372 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
374 AWE_CHN_PRESSURE(synth_dev,channel,vel);
379 for (i=0; i<card_info.nr_voices;i++)
380 if (voices[i].channel == channel)
381 SEQ_CHN_PRESSURE(synth_dev,i,vel);
391 if (card_info.synth_type == SYNTH_TYPE_SAMPLE
392 && card_info.synth_subtype == SAMPLE_TYPE_AWE32)
396 SEQ_STOP_NOTE(synth_dev,i,j,0);
401 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
407 for (i=0; i<card_info.nr_voices;i++)
408 SEQ_STOP_NOTE(synth_dev,i,voices[i].note,0);
412 int get_dtime(unsigned char *data, int *pos)
420 result = (0x7f & buf);
426 result |=(int) (((int) 0x7f & (int) buf)<<7);
431 result |=(int) (((int) 0x7f & (int) buf)<<14);
436 result |=(int) (((int) 0x7f & (int) buf)<<21);
444 int do_track_event(unsigned char *data, int *pos)
447 unsigned char buf[5];
451 channel = buf[0] & 0xf;
453 if (card_info.synth_type==SYNTH_TYPE_MIDI) {
454 switch((buf[0]&0xf0)) {
460 buf[1]=data[*pos]; *pos+=1;
461 buf[2]=data[*pos]; *pos+=1;
462 MIDI_MESSAGE3(buf[0],buf[1],buf[2]);
466 buf[1]=data[*pos]; *pos+=1;
467 MIDI_MESSAGE3(buf[0],0,buf[1]);
479 switch((buf[0] & 0xf0))
486 stop_note((int) channel, (int) buf[1], (int) buf[2]);
495 stop_note((int) channel, (int) buf[1], (int) buf[2]);
499 start_note((int) channel, (int) buf[1], (int) buf[2]);
507 set_key_pressure((int) channel, (int) buf[1], (int) buf[2]);
514 set_control((int) channel, (int) buf[1], (int) buf[2]);
521 set_pitchbend((int) channel, (int) ((buf[2] << 7) + buf[1]));
526 set_program((int) channel, (int) buf[1] );
531 set_chn_pressure((int) channel, (int) buf[1]);
542 void send_ipc(char *message)
544 printf ("sendipc %s\n", message);//##########3
547 ipc_queue_id=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's',
549 snd=malloc(sizeof(long) + 32);
551 player_thread=SDL_CreateThread((int (*)(void *))play_hmi, NULL);
552 // player_pid = play_hmi();
554 if (strlen(message) < 16)
556 sprintf(snd->mtext,"%s",message);
557 msgsnd(ipc_queue_id,snd,16,0);
564 // kill(player_pid,SIGTERM);
565 msgctl( ipc_queue_id, IPC_RMID, 0);
571 int do_ipc(int qid, struct msgbuf *buf, int flags)
575 float last_volume = volume;
578 ipc_read = msgrcv(qid,buf,16,0,flags | MSG_NOERROR);
585 perror("IPC trouble");
590 printf ("do_ipc %s\n", buf->mtext);//##########3
591 switch (buf->mtext[0])
594 volume = (double)(atof(buf->mtext + 1) / 128.0);
595 printf("vol %f->%f\n", last_volume, volume);
596 if (last_volume <= 0 && volume > 0)
598 buf->mtext[0] = 'p'; // start playing again if volume raised above 0
599 strcpy(buf->mtext + 1, digi_last_midi_song);
600 // fall through to case 'p'
602 else if (last_volume > 0 && volume <= 0)
604 strcpy(buf->mtext, "s"); // stop playing if volume reduced to 0
613 strcpy(digi_last_midi_song, buf->mtext + 1);
615 fptr = cfopen((buf->mtext + 1), "rb");
619 l = cfilelength(fptr);
620 data=realloc(data,(size_t) l);
621 cfread(data, l, 1, fptr);
623 printf ("good. fpr=%p l=%i data=%p\n", fptr, l, data);//##########3
628 strcpy(buf->mtext, "s"); // not playing, thus "stop".
636 // SDL_KillThread(player_thread);
639 //printf("do_ipc %s ret %i\n", buf->mtext, ipc_read); // ##########3
645 void play_hmi (void * arg)
662 printf ("play_hmi\n");//#########
679 // signal(SIGTERM, my_quit);
680 rcv=malloc(sizeof(long) + 16);
685 qid=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's', 0660);
693 ipc_read=do_ipc(qid,rcv,0);
695 while(rcv->mtext[0] != 'p');
704 t_info = malloc(sizeof(Track_info)*n_chunks);
709 for(i=0;i<n_chunks;i++)
711 t_info[i].position = pos + 12;
712 t_info[i].status = PLAYING;
713 t_info[i].time = get_dtime(data,&t_info[i].position);
714 pos += (( (0xff & data[pos + 5]) << 8 ) + (0xff & data[pos + 4]));
727 if (t_info[i].status == PLAYING)
731 while((low_chunk <=0) && (i<n_chunks));
736 low_dtime = t_info[low_chunk].time;
738 for(i=1;i<n_chunks;i++)
740 if ((t_info[i].time < low_dtime) &&
741 (t_info[i].status == PLAYING))
743 low_dtime = t_info[i].time;
749 printf("Serious warning: d_time negative!!!!!!\n");
751 csec = 0.86 * low_dtime;
753 //flush sequencer buffer after 20 events
756 ioctl(seqfd, SNDCTL_SEQ_SYNC);
766 t_info[low_chunk].status = do_track_event(data,&t_info[low_chunk].position);
768 if (t_info[low_chunk].status == 3)
770 printf("Error playing data in chunk %d\n",low_chunk);
771 t_info[low_chunk].status = STOPPED;
774 if (t_info[low_chunk].status == PLAYING)
775 t_info[low_chunk].time += get_dtime(data,&t_info[low_chunk].position);
777 //Check if the song has reached the end
778 stop = t_info[0].status;
779 for(i=1;i<n_chunks;i++)
780 stop &= t_info[i].status;
782 if((do_ipc(qid,rcv,IPC_NOWAIT) > 0) && (rcv->mtext[0]=='p'))
785 t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
798 ipc_read=do_ipc(qid,rcv,0);
800 while(rcv->mtext[0] != 'p');
803 t_info = realloc(t_info,sizeof(Track_info)*n_chunks);
814 void digi_play_midi_song(char *filename, char *melodic_bank, char *drum_bank, int loop)
816 if (FindArg("-nomusic"))
824 sprintf(buf, "p%s", filename);
829 void digi_set_midi_volume( int mvolume ) {
831 if(FindArg("-nomusic"))
834 sprintf(buf,"v%i",mvolume);