⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wave.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
    UnprepareWaveHeader    Cleans up after a header has been used, by killing the event we set up    above, and freeing the preparation data.    Winmm is intelligent enough to not call this function with a header that    is currently queued for playing!*/MMRESULT UnprepareWaveHeader(PWAVEHDR header){    MMRESULT result = MMSYSERR_ERROR;    PWDMAUD_WAVE_PREPARATION_DATA prep_data = NULL;    DPRINT("UnprepareHeader called\n");    /* Make sure we were actually given a header to process */    if ( ! header )    {        DPRINT1("Bad header supplied\n");        return MMSYSERR_INVALPARAM;    }    prep_data = (PWDMAUD_WAVE_PREPARATION_DATA) header->reserved;    result = ValidateWavePreparationData(prep_data);    if ( result != MMSYSERR_NOERROR )    {        DPRINT1("Bad wave header preparation structure pointer\n");        return result;    }    /* We're about to free the preparation structure, so this needs to go */    header->reserved = 0;    /* Kill the event */    CloseHandle(prep_data->overlapped->hEvent);    FreeMem(prep_data->overlapped);    /* Overwrite the signature (structure will be invalid from now on) */    ZeroMemory(prep_data->signature, 4);    FreeMem(prep_data);    /* Always return like this so winmm thinks we didn't do anything */    DPRINT("Header now unprepared.\n");    result = MMSYSERR_NOTSUPPORTED;    return result;}/* Not sure about this */MMRESULT CompleteWaveHeader(PWAVEHDR header){    return MMSYSERR_NOTSUPPORTED;}/*    SubmitWaveHeader Overview :    This may span 2 functions (this one and and another "SubmitHeader")    First, validate the device info, then the state.    Validate the header, followed by the reserved member.    Fail if INQUEUE flag is set in header, or if PREPARED is not set in    header.    AND the flags with PREPARED, BEGINLOOP, ENDLOOP and INQUEUE. OR the    result with INQUEUE.    Enter the csQueue critical section.    Check if the device state's "open descriptor" member is NULL or not.    If we're adding an extra buffer, it will already have been allocated.    If the open descriptor is NULL:        If it's NULL, set "opendesc" to point to the wave header (?!)        If the state structure's "hevtQueue" member isn't NULL, compare it's        value to 0x43434343h and 0x42424242h. If it's not NULL or one of        those values, set the event.    If the open descriptor is NOT NULL:        Check the header's lpNext member. If it's not NULL, check that        structure's lpNext member, and so on, until a NULL entry is        found.        Set the NULL entry to point to our header.    Leave the csQueue critical section.    ** SUBMIT THE HEADER ** TODO **    If submission failed:        AND the flags with 0xFFFFFFEFh. If csQueue is set in the target        (the header who's lpNext was NULL), set it to NULL. Set the open        descriptor of state to NULL, too. And fail, of course.    If the device state is PAUSED or RUNNING, we must fail.    Otherwise, reset the device and set it as RUNNING. This may be done by    our caller (wodMessage, etc.)    0x1d8104 is used for wave in    0x1d8148 is used for wave out?    SetDeviceState should now be called with the above IOCTL code and the    device info structure.*//*    ValidateWriteWaveDataParams    This is just a helper function that shrinks WriteWaveData a little    bit.*/static MMRESULT ValidateWriteWaveDataParams(    PWDMAUD_DEVICE_INFO device,    PWAVEHDR header){    MMRESULT result;    result = ValidateWaveHeader(header);    if ( result != MMSYSERR_NOERROR )    {        DPRINT1("Bad wave header supplied\n");        return result;    }    /*        We don't want to queue something already queued, and we don't want        to queue something that hasn't been prepared. Who knows what garbage        might be sent to us?!    */    if ( header->dwFlags & WHDR_INQUEUE )    {        DPRINT1("This header is already queued!\n");        return MMSYSERR_INVALFLAG;    }    if ( ! header->dwFlags & WHDR_PREPARED )    {        DPRINT1("This header isn't prepared!\n");        return WAVERR_UNPREPARED;    }    result = ValidateDeviceData(device, TRUE);    if ( result != MMSYSERR_NOERROR )    {        DPRINT1("Bad device info or device state supplied\n");        return result;    }    return result;}/*    WriteWaveData    This is the exciting (?!) bit where playback actually begins. Various    validation takes place, before the header is queued for playback. Playback    can then begin. This entails telling the kernel-mode device about the    header, then telling the device to start playback.    It all seems pretty straightforward, but it's not all that easy...*/MMRESULT WriteWaveData(PWDMAUD_DEVICE_INFO device, PWAVEHDR header){    MMRESULT result = MMSYSERR_ERROR;    DWORD io_result = 0;    PWDMAUD_WAVE_PREPARATION_DATA prep_data = NULL;    /* PWDMAUD_DEVICE_INFO clone; */    /* For the DeviceIoControl later */    DWORD ioctl_code;    DWORD bytes_returned;    DPRINT("WriteWaveHeader called\n");    result = ValidateWriteWaveDataParams(device, header);    if ( result != MMSYSERR_NOERROR )        return result;    /* Check to see if we actually get called with bad flags! */    if ( ! IS_WAVEHDR_FLAG_SET(header, WHDR_PREPARED) )    {        DPRINT1("Not prepared!\n");        return WAVERR_UNPREPARED;    }    /* Retrieve our precious data from the reserved member */    prep_data = (PWDMAUD_WAVE_PREPARATION_DATA) header->reserved;    result = ValidateWavePreparationData(prep_data);    if ( result != MMSYSERR_NOERROR )    {        DPRINT1("Bad wave preparation structure supplied\n");        return result;    }    DPRINT("Flags == 0x%x\n", (int) header->dwFlags);    /* Mask the "done" flag */    CLEAR_WAVEHDR_FLAG(header, WHDR_DONE);    /* header->dwFlags &= ~WHDR_DONE; */    /* ...and set the queue flag! */    SET_WAVEHDR_FLAG(header, WHDR_INQUEUE);    /* header->dwFlags |= WHDR_INQUEUE; */    DPRINT("Flags == 0x%x\n", (int) header->dwFlags);    EnterCriticalSection(device->state->device_queue_guard);    if ( ! device->state->current_wave_header )    {        DPRINT("Device state wave_header is NULL\n");        device->state->current_wave_header = header;        /* My, what pretty symmetry you have... */        DPRINT("Queue event == 0x%x\n", (int) device->state->queue_event);        if ( ( (DWORD) device->state->queue_event != 0 ) &&             ( (DWORD) device->state->queue_event != MAGIC_42 ) &&             ( (DWORD) device->state->queue_event != MAGIC_43 ) )        {            DPRINT("Setting queue event\n");            SetEvent(device->state->queue_event);        }    }    else    {        DPRINT("Device state open_descriptor is NOT NULL\n");        /* TODO */        ASSERT(FALSE);    }    LeaveCriticalSection(device->state->device_queue_guard);    /* Now we send the header to the kernel device */    if ( ! IsHeaderPrepared(header) )    {        DPRINT1("Unprepared header!\n");        result = MMSYSERR_INVALPARAM;        goto cleanup;    }    /*        Not sure what this is for. I *think* it's used for tracking which        device a preparation belongs to.    */    prep_data->offspring = device;    /* The modern version of WODM_WRITE, I guess ;) */    device->ioctl_param1 = sizeof(WAVEHDR);    device->ioctl_param2 = (DWORD) header;    ioctl_code = device->type == WDMAUD_WAVE_IN                                ? IOCTL_WDMAUD_SUBMIT_WAVE_IN_HDR   /* FIXME */                                : IOCTL_WDMAUD_SUBMIT_WAVE_OUT_HDR;    /*        FIXME:        For wave input to work, we may need to pass different parameters.    */    /* We now send the header to the driver */    io_result =        DeviceIoControl(GetKernelInterface(),                        ioctl_code,                        device,                        sizeof(WDMAUD_DEVICE_INFO) + (lstrlen(device->path) * 2),                        device,                        sizeof(WDMAUD_DEVICE_INFO),                        &bytes_returned,    /* ... */                        prep_data->overlapped);    DPRINT("Wave header submission result : %d\n", (int) io_result);    if ( io_result != STATUS_SUCCESS )    {        DPRINT1("Wave header submission FAILED! (error %d)\n", (int) io_result);        CLEAR_WAVEHDR_FLAG(header, WHDR_INQUEUE);        device->state->device_queue_guard = NULL;        device->state->current_wave_header = NULL;        return TranslateWinError(io_result);    }    /* CallKernelDevice(clone, ioctl_code, 0x20, (DWORD) header); */    if ( ! CreateCompletionThread(device) )    {        DPRINT1("Couldn't create completion thread\n");        CLEAR_WAVEHDR_FLAG(header, WHDR_INQUEUE);        device->state->device_queue_guard = NULL;        device->state->current_wave_header = NULL;        return MMSYSERR_ERROR; /* Care to be more specific? */    }    /* ***** FIXME ****** THIS IS NASTY HACKERY ****** */    DPRINT("applying hacks\n");    DPRINT("Running %d paused %d\n", (int)device->state->is_running, (int)device->state->is_paused);#if 1    /* HACK */    DPRINT("%d\n", (int)        DeviceIoControl(GetKernelInterface(),                        IOCTL_WDMAUD_WAVE_OUT_START,                        device,                        sizeof(WDMAUD_DEVICE_INFO) + (lstrlen(device->path) * 2),                        device,                        sizeof(WDMAUD_DEVICE_INFO),                        &bytes_returned,    /* ... */                        prep_data->overlapped) );    DPRINT("Running %d paused %d\n", (int)device->state->is_running, (int)device->state->is_paused);#if 0 /* on error */    DPRINT("%d\n", (int)        DeviceIoControl(GetKernelInterface(),                        0x1d8148,                        device,                        sizeof(WDMAUD_DEVICE_INFO) + (lstrlen(device->path) * 2),                        device,                        sizeof(WDMAUD_DEVICE_INFO),                        &bytes_returned,    /* ... */                        prep_data->overlapped) );#endif#endif    result = MMSYSERR_NOERROR;    cleanup :    {        /* TODO */        return result;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -