Ejemplo n.º 1
0
static void
RemPlayers ( struct List *list,
             struct AHIDevUnit *iounit,
             struct AHIBase *AHIBase )
{
  struct AHIRequest *ioreq, *node;

  node = (struct AHIRequest *) list->lh_Head;
  while(node->ahir_Std.io_Message.mn_Node.ln_Succ)
  {
    ioreq = node;
    node = (struct AHIRequest *) node->ahir_Std.io_Message.mn_Node.ln_Succ;

    if(ioreq->ahir_Std.io_Command == AHICMD_WRITTEN)
    {
      Remove((struct Node *) ioreq);

      if(ioreq->ahir_Link)
      {
        // Move the attached one to the list
        Remove((struct Node *) ioreq->ahir_Link);
        GetExtras(ioreq->ahir_Link)->Channel = GetExtras(ioreq)->Channel;
        Enqueue(list, (struct Node *) ioreq->ahir_Link);
        // We have to go through the whole procedure again, in case
        // the child is finished, too.
        node = (struct AHIRequest *) list->lh_Head;
      }

      ioreq->ahir_Std.io_Error = AHIE_OK;
      ioreq->ahir_Std.io_Command = CMD_WRITE;
      ioreq->ahir_Std.io_Actual = ioreq->ahir_Std.io_Length
                                * AHI_SampleFrameSize(ioreq->ahir_Type);
      TermIO(ioreq, AHIBase);
    }
  }
}
Ejemplo n.º 2
0
VOID DispatcherThread(struct MOSWriteHandle* h)
{
	struct MsgPort*	  ahi_port = NULL;
	struct AHIRequest*  ahi_request = NULL;
	struct AHIAudioCtrl*ahi_control = NULL;
	BYTE*					  sample_bufs = NULL;
	ULONG					  sample_size = 2;
	BYTE					  ahi_device = -1;
	LONG					  switch_sig_bit = -1;
	LONG				     locked_buf = -1;
	struct DispatcherStartupMsg *startup_msg;
	struct DispatcherInitReport *init_report;
	struct MsgPort     *task_port = NULL;
	struct ExecBase *SysBase = *(struct ExecBase **) 4;

	init_report = (struct DispatcherInitReport *) AllocVec(sizeof (struct DispatcherInitReport), MEMF_PUBLIC | MEMF_CLEAR);
	if (init_report == NULL)
		return;

	NewGetTaskAttrsA(NULL, &task_port, sizeof (task_port), TASKINFOTYPE_TASKMSGPORT, NULL);
	NewGetTaskAttrsA(NULL, &startup_msg, sizeof (startup_msg), TASKINFOTYPE_STARTUPMSG, NULL);

	if (task_port == NULL || startup_msg == NULL)
	{
		FreeVec(init_report);
		return;
	}

	startup_msg->dsm_Result = -1;
	switch_sig_bit = AllocSignal(-1);

	if (switch_sig_bit != -1 && (ahi_port = CreateMsgPort()))
	{
		if ((ahi_request = (struct AHIRequest *) CreateIORequest(ahi_port, sizeof (struct AHIRequest))))
		{
			ahi_request->ahir_Version = 4;
			if ((ahi_device = OpenDevice(AHINAME, AHI_NO_UNIT, (struct IORequest *) ahi_request, 0)) == 0)
			{
				AHIBase = (struct Library*) ahi_request->ahir_Std.io_Device;

				/*dprintf("AllocAudio with %d channels, %d sounds and frequency %d\n", h->wh_Channels, AHI_BUFFERS, h->wh_Frequency);*/
				ahi_control = AHI_AllocAudio(AHIA_AudioID,   AHI_DEFAULT_ID,
													  AHIA_Channels,  h->wh_Channels,
													  AHIA_Sounds,	   AHI_BUFFERS,
													  AHIA_MixFreq,   h->wh_Frequency,
													  AHIA_SoundFunc, (ULONG) &OpenAL_SoundHook,
													  AHIA_UserData,	(ULONG) h,
													  TAG_DONE
													 );
				if (ahi_control)
				{
					ULONG buf_size;
					ULONG samples, fs, fm;

					AHI_GetAudioAttrs(AHI_INVALID_ID, ahi_control, AHIDB_MaxPlaySamples, (ULONG) &samples, TAG_DONE);
					AHI_ControlAudio(ahi_control, AHIC_MixFreq_Query, (ULONG) &fm, TAG_DONE);
					fs = h->wh_Frequency;

					buf_size = samples*fs/fm;
					/*dprintf("OpenAL: Minimum buffer size is %d, requested buffer size is %d\n", buf_size, h->wh_BufSize);*/
					if (buf_size > h->wh_BufSize)
						h->wh_BufSize = buf_size;

					sample_bufs = AllocVec(h->wh_BufSize*AHI_BUFFERS, MEMF_PUBLIC | MEMF_CLEAR);
					if (sample_bufs)
					{
						struct Buffer* bn;
						ULONG	buf;
						LONG err = AHIE_OK;

						sample_size = AHI_SampleFrameSize(h->wh_SampleType);

						for (buf = 0; buf < AHI_BUFFERS && err == AHIE_OK; buf++)
						{
							bn = &h->wh_Buffers[buf];
							bn->bn_SampleNo = buf;
							bn->bn_SampleInfo.ahisi_Type = h->wh_SampleType;
							bn->bn_SampleInfo.ahisi_Address = &sample_bufs[buf*h->wh_BufSize];
							bn->bn_SampleInfo.ahisi_Length = h->wh_BufSize/sample_size;
							InitSemaphore(&bn->bn_Semaphore);
							bn->bn_FillSize = 0;
							err = AHI_LoadSound(buf, AHIST_DYNAMICSAMPLE, &bn->bn_SampleInfo, ahi_control);
						}

						if (err != AHIE_OK)
						{
							FreeVec(sample_bufs);
							sample_bufs = NULL;
						}
					}
				}
			}
		}
	}

	if (sample_bufs)
	{
		BOOL dispatcher_running = TRUE;
		ULONG signal_mask = 1 << task_port->mp_SigBit;
		ULONG signal_set;
		struct MsgPort *reply_port;

		reply_port = CreateMsgPort();
		if (reply_port == NULL)
			reply_port = task_port;

		if (startup_msg)
			startup_msg->dsm_Result = 0;
		init_report->dir_Msg.mn_Node.ln_Type = NT_MESSAGE;
		init_report->dir_Msg.mn_ReplyPort = reply_port;
		init_report->dir_Msg.mn_Length = sizeof (struct DispatcherInitReport);
		AHI_ControlAudio(ahi_control, AHIC_MixFreq_Query, (ULONG) &init_report->dir_RealFrequency, TAG_DONE);
		init_report->dir_RealBufSize = h->wh_BufSize;
		PutMsg(startup_msg->dsm_Msg.mn_ReplyPort, (struct Message*) init_report);
		WaitPort(reply_port);
		GetMsg(reply_port);
		FreeVec(init_report);
		init_report = NULL;

		if (reply_port != task_port)
			DeleteMsgPort(reply_port);

		h->wh_SwitchSignal = 1UL << switch_sig_bit;
		h->wh_ReadBuf = 0;
		while (dispatcher_running)
		{
			signal_set = Wait(signal_mask);

			if (signal_set & (1 << task_port->mp_SigBit))
			{
				struct DispatcherMsg *msg;

				while ((msg = (struct DispatcherMsg *) GetMsg(task_port)))
				{
					if (msg->dm_Msg.mn_Length == sizeof (struct DispatcherMsg))
					{
						switch (msg->dm_Command)
						{
							case DISPATCHER_CMD_START:
							{
								/*
								 * First buffer has been filled and we were previously not
								 * playing any sound yet
								 */
								ULONG chan;
								ULONG cur_buf;

								cur_buf = h->wh_ReadBuf;
								AHI_ControlAudio(ahi_control, AHIC_Play, TRUE, TAG_DONE);

								/* Lock first audio buffer */
								ObtainSemaphore(&h->wh_Buffers[cur_buf].bn_Semaphore);
								locked_buf = cur_buf;

								for (chan = 0; chan < h->wh_Channels; chan++)
								{
									AHI_SetFreq(chan, h->wh_Frequency, ahi_control, AHISF_IMM);
									AHI_SetVol(chan, 0x10000L, -0x8000L, ahi_control, AHISF_IMM);
									AHI_SetSound(chan, cur_buf, 0, 0, ahi_control, AHISF_IMM);
								}

								Wait(1 << switch_sig_bit);
								cur_buf++;
								if (cur_buf >= AHI_BUFFERS)
									cur_buf = 0;
								h->wh_ReadBuf = cur_buf;

								signal_mask |= 1UL << switch_sig_bit;
								break;
							}

							case DISPATCHER_CMD_PAUSE:
							case DISPATCHER_CMD_RESUME:
								AHI_ControlAudio(ahi_control, AHIC_Play, msg->dm_Command == DISPATCHER_CMD_RESUME, TAG_DONE);
								break;

							case DISPATCHER_CMD_BREAK:
								/* Break requests and quit */
								/*dprintf("Dispatcher thread: break requested\n");*/
								AHI_ControlAudio(ahi_control, AHIC_Play, FALSE, TAG_DONE);
								dispatcher_running = FALSE;
								break;
						}
					}

					ReplyMsg((struct Message *) msg);
				}
			}

			if (signal_set & (1UL << switch_sig_bit))
			{
				/* Switch to next read buffer */
				ULONG cur_buf;

				cur_buf = h->wh_ReadBuf;
				/*dprintf("Dispatcher thread: buffer switch requested. Releasing lock on %d, locking %d\n", locked_buf, cur_buf);*/
				memset(h->wh_Buffers[locked_buf].bn_SampleInfo.ahisi_Address, 0, h->wh_BufSize);
				ReleaseSemaphore(&h->wh_Buffers[locked_buf].bn_Semaphore);
				cur_buf++;
				if (cur_buf >= AHI_BUFFERS)
					cur_buf = 0;
				ObtainSemaphore(&h->wh_Buffers[cur_buf].bn_Semaphore);
				locked_buf = cur_buf;
				h->wh_ReadBuf = cur_buf;
				/*dprintf("Dispatcher thread: buffer switch done\n");*/
			}
		}
	}

	/* Cleanup */
	if (init_report)
	{
		FreeVec(init_report);
		init_report = NULL;
	}

	if (locked_buf != -1)
	{
		ReleaseSemaphore(&h->wh_Buffers[locked_buf].bn_Semaphore);
		locked_buf = -1;
	}

	if (switch_sig_bit != -1)
	{
		FreeSignal(switch_sig_bit);
		switch_sig_bit = -1;
	}

	if (ahi_control)
	{
		AHI_FreeAudio(ahi_control);  /* Also unloads all sounds */
		ahi_control = NULL;
	}

	if (ahi_request)
	{
		CloseDevice((struct IORequest*) ahi_request);
		DeleteIORequest((struct IORequest*) ahi_request);
		ahi_request = NULL;
		ahi_device = -1;
	}

	if (sample_bufs)
	{
		FreeVec(sample_bufs);
		sample_bufs = NULL;
	}

	if (ahi_port)
	{
		DeleteMsgPort(ahi_port);
		ahi_port = NULL;
	}
}
Ejemplo n.º 3
0
static void
Slave( struct ExecBase* SysBase )
{
  struct AHIAudioCtrlDrv* AudioCtrl;
  struct DriverBase*      AHIsubBase;
  struct DeviceBase* DeviceBase;
  BOOL                    running;
  ULONG                   signals;

  AudioCtrl  = (struct AHIAudioCtrlDrv*) FindTask( NULL )->tc_UserData;
  AHIsubBase = (struct DriverBase*) dd->ahisubbase;
  DeviceBase = (struct DeviceBase*) AHIsubBase;

  dd->slavesignal = AllocSignal( -1 );

  if( dd->slavesignal != -1 )
  {
    struct MsgPort*    ahi_mp           = NULL;
    struct AHIRequest* ahi_iorequest    = NULL;
    APTR               ahi_iocopy       = NULL;
    BYTE               ahi_device       = -1;

    struct AHIRequest* ahi_io[ 2 ]      = { NULL,  NULL };
    BOOL               ahi_io_used[ 2 ] = { FALSE, FALSE };

    ULONG              frame_length     = 0;

    ahi_mp = CreateMsgPort();

    if( ahi_mp != NULL )
    {
      ahi_iorequest = CreateIORequest( ahi_mp, sizeof( struct AHIRequest ) );

      if( ahi_iorequest != NULL )
      {
	ahi_iorequest->ahir_Version = 4;

	ahi_device = OpenDevice( AHINAME, dd->unit,
				 (struct IORequest*) ahi_iorequest, 0 );

	if( ahi_device == 0 )
	{
	  struct Library* AHIBase = (struct Library*) ahi_iorequest->ahir_Std.io_Device;

	  ahi_iocopy = AllocVec( sizeof( *ahi_iorequest ), MEMF_ANY );

	  if( ahi_iocopy != NULL )
	  {
	    bcopy( ahi_iorequest, ahi_iocopy, sizeof( *ahi_iorequest ) );

	    ahi_io[ 0 ] = ahi_iorequest;
	    ahi_io[ 1 ] = ahi_iocopy;
    
	    // Everything set up. Tell Master we're alive and healthy.

	    Signal( (struct Task*) dd->mastertask,
		    1L << dd->mastersignal );

	    running = TRUE;

	    // The main playback loop follow

	    while( running )
	    {
	      int skip_mix;
	      APTR tmp_buff;
	      struct AHIRequest* tmp_io;
	      
	      if( ahi_io_used[ 0 ] )
	      {
		LONG  err;
		ULONG mask = ( SIGBREAKF_CTRL_C |
			       (1L << dd->slavesignal) |
			       (1L << ahi_mp->mp_SigBit) );
	      
		signals = Wait( mask );

		if( signals & ( SIGBREAKF_CTRL_C |
				(1L << dd->slavesignal) ) ) 
		{
		  running = FALSE;
		  break;
		}

		err = WaitIO( (struct IORequest*) ahi_io[ 0 ] );

		if( err != 0 )
		{
		  KPrintF( DRIVER ": AHI device error %ld\n", err );
//		  running = FALSE;
		  break;
		}
	      }

	      skip_mix = CallHookPkt( AudioCtrl->ahiac_PreTimerFunc,
				      (Object*) AudioCtrl, 0 );

	      CallHookPkt( AudioCtrl->ahiac_PlayerFunc, AudioCtrl, NULL );
		
	      if( ! skip_mix )
	      {
		CallHookPkt( AudioCtrl->ahiac_MixerFunc, AudioCtrl,
			     dd->mixbuffers[ 0 ] );
	      }
		
	      CallHookPkt( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 );

	      if( frame_length == 0 )
	      {
		frame_length = AHI_SampleFrameSize( AudioCtrl->ahiac_BuffType );
	      }
	      
	      ahi_io[ 0 ]->ahir_Std.io_Command = CMD_WRITE;
	      ahi_io[ 0 ]->ahir_Std.io_Data    = dd->mixbuffers[ 0 ];
	      ahi_io[ 0 ]->ahir_Std.io_Length  = ( AudioCtrl->ahiac_BuffSamples *
						   frame_length );
	      ahi_io[ 0 ]->ahir_Std.io_Offset  = 0;
	      ahi_io[ 0 ]->ahir_Frequency      = AudioCtrl->ahiac_MixFreq;
	      ahi_io[ 0 ]->ahir_Type           = AudioCtrl->ahiac_BuffType;
	      ahi_io[ 0 ]->ahir_Volume         = 0x10000;
	      ahi_io[ 0 ]->ahir_Position       = 0x08000;
	      ahi_io[ 0 ]->ahir_Link           = ( ahi_io_used[ 1 ] ?
						   ahi_io[ 1 ] : NULL );

	      SendIO( (struct IORequest*) ahi_io[ 0 ] );
    
	      tmp_io = ahi_io[ 0 ];
	      ahi_io[ 0 ] = ahi_io[ 1 ];
	      ahi_io[ 1 ] = tmp_io;

	      tmp_buff = dd->mixbuffers[ 0 ];
	      dd->mixbuffers[ 0 ] = dd->mixbuffers[ 1 ];
	      dd->mixbuffers[ 1 ] = tmp_buff;
	      
	      ahi_io_used[ 0 ] = ahi_io_used[ 1 ];
	      ahi_io_used[ 1 ] = TRUE;
	    }

	    
	    if( ahi_io_used[ 0 ] )
	    {
	      AbortIO( (struct IORequest*) ahi_io[ 0 ] );
	      WaitIO( (struct IORequest*) ahi_io[ 0 ] );
	    }

	    if( ahi_io_used[ 1 ] )
	    {
	      AbortIO( (struct IORequest*) ahi_io[ 1 ] );
	      WaitIO( (struct IORequest*) ahi_io[ 1 ] );
	    }
	    
	    FreeVec( ahi_iocopy );
	  }

	  CloseDevice( (struct IORequest*) ahi_iorequest );
	}

	DeleteIORequest( (struct IORequest*) ahi_iorequest );
      }

      DeleteMsgPort( ahi_mp );
    }
  }

  FreeSignal( dd->slavesignal );
  dd->slavesignal = -1;

  Forbid();

  // Tell the Master we're dying

  Signal( (struct Task*) dd->mastertask,
          1L << dd->mastersignal );

  dd->slavetask = NULL;

  // Multitaking will resume when we are dead.
}
Ejemplo n.º 4
0
static void 
FillReadBuffer ( struct AHIRequest *ioreq,
                 struct AHIDevUnit *iounit,
                 struct AHIBase *AHIBase )
{
  ULONG length,length2;
  APTR  oldaddress;
  BOOL  remove;

