/* $Id: hmiplay.c,v 1.1.1.1 2006/03/17 19:40:45 zicodxx Exp $ */ /* * HMI midi playing routines by Jani Frilander * * External device support by Patrick McCarthy * * Ported to d1x/sdl_threads by Matthew Mueller * */ #include #include #include #include #include #include #include #include #include #include #include #define __USE_GNU //in recent glibc versions msgbuf is only defined if you have __USE_GNU defined #include #include "music.h" #include "cfile.h" #include "args.h" #include //#define WANT_AWE32 1 #ifdef WANT_AWE32 #include #endif //#define WANT_MPU401 1 #ifdef WANT_MPU401 unsigned char reset_genmidi[5] = { 0x7e, 0x7f, 0x09, 0x01, 0xf7 }; #define MIDI_RESET { \ SEQ_MIDIOUT(synth_dev,MIDI_SYSTEM_PREFIX); \ SEQ_MIDIOUT(synth_dev,reset_genmidi[0]); \ SEQ_MIDIOUT(synth_dev,reset_genmidi[1]); \ SEQ_MIDIOUT(synth_dev,reset_genmidi[2]); \ SEQ_MIDIOUT(synth_dev,reset_genmidi[3]); \ SEQ_MIDIOUT(synth_dev,reset_genmidi[4]); \ } #define MIDI_MESSAGE2(a,b) { \ SEQ_MIDIOUT(synth_dev,a); \ SEQ_MIDIOUT(synth_dev,b); \ } #define MIDI_MESSAGE3(a,b,c) { \ SEQ_MIDIOUT(synth_dev,a); \ SEQ_MIDIOUT(synth_dev,b); \ SEQ_MIDIOUT(synth_dev,c); \ } #endif SEQ_DEFINEBUF(1024); int drumflag = 1<<9; int seqfd; int synth_dev; int program[16]; int stop; double volume=1; int rephmi; int ipc_queue_id = -1; struct msgbuf *snd; SDL_Thread *player_thread=NULL; Voice_info *voices; unsigned char *data=NULL; char digi_last_midi_song[16] = ""; struct synth_info card_info; void seqbuf_dump() { if (_seqbufptr) { if (write(seqfd, _seqbuf, _seqbufptr) == -1) { perror ("Error writing sequencer device"); SDL_KillThread(player_thread); } } _seqbufptr = 0; } void my_quit() { // printf("goodbye\n");//##### // exit(0); } int seq_init() { int nrmidis,nrsynths,i; if ((seqfd = open(SEQ_DEV, O_WRONLY, 0)) < 0) { perror ("Error opening sequencer device"); return (-1); } if (ioctl(seqfd, SNDCTL_SEQ_NRSYNTHS, &nrsynths) == -1) { perror ("There is no soundcard"); return (-1); } if (ioctl(seqfd, SNDCTL_SEQ_NRMIDIS, &nrmidis) == -1) { perror ("There is no soundcard"); return (-1); } if(nrsynths < 1 && nrmidis < 1) { printf("No synth or midi device!\n"); return -1; } synth_dev = 0; //Check if we have wavetable synth device for (i=0; i < nrsynths; i++) { card_info.device = i; if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1) { perror("cannot get info on soundcard"); return (-1); } if (card_info.synth_type == SYNTH_TYPE_SAMPLE) { synth_dev = i; break; } } #ifdef WANT_AWE32 for (i=0; i < nrsynths; i++) { card_info.device = i; if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1) { perror("cannot get info on soundcard"); return (-1); } if (card_info.synth_type==SYNTH_TYPE_SAMPLE &&card_info.synth_subtype==SAMPLE_TYPE_AWE32) { synth_dev = i; break; } } #endif #ifdef WANT_MPU401 for (i=0; i < nrmidis; i++) { struct midi_info cinfo; cinfo.device = i; if (ioctl(seqfd, SNDCTL_MIDI_INFO, &cinfo) == -1) { perror("cannot get info on soundcard"); return (-1); } // Just take first available for now. card_info.synth_type=SYNTH_TYPE_MIDI; card_info.device=i; synth_dev=i; break; } if (card_info.synth_type!=SYNTH_TYPE_MIDI) { #endif card_info.device = synth_dev; if (ioctl(seqfd, SNDCTL_SYNTH_INFO, &card_info) == -1) { perror("cannot get info on soundcard"); return (-1); } #ifdef WANT_MPU401 } if (card_info.synth_type==SYNTH_TYPE_MIDI) { MIDI_RESET; SEQ_DUMPBUF(); } else #endif #ifdef WANT_AWE32 if (card_info.synth_type == SYNTH_TYPE_SAMPLE && card_info.synth_subtype == SAMPLE_TYPE_AWE32) { AWE_SET_CHANNEL_MODE(synth_dev,1); AWE_DRUM_CHANNELS(synth_dev,drumflag); } else #endif { voices = malloc(sizeof(Voice_info)*card_info.nr_voices); for (i=0;imtype=1; player_thread=SDL_CreateThread((int (*)(void *))play_hmi, NULL); } if (strlen(message) < 16) { sprintf(snd->mtext,"%s",message); msgsnd(ipc_queue_id,snd,16,0); } } void kill_ipc() { msgctl( ipc_queue_id, IPC_RMID, 0); free(snd); ipc_queue_id = -1; } int do_ipc(int qid, struct msgbuf *buf, int flags) { int ipc_read; CFILE *fptr = NULL; float last_volume = volume; int l=0; ipc_read = msgrcv(qid,buf,16,0,flags | MSG_NOERROR); switch (ipc_read) { case -1: if (errno == ENOMSG) break; perror("IPC trouble"); break; case 0: break; default: printf ("do_ipc %s\n", buf->mtext);//##########3 switch (buf->mtext[0]) { case 'v': volume = (double)(atof(buf->mtext + 1) / 128.0); printf("vol %f->%f\n", last_volume, volume); if (last_volume <= 0 && volume > 0) { buf->mtext[0] = 'p'; // start playing again if volume raised above 0 strcpy(buf->mtext + 1, digi_last_midi_song); // fall through to case 'p' } else if (last_volume > 0 && volume <= 0) { strcpy(buf->mtext, "s"); // stop playing if volume reduced to 0 stop = 2; break; } else break; case 'p': if (buf->mtext[1]) { strcpy(digi_last_midi_song, buf->mtext + 1); if (volume > 0) fptr = cfopen((buf->mtext + 1), "rb"); } if(fptr != NULL) { l = cfilelength(fptr); data=realloc(data,(size_t) l); cfread(data, l, 1, fptr); cfclose(fptr); printf ("good. fpr=%p l=%i data=%p\n", fptr, l, data);//##########3 stop = 0; } else { strcpy(buf->mtext, "s"); // not playing, thus "stop". stop = 2; } break; case 's': stop = 2; break; case 'q': break; } } return ipc_read; } void play_hmi (void * arg) { int i; int pos = 0x308; int n_chunks = 0; int low_dtime; int low_chunk; int csec, lcsec; int qid; int ipc_read = 0; int k=0; char t1; struct msgbuf *rcv; Track_info *t_info; printf ("play_hmi\n"); stop = 0; ipc_read=0; rcv=malloc(sizeof(long) + 16); rcv->mtype=1; rcv->mtext[0]='0'; qid=msgget ((key_t) ('l'<<24) | ('d'<<16) | ('e'<<8) | 's', 0660); if(qid == -1) { return; } do { ipc_read=do_ipc(qid,rcv,0); } while(rcv->mtext[0] != 'p'); stop=0; rcv->mtext[0] = '0'; seq_init(); n_chunks=data[0x30]; t_info = malloc(sizeof(Track_info)*n_chunks); while(1) { for(i=0;i 1950) send_ipc("s"); if((do_ipc(qid,rcv,IPC_NOWAIT) > 0) && (rcv->mtext[0]=='p')) { n_chunks=data[0x30]; t_info = realloc(t_info,sizeof(Track_info)*n_chunks); stop = 1; rcv->mtext[0] = '0'; stop_all(); } } while(!stop); SEQ_STOP_TIMER(); if( stop == 2) { stop_all(); do { ipc_read=do_ipc(qid,rcv,0); } while(rcv->mtext[0] != 'p'); rcv->mtext[0] = '0'; n_chunks=data[0x30]; t_info = realloc(t_info,sizeof(Track_info)*n_chunks); stop = 0; } pos=0x308; } free(data); free(t_info); free(rcv); } void digi_play_midi_song(char *filename, char *melodic_bank, char *drum_bank, int loop) { if (FindArg("-nomusic")) return; if (!filename) send_ipc("p"); else { char buf[128]; sprintf(buf, "p%s", filename); send_ipc(buf); } rephmi=loop; } void digi_set_midi_volume( int mvolume ) { char buf[128]; if(FindArg("-nomusic")) return; sprintf(buf,"v%i",mvolume); send_ipc(buf); }