예제 #1
0
LONG APIENTRY DARTEvent (ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
{
    ULONG rc;
    switch (ulFlags)
    {
    case MIX_WRITE_COMPLETE:
        //
        // start the playback of the next buffer
        //
        rc=MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle,
                                   &(buffers[play]), 1);
        //
        // get the sound mutex
        //
        if (DosRequestMutexSem(hmtxSnd, SEM_INDEFINITE_WAIT))
            return TRUE;
        //
        // empty the buffer which was finished
        //
        memset(buffers[last].pBuffer, 0, BufferParms.ulBufferSize);

        //
        // point to the next playable buffer and remember this buffer
        // as the last one which was played
        //
        last  = play++;
        play %= BufferParms.ulNumBuffers;

        //
        // release mutex
        //
        DosReleaseMutexSem(hmtxSnd);

        if (rc != MCIERR_SUCCESS)
            sound_err(dlog, rc, "Writing to Mixer (pmixWrite, MIX_WRITE_COMPLETE).");
        return TRUE;

    case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE: // 130  /* error occur in device */
        switch (ulStatus)
        {
        case ERROR_DEVICE_UNDERRUN: // 5626
            sound_err(dlog, ulStatus, "Device underrun.");
            play += 2;
            play %= BufferParms.ulNumBuffers;
            break;
        case ERROR_DEVICE_OVERRUN:  // 5627
            sound_err(dlog, ulStatus, "Device overrun.");
            break;
        }
        rc=MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle,
                                   &(buffers[play]), 1);
        if (rc != MCIERR_SUCCESS)
            sound_err(dlog, rc, "Writing to Mixer (pmixWrite, MIX_STREAM_ERROR).");

        return TRUE;
    }
    return TRUE;
}
예제 #2
0
void set_volume(int vol)
{
    ULONG rc;

    if ((rc=DosRequestMutexSem(hmtxOC, SEM_INDEFINITE_WAIT)))
    {
        log_warning(dlog, "set_volume, DosRequestMutexSem rc=%i", rc);
        return;
    }
    if (usDeviceID)
    {
        MCI_SET_PARMS  MciSetParms;

        memset(&MciSetParms, 0, sizeof(MCI_SET_PARMS));

        MciSetParms.ulLevel = vol;
        MciSetParms.ulAudio = MCI_SET_AUDIO_ALL;

        log_message(dlog, "Setting volume to %d%%", vol);

        rc = mciSendCommand(usDeviceID, MCI_SET, MCI_WAIT|
                            MCI_SET_VOLUME|MCI_SET_AUDIO,
                            (PVOID) &MciSetParms, 0);
        if (rc != MCIERR_SUCCESS)
            sound_err(dlog, rc, "Setting up Volume (MCI_SET).");
    }
    volume=vol;
    DosReleaseMutexSem(hmtxOC);
}
예제 #3
0
static int DartOpen(void)
{
    ULONG rc;
    MCI_AMP_OPEN_PARMS AmpOpenParms;

    memset(&AmpOpenParms, 0, sizeof (MCI_AMP_OPEN_PARMS));

    AmpOpenParms.usDeviceID    = (USHORT) 0;
    AmpOpenParms.pszDeviceType = (PSZ) MCI_DEVTYPE_AUDIO_AMPMIX;
    AmpOpenParms.hwndCallback  = 0;

    rc = mciSendCommand(0, MCI_OPEN,
                        MCI_WAIT|MCI_OPEN_TYPE_ID|MCI_OPEN_SHAREABLE /* | MCI_DOS_QUEUE*/,
                        (PVOID) &AmpOpenParms, 0);

    if (rc != MCIERR_SUCCESS)
    {
        usDeviceID = 0;
        sound_err(dlog, rc, "Opening DART (MCI_OPEN).");

        return FALSE;
    }

    usDeviceID = AmpOpenParms.usDeviceID;
    return TRUE;
}
예제 #4
0
void mute(int state)
{
    ULONG rc;

    if ((rc=DosRequestMutexSem(hmtxOC, SEM_INDEFINITE_WAIT)))
    {
        log_warning(dlog, "mute, DosRequestMutexSem rc=%i", rc);
        return;
    }
    if (usDeviceID)
    {
        MCI_SET_PARMS MciSetParms;

        memset(&MciSetParms, 0, sizeof(MCI_SET_PARMS));

        MciSetParms.ulAudio = MCI_SET_AUDIO_ALL;
        rc = mciSendCommand(usDeviceID, MCI_SET, MCI_WAIT|state|MCI_SET_AUDIO,
                            (PVOID) &MciSetParms, 0);

        if (rc != MCIERR_SUCCESS)
            sound_err(dlog, rc, "Setting mute state (MCI_SET_ON/OFF).");
    }
    DosReleaseMutexSem(hmtxOC);

    if (state==MCI_SET_ON)
        set_volume(volume);
}
예제 #5
0
static void dart_close()
{
    MCI_GENERIC_PARMS GenericParms = { 0 };
    ULONG rc;

    // prevent sound from clicking
    mute(MUTE_ON);

    if ((rc = DosRequestMutexSem(hmtxOC, SEM_INDEFINITE_WAIT))) {
        log_warning(dlog, "dart_close, DosRequestMutexSem rc=%i", rc);
        return;
    }

    //DosRequestMutexSem(hmtxSnd, SEM_INDEFINITE_WAIT);
    for (rc = 0; rc < BufferParms.ulNumBuffers; rc++) {
        buffers[rc].ulFlags = MIX_BUFFER_EOS;
    }

    rc = mciSendCommand(usDeviceID, MCI_STOP, MCI_WAIT,
                        (PVOID) &GenericParms, 0);
    if (rc != MCIERR_SUCCESS) {
        sound_err(dlog, rc, "Stopping device (MCI_STOP).");
    }

    //log_message(LOG_DEFAULT, "sounddrv.c: Sound stopped.");

    rc = mciSendCommand(usDeviceID, MCI_BUFFER, MCI_WAIT | MCI_DEALLOCATE_MEMORY,
                        (PVOID) &BufferParms, 0);
    if (rc != MCIERR_SUCCESS) {
        sound_err(dlog, rc, "Deallocating buffer (MCI_DEALLOCATE).");
    }

    //log_message(LOG_DEFAULT, "sounddrv.c: Buffer deallocated.");
    /*    rc = mciSendCommand(usDeviceID, MCI_MIXSETUP, MCI_WAIT|MCI_MIXSETUP_DEINIT,
     (PVOID) &MixSetupParms, 0);
     if (rc != MCIERR_SUCCESS) return sound_err(dlog, (rc, "DART_ERR_MIXSETUP_DEINIT");*/

    DartClose();

    lib_free(buffers);
    //log_message(LOG_DEFAULT, "sounddrv.c: Buffer freed.");

    DosReleaseMutexSem(hmtxOC);
}
예제 #6
0
static void DartClose(void)
{
    MCI_GENERIC_PARMS GenericParms = {0};

    ULONG rc = mciSendCommand(usDeviceID, MCI_CLOSE, MCI_WAIT,
                              (PVOID) &GenericParms, 0);

    if (rc != MCIERR_SUCCESS)
        sound_err(dlog, rc, "Closing Dart (MCI_CLOSE).");

    log_message(dlog, "Sound closed.");

    usDeviceID = 0;
}
예제 #7
0
static int dart_init(const char *param, int *speed,
                     int *fragsize, int *fragnr, int *channels)
{

/* The application sends the MCI_MIX_SETUP message to the amp mixer to
 initialize the device for direct reading and writing of audio data in
 the correct mode and format-for example, PCM, MIDI, or MPEG audio.

 If waveform audio data will be played or recorded, the application
 fills in the ulDeviceType field with MCI_DEVICETYPE_WAVEFORM_AUDIO. It
 must also provide values for the following digital-audio-specific
 fields:  format tag, bits per sample, number of samples per second, and
 number of channels.*/

 // MCI_MIXSETUP informs the mixer device of the entry point
 // to report buffers being read or written.
 // We will also need to tell the mixer which media type
 // we will be streaming.  In this case, we'll use
 // MCI_DEVTYPE_WAVEFORM_AUDIO.

    ULONG i, rc;

    if (DosRequestMutexSem(hmtxOC, SEM_IMMEDIATE_RETURN))
        return TRUE;

    // ---------
    if (!DartOpen())
    {
        DosReleaseMutexSem(hmtxOC);
        return 1;
    }
    // ---------

    memset(&MixSetupParms, 0, sizeof(MCI_MIXSETUP_PARMS));

    MixSetupParms.ulBitsPerSample = 16;
    MixSetupParms.ulFormatTag     = MCI_WAVE_FORMAT_PCM;
    MixSetupParms.ulSamplesPerSec = *speed; 
    MixSetupParms.ulChannels      = *channels; /* Stereo/Mono */
    MixSetupParms.ulFormatMode    = MCI_PLAY;
    MixSetupParms.ulDeviceType    = MCI_DEVTYPE_WAVEFORM_AUDIO;

    // MCI_MIXSETUP_QUERYMODE
    // Queries a device to see if a specific mode is supported
    /*    rc = mciSendCommand( usDeviceID, MCI_MIXSETUP,
     MCI_WAIT | MCI_MIXSETUP_QUERYMODE,
     (PVOID) &MixSetupParms, 0);

     if (rc != MCIERR_SUCCESS) return sound_err(dlog, (rc, "Can't play.");*/

    // The mixer will inform us of entry points to
    // read/write buffers to and also give us a
    // handle to use with these entry points.

    MixSetupParms.pmixEvent = DARTEvent;

    // MCI_MIXSETUP_INIT (DEINIT)
    // Initializes the mixer for the correct mode (MCI_MIXSETUP_PARMS)
    rc = mciSendCommand(usDeviceID, MCI_MIXSETUP,
                        MCI_WAIT|MCI_MIXSETUP_INIT,
                        (PVOID) &MixSetupParms, 0);

    if (rc != MCIERR_SUCCESS)
    {
        sound_err(dlog, rc, "Initialising mixer device (MCI_MIXSETUP_INIT).");
        DartClose();
        DosReleaseMutexSem(hmtxOC);
        return 1;
    }

    //log_message(LOG_DEFAULT, "sounddart.c: %3i buffers � %6i bytes (suggested by dart)", MixSetupParms.ulNumBuffers, MixSetupParms.ulBufferSize);
    //log_message(LOG_DEFAULT, "sounddart.c: %3i buffers � %6i bytes (wanted by vice)", *fragnr, *fragsize*sizeof(SWORD));

    /*  After the mixer device is set up to use DART, the application
     instructs the device to allocate memory by sending the MCI_BUFFER
     message with the MCI_ALLOCATE_MEMORY flag set. The application uses the
     MCI_BUFFER_PARMS structure to specify the number of buffers it wants
     and the size to be used for each buffer.

     Note: Because of device driver restrictions, buffers are limited to
     64KB on Intel-based systems. No such limit exists on PowerPC systems.

     The pBufList field contains a pointer to an array of MCI_MIX_BUFFER
     structures where the allocated information is to be returned.*/

    buffers = lib_calloc(*fragnr, sizeof(MCI_MIX_BUFFER));

    BufferParms.pBufList     = buffers;
    BufferParms.ulNumBuffers = *fragnr;
    BufferParms.ulBufferSize = *fragsize*sizeof(SWORD);

    rc = mciSendCommand(usDeviceID, MCI_BUFFER, MCI_WAIT|MCI_ALLOCATE_MEMORY,
                        (PVOID) &BufferParms, 0);

    if (rc != MCIERR_SUCCESS)
    {
        sound_err(dlog, rc, "Allocating Memory (MCI_ALLOCATE_MEMORY).");
        DartClose();
        DosReleaseMutexSem(hmtxOC);
        return 1;
    }

    // MCI driver will return the number of buffers it
    // was able to allocate
    // it will also return the size of the information
    // allocated with each buffer.

    if (*fragnr  !=BufferParms.ulNumBuffers)
    {
        *fragnr   = BufferParms.ulNumBuffers;
        log_message(dlog, "got %3i buffers � %6i bytes.", BufferParms.ulNumBuffers, BufferParms.ulBufferSize);
    }
    if (*fragsize!=BufferParms.ulBufferSize/sizeof(SWORD))
    {
        *fragsize = BufferParms.ulBufferSize/sizeof(SWORD);
        log_message(dlog, "got %3i buffers � %6i bytes.", BufferParms.ulNumBuffers, BufferParms.ulBufferSize);
    }

    // SECURITY for *fragnr <2 ????
    for (i=0; i<*fragnr; i++)
        memset(buffers[i].pBuffer, 0, BufferParms.ulBufferSize);
    // *fragsize*sizeof(SWORD));

    mmtime  = (float)*speed/1000;
    written = 0;
    rest    = BufferParms.ulBufferSize;

    // Must write at least two buffers to start mixer
    play = 2;  // this is the buffer which is played next
    last = 1;  // this is the buffer which is played last before next
    pos  = 0;  // this is the position to which buffer we have to write
    MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle,
                            &(buffers[0]), 2);

    DosReleaseMutexSem(hmtxOC);

    mute(MUTE_OFF);

    return 0;
}