This is midi_threads.c in view mode; [Download] [Up]
#include "midi_threads.h" #include <sys/prctl.h> #include <stdio.h> std_task_block *my; void **taskblocks; volatile int kids = 0; volatile int ntasks = 1; int maxtasks = 10; BOOL threads_initialized = NO; void init_std_sigaction(struct sigaction *act,int sig,HANDLER(handler)) { act->sa_handler = handler; act->sa_mask = sigmask(sig); act->sa_flags = 0; } int std_sigaction(int sig,HANDLER(handler),struct sigaction *act) { init_std_sigaction(act,sig,handler); return sigaction(sig, act, NULL); } void init_threads() { if (threads_initialized == NO) { threads_initialized = YES; taskblocks = (void **) malloc(maxtasks * sizeof(void *)); my = STB_new(); taskblocks[0] = (void *) my; } } tid_t create_task (char *name, void (*entry)(), void *arg,int sched) { tid_t result; void **newblock; if (ntasks == maxtasks) { maxtasks += 3; newblock = realloc(newblock, maxtasks * sizeof(void *)); if (newblock) taskblocks = (void **) newblock; else { fprintf(stderr,"create_task: Could not allocate memory to keep track of task arguments\n"); return -1; } } result = taskcreate(name,entry,arg,0); if (result == -1) fprintf(stderr,"Could not create a new task %s\n",name); else { kids++; ntasks++; taskblocks[ntasks] = arg; #ifdef DEBUG fprintf(stderr,"New task %s: %d\n",name,result); #endif } return result; } midi_daemon_block * MTB_new(MIPortedQueue *q) { midi_daemon_block *result; int i; result = (midi_daemon_block *) malloc(sizeof(midi_daemon_block)); result->queue = q; for (i=0; i<8; i++) result->smpteok[i] = NO; result->semops = (struct sembuf *) malloc(sizeof(struct sembuf)); result->actions = SASnew(1); return result; } HANDLER_RETURN_TYPE sighup_handler (int sig) { exit(0); } BOOL send_midi(MIevent_queue *q,MIevent *the_event) { #ifdef DEBUG0 fprintf(stderr, "Enqueuing MIDI data"); #endif MIQlock(q); MIQpush(q,the_event); MIQunlock(q); request(SEND_MIDI); } void midi_sender_process_request(midi_daemon_block *my) { /* register BOOL must_close; register BOOL *to_close; register int i; */ MIQlock(my->queue->queue); my->event = MIQhead(my->queue->queue); MIQunlock(my->queue->queue); if (my->event != (MIevent *) NULL) { #ifdef DEBUG0 fprintf(stderr,"Sending MIDI data:\n"); #endif #ifdef SENDER_PRINT lock(PRINTMIDI); myMIDIPrintEvent(stderr, my->event); unlock(PRINTMIDI); #endif for(my->i=0;my->i<my->queue->nports;my->i++) { #ifdef DEBUG fprintf(stderr,"In Sender loop\n"); fprintf(stderr,"On MIMultiPort: %ld\n",my->queue->midi_port[my->i]); fprintf(stderr,"On MIDI Port: %ld\n",my->queue->midi_port[my->i]->port); #endif FD_ZERO(&(my->fdset)); FD_SET(my->queue->midi_fd[my->i],&(my->fdset)); #ifdef DEBUG fprintf(stderr,"MIDI Sender going to select...\n"); #endif while(select(FD_SETSIZE,(fd_set *) 0,&(my->fdset),(fd_set *) 0, (struct timeval *) 0) == -1) fprintf(stderr,"MIDI Sender: Select failure...\n"); #ifdef DEBUG fprintf(stderr,"Out of select...\n"); #endif if (MIsend(my->queue->midi_port[my->i]->port,my->event,1) == -1) { perror("MIsend"); suicide(1); } } /*MIQunlock(my->queue->queue);*/ #ifdef DEBUG0 fprintf(stderr,"Sent MIDI data\n"); #endif MIQlock(my->queue->queue); MIQpopfree(my->queue->queue); MIQunlock(my->queue->queue); } else { MIQlock(my->queue->queue); my->must_close = MIQclosed(my->queue->queue); if (my->must_close) { my->to_close = (BOOL *) malloc(sizeof(BOOL) * my->queue->nports); for(my->i=0;my->i<my->queue->nports;my->i++) my->to_close[my->i] = YES; while(my->must_close) { FD_ZERO(&(my->fdset)); for(my->i=0;my->i<my->queue->nports;my->i++) if (my->to_close[my->i]) FD_SET(my->queue->midi_fd[my->i],&(my->fdset)); my->nready = select(FD_SETSIZE,(fd_set *) 0,&(my->fdset),(fd_set *) 0, (struct timeval *) 0); #ifdef DEBUG fprintf(stderr,"Out of select...\n"); #endif if (my->nready == -1) { perror("Select failure\n"); suicide(-1); } my->must_close = NO; for(my->i=0;my->i<my->queue->nports;my->i++) if (my->to_close[my->i]) if (FD_ISSET(my->queue->midi_fd[my->i],&(my->fdset))) { MImulti_close(my->queue->midi_port[my->i]); my->to_close[my->i] = NO; } else my->must_close = YES; } free(my->to_close); MIQclose_done(my->queue->queue); MIQunlock(my->queue->queue); free(my); /* Remember that the queue and events stay around... */ exit(0); } MIQunlock(my->queue->queue); } } void midi_sender(midi_daemon_block *my) { prctl(PR_TERMCHILD); my->act = SASreserve(my->actions); std_sigaction(SIGHUP,sighup_handler,my->act); #ifdef DEBUG fprintf(stderr,"New MIDI Sender: %d\n",getpid()); #endif while (1) { wait_request(SEND_MIDI); midi_sender_process_request(my); } } void midi_receiver(midi_daemon_block *my) { /* int register i; */ prctl(PR_TERMCHILD); my->act = SASreserve(my->actions); std_sigaction(SIGHUP,sighup_handler,my->act); #ifdef DEBUG fprintf(stderr,"New MIDI Receiver: %d\n",getpid()); #endif while (1) { FD_ZERO(&(my->fdset)); for(my->i=0;my->i<my->queue->nports;my->i++) { FD_SET(my->queue->midi_fd[my->i],&(my->fdset)); } #ifdef DEBUG fprintf(stderr,"MIDI Receiver going to select...\n"); #endif my->nready = select(FD_SETSIZE,&(my->fdset),(fd_set *) 0,(fd_set *) 0, (struct timeval *) 0); #ifdef DEBUG fprintf(stderr,"Out of select...\n"); #endif if (my->nready == -1) { perror("Select failure\n"); suicide(-1); } for(my->i=0;my->i<my->queue->nports;my->i++) if (FD_ISSET(my->queue->midi_fd[my->i],&(my->fdset))) { #ifdef DEBUG fprintf(stderr,"Got MIDI!\n"); #endif MIQlock(my->queue->queue); my->event = MIQreserve(my->queue->queue); MIQunlock(my->queue->queue); my->result = MIreceive(my->queue->midi_port[my->i]->port,my->event,1); if (my->result < 0) { perror("Error while receiving MIDI\n"); suicide(-3); } MIQlock(my->queue->queue); MIQpush(my->queue->queue,my->event); MIQunlock(my->queue->queue); midi_receive_callback(my); } } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.