  if(iounit->ValidRecord) // Make sure we have a valid source buffer
  {
    oldaddress = ioreq->ahir_Std.io_Data;

    length = (ioreq->ahir_Std.io_Length - ioreq->ahir_Std.io_Actual)
             / AHI_SampleFrameSize(ioreq->ahir_Type);

    length2 = (iounit->RecordSize - ioreq->ahir_Std.io_Offset)
              / AHI_SampleFrameSize(AHIST_S16S);
    length2 = MultFixed(length2, (Fixed) ioreq->ahir_Frequency);

    if(length <= length2)
    {
      remove=TRUE;
    }
    else
    {
      length = length2;
      remove = FALSE;
    }

    switch (ioreq->ahir_Type)
    {
#if 0
      case AHIST_M8S:
        RecM8S(length,ioreq->ahir_Frequency,
            iounit->RecordBuffer,
            &ioreq->ahir_Std.io_Offset,
            &ioreq->ahir_Std.io_Data);
        break;
      case AHIST_S8S:
        RecS8S(length,ioreq->ahir_Frequency,
            iounit->RecordBuffer,
            &ioreq->ahir_Std.io_Offset,
            &ioreq->ahir_Std.io_Data);
        break;
      case AHIST_M16S:
        RecM16S(length,ioreq->ahir_Frequency,
            iounit->RecordBuffer,
            &ioreq->ahir_Std.io_Offset,
            &ioreq->ahir_Std.io_Data);
        break;
      case AHIST_S16S:
        RecS16S(length,ioreq->ahir_Frequency,
            iounit->RecordBuffer,
            &ioreq->ahir_Std.io_Offset,
            &ioreq->ahir_Std.io_Data);
        break;
      case AHIST_M32S:
        RecM32S(length,ioreq->ahir_Frequency,
            iounit->RecordBuffer,
            &ioreq->ahir_Std.io_Offset,
            &ioreq->ahir_Std.io_Data);
        break;
      case AHIST_S32S:
        RecS32S(length,ioreq->ahir_Frequency,
            iounit->RecordBuffer,
            &ioreq->ahir_Std.io_Offset,
            &ioreq->ahir_Std.io_Data);
        break;
#endif
      default:
        ioreq->ahir_Std.io_Error = AHIE_BADSAMPLETYPE;
        remove = TRUE;
        break;
    }
    
    ioreq->ahir_Std.io_Actual += ((ULONG) ioreq->ahir_Std.io_Data - (ULONG) oldaddress);

    if(remove)
    {
      Remove((struct Node *) ioreq);
      TermIO(ioreq, AHIBase);
    }
    else
    {
      ioreq->ahir_Std.io_Offset = 0;
    }
  }
  else
  {
    ioreq->ahir_Std.io_Offset = 0;
  }
}
Ejemplo n.º 5
0
static void
WriteCmd ( struct AHIRequest *ioreq,
           struct AHIBase *AHIBase )
{
  struct AHIDevUnit *iounit;
  ULONG error = 0;

