ftp.nice.ch/pub/next/unix/music/cm.sd.tar.gz#/midi/sgi/midi_threads.c

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.