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.