  if(AHIBase->ahib_DebugLevel >= AHI_DEBUG_HIGH)
  {
    KPrintF("CMD_WRITE\n");
  }

  iounit = (struct AHIDevUnit *) ioreq->ahir_Std.io_Unit;

  /* Start playback if neccessary */
  if( ! iounit->IsPlaying)
  {
    if( (! iounit->FullDuplex) && iounit->IsRecording)
    {
      error = AHIE_HALFDUPLEX;   // FIXIT!
    }
    else
    {
      error = AHI_ControlAudio(iounit->AudioCtrl,
         AHIC_Play,TRUE,
         TAG_DONE);
    }

    if( ! error)
    {
      iounit->IsPlaying = TRUE;
    }
  }

  ioreq->ahir_Extras = (ULONG) AllocVec(sizeof(struct Extras), MEMF_PUBLIC|MEMF_CLEAR);

  if(ioreq->ahir_Extras == NULL)
  {
    error = AHIE_NOMEM;
  }
  else
  {
    // Initialize the structure
    GetExtras(ioreq)->Channel = NOCHANNEL;
    GetExtras(ioreq)->Sound   = AHI_NOSOUND;
    GetExtras(ioreq)->Count   = 2;
  }

  if(iounit->IsPlaying && !error)
  {
    ioreq->ahir_Std.io_Actual = 0;

    // Convert length in bytes to length in samples

    ioreq->ahir_Std.io_Length /= AHI_SampleFrameSize(ioreq->ahir_Type);

    switch(ioreq->ahir_Type)
    {
      case AHIST_M8S:
      case AHIST_S8S:
      case AHIST_M16S:
      case AHIST_S16S:
        break;
      case AHIST_M32S:
      case AHIST_S32S:
      default:
        error = AHIE_BADSAMPLETYPE;
    }

    if(! error)
    {
      NewWriter(ioreq, iounit, AHIBase);
    }
  }

  if(error)
  {
    ioreq->ahir_Std.io_Error = error;
    TermIO(ioreq, AHIBase);
  }
}